dsh-composer-ux 0.6.1 → 0.6.2

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/lib/client.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/client.tsx", "../src/terminal/discover.ts", "../src/terminal/contracts.ts", "../src/settings-contract.ts", "../src/client/prompt-book.ts", "../src/client/chords.ts", "../src/client/quick-commands.ts", "../src/client/interceptors.ts", "../src/client/panel.ts", "../src/client/settings-style.ts", "../src/client/quick-style.ts", "../src/client/ContextMenuHost.tsx", "../src/client/styles.ts", "../src/client/PanelResizeHandles.tsx", "../src/client/SettingsSection.tsx", "../src/client/AddPromptRow.tsx", "../src/optimizer-prompt.ts", "../src/client/OptimizerPromptEditor.tsx", "../src/client/PillChoice.tsx", "../src/client/InsertModeControl.tsx", "../src/client/QuickCommandsButton.tsx", "../src/client/QuickCommandsPanel.tsx"],
4
- "sourcesContent": ["/**\n * Browser half\uFF1A\u6CE8\u518C\u8BBE\u7F6E\u9875\uFF08settings.section\uFF09\u3001\u53F3\u952E\u83DC\u5355\u4E0E\u8BBE\u7F6E\u9762\u677F\u62D6\u62FD\n * \u624B\u67C4\uFF08shell.overlay\uFF09\uFF0C\u5E76\u5B89\u88C5\u8F93\u5165\u6846\u62E6\u622A\u5668\uFF08\u952E\u4F4D + \u53F3\u952E\u83DC\u5355\uFF09\u4E0E\u9762\u677F\n * \u6EDA\u52A8\u6837\u5F0F\u3002\n */\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport {\n DEFAULT_SETTINGS, ENABLED_FIELD, HEADER_ENABLED_FIELD, HEADER_NAME_FIELD,\n HEADER_ROUTES_FIELD, HEADER_VALUE_FIELD, KEYS_ENABLED_FIELD, MENU_ENABLED_FIELD,\n MENU_FIELDS, MENU_MODE_FIELD, MENU_NATIVE_FIELD, NAMESPACE,\n NEWLINE_KEY_FIELD, OPTIMIZER_TIER_FIELD, PANEL_ENABLED_FIELD, PANEL_RESIZE_FIELD,\n PANEL_WIDTH_FIELD, PANEL_HEIGHT_FIELD, QUICK_ENABLED_FIELD, SEND_KEY_FIELD, TERMINAL_ENABLED_FIELD,\n activeSections, sanitizeSettings,\n alwaysQuickPrompts, appendBatchForSend, defaultQuickBook,\n type ComposerUxSettings, type InsertMode, type MenuState, type OptimizerTier, type QuickPrompt,\n type QuickPromptBook, type SettingsField,\n} from './settings-contract.ts'\n// \u7EC8\u7AEF\u5B57\u6BB5\u7684\u5E38\u91CF\u4F4F\u5728\u7EC8\u7AEF\u5951\u7EA6\u91CC\uFF08settings-contract \u53EA\u662F\u628A\u5B83\u4EEC\u5E76\u8FDB\u8BBE\u7F6E\u5951\u7EA6\uFF09\u3002\nimport { TERMINAL_BASH_PATH_FIELD, TERMINAL_MODE_FIELD } from './terminal/contracts.ts'\nimport {\n loadPromptBook, savePromptBook, withCategoryAdded, withCategoryMoved,\n withCategoryRemoved, withCategoryRenamed, withInsertMode, withPromptAdded, withPromptMoved,\n withPromptMovedToCategory, withPromptPatched, withPromptRemoved,\n} from './client/prompt-book.ts'\nimport { installInterceptors, runMenuAction } from './client/interceptors.ts'\nimport { installPanelResizeStyle } from './client/panel.ts'\nimport { installSettingsCardStyle } from './client/settings-style.ts'\nimport { installQuickButtonStyle } from './client/quick-style.ts'\nimport { ContextMenuHost } from './client/ContextMenuHost.tsx'\nimport { PanelResizeHandles } from './client/PanelResizeHandles.tsx'\nimport { SettingsSection } from './client/SettingsSection.tsx'\nimport { QuickCommandsButton, type QuickPanelAnchor } from './client/QuickCommandsButton.tsx'\nimport { QuickCommandsPanel } from './client/QuickCommandsPanel.tsx'\nimport {\n focusComposer, insertIntoDraft, optimizeDraft, replaceDraft, currentBlankSession, currentDraft,\n} from './client/quick-commands.ts'\n\nexport const name = 'composer-ux'\n/**\n * \u53EA\u786C\u4F9D\u8D56 `slots`\u3002\n *\n * \u8BBE\u7F6E\u670D\u52A1\u6362\u4E86\u540D\u5B57\u4E0E\u5F62\u72B6\uFF0C\u800C\u4E14**\u4E0D\u80FD\u540C\u65F6\u5199\u8FDB `inject`**\uFF1A\n * 0.1.6 \u53CA\u4EE5\u524D = `ctx.settingsScope.bind({ namespace })`\n * 0.1.7 \u8D77 = `ctx.configForms.get(namespace)`\n * \u8C01\u5728\u5BF9\u65B9\u90A3\u4E00\u4EE3\u90FD\u4E0D\u5B58\u5728\uFF0C\u9759\u6001 inject \u4E00\u65E6\u5199\u9519\uFF0C\u63D2\u4EF6\u5C31\u6C38\u8FDC\u7B49\u4E0D\u5230\u4F9D\u8D56\u800C\u6574\u5757\u4E0D\u6302\u8F7D\n * \uFF08\u8BBE\u7F6E\u9875\u3001\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u3001\u5FEB\u6377\u6307\u4EE4\u4E00\u8D77\u6D88\u5931\uFF09\u3002\u6240\u4EE5\u8FD9\u91CC\u53EA\u786C\u4F9D\u8D56 slots\uFF0C\n * \u4E24\u4E2A\u540D\u5B57\u5404\u7528 `ctx.inject` \u7B49\u4E00\u6B21\uFF0C\u8C01\u5148\u5230\u5C31\u7528\u8C01\uFF08\u89C1 `adoptSettings`\uFF09\u3002\n */\nexport const inject = ['slots']\n\n/** \u4E00\u4E2A\u8BBE\u7F6E\u4F5C\u7528\u57DF\u7684\u6700\u5C0F\u7528\u6CD5\uFF1A\u4E24\u4EE3 `SettingsScope` / `ConfigForm` \u7684\u4EA4\u96C6\u3002 */\ninterface SettingsScopeLike {\n getSnapshot(): { status: string; value?: unknown }\n subscribe(listener: () => void): () => void\n set(field: string, value: unknown): Promise<unknown>\n unset(field: string): Promise<unknown>\n mutate(ops: readonly { op: 'set' | 'unset'; path: readonly string[]; value?: unknown }[]): Promise<unknown>\n}\n\n/**\n * \u8BBE\u7F6E\u670D\u52A1\u7F3A\u5E2D\u65F6\u7684\u66FF\u8EAB\uFF1A\u754C\u9762\u4EE5\u9ED8\u8BA4\u503C\u7167\u5E38\u53EF\u7528\u3002\n *\n * \u5B58\u5728\u7684\u610F\u4E49\u662F\"\u964D\u7EA7\u800C\u4E0D\u662F\u6D88\u5931\"\u2014\u2014\u4E24\u4EE3 DSH \u90FD\u6709\u8FD9\u4E2A\u670D\u52A1\uFF0C\u6240\u4EE5\u5B83\u53EA\u5728\n * \u7EC4\u5408\u91CC\u6839\u672C\u6CA1\u6709\u8BBE\u7F6E provider \u65F6\u515C\u5E95\u3002\n */\nconst NULL_SCOPE: SettingsScopeLike = {\n getSnapshot: () => ({ status: 'unavailable', value: undefined }),\n subscribe: () => () => {},\n set: async () => false,\n unset: async () => false,\n mutate: async () => false,\n}\n\n/** \u5BA2\u6237\u7AEF\u63D2\u4EF6\u5165\u53E3\u3002 */\nexport function apply(ctx: any): void {\n const slots = ctx.slots\n\n const live = createSnapshotStore<ComposerUxSettings>({ ...DEFAULT_SETTINGS })\n const menu = createSnapshotStore<MenuState | null>(null)\n const panel = createSnapshotStore<QuickPanelAnchor | null>(null)\n const optimizing = createSnapshotStore<boolean>(false)\n const panelNotice = createSnapshotStore<string>('')\n /**\n * \u8BBE\u7F6E\u5199\u5165\u7684\u8BF4\u660E\u884C\uFF1B'' = \u6B63\u5E38\u3002\u6E32\u67D3\u5728\u8BBE\u7F6E\u5361\u7247\u9876\u90E8\uFF08\u4E0E\u300C\u91CD\u542F DSH\u300D\u6A2A\u5E45\u540C\u4F4D\u7F6E\uFF09\u3002\n *\n * \u5B58\u5728\u7684\u7406\u7531\uFF1A`ConfigForm.set` \u8FD4\u56DE `true` \u53EA\u4EE3\u8868\u5BBF\u4E3B**\u6536\u4E0B**\u4E86\u8FD9\u6B21\u5199\u5165\uFF0C\u4E0D\u4FDD\u8BC1\u8FD0\u884C\u65F6\n * \u7684\u6D3B\u503C\u8DDF\u7740\u53D8\u3002\u771F\u673A\u4E8B\u6545\uFF082026-09-23\uFF09\u91CC\uFF0C\u8BBE\u7F6E\u5199\u5165\u88AB\u4E00\u628A\u5B64\u513F\u9501\u6321\u4F4F\uFF0C\u7528\u6237\u80FD\u770B\u5230\u7684\n * \u53EA\u6709\"\u5F00\u5173\u4E0D\u52A8\"\u2014\u2014\u4E00\u53E5\u63D0\u793A\u90FD\u6CA1\u6709\u3002\u6240\u4EE5\u5E03\u5C14\u5B57\u6BB5\u5199\u5B8C\u56DE\u8BFB\u4E00\u6B21\uFF0C\u5BF9\u4E0D\u4E0A\u5C31\u628A\u8BDD\u8BF4\u51FA\u6765\u3002\n */\n const writeNotice = createSnapshotStore<string>('')\n\n /** \u5F53\u524D\u8BBE\u7F6E\u4F5C\u7528\u57DF\uFF1B\u771F\u7684\u90A3\u4E2A\u5230\u4E86\u4E4B\u540E\u88AB `adoptSettings` \u6362\u6389\uFF08\u89C1\u6587\u4EF6\u4E0A\u65B9 inject \u90A3\u6BB5\uFF09\u3002 */\n let scope: SettingsScopeLike = NULL_SCOPE\n\n const sync = (): void => {\n const snapshot = scope.getSnapshot()\n live.set(snapshot.status === 'ready' && snapshot.value !== undefined\n ? { ...DEFAULT_SETTINGS, ...sanitizeSettings(snapshot.value) }\n : { ...DEFAULT_SETTINGS })\n }\n sync()\n\n /**\n * \u8BA4\u9886\u7B2C\u4E00\u4E2A\u51FA\u73B0\u7684\u8BBE\u7F6E\u670D\u52A1\u3002\n *\n * 0.1.7 \u7684 `ConfigForm.set/unset/mutate` \u8FD4\u56DE `Promise<boolean>`\uFF08`false` = \u5BBF\u4E3B\u62D2\u7EDD\uFF0C\n * \u4F8B\u5982\u5B57\u6BB5\u4E0D\u662F volatile\u3001\u6216\u4FEE\u8BA2\u53F7\u88AB\u522B\u4EBA\u62A2\u5148\uFF09\uFF1B0.1.6 \u8FD4\u56DE `Promise<void>`\u3002\n * \u6240\u4EE5\u8FD9\u91CC\u53EA\u5728\u660E\u786E\u62FF\u5230 `false` \u65F6\u8BB0\u4E00\u6761\u8B66\u544A\uFF0C\u4E24\u4EE3\u90FD\u4E0D\u4F1A\u8BEF\u62A5\u3002\n */\n let adopted = false\n const adoptSettings = (service: unknown, shape: 'get' | 'bind'): void => {\n if (adopted || service === null || service === undefined) return\n const api = service as {\n get?: (namespace: string) => unknown\n bind?: (spec: { namespace: string }) => unknown\n }\n const next = shape === 'get' ? api.get?.(NAMESPACE) : api.bind?.({ namespace: NAMESPACE })\n if (next === null || next === undefined) return\n if (typeof (next as SettingsScopeLike).getSnapshot !== 'function') return\n adopted = true\n scope = next as SettingsScopeLike\n sync()\n ctx.effect(() => scope.subscribe(sync), 'composer-ux: settings sync')\n }\n /**\n * \u7B49\u4E00\u4E2A\u670D\u52A1\u51FA\u73B0\uFF08cordis \u7684 `inject` \u8BED\u4E49\uFF09\u3002\n *\n * `ctx.inject` \u7406\u8BBA\u4E0A\u4E00\u5B9A\u5728\uFF08\u5BBF\u4E3B\u534A\u4E5F\u5728\u7528\uFF09\uFF0C\u4F46\u5B83\u662F\u8FD9\u4E00\u5757\u552F\u4E00\u4F1A\u8BA9 apply \u629B\u51FA\u7684\u8C03\u7528 \u2014\u2014\n * \u629B\u51FA\u610F\u5473\u7740\u6574\u5757\u6D88\u5931\uFF0C\u6240\u4EE5\u7F3A\u5E2D\u65F6\u9759\u9ED8\u8DF3\u8FC7\uFF1A\u4E0B\u9762\u7684\"\u76F4\u63A5\u8BFB\u4E00\u6B21\"\u515C\u5E95\u4ECD\u4F1A\u8BA4\u9886\u5DF2\u5230\u4F4D\u7684\u670D\u52A1\u3002\n */\n const whenService = (deps: string[], callback: (view: Record<string, unknown>) => void): void => {\n if (typeof ctx.inject !== 'function') return\n try {\n ctx.inject(deps, callback)\n } catch (error: unknown) {\n console.warn('[composer-ux] settings service inject failed', error)\n }\n }\n whenService(['configForms'], view => { adoptSettings(view.configForms, 'get') })\n whenService(['settingsScope'], view => { adoptSettings(view.settingsScope, 'bind') })\n /**\n * \u76F4\u63A5\u8BFB\u4E00\u6B21\u5C5E\u6027\uFF0C\u4E24\u4EE3\u5404\u8BD5\u4E00\u6B21\uFF08`adoptSettings` \u5185\u90E8\u6709 `adopted` \u95F8\uFF0C\u4E0D\u4F1A\u91CD\u590D\u8BA4\u9886\uFF09\u3002\n *\n * \u5FC5\u987B\u5305 try\uFF1Acordis \u7684\u4E0A\u4E0B\u6587\u4EE3\u7406\u5BF9**\u672A\u51FA\u73B0\u5728 inject \u91CC**\u7684\u670D\u52A1\u540D\u76F4\u63A5\u629B\u51FA\n * `cannot get property \"X\" without inject`\u3002\u672C\u63D2\u4EF6\u53EA\u58F0\u660E `inject = ['slots']`\uFF0C\n * \u6240\u4EE5\u5728\u7F3A\u8FD9\u4E00\u4EE3\u670D\u52A1\u7684 DSH \u4E0A\uFF080.1.6 \u6CA1\u6709 `configForms`\u30010.1.7 \u6CA1\u6709\n * `settingsScope`\uFF09\uFF0C\u88F8\u8BFB\u5C5E\u6027\u4F1A\u8BA9\u6574\u4E2A apply \u629B\u51FA \u2014\u2014 \u8BBE\u7F6E\u9875\u3001\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u3001\n * \u5FEB\u6377\u6307\u4EE4\u4E00\u8D77\u6D88\u5931\uFF0C\u6B63\u662F\u4E0A\u9762\u6CE8\u91CA\u8981\u907F\u514D\u7684\u90A3\u79CD\"\u6574\u5757\u4E0D\u6302\u8F7D\"\u3002\n */\n const peekService = (name: string): unknown => {\n try {\n return (ctx as Record<string, unknown>)[name]\n } catch {\n return undefined\n }\n }\n adoptSettings(peekService('configForms'), 'get')\n adoptSettings(peekService('settingsScope'), 'bind')\n\n /**\n * \u5199\u5165\u4E00\u4E2A\u5B57\u6BB5\uFF1B\u88AB\u5BBF\u4E3B\u62D2\u7EDD\uFF08\u65B0\u7248\u8FD4\u56DE false\uFF09\u65F6\u5728\u63A7\u5236\u53F0\u7559\u75D5\uFF0C\u5E76\u628A\u539F\u56E0\u7559\u7ED9\u8BBE\u7F6E\u9875\u3002\n *\n * \u4E3A\u4EC0\u4E48\u8FD8\u8981**\u56DE\u8BFB\u6821\u9A8C**\uFF1A`ConfigForm.set` \u8FD4\u56DE `true` \u53EA\u8BF4\u660E\u5BBF\u4E3B\u6536\u4E0B\u4E86\u5199\u5165\uFF0C\u4E0D\u4FDD\u8BC1\n * \u8FD0\u884C\u65F6\u7684\u6D3B\u503C\u8DDF\u7740\u53D8\u3002\u771F\u673A\u4E0A\u51FA\u73B0\u8FC7\u4E24\u79CD\"\u70B9\u4E86\u6CA1\u53CD\u5E94\"\uFF1A\n * \u00B7 \u5199\u5165\u88AB\u62D2\uFF08false\uFF09\u2014\u2014 profile \u7684\u5199\u5165\u9501\u88AB\u5360/\u662F\u5B64\u513F\u9501\uFF0C\u7B49 2 \u79D2\u8D85\u65F6\uFF1B\n * \u00B7 \u5199\u5165\u843D\u76D8\u3001\u4F46\u8FDB\u7A0B\u91CC\u7684\u6D3B\u503C\u6CA1\u63A5\u4F4F \u2014\u2014 \u754C\u9762\u7EE7\u7EED\u663E\u793A\u65E7\u503C\u3002\n * \u4E24\u79CD\u90FD\u8981\u91CD\u542F\uFF08\u6216\u624B\u5DE5\u56DE\u6536\u9501\uFF09\u624D\u80FD\u6062\u590D\uFF0C\u800C\u7528\u6237\u552F\u4E00\u7684\u7EBF\u7D22\u5C31\u662F\"\u5F00\u5173\u4E0D\u52A8\"\u3002\u6240\u4EE5\u8FD9\u91CC\n * \u56DE\u8BFB\u4E00\u6B21\uFF0C\u5BF9\u4E0D\u4E0A\u5C31\u628A\u8BF4\u660E\u6302\u5230\u8BBE\u7F6E\u9875\u9876\u90E8\u3002\n *\n * \u4E3A\u4EC0\u4E48\u53EA\u6821\u9A8C\u5E03\u5C14\u5B57\u6BB5\uFF1A\u5E03\u5C14\u4E0D\u4F1A\u88AB\u51C0\u5316\u5C42\u5939\u53D6\uFF0C\u4E5F\u6CA1\u6709\"\u5199\u5165\u540C\u4E00\u4E2A\u503C\"\u7684\u6B63\u5E38\u573A\u666F\uFF0C\n * \u4E8E\u662F\"\u56DE\u8BFB\u4ECD\u4E0D\u7B49\u4E8E\u521A\u5199\u7684\u503C\"\u5C31\u662F\u660E\u786E\u5F02\u5E38\uFF1B\u5C3A\u5BF8/\u6587\u672C\u6709\u5939\u53D6\u4E0E\u622A\u65AD\uFF0C\u62FF\u5B83\u4EEC\u5224\u7B49\u4F1A\u8BEF\u62A5\u3002\n */\n const WRITE_READBACK_MS = 1200\n const setField = (field: SettingsField, value: unknown): void => {\n writeNotice.set('')\n const verify = typeof value === 'boolean'\n void scope.set(field, value as never).then((accepted: unknown) => {\n if (accepted === false) {\n console.warn('[composer-ux] settings write refused', field)\n writeNotice.set(\n `\u5199\u5165\u300C${field}\u300D\u88AB\u5BBF\u4E3B\u62D2\u7EDD\u3002\u5E38\u89C1\u539F\u56E0\uFF1Aprofile \u7684\u5199\u5165\u9501\u88AB\u5360\u7528\uFF0C\u6216\u662F\u4E00\u628A\u5B64\u513F\u9501`\n + '\uFF08\u786C\u6740\u91CD\u542F\u7559\u4E0B\u7684\uFF09\u2014\u2014\u89C1 README\u300C\u8BBE\u7F6E\u5199\u4E0D\u8FDB\u53BB\u300D\u4E00\u8282\uFF1B\u91CD\u542F DSH \u540E\u4ECD\u65E0\u6548\uFF0C'\n + '\u5C31\u624B\u5DE5\u5220\u6389 profiles/<\u4F60\u7684 profile>/package.json.lock\u3002',\n )\n return\n }\n if (!verify) return\n setTimeout(() => {\n const now = (live.getSnapshot() as unknown as Record<string, unknown>)[field]\n if (now === value) return\n console.warn('[composer-ux] settings write had no visible effect', field, now, value)\n writeNotice.set(\n `\u5199\u5165\u300C${field}\u300D\u5DF2\u88AB\u5BBF\u4E3B\u63A5\u53D7\uFF0C\u4F46\u8FD0\u884C\u65F6\u7684\u503C\u6CA1\u6709\u53D8\u5316\uFF08\u4ECD\u662F ${String(now)}\uFF09\u3002`\n + '\u914D\u7F6E\u53EF\u80FD\u5DF2\u7ECF\u843D\u76D8\uFF0C\u53EA\u662F\u8FD9\u4E2A\u8FDB\u7A0B\u6CA1\u63A5\u4F4F\u2014\u2014\u91CD\u542F DSH \u5373\u53EF\u751F\u6548\u3002',\n )\n }, WRITE_READBACK_MS)\n }, (error: unknown) => {\n console.error('[composer-ux] settings write failed', error)\n writeNotice.set(`\u5199\u5165\u300C${field}\u300D\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`)\n })\n }\n const clearField = (field: SettingsField): void => {\n void scope.unset(field).then((accepted: unknown) => {\n if (accepted === false) console.warn('[composer-ux] settings clear refused', field)\n }, (error: unknown) => {\n console.error('[composer-ux] settings clear failed', error)\n })\n }\n\n // \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\u5B58\u50A8\uFF08\u5206\u7C7B\u7ED3\u6784\uFF1B\u771F\u76F8\u5728 $DSH_HOME/quick-prompts.json\uFF09 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n //\n // \u8BFB\uFF1Aapply \u65F6\u62C9\u4E00\u6B21\u3002\u5199\uFF1A\u5148\u4E50\u89C2\u66F4\u65B0\u672C\u5730\u5FEB\u7167\u8BA9\u754C\u9762\u7ACB\u523B\u54CD\u5E94\uFF0C\u518D\u628A\u6574\u672C POST \u4E0A\u53BB\uFF1B\n // \u5931\u8D25\u5C31\u4EE5\u78C1\u76D8\u4E3A\u51C6\u56DE\u6EDA\u2014\u2014\u4E0D\u8BA9\u300C\u754C\u9762\u663E\u793A\u7684\u300D\u548C\u300C\u6587\u4EF6\u91CC\u7684\u300D\u957F\u671F\u4E0D\u4E00\u81F4\u3002\n const book = createSnapshotStore<QuickPromptBook>(defaultQuickBook())\n /** '' = \u6B63\u5E38\uFF1B'saving' = \u6B63\u5728\u5199\uFF1B\u5176\u4F59 = \u4E0A\u4E00\u6B21\u7684\u9519\u8BEF\u6587\u6848\u3002 */\n const bookStatus = createSnapshotStore<string>('')\n\n const reloadBook = async (): Promise<void> => {\n const reply = await loadPromptBook()\n if (reply.ok && reply.book !== undefined) {\n book.set(reply.book)\n bookStatus.set('')\n return\n }\n bookStatus.set(reply.error ?? '\u8BFB\u53D6\u5FEB\u6377\u6307\u4EE4\u5931\u8D25')\n }\n\n const commitBook = (next: QuickPromptBook): void => {\n book.set(next)\n bookStatus.set('saving')\n void savePromptBook(next).then(\n (reply) => {\n if (reply.ok && reply.book !== undefined) {\n // \u7528\u5BBF\u4E3B\u56DE\u8BFB\u7684**\u78C1\u76D8\u771F\u5B9E\u5185\u5BB9**\u8986\u76D6\u672C\u5730\uFF1A\u4EFB\u4F55\u88AB\u6536\u7A84/\u4E22\u5F03\u7684\u5B57\u6BB5\u7ACB\u523B\u53EF\u89C1\u3002\n book.set(reply.book)\n bookStatus.set('')\n return\n }\n bookStatus.set(reply.error ?? '\u4FDD\u5B58\u5931\u8D25')\n void reloadBook()\n },\n (error: unknown) => {\n bookStatus.set(error instanceof Error ? error.message : String(error))\n void reloadBook()\n },\n )\n }\n\n void reloadBook()\n\n const bookActions = {\n reload: (): void => { void reloadBook() },\n addCategory: (name: string): void => { commitBook(withCategoryAdded(book.getSnapshot(), name)) },\n renameCategory: (id: string, name: string): void => {\n commitBook(withCategoryRenamed(book.getSnapshot(), id, name))\n },\n removeCategory: (id: string): void => { commitBook(withCategoryRemoved(book.getSnapshot(), id)) },\n moveCategory: (id: string, delta: number): void => {\n commitBook(withCategoryMoved(book.getSnapshot(), id, delta))\n },\n addPrompt: (categoryId: string): void => { commitBook(withPromptAdded(book.getSnapshot(), categoryId)) },\n patchPrompt: (categoryId: string, id: string, patch: { label?: string; prompt?: string }): void => {\n commitBook(withPromptPatched(book.getSnapshot(), categoryId, id, patch))\n },\n removePrompt: (categoryId: string, id: string): void => {\n commitBook(withPromptRemoved(book.getSnapshot(), categoryId, id))\n },\n movePrompt: (categoryId: string, id: string, delta: number): void => {\n commitBook(withPromptMoved(book.getSnapshot(), categoryId, id, delta))\n },\n resetBook: (): void => { commitBook(defaultQuickBook()) },\n /** \u628A\u67D0\u6761\u4ECE\u5B83\u6240\u5728\u5206\u7C7B\u79FB\u5230\u76EE\u6807\u5206\u7C7B\uFF08\u300C\u79FB\u52A8\u5230\u8FD9\u91CC\u300D\uFF1A\u8FFD\u52A0\u5230\u76EE\u6807\u672B\u5C3E\uFF09\u3002 */\n movePromptToCategory: (promptId: string, toCategoryId: string): void => {\n commitBook(withPromptMovedToCategory(book.getSnapshot(), promptId, toCategoryId))\n },\n /** \u8BBE\u7F6E\u9875\u300C\u4FDD\u5B58\u300D\uFF1A\u628A\u7F16\u8F91\u5668\u91CC\u7684\u6574\u672C\u4E00\u6B21\u5199\u56DE\uFF08\u800C\u4E0D\u662F\u6BCF\u6572\u4E00\u4E2A\u5B57\u5C31\u5199\u76D8\uFF09\u3002 */\n saveBook: (next: QuickPromptBook): void => { commitBook(next) },\n }\n\n const resetAll = (): void => {\n // \u6CE8\u610F\uFF1A\u5BBF\u4E3B\u534A\u7684\u8BB0\u8D26\u5B57\u6BB5\uFF08HOST_OWNED_FIELDS\uFF09\u6545\u610F\u4E0D\u5728\u540D\u5355\u91CC\u2014\u2014\u6E05\u6389\u5B83\u4EEC\u4F1A\u8BA9\n // \u5DF2\u7ECF\u5199\u5165 llm-pi-ai \u7684\u8BF7\u6C42\u5934\u5931\u53BB\u8BB0\u8D26\uFF0C\u4ECE\u800C\u6C38\u8FDC\u64A4\u9500\u4E0D\u6389\u3002\n // \u5FEB\u6377\u6307\u4EE4\u4E5F\u4E0D\u5728\u540D\u5355\u91CC\uFF1A\u5B83\u7684\u771F\u76F8\u5DF2\u7ECF\u642C\u5230 quick-prompts.json\uFF08\u89C1 bookActions.resetBook\uFF09\uFF0C\n // \u800C\u8BBE\u7F6E\u6587\u6863\u91CC\u90A3\u4EFD 0.2.x \u7684\u65E7\u503C\u662F**\u8FC1\u79FB\u7684\u79CD\u5B50**\uFF0C\u6545\u610F\u7559\u7740\u4E0D\u6E05\u2014\u2014\u4E07\u4E00\u56DE\u6EDA\u5230\u65E7\u7248\u8FD8\u80FD\u770B\u5230\u3002\n void scope.mutate(\n [\n ENABLED_FIELD, SEND_KEY_FIELD, NEWLINE_KEY_FIELD, ...MENU_FIELDS,\n MENU_MODE_FIELD,\n // \u65E7\u7684\u5E03\u5C14\u5B57\u6BB5\u4E5F\u4E00\u5E76\u6E05\u6389\uFF1A\u5B83\u53EA\u662F\u8FC1\u79FB\u7EBF\u7D22\uFF0C\u7559\u7740\u4F1A\u628A\u300C\u6062\u590D\u9ED8\u8BA4\u300D\u540E\u7684\u6863\u4F4D\u53C8\u62C9\u56DE\u65E7\u503C\u3002\n MENU_NATIVE_FIELD,\n PANEL_RESIZE_FIELD, PANEL_WIDTH_FIELD, PANEL_HEIGHT_FIELD,\n HEADER_ENABLED_FIELD, HEADER_NAME_FIELD, HEADER_VALUE_FIELD, HEADER_ROUTES_FIELD,\n OPTIMIZER_TIER_FIELD,\n // 0.5.0 \u65B0\u589E\u7684\u7528\u6237\u914D\u7F6E\uFF1A\u7EC8\u7AEF\u6863\u4F4D/\u8DEF\u5F84\uFF08\u300C\u6062\u590D\u9ED8\u8BA4\u300D\u4E5F\u8BE5\u628A\u5B83\u4EEC\u6062\u590D\uFF09\u3002\n TERMINAL_MODE_FIELD, TERMINAL_BASH_PATH_FIELD,\n // \u4E94\u680F\u5F00\u5173\u4E5F\u6E05\u6389\uFF1A\u6E05\u6389 = \u56DE\u5230\"\u4ECE\u6CA1\u78B0\u8FC7\u8FD9\u4E00\u680F\"\u21D2 \u5168\u5173\uFF08\u65B0\u88C5\u9ED8\u8BA4\u7684\u6837\u5B50\uFF09\u3002\n // \u82E5\u4E0D\u6E05\uFF0C\u6062\u590D\u9ED8\u8BA4\u4E4B\u540E\u516D\u680F\u8FD8\u4F1A\u4FDD\u6301\u4E4B\u524D\u6253\u5F00\u7684\u72B6\u6001\uFF0C\u4E0E\"\u9ED8\u8BA4\u5173\"\u7684\u8BED\u4E49\u4E0D\u7B26\u3002\n KEYS_ENABLED_FIELD, MENU_ENABLED_FIELD, QUICK_ENABLED_FIELD,\n PANEL_ENABLED_FIELD, TERMINAL_ENABLED_FIELD,\n // 0.5.0 \u91CC\u90A3\u4E2A\u300C\u53EF\u9009\u91CD\u542F\u547D\u4EE4\u300D\u5B57\u6BB5\u5DF2\u7ECF\u5220\u6389\uFF0C\u4F46\u8001\u6587\u6863\u91CC\u53EF\u80FD\u8FD8\u7559\u7740\u503C\uFF1A\n // \u987A\u624B\u6E05\u6389\uFF0C\u514D\u5F97\u5B83\u6C38\u8FDC\u8EBA\u5728\u8BBE\u7F6E\u6587\u4EF6\u91CC\u6CA1\u4EBA\u8BA4\u8BC6\u3002\n 'restartCommand',\n ].map(field => ({ op: 'unset', path: [field] })),\n ).catch((error: unknown) => {\n console.error('[composer-ux] settings reset failed', error)\n })\n bookActions.resetBook()\n }\n\n // \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\u4E0E\u63D0\u793A\u8BCD\u4F18\u5316 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** \u9762\u677F\u5E95\u90E8\u7684\u77ED\u63D0\u793A\uFF1B\u5230\u65F6\u81EA\u52A8\u6D88\u5931\uFF08\u4E0E\u53F3\u952E\u83DC\u5355\u7684 note \u540C\u4E00\u5957\u8DEF\uFF09\u3002 */\n let noticeTimer: ReturnType<typeof setTimeout> | undefined\n const note = (message: string, ms = 4500): void => {\n panelNotice.set(message)\n if (noticeTimer !== undefined) clearTimeout(noticeTimer)\n if (message === '') return\n noticeTimer = setTimeout(() => { panelNotice.set('') }, ms)\n }\n ctx.effect(() => () => {\n if (noticeTimer !== undefined) clearTimeout(noticeTimer)\n }, 'composer-ux: quick notice timer')\n\n const quickActions = {\n toggle: (anchor: { left: number; bottom: number; width: number }): void => {\n if (panel.getSnapshot() !== null) {\n panel.set(null)\n panelNotice.set('')\n return\n }\n panelNotice.set('')\n panel.set(anchor)\n },\n close: (): void => {\n panel.set(null)\n panelNotice.set('')\n },\n insert: (text: string): void => {\n if (insertIntoDraft(text)) focusComposer()\n },\n optimize: (): void => {\n if (optimizing.getSnapshot()) return\n const draft = currentDraft()\n if (draft.trim() === '') {\n note('\u8F93\u5165\u6846\u662F\u7A7A\u7684\uFF1A\u5148\u5199\u70B9\u4EC0\u4E48\uFF0C\u518D\u70B9\u4F18\u5316')\n return\n }\n optimizing.set(true)\n note('\u6B63\u5728\u4F18\u5316\u2026')\n void optimizeDraft(draft, live.getSnapshot().optimizerTier).then(\n (result) => {\n optimizing.set(false)\n if (!result.ok) {\n note(`\u4F18\u5316\u5931\u8D25\uFF1A${result.error ?? '\u672A\u77E5\u539F\u56E0'}`)\n return\n }\n replaceDraft(result.text ?? '')\n focusComposer()\n // \u72B6\u6001\u884C\u5982\u5B9E\u4EA4\u4EE3\u8FD9\u4E00\u8F6E\u5230\u5E95\u53D1\u751F\u4E86\u4EC0\u4E48\uFF080.6.0 \u8D77\u5BBF\u4E3B\u4F1A\u56DE\u62A5\u8BB0\u8D26\u4FE1\u606F\uFF09\uFF1A\n // \u7528\u4E86\u51E0\u4E2A\u6761\u76EE\u3001\u4E22\u4E86\u51E0\u6761\u3001\u8D70\u6CA1\u8D70\u964D\u7EA7/\u91CD\u8BD5 \u2014\u2014 \u7528\u6237\u636E\u6B64\u5224\u65AD\u8FD9\u6B21\u4F18\u5316\u53EF\u4E0D\u53EF\u4FE1\u3002\n const bits: string[] = []\n if (result.fallback === true) bits.push('\u6A21\u578B\u6CA1\u6309\u6761\u76EE\u5951\u7EA6\u8F93\u51FA\uFF0C\u5DF2\u6574\u6BB5\u7167\u6536\uFF08\u672A\u6821\u9A8C\u4F9D\u636E\uFF09')\n else bits.push(`${String(result.itemCount ?? 0)} \u6761\u8865\u5168`)\n const lost = result.dropped?.length ?? 0\n if (lost > 0) bits.push(`\u4E22\u5F03 ${String(lost)} \u6761`)\n if (result.promptSource === 'custom') bits.push('\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD')\n if (result.retried === true) bits.push('\u91CD\u8BD5\u8FC7\u4E00\u6B21')\n note(`\u5DF2\u5199\u56DE\u8F93\u5165\u6846\uFF08${result.route}\uFF09\u00B7 ${bits.join(' \u00B7 ')} \u00B7 Ctrl+Z \u53EF\u8FD8\u539F`)\n },\n (error: unknown) => {\n optimizing.set(false)\n note(`\u4F18\u5316\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`)\n },\n )\n },\n setTier: (tier: OptimizerTier): void => { setField(OPTIMIZER_TIER_FIELD, tier) },\n /**\n * \u8BBE\u7F6E\u67D0\u6761\u7684\u63D2\u5165\u6A21\u5F0F\uFF08\u5173 / \u6BCF\u6B21 / \u4EC5\u9996\u6B21\uFF09\u3002\n *\n * \u754C\u9762\u4E0A\u53EA\u6709\u8FD9\u4E00\u4E2A\u5165\u53E3\uFF1A\u4E24\u4E2A\u4E92\u65A5\u6807\u5FD7\u7531 `withInsertMode` **\u4E00\u6B21\u5199\u5BF9**\uFF0C\n * \u4E0D\u7ED9\u300C\u53C8\u6BCF\u6B21\u53C8\u4EC5\u9996\u6B21\u300D\u7559\u7F1D\u3002\n */\n setInsertMode: (promptId: string, mode: InsertMode): void => {\n commitBook(withInsertMode(book.getSnapshot(), promptId, mode))\n },\n }\n\n // \u8BBE\u7F6E\u9875\u6761\u76EE\u3002\n slots.inject('settings.section', () => slots.register({\n name: 'settings.section',\n id: 'composer-ux',\n order: 40,\n label: '\u8F93\u5165\u4F53\u9A8C',\n inject: () => ({\n hooks: { live, book, bookStatus, writeNotice },\n actions: {\n setField, clearField, resetAll,\n saveBook: bookActions.saveBook,\n reloadBook: bookActions.reload,\n resetBook: bookActions.resetBook,\n dismissNotice: () => { writeNotice.set('') },\n },\n }),\n }, SettingsSection))\n\n // \u53F3\u952E\u83DC\u5355\u6D6E\u5C42\uFF08shell.overlay \u662F root \u7EA7 list \u69FD\uFF1B\u5149\u6807\u5C42\u672C\u8EAB\u70B9\u51FB\u7A7F\u900F\uFF0C\u83DC\u5355\u81EA\u8425 pointer-events\uFF09\u3002\n slots.inject('shell.overlay', () => slots.register({\n name: 'shell.overlay',\n id: 'composer-ux-menu',\n inject: () => ({\n hooks: { menu, live },\n actions: {\n run: runMenuAction,\n close: () => { menu.set(null) },\n note: (message: string | undefined) => {\n const current = menu.getSnapshot()\n if (current === null) return\n menu.set({ ...current, note: message })\n },\n },\n }),\n }, ContextMenuHost))\n\n // \u8BBE\u7F6E\u9762\u677F\u8FB9\u7F18\u62D6\u62FD\u624B\u67C4\u3002\n slots.inject('shell.overlay', () => slots.register({\n name: 'shell.overlay',\n id: 'composer-ux-panel-resize',\n inject: () => ({ hooks: { live }, actions: { setField } }),\n }, PanelResizeHandles))\n\n // \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u5165\u53E3\u6309\u94AE\uFF1A\u4E0E\u5B98\u65B9\u300C\u5C55\u5F00\u300D\u6309\u94AE\u540C\u6392\uFF08order 89 < \u5C55\u5F00\u7684 90\uFF09\u3002\n slots.inject('conversation.input.right', () => slots.register({\n name: 'conversation.input.right',\n id: 'composer-ux-quick',\n order: 89,\n label: '\u5FEB\u6377\u6307\u4EE4',\n inject: () => ({\n hooks: { live, panel },\n actions: { toggle: quickActions.toggle },\n }),\n }, QuickCommandsButton))\n\n // \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u5C55\u5F00\u9762\u677F\uFF1A\u8D70 root \u7EA7\u6D6E\u5C42\uFF0C\u4E0D\u53D7\u8F93\u5165\u5361\u7247\u88C1\u526A\u3002\n slots.inject('shell.overlay', () => slots.register({\n name: 'shell.overlay',\n id: 'composer-ux-quick-panel',\n inject: () => ({\n hooks: { live, panel, busy: optimizing, notice: panelNotice, book, bookStatus },\n actions: {\n toggle: quickActions.toggle,\n close: quickActions.close,\n insert: quickActions.insert,\n optimize: quickActions.optimize,\n setTier: quickActions.setTier,\n setInsertMode: quickActions.setInsertMode,\n addCategory: bookActions.addCategory,\n renameCategory: bookActions.renameCategory,\n removeCategory: bookActions.removeCategory,\n moveCategory: bookActions.moveCategory,\n addPrompt: bookActions.addPrompt,\n movePrompt: bookActions.movePromptToCategory,\n reloadBook: bookActions.reload,\n },\n }),\n }, QuickCommandsPanel))\n\n // \u8BBE\u7F6E\u9875\u6298\u53E0\u5361\u7247\u6837\u5F0F\uFF08\u5E38\u9A7B\uFF1B\u53EA\u7BA1\u8BBE\u7F6E\u9875\u5916\u89C2\uFF0C\u4E0E\u603B\u5F00\u5173\u65E0\u5173\uFF09\u3002\n ctx.effect(() => installSettingsCardStyle(), 'composer-ux: settings card style')\n\n // \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u5165\u53E3\u6309\u94AE\u6837\u5F0F\u8868\uFF08\u4E0E\u65C1\u8FB9\u5B98\u65B9\u300C\u5C55\u5F00\u300D\u6309\u94AE\u9010\u9879\u5BF9\u9F50\uFF09\u3002\n ctx.effect(() => installQuickButtonStyle(), 'composer-ux: quick button style')\n\n // \u8BBE\u7F6E\u9762\u677F\u5C3A\u5BF8\u624B\u67C4\u6837\u5F0F\uFF08\u5E38\u9A7B\uFF1B\u300C\u8BBE\u7F6E\u9762\u677F\u300D\u680F\u5173\u6389\u65F6\u624B\u67C4\u7EC4\u4EF6\u81EA\u5DF1\u8FD4\u56DE null\uFF0C\u6837\u5F0F\u7559\u7740\u65E0\u526F\u4F5C\u7528\uFF09\u3002\n // 0.6.0 \u8D77\u8FD9\u91CC\u53EA\u5269\u5C3A\u5BF8\u624B\u67C4\uFF1A\u5BFC\u822A\u5217\u6EDA\u52A8\u7531 DSH 0.1.7 \u7684\u5B98\u65B9\u8BBE\u7F6E\u9875\u81EA\u5E26\u3002\n ctx.effect(() => installPanelResizeStyle(), 'composer-ux: panel resize style')\n\n // \u952E\u4F4D\u62E6\u622A + \u53F3\u952E\u83DC\u5355\u6253\u5F00 + \u5B98\u65B9\u53D1\u9001\u6309\u94AE\u4E0A\u7684\u6761\u76EE\u9644\u52A0\uFF08\u4E09\u4EF6\u4E8B\u5171\u7528\u8FD9\u4E00\u7EC4\u6355\u83B7\u76D1\u542C\uFF09\u3002\n // \u5B89\u88C5\u6761\u4EF6\u653E\u5BBD\u6210\"\u4E09\u680F\u91CC\u4EFB\u610F\u4E00\u680F\u5F00\u7740\"\uFF0C\u5404\u81EA\u5728\u81EA\u5DF1\u7684\u5904\u7406\u51FD\u6570\u91CC\u6309\u680F\u5224\u65AD \u2014\u2014\n // \u514D\u5F97\u53EA\u5F00\u300C\u5FEB\u6377\u6307\u4EE4\u300D\u65F6\u8FDE\u5B98\u65B9\u53D1\u9001\u6309\u94AE\u90A3\u6761\u8DEF\u90FD\u4E0D\u88C5\uFF08\u90A3\u6837\u9644\u52A0\u5C31\u5931\u6548\u4E86\uFF09\u3002\n ctx.effect(() => {\n let dispose: (() => void) | null = null\n const syncInterceptors = (): void => {\n const settings = live.getSnapshot()\n const sections = activeSections(settings)\n const wanted = sections.keys || sections.menu || sections.quick\n if (wanted && dispose === null) {\n dispose = installInterceptors({\n settings: () => live.getSnapshot(),\n // \u300C\u4EC5\u9996\u6B21\u300D\u7531\u8FD9\u91CC\u51B3\u5B9A\u662F\u5426\u7B97\u8FDB\u8FD9\u4E00\u6279\uFF1A\u4F1A\u8BDD\u8FD8\u662F\u7A7A\u7684\uFF08blank\uFF09\u624D\u5E26\u4E0A\u3002\n // \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u680F\u5173\u6389\u65F6\u8FD9\u91CC\u76F4\u63A5\u7ED9\u7A7A\u6279\u6B21 \u2014\u2014 \u8FD9\u662F\u552F\u4E00\u4E00\u5904\"\u5173\u6389\u5C31\u4E0D\u9644\u52A0\"\u7684\u95F8\uFF0C\n // \u952E\u4F4D\u53D1\u9001\u4E0E\u5B98\u65B9\u6309\u94AE\u4E24\u6761\u8DEF\u90FD\u4ECE\u8FD9\u91CC\u53D6\u6279\u6B21\uFF0C\u4E0D\u9700\u8981\u5404\u5199\u4E00\u904D\u3002\n promptsForSend: () => (activeSections(live.getSnapshot()).quick\n ? appendBatchForSend(book.getSnapshot(), currentBlankSession())\n : []),\n setMenu: state => { menu.set(state) },\n menuOpen: () => menu.getSnapshot() !== null,\n })\n } else if (!wanted) {\n dispose?.()\n dispose = null\n }\n // \u53EA\u8981\u4E0D\u662F\u300C\u81EA\u5B9A\u4E49\u300D\u6863\uFF0C\u5C31\u6E05\u6389\u53EF\u80FD\u8FD8\u5F00\u7740\u7684\u81EA\u5B9A\u4E49\u83DC\u5355\uFF08\u5B98\u65B9 / \u6D4F\u89C8\u5668\u4E24\u6863\u90FD\u4E0D\u8BE5\u7559\u4E0B\u5B83\uFF09\u3002\n if (settings.menuMode !== 'custom' || !sections.menu) menu.set(null)\n // \u5FEB\u6377\u6307\u4EE4\u680F\u5173\u6389\u65F6\u6309\u94AE\u672C\u8EAB\u4E5F\u4F1A\u6D88\u5931\uFF08\u7EC4\u4EF6\u91CC\u6309\u5F00\u5173\u8FD4\u56DE null\uFF09\uFF0C\n // \u6D6E\u5C42\u5FC5\u987B\u8DDF\u7740\u4E00\u8D77\u6536\uFF0C\u5426\u5219\u4F1A\u7559\u4E0B\u4E00\u4E2A\u6CA1\u6709\u951A\u70B9\u7684\u9762\u677F\u3002\n if (!sections.quick) panel.set(null)\n }\n syncInterceptors()\n const unsubscribe = live.subscribe(syncInterceptors)\n return () => {\n unsubscribe()\n dispose?.()\n dispose = null\n }\n }, 'composer-ux: input interceptors')\n}\n", "/**\n * bash \u63A2\u6D4B\uFF08\u7EAF\u51FD\u6570\uFF0C\u96F6 import\uFF0Chost \u4E0E\u6D4B\u8BD5\u5171\u7528\uFF09\u3002\n *\n * \u4E3A\u4EC0\u4E48\u4E0D\u80FD\"\u626B PATH \u91CC\u7684 bash.exe \u5C31\u5B8C\u4E8B\"\uFF1A\n *\n * 1. **Windows \u4E0A `bash.exe` \u6709\u4E24\u4E2A\u6765\u6E90\uFF0C\u5176\u4E2D\u4E00\u4E2A\u5FC5\u987B\u6392\u9664\u3002**\n * `C:\\Windows\\System32\\bash.exe` \u4E0E `\u2026\\Microsoft\\WindowsApps\\bash.exe` \u662F WSL \u7684\n * \u542F\u52A8\u5668\u3002\u628A\u5B83\u4EA4\u7ED9\u6A21\u578B\uFF0C\u7B49\u4E8E\u628A Windows \u8DEF\u5F84\u4F53\u7CFB\u6362\u6389\uFF1A`D:\\a\\b` \u8981\u5199\u6210 `/mnt/d/a/b`\uFF0C\n * \u76D8\u7B26\u3001\u53CD\u659C\u6760\u3001`%TEMP%` \u5168\u90FD\u4E0D\u901A\uFF0C\u800C\u6A21\u578B\u624B\u91CC\u8FD8\u62FF\u7740 Windows \u98CE\u683C\u7684\u8DEF\u5F84\u4E0E\u5DE5\u4F5C\u76EE\u5F55\u3002\n * \u6240\u4EE5\u8FD9\u91CC\u662F**\u786C\u6392\u9664**\uFF08`isWslBash`\uFF09\uFF0C\u4E0D\u662F\"\u6392\u5E8F\u9760\u540E\"\u3002\n *\n * 2. **Git for Windows \u4E0D\u4E00\u5B9A\u88C5\u5728 Program Files\u3002** \u5B89\u88C5\u5668\u4EE5\u7BA1\u7406\u5458\u8FD0\u884C\u65F6\u9ED8\u8BA4\u843D\n * `C:\\Program Files\\Git`\uFF0C**\u4EE5\u666E\u901A\u7528\u6237\u8FD0\u884C\u65F6\u9ED8\u8BA4\u843D `%LOCALAPPDATA%\\Programs\\Git`**\uFF1B\n * \u8FD8\u6709 Scoop / Chocolatey / GitHub Desktop \u5185\u5D4C / \u81EA\u89E3\u538B PortableGit \u7B49\u6765\u6E90\u3002\n * \u672C\u673A\u5C31\u662F\u53CD\u4F8B\uFF1AGit \u88C5\u5728 `D:\\Git`\uFF08\u53EA\u6709\u56E0\u4E3A `D:\\Git\\cmd` \u5728 PATH \u4E0A\u624D\u88AB\u627E\u5230\uFF09\u3002\n * \u6240\u4EE5\u63A2\u6D4B\u662F**\u5148\u627E git\uFF0C\u518D\u7531\u540C\u4E00\u4E2A\u5B89\u88C5\u53CD\u63A8 bash**\uFF0C\u518D\u53E0\u52A0\u4E00\u4EFD\"\u5E38\u89C1\u6765\u6E90\"\u5019\u9009\u8868\u3002\n *\n * 3. **Niubash\uFF08\u725B bash\uFF0C`niu.exe`\uFF09\u662F\u5019\u9009\u800C\u4E0D\u662F\u9ED8\u8BA4\u3002** \u5B83\u7684\u547D\u4EE4\u96C6\uFF08winuxcmd\uFF09\u5BF9\n * \u975E ASCII \u53C2\u6570\u7684\u5904\u7406\u6709\u95EE\u9898\uFF08\u5B9E\u6D4B\uFF1A`grep <\u4E2D\u6587\u6587\u4EF6\u540D>` \u76F4\u63A5 `cannot open` \u5E76\u4EE5\n * `0xC0000409` \u9000\u51FA\uFF09\uFF0C\u6240\u4EE5\u6392\u5728\u771F Git Bash \u4E4B\u540E\uFF0C\u4F46\u4ECD\u7136\u5217\u51FA\u6765 \u2014\u2014 \u7528\u6237\u53EF\u80FD\u7279\u610F\u9009\u4E86\u5B83\u3002\n *\n * \u8986\u76D6\u7684\u6765\u6E90\uFF08\u987A\u5E8F\u5373\u4F18\u5148\u7EA7\uFF0C\u540C\u7C7B\u5185\u4FDD\u6301\u8FD9\u91CC\u7684\u5148\u540E\uFF09\uFF1A\n * \u663E\u5F0F\u8DEF\u5F84 \u2192 PATH \u4E0A\u7684 git \u53CD\u63A8 \u2192 Program Files / x86 / W6432 / `%LOCALAPPDATA%\\Programs`\n * \u2192 Scoop \u2192 Chocolatey \u4FBF\u643A\u5305 \u2192 GitHub Desktop \u5185\u5D4C \u2192 \u65E7 GitHub \u7684 PortableGit\n * \u2192 Visual Studio \u5185\u5D4C \u2192 MSYS2 \u2192 Cygwin \u2192 **\u5404\u76D8\u7B26\u6839\u4E0B\u7684 Git / PortableGit / msys64 / cygwin64**\n * \u2192 Niubash \u2192 PATH \u515C\u5E95\u3002\n *\n * \u5E26\u7248\u672C\u53F7\u7684\u6765\u6E90\uFF08GitHub Desktop \u7684 `app-*`\u3001\u65E7 GitHub \u7684 `PortableGit_*`\u3001VS \u7684\n * `<\u5E74\u4EFD>\\<\u7248\u672C>`\uFF09\u9700\u8981\"\u5217\u4E00\u773C\u5B50\u76EE\u5F55\"\uFF0C\u6240\u4EE5\u8F93\u5165\u91CC\u591A\u4E86\u4E00\u4E2A\u53EF\u6CE8\u5165\u7684 `listDirs`\uFF1B\n * **\u4E0D\u6CE8\u5165\u5C31\u9000\u5316\u6210\u7EAF\u5B58\u5728\u6027\u68C0\u67E5**\uFF08\u4E0D\u8BFB\u76EE\u5F55\uFF09\u3002\u5168\u7A0B\u4E0D\u8FD0\u884C\u4EFB\u4F55\u8FDB\u7A0B\uFF1A\u7248\u672C\u63A2\u6D4B\u5C5E\u4E8E\u5BBF\u4E3B\u534A\u3002\n */\n\n/** \u5019\u9009\u7684\u79CD\u7C7B\uFF08\u51B3\u5B9A\u6392\u5E8F\u6743\u91CD\u4E0E\u9ED8\u8BA4\u6807\u7B7E\uFF09\u3002 */\nexport type BashKind = 'git' | 'msys2' | 'cygwin' | 'niubash' | 'path'\n\n/** \u4E00\u4E2A\u5019\u9009 shell\u3002 */\nexport interface BashCandidate {\n /** \u5F52\u4E00\u5316\u540E\u7684\u7EDD\u5BF9\u8DEF\u5F84\uFF08\u6B63\u659C\u6760\uFF09\uFF0C\u53EF\u76F4\u63A5\u843D\u76D8\u4E0E\u56DE\u663E\u3002 */\n readonly path: string\n readonly kind: BashKind\n /** \u7ED9\u7528\u6237\u770B\u7684\u6765\u6E90\u6807\u7B7E\uFF08\u5177\u4F53\u6765\u6E90\u4F18\u5148\uFF0C\u4F8B\u5982 'Scoop \u7684 git'\uFF0C\u5426\u5219\u7528\u79CD\u7C7B\u6807\u7B7E\uFF09\u3002 */\n readonly label: string\n /** \u662F\u5426\u662F\u7528\u6237\u5728\u8BBE\u7F6E\u91CC\u663E\u5F0F\u6307\u5B9A\u7684\uFF08\u754C\u9762\u6807\u6CE8\u300C\u4F60\u6307\u5B9A\u7684\u300D\uFF0C\u4E14\u6392\u5E8F\u6C38\u8FDC\u5728\u6700\u524D\uFF09\u3002 */\n readonly explicit: boolean\n}\n\n/** \u88AB\u786C\u6392\u9664\u7684\u8DEF\u5F84\u53CA\u539F\u56E0\uFF08\u8BBE\u7F6E\u9875\u8981\u5982\u5B9E\u8BF4\u660E\"\u4E3A\u4EC0\u4E48\u4E0D\u9009\u5B83\"\uFF09\u3002 */\nexport interface ExcludedPath {\n readonly path: string\n readonly reason: string\n}\n\n/** \u663E\u5F0F\u8DEF\u5F84\uFF08\u8BBE\u7F6E\u91CC\u586B\u7684\uFF09\u7684\u72B6\u6001\u3002 */\nexport interface ExplicitState {\n readonly path: string\n readonly state: 'ok' | 'missing' | 'wsl'\n}\n\n/** \u63A2\u6D4B\u7684\u8F93\u5165\uFF08\u5168\u90E8\u53EF\u6CE8\u5165\uFF0C\u6D4B\u8BD5\u91CC\u7ED9\u5047\u5B9E\u73B0\u5373\u53EF\uFF09\u3002 */\nexport interface DiscoverInput {\n /** \u8DEF\u5F84\u662F\u5426\u5B58\u5728\u3002 */\n readonly exists: (path: string) => boolean\n /** \u6309\u987A\u5E8F\u7684 PATH \u6761\u76EE\uFF08\u672A\u6E05\u6D17\uFF09\u3002 */\n readonly pathEntries: readonly string[]\n /** \u73AF\u5883\u53D8\u91CF\u53D6\u503C\u3002 */\n readonly env: (name: string) => string | undefined\n /** \u8BBE\u7F6E\u91CC\u663E\u5F0F\u586B\u7684 bash \u8DEF\u5F84\uFF08\u53EF\u7A7A\uFF09\u3002 */\n readonly explicitPath?: string\n /**\n * \u5217\u51FA\u67D0\u4E2A\u76EE\u5F55\u4E0B\u7684**\u5B50\u76EE\u5F55\u540D**\uFF08\u53EA\u7528\u4E8E\u5E26\u7248\u672C\u53F7\u7684\u6765\u6E90\uFF1AGitHub Desktop / \u65E7 GitHub / VS\uFF09\u3002\n * \u4E0D\u6CE8\u5165\u3001\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u6CA1\u6709\u6743\u9650\u65F6\u90FD\u5F53\u4F5C\"\u7A7A\"\uFF0C\u63A2\u6D4B\u9000\u5316\u6210\u7EAF\u5B58\u5728\u6027\u68C0\u67E5\u3002\n */\n readonly listDirs?: (parent: string) => readonly string[]\n}\n\n/** \u63A2\u6D4B\u7ED3\u679C\u3002 */\nexport interface DiscoverResult {\n /** \u6309\u4F18\u5148\u7EA7\u6392\u597D\u5E8F\u3001\u5DF2\u53BB\u91CD\u3001\u5DF2\u5254\u9664 WSL \u7684\u5019\u9009\u3002 */\n readonly candidates: readonly BashCandidate[]\n /** \u88AB\u786C\u6392\u9664\u7684\u8DEF\u5F84\uFF08\u5F53\u524D\u53EA\u6709 WSL\uFF09\u3002 */\n readonly excluded: readonly ExcludedPath[]\n /** \u663E\u5F0F\u8DEF\u5F84\u7684\u72B6\u6001\uFF1B\u6CA1\u586B\u5C31\u662F undefined\u3002 */\n readonly explicit?: ExplicitState\n}\n\n/** WSL \u6392\u9664\u539F\u56E0\uFF08\u8BBE\u7F6E\u9875\u76F4\u63A5\u5C55\u793A\u8FD9\u53E5\u8BDD\uFF09\u3002 */\nexport const WSL_REASON = 'WSL \u7684 bash\uFF1A\u5B83\u6309 Linux \u89C4\u5219\u89E3\u91CA\u8DEF\u5F84\uFF08D:\\\\x \u8981\u5199\u6210 /mnt/d/x\uFF09\uFF0C'\n + '\u4E0E\u6A21\u578B\u624B\u91CC\u7684 Windows \u5DE5\u4F5C\u76EE\u5F55\u4E0D\u517C\u5BB9\uFF0C\u6545\u4E0D\u91C7\u7528'\n\n/** \u5F52\u4E00\u5316\uFF1A\u53CD\u659C\u6760\u8F6C\u6B63\u659C\u6760\u3001\u53BB\u6389\u5305\u88F9\u5F15\u53F7\u4E0E\u7ED3\u5C3E\u659C\u6760\u3001\u5408\u5E76\u91CD\u590D\u5206\u9694\u7B26\u3002 */\nexport function normalizePath(value: string): string {\n const trimmed = value.trim().replace(/^\"|\"$/g, '')\n const slashed = trimmed.replace(/\\\\/g, '/').replace(/\\/{2,}/g, '/')\n return slashed.length > 1 ? slashed.replace(/\\/+$/, '') : slashed\n}\n\n/** \u662F\u5426 WSL \u7684 bash\uFF08System32 \u7684\u542F\u52A8\u5668\u4E0E WindowsApps \u7684\u522B\u540D\uFF09\u3002 */\nexport function isWslBash(value: string): boolean {\n const path = normalizePath(value).toLowerCase()\n return /\\/windows\\/system32\\/bash\\.exe$/.test(path) || /\\/windowsapps\\/bash\\.exe$/.test(path)\n}\n\n/** \u6309\u8DEF\u5F84\u5F62\u6001\u5224\u65AD\u79CD\u7C7B\uFF08\u663E\u5F0F\u8DEF\u5F84\u4E5F\u80FD\u56E0\u6B64\u62FF\u5230\u6B63\u786E\u7684\u6807\u7B7E\u4E0E\u4F18\u5148\u7EA7\uFF09\u3002 */\nexport function candidateKindOf(value: string): BashKind {\n const path = normalizePath(value).toLowerCase()\n if (path.endsWith('/niu.exe') || path.includes('/niubash/')) return 'niubash'\n if (path.includes('/msys64/') || path.includes('/msys32/') || path.includes('/msys2/')) return 'msys2'\n if (path.includes('/cygwin')) return 'cygwin'\n // `PortableGit` \u4E5F\u7B97 git\uFF08\u6B63\u5219\u91CC\u628A\u53EF\u9009\u524D\u7F00\u5199\u4E0A\uFF09\uFF0C\u53EA\u662F\u6807\u7B7E\u4E0D\u540C\u3002\n if (/(^|\\/)(portable)?git(\\/|$)/.test(path)) return 'git'\n return 'path'\n}\n\n/** \u79CD\u7C7B \u2192 \u754C\u9762\u6807\u7B7E\uFF08\u5177\u4F53\u6765\u6E90\u6CA1\u7ED9\u65F6\u7528\u5B83\uFF09\u3002 */\nexport function kindLabel(kind: BashKind): string {\n switch (kind) {\n case 'git': return 'Git for Windows'\n case 'msys2': return 'MSYS2'\n case 'cygwin': return 'Cygwin'\n case 'niubash': return 'Niubash\uFF08\u725B bash\uFF09'\n default: return 'PATH'\n }\n}\n\n/** \u79CD\u7C7B\u6392\u5E8F\u6743\u91CD\uFF08\u6570\u5B57\u8D8A\u5C0F\u8D8A\u4F18\u5148\uFF09\uFF1Bniubash \u4F4E\u4E8E MSYS2/Cygwin\uFF0C\u9AD8\u4E8E\u6742\u9879 PATH\u3002 */\nconst KIND_RANK: Record<BashKind, number> = { git: 0, msys2: 1, cygwin: 2, niubash: 3, path: 4 }\n\n/** \u76D8\u7B26\u626B\u63CF\u7684\u5B57\u6BCD\uFF08\u8DF3\u8FC7 A:/B: \u8F6F\u9A71\u4F4D\uFF09\u3002 */\nconst DRIVE_LETTERS = 'CDEFGHIJKLMNOPQRSTUVWXYZ'\n\n/** \u4ECE PATH \u6761\u76EE\u91CC\u8BA4\u51FA git \u5B89\u88C5\u6839\uFF08`<root>\\cmd` / `<root>\\bin` / `<root>\\mingw64\\bin` \u90FD\u5F52\u5230 root\uFF09\u3002 */\nfunction gitRootOf(entry: string): string | undefined {\n const path = normalizePath(entry)\n if (path === '') return undefined\n const lower = path.toLowerCase()\n for (const suffix of ['/mingw64/bin', '/mingw32/bin', '/usr/bin', '/cmd', '/bin']) {\n if (lower.endsWith(suffix)) return path.slice(0, path.length - suffix.length)\n }\n return path\n}\n\n/** \u4E00\u4E2A\u5B89\u88C5\u6839\u4E0B\u6240\u6709\u53EF\u80FD\u7684 bash \u4F4D\u7F6E\uFF08\u987A\u5E8F\u5373\u4F18\u5148\u7EA7\uFF09\u3002 */\nfunction bashPathsUnder(root: string): readonly string[] {\n return [`${root}/bin/bash.exe`, `${root}/usr/bin/bash.exe`, `${root}/mingw64/bin/bash.exe`]\n}\n\n/**\n * `usr/bin` / `mingw64/bin` \u4E0B\u7684 bash \u662F**\u88F8\u672C\u4F53**\uFF1A\u76F4\u63A5\u8DD1\u5B83\u4E0D\u4F1A\u51C6\u5907 MSYS \u73AF\u5883\u3002\n *\n * \u672C\u673A\u5B9E\u6D4B\uFF08`D:\\Git` \u4E24\u4E2A\u90FD\u8DD1\u4E86\u4E00\u904D\uFF09\uFF1A`bin\\bash.exe` \u7ED9\u51FA `MSYSTEM=MINGW64`\u3001\n * `PATH` \u524D\u7F6E `/mingw64/bin:/usr/bin`\uFF0C`head` / `grep` / `uname` \u90FD\u5728\uFF08\u4E2D\u6587\u6587\u4EF6\u540D\u5F53\u53C2\u6570\u4E5F\u6B63\u5E38\uFF09\uFF1B\n * \u800C `usr\\bin\\bash.exe` \u7684 `MSYSTEM` \u4E3A\u7A7A\u3001`PATH` \u53EA\u6709\u7EE7\u627F\u6765\u7684 Windows PATH\uFF08\u91CC\u9762\u53EA\u6709 `D:\\Git\\cmd`\uFF09\uFF0C\n * \u4E8E\u662F `head` / `grep` / `uname` **\u5168\u90E8 command not found** \u2014\u2014 \u4EA4\u7ED9\u6A21\u578B\u5C31\u662F\u5927\u9762\u79EF\u5931\u8D25\u3002\n *\n * \u6240\u4EE5\uFF1A\u540C\u4E00\u4E2A\u6839\u4E0B\u53EA\u8981\u6709 `bin/bash.exe`\uFF0C\u5C31\u4E0D\u518D\u5217\u8FD9\u4E2A\u88F8\u672C\u4F53\uFF08\u7528\u6237\u4ECD\u53EF\u624B\u586B\uFF09\u3002\n * \u6CA1\u6709 `bin/bash.exe` \u5144\u5F1F\u7684\uFF08\u4F8B\u5982 MSYS2 \u53EA\u63D0\u4F9B `usr\\bin\\bash.exe`\uFF09\u7167\u5E38\u5217\u51FA\u3002\n * @param value \u5019\u9009\u8DEF\u5F84\u3002\n * @returns \u5B89\u88C5\u6839\uFF1B\u4E0D\u662F\u88F8\u672C\u4F53\u65F6 undefined\u3002\n */\nexport function unpreparedBashRoot(value: string): string | undefined {\n const match = /^(.*)\\/(usr|mingw32|mingw64)\\/bin\\/bash\\.exe$/i.exec(normalizePath(value))\n return match?.[1]\n}\n\n/** \u4E00\u4E2A\u5019\u9009\u6765\u6E90\uFF1A\u4E00\u7EC4\u5B89\u88C5\u6839 + \u53EF\u9009\u7684\u5177\u4F53\u6807\u7B7E\u3002 */\ninterface SourceGroup {\n readonly roots: readonly string[]\n readonly label?: string\n}\n\n/**\n * \u63A2\u6D4B\u5019\u9009 bash\u3002\n * @param input \u6CE8\u5165\u7684 exists/PATH/\u73AF\u5883\u53D8\u91CF\uFF0C\u4EE5\u53CA\u53EF\u9009\u7684 listDirs\uFF08\u5217\u5B50\u76EE\u5F55\uFF09\u3002\n * @returns \u5019\u9009\u3001\u88AB\u6392\u9664\u7684\u8DEF\u5F84\u3001\u663E\u5F0F\u8DEF\u5F84\u72B6\u6001\u3002\n */\nexport function discoverBashCandidates(input: DiscoverInput): DiscoverResult {\n const seen = new Set<string>()\n const excluded: ExcludedPath[] = []\n const ordered: BashCandidate[] = []\n\n /** \u5217\u5B50\u76EE\u5F55\uFF1B\u6CA1\u6709\u6CE8\u5165\u3001\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u6CA1\u6743\u9650\u90FD\u5F53\u7A7A\u3002 */\n const dirsOf = (parent: string): readonly string[] => {\n if (input.listDirs === undefined) return []\n try {\n return input.listDirs(parent)\n } catch {\n return []\n }\n }\n\n /** \u8BB0\u4E00\u4E2A\u5019\u9009\uFF1BWSL \u4E00\u5F8B\u8F6C\u6210\u6392\u9664\u9879\uFF0C\u91CD\u590D\u8DEF\u5F84\u53EA\u7559\u7B2C\u4E00\u6B21\uFF08\u5373\u4F18\u5148\u7EA7\u6700\u9AD8\u7684\u90A3\u4E00\u6B21\uFF09\u3002 */\n const consider = (raw: string, label?: string, isExplicit = false): void => {\n const path = normalizePath(raw)\n if (path === '') return\n if (isWslBash(path)) {\n // \u53EA\u5728\u5B83**\u786E\u5B9E\u5B58\u5728**\u65F6\u62A5\"\u5DF2\u6392\u9664\"\uFF1A\u5426\u5219\u6BCF\u53F0\u673A\u5668\u90FD\u4F1A\u51ED\u7A7A\u591A\u51FA\u4E00\u6761 WSL \u8B66\u544A\u3002\n if (!input.exists(path)) return\n if (!excluded.some(item => item.path.toLowerCase() === path.toLowerCase())) {\n excluded.push({ path, reason: WSL_REASON })\n }\n return\n }\n // \u88F8\u672C\u4F53\uFF08usr/bin\u3001mingw64/bin\uFF09\uFF1A\u540C\u6839\u4E0B\u5DF2\u6709\u4F1A\u51C6\u5907\u73AF\u5883\u7684 `bin/bash.exe` \u65F6\u4E0D\u518D\u4F5C\u4E3A\u5019\u9009\uFF0C\n // \u514D\u5F97\u7528\u6237\u70B9\u5230\u4E00\u4E2A\"\u547D\u4EE4\u5168\u627E\u4E0D\u5230\"\u7684 shell\u3002**\u663E\u5F0F\u8DEF\u5F84\u4E0D\u53D7\u6B64\u9650**\uFF1A\u90A3\u662F\u7528\u6237\u81EA\u5DF1\u7684\u9009\u62E9\u3002\n if (!isExplicit) {\n const root = unpreparedBashRoot(path)\n if (root !== undefined && input.exists(`${root}/bin/bash.exe`)) return\n }\n const key = path.toLowerCase()\n if (seen.has(key)) return\n if (!input.exists(path)) return\n seen.add(key)\n const kind = candidateKindOf(path)\n ordered.push({ path, kind, label: label ?? kindLabel(kind), explicit: isExplicit })\n }\n\n /** \u4E00\u7EC4\u6765\u6E90\uFF1A\u53EA\u8BD5\u5B58\u5728\u7684\u5B89\u88C5\u6839\uFF0C\u518D\u628A\u8BE5\u6839\u4E0B\u6240\u6709\u53EF\u80FD\u7684 bash \u4F4D\u7F6E\u4E22\u7ED9 consider\u3002 */\n const addGroup = (group: SourceGroup): void => {\n for (const root of group.roots) {\n if (root === '' || !input.exists(root)) continue\n for (const path of bashPathsUnder(root)) consider(path, group.label)\n }\n }\n\n // 1) \u663E\u5F0F\u8DEF\u5F84\uFF1A\u7528\u6237\u81EA\u5DF1\u586B\u7684\uFF0C\u4F18\u5148\u7EA7\u6700\u9AD8\uFF08\u586B\u9519\u4E5F\u4F1A\u5982\u5B9E\u62A5\u544A\uFF09\u3002\n const explicitRaw = normalizePath(input.explicitPath ?? '')\n let explicit: ExplicitState | undefined\n if (explicitRaw !== '') {\n if (isWslBash(explicitRaw)) {\n explicit = { path: explicitRaw, state: 'wsl' }\n // \u7528\u6237\u660E\u786E\u586B\u4E86 WSL\uFF1A\u8981\u8BA9\u4ED6\u770B\u5230\"\u4E3A\u4EC0\u4E48\u4E0D\u91C7\u7528\"\uFF0C\u800C\u4E0D\u662F\u770B\u5230\u5019\u9009\u91CC\u6084\u6084\u5C11\u4E86\u4E00\u6761\u3002\n if (input.exists(explicitRaw)) excluded.push({ path: explicitRaw, reason: WSL_REASON })\n } else if (input.exists(explicitRaw)) explicit = { path: explicitRaw, state: 'ok' }\n else explicit = { path: explicitRaw, state: 'missing' }\n }\n\n const entries = input.pathEntries\n .map(entry => normalizePath(entry))\n .filter(entry => entry !== '')\n const env = (name: string): string | undefined => {\n const value = input.env(name)\n return value === undefined || value === '' ? undefined : normalizePath(value)\n }\n\n const programFiles = env('ProgramFiles') ?? 'C:/Program Files'\n const programFilesX86 = env('ProgramFiles(x86)') ?? 'C:/Program Files (x86)'\n const programW6432 = env('ProgramW6432')\n const localAppData = env('LOCALAPPDATA')\n const home = env('USERPROFILE') ?? env('HOME')\n const scoop = env('SCOOP') ?? (home === undefined ? undefined : `${home}/scoop`)\n const choco = env('ChocolateyInstall')\n ?? (env('ProgramData') === undefined ? 'C:/ProgramData/chocolatey' : `${env('ProgramData') as string}/chocolatey`)\n\n // \u5E26\u7248\u672C\u53F7\u7684\u6765\u6E90\uFF1A\u5217\u4E00\u773C\u5B50\u76EE\u5F55\uFF0C\u6309\u540D\u5B57**\u5012\u5E8F**\uFF08`app-3.4.3` \u8FD9\u79CD\u540D\u5B57\uFF0C\u65B0\u7684\u6392\u5728\u524D\u9762\uFF09\u3002\n const versioned: string[] = []\n if (localAppData !== undefined) {\n const desktop = `${localAppData}/GitHubDesktop`\n for (const dir of [...dirsOf(desktop)].sort().reverse()) {\n if (dir.startsWith('app-')) versioned.push(`${desktop}/${dir}/resources/app/git`)\n }\n const github = `${localAppData}/GitHub`\n for (const dir of [...dirsOf(github)].sort().reverse()) {\n if (dir.startsWith('PortableGit')) versioned.push(`${github}/${dir}`)\n }\n }\n const vsRoot = `${programFiles}/Microsoft Visual Studio`\n for (const year of dirsOf(vsRoot)) {\n const yearRoot = `${vsRoot}/${year}`\n for (const edition of dirsOf(yearRoot)) {\n versioned.push(`${yearRoot}/${edition}/Common7/IDE/CommonExtensions/Microsoft/TeamFoundation/Team Explorer/Git`)\n }\n }\n\n // \u5404\u76D8\u7B26\u6839\u4E0B\u7684\u5E38\u89C1\u540D\u5B57\uFF1A\u8986\u76D6\"\u88C5\u5728 D:\\Git / D:\\PortableGit / \u81EA\u5DF1\u89E3\u538B\"\u7684\u60C5\u51B5\u3002\n const drives: string[] = []\n for (const letter of DRIVE_LETTERS) {\n const root = `${letter}:`\n if (input.exists(`${root}/`)) drives.push(root)\n }\n const driveRoots = (names: readonly string[]): readonly string[] =>\n drives.flatMap(root => names.map(name => `${root}/${name}`))\n\n const groups: readonly SourceGroup[] = [\n // 2) PATH \u4E0A\u8BA4\u51FA\u6765\u7684 git \u6839 \u2014\u2014 \u90A3\u624D\u662F\u7528\u6237\u5B9E\u9645\u5728\u7528\u7684\u90A3\u4EFD\u3002\n ...entries.map(entry => gitRootOf(entry))\n .filter((root): root is string => root !== undefined)\n .map(root => ({ roots: [root] })),\n // 3) \u5B98\u65B9\u5B89\u88C5\u5668\u7684\u4E24\u4E2A\u9ED8\u8BA4\u843D\u70B9 + 32 \u4F4D / \u91CD\u5B9A\u5411\u540E\u7684 Program Files\u3002\n { roots: [programFiles, programFilesX86, programW6432, localAppData === undefined ? undefined : `${localAppData}/Programs`]\n .filter((base): base is string => base !== undefined)\n .map(base => `${base}/Git`) },\n // 4) Scoop\uFF08`scoop install git` \u4F1A\u5E26\u4E00\u4EFD bash\uFF09\u3002\n ...(scoop === undefined ? [] : [{ roots: [`${scoop}/apps/git/current`, `${scoop}/apps/git`], label: 'Scoop \u7684 git' }]),\n // 5) Chocolatey \u7684\u4FBF\u643A\u5305\uFF08`git.install` \u88C5\u7684\u4ECD\u5728 Program Files\uFF0C\u4E0A\u9762\u90A3\u6761\u5DF2\u8986\u76D6\uFF09\u3002\n { roots: [`${choco}/lib/git.portable/tools`, `${choco}/lib/git.portable/tools/git`], label: 'Chocolatey \u4FBF\u643A\u5305' },\n // 6) GitHub Desktop / \u65E7 GitHub for Windows / Visual Studio \u81EA\u5E26\uFF08\u90FD\u5E26\u7248\u672C\u53F7\uFF0C\u9760 listDirs\uFF09\u3002\n { roots: versioned.filter(path => path.includes('GitHubDesktop')), label: 'GitHub Desktop \u5185\u5D4C' },\n { roots: versioned.filter(path => path.includes('/GitHub/PortableGit')), label: 'GitHub PortableGit' },\n { roots: versioned.filter(path => path.includes('/Microsoft Visual Studio/')), label: 'Visual Studio \u5185\u5D4C' },\n // 7) MSYS2 / Cygwin \u7684\u5E38\u89C1\u4F4D\u7F6E\uFF08\u542B\u5404\u76D8\u7B26\u6839\u4E0B\u7684\u540C\u540D\u76EE\u5F55\uFF09\u3002\n { roots: [`${programFiles}/msys64`, 'C:/msys64', ...driveRoots(['msys64'])], label: 'MSYS2' },\n { roots: [`${programFiles}/cygwin64`, 'C:/cygwin64', 'C:/cygwin', ...driveRoots(['cygwin64', 'cygwin'])], label: 'Cygwin' },\n // 8) \u5404\u76D8\u7B26\u6839\u4E0B\u7684 Git / PortableGit\uFF08\u88C5\u5728 D:\\Git\u3001D:\\PortableGit \u8FD9\u7C7B\uFF09\u3002\n { roots: driveRoots(['Git', 'Program Files/Git', 'Program Files (x86)/Git']), label: 'Git for Windows' },\n { roots: driveRoots(['PortableGit']), label: 'PortableGit\uFF08\u81EA\u89E3\u538B\uFF09' },\n ]\n for (const group of groups) addGroup(group)\n\n // 9) Niubash\uFF08\u7528\u6237\u53EF\u80FD\u7279\u610F\u88C5\u7684 bash \u517C\u5BB9\u73AF\u5883\uFF09\u3002\u5B83\u7684\u53EF\u6267\u884C\u6587\u4EF6\u53EB `niu.exe` \u4E14\u5C31\u5728\u6839\u76EE\u5F55\uFF0C\n // \u4E0D\u7B26\u5408\"\u5B89\u88C5\u6839 / bin|usr/bin|mingw64/bin\"\u7684\u5F62\u72B6\uFF0C\u6240\u4EE5\u5355\u72EC\u8003\u8651\uFF0C\u4E0D\u80FD\u585E\u8FDB\u5206\u7EC4\u3002\n if (localAppData !== undefined) consider(`${localAppData}/Programs/Niubash/niu.exe`, 'Niubash\uFF08\u725B bash\uFF09')\n\n // 10) PATH \u515C\u5E95\uFF1A\u6700\u5BB9\u6613\u547D\u4E2D\u7684\u662F WSL\uFF0C\u9760 consider() \u91CC\u7684 isWslBash \u62E6\u6389\u3002\n for (const entry of entries) consider(`${entry}/bash.exe`)\n\n // \u663E\u5F0F\u8DEF\u5F84\u4E5F\u4EA4\u7ED9 consider \u53C2\u4E0E\u53BB\u91CD\uFF1B\u5B83\u9760 `explicit` \u6807\u8BB0\u5728\u6392\u5E8F\u91CC\u62FF\u7B2C\u4E00\uFF0C\n // \u800C\u4E0D\u662F\u9760\u5728\u6570\u7EC4\u91CC\u63D2\u961F \u2014\u2014 \u5426\u5219\u540C\u4E00\u6761\u8DEF\u5F84\u53EF\u80FD\u51FA\u73B0\u4E24\u6B21\u3002\n if (explicit?.state === 'ok') consider(explicit.path, undefined, true)\n\n // \u6392\u5E8F\uFF1A\u663E\u5F0F\u4F18\u5148 \u2192 \u79CD\u7C7B\u6743\u91CD \u2192 \u540C\u4E00\u7EC4\u5185\u4FDD\u6301\u4E0A\u9762\u7684\u641C\u7D22\u5148\u540E\u3002\n const ranked = ordered\n .map((candidate, index) => ({ candidate, index }))\n .sort((a, b) => {\n if (a.candidate.explicit !== b.candidate.explicit) return a.candidate.explicit ? -1 : 1\n const rank = KIND_RANK[a.candidate.kind] - KIND_RANK[b.candidate.kind]\n return rank !== 0 ? rank : a.index - b.index\n })\n .map(item => item.candidate)\n\n return {\n candidates: ranked,\n excluded,\n ...(explicit === undefined ? {} : { explicit }),\n }\n}\n\n/**\n * \u9ED8\u8BA4\u9009\u8C01\uFF1A\u5019\u9009\u8868\u91CC\u7684\u7B2C\u4E00\u4E2A\uFF08\u63A2\u6D4B\u987A\u5E8F\u5DF2\u7ECF\u628A\"\u663E\u5F0F\u8DEF\u5F84 \u2192 \u771F Git Bash \u2192 \u5176\u5B83\"\u6392\u597D\u4E86\uFF09\u3002\n * @param result \u63A2\u6D4B\u7ED3\u679C\u3002\n * @returns \u8DEF\u5F84\uFF1B\u4E00\u4E2A\u5019\u9009\u90FD\u6CA1\u6709\u65F6\u8FD4\u56DE\u7A7A\u4E32\u3002\n */\nexport function defaultBashPath(result: DiscoverResult): string {\n return result.candidates[0]?.path ?? ''\n}\n", "/**\n * \u300C\u9ED8\u8BA4\u7EC8\u7AEF\u300D\u7684\u516C\u5171\u5951\u7EA6\uFF1A\u8BBE\u7F6E\u5B57\u6BB5\u3001\u4E09\u6863\u5143\u6570\u636E\u3001\u5019\u9009\u5F62\u72B6\u3001\u51C0\u5316\u4E0E\"\u6700\u7EC8\u7528\u8C01\"\u7684\u5224\u5B9A\u3002\n *\n * \u96F6 import\uFF08host \u4E0E client \u4E24\u534A\u5171\u7528\uFF0C\u8DE8\u7AEF\u4E0D\u5171\u4EAB\u4EFB\u4F55\u8FD0\u884C\u65F6\u8EAB\u4EFD\uFF09\u3002\n *\n * \u8FD9\u91CC\u7684\u5B57\u6BB5\u5206\u4E24\u7C7B\uFF0C**\u4E0D\u8981\u6DF7**\uFF1A\n * - \u7528\u6237\u914D\u7F6E\uFF1A`terminalMode` / `terminalBashPath` \u2014\u2014 \u7531\u8BBE\u7F6E\u9875\u5199\uFF0C\u5BBF\u4E3B\u534A\u8BFB\uFF1B\n * - \u5BBF\u4E3B\u534A\u81EA\u6301\uFF1A`terminalCandidates` / `terminalStatus` / `terminalEffective` \u2014\u2014\n * \u53EA\u7531\u5BBF\u4E3B\u534A\u5199\uFF08\u63A2\u6D4B\u7ED3\u679C\u4E0E\u8FD0\u884C\u72B6\u6001\uFF09\uFF0C\u8BBE\u7F6E\u9875\u53EA\u8BFB\u5C55\u793A\uFF1B\u300C\u6062\u590D\u9ED8\u8BA4\u300D\u4E0D\u5F97\u6E05\u7A7A\u5B83\u4EEC\n * \uFF08\u89C1 settings-contract \u7684 HOST_OWNED_FIELDS\uFF09\uFF0C\u5426\u5219\u754C\u9762\u4F1A\u5931\u53BB\u63A2\u6D4B\u7ED3\u679C\u4E0E\u72B6\u6001\u3002\n */\nimport type { BashCandidate, BashKind, DiscoverResult, ExplicitState } from './discover.ts'\nimport { defaultBashPath, discoverBashCandidates, normalizePath } from './discover.ts'\n\n/** \u7528\u6237\u914D\u7F6E\u5B57\u6BB5\uFF1A\u7EC8\u7AEF\u6863\u4F4D\u3002 */\nexport const TERMINAL_MODE_FIELD = 'terminalMode'\n\n/** \u7528\u6237\u914D\u7F6E\u5B57\u6BB5\uFF1AGit Bash \u8DEF\u5F84\uFF08\u7559\u7A7A = \u7528\u63A2\u6D4B\u5230\u7684\u7B2C\u4E00\u4E2A\u5019\u9009\uFF09\u3002 */\nexport const TERMINAL_BASH_PATH_FIELD = 'terminalBashPath'\n\n/** \u5BBF\u4E3B\u534A\u81EA\u6301\uFF1A\u63A2\u6D4B\u5230\u7684\u5019\u9009\u5217\u8868\u3002 */\nexport const TERMINAL_CANDIDATES_FIELD = 'terminalCandidates'\n\n/** \u5BBF\u4E3B\u534A\u81EA\u6301\uFF1A\u72B6\u6001\u884C\uFF08\u5F53\u524D\u751F\u6548 shell / \u4E3A\u4EC0\u4E48\u6CA1\u751F\u6548\uFF09\u3002 */\nexport const TERMINAL_STATUS_FIELD = 'terminalStatus'\n\n/** \u5BBF\u4E3B\u534A\u81EA\u6301\uFF1A\u5F53\u524D\u5B9E\u9645\u751F\u6548\u7684 shell\uFF08'bash' / 'pwsh'\uFF09\u3002 */\nexport const TERMINAL_EFFECTIVE_FIELD = 'terminalEffective'\n\n/** \u5BBF\u4E3B\u534A\u6CE8\u518C\u7684\u72B6\u6001/\u53D1\u73B0\u63A5\u53E3\u8DEF\u5F84\uFF08\u5BA2\u6237\u7AEF\u534A\u8BFB\u5199\uFF09\u3002 */\nexport const TERMINAL_API_PATH = '/composer-ux/terminal'\n\n/** \u6863\u4F4D\u3002 */\nexport type TerminalMode = 'auto' | 'gitbash' | 'pwsh'\n\n/** \u4E09\u6863\u5143\u6570\u636E\uFF08\u6570\u7EC4\u987A\u5E8F\u5373\u754C\u9762\u987A\u5E8F\uFF09\u3002 */\nexport const TERMINAL_MODES: readonly {\n readonly id: TerminalMode\n readonly label: string\n readonly hint: string\n}[] = [\n {\n id: 'auto',\n label: '\u81EA\u52A8',\n hint: '\u63A2\u6D4B\u5230 Git Bash \u5C31\u7528\u5B83\uFF08\u627E\u4E0D\u5230\u5219\u4FDD\u6301 PowerShell\uFF09\uFF1B\u5F00\u7BB1\u5373\u7528\uFF0C\u4E0D\u7528\u624B\u586B\u8DEF\u5F84',\n },\n {\n id: 'gitbash',\n label: 'Git Bash',\n hint: '\u5F3A\u5236\u6362\u6210 Git Bash\uFF1B\u6CA1\u63A2\u6D4B\u5230\u5C31\u56DE\u843D PowerShell\uFF0C\u5E76\u5728\u72B6\u6001\u884C\u5199\u660E\u539F\u56E0',\n },\n {\n id: 'pwsh',\n label: 'PowerShell',\n hint: '\u4FDD\u6301 DSH \u9ED8\u8BA4\uFF08\u672C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u78B0\u7EC8\u7AEF\u5DE5\u5177\u9762\uFF09',\n },\n]\n\n/** \u9ED8\u8BA4\u6863\u4F4D\uFF1A\u81EA\u52A8\uFF08\u96F6\u914D\u7F6E\u5373\u5F97\u6536\u76CA\uFF0C\u4E14\u627E\u4E0D\u5230 bash \u65F6\u4E0D\u4F1A\u628A\u73AF\u5883\u5F04\u574F\uFF09\u3002 */\nexport const DEFAULT_TERMINAL_MODE: TerminalMode = 'auto'\n\n/** \u843D\u76D8\u7684\u5019\u9009\u5F62\u72B6\uFF08\u6BD4\u63A2\u6D4B\u7ED3\u679C\u591A\u4E00\u70B9\uFF1Akind \u4E0E explicit \u4F9B\u754C\u9762\u6807\u6CE8\uFF09\u3002 */\nexport interface TerminalCandidate {\n readonly path: string\n readonly label: string\n readonly kind: BashKind\n readonly explicit: boolean\n}\n\n/** \u6536\u7A84\u6863\u4F4D\u3002 */\nexport function terminalModeFrom(value: unknown): TerminalMode {\n return value === 'auto' || value === 'gitbash' || value === 'pwsh' ? value : DEFAULT_TERMINAL_MODE\n}\n\n/** \u63A2\u6D4B\u7ED3\u679C \u2192 \u843D\u76D8\u5019\u9009\uFF08\u53BB\u6389\u8FD0\u884C\u671F\u624D\u77E5\u9053\u7684\u5B57\u6BB5\uFF09\u3002 */\nexport function candidatesToStored(candidates: readonly BashCandidate[]): readonly TerminalCandidate[] {\n return candidates.map(candidate => ({\n path: candidate.path,\n label: candidate.label,\n kind: candidate.kind,\n explicit: candidate.explicit,\n }))\n}\n\n/** \u6536\u7A84\u843D\u76D8\u5019\u9009\uFF08\u9632\u810F\u6570\u636E\uFF1B\u4E0A\u9650 20 \u6761\u591F\u7528\uFF09\u3002 */\nexport function sanitizeTerminalCandidates(value: unknown): readonly TerminalCandidate[] {\n if (!Array.isArray(value)) return []\n const out: TerminalCandidate[] = []\n const seen = new Set<string>()\n for (const item of value) {\n if (out.length >= 20) break\n if (typeof item !== 'object' || item === null) continue\n const row = item as Record<string, unknown>\n const path = typeof row.path === 'string' ? normalizePath(row.path).slice(0, 400) : ''\n if (path === '') continue\n const key = path.toLowerCase()\n if (seen.has(key)) continue\n seen.add(key)\n const label = typeof row.label === 'string' ? row.label.slice(0, 40) : ''\n const kind = row.kind === 'git' || row.kind === 'msys2' || row.kind === 'cygwin'\n || row.kind === 'niubash' || row.kind === 'path' ? row.kind : 'path'\n out.push({ path, label: label === '' ? 'PATH' : label, kind, explicit: row.explicit === true })\n }\n return out\n}\n\n/**\n * \u8FD9\u4E00\u8F6E\u5B9E\u9645\u8BE5\u7528\u54EA\u4E2A bash\u3002\n *\n * \u4E09\u6863\u7684\u5DEE\u522B\u53EA\u5728\u8FD9\u91CC\uFF0C\u522B\u5728\u8C03\u7528\u5904\u518D\u5224\u4E00\u6B21\uFF1A\n * - `pwsh`\uFF1A\u4E0D\u7528 bash\uFF08\u8FD4\u56DE\u7A7A\u4E32\uFF09\uFF1B\n * - `gitbash` / `auto`\uFF1A\u4F18\u5148\u7528\u6237\u586B\u7684\u8DEF\u5F84\uFF0C\u5176\u6B21\u5019\u9009\u8868\u7B2C\u4E00\u4E2A\uFF08\u63A2\u6D4B\u987A\u5E8F\u5DF2\u6392\u597D\uFF1A\n * \u663E\u5F0F \u2192 Git Bash \u2192 MSYS2/Cygwin \u2192 Niubash \u2192 PATH\uFF09\uFF1B\n * - \u4E24\u8005\u90FD\u4E0D\u8981\u6C42\"\u5FC5\u987B\u627E\u5230\"\uFF1A\u627E\u4E0D\u5230\u65F6\u8FD4\u56DE\u7A7A\u4E32\uFF0C\u7531\u8C03\u7528\u65B9\u56DE\u843D PowerShell\n * \uFF08`auto` \u9759\u9ED8\u56DE\u843D\uFF0C`gitbash` \u4F1A\u5728\u72B6\u6001\u884C\u91CC\u8BF4\u660E\u2014\u2014\u5DEE\u522B\u53EA\u662F\"\u8981\u4E0D\u8981\u89E3\u91CA\"\uFF09\u3002\n * @param mode \u5F53\u524D\u6863\u4F4D\u3002\n * @param bashPath \u7528\u6237\u586B\u7684\u8DEF\u5F84\uFF08\u53EF\u7A7A\uFF09\u3002\n * @param candidates \u5BBF\u4E3B\u534A\u4E0A\u6B21\u63A2\u6D4B\u5230\u7684\u5019\u9009\u3002\n * @returns \u53EF\u6267\u884C\u6587\u4EF6\u8DEF\u5F84\uFF1B\u7A7A\u4E32\u8868\u793A\u8FD9\u4E00\u8F6E\u4E0D\u7528 bash\u3002\n */\nexport function activeBashPath(\n mode: TerminalMode,\n bashPath: string,\n candidates: readonly TerminalCandidate[],\n explicitState?: ExplicitState,\n): string {\n if (mode === 'pwsh') return ''\n const explicit = normalizePath(bashPath)\n // \u663E\u5F0F\u8DEF\u5F84\u53EA\u6709\u5728\"\u786E\u5B9E\u5B58\u5728\"\uFF08\u6216\u8C03\u7528\u65B9\u5DF2\u7ECF\u9A8C\u8BC1\u8FC7\u3001\u6CA1\u7ED9\u72B6\u6001\uFF09\u65F6\u624D\u538B\u8FC7\u63A2\u6D4B\u7ED3\u679C\u3002\n if (explicit !== '' && (explicitState === undefined || explicitState.state === 'ok')) return explicit\n return defaultBashPath({ candidates, excluded: [] })\n}\n\n/** \u63A2\u6D4B\uFF08\u628A\u5199\u6B7B\u7684\u73AF\u5883\u8BFB\u53D6\u96C6\u4E2D\u5728\u8FD9\u91CC\uFF0C\u5176\u4F59\u903B\u8F91\u90FD\u5728\u7EAF\u51FD\u6570\u91CC\uFF09\u3002 */\nexport function probeBash(\n explicitPath: string,\n pathValue: string,\n env: (name: string) => string | undefined,\n exists: (path: string) => boolean,\n listDirs?: (parent: string) => readonly string[],\n): DiscoverResult {\n return discoverBashCandidates({\n exists,\n pathEntries: pathValue.split(';'),\n env,\n explicitPath,\n ...(listDirs === undefined ? {} : { listDirs }),\n })\n}\n\n/** \u72B6\u6001\u884C\u7684\u8F93\u5165\uFF08\u5BBF\u4E3B\u534A\u7B97\u597D\u8FD9\u4E9B\u4E8B\u5B9E\uFF0C\u6587\u6848\u672C\u8EAB\u662F\u7EAF\u51FD\u6570\uFF0C\u4FBF\u4E8E\u5355\u6D4B\uFF09\u3002 */\nexport interface StatusInput {\n /** `process.platform`\u3002 */\n readonly platform: string\n readonly mode: TerminalMode\n /** \u63A2\u6D4B\u5230\u7684\u5019\u9009\uFF08\u5DF2\u6392\u5E8F\uFF09\u3002 */\n readonly candidates: readonly TerminalCandidate[]\n /** \u88AB\u786C\u6392\u9664\u7684 WSL \u8DEF\u5F84\u6761\u6570\u3002 */\n readonly excludedCount: number\n /** \u7528\u6237\u663E\u5F0F\u586B\u7684\u8DEF\u5F84\u72B6\u6001\uFF08\u6CA1\u586B\u5219 undefined\uFF09\u3002 */\n readonly explicit?: ExplicitState\n /** \u8FD9\u4E00\u8F6E\u5B9E\u9645\u751F\u6548\u7684 shell\u3002 */\n readonly effective: 'bash' | 'pwsh' | 'unsupported'\n /** \u751F\u6548\u65F6\u7528\u7684\u5177\u4F53\u8DEF\u5F84\uFF08effective \u4E3A bash \u65F6\u7ED9\u51FA\uFF09\u3002 */\n readonly effectivePath?: string\n /** \u4E0B\u53D1\u5230 agent \u65F6\u9047\u5230\u7684\u5931\u8D25\u539F\u56E0\uFF08restrict/register \u5931\u8D25\uFF09\u3002 */\n readonly failure?: string\n /**\n * \u8FD9\u4E00\u8F6E**\u6CA1\u80FD\u771F\u7684\u6362\u4E0A**\uFF08\u4F8B\u5982 `tools.register` \u5931\u8D25\uFF0Crestrict \u5DF2\u56DE\u6EDA\uFF09\u3002\n *\n * \u7528\u6765\u628A\u90A3\u53E5\"\u5019\u9009\u4E0D\u53EF\u7528\"\u6362\u6210\u51C6\u786E\u8BF4\u6CD5\uFF1A\u5019\u9009\u662F\u6709\u7684\u3001bash \u4E5F\u5B58\u5728\uFF0C\u53EA\u662F\u6CA1\u88C5\u4E0A\u3002\n */\n readonly deliveryFailed?: boolean\n}\n\n/**\n * \u751F\u6210\u72B6\u6001\u884C\uFF08\u8BBE\u7F6E\u9875\u76F4\u63A5\u5C55\u793A\u8FD9\u53E5\u8BDD\uFF09\u3002\n *\n * \u539F\u5219\uFF1A**\u53EA\u8BF4\u4E8B\u5B9E\uFF0C\u4E0D\u7ED9\u5EFA\u8BAE**\u3002\u751F\u6548\u65F6\u7ED9\u51FA\u8DEF\u5F84\u4E0E\u6765\u6E90\uFF1B\u4E0D\u751F\u6548\u65F6\u89E3\u91CA\u4E3A\u4EC0\u4E48\n * \uFF08\u6CA1\u627E\u5230 / \u8DEF\u5F84\u4E0D\u5B58\u5728 / \u5E73\u53F0\u4E0D\u5BF9\uFF09\uFF0C\u5E76\u4E14\u660E\u786E\u8BF4\u51FA\"\u5DF2\u6392\u9664 WSL\"\u8FD9\u79CD\u6211\u4EEC\u4E3B\u52A8\u505A\u7684\u51B3\u5B9A\u3002\n * @param input \u4E8B\u5B9E\u3002\n * @returns \u4E00\u884C\u4E2D\u6587\u72B6\u6001\uFF08\u6700\u957F 400 \u5B57\u7B26\uFF0C\u4E0E schema \u4E0A\u9650\u4E00\u81F4\uFF09\u3002\n */\nexport function terminalStatusText(input: StatusInput): string {\n const text = (() => {\n if (input.platform !== 'win32') {\n return `\u672C\u63D2\u4EF6\u53EA\u5728 Windows \u4E0A\u63A5\u7BA1\u7EC8\u7AEF\uFF08\u5F53\u524D\u5E73\u53F0 ${input.platform}\uFF09\uFF0C\u6B64\u5904\u4E0D\u751F\u6548`\n }\n if (input.mode === 'pwsh') {\n return '\u4FDD\u6301 DSH \u9ED8\u8BA4\uFF08PowerShell\uFF09\u2014\u2014\u672C\u63D2\u4EF6\u4E0D\u4ECB\u5165\u7EC8\u7AEF\u5DE5\u5177\u9762'\n }\n if (input.effective === 'bash') {\n const path = input.effectivePath ?? ''\n const candidate = input.candidates.find(item => item.path === path)\n const suffix = input.explicit?.state === 'missing'\n ? `\uFF08\u4F60\u586B\u7684\u8DEF\u5F84\u4E0D\u5B58\u5728\uFF1A${input.explicit.path}\uFF09`\n : input.explicit?.state === 'wsl'\n ? `\uFF08\u4F60\u586B\u7684\u662F WSL \u7684 bash\uFF1A${input.explicit.path}\uFF09`\n : ''\n return `\u5DF2\u751F\u6548\uFF1A${path}${candidate === undefined ? '' : `\uFF08${candidate.label}\uFF09`}${suffix}`\n }\n if (input.candidates.length === 0) {\n const excluded = input.excludedCount > 0 ? `\uFF08\u5DF2\u6392\u9664 ${input.excludedCount} \u4E2A WSL \u7684 bash.exe\uFF09` : ''\n return `\u6CA1\u627E\u5230\u53EF\u7528\u7684 bash${excluded}\uFF0C\u6682\u65F6\u4FDD\u6301 PowerShell`\n }\n if (input.deliveryFailed === true) {\n return '\u627E\u5230\u4E86 bash \u4F46\u6CA1\u80FD\u6362\u4E0A\uFF08\u5DF2\u56DE\u6EDA\uFF0Cpwsh \u7167\u65E7\u53EF\u7528\uFF09\uFF0C\u6682\u65F6\u4FDD\u6301 PowerShell'\n }\n return `\u5019\u9009\u4E0D\u53EF\u7528\uFF0C\u6682\u65F6\u4FDD\u6301 PowerShell`\n })()\n const failure = input.failure === undefined || input.failure === '' ? '' : `\uFF1B\u4E0B\u53D1\u5931\u8D25\uFF1A${input.failure}`\n return `${text}${failure}`.slice(0, 400)\n}\n", "/**\n * dsh-composer-ux \u516C\u5171\u5951\u7EA6\uFF1A\u8BBE\u7F6E\u5B57\u6BB5\u3001\u9ED8\u8BA4\u503C\u3001\u5C55\u793A\u5143\u6570\u636E\u3002\n * \u672C\u6A21\u5757\u5FC5\u987B\u96F6 import\uFF08host \u4E0E client \u4E24\u534A\u5171\u7528\uFF0C\u8DE8\u7AEF\u4E0D\u5171\u4EAB\u4EFB\u4F55\u8FD0\u884C\u65F6\u8EAB\u4EFD\uFF09\u3002\n *\n * \u552F\u4E00\u7684\u4F8B\u5916\u662F `./terminal/` \u4E0B\u90A3\u51E0\u4E2A**\u7EAF\u51FD\u6570**\u6A21\u5757\uFF08\u96F6\u5916\u90E8\u4F9D\u8D56\u3001\u65E0 DOM\u3001\u65E0 node API\uFF09\uFF0C\n * \u300C\u9ED8\u8BA4\u7EC8\u7AEF\u300D\u7684\u5B57\u6BB5\u4E0E\u5224\u5B9A\u653E\u5728\u90A3\u91CC\uFF0C\u8FD9\u91CC\u53EA\u628A\u5B83\u4EEC\u5E76\u8FDB\u8BBE\u7F6E\u5951\u7EA6\u3002\n */\nimport {\n DEFAULT_TERMINAL_MODE, TERMINAL_BASH_PATH_FIELD, TERMINAL_CANDIDATES_FIELD,\n TERMINAL_EFFECTIVE_FIELD, TERMINAL_MODE_FIELD, TERMINAL_STATUS_FIELD,\n sanitizeTerminalCandidates, terminalModeFrom,\n type TerminalCandidate, type TerminalMode,\n} from './terminal/contracts.ts'\n\n/** Host settings namespace\uFF08\u5C0F\u5199\u5B57\u6BCD/\u6570\u5B57/\u8FDE\u5B57\u7B26\uFF09\u3002 */\nexport const NAMESPACE = 'composer-ux'\n\n/**\n * \u4ED3\u5E93\u5730\u5740\uFF1A\u8BBE\u7F6E\u9875\u62AC\u5934\u90A3\u4E2A\u300CGitHub \u2197\u300D\u94FE\u63A5\u7528\u5B83\u3002\n *\n * \u5FC5\u987B\u4E0E `package.json` \u7684 `repository.url` \u4E00\u81F4 \u2014\u2014 `test/client-registration.mjs`\n * \u6709\u4E00\u6761\u62A4\u680F\u76EF\u7740\u4E24\u5904\uFF0C\u514D\u5F97\u5404\u5199\u4E00\u4EFD\u7136\u540E\u6162\u6162\u5206\u53C9\uFF08\u5BA2\u6237\u7AEF\u4E5F\u4E0D\u8BB8\u786C\u7F16\u7801\u7B2C\u4E8C\u4EFD\u5730\u5740\uFF09\u3002\n */\nexport const REPO_URL = 'https://github.com/fangwen9527/dsh-composer-ux'\n\n// \u2500\u2500 \u300C\u91CD\u542F DSH\u300D\u6309\u94AE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// \u4E3A\u4EC0\u4E48\u8FD9\u4EF6\u4E8B\u5FC5\u987B\u843D\u5728\u5BBF\u4E3B\u534A\uFF1A\u53EA\u6709\u5BBF\u4E3B\u8FDB\u7A0B\u80FD\u628A\u81EA\u5DF1\u91CD\u65B0\u62C9\u8D77\u6765\uFF08\u6D4F\u89C8\u5668\u78B0\u4E0D\u5230\u8FDB\u7A0B\uFF09\u3002\n// \u673A\u5236\u7167\u642C\u63D2\u4EF6\u5E02\u573A\uFF08\u5206\u79BB\u4E00\u4E2A node \u52A9\u624B\u8FDB\u7A0B\u3001\u7B49\u7AEF\u53E3\u7A7A\u95F2\u3001\u7528\u9690\u85CF\u63A7\u5236\u53F0\u7684 PowerShell \u8D77\u65B0\u5BBF\u4E3B\uFF09\uFF0C\n// \u5168\u90E8\u7EC6\u8282\u5728 `src/restart.ts`\u3002\u8FD9\u91CC\u53EA\u6709\u4E24\u7AEF\u5171\u7528\u7684\u90A3\u4E00\u4E2A\u5E38\u91CF\u3002\n// 0.5.0 \u91CC\u90A3\u4E2A\u300C\u53EF\u9009\u91CD\u542F\u547D\u4EE4\u300D\u5B57\u6BB5\u5DF2\u53BB\u6389\uFF1A\u673A\u5236\u8DB3\u591F\u53EF\u9760\u4E4B\u540E\u5B83\u53EA\u5269\"\u591A\u4E00\u4E2A\u4F1A\u586B\u9519\u7684\u5730\u65B9\"\u3002\n\n/** \u91CD\u542F\u63A5\u53E3\u8DEF\u5F84\uFF08\u5BBF\u4E3B\u534A\u6CE8\u518C\uFF0C\u5BA2\u6237\u7AEF\u534A\u8C03\u7528\uFF09\u3002 */\nexport const RESTART_API_PATH = '/composer-ux/restart'\n\n/** \u5168\u5C40\u603B\u5F00\u5173\u5B57\u6BB5\u540D\u3002 */\nexport const ENABLED_FIELD = 'enabled'\n\n// \u2500\u2500 \u300C\u6BCF\u4E00\u680F\u4E00\u4E2A\u5F00\u5173\u300D \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// \u516D\u5F20\u6298\u53E0\u5361\u5404\u6709\u4E00\u4E2A\"\u8FD9\u4E00\u680F\u8981\u4E0D\u8981\u751F\u6548\"\u7684\u5F00\u5173\uFF0C**\u9ED8\u8BA4\u5173**\uFF1B\u603B\u5F00\u5173\uFF08`enabled`\uFF09\u9ED8\u8BA4\u5F00\uFF0C\n// \u5B83\u662F\u4E00\u9053\u603B\u95F8\uFF1A`enabled && \u8BE5\u680F\u5F00\u5173` \u624D\u751F\u6548\u3002\n//\n// \u4E3A\u4EC0\u4E48\u8981\u6709\"\u4ECE\u6CA1\u78B0\u8FC7\u7684\u680F\u624D\u9ED8\u8BA4\u5173\"\u8FD9\u6761\u8FC1\u79FB\u89C4\u5219\uFF08\u7528\u6237\u62CD\u677F A \u65B9\u6848\uFF09\uFF1A\u672C\u63D2\u4EF6\u5DF2\u7ECF\u53D1\u5E03\u8FC7\uFF0C\n// \u8001\u7528\u6237\u8BBE\u7F6E\u6587\u6863\u91CC\u5168\u662F\"\u6211\u6B63\u5728\u7528\"\u7684\u75D5\u8FF9\u3002\u82E5\u4E00\u5F8B\u9ED8\u8BA4\u5173\uFF0C\u5347\u7EA7\u90A3\u4E00\u523B\u4ED6\u7684\u952E\u4F4D\u5C31\u56DE\u5230 DSH \u539F\u751F\u3001\n// OpenCode \u8DEF\u7531\u76F4\u63A5 400\uFF08\u8BF7\u6C42\u5934\u4E0D\u518D\u6CE8\u5165\uFF09\u3001Git Bash \u6362\u56DE PowerShell \u2014\u2014 \u5168\u662F\u8981\u7528\u5230\u624D\u53D1\u73B0\u7684\u7834\u574F\u3002\n// \u6240\u4EE5\uFF1A**\u8FD9\u4E00\u680F\u7684\u503C\u4E0D\u7B49\u4E8E\"\u4ECE\u6CA1\u78B0\u8FC7\u7684\u6837\u5B50\" \u21D2 \u8BA4\u5B9A\u78B0\u8FC7 \u21D2 \u5F00**\uFF08\u5224\u636E\u89C1 `sectionEnabledOf`\uFF09\u3002\n// \u5168\u65B0\u5B89\u88C5\uFF08\u4EC0\u4E48\u75D5\u8FF9\u90FD\u6CA1\u6709\uFF09\u56E0\u6B64\u662F\u516D\u680F\u5168\u5173\u3002\u89C4\u5219\u7684\u5B9E\u73B0\u5728\u4E0B\u9762 `sectionEnabledOf`\u3002\n//\n// \u300COpenCode \u8BF7\u6C42\u5934\u300D\u90A3\u4E00\u680F**\u6CA1\u6709\u65B0\u952E**\uFF1A\u5B83\u539F\u6765\u7684 `headerEnabled`\uFF08\u9ED8\u8BA4 false\uFF09\u672C\u6765\u5C31\u662F\n// \"\u8FD9\u4E00\u680F\u8981\u4E0D\u8981\u751F\u6548\"\uFF0C\u76F4\u63A5\u642C\u5230\u6807\u9898\u884C\u5F53\u5361\u7EA7\u5F00\u5173\uFF0C\u4E0D\u518D\u9020\u4E00\u4E2A\u540C\u4E49\u7684\u952E\u3002\n\n/** \u300C\u952E\u4F4D\u300D\u680F\u5F00\u5173\u3002 */\nexport const KEYS_ENABLED_FIELD = 'keysEnabled'\n/** \u300C\u53F3\u952E\u83DC\u5355\u300D\u680F\u5F00\u5173\u3002 */\nexport const MENU_ENABLED_FIELD = 'menuEnabled'\n/** \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u680F\u5F00\u5173\u3002 */\nexport const QUICK_ENABLED_FIELD = 'quickEnabled'\n/** \u300C\u8BBE\u7F6E\u9762\u677F\u300D\u680F\u5F00\u5173\u3002 */\nexport const PANEL_ENABLED_FIELD = 'panelEnabled'\n/** \u300C\u9ED8\u8BA4\u7EC8\u7AEF\u300D\u680F\u5F00\u5173\u3002 */\nexport const TERMINAL_ENABLED_FIELD = 'terminalEnabled'\n\n/** \u952E\u4F4D\u5B57\u6BB5\u540D\u3002 */\nexport const SEND_KEY_FIELD = 'sendKey'\nexport const NEWLINE_KEY_FIELD = 'newlineKey'\n\n/**\n * \u8BBE\u7F6E\u9762\u677F\u5B57\u6BB5\u540D\u3002\n *\n * 0.6.0 \u8D77**\u6CA1\u6709** `panelScroll`\uFF1ADSH 0.1.7 \u7684\u5B98\u65B9\u8BBE\u7F6E\u9875\u7ED9\u5BFC\u822A\u5217\u81EA\u5E26\n * `overflow-y: auto`\uFF08`ui-settings-general` \u7684 `.navList`\uFF09\uFF0C\u6211\u4EEC\u90A3\u5957\n * `html.dsh-ux-panel-scroll` \u6CE8\u5165\u6837\u5F0F\u5DF2\u88AB\u5B98\u65B9\u53D6\u4EE3\uFF0C\u6545\u6574\u9879\u5220\u9664\u3002\n */\nexport const PANEL_RESIZE_FIELD = 'panelResize'\nexport const PANEL_WIDTH_FIELD = 'panelWidth'\nexport const PANEL_HEIGHT_FIELD = 'panelHeight'\n\n/** \u53F3\u952E\u83DC\u5355\u5F00\u5173\u5B57\u6BB5\u540D\u3002 */\nexport const MENU_FIELDS = [\n 'menuUndo',\n 'menuRedo',\n 'menuCut',\n 'menuCopy',\n 'menuPaste',\n 'menuDelete',\n 'menuSelectAll',\n] as const\n\nexport type MenuField = (typeof MENU_FIELDS)[number]\n\n/**\n * \u53F3\u952E\u83DC\u5355\u6A21\u5F0F\u5B57\u6BB5\u540D\uFF080.5.0 \u8D77\u4E09\u6863\uFF09\u3002\n *\n * 0.2.x\uFF5E0.4.0 \u7528\u7684\u662F\u5E03\u5C14 `menuNative`\uFF1Atrue = \u6D4F\u89C8\u5668\u539F\u751F\u83DC\u5355\u3001false = \u81EA\u5B9A\u4E49\u83DC\u5355\u3002\n * \u5E03\u5C14\u53EA\u6709\u4E24\u4F4D\uFF0C\u8868\u8FBE\u4E0D\u4E86\u300C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u4ECB\u5165\u300D\uFF08\u4E0D\u6321\u522B\u7684\u63D2\u4EF6\u7684\u83DC\u5355\uFF09\u8FD9\u4E00\u6863\uFF0C\u6240\u4EE5\u6362\u6210\n * \u5B57\u7B26\u4E32\u4E09\u6863\u3002\u65E7\u5B57\u6BB5**\u53EA\u4F5C\u4E3A\u8FC1\u79FB\u7EBF\u7D22\u4FDD\u7559**\uFF1A\u672C\u5B57\u6BB5\u4E3A\u7A7A\u65F6\u6309\u65E7\u5B57\u6BB5\u63A8\u65AD\uFF08\u89C1 `menuModeFrom`\uFF09\u3002\n */\nexport const MENU_MODE_FIELD = 'menuMode'\n\n/** 0.2.x\uFF5E0.4.0 \u7684\u65E7\u5B57\u6BB5\u540D\uFF1A\u8FC1\u79FB\u7EBF\u7D22\uFF0C0.5.0 \u8D77\u4E0D\u518D\u5199\u5B83\u3002 */\nexport const MENU_NATIVE_FIELD = 'menuNative'\n\n/** \u53F3\u952E\u83DC\u5355\u6A21\u5F0F\uFF1A\u5B98\u65B9\u4E0D\u4ECB\u5165 / \u6D4F\u89C8\u5668\u83DC\u5355 / \u81EA\u5B9A\u4E49\u83DC\u5355\u3002 */\nexport type MenuMode = 'official' | 'browser' | 'custom'\n\n/** \u4E09\u6863\u7684\u5143\u6570\u636E\uFF08\u6570\u7EC4\u987A\u5E8F\u5373\u754C\u9762\u987A\u5E8F\uFF09\u3002 */\nexport const MENU_MODES: readonly {\n readonly id: MenuMode\n readonly label: string\n readonly hint: string\n}[] = [\n {\n id: 'official',\n label: '\u5B98\u65B9',\n hint: '\u672C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u4ECB\u5165\uFF1ADSH \u4E0E\u5176\u5B83\u63D2\u4EF6\u81EA\u5DF1\u7684\u53F3\u952E\u5904\u7406\u539F\u6837\u751F\u6548\uFF08DSH \u5B98\u65B9\u8F93\u5165\u6846\u672C\u8EAB\u6CA1\u6709\u53F3\u952E\u83DC\u5355\uFF0C\u901A\u5E38\u770B\u5230\u7684\u5C31\u662F\u6D4F\u89C8\u5668\u7684\u83DC\u5355\uFF09',\n },\n {\n id: 'browser',\n label: '\u6D4F\u89C8\u5668',\n hint: '\u56FA\u5B9A\u4F7F\u7528\u6D4F\u89C8\u5668\u81EA\u5E26\u7684\u83DC\u5355\uFF0C\u5E76\u5728\u672C\u63D2\u4EF6\u8FD9\u4E00\u5C42\u6321\u4F4F\u5176\u5B83\u63D2\u4EF6\u7684\u83DC\u5355\uFF1B\u7C98\u8D34\u514D\u6388\u6743\u3001\u96F6\u914D\u7F6E',\n },\n {\n id: 'custom',\n label: '\u81EA\u5B9A\u4E49',\n hint: '\u4F7F\u7528\u672C\u63D2\u4EF6\u7684\u56FA\u5B9A\u6837\u5F0F\u83DC\u5355\uFF1B\u672A\u9009\u4E2D\u6587\u672C\u65F6\u300C\u526A\u5207 / \u590D\u5236 / \u5220\u9664\u300D\u7F6E\u7070\uFF0C\u7C98\u8D34\u9700\u8981\u6D4F\u89C8\u5668\u526A\u8D34\u677F\u6388\u6743',\n },\n]\n\n/**\n * \u5B9A\u51FA\u53F3\u952E\u83DC\u5355\u6A21\u5F0F\uFF1A\u65B0\u5B57\u6BB5\u4F18\u5148\uFF0C\u5176\u6B21\u6309\u65E7\u5E03\u5C14\u63A8\u65AD\uFF0C\u90FD\u6CA1\u6709\u5C31\u7528\u9ED8\u8BA4\u6863\u3002\n *\n * \u4E09\u79CD\u60C5\u51B5\u5224\u65AD\u5F97\u51FA\u6765\uFF0C\u662F\u56E0\u4E3A\u5BBF\u4E3B\u534A\u628A\u65E7\u5B57\u6BB5\u58F0\u660E\u6210**\u53EF\u9009**\uFF08\u6CA1\u6709 `.default(false)`\uFF09\uFF1A\n * \u300C\u4ECE\u6CA1\u78B0\u8FC7\u90A3\u4E2A\u5F00\u5173\u300D\u4E0E\u300C\u660E\u786E\u5173\u4E86\u5B83\u300D\u5728\u6587\u6863\u91CC\u957F\u5F97\u4E0D\u4E00\u6837\uFF08\u952E\u4E0D\u5B58\u5728 / \u952E\u4E3A false\uFF09\uFF0C\n * \u524D\u8005\u843D\u5230\u65B0\u9ED8\u8BA4\u6863\uFF08\u5B98\u65B9\u4E0D\u4ECB\u5165\uFF09\uFF0C\u540E\u8005\u4FDD\u6301\u539F\u6765\u7684\u81EA\u5B9A\u4E49\u83DC\u5355\u3002\n * @param storedMode - \u6587\u6863\u91CC\u7684\u65B0\u5B57\u6BB5\u503C\uFF08\u53EF\u80FD\u662F\u810F\u6570\u636E\uFF09\u3002\n * @param legacyNative - \u6587\u6863\u91CC\u7684\u65E7\u5E03\u5C14\u503C\uFF08\u53EF\u80FD\u4E0D\u5B58\u5728\uFF09\u3002\n * @returns \u4E09\u6863\u4E4B\u4E00\u3002\n */\nexport function menuModeFrom(storedMode: unknown, legacyNative: unknown): MenuMode {\n if (storedMode === 'official' || storedMode === 'browser' || storedMode === 'custom') return storedMode\n if (legacyNative === true) return 'browser'\n if (legacyNative === false) return 'custom'\n return DEFAULT_SETTINGS.menuMode\n}\n\n// \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\u4E0E\u63D0\u793A\u8BCD\u4F18\u5316 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** \u5FEB\u6377\u6307\u4EE4\u5217\u8868\u5B57\u6BB5\u540D\u3002 */\nexport const QUICK_PROMPTS_FIELD = 'quickPrompts'\n\n/** \u4F18\u5316\u5F3A\u5EA6\u6863\u4F4D\u5B57\u6BB5\u540D\u3002 */\nexport const OPTIMIZER_TIER_FIELD = 'optimizerTier'\n\n/** \u5355\u4E2A\u5206\u7C7B\u5185\u7684\u6761\u6570\u4E0A\u9650\u3002 */\nexport const QUICK_PROMPT_MAX = 60\n\n/** \u5206\u7C7B\u6570\u4E0A\u9650\u3002 */\nexport const QUICK_CATEGORY_MAX = 20\n\n/** \u5206\u7C7B\u540D\u7684\u5B57\u7B26\u4E0A\u9650\u3002 */\nexport const QUICK_CATEGORY_NAME_MAX = 40\n\n/** \u5355\u6761\u300C\u540D\u79F0\u300D\u7684\u5B57\u7B26\u4E0A\u9650\u3002 */\nexport const QUICK_LABEL_MAX = 40\n\n/**\n * \u5355\u6761\u300C\u63D0\u793A\u8BCD\u300D\u7684\u5B57\u7B26\u4E0A\u9650\u3002\n *\n * 0.3.0 \u8D77\u5FEB\u6377\u6307\u4EE4\u6539\u5B58 `$DSH_HOME/quick-prompts.json`\uFF0C\u4E0D\u518D\u53D7\u8BBE\u7F6E\u6587\u6863\u7684\u4F53\u79EF\u7EA6\u675F\uFF0C\n * \u6240\u4EE5\u8FD9\u91CC\u4ECE 4000 \u63D0\u5230 20 \u4E07\u2014\u2014\u53EA\u505A\u300C\u522B\u628A\u51E0\u767E MB \u585E\u8FDB\u6765\u300D\u7684\u9632\u5446\uFF0C\u6B63\u5E38\u63D0\u793A\u8BCD\u4E0D\u518D\u88AB\u622A\u65AD\u3002\n */\nexport const QUICK_TEXT_MAX = 200_000\n\n/**\n * \u9001\u53BB\u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\u7684\u539F\u6587\u4E0A\u9650\u3002\n *\n * \u4E0E\u539F `QUICK_TEXT_MAX * 2`\uFF08= 8000\uFF09\u7B49\u503C\uFF1A\u62AC\u9AD8\u7B49\u5FEB\u6377\u6307\u4EE4\u7684\u5B58\u50A8\u4E0A\u9650\u65F6**\u4E0D\u80FD**\n * \u987A\u5E26\u628A\u4F18\u5316\u8BF7\u6C42\u7684\u8F93\u5165\u4E0A\u9650\u4E5F\u62AC\u4E0A\u53BB\uFF0C\u5426\u5219\u8D85\u957F\u6587\u672C\u4F1A\u88AB\u4E22\u7ED9\u6A21\u578B\u3002\n */\nexport const OPTIMIZE_TEXT_MAX = 8_000\n\n/**\n * \u5FEB\u6377\u6307\u4EE4\u5B58\u50A8\u7684 HTTP \u8DEF\u5F84\uFF08\u5BBF\u4E3B\u534A\u6CE8\u518C\uFF0C\u5BA2\u6237\u7AEF\u534A\u8BFB\u5199\uFF09\u3002\n *\n * \u4E3A\u4EC0\u4E48\u5B58\u50A8\u4E5F\u5FC5\u987B\u8D70 HTTP\uFF1A\u6D4F\u89C8\u5668\u4FA7\u6CA1\u6709\u6587\u4EF6\u7CFB\u7EDF\uFF0C\u800C\u300C\u7528\u6237\u5185\u5BB9\u300D\u9700\u8981\u4E00\u4EFD\n * \u5168\u5C40\u3001\u4E0E\u4F1A\u8BDD/\u9879\u76EE\u65E0\u5173\u7684\u843D\u70B9\uFF0C\u53EA\u6709\u5BBF\u4E3B\u534A\u80FD\u63D0\u4F9B\u3002\n */\nexport const QUICK_PROMPTS_API_PATH = '/composer-ux/prompts'\n\n/** \u6587\u4EF6\u683C\u5F0F\u7248\u672C\uFF1B\u4E0E lnyuqian/dsh-quick-prompts \u7684 v2 \u5BF9\u9F50\uFF08\u89C1 bookToFile \u6CE8\u91CA\uFF09\u3002 */\nexport const QUICK_BOOK_VERSION = 2\n\n/** \u8FC1\u79FB/\u515C\u5E95\u5206\u7C7B\u540D\u3002 */\nexport const DEFAULT_CATEGORY_NAME = '\u9ED8\u8BA4'\n\n/** \u4F18\u5316\u7ED3\u679C\u957F\u5EA6\u4E0A\u9650\uFF08\u8D85\u8FC7\u89C6\u4E3A\u5F02\u5E38\u4EA7\u51FA\uFF0C\u622A\u65AD\u5E76\u63D0\u793A\uFF09\u3002 */\nexport const OPTIMIZE_OUTPUT_MAX = 12000\n\n/**\n * \u5BBF\u4E3B\u534A\u4E3A\u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\u6CE8\u518C\u7684 HTTP \u63A5\u53E3\u8DEF\u5F84\u3002\n *\n * \u4E3A\u4EC0\u4E48\u5FC5\u987B\u8D70 HTTP\uFF1A\u51FA\u7F51\u8BF7\u6C42\u7531\u5BBF\u4E3B\u7684\u6A21\u578B\u9002\u914D\u5668\u53D1\u51FA\uFF08\u6D4F\u89C8\u5668\u4FA7\u78B0\u4E0D\u5230\u6A21\u578B\u8DEF\u7531\uFF09\uFF0C\n * \u800C\u5BBF\u4E3B\u534A <-> \u5BA2\u6237\u7AEF\u534A\u4E4B\u95F4\u6CA1\u6709\u522B\u7684\u53D7\u652F\u6301\u901A\u9053 \u2014\u2014 \u4E0E\n * WestFox-AwA/dsh-prompt-optimizer \u7684\u505A\u6CD5\u4E00\u81F4\u3002\n */\nexport const OPTIMIZER_API_PATH = '/composer-ux/optimize'\n\n/**\n * \u4E00\u6761\u5FEB\u6377\u6307\u4EE4\u3002\n *\n * `always` \u5C31\u662F\u754C\u9762\u4E0A\u7684\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\uFF1A\u52FE\u4E0A\u4E4B\u540E\uFF0C\u70B9\u53D1\u9001\u65F6\u8FD9\u6761\u63D0\u793A\u8BCD\u4F1A\u88AB\n * \u81EA\u52A8\u62FC\u5230\u6D88\u606F**\u672B\u5C3E**\u4E00\u8D77\u53D1\u51FA\u53BB\uFF08\u8F93\u5165\u6846\u91CC\u4E0D\u63D0\u524D\u663E\u793A\uFF09\uFF0C\u89C1\n * `client/quick-commands.ts` \u7684 `appendAlwaysPrompts()`\u3002\n */\nexport interface QuickPrompt {\n /** \u7A33\u5B9A id\uFF1A\u7F16\u8F91\u540D\u79F0/\u5185\u5BB9\u65F6\u4E0D\u53D8\uFF0C\u7528\u4E8E\u52FE\u9009\u72B6\u6001\u4E0E\u5217\u8868 diff\u3002 */\n readonly id: string\n /** \u6309\u94AE\u4E0A\u663E\u793A\u7684\u540D\u79F0\u3002 */\n readonly label: string\n /** \u70B9\u51FB\u540E\u63D2\u5165\u8F93\u5165\u6846\u7684\u63D0\u793A\u8BCD\u6B63\u6587\u3002 */\n readonly prompt: string\n /** \u300C\u6BCF\u6B21\u300D\uFF1A\u6BCF\u6B21\u53D1\u9001\u90FD\u81EA\u52A8\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E\u3002\u4E0E `firstOnly` \u4E92\u65A5\u3002 */\n readonly always: boolean\n /**\n * \u300C\u4EC5\u9996\u6B21\u300D\uFF1A\u53EA\u5728**\u8FD9\u4E2A\u4F1A\u8BDD\u7684\u7B2C\u4E00\u6761\u6D88\u606F**\u4E0A\u9644\u52A0\u3002\n *\n * \u5224\u636E\u662F\u4F1A\u8BDD\u5FEB\u7167\u7684 `blank`\uFF08\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u4EFB\u4F55\u6D88\u606F\uFF09\u2014\u2014\u53D1\u5B8C\u7B2C\u4E00\u6761\u5B83\u81EA\u5DF1\u5C31\u53D8\u6210 false\uFF0C\n * \u6240\u4EE5\u4E0D\u9700\u8981\u6211\u4EEC\u81EA\u5DF1\u8BB0\u300C\u8FD9\u6B21\u4F1A\u8BDD\u9644\u52A0\u8FC7\u6CA1\u6709\u300D\uFF0C\u5237\u65B0\u9875\u9762\u4E5F\u4E0D\u4F1A\u91CD\u590D\u9644\u52A0\u3002\n * \u4E0E `always` \u4E92\u65A5\uFF08\u754C\u9762\u4E0A\u662F\u4E09\u9009\u4E00\uFF09\u3002\n */\n readonly firstOnly: boolean\n}\n\n/** \u63D2\u5165\u6A21\u5F0F\uFF1A\u754C\u9762\u4E0A\u90A3\u6761\u4E09\u9009\u4E00\u3002 */\nexport type InsertMode = 'never' | 'always' | 'first'\n\n/** \u4E09\u9009\u4E00\u7684\u5143\u6570\u636E\uFF08\u6570\u7EC4\u987A\u5E8F\u5373\u754C\u9762\u987A\u5E8F\uFF09\u3002 */\nexport const INSERT_MODES: readonly {\n readonly id: InsertMode\n readonly label: string\n readonly hint: string\n}[] = [\n { id: 'never', label: '\u5173', hint: '\u70B9\u6761\u76EE\u53EA\u63D2\u5165\u8F93\u5165\u6846\uFF0C\u53D1\u9001\u65F6\u4E0D\u9644\u52A0' },\n { id: 'always', label: '\u6BCF\u6B21', hint: '\u6BCF\u6B21\u53D1\u9001\u90FD\u628A\u8FD9\u6761\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E' },\n { id: 'first', label: '\u4EC5\u9996\u6B21', hint: '\u53EA\u5728\u5F53\u524D\u4F1A\u8BDD\u7684\u7B2C\u4E00\u6761\u6D88\u606F\u4E0A\u9644\u52A0' },\n]\n\n/**\n * \u8BFB\u4E00\u6761\u7684\u63D2\u5165\u6A21\u5F0F\u3002\n *\n * \u4E24\u4E2A\u6807\u5FD7\u90FD\u662F true \u65F6\u6309\u300C\u6BCF\u6B21\u300D\u5904\u7406\uFF08\u624B\u5DE5\u7F16\u8F91\u7684\u6587\u4EF6\u53EF\u80FD\u5199\u6210\u8FD9\u6837\uFF1B\u300C\u6BCF\u6B21\u300D\u672C\u6765\u5C31\n * \u5305\u542B\u7B2C\u4E00\u6B21\uFF09\uFF0C\u5E76\u4E14\u4E0B\u4E00\u6B21\u5199\u76D8\u4F1A\u628A\u4E92\u65A5\u6027\u4FEE\u6B63\u56DE\u6765\u3002\n */\nexport function insertModeOf(prompt: Pick<QuickPrompt, 'always' | 'firstOnly'>): InsertMode {\n if (prompt.always) return 'always'\n if (prompt.firstOnly) return 'first'\n return 'never'\n}\n\n/**\n * \u4F18\u5316\u5F3A\u5EA6\u6863\u4F4D\u3002\n *\n * \u63D0\u793A\u8BCD\u521D\u7248\u9010\u5B57\u63D0\u53D6\u81EA WestFox-AwA/dsh-prompt-optimizer\uFF08BSD-3-Clause\uFF0C\u4F5C\u8005\u300C\u5543\u8F6E\u80CE\u7684\u897F\u72D0\u300D\uFF09\uFF1B\n * 0.6.0 \u8D77\u6309\u5BF9\u65B9 **0.6 \u7EBF**\uFF08`po06/lib/interpreter.js`\uFF09\u7684\u673A\u5236\u91CD\u5199\uFF1A\u6A21\u578B\u4E0D\u518D\u81EA\u7531\u6539\u5199\uFF0C\n * \u800C\u662F\u4EA7\u51FA\u300C\u53EF\u5B9A\u4F4D\u5230\u539F\u8BDD\u67D0\u4E00\u6BB5\u300D\u7684\u6761\u76EE\uFF0C\u7531\u5BBF\u4E3B\u9010\u6761\u505A\u5B57\u9762\u6BD4\u5BF9\u540E\u518D\u88C5\u914D\u6210\u4E00\u6761\u547D\u4EE4\u3002\n * \u6863\u4F4D\u8BED\u4E49\u4E5F\u968F\u4E4B\u5BF9\u9F50\u5BF9\u65B9\u300C\u6863\u4F4D = \u4F9D\u636E\u9884\u7B97\u300D\u7684\u8BF4\u6CD5\uFF08\u89C1 `optimizer-prompt.ts`\uFF09\u3002\n */\nexport type OptimizerTier = 'basic' | 'advanced' | 'extreme'\n\n/** \u6863\u4F4D\u5143\u6570\u636E\uFF08\u987A\u5E8F\u5373\u754C\u9762\u987A\u5E8F\uFF09\u3002 */\nexport const OPTIMIZER_TIERS: readonly {\n readonly id: OptimizerTier\n readonly label: string\n readonly hint: string\n}[] = [\n { id: 'basic', label: '\u666E\u901A', hint: '\u53EA\u505A\u8BED\u8A00\u5C42\u4FEE\u590D\uFF1A\u75C5\u53E5\u3001\u9519\u522B\u5B57\u3001\u6307\u4EE3\u4E0E\u542B\u7CCA\u8BCD\uFF0C\u4E0D\u65B0\u589E\u4EFB\u4F55\u9700\u6C42\uFF0C\u7BC7\u5E45\u7EA6\u4E3A\u539F\u6587 1.4 \u500D\u3002' },\n { id: 'advanced', label: '\u9AD8\u7EA7', hint: '\u5728\u4E0D\u52A8\u76EE\u6807\u7684\u524D\u63D0\u4E0B\uFF0C\u628A\u300C\u4F60\u663E\u7136\u60F3\u8981\u3001\u4F46\u6CA1\u8BF4\u51FA\u53E3\u300D\u7684\u5FC5\u8981\u8981\u6C42\u8865\u6210\u5BF9 AI \u7684\u8981\u6C42\uFF0C\u6BCF\u6761\u90FD\u8981\u6307\u56DE\u4F60\u539F\u8BDD\u91CC\u7684\u67D0\u4E00\u53E5\u3002' },\n { id: 'extreme', label: '\u6781\u7AEF', hint: '\u6309\u590D\u6742\u4EFB\u52A1\u5904\u7406\uFF1A\u5728\u4E0A\u9762\u57FA\u7840\u4E0A\u518D\u52A0\u5206\u9636\u6BB5\u6267\u884C\u8BA1\u5212\u4E0E 2~4 \u79CD\u60C5\u51B5\u7684\u9884\u6848\u3002' },\n]\n\n/** \u9ED8\u8BA4\u6863\u4F4D\u3002 */\nexport const DEFAULT_OPTIMIZER_TIER: OptimizerTier = 'advanced'\n\n/**\n * \u6BCF\u4E2A\u6863\u4F4D\u7684\u300C\u81EA\u5B9A\u4E49\u7CFB\u7EDF\u63D0\u793A\u8BCD\u300D\u5B57\u6BB5\u540D\u3002\n *\n * \u4E3A\u4EC0\u4E48\u662F\u4E09\u4E2A\u5E73\u94FA\u5B57\u7B26\u4E32\u800C\u4E0D\u662F\u4E00\u4E2A\u5BF9\u8C61\uFF1A\u4E0E\u672C\u63D2\u4EF6\u5176\u5B83\u53EF\u7F16\u8F91\u9879\u4E00\u81F4\uFF08\u8BBE\u7F6E\u9875\u6309\u5B57\u6BB5\u540D\u8BFB\u5199\u3001\n * \u5BBF\u4E3B\u534A\u7684 schema \u4E5F\u662F\u5E73\u94FA key\uFF09\uFF0C\u4E14**\u7559\u7A7A = \u7528\u5185\u7F6E\u90A3\u4EFD**\u8FD9\u4E2A\u8BED\u4E49\u7528\u7A7A\u4E32\u8868\u8FBE\u6700\u76F4\u63A5 \u2014\u2014\n * \u4E0D\u9700\u8981\u989D\u5916\u4E00\u4E2A\"\u662F\u5426\u81EA\u5B9A\u4E49\"\u7684\u5E03\u5C14\uFF08\u591A\u4E00\u4E2A\u5E03\u5C14\u5C31\u591A\u4E00\u79CD\u81EA\u76F8\u77DB\u76FE\u7684\u72B6\u6001\uFF09\u3002\n */\nexport const OPTIMIZER_PROMPT_FIELDS = {\n basic: 'optimizerPromptBasic',\n advanced: 'optimizerPromptAdvanced',\n extreme: 'optimizerPromptExtreme',\n} as const\n\n/** \u5168\u90E8\u6863\u4F4D\u7684\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u5B57\u6BB5\u540D\uFF08\u987A\u5E8F\u5373\u6863\u4F4D\u987A\u5E8F\uFF09\u3002 */\nexport const OPTIMIZER_PROMPT_FIELD_LIST: readonly string[] =\n OPTIMIZER_TIERS.map(item => OPTIMIZER_PROMPT_FIELDS[item.id])\n\n/**\n * \u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u7684\u5B57\u6570\u4E0A\u9650\u3002\n *\n * \u4E0E `QUICK_TEXT_MAX` \u4E0D\u540C\uFF1A\u8FD9\u91CC\u5B58\u7684\u662F**\u6A21\u578B\u6307\u4EE4**\u800C\u4E0D\u662F\u7528\u6237\u5185\u5BB9\uFF0C\u5185\u7F6E\u90A3\u4E09\u4EFD\u90FD\u5728 3\u20135 KB\uFF0C\n * \u7ED9 2 \u4E07\u5B57\u7B26\u8DB3\u591F\u5BB9\u7EB3\u7528\u6237\u7684\u6539\u5199\uFF0C\u53C8\u80FD\u6321\u4F4F\"\u628A\u8BBE\u7F6E\u6587\u6863\u6491\u6210\u4E00\u672C\u4E66\"\u3002\n */\nexport const OPTIMIZER_PROMPT_MAX = 20_000\n\n/**\n * \u6309\u6863\u4F4D\u53D6\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u7684\u5B57\u6BB5\u540D\u3002\n * @param tier - \u6863\u4F4D id\uFF1B\u672A\u77E5\u503C\u56DE\u843D\u5230\u9ED8\u8BA4\u6863\uFF08\u4E0E `buildOptimizeSystem` \u540C\u4E00\u53E3\u5F84\uFF09\u3002\n * @returns \u8BE5\u6863\u4F4D\u5BF9\u5E94\u7684\u8BBE\u7F6E\u5B57\u6BB5\u540D\u3002\n */\nexport function optimizerPromptFieldOf(tier: string): string {\n return OPTIMIZER_PROMPT_FIELDS[tier as OptimizerTier] ?? OPTIMIZER_PROMPT_FIELDS[DEFAULT_OPTIMIZER_TIER]\n}\n\n/**\n * \u5185\u7F6E\u7684 9 \u6761\u5FEB\u6377\u6307\u4EE4 = \u7528\u6237\u53E3\u8FF0\u7684 4 \u6761 + \u63D0\u53D6\u81EA congyaqwq/dsh-quick-prompts \u7684 5 \u6761\u3002\n *\n * \u8BF4\u660E\uFF08\u5982\u5B9E\u8BB0\u5F55\u8C03\u7814\u7ED3\u679C\uFF09\uFF1A\u53E6\u5916\u4E24\u4E2A\u540C\u540D\u63D2\u4EF6 lcsdg / lnyuqian \u7684\n * dsh-quick-prompts **\u4E0D\u5E26\u5185\u7F6E\u6307\u4EE4**\uFF08\u5217\u8868\u9ED8\u8BA4\u662F\u7A7A\u7684\uFF0C\u9760\u7528\u6237\u81EA\u5EFA\uFF09\uFF0C\n * \u6240\u4EE5\u4ECE\u5B83\u4EEC\u90A3\u91CC\u6CA1\u6709\u53EF\u63D0\u53D6\u7684\u6761\u76EE\u3002\n */\nexport const DEFAULT_QUICK_PROMPTS: readonly QuickPrompt[] = [\n { id: 'builtin-1', label: '\u4E00\u95EE\u4E00\u7B54', prompt: '\u4F60\u4E0D\u61C2\u7684\u5C31\u95EE\u6211\uFF0C\u4E00\u95EE\u4E00\u7B54\uFF1B\u540C\u65F6\u8BF4\u6E05\u695A\u4F60\u4E3A\u4EC0\u4E48\u8981\u95EE\u8BE5\u95EE\u9898\uFF1B\u76F4\u5230\u4F60\u5BF9\u6211\u7684\u76EE\u6807\u6709\u660E\u786E\u8BA4\u77E5\u540E\u518D\u5F00\u59CB\u5E72\u6D3B\u3002', always: false, firstOnly: false },\n { id: 'builtin-2', label: '\u4EA4\u63A5\u6587\u6863', prompt: '\u628A\u8FD9\u6B21\u4EFB\u52A1\u3001\u5DF2\u5B8C\u6210\u5185\u5BB9\u3001\u5F53\u524D\u5361\u70B9\u3001\u4E0B\u4E00\u6B65\u8BA1\u5212\u3001\u8E29\u8FC7\u7684\u5751\uFF0C\u6574\u7406\u6210\u4E00\u4EFD\u4EA4\u63A5\u6587\u6863\uFF0C\u5199\u7ED9\u65B0\u4F1A\u8BDD\u770B\u3002', always: false, firstOnly: false },\n { id: 'builtin-3', label: '\u4EC5\u8BF4\u660E\u539F\u56E0', prompt: '\u4EC5\u8BF4\u660E\u539F\u56E0\uFF0C\u4E0D\u8981\u505A\u5176\u4ED6\u52A8\u4F5C\u3002', always: false, firstOnly: false },\n { id: 'builtin-4', label: '\u5206\u6790\u540E\u76F4\u63A5\u5E72', prompt: '\u5206\u6790\u539F\u56E0\uFF0C\u7136\u540E\u76F4\u63A5\u5F00\u59CB\u5E72\u6D3B\uFF0C\u4E0D\u9700\u8981\u8FC7\u95EE\u6211\u3002', always: false, firstOnly: false },\n { id: 'builtin-5', label: '\u63D0\u4EA4\u4EE3\u7801', prompt: '\u8BF7\u5E2E\u6211\u63D0\u4EA4\u4EE3\u7801\uFF1A\u68C0\u67E5\u5F53\u524D git \u53D8\u66F4\uFF0C\u751F\u6210\u89C4\u8303\u7684 commit message \u5E76\u6267\u884C\u63D0\u4EA4\u3002', always: false, firstOnly: false },\n { id: 'builtin-6', label: '\u7ED9\u65B9\u6848', prompt: '\u8BF7\u9488\u5BF9\u4E0A\u9762\u7684\u95EE\u9898\u7ED9\u51FA\u4E00\u4E2A\u5B8C\u6574\u65B9\u6848\uFF0C\u5305\u62EC\u601D\u8DEF\u3001\u6B65\u9AA4\u3001\u6CE8\u610F\u4E8B\u9879\u548C\u98CE\u9669\u3002', always: false, firstOnly: false },\n { id: 'builtin-7', label: '\u89E3\u91CA\u4EE3\u7801', prompt: '\u8BF7\u89E3\u91CA\u8FD9\u6BB5\u4EE3\u7801\u7684\u4F5C\u7528\u548C\u5B9E\u73B0\u601D\u8DEF\u3002', always: false, firstOnly: false },\n { id: 'builtin-8', label: '\u5199\u6D4B\u8BD5', prompt: '\u8BF7\u4E3A\u4E0B\u9762\u7684\u4EE3\u7801\u7F16\u5199\u5355\u5143\u6D4B\u8BD5\u3002', always: false, firstOnly: false },\n { id: 'builtin-9', label: '\u4EE3\u7801\u5BA1\u67E5', prompt: '\u8BF7\u5BF9\u4E0B\u9762\u7684\u4EE3\u7801\u8FDB\u884C\u4EE3\u7801\u5BA1\u67E5\uFF0C\u6307\u51FA\u95EE\u9898\u5E76\u7ED9\u51FA\u6539\u8FDB\u5EFA\u8BAE\u3002', always: false, firstOnly: false },\n]\n\n/** \u751F\u6210\u4E00\u6761\u65B0\u5FEB\u6377\u6307\u4EE4\u7684 id\uFF08\u65F6\u95F4\u6233 + \u968F\u673A\u540E\u7F00\uFF0C\u907F\u514D\u4E0E\u65E2\u6709 id \u78B0\u649E\uFF09\u3002 */\nexport function newQuickPromptId(): string {\n return `qp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`\n}\n\n// \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\uFF1A\u5206\u7C7B\u7ED3\u6784\u4E0E\u6587\u4EF6\u6620\u5C04 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// 0.3.0 \u8D77\u5FEB\u6377\u6307\u4EE4\u4E0D\u518D\u5B58\u5728\u8BBE\u7F6E\u6587\u6863\u91CC\uFF0C\u800C\u662F\u5B58\u5728 `$DSH_HOME/quick-prompts.json`\u3002\n// \u539F\u56E0\u662F\u8BBE\u7F6E\u6587\u6863\u5BF9**\u6570\u7EC4**\u662F\u300C\u6574\u4EFD\u66FF\u6362\u300D\u3001\u4E14\u53D7 schema \u957F\u5EA6\u4E0A\u9650\u7EA6\u675F\uFF08\u65E7 4000 \u5B57\u4F1A\u9759\u9ED8\n// \u622A\u65AD\uFF09\uFF0C\u800C\u5FEB\u6377\u6307\u4EE4\u662F\u7528\u6237\u5185\u5BB9\u3001\u4F1A\u5199\u5F88\u957F\u7684\u63D0\u793A\u8BCD\u3002\u4E13\u7528\u6587\u4EF6\u8FD8\u4FBF\u4E8E\u5355\u72EC\u5907\u4EFD\u4E0E\u8FC1\u79FB\u3002\n//\n// \u6587\u4EF6\u5B57\u6BB5\u540D\u4E0E lnyuqian/dsh-quick-prompts \u5BF9\u9F50\uFF08categories / name / title / text /\n// autoSend / order\uFF09\uFF0C\u8FD9\u6837\u540C\u4E00\u4E2A\u6587\u4EF6\u4E24\u8FB9\u90FD\u8BFB\u5F97\u61C2\uFF1A\u5185\u90E8\u7528 label/prompt/always\uFF0C\n// \u53EA\u5728\u6587\u4EF6\u8FB9\u754C\u6620\u5C04\uFF08\u89C1 bookToFile / asPromptRow\uFF09\u3002\n// \u26A0\uFE0F \u4F46**\u4E0D\u8981\u540C\u65F6\u88C5\u4E24\u4E2A\u63D2\u4EF6**\u2014\u2014\u540C\u4E00\u4E2A\u6587\u4EF6\u4E24\u4E2A\u5199\u8005\u4F1A\u4E92\u76F8\u8986\u76D6\uFF0C\u800C\u5B83\u90A3\u8FB9\u662F\u975E\u539F\u5B50\u5199\u3002\n\n/** \u751F\u6210\u4E00\u4E2A\u65B0\u5206\u7C7B id\u3002 */\nexport function newQuickCategoryId(): string {\n return `qc-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`\n}\n\n/** \u4E00\u4E2A\u5206\u7C7B\uFF1A\u540D\u5B57 + \u5B83\u81EA\u5DF1\u7684\u6761\u76EE\u5217\u8868\uFF08\u987A\u5E8F\u5373\u663E\u793A\u987A\u5E8F\uFF09\u3002 */\nexport interface QuickPromptCategory {\n readonly id: string\n readonly name: string\n readonly prompts: readonly QuickPrompt[]\n}\n\n/** \u5168\u5C40\u5FEB\u6377\u6307\u4EE4\u672C\uFF1A\u5206\u7C7B\u4E24\u7EA7\u7ED3\u6784\uFF0C\u843D\u76D8\u6210\u4E00\u4EFD JSON \u6587\u4EF6\u3002 */\nexport interface QuickPromptBook {\n readonly version: number\n readonly categories: readonly QuickPromptCategory[]\n}\n\n/** \u5185\u7F6E\u9ED8\u8BA4\u672C\uFF1A\u4E00\u4E2A\u300C\u9ED8\u8BA4\u300D\u5206\u7C7B\u88C5\u90A3 9 \u6761\u3002 */\nexport function defaultQuickBook(): QuickPromptBook {\n return {\n version: QUICK_BOOK_VERSION,\n categories: [{ id: 'cat-default', name: DEFAULT_CATEGORY_NAME, prompts: DEFAULT_QUICK_PROMPTS }],\n }\n}\n\n/** \u6587\u4EF6\u91CC\u7684\u5206\u7C7B\u5F62\u72B6\uFF08\u5199\u76D8\u7528\uFF1B\u4E0E\u53C2\u8003\u5B9E\u73B0\u540C\u540D\u5B57\u6BB5\uFF09\u3002 */\nexport interface QuickCategoryFileRow {\n readonly id: string\n readonly name: string\n readonly prompts: readonly {\n readonly id: string\n readonly title: string\n readonly text: string\n readonly autoSend: boolean\n /** \u300C\u4EC5\u9996\u6B21\u300D\u6807\u5FD7\uFF08\u6211\u4EEC\u7684\u6269\u5C55\u952E\uFF1B\u53C2\u8003\u5B9E\u73B0\u4F1A\u5FFD\u7565\u5B83\uFF0C\u5199\u56DE\u65F6\u53EF\u80FD\u4E22\u6389\uFF09\u3002 */\n readonly autoSendFirst?: boolean\n readonly order: number\n }[]\n}\n\n/** \u6536\u7A84\u4E00\u6761\uFF1A\u5185\u90E8\u5B57\u6BB5\u540D\uFF08label/prompt/always\uFF09\u4E0E\u6587\u4EF6\u5B57\u6BB5\u540D\uFF08title/text/autoSend\uFF09\u90FD\u8BA4\u3002 */\nfunction asPromptRow(value: unknown): { readonly prompt: QuickPrompt; readonly order?: number } | undefined {\n if (typeof value !== 'object' || value === null) return undefined\n const row = value as Record<string, unknown>\n const either = (first: unknown, second: unknown): string => {\n const picked = typeof first === 'string' && first !== '' ? first : second\n return typeof picked === 'string' ? picked : ''\n }\n const prompt = either(row.prompt, row.text).slice(0, QUICK_TEXT_MAX).trim()\n if (prompt === '') return undefined\n const label = either(row.label, row.title).slice(0, QUICK_LABEL_MAX).trim()\n const id = typeof row.id === 'string' && row.id !== '' ? row.id.slice(0, 64) : newQuickPromptId()\n const order = typeof row.order === 'number' && Number.isFinite(row.order)\n ? Math.max(1, Math.round(row.order))\n : undefined\n return {\n prompt: {\n id,\n label: label === '' ? prompt.slice(0, 12) : label,\n prompt,\n always: row.always === true || row.autoSend === true,\n firstOnly: row.firstOnly === true || row.autoSendFirst === true,\n },\n order,\n }\n}\n\n/** \u6536\u7A84\u4E00\u4E2A\u5217\u8868\uFF1A\u6309 id \u53BB\u91CD\u4FDD\u5E8F\u3001\u6309 order \u5347\u5E8F\uFF08\u6CA1\u6709 order \u7684\u4FDD\u6301\u539F\u76F8\u5BF9\u4F4D\u7F6E\uFF09\u3001\u9650\u91CF\u3002 */\nfunction toPromptList(values: readonly unknown[]): readonly QuickPrompt[] {\n const rows: { prompt: QuickPrompt; order?: number; index: number }[] = []\n for (const value of values) {\n const row = asPromptRow(value)\n if (row !== undefined) rows.push({ ...row, index: rows.length })\n }\n rows.sort((a, b) => {\n const left = a.order ?? Number.MAX_SAFE_INTEGER\n const right = b.order ?? Number.MAX_SAFE_INTEGER\n return left === right ? a.index - b.index : left - right\n })\n const seen = new Set<string>()\n const out: QuickPrompt[] = []\n for (const row of rows) {\n if (out.length >= QUICK_PROMPT_MAX) break\n if (seen.has(row.prompt.id)) continue\n seen.add(row.prompt.id)\n out.push(row.prompt)\n }\n return out\n}\n\n/**\n * \u628A\u4EFB\u610F\u6765\u6E90\u6536\u7A84\u6210\u4E00\u672C\uFF08\u6587\u4EF6\u5185\u5BB9\u3001HTTP \u8BF7\u6C42\u4F53\u90FD\u8D70\u8FD9\u91CC\uFF09\u3002\n * @param value \u4EFB\u610F\u503C\u3002\n * @returns \u6536\u7A84\u540E\u7684\u672C\uFF1B**\u8BA4\u4E0D\u51FA\u7684\u5F62\u72B6\u8FD4\u56DE undefined** \u2014\u2014 \u8C03\u7528\u65B9\u5FC5\u987B\u628A\u5B83\u5F53\u6210\u635F\u574F\uFF0C\n * \u7EDD\u4E0D\u80FD\u56DE\u9000\u6210\u7A7A\u672C\u518D\u5199\u56DE\u53BB\uFF08\u90A3\u4F1A\u628A\u7528\u6237\u6570\u636E\u62B9\u6389\uFF09\u3002\n */\nexport function sanitizeBook(value: unknown): QuickPromptBook | undefined {\n if (typeof value !== 'object' || value === null) return undefined\n const source = value as Record<string, unknown>\n\n // v1 \u5E73\u94FA\uFF08\u88F8\u6570\u7EC4\uFF0C\u6216 { prompts: [...] }\uFF09\uFF1A\u5347\u7EA7\u6210\u4E00\u4E2A\u300C\u9ED8\u8BA4\u300D\u5206\u7C7B\u3002\n const flat = Array.isArray(value) ? value : (Array.isArray(source.prompts) ? source.prompts : undefined)\n if (flat !== undefined) {\n const prompts = toPromptList(flat)\n return {\n version: QUICK_BOOK_VERSION,\n categories: prompts.length === 0\n ? []\n : [{ id: 'cat-default', name: DEFAULT_CATEGORY_NAME, prompts }],\n }\n }\n\n if (!Array.isArray(source.categories)) return undefined\n const seen = new Set<string>()\n const categories: QuickPromptCategory[] = []\n for (const raw of source.categories) {\n if (categories.length >= QUICK_CATEGORY_MAX) break\n if (typeof raw !== 'object' || raw === null) continue\n const row = raw as Record<string, unknown>\n const prompts = toPromptList(Array.isArray(row.prompts) ? row.prompts : [])\n // \u7A7A\u5206\u7C7B**\u4FDD\u7559**\uFF08\u8FD9\u70B9\u4E0E\u53C2\u8003\u5B9E\u73B0\u4E0D\u540C\uFF09\uFF1A\u9762\u677F\u7684\u300C\uFF0B\u300D\u53EA\u662F\u65B0\u5EFA\u4E00\u4E2A\u5206\u7C7B\uFF0C\u7528\u6237\u63A5\u4E0B\u6765\n // \u624D\u4F1A\u5F80\u91CC\u653E\u6761\u76EE\uFF1B\u82E5\u5728\u8FD9\u91CC\u4E22\u6389\uFF0C\u70B9\u300C\uFF0B\u300D\u5C31\u4F1A\u770B\u8D77\u6765\u6BEB\u65E0\u53CD\u5E94\uFF080.3.0 \u771F\u673A\u4E0A\u8E29\u5230\uFF09\u3002\n // \u7A7A\u5206\u7C7B\u5728\u6587\u4EF6\u91CC\u4E5F\u662F\u5408\u6CD5\u72B6\u6001\uFF0C\u6570\u91CF\u4E0A\u9650\u7531 QUICK_CATEGORY_MAX \u515C\u4F4F\u3002\n const wanted = typeof row.id === 'string' && row.id !== '' ? row.id.slice(0, 64) : newQuickCategoryId()\n const id = seen.has(wanted) ? newQuickCategoryId() : wanted\n seen.add(id)\n const name = (typeof row.name === 'string' ? row.name : '').slice(0, QUICK_CATEGORY_NAME_MAX).trim()\n categories.push({ id, name: name === '' ? DEFAULT_CATEGORY_NAME : name, prompts })\n }\n return { version: QUICK_BOOK_VERSION, categories }\n}\n\n/** \u5185\u90E8\u7ED3\u6784 \u2192 \u6587\u4EF6\u7ED3\u6784\uFF08\u5199\u76D8\u65F6\u7528\uFF1B\u987A\u5E8F\u5373 order\uFF09\u3002 */\nexport function bookToFile(book: QuickPromptBook): { version: number; categories: readonly QuickCategoryFileRow[] } {\n return {\n version: QUICK_BOOK_VERSION,\n categories: book.categories.map(category => ({\n id: category.id,\n name: category.name,\n prompts: category.prompts.map((prompt, index) => ({\n id: prompt.id,\n title: prompt.label,\n text: prompt.prompt,\n autoSend: prompt.always,\n // \u300C\u4EC5\u9996\u6B21\u300D\u662F\u6211\u4EEC\u52A0\u7684\u952E\uFF0C\u53EA\u5728\u4E3A\u771F\u65F6\u5199\u51FA\u6765\uFF1A\u6587\u4EF6\u5F62\u72B6\u5C3D\u91CF\u8D34\u8FD1\u53C2\u8003\u5B9E\u73B0\u3002\n ...(prompt.firstOnly ? { autoSendFirst: true } : {}),\n order: index + 1,\n })),\n })),\n }\n}\n\n/** \u8DE8\u5206\u7C7B\u62CD\u5E73\uFF08\u9762\u677F\u5217\u8868\u3001\u603B\u6761\u6570\u7EDF\u8BA1\u7528\uFF09\u3002 */\nexport function flattenQuickPrompts(book: QuickPromptBook): readonly QuickPrompt[] {\n return book.categories.flatMap(category => category.prompts)\n}\n\n/** \u53EA\u53D6\u300C\u6BCF\u6B21\u300D\u7684\u90A3\u4E9B\uFF08\u6BCF\u6B21\u53D1\u9001\u90FD\u9644\u52A0\uFF1B\u8DE8\u6240\u6709\u5206\u7C7B\uFF09\u3002 */\nexport function alwaysQuickPrompts(book: QuickPromptBook): readonly QuickPrompt[] {\n return flattenQuickPrompts(book).filter(prompt => insertModeOf(prompt) === 'always')\n}\n\n/** \u53EA\u53D6\u300C\u4EC5\u9996\u6B21\u300D\u7684\u90A3\u4E9B\uFF08\u8DE8\u6240\u6709\u5206\u7C7B\uFF09\u3002 */\nexport function firstOnlyQuickPrompts(book: QuickPromptBook): readonly QuickPrompt[] {\n return flattenQuickPrompts(book).filter(prompt => insertModeOf(prompt) === 'first')\n}\n\n/**\n * \u8FD9\u4E00\u6B21\u53D1\u9001\u8981\u9644\u52A0\u7684\u6279\u6B21\u3002\n *\n * @param book \u5F53\u524D\u8FD9\u672C\u3002\n * @param blank \u4F1A\u8BDD\u5FEB\u7167\u7684 `blank`\uFF1Atrue = \u8FD9\u4E2A\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u4EFB\u4F55\u6D88\u606F\uFF08\u4E5F\u5C31\u662F\u7B2C\u4E00\u6761\uFF09\u3002\n * @returns \u987A\u5E8F = \u300C\u6BCF\u6B21\u300D\u7684\u90A3\u4E9B\uFF0C\u518D\u8DDF\u4E0A\u300C\u4EC5\u9996\u6B21\u300D\u7684\u90A3\u4E9B\uFF08\u4EC5\u9996\u6B21\u53EA\u5728\u7B2C\u4E00\u6761\u4E0A\u51FA\u73B0\uFF09\u3002\n */\nexport function appendBatchForSend(book: QuickPromptBook, blank: boolean): readonly QuickPrompt[] {\n const every = alwaysQuickPrompts(book)\n if (!blank) return every\n return [...every, ...firstOnlyQuickPrompts(book)]\n}\n\n// \u2500\u2500 OpenCode \u8BF7\u6C42\u5934 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// OpenCode \u7684\u63A5\u53E3\u8981\u6C42\u5BA2\u6237\u7AEF\u6BCF\u6B21\u8BF7\u6C42\u90FD\u5E26\u4E00\u4E2A\u7A33\u5B9A\u7684\u4F1A\u8BDD ID \u8BF7\u6C42\u5934\n// \uFF08\u5B98\u65B9 Go \u6587\u6863\u300C\u53EF\u4EE5\u5728\u54EA\u91CC\u4F7F\u7528\uFF1F\u300D\u7B2C 3 \u6761\uFF09\u3002DSH \u7684 Models \u8BBE\u7F6E\u9875\u660E\u786E\u4E0D\u63D0\u4F9B\n// \u8BF7\u6C42\u5934\u7F16\u8F91\u5668\uFF0C\u6240\u4EE5\u672C\u63D2\u4EF6\u628A\u8FD9\u4E00\u9879\u5199\u8FDB llm-pi-ai \u7684 provider profile.headers \u2014\u2014\n// \u90A3\u662F DSH \u91CC\u552F\u4E00\u53D7\u652F\u6301\u7684\u51FA\u7F51\u8BF7\u6C42\u5934\u5165\u53E3\uFF08\u4F1A\u5728 pi-ai \u4FA7\u6700\u540E\u5408\u5E76\uFF0C\u4E0B\u4E00\u6B21\u8BF7\u6C42\u751F\u6548\uFF09\u3002\n\n/** \u8BF7\u6C42\u5934\u680F\u76EE\u5B57\u6BB5\u540D\u3002 */\nexport const HEADER_ENABLED_FIELD = 'headerEnabled'\nexport const HEADER_NAME_FIELD = 'headerName'\nexport const HEADER_VALUE_FIELD = 'headerValue'\n/** \u4F5C\u7528\u8DEF\u7531\u540D\u5355\uFF08\u9017\u53F7/\u7A7A\u683C\u5206\u9694\uFF09\uFF1B\u7559\u7A7A = \u81EA\u52A8\u5339\u914D OpenCode \u8DEF\u7531\uFF08\u89C1 OPENCODE_ROUTE_PREFIX / OPENCODE_HOSTS\uFF09\u3002 */\nexport const HEADER_ROUTES_FIELD = 'headerRoutes'\n\n/** \u5BBF\u4E3B\u534A\u8BB0\u8D26\uFF1A\u4E0A\u6B21\u5B9E\u9645\u5199\u5165\u7684\u5934\u540D\u4E0E\u503C\uFF08\u51B3\u5B9A\u505C\u7528/\u6539\u540D\u65F6\u64A4\u9500\u54EA\u4E9B\u952E\uFF09\u3002 */\nexport const HEADER_APPLIED_NAME_FIELD = 'headerAppliedName'\nexport const HEADER_APPLIED_VALUE_FIELD = 'headerAppliedValue'\n\n/** \u5BBF\u4E3B\u534A\u5199\u5165\u7684\u6267\u884C\u7ED3\u679C\uFF1B\u8BBE\u7F6E\u9875\u53EA\u8BFB\u5C55\u793A\u3002 */\nexport const HEADER_STATUS_FIELD = 'headerStatus'\n\n/**\n * \u53EA\u5728\u5BBF\u4E3B\u534A\u7EF4\u62A4\u7684\u5B57\u6BB5\uFF1A\u8BBE\u7F6E\u9875\u300C\u6062\u590D\u9ED8\u8BA4\u300D\u4E0D\u5F97\u6E05\u7A7A\u5B83\u4EEC\uFF0C\n * \u5426\u5219\u5DF2\u5199\u5165\u7684\u5934\u4F1A\u5931\u53BB\u8BB0\u8D26\u3001\u6C38\u8FDC\u64A4\u9500\u4E0D\u6389\u3002\n *\n * \u300C\u9ED8\u8BA4\u7EC8\u7AEF\u300D\u7684\u4E09\u4E2A\u81EA\u6301\u5B57\u6BB5\u540C\u7406\uFF1A\u5019\u9009\u8868\u4E0E\u72B6\u6001\u662F**\u5BBF\u4E3B\u534A\u7684\u63A2\u6D4B\u7ED3\u679C**\uFF0C\n * \u6E05\u6389\u4E4B\u540E\u754C\u9762\u4F1A\u53D8\u6210\"\u6CA1\u63A2\u6D4B\u8FC7\"\u7684\u6837\u5B50\uFF08\u800C\u5B9E\u9645\u8FD8\u5728\u7528\u67D0\u4E2A bash\uFF09\uFF0C\n * \u7528\u6237\u70B9\u4E00\u6B21\u300C\u6062\u590D\u9ED8\u8BA4\u300D\u5C31\u4F1A\u770B\u5230\u81EA\u76F8\u77DB\u76FE\u7684\u72B6\u6001\u3002\n */\nexport const HOST_OWNED_FIELDS = [\n HEADER_APPLIED_NAME_FIELD,\n HEADER_APPLIED_VALUE_FIELD,\n HEADER_STATUS_FIELD,\n TERMINAL_CANDIDATES_FIELD,\n TERMINAL_STATUS_FIELD,\n TERMINAL_EFFECTIVE_FIELD,\n] as const\n\n/** \u8BF7\u6C42\u5934\u6700\u7EC8\u843D\u5730\u7684\u8BBE\u7F6E\u547D\u540D\u7A7A\u95F4\uFF08\u7531 llm-pi-ai \u6CE8\u518C\uFF09\u3002 */\nexport const LLM_NAMESPACE = 'llm-pi-ai'\n\n/**\n * \u81EA\u52A8\u5339\u914D\u7684\u4E24\u6761\u5224\u636E\uFF08\u6EE1\u8DB3\u5176\u4E00\u5373\u7B97 OpenCode \u8DEF\u7531\uFF09\uFF1A\n * 1. \u8DEF\u7531\u540D\u4EE5 `opencode` \u5F00\u5934\u2014\u2014DSH \u5185\u7F6E\u7684 `opencode-go` \u5C31\u5C5E\u4E8E\u8FD9\u79CD\uFF0C\n * \u5B83\u7684 baseURL \u7531 pi-ai \u76EE\u5F55\u5185\u7F6E\uFF0C\u914D\u7F6E\u91CC\u8BFB\u4E0D\u5230\uFF0C\u53EA\u80FD\u9760\u540D\u5B57\u3002\n * 2. \u8BE5\u8DEF\u7531\u7684 `baseURL` \u4E3B\u673A\u662F opencode.ai\uFF08\u542B\u5B50\u57DF\uFF09\u2014\u2014\u7528\u6237\u81EA\u5EFA\u8DEF\u7531\u5E38\u8D77\u4EFB\u610F\u540D\u5B57\n * \uFF08\u4F8B\u5982 `go`\uFF09\uFF0C\u4F46\u7AEF\u70B9\u7167\u6837\u662F OpenCode\uFF0C\u6309 URL \u8BA4\u6BD4\u6309\u540D\u5B57\u8BA4\u53EF\u9760\u3002\n */\nexport const OPENCODE_ROUTE_PREFIX = 'opencode'\n\n/** \u5224\u636E 2 \u7528\u7684\u4E3B\u673A\u540D\uFF08\u542B\u5B50\u57DF\uFF09\u3002 */\nexport const OPENCODE_HOSTS = ['opencode.ai'] as const\n\n/** \u5934\u540D\u9ED8\u8BA4\u503C = OpenCode \u5B98\u65B9\u8981\u6C42\u7684\u90A3\u4E00\u4E2A\u3002 */\nexport const DEFAULT_HEADER_NAME = 'x-opencode-session'\n\n/** \u5934\u503C\u957F\u5EA6\u4E0A\u9650\uFF08HTTP \u5934\u4E0E\u8BBE\u7F6E\u6587\u6863\u90FD\u4E0D\u5B9C\u8FC7\u957F\uFF09\u3002 */\nexport const HEADER_VALUE_MAX = 200\n\n/** \u5934\u540D\u957F\u5EA6\u4E0A\u9650\u3002 */\nexport const HEADER_NAME_MAX = 64\n\n/** \u5168\u90E8\u53EF\u6301\u4E45\u5316\u5B57\u6BB5\u3002 */\nexport type SettingsField =\n | typeof ENABLED_FIELD\n | typeof KEYS_ENABLED_FIELD\n | typeof MENU_ENABLED_FIELD\n | typeof QUICK_ENABLED_FIELD\n | typeof PANEL_ENABLED_FIELD\n | typeof TERMINAL_ENABLED_FIELD\n | typeof SEND_KEY_FIELD\n | typeof NEWLINE_KEY_FIELD\n | typeof PANEL_RESIZE_FIELD\n | typeof PANEL_WIDTH_FIELD\n | typeof PANEL_HEIGHT_FIELD\n | typeof MENU_NATIVE_FIELD\n | typeof MENU_MODE_FIELD\n | typeof HEADER_ENABLED_FIELD\n | typeof HEADER_NAME_FIELD\n | typeof HEADER_VALUE_FIELD\n | typeof HEADER_ROUTES_FIELD\n | typeof QUICK_PROMPTS_FIELD\n | typeof OPTIMIZER_TIER_FIELD\n | typeof OPTIMIZER_PROMPT_FIELDS.basic\n | typeof OPTIMIZER_PROMPT_FIELDS.advanced\n | typeof OPTIMIZER_PROMPT_FIELDS.extreme\n | typeof TERMINAL_MODE_FIELD\n | typeof TERMINAL_BASH_PATH_FIELD\n | MenuField\n\n/** \u9F20\u6807\u53F3\u952E\u83DC\u5355\u6253\u5F00\u65F6\u7684\u4E00\u6B21\u5FEB\u7167\uFF08\u542B\u4F4D\u7F6E\u4E0E\u9009\u62E9\u72B6\u6001\uFF09\u3002 */\nexport interface MenuState {\n /** \u89C6\u53E3\u5750\u6807\u3002 */\n readonly x: number\n readonly y: number\n /** \u53F3\u952E\u65F6\u8F93\u5165\u6846\u5185\u662F\u5426\u6709\u975E\u6298\u53E0\u9009\u533A\uFF08\u51B3\u5B9A\u526A\u5207/\u590D\u5236/\u5220\u9664\u662F\u5426\u53EF\u7528\uFF09\u3002 */\n readonly hasSelection: boolean\n /** \u7C98\u8D34\u5931\u8D25\u65F6\u7684\u77ED\u6682\u63D0\u793A\u3002 */\n readonly note?: string\n}\n\n/** \u89E3\u6790\u540E\u7684\u8BBE\u7F6E\u3002 */\nexport interface ComposerUxSettings {\n /** \u5168\u5C40\u603B\u5F00\u5173\uFF1Afalse \u65F6\u672C\u63D2\u4EF6\u6240\u6709\u529F\u80FD\u505C\u7528\u3002\u9ED8\u8BA4**\u5F00**\u3002 */\n enabled: boolean\n /**\n * \u516D\u680F\u5404\u81EA\u7684\u5F00\u5173\uFF1A`enabled && \u8BE5\u680F\u5F00\u5173` \u624D\u751F\u6548\u3002\u9ED8\u8BA4**\u5173**\uFF08\u8001\u7528\u6237\u6309\"\u78B0\u8FC7\u6CA1\"\u8FC1\u79FB\uFF0C\u89C1\n * `sectionEnabledOf`\uFF09\u3002\u300COpenCode \u8BF7\u6C42\u5934\u300D\u90A3\u4E00\u680F\u76F4\u63A5\u7528 `headerEnabled`\uFF0C\u6CA1\u6709\u5355\u72EC\u7684\u952E\u3002\n */\n keysEnabled: boolean\n menuEnabled: boolean\n quickEnabled: boolean\n panelEnabled: boolean\n terminalEnabled: boolean\n /** \u53D1\u9001\u952E\u4F4D\u89C4\u8303\u4E32\uFF08\u5982 'Enter'\u3001'Ctrl+Enter'\u3001''=\u65E0\uFF09\u3002 */\n sendKey: string\n /** \u6362\u884C\u952E\u4F4D\u89C4\u8303\u4E32\u3002 */\n newlineKey: string\n menuUndo: boolean\n menuRedo: boolean\n menuCut: boolean\n menuCopy: boolean\n menuPaste: boolean\n menuDelete: boolean\n menuSelectAll: boolean\n /**\n * \u53F3\u952E\u83DC\u5355\u6A21\u5F0F\uFF08\u5B98\u65B9\u4E0D\u4ECB\u5165 / \u6D4F\u89C8\u5668\u83DC\u5355 / \u81EA\u5B9A\u4E49\u83DC\u5355\uFF09\u3002\n * \u6587\u6863\u91CC\u6CA1\u6709\u8FD9\u4E2A\u5B57\u6BB5\u65F6\u6309\u65E7\u5E03\u5C14 `menuNative` \u63A8\u65AD\uFF0C\u89C1 `menuModeFrom`\u3002\n */\n menuMode: MenuMode\n /** \u8BBE\u7F6E\u9762\u677F\uFF1A\u5141\u8BB8\u62D6\u62FD\u8FB9\u7F18\u8C03\u6574\u5927\u5C0F\u3002 */\n panelResize: boolean\n /** \u8BBE\u7F6E\u9762\u677F\u5BBD\uFF08px\uFF09\uFF1B\u7F3A\u7701\u4F7F\u7528\u5B98\u65B9\u9ED8\u8BA4 800\u3002 */\n panelWidth?: number\n /** \u8BBE\u7F6E\u9762\u677F\u9AD8\uFF08px\uFF09\uFF1B\u7F3A\u7701\u4F7F\u7528\u5B98\u65B9\u9ED8\u8BA4 min(800, \u89C6\u53E3-48)\u3002 */\n panelHeight?: number\n /** OpenCode \u8BF7\u6C42\u5934\uFF1A\u542F\u7528\u540E\u5199\u8FDB llm-pi-ai \u7684 opencode \u7CFB\u8DEF\u7531\u3002 */\n headerEnabled: boolean\n /** \u5934\u540D\uFF08\u9ED8\u8BA4 x-opencode-session\uFF09\u3002 */\n headerName: string\n /** \u5934\u503C\uFF1B\u7559\u7A7A\u65F6\u9996\u6B21\u542F\u7528\u7531\u5BBF\u4E3B\u534A\u751F\u6210\u4E00\u4E2A\u7A33\u5B9A ID \u5E76\u843D\u76D8\u6CBF\u7528\u3002 */\n headerValue: string\n /** \u4F5C\u7528\u8DEF\u7531\u540D\u5355\uFF1B\u7559\u7A7A = \u81EA\u52A8\u5339\u914D opencode \u7CFB\u8DEF\u7531\uFF08\u53EA\u52A8\u5DF2\u5B58\u5728\u7684\u8DEF\u7531\uFF09\u3002 */\n headerRoutes: string\n /** \u5BBF\u4E3B\u534A\u8BB0\u8D26\u5B57\u6BB5\uFF08\u8BBE\u7F6E\u9875\u53EA\u8BFB\uFF09\u3002 */\n headerAppliedName: string\n headerAppliedValue: string\n /** \u5BBF\u4E3B\u534A\u5199\u5165\u7ED3\u679C\uFF08\u8BBE\u7F6E\u9875\u53EA\u8BFB\uFF09\u3002 */\n headerStatus: string\n /** \u5FEB\u6377\u6307\u4EE4\u5217\u8868\uFF08\u987A\u5E8F\u5373\u9762\u677F\u4E0E\u8BBE\u7F6E\u9875\u91CC\u7684\u663E\u793A\u987A\u5E8F\uFF09\u3002 */\n quickPrompts: readonly QuickPrompt[]\n /** \u63D0\u793A\u8BCD\u4F18\u5316\u5F3A\u5EA6\u6863\u4F4D\u3002 */\n optimizerTier: OptimizerTier\n /**\n * \u4E09\u6863\u7684**\u81EA\u5B9A\u4E49**\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF1B\u7559\u7A7A = \u7528 `optimizer-prompt.ts` \u91CC\u7684\u5185\u7F6E\u90A3\u4EFD\u3002\n *\n * \u6539\u7684\u662F\u300C\u4EFB\u52A1\u4E0E\u98CE\u683C\u300D\u90A3\u4E00\u6BB5\uFF1BJSON \u8F93\u51FA\u5951\u7EA6\u7531\u63D2\u4EF6\u5728\u672B\u5C3E\u8FFD\u52A0\u3001\u4E0D\u7531\u8FD9\u91CC\u63A7\u5236\n * \uFF08\u5B83\u7684\u4F5C\u7528\u662F\u8BA9\u5BBF\u4E3B\u80FD\u6309\u9010\u5B57\u4F9D\u636E\u6821\u9A8C\u6BCF\u4E00\u6761\uFF0C\u88AB\u6539\u6389\u6574\u4E2A\u673A\u5236\u5C31\u5931\u6548\u4E86\uFF09\u3002\n */\n optimizerPromptBasic: string\n optimizerPromptAdvanced: string\n optimizerPromptExtreme: string\n /**\n * \u300C\u9ED8\u8BA4\u7EC8\u7AEF\u300D\u6863\u4F4D\uFF1A\u81EA\u52A8 / Git Bash / PowerShell\u3002\u53EA\u5BF9 Windows \u751F\u6548\n * \uFF08\u975E Windows \u4E0A\u5BBF\u4E3B\u534A\u76F4\u63A5\u8DF3\u8FC7\uFF0C\u5361\u7247\u663E\u793A\"\u4E0D\u9700\u8981\"\uFF09\u3002\n */\n terminalMode: TerminalMode\n /** \u7528\u6237\u6307\u5B9A\u7684 Git Bash \u8DEF\u5F84\uFF1B\u7559\u7A7A = \u7528\u63A2\u6D4B\u5230\u7684\u7B2C\u4E00\u4E2A\u5019\u9009\u3002 */\n terminalBashPath: string\n /** \u5BBF\u4E3B\u534A\u63A2\u6D4B\u5230\u7684\u5019\u9009\uFF08\u53EA\u8BFB\u5C55\u793A\uFF0C\u89C1 HOST_OWNED_FIELDS\uFF09\u3002 */\n terminalCandidates: readonly TerminalCandidate[]\n /** \u5BBF\u4E3B\u534A\u5199\u7684\u72B6\u6001\u884C\uFF1A\u5F53\u524D\u751F\u6548 shell / \u4E3A\u4EC0\u4E48\u6CA1\u751F\u6548\uFF08\u53EA\u8BFB\u5C55\u793A\uFF09\u3002 */\n terminalStatus: string\n /** \u5BBF\u4E3B\u534A\u5199\u7684\u5F53\u524D\u751F\u6548 shell\uFF1A'bash' / 'pwsh'\uFF08\u53EA\u8BFB\u5C55\u793A\uFF09\u3002 */\n terminalEffective: string\n}\n\n/** \u9ED8\u8BA4\u503C = DSH Web \u73B0\u72B6\uFF08Enter \u53D1\u9001\u3001Shift+Enter \u6362\u884C\u3001\u53F3\u952E\u83DC\u5355\u5168\u5F00\uFF09\u3002 */\nexport const DEFAULT_SETTINGS: ComposerUxSettings = {\n // \u603B\u5F00\u5173\u9ED8\u8BA4\u5F00\uFF1A\u5B83\u53EA\u662F\u603B\u95F8\uFF0C\u771F\u6B63\"\u8981\u4E0D\u8981\u7528\u8FD9\u4E00\u680F\"\u7531\u4E0B\u9762\u4E94\u4E2A\u5F00\u5173\u51B3\u5B9A\uFF08\u9ED8\u8BA4\u5173\uFF09\u3002\n enabled: true,\n // \u4E94\u680F\u9ED8\u8BA4\u5173\uFF08\u8001\u6587\u6863\u7531 sectionEnabledOf \u8FC1\u79FB\u6210\"\u78B0\u8FC7\u5C31\u5F00\"\uFF09\u3002\n keysEnabled: false,\n menuEnabled: false,\n quickEnabled: false,\n panelEnabled: false,\n terminalEnabled: false,\n sendKey: 'Enter',\n newlineKey: 'Shift+Enter',\n menuUndo: true,\n menuRedo: true,\n menuCut: true,\n menuCopy: true,\n menuPaste: true,\n menuDelete: true,\n menuSelectAll: true,\n menuMode: 'official',\n panelResize: true,\n headerEnabled: false,\n headerName: DEFAULT_HEADER_NAME,\n headerValue: '',\n headerRoutes: '',\n headerAppliedName: '',\n headerAppliedValue: '',\n headerStatus: '',\n quickPrompts: DEFAULT_QUICK_PROMPTS,\n optimizerTier: DEFAULT_OPTIMIZER_TIER,\n // \u7A7A\u4E32 = \u7528\u5185\u7F6E\u63D0\u793A\u8BCD\u3002\u9ED8\u8BA4\u5FC5\u987B\u662F\u7A7A\u4E32\uFF1A\u5B83\u540C\u65F6\u5C31\u662F\u300C\u6062\u590D\u5185\u7F6E\u300D\u8981\u5199\u56DE\u53BB\u7684\u503C\u3002\n optimizerPromptBasic: '',\n optimizerPromptAdvanced: '',\n optimizerPromptExtreme: '',\n terminalMode: DEFAULT_TERMINAL_MODE,\n terminalBashPath: '',\n terminalCandidates: [],\n terminalStatus: '',\n terminalEffective: '',\n}\n\n/**\n * \u516D\u680F\u91CC\u54EA\u51E0\u680F\u751F\u6548\uFF1A**\u603B\u5F00\u5173 +\uFF08OpenCode \u90A3\u680F\u7528\u81EA\u5DF1\u7684 `headerEnabled`\uFF09+ \u8BE5\u680F\u5F00\u5173**\u3002\n *\n * \u5BBF\u4E3B\u534A\u4E0E\u5BA2\u6237\u7AEF\u534A\u90FD\u8D70\u8FD9\u4E00\u4E2A\u51FD\u6570\uFF0C\u514D\u5F97\u6709\u4EBA\u53EA\u770B\u4E86\u680F\u5F00\u5173\u3001\u5FD8\u4E86\u603B\u95F8\uFF08\u6216\u8005\u53CD\u8FC7\u6765\uFF09\u3002\n */\nexport function activeSections(settings: ComposerUxSettings): {\n readonly keys: boolean\n readonly menu: boolean\n readonly quick: boolean\n readonly panel: boolean\n readonly header: boolean\n readonly terminal: boolean\n} {\n const on = settings.enabled\n return {\n keys: on && settings.keysEnabled,\n menu: on && settings.menuEnabled,\n quick: on && settings.quickEnabled,\n panel: on && settings.panelEnabled,\n header: on && settings.headerEnabled,\n terminal: on && settings.terminalEnabled,\n }\n}\n\n/** \u8BBE\u7F6E\u9875\u300C\u952E\u4F4D\u300D\u4E00\u8282\u7684\u9884\u8BBE\u3002 */\nexport const SEND_PRESETS: readonly string[] = ['Enter', 'Ctrl+Enter', 'Alt+Enter', 'Shift+Enter']\nexport const NEWLINE_PRESETS: readonly string[] = ['Shift+Enter', 'Enter', 'Ctrl+Enter', 'Alt+Enter']\n\n/** \u53F3\u952E\u83DC\u5355\u6761\u76EE\uFF08\u987A\u5E8F\u5373\u663E\u793A\u987A\u5E8F\uFF1Bshortcut \u4E0E\u56FE\u7247\u4E00\u81F4\uFF09\u3002 */\nexport const MENU_ITEMS: readonly {\n readonly field: MenuField\n readonly label: string\n readonly shortcut: string\n}[] = [\n { field: 'menuUndo', label: '\u64A4\u9500', shortcut: 'Ctrl+Z' },\n { field: 'menuRedo', label: '\u91CD\u505A', shortcut: 'Ctrl+Y' },\n { field: 'menuCut', label: '\u526A\u5207', shortcut: 'Ctrl+X' },\n { field: 'menuCopy', label: '\u590D\u5236', shortcut: 'Ctrl+C' },\n { field: 'menuPaste', label: '\u7C98\u8D34', shortcut: 'Ctrl+V' },\n { field: 'menuDelete', label: '\u5220\u9664', shortcut: '' },\n { field: 'menuSelectAll', label: '\u5168\u9009', shortcut: 'Ctrl+A' },\n]\n\n/**\n * \u751F\u6210\u4E00\u4E2A\u7A33\u5B9A\u7684\u4F1A\u8BDD ID\uFF08UUID v4\uFF1B\u65E0 crypto \u65F6\u9000\u56DE\u7B49\u4EF7\u7684\u968F\u673A\u5341\u516D\u8FDB\u5236\uFF09\u3002\n * \u503C\u672C\u8EAB\u4E0D\u53C2\u4E0E\u9274\u6743\uFF0C\u53EA\u7528\u4E8E\u8BA9\u7F51\u5173\u628A\u540C\u4E00\u6BB5\u5BF9\u8BDD\u56FA\u5B9A\u5230\u540C\u4E00\u4E2A\u4E0A\u6E38\uFF0C\u6545 Math.random \u515C\u5E95\u53EF\u63A5\u53D7\u3002\n * @returns 36 \u5B57\u7B26\u7684 UUID \u5B57\u7B26\u4E32\u3002\n */\nexport function newSessionId(): string {\n const bag = globalThis as unknown as { crypto?: { randomUUID?: () => string } }\n if (typeof bag.crypto?.randomUUID === 'function') return bag.crypto.randomUUID()\n const hex = (count: number): string => Array.from(\n { length: count },\n () => Math.floor(Math.random() * 16).toString(16),\n ).join('')\n return `${hex(8)}-${hex(4)}-4${hex(3)}-a${hex(3)}-${hex(12)}`\n}\n\n/** \u89E3\u6790\u300C\u4F5C\u7528\u8DEF\u7531\u300D\u6587\u672C\uFF1A\u9017\u53F7 / \u7A7A\u683C / \u6362\u884C\u5206\u9694\uFF0C\u53BB\u91CD\u4FDD\u5E8F\u3002 */\nexport function parseRouteList(text: string): readonly string[] {\n const parts = text.split(/[\\s,\uFF0C\u3001]+/).map(item => item.trim()).filter(item => item !== '')\n return [...new Set(parts)]\n}\n\n/**\n * \u6BCF\u680F\u7684\"\u7528\u6237\u78B0\u8FC7\u6CA1\"\u5224\u636E\uFF08\u8FC1\u79FB\u89C4\u5219\u7528\uFF0C\u89C1\u6587\u4EF6\u4E0A\u65B9\u90A3\u6BB5\u8BF4\u660E\uFF09\u3002\n *\n * \u26A0\uFE0F \u5224\u636E\u5FC5\u987B\u662F\u300C**\u503C\u4E0D\u7B49\u4E8E\"\u4ECE\u6CA1\u78B0\u8FC7\"\u7684\u6837\u5B50**\u300D\uFF0C\u4E0D\u80FD\u662F\u300C\u952E\u5B58\u5728\u300D\uFF1A\n * `settings.get()` \u7ED9\u7684\u662F**\u5DF2\u89E3\u6790**\u7684\u503C\uFF08schema \u9ED8\u8BA4\u503C + \u7EC4\u5408 base + \u7528\u6237\u5C42\uFF09\uFF0C\n * \u6240\u4EE5\u4ECE\u6CA1\u78B0\u8FC7\u7684\u4EBA\u7684\u6587\u6863\u91CC\u4E5F\u7167\u6837\u6709 `sendKey: 'Enter'`\u3001`panelScroll: true` \u8FD9\u4E9B\u9ED8\u8BA4\u503C \u2014\u2014\n * \u6309\"\u952E\u5B58\u5728\"\u5224\u65AD\u4F1A\u8BA9\u5168\u65B0\u5B89\u88C5\u516D\u680F\u5168\u5F00\uFF0C\u4E0E\"\u9ED8\u8BA4\u5173\"\u6B63\u597D\u76F8\u53CD\u3002\n * \uFF08\u7B2C\u4E00\u7248\u5C31\u5199\u6210\u4E86\"\u952E\u5B58\u5728\"\uFF0C\u662F\u63A8\u7406 + \u6D4B\u8BD5\u5F53\u573A\u902E\u4F4F\u7684\uFF0C\u6CE8\u91CA\u7559\u5728\u8FD9\u91CC\u9632\u590D\u53D1\u3002\uFF09\n *\n * \u53E6\u5916\uFF1A\u5BBF\u4E3B\u534A\u81EA\u6301\u5B57\u6BB5\uFF08`terminalStatus` / `terminalCandidates` / `terminalEffective` /\n * `headerApplied*`\uFF09**\u4E0D\u8BB8**\u5F53\u5224\u636E \u2014\u2014 \u5B83\u4EEC\u662F\u63D2\u4EF6\u81EA\u5DF1\u5199\u7684\uFF0C\u5168\u65B0\u5B89\u88C5\u4E5F\u4F1A\u51FA\u73B0\u3002\n *\n * \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u680F\u8FD8\u6709\u4E00\u4E2A\u6587\u6863\u91CC\u770B\u4E0D\u51FA\u6765\u7684\u4FE1\u53F7\uFF1A0.3.0 \u8D77\u6761\u76EE\u642C\u5230\u4E86 `quick-prompts.json`\uFF0C\n * \u7528\u8FC7\u7684\u4EBA\u548C\u6CA1\u7528\u8FC7\u7684\u4EBA\u7684\u8BBE\u7F6E\u6587\u6863\u53EF\u4EE5\u4E00\u6A21\u4E00\u6837\u3002\u90A3\u4E00\u6761\u7531\u5BBF\u4E3B\u534A\u8BFB\u6587\u4EF6\u540E**\u4E00\u6B21\u6027\u5199\u56DE\u6587\u6863**\n * \uFF08\u89C1 `src/host.ts` \u7684 `migrateQuickSection`\uFF09\uFF0C\u6240\u4EE5\u8FD9\u91CC\u53EA\u5269\"\u6587\u6863\u91CC\u7684\u5217\u8868\u88AB\u6539\u8FC7\"\u8FD9\u4E00\u6B21\u7EA7\u4FE1\u53F7\u3002\n */\nconst SECTION_SIGNALS: Readonly<Record<string, (source: Record<string, unknown>) => boolean>> = {\n [KEYS_ENABLED_FIELD]: source =>\n touched(source, SEND_KEY_FIELD, DEFAULT_SETTINGS.sendKey)\n || touched(source, NEWLINE_KEY_FIELD, DEFAULT_SETTINGS.newlineKey),\n // \u300C\u5B98\u65B9\u300D\uFF1D\u672C\u63D2\u4EF6\u4E0D\u4ECB\u5165\uFF0C\u7B49\u4EF7\u4E8E\u5173\uFF1B\u6240\u4EE5\u53EA\u6709\u9009\u8FC7\u53E6\u5916\u4E24\u6863\u624D\u7B97\"\u78B0\u8FC7\"\u3002\n // \uFF08`menuModeFrom` \u5BF9\"\u4E24\u4E2A\u952E\u90FD\u6CA1\u6709\"\u7ED9\u7684\u5C31\u662F 'official'\uFF0C\u5929\u7136\u6EE1\u8DB3\"\u7F3A\u7701 = \u9ED8\u8BA4\"\u3002\uFF09\n [MENU_ENABLED_FIELD]: source =>\n menuModeFrom(source[MENU_MODE_FIELD], source[MENU_NATIVE_FIELD]) !== 'official',\n [QUICK_ENABLED_FIELD]: source =>\n (Array.isArray(source[QUICK_PROMPTS_FIELD])\n && source[QUICK_PROMPTS_FIELD].length !== DEFAULT_QUICK_PROMPTS.length)\n || touched(source, OPTIMIZER_TIER_FIELD, DEFAULT_OPTIMIZER_TIER),\n [PANEL_ENABLED_FIELD]: source =>\n touched(source, PANEL_RESIZE_FIELD, true)\n || source[PANEL_WIDTH_FIELD] !== undefined\n || source[PANEL_HEIGHT_FIELD] !== undefined,\n [TERMINAL_ENABLED_FIELD]: source =>\n touched(source, TERMINAL_MODE_FIELD, DEFAULT_TERMINAL_MODE)\n || touched(source, TERMINAL_BASH_PATH_FIELD, ''),\n}\n\n/**\n * \u8FD9\u4E2A\u952E\u5728\u6587\u6863\u91CC**\u51FA\u73B0\u8FC7**\uFF0C\u4E14\u503C\u4E0D\u7B49\u4E8E\"\u4ECE\u6CA1\u78B0\u8FC7\u7684\u6837\u5B50\"\u3002\n *\n * \u4E24\u4E2A\u6761\u4EF6\u7F3A\u4E00\u4E0D\u53EF\uFF0C\u800C\u4E14\u7B2C\u4E8C\u534A\u6781\u6613\u6F0F\uFF1A\u6587\u6863\u91CC\u6CA1\u6709\u8FD9\u4E2A\u952E\u65F6\u503C\u662F `undefined`\uFF0C\n * \u62FF\u5B83\u53BB\u6BD4\u9ED8\u8BA4\u503C\u4F1A\u5F97\u51FA\"\u4E0D\u76F8\u7B49 \u21D2 \u78B0\u8FC7\"\uFF08`'' !== 'Enter'`\u3001`undefined !== true` \u90FD\u662F\u771F\uFF09\uFF0C\n * \u4E8E\u662F\u5168\u65B0\u5B89\u88C5\u516D\u680F\u5168\u5F00 \u2014\u2014 \u4E0E\"\u9ED8\u8BA4\u5173\"\u6B63\u597D\u76F8\u53CD\u3002\u7B2C\u4E00\u7248\u5C31\u662F\u8FD9\u4E48\u5199\u7684\uFF0C\u88AB\u6D4B\u8BD5\u5F53\u573A\u902E\u4F4F\u3002\n */\nfunction touched(source: Record<string, unknown>, field: string, untouched: unknown): boolean {\n const value = source[field]\n return value !== undefined && value !== untouched\n}\n\n/**\n * \u7B97\u51FA\u4E00\u680F\u5F00\u5173\u7684\u503C\uFF1A\u663E\u5F0F\u5199\u8FC7\u5C31\u542C\u5B83\u7684\uFF0C\u5426\u5219\u6309\"\u7528\u6237\u78B0\u8FC7\u6CA1\"\u63A8\u65AD\u3002\n * @param field \u680F\u5F00\u5173\u5B57\u6BB5\u540D\u3002\n * @param source \u8BBE\u7F6E\u6587\u6863\uFF08\u89E3\u6790\u540E\u7684\u503C\uFF1B\u7F3A\u7701\u7684\u952E\u4F1A\u88AB schemastery \u7701\u6389\uFF0C\u6240\u4EE5 undefined \u5C31\u662F\"\u6CA1\u5199\u8FC7\"\uFF09\u3002\n * @returns \u8BE5\u680F\u662F\u5426\u751F\u6548\u3002\n */\nexport function sectionEnabledOf(field: string, source: Record<string, unknown>): boolean {\n const explicit = source[field]\n if (typeof explicit === 'boolean') return explicit\n const signal = SECTION_SIGNALS[field]\n return signal === undefined ? false : signal(source)\n}\n\n/** \u8BBE\u7F6E\u6570\u636E\u51C0\u5316\uFF1A\u628A\u7EBF\u4E0A\u503C\u6536\u7A84\u4E3A\u5B89\u5168\u5F62\u72B6\uFF08\u9632\u810F\u6570\u636E\uFF09\u3002 */\nexport function sanitizeSettings(value: unknown): ComposerUxSettings {\n const source = (typeof value === 'object' && value !== null ? value : {}) as Record<string, unknown>\n const asString = (field: string): string => {\n const v = source[field]\n return typeof v === 'string' && v.length > 0 && v.length <= 64 ? v : ''\n }\n const asText = (field: string, max: number): string => {\n const v = source[field]\n return typeof v === 'string' && v.length <= max ? v : ''\n }\n /**\n * \u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u4E13\u7528\uFF1A**\u8D85\u4E0A\u9650\u5C31\u622A\u65AD**\uFF0C\u800C\u4E0D\u662F\u50CF `asText` \u90A3\u6837\u6574\u4EFD\u4E22\u6389\u3002\n *\n * \u4E3A\u4EC0\u4E48\u8FD9\u91CC\u4E0E headerName \u90A3\u6761\u76F8\u53CD\uFF1A\u5934\u540D\u975E\u6CD5\u662F\"\u5199\u8FDB\u53BB\u4F1A\u51FA\u7F51\u51FA\u9519\"\uFF0C\u4E22\u6389\u662F\u5BF9\u7684\uFF1B\n * \u800C\u63D0\u793A\u8BCD\u662F**\u7528\u6237\u81EA\u5DF1\u6572\u7684\u5185\u5BB9**\uFF0C\u9759\u9ED8\u4E22\u5F03\u7B49\u4E8E\u628A\u4ED6\u7684\u5DE5\u4F5C\u5F04\u6CA1\u4E86\u3002\u622A\u65AD\u81F3\u5C11\u7559\u5F97\u4E0B\u5927\u534A\uFF0C\n * \u4E14\u8BBE\u7F6E\u9875\u91CC\u5F53\u573A\u770B\u5F97\u89C1\u88AB\u622A\u65AD\u540E\u7684\u6837\u5B50\uFF08textarea \u6709 maxLength\uFF0C\u6B63\u5E38\u6839\u672C\u8D70\u4E0D\u5230\u8FD9\u91CC\uFF0C\n * \u53EA\u6709\u624B\u6539 settings.yaml \u624D\u4F1A\uFF09\u3002\n */\n const asPrompt = (field: string, max: number): string => {\n const v = source[field]\n return typeof v === 'string' ? v.slice(0, max) : ''\n }\n const asBool = (field: string): boolean => {\n const v = source[field]\n return typeof v === 'boolean' ? v : (DEFAULT_SETTINGS as unknown as Record<string, unknown>)[field] as boolean\n }\n const asSize = (field: string): number | undefined => {\n const v = source[field]\n return typeof v === 'number' && Number.isFinite(v) && v >= 320 && v <= 4000 ? Math.round(v) : undefined\n }\n /**\n * \u51C0\u5316\u5FEB\u6377\u6307\u4EE4\u5217\u8868\uFF1A\u9010\u6761\u6536\u7A84\u5F62\u72B6\uFF0C\u4E22\u6389\u6B8B\u7F3A\u9879\uFF0C\u5E76\u6309 id \u53BB\u91CD\u4FDD\u5E8F\u3002\n * \u5B57\u6BB5\u7F3A\u5931 / \u4E0D\u662F\u6570\u7EC4\uFF08\u9996\u6B21\u542F\u7528\uFF09\u2192 \u56DE\u843D\u5230\u5185\u7F6E 9 \u6761\uFF1B\u5B57\u6BB5\u662F\u6570\u7EC4\u5C31\u7167\u5B83\u6765\uFF0C\n * \u7A7A\u6570\u7EC4\u4E5F\u662F\u5408\u6CD5\u72B6\u6001\uFF08\u7528\u6237\u628A\u6761\u76EE\u5168\u5220\u5149\uFF0C\u5C31\u5E94\u5F53\u4FDD\u6301\u5168\u7A7A\uFF0C\u4E0D\u518D\u81EA\u52A8\u5192\u51FA\u6765\uFF09\u3002\n */\n const asQuickPrompts = (): readonly QuickPrompt[] => {\n const raw = source[QUICK_PROMPTS_FIELD]\n if (!Array.isArray(raw)) return DEFAULT_QUICK_PROMPTS\n const seen = new Set<string>()\n const out: QuickPrompt[] = []\n for (const item of raw) {\n if (out.length >= QUICK_PROMPT_MAX) break\n if (typeof item !== 'object' || item === null) continue\n const row = item as Record<string, unknown>\n const prompt = typeof row.prompt === 'string' ? row.prompt.slice(0, QUICK_TEXT_MAX).trim() : ''\n if (prompt === '') continue\n const label = typeof row.label === 'string' ? row.label.slice(0, QUICK_LABEL_MAX).trim() : ''\n const id = typeof row.id === 'string' && row.id !== '' ? row.id.slice(0, 64) : newQuickPromptId()\n if (seen.has(id)) continue\n seen.add(id)\n out.push({\n id,\n label: label === '' ? prompt.slice(0, 12) : label,\n prompt,\n always: row.always === true,\n firstOnly: row.firstOnly === true,\n })\n }\n return out\n }\n const asTier = (): OptimizerTier => {\n const v = source[OPTIMIZER_TIER_FIELD]\n return v === 'basic' || v === 'advanced' || v === 'extreme' ? v : DEFAULT_OPTIMIZER_TIER\n }\n return {\n enabled: asBool(ENABLED_FIELD),\n // \u4E94\u680F\u5F00\u5173\uFF1A\u663E\u5F0F\u5199\u8FC7\u542C\u5B83\u7684\uFF0C\u5426\u5219\u6309\"\u7528\u6237\u78B0\u8FC7\u6CA1\"\u8FC1\u79FB\uFF08\u89C1 sectionEnabledOf\uFF09\u3002\n keysEnabled: sectionEnabledOf(KEYS_ENABLED_FIELD, source),\n menuEnabled: sectionEnabledOf(MENU_ENABLED_FIELD, source),\n quickEnabled: sectionEnabledOf(QUICK_ENABLED_FIELD, source),\n panelEnabled: sectionEnabledOf(PANEL_ENABLED_FIELD, source),\n terminalEnabled: sectionEnabledOf(TERMINAL_ENABLED_FIELD, source),\n sendKey: asString(SEND_KEY_FIELD),\n newlineKey: asString(NEWLINE_KEY_FIELD),\n menuUndo: asBool('menuUndo'),\n menuRedo: asBool('menuRedo'),\n menuCut: asBool('menuCut'),\n menuCopy: asBool('menuCopy'),\n menuPaste: asBool('menuPaste'),\n menuDelete: asBool('menuDelete'),\n menuSelectAll: asBool('menuSelectAll'),\n menuMode: menuModeFrom(source[MENU_MODE_FIELD], source[MENU_NATIVE_FIELD]),\n panelResize: asBool(PANEL_RESIZE_FIELD),\n panelWidth: asSize(PANEL_WIDTH_FIELD),\n panelHeight: asSize(PANEL_HEIGHT_FIELD),\n headerEnabled: asBool(HEADER_ENABLED_FIELD),\n // \u5934\u540D\u7559\u7A7A\u662F\u4E0D\u5408\u6CD5\u72B6\u6001\uFF08\u5BBF\u4E3B\u534A\u4F1A\u62D2\u7EDD\u5199\u5165\u5E76\u628A\u539F\u56E0\u5199\u8FDB headerStatus\uFF09\uFF0C\n // \u6545\u51C0\u5316\u53EA\u505A\u957F\u5EA6\u6536\u7A84\u3001\u4FDD\u7559\u539F\u6837\uFF0C\u8BA9\u7528\u6237\u770B\u5F97\u89C1\u81EA\u5DF1\u8F93\u9519\u4E86\u4EC0\u4E48\u3002\n headerName: asText(HEADER_NAME_FIELD, HEADER_NAME_MAX),\n headerValue: asText(HEADER_VALUE_FIELD, HEADER_VALUE_MAX),\n headerRoutes: asText(HEADER_ROUTES_FIELD, HEADER_VALUE_MAX),\n headerAppliedName: asText(HEADER_APPLIED_NAME_FIELD, HEADER_NAME_MAX),\n headerAppliedValue: asText(HEADER_APPLIED_VALUE_FIELD, HEADER_VALUE_MAX),\n headerStatus: asText(HEADER_STATUS_FIELD, HEADER_VALUE_MAX),\n quickPrompts: asQuickPrompts(),\n optimizerTier: asTier(),\n optimizerPromptBasic: asPrompt(OPTIMIZER_PROMPT_FIELDS.basic, OPTIMIZER_PROMPT_MAX),\n optimizerPromptAdvanced: asPrompt(OPTIMIZER_PROMPT_FIELDS.advanced, OPTIMIZER_PROMPT_MAX),\n optimizerPromptExtreme: asPrompt(OPTIMIZER_PROMPT_FIELDS.extreme, OPTIMIZER_PROMPT_MAX),\n terminalMode: terminalModeFrom(source[TERMINAL_MODE_FIELD]),\n // \u8DEF\u5F84\u53EA\u505A\u957F\u5EA6\u4E0E\u5F52\u4E00\u5316\u6536\u7A84\uFF0C\u4E0D\u5728\u8FD9\u91CC\u5224\"\u5B58\u4E0D\u5B58\u5728\"\u2014\u2014\u90A3\u662F\u5BBF\u4E3B\u534A\u7684\u63A2\u6D4B\u7ED3\u8BBA\uFF0C\n // \u7531\u72B6\u6001\u884C\u544A\u8BC9\u7528\u6237\uFF08\u7528\u6237\u770B\u5F97\u89C1\u81EA\u5DF1\u586B\u4E86\u4EC0\u4E48\uFF0C\u6BD4\u6084\u6084\u6E05\u7A7A\u597D\uFF09\u3002\n terminalBashPath: asText(TERMINAL_BASH_PATH_FIELD, 400),\n terminalCandidates: sanitizeTerminalCandidates(source[TERMINAL_CANDIDATES_FIELD]),\n terminalStatus: asText(TERMINAL_STATUS_FIELD, 400),\n terminalEffective: asText(TERMINAL_EFFECTIVE_FIELD, 16),\n }\n}\n", "/**\n * \u5FEB\u6377\u6307\u4EE4\u7684**\u5BA2\u6237\u7AEF**\u8BFB\u5199\u5C42\u3002\n *\n * \u4E24\u4EF6\u4E8B\uFF1A\n * 1. \u7ECF\u5BBF\u4E3B\u8DEF\u7531 `/composer-ux/prompts` \u8BFB\u3001\u5199\u6574\u672C\uFF08\u6D4F\u89C8\u5668\u6CA1\u6709\u6587\u4EF6\u7CFB\u7EDF\uFF0C\u53EA\u80FD\u8D70 HTTP\uFF09\uFF1B\n * 2. \u4E00\u7EC4**\u7EAF**\u7F16\u8F91\u51FD\u6570\uFF08\u589E\u5220\u6539\u79FB\uFF09\uFF0C\u5168\u90E8\u4E0D\u53EF\u53D8\u2014\u2014\u5217\u8868\u64CD\u4F5C\u6700\u5BB9\u6613\u51FA\u300C\u539F\u5730\u6539\u574F\u300D\u7684\n * bug\uFF0C\u7EAF\u51FD\u6570\u8BA9\u5B83\u80FD\u5728 node \u91CC\u76F4\u63A5\u6D4B\uFF08\u89C1 test/quick-store.mjs \u7B2C 10 \u8282\uFF09\u3002\n *\n * \u4FDD\u5B58\u7B56\u7565\uFF1A\u5148\u4E50\u89C2\u66F4\u65B0\u672C\u5730\u5FEB\u7167\u8BA9 UI \u7ACB\u523B\u54CD\u5E94\uFF0C\u518D\u628A\u6574\u672C POST \u4E0A\u53BB\uFF1B**\u5931\u8D25\u5C31\u4EE5\u78C1\u76D8\n * \u4E3A\u51C6\u56DE\u6EDA**\u2014\u2014\u7EDD\u4E0D\u8BA9\u300C\u754C\u9762\u663E\u793A\u7684\u300D\u548C\u300C\u6587\u4EF6\u91CC\u7684\u300D\u957F\u671F\u4E0D\u4E00\u81F4\u3002\n */\nimport {\n DEFAULT_CATEGORY_NAME, QUICK_CATEGORY_MAX, QUICK_CATEGORY_NAME_MAX, QUICK_LABEL_MAX,\n QUICK_PROMPTS_API_PATH, QUICK_PROMPT_MAX, QUICK_TEXT_MAX,\n insertModeOf, newQuickCategoryId, newQuickPromptId, sanitizeBook,\n type InsertMode, type QuickPrompt, type QuickPromptBook, type QuickPromptCategory,\n} from '../settings-contract.ts'\n\n/** \u8DEF\u7531\u5E94\u7B54\uFF08\u6210\u529F\u4E0E\u5931\u8D25\u90FD\u8D70\u540C\u4E00\u5F62\u72B6\uFF0C\u4FBF\u4E8E\u7EDF\u4E00\u5904\u7406\uFF09\u3002 */\nexport interface PromptBookReply {\n readonly ok: boolean\n readonly book?: QuickPromptBook\n readonly error?: string\n /** \u78C1\u76D8\u4E0A\u7684\u771F\u5B9E\u8DEF\u5F84\uFF08\u5C55\u793A\u7ED9\u7528\u6237\uFF0C\u4FBF\u4E8E\u624B\u5DE5\u7F16\u8F91/\u5907\u4EFD\uFF09\u3002 */\n readonly file?: string\n /** \u574F\u6587\u4EF6\u88AB\u9694\u79BB\u540E\u7684\u8DEF\u5F84\uFF08\u975E\u7A7A\u8BF4\u660E\u51FA\u4E86\u95EE\u9898\u3001\u4E14\u539F\u6587\u4EF6\u5DF2\u4FDD\u4F4F\uFF09\u3002 */\n readonly quarantined?: string\n}\n\nasync function requestBook(method: 'GET' | 'POST', body?: unknown): Promise<PromptBookReply> {\n try {\n const response = await fetch(QUICK_PROMPTS_API_PATH, {\n method,\n headers: body === undefined ? undefined : { 'content-type': 'application/json' },\n body: body === undefined ? undefined : JSON.stringify(body),\n })\n const text = await response.text()\n let parsed: unknown\n try {\n parsed = JSON.parse(text)\n } catch {\n return { ok: false, error: `\u670D\u52A1\u7AEF\u8FD4\u56DE\u7684\u4E0D\u662F JSON\uFF08HTTP ${String(response.status)}\uFF09` }\n }\n const row = (typeof parsed === 'object' && parsed !== null ? parsed : {}) as Record<string, unknown>\n const book = sanitizeBook(row.book)\n const textOf = (value: unknown): string | undefined => (typeof value === 'string' && value !== '' ? value : undefined)\n return {\n ok: row.ok === true,\n ...(book === undefined ? {} : { book }),\n ...(textOf(row.error) === undefined ? {} : { error: textOf(row.error) }),\n ...(textOf(row.file) === undefined ? {} : { file: textOf(row.file) }),\n ...(textOf(row.quarantined) === undefined ? {} : { quarantined: textOf(row.quarantined) }),\n }\n } catch (error: unknown) {\n return { ok: false, error: error instanceof Error ? error.message : String(error) }\n }\n}\n\n/** \u8BFB\u6574\u672C\uFF08\u9996\u6B21\u8BFB\u53D6\u4F1A\u89E6\u53D1\u5BBF\u4E3B\u534A\u7684\u4E00\u6B21\u6027\u8FC1\u79FB\uFF09\u3002 */\nexport function loadPromptBook(): Promise<PromptBookReply> {\n return requestBook('GET')\n}\n\n/** \u5199\u6574\u672C\uFF08\u5BBF\u4E3B\u534A\u4F1A\u505A\u539F\u5B50\u5199\uFF1B\u574F\u6587\u4EF6\u65F6\u5B83\u4F1A\u62D2\u7EDD\u5199\u5165\u5E76\u62A5\u9519\uFF09\u3002 */\nexport function savePromptBook(book: QuickPromptBook): Promise<PromptBookReply> {\n return requestBook('POST', { book })\n}\n\n// \u2500\u2500 \u7EAF\u7F16\u8F91\u51FD\u6570\uFF08\u5168\u90E8\u4E0D\u53EF\u53D8\uFF0C\u8FD4\u56DE\u65B0\u672C\uFF09 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** \u6309 id \u627E\u5206\u7C7B\u3002 */\nexport function categoryOf(book: QuickPromptBook, categoryId: string): QuickPromptCategory | undefined {\n return book.categories.find(category => category.id === categoryId)\n}\n\n/** \u6309 id \u627E\u6761\u76EE\uFF08\u8DE8\u5206\u7C7B\uFF1A\u9762\u677F\u91CC\u7684\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u52FE\u9009\u4E0D\u5E26\u5206\u7C7B\u4E0A\u4E0B\u6587\uFF09\u3002 */\nexport function findPrompt(\n book: QuickPromptBook,\n promptId: string,\n): { readonly category: QuickPromptCategory; readonly prompt: QuickPrompt } | undefined {\n for (const category of book.categories) {\n const prompt = category.prompts.find(item => item.id === promptId)\n if (prompt !== undefined) return { category, prompt }\n }\n return undefined\n}\n\n/** \u7EDF\u8BA1\uFF08\u9762\u677F\u5934\u90E8\u4E0E\u8BBE\u7F6E\u9875\u7528\uFF09\u3002`always` = \u6BCF\u6B21\uFF0C`first` = \u4EC5\u9996\u6B21\u3002 */\nexport function bookCounts(book: QuickPromptBook): {\n readonly categories: number\n readonly prompts: number\n readonly always: number\n readonly first: number\n} {\n const prompts = book.categories.flatMap(category => category.prompts)\n return {\n categories: book.categories.length,\n prompts: prompts.length,\n always: prompts.filter(prompt => insertModeOf(prompt) === 'always').length,\n first: prompts.filter(prompt => insertModeOf(prompt) === 'first').length,\n }\n}\n\nfunction mapCategory(\n book: QuickPromptBook,\n categoryId: string,\n edit: (category: QuickPromptCategory) => QuickPromptCategory,\n): QuickPromptBook {\n return {\n version: book.version,\n categories: book.categories.map(category => (category.id === categoryId ? edit(category) : category)),\n }\n}\n\n/** \u65B0\u589E\u5206\u7C7B\uFF08\u540D\u5B57\u53BB\u7A7A\u767D\uFF1B\u8D85\u8FC7\u4E0A\u9650\u5219\u4E0D\u52A8\u4F5C\u5E76\u8FD4\u56DE\u539F\u672C\uFF09\u3002 */\nexport function withCategoryAdded(book: QuickPromptBook, name: string): QuickPromptBook {\n if (book.categories.length >= QUICK_CATEGORY_MAX) return book\n const clean = name.trim().slice(0, QUICK_CATEGORY_NAME_MAX)\n return {\n version: book.version,\n categories: [...book.categories, { id: newQuickCategoryId(), name: clean === '' ? DEFAULT_CATEGORY_NAME : clean, prompts: [] }],\n }\n}\n\n/** \u6539\u5206\u7C7B\u540D\uFF08\u7A7A\u540D\u56DE\u843D\u5230\u9ED8\u8BA4\u540D\uFF0C\u907F\u514D\u51FA\u73B0\u70B9\u4E0D\u4E2D\u7684\u7A7A\u6807\u7B7E\uFF09\u3002 */\nexport function withCategoryRenamed(book: QuickPromptBook, categoryId: string, name: string): QuickPromptBook {\n const clean = name.trim().slice(0, QUICK_CATEGORY_NAME_MAX)\n return mapCategory(book, categoryId, category => ({ ...category, name: clean === '' ? DEFAULT_CATEGORY_NAME : clean }))\n}\n\n/** \u5220\u5206\u7C7B\uFF08\u8FDE\u5E26\u5B83\u91CC\u9762\u7684\u6761\u76EE\u4E00\u8D77\u5220\uFF09\u3002 */\nexport function withCategoryRemoved(book: QuickPromptBook, categoryId: string): QuickPromptBook {\n return { version: book.version, categories: book.categories.filter(category => category.id !== categoryId) }\n}\n\n/** \u5206\u7C7B\u6362\u4F4D\uFF08delta = -1 \u4E0A\u79FB / +1 \u4E0B\u79FB\uFF09\uFF1B\u8D8A\u754C\u65F6\u539F\u6837\u8FD4\u56DE\u3002 */\nexport function withCategoryMoved(book: QuickPromptBook, categoryId: string, delta: number): QuickPromptBook {\n const index = book.categories.findIndex(category => category.id === categoryId)\n const next = index + delta\n if (index < 0 || next < 0 || next >= book.categories.length) return book\n const categories = [...book.categories]\n const [moved] = categories.splice(index, 1)\n categories.splice(next, 0, moved)\n return { version: book.version, categories }\n}\n\n/**\n * \u5728\u6307\u5B9A\u5206\u7C7B\u91CC\u52A0\u4E00\u6761\u65B0\u6761\u76EE\u3002\n *\n * \u6B63\u6587\u7ED9\u7684\u662F**\u5360\u4F4D\u6587\u6848**\u800C\u4E0D\u662F\u7A7A\u4E32\uFF1A\u7A7A\u6B63\u6587\u7684\u6761\u76EE\u4F1A\u88AB\u51C0\u5316\u4E22\u6389\uFF08`asPromptRow` \u8981\u6C42\u6B63\u6587\n * \u975E\u7A7A\uFF09\uFF0C\u800C\u9762\u677F\u91CC\u7684\u300C\u65B0\u5EFA\u300D\u662F**\u7ACB\u5373\u5199\u76D8**\u7684\u2014\u2014\u7ED9\u7A7A\u6B63\u6587\u7684\u8BDD\u5B83\u4F1A\u5F53\u573A\u6D88\u5931\u3001\u770B\u8D77\u6765\u50CF\u574F\u6389\u4E86\u3002\n * \u8BBE\u7F6E\u9875\u540C\u6837\u7528\u5B83\uFF0C\u4E8E\u662F\u4E24\u8FB9\u884C\u4E3A\u4E00\u81F4\uFF1A\u65B0\u5EFA\u51FA\u6765\u7684\u662F\u4E00\u6761\u300C\u65B0\u6307\u4EE4 /\uFF08\u5F85\u586B\u5199\uFF09\u300D\uFF0C\u628A\u6B63\u6587\n * \u66FF\u6362\u6389\u5373\u53EF\u3002\n */\nexport function withPromptAdded(book: QuickPromptBook, categoryId: string): QuickPromptBook {\n return mapCategory(book, categoryId, (category) => {\n if (category.prompts.length >= QUICK_PROMPT_MAX) return category\n return {\n ...category,\n prompts: [...category.prompts, {\n id: newQuickPromptId(), label: '\u65B0\u6307\u4EE4', prompt: '\uFF08\u5F85\u586B\u5199\uFF09', always: false, firstOnly: false,\n }],\n }\n })\n}\n\n/**\n * \u6539\u6761\u76EE\u5B57\u6BB5\u3002\n *\n * `prompt` \u7A7A\u4E32\u662F**\u5408\u6CD5\u4E2D\u95F4\u6001**\uFF08\u7528\u6237\u6B63\u5728\u7F16\u8F91\uFF09\uFF0C\u6545\u8FD9\u91CC\u4E0D\u505A\u300C\u7A7A\u5C31\u4E22\u6389\u300D\u7684\u6536\u7A84\u2014\u2014\n * \u6536\u7A84\u53D1\u751F\u5728\u5199\u76D8\u4E0E\u51C0\u5316\u65F6\uFF08`sanitizeBook` \u4F1A\u4E22\u6389\u7A7A\u6B63\u6587\u7684\u6761\u76EE\uFF09\uFF0C\u754C\u9762\u4E0A\u4F1A\u8868\u73B0\u4E3A\n * \u300C\u4FDD\u5B58\u540E\u7A7A\u6761\u76EE\u6D88\u5931\u300D\uFF0C\u8FD9\u662F\u671F\u671B\u884C\u4E3A\u3002\n */\nexport function withPromptPatched(\n book: QuickPromptBook,\n categoryId: string,\n promptId: string,\n patch: Partial<Pick<QuickPrompt, 'label' | 'prompt' | 'always' | 'firstOnly'>>,\n): QuickPromptBook {\n return mapCategory(book, categoryId, (category) => ({\n ...category,\n prompts: category.prompts.map((prompt) => {\n if (prompt.id !== promptId) return prompt\n const label = patch.label === undefined ? prompt.label : patch.label.slice(0, QUICK_LABEL_MAX)\n const text = patch.prompt === undefined ? prompt.prompt : patch.prompt.slice(0, QUICK_TEXT_MAX)\n const always = patch.always === undefined ? prompt.always : patch.always\n const firstOnly = patch.firstOnly === undefined ? prompt.firstOnly : patch.firstOnly\n return { id: prompt.id, label, prompt: text, always, firstOnly }\n }),\n }))\n}\n\n/**\n * \u8BBE\u7F6E\u4E00\u6761\u7684\u63D2\u5165\u6A21\u5F0F\uFF08\u754C\u9762\u4E0A\u7684\u4E09\u9009\u4E00\uFF09\u3002\n *\n * **\u4E24\u4E2A\u4E92\u65A5\u6807\u5FD7\u5FC5\u987B\u4E00\u6B21\u5199\u5BF9**\u2014\u2014\u5206\u522B\u5199\u5C31\u53EF\u80FD\u7559\u4E0B\u300C\u53C8\u6BCF\u6B21\u53C8\u4EC5\u9996\u6B21\u300D\u7684\u77DB\u76FE\u72B6\u6001\uFF0C\n * \u6240\u4EE5\u754C\u9762\u53EA\u5141\u8BB8\u901A\u8FC7\u8FD9\u91CC\u6539\u6A21\u5F0F\uFF0C\u4E0D\u76F4\u63A5\u6539\u90A3\u4E24\u4E2A\u5E03\u5C14\u3002\n *\n * @returns \u65B0\u672C\uFF1B\u6761\u76EE\u4E0D\u5B58\u5728\u3001\u6216\u6A21\u5F0F\u6CA1\u53D8\u5316\u65F6**\u539F\u6837\u8FD4\u56DE\u4F20\u5165\u5BF9\u8C61**\uFF08\u907F\u514D\u65E0\u610F\u4E49\u5199\u76D8\uFF09\u3002\n */\nexport function withInsertMode(book: QuickPromptBook, promptId: string, mode: InsertMode): QuickPromptBook {\n const hit = findPrompt(book, promptId)\n if (hit === undefined) return book\n if (insertModeOf(hit.prompt) === mode) return book\n return withPromptPatched(book, hit.category.id, promptId, {\n always: mode === 'always',\n firstOnly: mode === 'first',\n })\n}\n\n/** \u5220\u6761\u76EE\u3002 */\nexport function withPromptRemoved(book: QuickPromptBook, categoryId: string, promptId: string): QuickPromptBook {\n return mapCategory(book, categoryId, category => ({\n ...category,\n prompts: category.prompts.filter(prompt => prompt.id !== promptId),\n }))\n}\n\n/** \u6761\u76EE\u6362\u4F4D\uFF1B\u8D8A\u754C\u65F6**\u8FD4\u56DE\u4F20\u5165\u7684\u90A3\u4E2A\u5BF9\u8C61**\uFF08\u8C03\u7528\u65B9\u636E\u6B64\u907F\u514D\u65E0\u610F\u4E49\u7684\u5199\u76D8\uFF09\u3002 */\nexport function withPromptMoved(book: QuickPromptBook, categoryId: string, promptId: string, delta: number): QuickPromptBook {\n const category = categoryOf(book, categoryId)\n if (category === undefined) return book\n const index = category.prompts.findIndex(prompt => prompt.id === promptId)\n const next = index + delta\n if (index < 0 || next < 0 || next >= category.prompts.length) return book\n const prompts = [...category.prompts]\n const [moved] = prompts.splice(index, 1)\n prompts.splice(next, 0, moved)\n return mapCategory(book, categoryId, target => ({ ...target, prompts }))\n}\n\n/** \u52FE\u9009/\u53D6\u6D88\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\uFF08\u6309 id \u8DE8\u5206\u7C7B\u627E\uFF09\u3002 */\nexport function withAlwaysToggled(book: QuickPromptBook, promptId: string, value: boolean): QuickPromptBook {\n const hit = findPrompt(book, promptId)\n if (hit === undefined) return book\n return withPromptPatched(book, hit.category.id, promptId, { always: value })\n}\n\n/** \u300C\u79FB\u52A8\u5230\u8FD9\u91CC\u300D\u83DC\u5355\u7684\u6570\u636E\u6E90\uFF1A\u5176\u5B83\u5206\u7C7B\u91CC\u7684\u5168\u90E8\u6761\u76EE\uFF08\u5E26\u6765\u6E90\u5206\u7C7B\u540D\uFF09\u3002 */\nexport function promptsElsewhere(\n book: QuickPromptBook,\n categoryId: string,\n): readonly { readonly categoryId: string; readonly categoryName: string; readonly prompt: QuickPrompt }[] {\n return book.categories\n .filter(category => category.id !== categoryId)\n .flatMap(category => category.prompts.map(prompt => ({\n categoryId: category.id,\n categoryName: category.name,\n prompt,\n })))\n}\n\n/**\n * \u628A\u4E00\u4E2A\u6761\u76EE\u4ECE**\u5B83\u5F53\u524D\u6240\u5728\u7684\u5206\u7C7B**\u79FB\u5230\u76EE\u6807\u5206\u7C7B\uFF0C\u8FFD\u52A0\u5230\u76EE\u6807\u672B\u5C3E\u3002\n *\n * \u53EA\u6309 id \u627E\u6761\u76EE\uFF08\u8C03\u7528\u65B9\u4E0D\u5FC5\u77E5\u9053\u5B83\u5728\u54EA\u4E2A\u5206\u7C7B\uFF09\uFF1A\u9762\u677F\u91CC\u300C\u5F53\u524D\u5206\u7C7B\u300D\u662F\u6807\u7B7E\u51B3\u5B9A\u7684\uFF0C\n * \u8BBE\u7F6E\u9875\u6BCF\u4E2A\u5206\u7C7B\u5404\u6709\u4E00\u4EFD\u5217\u8868\u2014\u2014\u6309 id \u627E\u80FD\u5C11\u4E00\u4E2A\u53C2\u6570\uFF0C\u4E5F\u5C11\u4E00\u7C7B\u300C\u4F20\u9519\u6765\u6E90\u300D\u7684 bug\u3002\n *\n * @returns \u65B0\u672C\uFF1B\u4E0B\u5217\u60C5\u51B5**\u539F\u6837\u8FD4\u56DE\u4F20\u5165\u5BF9\u8C61**\uFF08\u8C03\u7528\u65B9\u636E\u6B64\u907F\u514D\u65E0\u610F\u4E49\u7684\u5199\u76D8\uFF09\uFF1A\n * \u6761\u76EE\u4E0D\u5B58\u5728\u3001\u76EE\u6807\u5206\u7C7B\u4E0D\u5B58\u5728\u3001\u76EE\u6807\u5C31\u662F\u5B83\u73B0\u5728\u6240\u5728\u7684\u5206\u7C7B\u3001\u76EE\u6807\u5206\u7C7B\u5DF2\u6EE1\u3002\n */\nexport function withPromptMovedToCategory(\n book: QuickPromptBook,\n promptId: string,\n toCategoryId: string,\n): QuickPromptBook {\n const hit = findPrompt(book, promptId)\n if (hit === undefined || hit.category.id === toCategoryId) return book\n const target = categoryOf(book, toCategoryId)\n if (target === undefined || target.prompts.length >= QUICK_PROMPT_MAX) return book\n return {\n version: book.version,\n categories: book.categories.map((category) => {\n if (category.id === hit.category.id) {\n return { ...category, prompts: category.prompts.filter(prompt => prompt.id !== promptId) }\n }\n if (category.id === toCategoryId) {\n // \u539F\u6837\u642C\u540C\u4E00\u4E2A\u5BF9\u8C61\uFF1Aid / \u540D\u79F0 / \u6B63\u6587 / \u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u6807\u8BB0\u90FD\u8DDF\u7740\u8D70\u3002\n return { ...category, prompts: [...category.prompts, hit.prompt] }\n }\n return category\n }),\n }\n}\n", "/**\n * \u952E\u4F4D\u89C4\u8303\u4E32\uFF1A\u4FEE\u9970\u952E\u6309 Ctrl+Alt+Shift+Meta \u987A\u5E8F + \u4E3B\u952E\uFF0C\u7528 '+' \u8FDE\u63A5\u3002\n * \u4E3B\u952E\u53D6\u503C\u4F18\u5148\u7269\u7406\u7801\uFF08KeyJ\u2192J\u3001Digit3\u21923\uFF09\uFF0C\u5176\u4F59\u7528\u6807\u51C6\u6309\u952E\u540D\uFF08Enter\u3001Space\u3001F2...\uFF09\u3002\n */\n\n/** \u4E00\u6B21\u6309\u952E\u4E8B\u4EF6\u7684\u53EA\u8BFB\u6295\u5F71\uFF08KeyboardEvent \u7684\u6700\u5C0F\u5F62\u72B6\uFF09\u3002 */\nexport interface ChordEvent {\n readonly ctrlKey: boolean\n readonly altKey: boolean\n readonly shiftKey: boolean\n readonly metaKey: boolean\n readonly code: string\n readonly key: string\n}\n\n/** \u4FEE\u9970\u952E\u672C\u8EAB\uFF08\u4E0D\u5E94\u4F5C\u4E3A\u4E3B\u952E\u53C2\u4E0E\u7ED1\u5B9A\uFF09\u3002 */\nconst MODIFIER_KEYS = new Set(['Control', 'Alt', 'Shift', 'Meta', 'AltGraph'])\n\n/** \u5E38\u89C1\u6807\u70B9\u4E3B\u952E\u7684\u53CB\u597D\u540D\u3002 */\nconst CODE_LABELS: Readonly<Record<string, string>> = {\n Slash: '/',\n Backslash: '\\\\',\n BracketLeft: '[',\n BracketRight: ']',\n Semicolon: ';',\n Quote: \"'\",\n Comma: ',',\n Period: '.',\n Backquote: '`',\n Minus: '-',\n Equal: '=',\n Space: 'Space',\n}\n\n/** \u628A\u4E00\u6B21\u6309\u952E\u4E8B\u4EF6\u7F16\u7801\u4E3A\u89C4\u8303\u4E32\uFF1B\u7EAF\u4FEE\u9970\u952E\u8FD4\u56DE ''\u3002 */\nexport function encodeChord(event: ChordEvent): string {\n const parts: string[] = []\n if (event.ctrlKey) parts.push('Ctrl')\n if (event.altKey) parts.push('Alt')\n if (event.shiftKey) parts.push('Shift')\n if (event.metaKey) parts.push('Meta')\n const mainKey = normalizeMainKey(event)\n if (mainKey === '') return ''\n parts.push(mainKey)\n return parts.join('+')\n}\n\n/** \u4E3B\u952E\u540D\uFF1A\u5B57\u6BCD/\u6570\u5B57\u7528\u7269\u7406\u7801\u5F52\u4E00\uFF0C\u5176\u4F59\u7528\u6807\u51C6\u540D\u3002 */\nfunction normalizeMainKey(event: ChordEvent): string {\n const code = event.code\n if (code.startsWith('Key')) return code.slice(3)\n if (code.startsWith('Digit')) return code.slice(5)\n if (CODE_LABELS[code] !== undefined) return CODE_LABELS[code] as string\n // F1..F24 \u53CA Enter/Tab/Arrow* /Backspace/Delete \u7B49 code \u672C\u8EAB\u5373\u6807\u51C6\u540D\u3002\n return code !== '' ? code : event.key\n}\n\n/** \u662F\u5426\u7EAF\u4FEE\u9970\u952E\u6309\u4E0B\uFF08\u7528\u4E8E\u5FFD\u7565 Ctrl/Alt/Shift \u5355\u72EC\u6309\u4E0B\uFF09\u3002 */\nexport function isModifierOnly(event: ChordEvent): boolean {\n return MODIFIER_KEYS.has(event.key)\n}\n\n/** \u4E3B\u952E\u662F\u5426\u5C5E\u4E8E\u300C\u6253\u5B57\u7C7B\u300D\u6309\u952E\uFF08\u672A\u88AB\u8BB0\u5F55\u89C4\u5219\u5141\u8BB8\u7684\u88F8\u952E\uFF09\u3002 */\nconst BARE_ALLOWED = new Set([\n 'Enter', 'Space', 'Tab', 'Backspace', 'Delete', 'Insert', 'Home', 'End',\n 'PageUp', 'PageDown', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight',\n])\n\n/** \u88F8\u952E\uFF08\u65E0\u4EFB\u4F55\u4FEE\u9970\u952E\uFF09\u662F\u5426\u5141\u8BB8\u7ED1\u5B9A\u3002 */\nexport function isBareKeyAllowed(chord: string): boolean {\n if (chord.includes('+')) return true\n if (BARE_ALLOWED.has(chord)) return true\n return /^F\\d{1,2}$/.test(chord)\n}\n\n/** \u89E3\u6790\u89C4\u8303\u4E32 \u2192 \u53CD\u5411\u4E8B\u4EF6\u521D\u59CB\u5316\u53C2\u6570\uFF08\u7528\u4E8E\u5408\u6210\u56DE\u653E\uFF09\u3002 */\nexport function chordToInit(chord: string): KeyboardEventInit {\n const parts = chord.split('+').filter(Boolean)\n const init: KeyboardEventInit = {\n ctrlKey: false,\n altKey: false,\n shiftKey: false,\n metaKey: false,\n bubbles: true,\n cancelable: true,\n }\n const key = parts.pop() ?? ''\n init.key = key\n // \u4E3B\u952E\u7684 code \u53CD\u63A8\uFF08\u5C3D\u529B\u8FD8\u539F\uFF1B\u4EC5\u5F71\u54CD IME/\u7269\u7406\u7801\u8BFB\u53D6\uFF0C\u4E0D\u5C5E\u5173\u952E\u8DEF\u5F84\uFF09\u3002\n init.code = key.length === 1 ? (/^[A-Z]$/.test(key) ? `Key${key}` : key) : key\n for (const part of parts) {\n if (part === 'Ctrl') init.ctrlKey = true\n else if (part === 'Alt') init.altKey = true\n else if (part === 'Shift') init.shiftKey = true\n else if (part === 'Meta') init.metaKey = true\n }\n return init\n}\n\n/** \u952E\u4F4D\u662F\u5426\u5C5E\u4E8E Enter \u5BB6\u65CF\uFF08\u62E6\u622A\u5668\u53EA\u63A5\u7BA1\u8FD9\u4E9B\u7EC4\u5408\uFF09\u3002 */\nexport function isEnterFamily(chord: string): boolean {\n return chord === 'Enter' || chord.endsWith('+Enter')\n}\n\n/** \u8BB0\u5F55\u65F6\u5408\u6CD5\u6027\u68C0\u67E5\u7ED3\u679C\u3002 */\nexport type RecordResult =\n | { kind: 'ok'; chord: string }\n | { kind: 'cancel' }\n | { kind: 'clear' }\n | { kind: 'ignore' }\n | { kind: 'reject'; message: string }\n\n/** \u68C0\u67E5\u5F55\u5236\u6309\u952E\uFF1A\u7ED3\u679C\u4E3A ok \u65F6\u8FD4\u56DE\u53EF\u5199\u5165\u7684\u89C4\u8303\u4E32\u3002 */\nexport function evaluateRecordedKey(event: ChordEvent): RecordResult {\n if (isModifierOnly(event)) return { kind: 'ignore' }\n if (event.code === 'Escape' || event.key === 'Escape') return { kind: 'cancel' }\n // Backspace/Delete = \u6E05\u9664\u7ED1\u5B9A\uFF08\u4E0E\u300C\u65E0\u300D\u7B49\u4EF7\uFF0C\u4F46\u8BED\u4E49\u66F4\u660E\u663E\uFF09\u3002\n if (event.code === 'Backspace' || event.code === 'Delete') return { kind: 'clear' }\n const chord = encodeChord(event)\n if (chord === '') return { kind: 'ignore' }\n if (!isBareKeyAllowed(chord)) {\n return {\n kind: 'reject',\n message: '\u5355\u4E2A\u5B57\u6BCD/\u6570\u5B57\u952E\u4F1A\u4E0E\u6253\u5B57\u51B2\u7A81\uFF0C\u8BF7\u914D\u5408 Ctrl / Alt / Shift \u4F7F\u7528\uFF0C\u6216\u9009\u62E9 Enter\u3002',\n }\n }\n return { kind: 'ok', chord }\n}\n\n/** \u952E\u4F4D\u663E\u793A\u6587\u672C\uFF1A'' \u2192 \u65E0\u3002 */\nexport function displayChord(chord: string): string {\n return chord === '' ? '\u65E0' : chord\n}\n", "/**\n * \u5FEB\u6377\u6307\u4EE4\u4E0E\u300C\u53D1\u9001\u65F6\u9644\u52A0\u6761\u76EE\u300D\u7684\u8FD0\u884C\u65F6\u6865\u63A5\u3002\n *\n * \u4E3A\u4EC0\u4E48\u9700\u8981\u8FD9\u4E2A\u6A21\u5757\uFF1A\u8F93\u5165\u6846\u62E6\u622A\u5668\uFF08interceptors.ts\uFF09\u6D3B\u5728\u7EAF DOM / \u6355\u83B7\u9636\u6BB5\u91CC\uFF0C\n * \u62FF\u4E0D\u5230 React \u69FD\u4F4D\u624D\u6709\u7684 `inputActions` \u4E0E InputState \u8349\u7A3F\uFF1B\u800C\u300C\u70B9\u53D1\u9001\u65F6\u81EA\u52A8\u628A\n * \u63D0\u793A\u8BCD\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E\u300D\u4E24\u6837\u90FD\u8981\u7528 \u2014\u2014 \u5F97\u77E5\u9053\u5F53\u524D\u8349\u7A3F\u662F\u4EC0\u4E48\uFF0C\u518D\u628A\u9644\u52A0\u540E\u7684\u6574\u6BB5\u5199\n * \u56DE\u7F16\u8F91\u5668\u3002\u4E8E\u662F\u7531 `conversation.input.right` \u7684\u6309\u94AE\u7EC4\u4EF6\u5728\u6BCF\u6B21\u6E32\u67D3\u65F6\u628A\u8FD9\u4E24\u6837\u4E1C\u897F\n * \u6295\u9012\u5230\u8FD9\u91CC\uFF0C\u62E6\u622A\u5668\u540C\u6B65\u8BFB\u53D6\u3002\n *\n * \u6CE8\u610F\u5206\u5DE5\uFF1A**\u300C\u54EA\u4E9B\u6761\u76EE\u8BE5\u9644\u52A0\u300D\u4E0D\u5728\u8FD9\u91CC\u5224\u65AD**\uFF0C\u7531\u8C03\u7528\u65B9\n * `appendBatchForSend(book, currentBlankSession())` \u51B3\u5B9A\uFF08\u300C\u6BCF\u6B21\u300D\u5168\u5E26\u4E0A\uFF0C\n * \u300C\u4EC5\u9996\u6B21\u300D\u53EA\u5728\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u6D88\u606F\u65F6\u5E26\u4E0A\uFF09\uFF1B\u672C\u6A21\u5757\u53EA\u8D1F\u8D23\u628A\u90A3\u4E00\u6279\u62FC\u4E0A\u53BB\u3001\u5199\u56DE\u53BB\u3002\n * 0.4.0 \u66FE\u5728\u4E00\u4E2A\u51FD\u6570\u91CC\u5224\u65AD\u4E86\u4E24\u6B21\uFF0C\u89C1 `withPromptsAppended` \u7684\u8BF4\u660E\u3002\n *\n * \u672C\u6A21\u5757\u96F6 React \u4F9D\u8D56\uFF0C\u53EF\u88AB\u62E6\u622A\u5668\u4E0E\u7EC4\u4EF6\u5171\u7528\u3002\n */\nimport type { QuickPrompt } from '../settings-contract.ts'\nimport { OPTIMIZER_API_PATH } from '../settings-contract.ts'\n\n/** \u5B98\u65B9\u516C\u5F00\u8F93\u5165\u52A8\u4F5C\u91CC\u672C\u6A21\u5757\u7528\u5230\u7684\u4E24\u4E2A\uFF08\u89C1 DSH \u7684 InputActions \u5951\u7EA6\uFF09\u3002 */\nexport interface InputActionsLike {\n /** \u6574\u4F53\u66FF\u6362\u8349\u7A3F\uFF08\u5B98\u65B9\u652F\u6301\u7684\u7A0B\u5E8F\u5316\u5199\u5165\u8DEF\u5F84\uFF09\u3002 */\n setDraft: (text: string) => void\n}\n\n/** \u8349\u7A3F\u6765\u6E90\uFF1A\u69FD\u4F4D\u5FEB\u7167\uFF08\u6743\u5A01\uFF09> DOM \u515C\u5E95\u3002 */\ninterface BridgeState {\n actions: InputActionsLike | null\n draft: string\n sessionId: string\n /**\n * \u4F1A\u8BDD\u662F\u5426\u8FD8**\u6CA1\u6709\u4EFB\u4F55\u6D88\u606F**\uFF08\u69FD\u4F4D\u7ED9\u7684 `SessionSnapshot.blank`\uFF09\u3002\n *\n * \u300C\u4EC5\u9996\u6B21\u63D2\u5165\u300D\u5C31\u9760\u5B83\uFF1A\u53D1\u5B8C\u7B2C\u4E00\u6761\u5B83\u81EA\u5DF1\u4F1A\u53D8\u6210 false\uFF0C\u6240\u4EE5\u4E0D\u5FC5\u81EA\u5DF1\u8BB0\u300C\u672C\u4F1A\u8BDD\u9644\u52A0\u8FC7\n * \u6CA1\u6709\u300D\uFF0C\u5237\u65B0\u9875\u9762\u4E5F\u4E0D\u4F1A\u91CD\u590D\u9644\u52A0\u3002\u53D6\u4E0D\u5230\u4F1A\u8BDD\u65F6\u6309 false \u5904\u7406\uFF08\u5B81\u53EF\u4E0D\u9644\u52A0\uFF0C\u4E5F\u4E0D\u8BEF\u9644\u52A0\uFF09\u3002\n */\n blank: boolean\n}\n\n/** \u8F93\u5165\u6846\u6839\u5143\u7D20\u7684\u9009\u62E9\u5668\uFF08\u4E0E interceptors.ts \u4FDD\u6301\u4E00\u81F4\uFF09\u3002 */\nconst COMPOSER_SELECTOR = '[data-composer-input]'\n\n/** \u8F93\u5165\u5361\u7247\u9009\u62E9\u5668\uFF08\u5B98\u65B9\u5728 InputBar \u4E0A\u5199\u7684\u6807\u8BB0\uFF09\u3002 */\nconst CARD_SELECTOR = '[data-composer-card]'\n\nconst state: BridgeState = { actions: null, draft: '', sessionId: '', blank: false }\n\n/**\n * \u69FD\u4F4D\u7EC4\u4EF6\u6BCF\u6B21\u6E32\u67D3\u6295\u9012\u4E00\u6B21\u6865\u63A5\u6570\u636E\u3002\n * @param next - \u672C\u4F1A\u8BDD\u7684\u8F93\u5165\u52A8\u4F5C\u3001\u5F53\u524D\u8349\u7A3F\u3001\u670D\u52A1\u7AEF\u4F1A\u8BDD id\u3001\u4EE5\u53CA\u4F1A\u8BDD\u662F\u5426\u8FD8\u6CA1\u6709\u6D88\u606F\u3002\n */\nexport function publishInputBridge(next: {\n readonly actions: InputActionsLike | null\n readonly draft: string\n readonly sessionId: string\n readonly blank: boolean\n}): void {\n state.actions = next.actions\n state.draft = next.draft\n state.sessionId = next.sessionId\n state.blank = next.blank\n}\n\n/**\n * \u5378\u8F7D\u65F6\u64A4\u4E0B\u6865\u63A5\uFF0C\u907F\u514D\u300C\u5207\u8D70\u7684\u4F1A\u8BDD\u300D\u7559\u4E0B\u7684\u65E7 actions \u88AB\u540E\u7EED\u624B\u52BF\u8BEF\u7528\u3002\n * \u53EA\u6E05\u81EA\u5DF1\u90A3\u4EFD\uFF1A\u540C\u4E00\u4E2A\u4F1A\u8BDD\u53EF\u80FD\u5148\u540E\u6302\u8F7D\u591A\u4E2A\u69FD\u4F4D\u6761\u76EE\u3002\n * @param sessionId - \u5378\u8F7D\u65B9\u6240\u5C5E\u4F1A\u8BDD id\u3002\n */\nexport function releaseInputBridge(sessionId: string): void {\n if (state.sessionId !== sessionId) return\n state.actions = null\n state.draft = ''\n state.sessionId = ''\n state.blank = false\n}\n\n/** \u5F53\u524D\u4F1A\u8BDD\u662F\u4E0D\u662F\u8FD8\u6CA1\u6709\u4EFB\u4F55\u6D88\u606F\uFF08\u300C\u4EC5\u9996\u6B21\u63D2\u5165\u300D\u7684\u5224\u636E\uFF09\u3002 */\nexport function currentBlankSession(): boolean {\n return state.blank === true\n}\n\n/** DOM \u515C\u5E95\u8BFB\u8349\u7A3F\uFF08\u69FD\u4F4D\u672A\u6302\u8F7D\u65F6\u7684\u6700\u540E\u624B\u6BB5\uFF09\u3002 */\nfunction draftFromDom(): string {\n const el = document.querySelector(COMPOSER_SELECTOR)\n if (!(el instanceof HTMLElement)) return ''\n return el.innerText.replace(/\\n+$/, '')\n}\n\n/** \u5F53\u524D\u8349\u7A3F\uFF1A\u6709\u69FD\u4F4D\u5C31\u4FE1\u69FD\u4F4D\u5FEB\u7167\uFF0C\u5426\u5219\u8BFB DOM\u3002 */\nexport function currentDraft(): string {\n return state.actions === null ? draftFromDom() : state.draft\n}\n\n/** \u5F53\u524D\u4F1A\u8BDD id\uFF08'' = \u65E0\u4F1A\u8BDD\uFF09\u3002 */\nexport function currentSessionId(): string {\n return state.sessionId\n}\n\n/**\n * \u628A\u8FD9\u4E00\u6B21\u8981\u9644\u52A0\u7684\u6761\u76EE\u62FC\u5230\u539F\u6587**\u672B\u5C3E**\u3002\n *\n * \u89C4\u5219\uFF08\u4E0E\u7528\u6237\u786E\u8BA4\u8FC7\u7684\u8BED\u4E49\u4E00\u81F4\uFF09\uFF1A\n * - \u591A\u6761\u6309\u5217\u8868\u987A\u5E8F\u62FC\u63A5\uFF0C\u6761\u76EE\u4E4B\u95F4\u7A7A\u4E00\u884C\uFF1B\n * - \u539F\u6587\u4E3A\u7A7A\u65F6**\u4E0D\u9644\u52A0** \u2014\u2014 \u6CA1\u6709\u300C\u4F60\u7684\u6D88\u606F\u300D\u53EF\u9644\u52A0\uFF0C\u6B64\u65F6\u5E94\u5F53\u4EA4\u8FD8\u5B98\u65B9\u539F\u8BED\u4E49\n * \uFF08\u7A7A\u8F93\u5165\u7684 Enter \u5728\u5B98\u65B9\u90A3\u91CC\u662F\u522B\u7684\u52A8\u4F5C\uFF0C\u62A2\u8FC7\u6765\u4F1A\u8BA9\u4EBA\u610F\u5916\uFF09\uFF1B\n * - \u6279\u6B21\u4E3A\u7A7A\u65F6\u8FD4\u56DE null\uFF1B\n * - **\u5DF2\u7ECF\u4EE5\u540C\u4E00\u6BB5\u540E\u7F00\u7ED3\u5C3E\u65F6\u8FD4\u56DE null\uFF08\u5E42\u7B49\uFF09** \u2014\u2014 \u4E07\u4E00\u53D1\u9001\u90A3\u4E00\u6B65\u6CA1\u6210\uFF0C\u7B2C\u4E8C\u6B21\n * \u70B9\u51FB\u4E0D\u4F1A\u628A\u540C\u4E00\u6BB5\u63D0\u793A\u8BCD\u518D\u53E0\u4E00\u904D\uFF0C\u800C\u662F\u76F4\u63A5\u653E\u884C\u5B98\u65B9\u53D1\u9001\uFF080.2.0 \u7684\u5931\u63A7\u75C7\u72B6\u5C31\u662F\n * \u300C\u4E00\u76F4\u70B9\u4E00\u76F4\u63D2\u5165\u300D\uFF0C\u8FD9\u6761\u62A4\u680F\u8BA9\u5B83\u53D8\u6210\u300C\u518D\u70B9\u4E00\u6B21\u5C31\u53D1\u51FA\u53BB\u300D\uFF09\u3002\n *\n * \u26A0\uFE0F **\u8FD9\u91CC\u7EDD\u4E0D\u80FD\u518D\u6309\u63D2\u5165\u6A21\u5F0F\u8FC7\u6EE4\u4E00\u904D**\uFF1A\u8FD9\u4E00\u6279\u91CC\u8BE5\u6709\u8C01\uFF0C\u5DF2\u7531\u8C03\u7528\u65B9\n * `appendBatchForSend(book, blank)` \u51B3\u5B9A\u30020.4.0 \u5C31\u662F\u5728\u8FD9\u91CC\u4E22\u8FC7\u529F\u80FD\u7684 \u2014\u2014 \u672C\u51FD\u6570\u5F53\u65F6\n * \u53EB `withAlwaysPrompts`\uFF0C\u5185\u90E8\u53C8\u6309 `always === true` \u8FC7\u6EE4\u4E86\u4E00\u6B21\uFF0C\u540E\u679C\u662F\uFF1A\n * \u00B7 \u65B0\u4F1A\u8BDD\u7B2C\u4E00\u6761\u91CC\u300C\u4EC5\u9996\u6B21\u300D\u7684\u6761\u76EE\u88AB\u8FD9\u5C42\u8FC7\u6EE4\u4E22\u6389\uFF0C\u53EA\u5269\u300C\u6BCF\u6B21\u300D\u7684\uFF1B\n * \u00B7 \u82E5\u4E00\u6761\u300C\u6BCF\u6B21\u300D\u90FD\u6CA1\u6709\uFF0C`picked.length === 0` \u76F4\u63A5\u8FD4\u56DE null\uFF0C\u7B2C\u4E00\u6761\u4EC0\u4E48\u90FD\u4E0D\u9644\u3002\n * \u6A21\u5F0F\u5224\u65AD\u53EA\u5141\u8BB8\u6709\u4E00\u5904\uFF08`settings-contract.ts` \u7684 `insertModeOf`\uFF09\u3002\n * @param draft - \u5F53\u524D\u8349\u7A3F\u539F\u6587\u3002\n * @param prompts - \u8FD9\u4E00\u6B21\u8981\u9644\u52A0\u7684\u6761\u76EE\uFF08\u8C03\u7528\u65B9\u5DF2\u51B3\u5B9A\uFF0C\u542B\u8DE8\u5206\u7C7B\u987A\u5E8F\uFF09\u3002\n * @returns \u62FC\u63A5\u540E\u7684\u5B8C\u6574\u8349\u7A3F\uFF1B\u65E0\u9700\u9644\u52A0\u65F6\u4E3A null\u3002\n */\nexport function withPromptsAppended(draft: string, prompts: readonly QuickPrompt[]): string | null {\n const picked = prompts.filter(item => item.prompt.trim() !== '')\n if (picked.length === 0) return null\n const base = draft.replace(/\\s+$/, '')\n if (base === '') return null\n const suffix = picked.map(item => item.prompt.trim()).join('\\n\\n')\n if (base.endsWith(suffix)) return null\n return `${base}\\n\\n${suffix}`\n}\n\n/**\n * \u628A\u8FD9\u4E00\u6B21\u8981\u9644\u52A0\u7684\u6761\u76EE\u5199\u56DE\u7F16\u8F91\u5668\u3002\n *\n * \u53EA\u8D1F\u8D23\u5199\u5165\uFF0C\u4E0D\u8D1F\u8D23\u53D1\u9001\uFF1A\u53D1\u9001\u52A8\u4F5C\u4EA4\u8FD8\u5B98\u65B9\u624B\u52BF\uFF08\u89C1 interceptors.ts \u7684\u4E24\u6761\u8DEF\u5F84\uFF09\uFF0C\n * \u8FD9\u6837\u300C\u53D1\u9001 / \u6392\u961F / \u6253\u65AD\u300D\u7684\u8BED\u4E49\u5B8C\u5168\u7531\u5B98\u65B9\u51B3\u5B9A\uFF0C\u672C\u63D2\u4EF6\u4E0D\u505A\u7B2C\u4E8C\u5957\u5224\u65AD\u3002\n * @param prompts - \u8FD9\u4E00\u6B21\u8981\u9644\u52A0\u7684\u6761\u76EE\uFF08\u6765\u81EA `deps.promptsForSend()`\uFF09\u3002\n * @returns true = \u5DF2\u5199\u5165\uFF08\u8C03\u7528\u65B9\u5E94\u7EE7\u7EED\u8D70\u5B98\u65B9\u53D1\u9001\u624B\u52BF\uFF09\uFF1Bfalse = \u65E0\u9700\u9644\u52A0\u3002\n */\nexport function applyPromptsForSend(prompts: readonly QuickPrompt[]): boolean {\n const actions = state.actions\n if (actions === null) return false\n const next = withPromptsAppended(currentDraft(), prompts)\n if (next === null) return false\n actions.setDraft(next)\n return true\n}\n\n/** \u628A\u4E00\u6BB5\u6587\u672C\u63D2\u8FDB\u8F93\u5165\u6846\uFF08\u6761\u76EE\u70B9\u51FB\u63D2\u5165\u7528\uFF1B\u539F\u6709\u5185\u5BB9\u4FDD\u7559\uFF0C\u65B0\u5185\u5BB9\u53E6\u8D77\u4E00\u884C\uFF09\u3002 */\nexport function insertIntoDraft(text: string): boolean {\n const actions = state.actions\n const body = text.trim()\n if (actions === null || body === '') return false\n const draft = currentDraft()\n const next = draft.trim() === '' ? body : `${draft.replace(/\\s+$/, '')}\\n${body}`\n actions.setDraft(next)\n return true\n}\n\n/** \u6574\u4F53\u66FF\u6362\u8349\u7A3F\uFF08\u4F18\u5316\u7ED3\u679C\u5199\u56DE\u7528\uFF09\u3002 */\nexport function replaceDraft(text: string): boolean {\n const actions = state.actions\n if (actions === null) return false\n actions.setDraft(text)\n return true\n}\n\n/** \u628A\u7126\u70B9\u4EA4\u8FD8\u8F93\u5165\u6846\uFF08\u63D2\u5165/\u5199\u56DE\u4E4B\u540E\u8C03\u7528\uFF0C\u65B9\u4FBF\u63A5\u7740\u6253\u5B57\uFF09\u3002 */\nexport function focusComposer(): void {\n const el = document.querySelector(COMPOSER_SELECTOR)\n if (el instanceof HTMLElement) el.focus({ preventScroll: true })\n}\n\n/**\n * \u627E\u51FA\u8FD9\u6B21\u70B9\u51FB\u843D\u5728\u7684**\u5B98\u65B9\u53D1\u9001\u4E3B\u6309\u94AE**\uFF1B\u4E0D\u662F\u53D1\u9001\u952E\u65F6\u8FD4\u56DE null\u3002\n *\n * \u4E3A\u4EC0\u4E48\u8FD4\u56DE\u5143\u7D20\u800C\u4E0D\u662F\u5E03\u5C14\uFF1A\u8C03\u7528\u65B9\u8981\u62FF\u5B83**\u91CD\u653E\u4E00\u6B21\u70B9\u51FB**\uFF08\u89C1 interceptors.ts\uFF09\u3002\n * \u8FD9\u91CC\u5FC5\u987B\u8FD4\u56DE\u771F\u6B63\u7684 `<button>`\uFF0C\u800C\u4E0D\u662F `event.target` \u2014\u2014 \u53D1\u9001\u952E\u662F\u4E2A\u5706\u5F62\u6309\u94AE\uFF0C\n * \u89C6\u89C9\u4E2D\u5FC3\u5C31\u662F\u91CC\u9762\u7684 `<svg>` / `<path>`\uFF0C\u800C **SVG \u5143\u7D20\u6CA1\u6709 `.click()`**\u3002\n * 0.2.0 \u5C31\u662F\u56E0\u4E3A\u628A `event.target` \u5F53\u6309\u94AE\u7528\u3001`click()` \u629B TypeError \u800C\u6CA1\u53D1\u9001\uFF0C\n * \u75C7\u72B6\u662F\u300C\u70B9\u4E86\u53EA\u63D2\u5165\u3001\u4E0D\u53D1\u9001\uFF0C\u4E00\u76F4\u70B9\u4E00\u76F4\u63D2\u5165\u300D\u3002\n *\n * \u4E3A\u4EC0\u4E48\u6562\u6309\u7ED3\u6784\u5224\u522B\uFF1A\u53D1\u9001\u952E\u4E0E\u505C\u6B62\u952E\u5171\u7528\u540C\u4E00\u4E2A\u4F4D\u7F6E\uFF08\u5361\u7247\u91CC\u6700\u540E\u4E00\u4E2A button\uFF09\uFF0C\n * \u53EA\u80FD\u9760\u56FE\u5F62\u533A\u5206 \u2014\u2014 \u505C\u6B62\u6E32\u67D3 `<rect>`\uFF08\u65B9\u5757\uFF09\uFF0C\u53D1\u9001\u6E32\u67D3 `<path>`\uFF08\u7BAD\u5934\uFF09\u3002\n * \u6309\u56FE\u5F62\u5224\u522B\u4E0E\u754C\u9762\u6587\u6848\u3001\u8BED\u8A00\u90FD\u65E0\u5173\uFF0C\u4E2D\u82F1\u6587\u73AF\u5883\u4E00\u81F4\u3002\n * @param target - \u4E8B\u4EF6\u76EE\u6807\uFF08\u53EF\u80FD\u662F\u6309\u94AE\u672C\u8EAB\uFF0C\u4E5F\u53EF\u80FD\u662F\u5B83\u5185\u90E8\u7684\u56FE\u6807\uFF09\u3002\n * @returns \u5B98\u65B9\u53D1\u9001\u4E3B\u6309\u94AE\uFF1B\u65E0\u6CD5\u786E\u5B9A\u65F6 null\uFF08\u6B64\u65F6\u8C03\u7528\u65B9\u5FC5\u987B**\u4E0D\u62E6\u622A**\uFF09\u3002\n */\nexport function sendButtonOf(target: EventTarget | null): HTMLButtonElement | null {\n if (!(target instanceof Element)) return null\n const card = target.closest(CARD_SELECTOR)\n if (card === null) return null\n const buttons = card.querySelectorAll('button')\n if (buttons.length === 0) return null\n const last = buttons[buttons.length - 1]!\n // \u5FC5\u987B\u662F\u771F\u6B63\u7684 <button>\uFF1A\u62FF\u5230\u7684\u82E5\u662F svg\uFF0C\u91CD\u653E\u70B9\u51FB\u4F1A\u5931\u8D25\u3002\n if (!(last instanceof HTMLButtonElement)) return null\n if (last !== target && !last.contains(target)) return null\n if (last.disabled) return null\n // \u505C\u6B62\u952E\uFF1A\u65B9\u5757\u56FE\u6807\u3002\u53D1\u9001\u952E\uFF1A\u7BAD\u5934 path\u3002\n if (last.querySelector('svg rect') !== null) return null\n if (last.querySelector('svg path') === null) return null\n return last\n}\n\n/** \u4E00\u6761\u88AB\u5BBF\u4E3B\u4E22\u6389\u7684\u6761\u76EE\uFF08\u9762\u677F\u636E\u6B64\u5982\u5B9E\u544A\u8BC9\u7528\u6237\"\u4E22\u4E86\u51E0\u6761\u3001\u4E3A\u4EC0\u4E48\"\uFF09\u3002 */\nexport interface OptimizeDropped {\n readonly id: string\n readonly kind: string\n readonly reason: string\n}\n\n/** \u4E00\u6B21\u4F18\u5316\u7684\u7ED3\u679C\u3002 */\nexport interface OptimizeOutcome {\n readonly ok: boolean\n /** \u6210\u529F\u65F6\uFF1A\u4F18\u5316\u540E\u7684\u6B63\u6587\u3002 */\n readonly text?: string\n /** \u5931\u8D25\u65F6\uFF1A\u7ED9\u7528\u6237\u770B\u7684\u4E00\u53E5\u8BDD\u539F\u56E0\u3002 */\n readonly error?: string\n /** \u6210\u529F\u65F6\uFF1A\u5B9E\u9645\u4F7F\u7528\u7684\u8DEF\u7531\uFF08\u7528\u4E8E\u300C\u4F18\u5316\u6CA1\u751F\u6548\u300D\u65F6\u7684\u6392\u67E5\uFF09\u3002 */\n readonly route?: string\n /** 0.6.0 \u8D77\uFF1A\u901A\u8FC7\u9010\u5B57\u4F9D\u636E\u6821\u9A8C\u3001\u771F\u7684\u8FDB\u5165\u6210\u54C1\u7684\u6761\u76EE\u6570\u3002 */\n readonly itemCount?: number\n /** 0.6.0 \u8D77\uFF1A\u88AB\u4E22\u6389\u7684\u6761\u76EE\uFF08\u5F15\u6587\u5BF9\u4E0D\u4E0A\u539F\u8BDD / \u8D85\u4E0A\u9650 / \u8D85\u7BC7\u5E45\u9884\u7B97\uFF09\u3002 */\n readonly dropped?: readonly OptimizeDropped[]\n /** 0.6.0 \u8D77\uFF1A\u5BBF\u4E3B\u7ED9\u7684\u8B66\u544A\uFF08\u622A\u65AD\u3001\u5FFD\u7565\u7684 op\u3001\u9884\u7B97\u964D\u7EA7\u2026\u2026\uFF09\u3002 */\n readonly warnings?: readonly string[]\n /** 0.6.0 \u8D77\uFF1Atrue = \u964D\u7EA7\u8DEF\u5F84\uFF08\u6A21\u578B\u6CA1\u6309 JSON \u5951\u7EA6\u8F93\u51FA\uFF0C\u6574\u6BB5\u7167\u6536\uFF0C\u672A\u505A\u4F9D\u636E\u6821\u9A8C\uFF09\u3002 */\n readonly fallback?: boolean\n /** 0.6.0 \u8D77\uFF1Atrue = \u7A7A\u4EA7\u51FA\u540E\u91CD\u8BD5\u8FC7\u4E00\u6B21\u3002 */\n readonly retried?: boolean\n /** 0.6.0 \u8D77\uFF1A'custom' = \u7528\u4E86\u8BBE\u7F6E\u9875\u91CC\u90A3\u4EFD\u63D0\u793A\u8BCD\uFF1B'builtin' = \u5185\u7F6E\u90A3\u4EFD\u3002 */\n readonly promptSource?: string\n /** 0.6.0 \u8D77\uFF1A\u88AB rewrite \u8986\u76D6\u6389\u7684\u539F\u8BDD\u5B57\u7B26\u6570\u3002 */\n readonly rewrittenChars?: number\n}\n\n/** \u628A\u5BBF\u4E3B\u56DE\u7684 `dropped` \u6536\u7A84\u6210\u5B89\u5168\u5F62\u72B6\uFF08\u54CD\u5E94\u4F53\u6309\u4E0D\u53EF\u4FE1\u8F93\u5165\u5904\u7406\uFF09\u3002 */\nfunction droppedOf(value: unknown): readonly OptimizeDropped[] {\n if (!Array.isArray(value)) return []\n const out: OptimizeDropped[] = []\n for (const entry of value) {\n if (typeof entry !== 'object' || entry === null) continue\n const row = entry as Record<string, unknown>\n out.push({\n id: typeof row.id === 'string' ? row.id : '',\n kind: typeof row.kind === 'string' ? row.kind : '',\n reason: typeof row.reason === 'string' ? row.reason : '',\n })\n }\n return out\n}\n\n/** \u628A\u5BBF\u4E3B\u56DE\u7684 `warnings` \u6536\u7A84\u6210\u5B57\u7B26\u4E32\u6570\u7EC4\u3002 */\nfunction warningsOf(value: unknown): readonly string[] {\n if (!Array.isArray(value)) return []\n return value.filter((entry): entry is string => typeof entry === 'string')\n}\n\n/**\n * \u8BF7\u5BBF\u4E3B\u534A\u8DD1\u4E00\u6B21\u72EC\u7ACB\u4F18\u5316\u3002\n *\n * \u4E3A\u4EC0\u4E48\u662F\u4E00\u6B21 HTTP \u5F80\u8FD4\uFF1A\u51FA\u7F51\u8BF7\u6C42\u7531\u5BBF\u4E3B\u7684\u6A21\u578B\u9002\u914D\u5668\u53D1\u51FA\uFF0C\u6D4F\u89C8\u5668\u4FA7\u78B0\u4E0D\u5230\u6A21\u578B\u8DEF\u7531\uFF1B\n * \u5BBF\u4E3B <-> \u5BA2\u6237\u7AEF\u4E4B\u95F4\u6CA1\u6709\u522B\u7684\u53D7\u652F\u6301\u901A\u9053\uFF08\u4E0E WestFox \u7684\u63D2\u4EF6\u540C\u6784\uFF09\u3002\n * @param text - \u8F93\u5165\u6846\u91CC\u7684\u539F\u6587\u3002\n * @param tier - \u5F3A\u5EA6\u6863\u4F4D\u3002\n * @returns \u4F18\u5316\u7ED3\u679C\uFF1B\u7F51\u7EDC\u5C42\u5931\u8D25\u4E5F\u5F52\u4E00\u6210 `ok: false` \u800C\u4E0D\u629B\u3002\n */\nexport async function optimizeDraft(text: string, tier: string): Promise<OptimizeOutcome> {\n const body = text.trim()\n if (body === '') return { ok: false, error: '\u8F93\u5165\u6846\u662F\u7A7A\u7684\uFF0C\u5148\u5199\u70B9\u4EC0\u4E48\u518D\u4F18\u5316' }\n let response: Response\n try {\n response = await fetch(OPTIMIZER_API_PATH, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ text: body, tier }),\n })\n } catch (error) {\n return { ok: false, error: `\u8FDE\u4E0D\u4E0A\u5BBF\u4E3B\u534A\u7684\u4F18\u5316\u63A5\u53E3\uFF1A${error instanceof Error ? error.message : String(error)}` }\n }\n if (!response.ok) {\n return { ok: false, error: `\u5BBF\u4E3B\u534A\u8FD4\u56DE HTTP ${response.status}\uFF08\u63D2\u4EF6\u53EF\u80FD\u8FD8\u6CA1\u91CD\u542F\u751F\u6548\uFF09` }\n }\n let payload: unknown\n try {\n payload = await response.json()\n } catch {\n return { ok: false, error: '\u5BBF\u4E3B\u534A\u8FD4\u56DE\u7684\u4E0D\u662F JSON' }\n }\n const record = (typeof payload === 'object' && payload !== null ? payload : {}) as Record<string, unknown>\n const retried = record.retried === true\n if (record.ok !== true) {\n const message = typeof record.error === 'string' && record.error !== '' ? record.error : '\u4F18\u5316\u5931\u8D25'\n return { ok: false, error: message, retried }\n }\n const optimized = typeof record.text === 'string' ? record.text.trim() : ''\n if (optimized === '') return { ok: false, error: '\u6A21\u578B\u6CA1\u6709\u4EA7\u51FA\u4EFB\u4F55\u5185\u5BB9', retried }\n const route = `${String(record.provider ?? '')}/${String(record.model ?? '')}`\n return {\n ok: true,\n text: optimized,\n route,\n itemCount: typeof record.itemCount === 'number' ? record.itemCount : 0,\n dropped: droppedOf(record.dropped),\n warnings: warningsOf(record.warnings),\n fallback: record.fallback === true,\n retried,\n promptSource: typeof record.promptSource === 'string' ? record.promptSource : '',\n rewrittenChars: typeof record.rewrittenChars === 'number' ? record.rewrittenChars : 0,\n }\n}\n", "/** \u8F93\u5165\u6846\u62E6\u622A\u5668\uFF1A\u63A5\u7BA1 Enter \u5BB6\u65CF\u952E\u4F4D\uFF08\u53D1\u9001/\u6362\u884C\uFF09\u4E0E\u53F3\u952E\u83DC\u5355\u3002\n * \u4E0E React \u65E0\u5173\uFF1A\u57FA\u4E8E\u300C\u6355\u83B7\u9636\u6BB5 + \u76EE\u6807\u9650\u5B9A + \u5408\u6210\u56DE\u653E\u300D\u7684\u62E6\u622A\u6A21\u578B\u3002\n *\n * \u952E\u4F4D\u89C4\u5219\uFF08\u603B\u62EC\uFF09\uFF1A\n * - \u8BB0\u5F55\u76EE\u6807\u53EA\u5728\u4E3B\u804A\u5929\u8F93\u5165\u6846 [data-composer-input] \u5185\uFF1B\n * - IME \u7EC4\u5408\u671F\u95F4\uFF08isComposing / keyCode 229\uFF09\u4E00\u5F8B\u653E\u884C\uFF0C\u7EDD\u4E0D\u5F71\u54CD\u4E2D\u6587\u8F93\u5165\uFF1B\n * - '/' '@' \u89E6\u53D1\u5668\u83DC\u5355\u6216\u4EFB\u4F55\u8F93\u5165\u6846 overlay \u6253\u5F00\u65F6\u653E\u884C Enter\uFF0C\u8BA9\u83DC\u5355\u4EF2\u88C1\u4F18\u5148\uFF1B\n * - \u547D\u4E2D\u300C\u53D1\u9001\u952E\u4F4D\u300D\u2192 \u56DE\u653E\u5E26 Ctrl \u52A0\u901F\u8BED\u4E49\u4E4B\u5916\u7684\u666E\u901A Enter\uFF08\u8D70\u5B98\u65B9\u63D0\u4EA4\u7BA1\u7EBF\uFF09\uFF1B\n * - \u547D\u4E2D\u300C\u6362\u884C\u952E\u4F4D\u300D\u2192 \u56DE\u653E Shift+Enter\uFF08\u5B98\u65B9\u6362\u884C\u7BA1\u7EBF\uFF09\uFF1B\n * - Ctrl+Enter / Meta+Enter \u82E5\u672A\u88AB\u7ED1\u5B9A\uFF0C\u5219\u56DE\u653E\u539F\u7EC4\u5408\uFF0C\u4FDD\u7559\u5B98\u65B9\u300C\u52A0\u901F\u63D0\u4EA4\u300D\u884C\u4E3A\uFF1B\n * - \u5176\u4F59 Enter \u5BB6\u65CF\u7EC4\u5408\uFF1A\u6D88\u8017\u4F46\u4E0D\u52A8\u4F5C\uFF08\u7528\u6237\u663E\u5F0F\u53D6\u6D88\u7684\u539F\u751F\u8BED\u4E49\uFF09\u3002\n *\n * \u5173\u952E\u5B88\u536B\uFF1A\u5408\u6210\u56DE\u653E\u4E8B\u4EF6\u4E5F\u5FC5\u987B\u7ECF\u8FC7 window \u6355\u83B7\u76D1\u542C\u5668\uFF0C\u56E0\u6B64\u56DE\u653E\u671F\u95F4\u7528\n * \u540C\u6B65\u6807\u5FD7\u8DF3\u8FC7\u81EA\u8EAB\u62E6\u622A\uFF0C\u5426\u5219\u53D1\u9001/\u6362\u884C\u56DE\u653E\u4F1A\u65E0\u9650\u81EA\u89E6\u53D1\u3002\n */\nimport {\n chordToInit, encodeChord, isEnterFamily, type ChordEvent,\n} from './chords.ts'\nimport { applyPromptsForSend, sendButtonOf } from './quick-commands.ts'\nimport { activeSections, type ComposerUxSettings, type MenuState, type QuickPrompt } from '../settings-contract.ts'\n\nexport interface InterceptorDeps {\n /** \u540C\u6B65\u8BFB\u53D6\u5F53\u524D\u89E3\u6790\u540E\u7684\u8BBE\u7F6E\uFF08\u62E6\u622A\u5668\u975E React \u73AF\u5883\uFF09\u3002 */\n readonly settings: () => ComposerUxSettings\n /**\n * \u540C\u6B65\u8BFB\u53D6**\u8FD9\u4E00\u6B21\u53D1\u9001\u8981\u9644\u52A0\u7684\u6761\u76EE**\uFF08\u8DE8\u5206\u7C7B\uFF09\u3002\n *\n * 0.3.0 \u8D77\u5FEB\u6377\u6307\u4EE4\u5B58\u5728 quick-prompts.json \u91CC\uFF0C\u4E0D\u518D\u5C5E\u4E8E\u8BBE\u7F6E\u6587\u6863\uFF0C\u6240\u4EE5\u8FD9\u91CC\u5355\u72EC\u8981\u4E00\u4E2A\n * \u53D6\u503C\u51FD\u6570\u3002\u300C\u4EC5\u9996\u6B21\u300D\u7684\u6761\u76EE\u662F\u5426\u7B97\u5728\u5185\uFF0C\u7531\u8C03\u7528\u65B9\u5728\u8FD9\u4E2A\u51FD\u6570\u91CC\u7ED3\u5408\u300C\u4F1A\u8BDD\u662F\u5426\u8FD8\u6CA1\u6709\n * \u6D88\u606F\u300D\u51B3\u5B9A\uFF08\u89C1 client.tsx \u7684 `appendBatchForSend(book, currentBlankSession())`\uFF09\u2014\u2014\n * \u62E6\u622A\u5668\u53EA\u8D1F\u8D23\u628A\u62FF\u5230\u7684\u8FD9\u4E00\u6279\u9644\u52A0\u4E0A\u53BB\u3002\n */\n readonly promptsForSend: () => readonly QuickPrompt[]\n /** \u6253\u5F00 / \u5173\u95ED\u53F3\u952E\u83DC\u5355\u3002 */\n readonly setMenu: (state: MenuState | null) => void\n /** \u81EA\u5B9A\u4E49\u83DC\u5355\u5F53\u524D\u662F\u5426\u6253\u5F00\uFF08\u539F\u751F\u83DC\u5355\u6A21\u5F0F\u4E0B\u9700\u8981\u6E05\u6389\uFF09\u3002 */\n readonly menuOpen: () => boolean\n}\n\nconst INPUT_SELECTOR = '[data-composer-input]'\nconst OVERLAY_SELECTOR = '[data-trigger-menu], [data-conversation-composer-overlay]'\n\n/** \u76EE\u6807\u662F\u5426\u843D\u5728\u4E3B\u804A\u5929\u8F93\u5165\u6846\u53CA\u5176\u5185\u90E8\u3002 */\nfunction findComposerRoot(target: EventTarget | null): HTMLElement | null {\n if (!(target instanceof Element)) return null\n return target.closest<HTMLElement>(INPUT_SELECTOR)\n}\n\n/** \u89E6\u53D1\u5668\u83DC\u5355\uFF08'/' '@'\uFF09\u6216\u8F93\u5165\u6846 overlay \u662F\u5426\u6253\u5F00\u3002 */\nfunction overlayOpen(): boolean {\n return document.querySelector(OVERLAY_SELECTOR) !== null\n}\n\n/** \u56DE\u653E\u8FDB\u884C\u4E2D\u6807\u5FD7\uFF1A\u5408\u6210\u4E8B\u4EF6\u56DE\u5230\u6355\u83B7\u76D1\u542C\u5668\u65F6\u8DF3\u8FC7\u81EA\u8EAB\u62E6\u622A\u3002 */\nlet replaying = false\n\n/** \u5B98\u65B9\u53D1\u9001\u6309\u94AE\u7684\u300C\u5148\u5199\u56DE\u3001\u518D\u91CD\u653E\u300D\u6807\u5FD7\uFF08\u907F\u514D\u5408\u6210\u70B9\u51FB\u88AB\u81EA\u5DF1\u518D\u62E6\u4E00\u6B21\uFF09\u3002 */\nlet replayingSendClick = false\n\n/** \u53F3\u952E\u65F6\u9884\u8BFB\u6210\u529F\u7684\u526A\u8D34\u677F\u6587\u672C\u7F13\u5B58\uFF08null = \u672A\u9884\u8BFB/\u9884\u8BFB\u5931\u8D25\uFF09\u3002 */\nlet pasteCache: string | null = null\n\n/** \u5728\u53F3\u952E\u624B\u52BF\u91CC\u53D1\u8D77\u4E00\u6B21\u9759\u9ED8\u9884\u8BFB\uFF1A\u6388\u6743\u6D6E\u7A97\u6B64\u523B\u51FA\u73B0\uFF0C\u7528\u6237\u987A\u624B\u70B9\u4E00\u6B21\u5373\u53EF\u3002 */\nfunction prefetchClipboard(): void {\n pasteCache = null\n const readText = (navigator as Navigator & { clipboard?: { readText?: () => Promise<string> } }).clipboard?.readText\n if (typeof readText !== 'function') return\n readText.call(navigator.clipboard).then(\n (text: string) => { pasteCache = text },\n () => { pasteCache = null },\n )\n}\n\n/** \u5411\u8F93\u5165\u6846\u6839\u5143\u7D20\u6D3E\u53D1\u5408\u6210\u6309\u952E\uFF08\u89E6\u53D1 Lexical \u81EA\u8EAB\u952E\u76D8\u7BA1\u7EBF\uFF09\u3002 */\nfunction dispatchKey(root: HTMLElement, init: KeyboardEventInit): void {\n replaying = true\n try {\n root.dispatchEvent(new KeyboardEvent('keydown', init))\n } finally {\n replaying = false\n }\n}\n\n/** \u662F\u5426\u8FDB\u5165 IME \u7EC4\u5408\uFF08\u5408\u6210\u4E8B\u4EF6\u9700\u4E0E\u771F\u5B9E\u6309\u952E\u8D70\u540C\u4E00\u5B88\u536B\uFF09\u3002 */\nfunction composing(event: KeyboardEvent): boolean {\n // oxlint-disable-next-line typescript/no-deprecated\n return event.isComposing || event.keyCode === 229\n}\n\n/** \u5B89\u88C5\u4E24\u4E2A\u6355\u83B7\u9636\u6BB5\u62E6\u622A\u5668\uFF1B\u8FD4\u56DE\u5378\u8F7D\u5668\u3002 */\nexport function installInterceptors(deps: InterceptorDeps): () => void {\n const onKeyDown = (event: KeyboardEvent): void => {\n if (replaying) return\n // \u300C\u952E\u4F4D\u300D\u680F\uFF08\u6216\u603B\u5F00\u5173\uFF09\u5173\u7740\u65F6\u5B8C\u5168\u4E0D\u4ECB\u5165\uFF1AEnter \u5BB6\u65CF\u6309 DSH \u539F\u751F\u884C\u4E3A\u8D70\u3002\n if (!activeSections(deps.settings()).keys) return\n const root = findComposerRoot(event.target)\n if (root === null) return\n if (composing(event)) return\n const chord = encodeChord(event as unknown as ChordEvent)\n if (!isEnterFamily(chord)) return\n // \u83DC\u5355/overlay \u6253\u5F00\u65F6\uFF0CEnter \u8981\u7ED9\u83DC\u5355\u4EF2\u88C1\uFF08\u8865\u5168\u9009\u62E9\u3001\u5F39\u5C42\u5173\u95ED\uFF09\u8BA9\u8DEF\u3002\n if (overlayOpen()) return\n\n const settings = deps.settings()\n const gesture = chord === settings.sendKey\n ? 'send'\n : chord === settings.newlineKey\n ? 'newline'\n : (chord === 'Ctrl+Enter' || chord === 'Meta+Enter') ? 'accelerated'\n : 'none'\n\n event.preventDefault()\n event.stopPropagation()\n // \u957F\u6309\u8FDE\u53D1\uFF1A\u6D88\u8017\u4E00\u6B21\u5373\u53EF\uFF08\u53D1\u9001\u9632\u673A\u67AA\u95E8\u4E0E\u5B98\u65B9\u4E00\u81F4\uFF0C\u6362\u884C\u8FDE\u53D1\u65E0\u610F\u4E49\uFF09\u3002\n if (event.repeat) return\n\n if (gesture === 'send') {\n // \u53D1\u9001\u65F6\u9644\u52A0\u6761\u76EE\uFF1A\u5148\u628A promptsForSend() \u7ED9\u51FA\u7684\u90A3\u4E00\u6279\u5199\u56DE\u7F16\u8F91\u5668\u672B\u5C3E\uFF0C\u518D\u56DE\u653E\u53D1\u9001\n // \u624B\u52BF \u2014\u2014 \u5B98\u65B9\u624B\u52BF\u7167\u65E7\uFF08\u542B\u8FD0\u884C\u4E2D\u300C\u6392\u961F / \u6253\u65AD\u300D\u7684\u5224\u5B9A\uFF09\uFF0C\u672C\u63D2\u4EF6\u4E0D\u505A\u7B2C\u4E8C\u5957\u5224\u65AD\u3002\n // \u539F\u6587\u4E3A\u7A7A\u65F6 applyPromptsForSend \u8FD4\u56DE false\uFF0C\u4E00\u5207\u7167\u65E7\u3002\n // \u26A0\uFE0F \u8FD9\u4E00\u6279\u91CC\u300C\u8BE5\u6709\u8C01\u300D\u5DF2\u7531 promptsForSend()\uFF08= appendBatchForSend + blank\uFF09\u5B9A\u597D\uFF0C\n // \u5199\u56DE\u8FD9\u4E00\u6B65\u4E0D\u5F97\u518D\u6309\u63D2\u5165\u6A21\u5F0F\u8FC7\u6EE4\uFF080.4.0 \u5728\u8FD9\u91CC\u4E22\u8FC7\u300C\u4EC5\u9996\u6B21\u300D\uFF09\u3002\n applyPromptsForSend(deps.promptsForSend())\n dispatchKey(root, chordToInit('Enter'))\n } else if (gesture === 'newline') {\n dispatchKey(root, chordToInit('Shift+Enter'))\n } else if (gesture === 'accelerated') {\n dispatchKey(root, chordToInit('Ctrl+Enter'))\n }\n // gesture === 'none'\uFF1A\u6D88\u8017\u4F46\u65E0\u52A8\u4F5C\u3002\n }\n\n const onContextMenu = (event: MouseEvent): void => {\n const root = findComposerRoot(event.target)\n if (root === null) return\n const settings = deps.settings()\n // \u300C\u53F3\u952E\u83DC\u5355\u300D\u680F\uFF08\u6216\u603B\u5F00\u5173\uFF09\u5173\u7740\u65F6\u672C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u4ECB\u5165 \u2014\u2014 \u4E0E\u4E0B\u9762\u7684\u300C\u5B98\u65B9\u300D\u6863\u540C\u4E00\u6761\u51FA\u53E3\u3002\n if (!activeSections(settings).menu) return\n const mode = settings.menuMode\n // \u5B98\u65B9\u6863\uFF1A\u672C\u63D2\u4EF6**\u5B8C\u5168\u4E0D\u4ECB\u5165** \u2014\u2014 \u65E2\u4E0D preventDefault \u4E5F\u4E0D stopImmediatePropagation\uFF0C\n // DSH \u5B98\u65B9\u4E0E\u5176\u5B83\u63D2\u4EF6\u81EA\u5DF1\u7684\u53F3\u952E\u5904\u7406\u539F\u6837\u751F\u6548\u3002\uFF08DSH \u5B98\u65B9\u8F93\u5165\u6846\u672C\u8EAB\u6CA1\u6709\u53F3\u952E\u83DC\u5355\uFF0C\n // \u6240\u4EE5\u901A\u5E38\u770B\u5230\u7684\u5C31\u662F\u6D4F\u89C8\u5668\u83DC\u5355\u3002\uFF09\u5DF2\u6253\u5F00\u7684\u81EA\u5B9A\u4E49\u83DC\u5355\u7531 client.tsx \u5728\u5207\u6863\u65F6\u5173\u6389\u3002\n if (mode === 'official') return\n // \u6D4F\u89C8\u5668\u6863\uFF1A\u4E0D\u8BA9\u7B2C\u4E09\u65B9\u63D2\u4EF6\uFF08\u5982 dsh-paste-input-plus \u7684\u300C\u53EA\u6709\u590D\u5236\u300D\u83DC\u5355\uFF09\u5403\u6389\n // contextmenu\u2014\u2014\u6211\u4EEC\u6392\u5728 capture \u9636\u6BB5\u5148\u6267\u884C\uFF0CstopImmediatePropagation \u540E\n // \u4E8B\u4EF6\u5230\u4E0D\u4E86 bubble \u9636\u6BB5\u7684\u63D2\u4EF6\u76D1\u542C\u5668\uFF1B\u4F46\u4E0D preventDefault\uFF0C\u6D4F\u89C8\u5668\u539F\u751F\u83DC\u5355\u7167\u5E38\u51FA\u73B0\u3002\n if (mode === 'browser') {\n if (deps.menuOpen()) deps.setMenu(null)\n event.stopImmediatePropagation()\n event.stopPropagation()\n return\n }\n // \u81EA\u5B9A\u4E49\u6863\uFF1A\u4E24\u4EF6\u4E8B\u90FD\u505A\u2014\u2014preventDefault \u6389\u6D4F\u89C8\u5668\u83DC\u5355\uFF08\u6539\u7531\u672C\u63D2\u4EF6\u63A5\u7BA1\uFF09\uFF0C\n // \u5E76\u4E14\u548C\u300C\u6D4F\u89C8\u5668\u300D\u6863\u4E00\u6837 stopImmediatePropagation \u6321\u4F4F\u540C\u4E00\u5C42\u91CC\u5176\u5B83\u63D2\u4EF6\u7684\u6355\u83B7\u76D1\u542C\u3002\n // \u5426\u5219\u4E24\u8FB9\u4F1A\u5404\u5F39\u4E00\u4E2A\u83DC\u5355\u3002\u62E6\u5230\u7684\u662F**\u522B\u7684\u63D2\u4EF6**\uFF0C\u4E0D\u5F71\u54CD\u6211\u4EEC\u81EA\u5DF1\uFF1A\u672C\u63D2\u4EF6\u7684\u83DC\u5355\u7EC4\u4EF6\n // \u53EA\u76D1\u542C pointerdown / keydown / scroll / resize\uFF08\u89C1 ContextMenuHost\uFF09\u3002\n event.preventDefault()\n event.stopImmediatePropagation()\n event.stopPropagation()\n const selection = window.getSelection()\n const hasSelection = selection !== null\n && !selection.isCollapsed\n && selection.anchorNode !== null\n && root.contains(selection.anchorNode)\n deps.setMenu({ x: event.clientX, y: event.clientY, hasSelection })\n // \u8D81\u7740\u53F3\u952E\u7684\u7528\u6237\u624B\u52BF\u8FD8\u5728\uFF0C\u9759\u9ED8\u9884\u8BFB\u526A\u8D34\u677F\uFF08\u6388\u6743\u6D6E\u7A97\u6B64\u523B\u5F39\u51FA\uFF0C\u70B9\u4E00\u6B21\u5373\u56FA\u5316\uFF09\u3002\n prefetchClipboard()\n }\n\n /**\n * \u5B98\u65B9\u300C\u53D1\u9001\u300D\u6309\u94AE\u4E0A\u7684\u6761\u76EE\u9644\u52A0\u3002\n *\n * \u5B98\u65B9\u4E3B\u6309\u94AE\u8D70\u7684\u662F\u5305\u5185\u90E8\u7684 keyboard.submit\uFF08\u6CA1\u6709\u5BF9\u5916\u7684\u62E6\u622A\u94A9\u5B50\uFF09\uFF0C\u6240\u4EE5\u53EA\u80FD\u5728\n * \u6355\u83B7\u9636\u6BB5\u8BA4\u4E0B\u8FD9\u6B21\u70B9\u51FB\u3002\u8BA4\u4E0B\u4E4B\u540E\u4E0D\u53BB\u81EA\u5DF1\u8C03 submit \u2014\u2014 \u800C\u662F\u5148\u628A\u9644\u52A0\u5185\u5BB9\u5199\u56DE\u7F16\u8F91\u5668\u3001\n * \u518D\u7528\u540C\u4E00\u4E2A\u6309\u94AE\u91CD\u653E\u4E00\u6B21\u70B9\u51FB\uFF0C\u8BA9\u5B98\u65B9\u7684 primarySubmitMode\uFF08\u53D1\u9001 / \u6392\u961F / \u6253\u65AD\uFF09\n * \u539F\u6837\u751F\u6548\u3002\n *\n * \u4E24\u6761\u5FC5\u987B\u5B88\u4F4F\u7684\u7EAA\u5F8B\uFF080.2.0 \u5728\u8FD9\u4E24\u5904\u90FD\u51FA\u8FC7\u4E8B\uFF09\uFF1A\n * 1. \u91CD\u653E\u7684\u5FC5\u987B\u662F `sendButtonOf()` \u8FD4\u56DE\u7684**\u771F <button>**\uFF0C\u4E0D\u80FD\u662F event.target\n * \u2014\u2014 \u70B9\u5728\u5706\u5F62\u6309\u94AE\u7684\u89C6\u89C9\u4E2D\u5FC3\u65F6 target \u662F\u5185\u90E8\u7684 svg\uFF0Csvg \u6CA1\u6709 `.click()`\uFF0C\n * \u4F1A\u629B TypeError\uFF0C\u7ED3\u679C\u5C31\u662F\u300C\u5DF2\u63D2\u5165\u4F46\u6CA1\u53D1\u9001\u300D\u3002\n * 2. \u53EA\u6709\u5728\u786E\u8BA4\u80FD\u91CD\u653E\u4E4B\u540E\u624D preventDefault/stopPropagation\uFF1B\u62FF\u4E0D\u5230\u6309\u94AE\u5C31\u76F4\u63A5\n * \u653E\u884C\uFF0C\u7EDD\u4E0D\u628A\u7528\u6237\u8FD9\u6B21\u70B9\u51FB\u541E\u6389\u3002\n */\n const onClickSend = (event: MouseEvent): void => {\n if (replayingSendClick) return\n const button = sendButtonOf(event.target)\n if (button === null) return\n if (!applyPromptsForSend(deps.promptsForSend())) return\n event.preventDefault()\n event.stopPropagation()\n replayingSendClick = true\n try {\n button.click()\n } finally {\n replayingSendClick = false\n }\n }\n\n window.addEventListener('keydown', onKeyDown, true)\n window.addEventListener('contextmenu', onContextMenu, true)\n window.addEventListener('click', onClickSend, true)\n return () => {\n window.removeEventListener('keydown', onKeyDown, true)\n window.removeEventListener('contextmenu', onContextMenu, true)\n window.removeEventListener('click', onClickSend, true)\n }\n}\n\n/** \u53F3\u952E\u83DC\u5355\u52A8\u4F5C id\uFF08\u4E0E MENU_ITEMS \u5BF9\u5E94\uFF09\u3002 */\nexport type MenuActionId = 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'delete' | 'selectAll'\n\nexport interface MenuActionResult {\n readonly ok: boolean\n readonly message?: string\n}\n\n/** \u5728\u5F53\u524D\u8F93\u5165\u6846\u4E0A\u6267\u884C\u4E00\u4E2A\u53F3\u952E\u83DC\u5355\u52A8\u4F5C\u3002 */\nexport async function runMenuAction(id: MenuActionId): Promise<MenuActionResult> {\n const root = document.querySelector<HTMLElement>(INPUT_SELECTOR)\n if (root === null) return { ok: false, message: '\u627E\u4E0D\u5230\u8F93\u5165\u6846' }\n if (!document.activeElement || !root.contains(document.activeElement)) {\n if (root.isConnected) {\n root.focus({ preventScroll: true })\n }\n }\n switch (id) {\n case 'undo':\n dispatchKey(root, chordToInit('Ctrl+Z'))\n return { ok: true }\n case 'redo':\n dispatchKey(root, chordToInit('Ctrl+Y'))\n return { ok: true }\n case 'copy':\n return { ok: document.execCommand('copy') }\n case 'cut':\n return { ok: document.execCommand('cut') }\n case 'delete':\n return { ok: document.execCommand('delete') }\n case 'selectAll':\n return { ok: document.execCommand('selectAll') }\n case 'paste':\n return pasteText(root)\n }\n}\n\n/** \u5E26\u8D85\u65F6\u7684 Promise\uFF08\u7528\u4E8E\u7B49\u5F85\u526A\u8D34\u677F\u6388\u6743\u5F39\u7A97\uFF09\u3002 */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => { reject(new Error('clipboard-read timeout')) }, ms)\n promise.then(\n (value) => { clearTimeout(timer); resolve(value) },\n (error: unknown) => { clearTimeout(timer); reject(error) },\n )\n })\n}\n\nfunction isClipboardTimeout(error: unknown): boolean {\n return error instanceof Error && error.message === 'clipboard-read timeout'\n}\n\n/** \u5F53\u524D\u6D4F\u89C8\u5668\u662F\u4E0D\u662F Firefox\uFF08\u5B83\u5BF9\u8BFB\u526A\u8D34\u677F\u6709\u989D\u5916\u7684\u786E\u8BA4\u5F39\u7A97\uFF0C\u89C1 FIREFOX_TIP\uFF09\u3002 */\nfunction isFirefox(): boolean {\n return typeof navigator !== 'undefined' && /Firefox\\//.test(navigator.userAgent)\n}\n\n/**\n * Firefox \u7684\u8BFB\u526A\u8D34\u677F\u786E\u8BA4\u5F39\u7A97\u8BF4\u660E\u3002\n *\n * \u5B9E\u6D4B\u66F4\u6B63\uFF080.4.0\uFF0C\u7528\u6237\u5728 Firefox \u4E0A\u9A8C\u8FC7\uFF09\uFF1A\u8FD9\u4E2A\u5F39\u7A97**\u4E0D\u662F**\u6743\u9650\u9762\u677F\u3001\u4E5F**\u4E0D\u80FD**\u7528\n * `about:config` \u91CC\u7684\u9996\u9009\u9879\u5173\u6389\u2014\u2014\u5B83\u662F Firefox \u7684\u5B89\u5168\u673A\u5236\uFF1A\u7F51\u9875\u8BFB\u526A\u8D34\u677F\u8981\u5148\u5F39\u4E00\u4E2A\u53EA\u6709\n * \u300C\u7C98\u8D34(P)\u300D\u4E00\u9879\u7684\u4E34\u65F6\u5C0F\u7A97\uFF08\u7EA6 1 \u79D2\u540E\u624D\u53EF\u70B9\uFF09\uFF0C\u7528\u6237\u70B9\u4E86\u624D\u5B8C\u6210\u8BFB\u53D6\u3002\u6309 MDN \u7684\u8BF4\u660E\uFF0C\n * \u53EA\u6709\u6D4F\u89C8\u5668\u6269\u5C55\u51ED `clipboardRead` \u6743\u9650\u624D\u80FD\u514D\u6389\u5B83\uFF1BFirefox 147 \u8D77\u666E\u901A\u7F51\u9875\u8D70\u5B8C\u8FD9\u4E2A\u5F39\u7A97\n * \u4E5F\u53EF\u4EE5\u8BFB\u3002\u80FD\u9760\u6539\u8BBE\u7F6E\u514D\u6389\u5B83\u7684\u53EA\u6709 `dom.events.testing.asyncClipboard` \u8FD9\u7C7B**\u6D4B\u8BD5\u7528**\u5F00\u5173\uFF0C\n * \u90A3\u7B49\u4E8E\u5141\u8BB8\u4EFB\u4F55\u7F51\u7AD9\u9759\u9ED8\u8BFB\u526A\u8D34\u677F\uFF0C\u6211\u4EEC\u4E0D\u5728\u754C\u9762\u4E0A\u6559\u8FD9\u4E2A\u3002\n */\nconst FIREFOX_TIP = 'Firefox \u4E0D\u5141\u8BB8\u7F51\u9875\u9759\u9ED8\u8BFB\u526A\u8D34\u677F\uFF1A\u8BF7\u5728\u5F39\u51FA\u7684\u300C\u7C98\u8D34(P)\u300D\u5C0F\u7A97\u4E0A\u70B9\u4E00\u4E0B\uFF08\u7EA6 1 \u79D2\u540E\u624D\u53EF\u70B9\uFF0C\u8FD9\u662F Firefox \u7684\u5B89\u5168\u673A\u5236\uFF0C\u63D2\u4EF6\u5173\u4E0D\u6389\uFF09\uFF1B\u4E0D\u60F3\u591A\u8FD9\u4E00\u6B65\u5C31\u76F4\u63A5\u6309 Ctrl+V'\n\n/** \u7C98\u8D34\uFF1A\u8BFB\u526A\u8D34\u677F\u540E\u5728\u5149\u6807\u5904\u63D2\u5165\u7EAF\u6587\u672C\u3002\n * \u6D4F\u89C8\u5668\u5B89\u5168\u6A21\u578B\uFF1A\u5199\u526A\u8D34\u677F\uFF08\u590D\u5236/\u526A\u5207\uFF09\u514D\u6388\u6743\uFF0C\u8BFB\u526A\u8D34\u677F\uFF08\u7C98\u8D34\uFF09\u5FC5\u987B\u6388\u6743\uFF0C\n * \u4EFB\u4F55\u7F51\u9875\u90FD\u65E0\u6CD5\u7ED5\u8FC7\u3002Chrome / Edge \u662F**\u6309\u7AD9\u70B9**\u6388\u6743\uFF0C\u5141\u8BB8\u4E00\u6B21\u540E\u8BB0\u4F4F\u8BE5\u7AD9\u70B9\u3001\u4E4B\u540E\u9759\u9ED8\u53EF\u7528\uFF1B\n * Firefox \u6CA1\u6709\u8FD9\u79CD\u300C\u8BB0\u4F4F\u300D\uFF0C\u6BCF\u6B21\u8BFB\u90FD\u8981\u7528\u6237\u70B9\u4E00\u4E0B\u5B83\u81EA\u5DF1\u5F39\u7684\u300C\u7C98\u8D34(P)\u300D\u5C0F\u7A97\uFF08\u89C1 FIREFOX_TIP\uFF09\u3002\n * \u4F18\u5148\u4F7F\u7528\u53F3\u952E\u65F6\u9884\u8BFB\u7684\u7F13\u5B58\uFF08\u6388\u6743\u5DF2\u88AB\u70B9\u51FB\u8FC7\u4E00\u6B21\uFF0C\u65E0\u611F\uFF09\uFF0C\u5931\u8D25\u518D\u5B9E\u65F6\u8BFB\u53D6\u3002\n */\nasync function pasteText(root: HTMLElement): Promise<MenuActionResult> {\n const insertText = (text: string): MenuActionResult => {\n if (!document.activeElement || !root.contains(document.activeElement)) {\n root.focus({ preventScroll: true })\n }\n if (text === '') return { ok: true }\n return { ok: document.execCommand('insertText', false, text) }\n }\n // \u7F13\u5B58\u547D\u4E2D\uFF1A\u53F3\u952E\u65F6\u6388\u6743\u5DF2\u5B8C\u6210\uFF0C\u76F4\u63A5\u63D2\u5165\uFF08\u53EF\u80FD\u4E3A\u7A7A\u5B57\u7B26\u4E32\uFF0C\u6B64\u65F6\u8D70\u5B9E\u65F6\u8BFB\u53D6\uFF09\u3002\n if (pasteCache !== null && pasteCache !== '') {\n const text = pasteCache\n pasteCache = null\n return insertText(text)\n }\n if (typeof navigator === 'undefined' || navigator.clipboard === undefined\n || typeof navigator.clipboard.readText !== 'function') {\n return { ok: false, message: '\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u8BFB\u53D6\u526A\u8D34\u677F\uFF0C\u8BF7\u7528 Ctrl+V \u7C98\u8D34' }\n }\n // \u6743\u9650\u9884\u68C0\uFF1A\u5DF2\u88AB\u660E\u786E\u62D2\u7EDD\u65F6\u76F4\u63A5\u7ED9\u6062\u590D\u6307\u5F15\uFF08\u907F\u514D\u5047\u6B7B\u6216\u8BEF\u5BFC\uFF09\u3002\n const permissions = (navigator as {\n permissions?: { query?: (descriptor: { name: string }) => Promise<{ state: string }> }\n }).permissions\n if (permissions?.query) {\n try {\n const result = await permissions.query({ name: 'clipboard-read' })\n if (result.state === 'denied') {\n if (isFirefox()) return { ok: false, message: FIREFOX_TIP }\n return {\n ok: false,\n message: '\u6D4F\u89C8\u5668\u5DF2\u62D2\u7EDD\u526A\u8D34\u677F\u8BFB\u53D6\uFF1A\u70B9\u51FB\u5730\u5740\u680F\u5DE6\u4FA7\u56FE\u6807 \u2192 \u7AD9\u70B9\u8BBE\u7F6E \u2192 \u526A\u8D34\u677F \u2192 \u5141\u8BB8\uFF1B\u6216\u76F4\u63A5\u6309 Ctrl+V',\n }\n }\n } catch {\n // \u4E0D\u652F\u6301\u8BE5\u6743\u9650\u67E5\u8BE2\uFF1A\u7EE7\u7EED\u5C1D\u8BD5\u8BFB\u53D6\u3002\n }\n }\n let text: string\n try {\n // \u7B49\u5F85\u6388\u6743\u5F39\u7A97\u53EF\u80FD\u8F83\u4E45\uFF08\u8981\u7528\u6237\u70B9\u51FB\uFF09\uFF0C\u4E0D\u7528\u77ED\u8D85\u65F6\u8BEF\u62A5\u5931\u8D25\uFF1B15 \u79D2\u65E0\u54CD\u5E94\n // \u624D\u63D0\u793A\uFF0C\u907F\u514D\u83DC\u5355\u6C38\u4E45\u6302\u8D77\u3002\n text = await withTimeout(navigator.clipboard.readText(), 15000)\n } catch (error) {\n if (isFirefox()) {\n return { ok: false, message: FIREFOX_TIP }\n }\n if (isClipboardTimeout(error)) {\n return {\n ok: false,\n message: '\u7B49\u5F85\u6D4F\u89C8\u5668\u6388\u6743\u8D85\u65F6\uFF1A\u8BF7\u5728\u5F39\u51FA\u63D0\u793A\u4E2D\u9009\u62E9\u300C\u5141\u8BB8\u300D\uFF08\u82E5\u672A\u51FA\u73B0\uFF0C\u70B9\u5730\u5740\u680F\u5DE6\u4FA7\u56FE\u6807\u5F00\u542F\uFF09\uFF0C\u6216\u6309 Ctrl+V',\n }\n }\n return {\n ok: false,\n message: '\u672A\u83B7\u526A\u8D34\u677F\u8BFB\u53D6\u6388\u6743\uFF1A\u70B9\u51FB\u5730\u5740\u680F\u5DE6\u4FA7\u56FE\u6807 \u2192 \u7AD9\u70B9\u8BBE\u7F6E \u2192 \u526A\u8D34\u677F \u2192 \u5141\u8BB8\uFF1B\u6216\u76F4\u63A5\u6309 Ctrl+V \u7C98\u8D34',\n }\n }\n if (!document.activeElement || !root.contains(document.activeElement)) {\n root.focus({ preventScroll: true })\n }\n if (text === '') return { ok: true }\n return { ok: document.execCommand('insertText', false, text) }\n}\n", "/**\r\n * \u8BBE\u7F6E\u9762\u677F\u589E\u5F3A\uFF1A\u5BFC\u822A\u5217\u6EDA\u52A8\u6837\u5F0F + \u9762\u677F\u5C3A\u5BF8\u8C03\u6574\u624B\u67C4\u3002\r\n *\r\n * \u5B98\u65B9\u9762\u677F\u7ED3\u6784\uFF08ui-settings-general SettingsRoot\uFF09\uFF1A\r\n * .overlay\uFF08position:fixed; inset:0; **z-index:1000**\uFF09\r\n * \u251C\u2500\u2500 .mask\uFF08position:absolute; inset:0\uFF09\u2500\u2500 \u5168\u5C4F\u906E\u7F69\r\n * \u2514\u2500\u2500 [role=\"dialog\"][aria-modal=\"true\"] \u2500\u2500 .panel\uFF08position:relative; width:800; overflow:hidden\uFF09\r\n * \u251C\u2500\u2500 <nav> \u2500\u2500 \u6807\u9898 + navList\uFF08\u6761\u76EE\u8F83\u591A\u65F6\u6EA2\u51FA\uFF09\r\n * \u2514\u2500\u2500 <div> \u2500\u2500 header + .options\uFF08\u672C\u8EAB overflow-y:auto\uFF09\r\n *\r\n * \u26A0\uFE0F \u5C42\u53E0\u4E0A\u4E0B\u6587\u9677\u9631\uFF080.2.0 \u6574\u6BB5\u529F\u80FD\u56E0\u6B64\u5931\u6548\uFF0C\u52A1\u5FC5\u8BB0\u4F4F\uFF09\uFF1A\r\n * \u672C\u63D2\u4EF6\u80FD\u6302\u6D6E\u5C42\u7684\u4F4D\u7F6E\u53EA\u6709 `shell.overlay`\uFF0C\u800C\u5B83\u88AB\u5B98\u65B9\u5C01\u5728\r\n * `ui-layout` \u7684 `.overlayLayer { position:absolute; inset:0; z-index:20 }` \u91CC \u2014\u2014\r\n * `position` + `z-index` \u4F7F\u5B83**\u81EA\u6210\u5C42\u53E0\u4E0A\u4E0B\u6587**\uFF0C\u91CC\u9762\u7684\u5143\u7D20\u518D\u600E\u4E48\u628A z-index\r\n * \u5199\u6210 9998 \u4E5F**\u9003\u4E0D\u51FA\u53BB**\uFF0C\u6C38\u8FDC\u6392\u5728\u8BBE\u7F6E\u5F39\u7A97\uFF081000\uFF09\u4E0B\u9762\uFF0C\u88AB\u5168\u5C4F\u906E\u7F69\u5403\u6389\u9F20\u6807\u3002\r\n * \u6240\u4EE5\uFF1A**\u51E1\u662F\u7ED9\u8BBE\u7F6E\u5F39\u7A97\u505A\u6D6E\u5C42\uFF0C\u5FC5\u987B\u628A\u624B\u67C4\u6302\u8FDB\u9762\u677F\u5185\u90E8**\uFF08`createPortal` \u5230\r\n * panel\uFF09\uFF0C\u800C\u4E0D\u662F\u5728 shell.overlay \u91CC\u5BF9\u51C6\u5750\u6807\u753B\u3002\r\n */\r\nimport type { CSSProperties } from 'react'\r\n\r\n/** \u8BBE\u7F6E\u5BF9\u8BDD\u6846\u9009\u62E9\u5668\uFF08\u9762\u677F\u4E3A\u300C\u5E26 nav \u5B50\u5143\u7D20\u7684 aria-modal \u5BF9\u8BDD\u6846\u300D\uFF0C\u5728\u5E94\u7528\r\n * \u91CC\u552F\u4E00\uFF1A\u5176\u5B83\u5BF9\u8BDD\u6846\uFF08\u5BA1\u6279\u3001\u6A21\u578B\u7F16\u8F91\u5668\u7B49\uFF09\u4E0D\u4EE5 nav \u4E3A\u76F4\u63A5\u5B50\u5143\u7D20\uFF09\u3002 */\r\nexport const PANEL_SELECTOR = '[role=\"dialog\"][aria-modal=\"true\"]:has(> nav)'\r\n\r\n\r\n/** \u624B\u67C4\u5C42\u7C7B\u540D\uFF08\u7531\u4E0B\u65B9\u6CE8\u5165\u6837\u5F0F\u8868\u5B9A\u4E49\uFF09\u3002 */\r\nexport const RESIZE_LAYER_CLASS = 'dsh-ux-resize-layer'\r\n/** \u56DB\u8FB9\u63CF\u8FB9\uFF08\u7EAF\u89C6\u89C9\uFF0C\u4E0D\u5403\u6307\u9488\uFF09\u3002 */\r\nexport const RESIZE_OUTLINE_CLASS = 'dsh-ux-resize-outline'\r\n/** \u53EF\u62D6\u62FD\u7684\u8FB9\u3002 */\r\nexport const RESIZE_EDGE_CLASS = 'dsh-ux-resize-edge'\r\n/** \u53EF\u62D6\u62FD\u7684\u53F3\u4E0B\u89D2\u6293\u624B\u3002 */\r\nexport const RESIZE_GRIP_CLASS = 'dsh-ux-resize-grip'\r\n\r\n/** \u53EF\u62D6\u62FD\u7684\u4F4D\u7F6E\u3002 */\r\nexport type ResizeEdge = 'left' | 'right' | 'top' | 'bottom' | 'br'\r\n\r\n/** \u8FB9\u7684\u6293\u53D6\u5E26\u5BBD\uFF08\u53EF\u89C1\u63CF\u8FB9\u662F 1px\uFF0C\u8FD9 8px \u662F\"\u597D\u6293\"\u7684\u4F59\u91CF\uFF09\u3002 */\r\nconst BAND = 8\r\n/** \u8FB9\u6761\u4E24\u7AEF\u907F\u8BA9\u91CF\uFF0C\u8BA9\u5706\u89D2\u5904\u4E0D\u51FA\u73B0\u538B\u7EBF\u7684\u76F4\u89D2\u3002 */\r\nconst INSET = 14\r\n/** \u53F3\u4E0B\u89D2\u6293\u624B\u5C3A\u5BF8\u3002 */\r\nconst GRIP = 26\r\n\r\n/**\r\n * \u4E00\u6761\u624B\u67C4\u5728**\u9762\u677F\u5185\u90E8**\u7684\u7EDD\u5BF9\u5B9A\u4F4D\u76D2\u3002\r\n *\r\n * \u523B\u610F\u4E0D\u4F7F\u7528\u89C6\u53E3\u5750\u6807\uFF1A\u624B\u67C4\u662F\u9762\u677F\u7684\u5B50\u5143\u7D20\uFF08\u6302\u8FDB\u9762\u677F\u5185\u90E8\uFF09\uFF0C\u6240\u4EE5\u5B9A\u4F4D\u5168\u90E8\u76F8\u5BF9\r\n * \u9762\u677F\u672C\u8EAB \u2014\u2014 \u9762\u677F\u79FB\u52A8\u3001\u6EDA\u52A8\u3001\u6539\u5C3A\u5BF8\u90FD\u4F1A\u81EA\u52A8\u8DDF\u968F\uFF0C\u4E0D\u9700\u8981\u4EFB\u4F55\u91CD\u7B97\u6216\u8F6E\u8BE2\u3002\r\n * @param edge - \u8FB9\u6216\u53F3\u4E0B\u89D2\u3002\r\n * @returns \u8BE5\u624B\u67C4\u7684 CSS \u5B9A\u4F4D\u5C5E\u6027\u3002\r\n */\r\nexport function handleBox(edge: ResizeEdge): CSSProperties {\r\n switch (edge) {\r\n case 'left': return { left: 0, top: INSET, bottom: INSET, width: BAND, cursor: 'ew-resize' }\r\n case 'right': return { right: 0, top: INSET, bottom: INSET, width: BAND, cursor: 'ew-resize' }\r\n case 'top': return { top: 0, left: INSET, right: INSET, height: BAND, cursor: 'ns-resize' }\r\n case 'bottom': return { bottom: 0, left: INSET, right: INSET, height: BAND, cursor: 'ns-resize' }\r\n case 'br': return { right: 8, bottom: 8, width: GRIP, height: GRIP, cursor: 'nwse-resize' }\r\n }\r\n}\r\n\r\n/** \u56DB\u8FB9\u63CF\u8FB9\u5C42\uFF1A\u8D34\u7740\u9762\u677F\u5706\u89D2\u753B\u4E00\u5708 1px \u7EC6\u7EBF\uFF08\u7EAF\u89C6\u89C9\uFF0C`pointer-events: none`\uFF09\u3002 */\r\nexport const RESIZE_OUTLINE_STYLE: CSSProperties = {\r\n position: 'absolute',\r\n inset: 0,\r\n // \u8DDF\u968F\u9762\u677F\u81EA\u8EAB\u7684\u5706\u89D2\uFF08\u5B98\u65B9 .panel \u662F 32px\uFF09\u2014\u2014\u7528 inherit \u800C\u4E0D\u662F\u5199\u6B7B\u6570\u5B57\uFF0C\r\n // \u5B98\u65B9\u6539\u5706\u89D2\u65F6\u8FD9\u91CC\u81EA\u52A8\u8DDF\u4E0A\u3002\r\n borderRadius: 'inherit',\r\n border: '1px solid rgba(127, 127, 137, .28)',\r\n pointerEvents: 'none',\r\n}\r\n\r\n/**\r\n * \u5C3A\u5BF8\u624B\u67C4\u6837\u5F0F\u3002\r\n *\r\n * \u624B\u67C4\u5C42\u6302\u5728**\u8BBE\u7F6E\u9762\u677F\u5185\u90E8**\uFF08\u89C1\u6587\u4EF6\u5934\u7684\u5C42\u53E0\u4E0A\u4E0B\u6587\u8BF4\u660E\uFF09\uFF0C\u6240\u4EE5\u8FD9\u4E9B\u89C4\u5219\u91CC\u7684\r\n * \u5B9A\u4F4D\u4E00\u5F8B\u76F8\u5BF9\u9762\u677F\uFF1B`pointer-events` \u5728\u5C42\u4E0A\u5173\u6389\u3001\u53EA\u5728\u5177\u4F53\u624B\u67C4\u4E0A\u6253\u5F00\uFF0C\r\n * \u514D\u5F97\u6574\u5C42\u5403\u6389\u9762\u677F\u672C\u8EAB\u7684\u70B9\u51FB\u3002\r\n *\r\n * \u26A0\uFE0F 0.6.0 \u5220\u6389\u4E86\u8FD9\u91CC\u53E6\u4E00\u534A\u300C\u5BFC\u822A\u5217\u6EDA\u52A8\u300D\u6837\u5F0F\uFF08\u539F PANEL_CSS +\r\n * `html.dsh-ux-panel-scroll` \u95E8\u63A7\uFF09\uFF1ADSH 0.1.7 \u7684\u5B98\u65B9\u8BBE\u7F6E\u9875\u5DF2\u7ECF\u7ED9 `.navList`\r\n * \u81EA\u5E26 `overflow-y: auto`\uFF0C\u6211\u4EEC\u518D\u6CE8\u5165\u4E00\u5957\u5C31\u6210\u4E86\u91CD\u590D\u5B9E\u73B0\uFF0C\u6545\u6574\u9879\u79FB\u9664\u3002\r\n */\r\nconst RESIZE_CSS = `\r\n.${RESIZE_LAYER_CLASS} { position: absolute; inset: 0; pointer-events: none; }\r\n.${RESIZE_EDGE_CLASS}, .${RESIZE_GRIP_CLASS} {\r\n position: absolute;\r\n pointer-events: auto;\r\n background: transparent;\r\n border-radius: 6px;\r\n transition: background-color .12s ease, color .12s ease;\r\n touch-action: none;\r\n}\r\n.${RESIZE_EDGE_CLASS}:hover { background: rgba(127, 127, 137, .22); }\r\n.${RESIZE_EDGE_CLASS}[data-active=\"true\"] { background: rgba(127, 127, 137, .3); }\r\n.${RESIZE_GRIP_CLASS} {\r\n display: flex;\r\n align-items: flex-end;\r\n justify-content: flex-end;\r\n padding: 3px;\r\n color: rgba(127, 127, 137, .55);\r\n}\r\n.${RESIZE_GRIP_CLASS}:hover { color: rgba(127, 127, 137, .95); background: rgba(127, 127, 137, .16); }\r\n`\r\n\r\n/** \u6CE8\u5165\u5C3A\u5BF8\u624B\u67C4\u6837\u5F0F\u8868\uFF1B\u8FD4\u56DE\u5378\u8F7D\u5668\u3002 */\r\nexport function installPanelResizeStyle(): () => void {\r\n const tag = document.createElement('style')\r\n tag.dataset.plugin = 'dsh-composer-ux-panel'\r\n tag.textContent = RESIZE_CSS\r\n document.head.appendChild(tag)\r\n return () => {\r\n tag.remove()\r\n }\r\n}\r\n\r\n/** \u67E5\u8BE2\u5F53\u524D\u6253\u5F00\u7684\u8BBE\u7F6E\u5BF9\u8BDD\u6846\u3002 */\r\nexport function findSettingsPanel(): HTMLElement | null {\r\n return document.querySelector<HTMLElement>(PANEL_SELECTOR)\r\n}\r\n\r\n/** \u5C3A\u5BF8\u8303\u56F4\u94B3\u5236\uFF08\u4E0E host schema \u4E00\u81F4\uFF09\u3002 */\r\nexport function clampPanelWidth(width: number): number {\r\n return Math.max(560, Math.min(width, Math.max(800, window.innerWidth - 48)))\r\n}\r\n\r\nexport function clampPanelHeight(height: number): number {\r\n return Math.max(320, Math.min(height, Math.max(400, window.innerHeight - 48)))\r\n}\r\n\r\n/** \u6301\u4E45\u5316\u5C3A\u5BF8\uFF08\u5199\u5165\u8BBE\u7F6E\uFF1B\u5931\u8D25\u9759\u9ED8\u2014\u2014\u4E0B\u6B21\u6253\u5F00\u56DE\u9000\u9ED8\u8BA4\uFF09\u3002 */\r\nexport function persistPanelSize(\r\n width: number,\r\n height: number,\r\n setField: (field: string, value: boolean | number) => void,\r\n): void {\r\n setField('panelWidth', clampPanelWidth(width))\r\n setField('panelHeight', clampPanelHeight(height))\r\n}\r\n", "/**\n * \u8BBE\u7F6E\u9875\u6298\u53E0\u5361\u7247\u6837\u5F0F\u3002\n *\n * \u89C2\u611F\u5BF9\u9F50\u793E\u533A\u63D2\u4EF6 @linxin666/dsh-web-all \u7684 SettingsCard\uFF1A12px \u5706\u89D2\u3001\n * 1px \u63CF\u8FB9\uFF08hover \u53D8 --dsw-alias-label-dimmed\uFF09\u3001\u5C55\u5F00\u65F6\u6362\u5E95\u8272\u5E76\u663E\u793A\u5206\u9694\u7EBF\u3001\n * \u53F3\u4FA7 chevron \u65CB\u8F6C 180\u00B0\u3002\u7C7B\u540D\u7EDF\u4E00 dsh-ux- \u524D\u7F00\uFF0C\u907F\u514D\u4E0E\u5BBF\u4E3B CSS Modules \u51B2\u7A81\u3002\n */\n\nconst CARD_CSS = `\n.dsh-ux-card {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-3);\n border-radius: 12px;\n margin-bottom: 12px;\n transition: border-color .16s, background .16s;\n}\n.dsh-ux-card:hover { border-color: var(--dsw-alias-label-dimmed); }\n.dsh-ux-cardOpen {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n.dsh-ux-cardHeader {\n appearance: none;\n box-sizing: border-box;\n flex: 1;\n min-width: 0;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n background: 0 0;\n border: 0;\n border-radius: 12px;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n}\n.dsh-ux-cardHeader:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n/* \u6807\u9898\u884C = \u5DE6\u8FB9\"\u5C55\u5F00\"\u6309\u94AE\uFF08\u5360\u6EE1\u5269\u4F59\u5BBD\u5EA6\uFF09+ \u53F3\u8FB9\u4ECE\u5C5E\u63A7\u4EF6\u4E0E\u672C\u680F\u5F00\u5173\u3002\n \u4E0D\u80FD\u5728 <button> \u91CC\u585E\u6309\u94AE\uFF0C\u6240\u4EE5\u4E24\u8005\u662F\u5144\u5F1F\u8282\u70B9\u3002 */\n.dsh-ux-cardHeaderRow {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px;\n padding-right: 12px;\n}\n.dsh-ux-cardControls {\n align-items: center;\n display: inline-flex;\n flex: none;\n flex-wrap: wrap;\n gap: 8px;\n}\n/* \u6807\u9898\u884C\u91CC\u7684\"\u6587\u5B57 + \u5C0F\u5F00\u5173\"\uFF08\u5BFC\u822A\u6EDA\u52A8 / \u8FB9\u7F18\u7F29\u653E\uFF09\u3002 */\n.dsh-ux-miniToggle {\n align-items: center;\n color: var(--dsw-alias-label-secondary);\n display: inline-flex;\n flex: none;\n font-size: 11px;\n gap: 5px;\n white-space: nowrap;\n}\n/* \u672A\u542F\u7528\uFF1A\u6807\u9898\u884C\u91CC\u8BF4\u6E05\u695A\uFF0C\u6B63\u6587\u538B\u6697\uFF0C\u8BA9\u4EBA\u4E00\u773C\u770B\u51FA\"\u8FD9\u4E00\u680F\u73B0\u5728\u4E0D\u751F\u6548\"\u3002 */\n.dsh-ux-cardOff { border-style: dashed; }\n.dsh-ux-cardOff .dsh-ux-cardBody { opacity: .6; }\n.dsh-ux-cardHeaderStatic {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n}\n.dsh-ux-cardHeadText {\n display: flex;\n flex-direction: column;\n flex: 1;\n gap: 4px;\n min-width: 0;\n}\n.dsh-ux-cardName {\n color: var(--dsw-alias-label-primary);\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n margin: 0;\n}\n.dsh-ux-cardDescription {\n color: var(--dsw-alias-label-secondary);\n font-size: 13px;\n line-height: 1.5;\n margin: 0;\n}\n.dsh-ux-cardLink {\n align-items: center;\n color: var(--dsw-alias-label-secondary);\n display: inline-flex;\n flex: none;\n font-size: 12px;\n gap: 4px;\n text-decoration: none;\n white-space: nowrap;\n}\n.dsh-ux-cardLink:hover {\n color: var(--dsw-alias-brand-primary);\n text-decoration: underline;\n}\n/* \u62AC\u5934\u53F3\u7AEF\u90A3\u4E00\u7EC4\uFF1A\u91CD\u542F\u6309\u94AE + GitHub \u94FE\u63A5\uFF0C\u4E24\u679A\u90FD\u4E0D\u53C2\u4E0E\u6536\u7F29\u3002 */\n.dsh-ux-cardActions {\n align-items: center;\n display: inline-flex;\n flex: none;\n gap: 10px;\n}\n.dsh-ux-restartButton {\n appearance: none;\n background: 0 0;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n flex: none;\n font: inherit;\n font-size: 12px;\n line-height: 1;\n padding: 6px 12px;\n transition: border-color .16s, color .16s, background .16s;\n white-space: nowrap;\n}\n.dsh-ux-restartButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n border-color: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-brand-primary);\n}\n.dsh-ux-restartButton:disabled {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n opacity: .7;\n}\n/* \u786E\u8BA4\u6761\uFF1A\u62AC\u5934\u6B63\u4E0B\u65B9\u7684\u4E00\u6761\uFF0C\u4F4D\u7F6E\u5BF9\u9F50\u5E02\u573A\u7684\u300CN \u9879\u53D8\u66F4\u9700\u91CD\u542F\u300D\u6A2A\u5E45\u3002 */\n.dsh-ux-restartBanner {\n align-items: center;\n background: var(--dsw-alias-bg-layer-2);\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n display: flex;\n gap: 10px;\n margin: 0 16px 12px;\n padding: 10px 12px;\n}\n.dsh-ux-restartBannerFailed { border-color: var(--dsw-alias-state-error-primary); }\n.dsh-ux-restartBannerText {\n color: var(--dsw-alias-label-secondary);\n flex: 1;\n font-size: 12px;\n line-height: 1.5;\n min-width: 0;\n}\n.dsh-ux-restartBannerFailed .dsh-ux-restartBannerText { color: var(--dsw-alias-state-error-primary); }\n.dsh-ux-restartBannerActions {\n align-items: center;\n display: inline-flex;\n flex: none;\n gap: 8px;\n}\n.dsh-ux-restartGo {\n appearance: none;\n background: var(--dsw-alias-button-primary-fill);\n border: 0;\n border-radius: 999px;\n color: var(--dsw-alias-label-primary-foreground);\n cursor: pointer;\n font: inherit;\n font-size: 12px;\n line-height: 1;\n padding: 7px 14px;\n white-space: nowrap;\n}\n.dsh-ux-restartGo:hover { background: var(--dsw-alias-brand-primary); }\n.dsh-ux-restartCancel {\n appearance: none;\n background: 0 0;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 12px;\n line-height: 1;\n padding: 7px 14px;\n white-space: nowrap;\n}\n.dsh-ux-restartCancel:hover {\n border-color: var(--dsw-alias-label-dimmed);\n color: var(--dsw-alias-label-primary);\n}\n.dsh-ux-cardChevron {\n color: var(--dsw-alias-label-tertiary);\n flex: none;\n transition: transform .16s;\n}\n.dsh-ux-cardChevronOpen { transform: rotate(180deg); }\n.dsh-ux-cardBody {\n border-top: 1px solid var(--dsw-alias-border-l2);\n margin: 0 16px;\n padding-bottom: 8px;\n}\n`\n\n/** \u6CE8\u5165\u5361\u7247\u6837\u5F0F\u8868\uFF1B\u8FD4\u56DE\u5378\u8F7D\u5668\uFF08\u968F\u63D2\u4EF6 fiber \u56DE\u6536\uFF09\u3002 */\nexport function installSettingsCardStyle(): () => void {\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dsh-composer-ux-settings'\n tag.textContent = CARD_CSS\n document.head.appendChild(tag)\n return () => { tag.remove() }\n}\n", "/**\n * \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u5165\u53E3\u6309\u94AE\u7684\u6837\u5F0F\u8868\u3002\n *\n * \u4E3A\u4EC0\u4E48\u4E0D\u7528\u884C\u5185\u6837\u5F0F\uFF08React `style`\uFF09\uFF1A\u5B83\u8868\u8FBE\u4E0D\u4E86 `:hover` / `[aria-expanded]`\n * \u8FD9\u7C7B\u72B6\u6001\uFF0C\u800C\u300C\u548C\u65C1\u8FB9\u7684\u5B98\u65B9\u6309\u94AE\u957F\u5F97\u4E00\u6837\u300D\u6070\u6070\u8981\u9760 hover \u4E0E\u5E38\u6001\u900F\u660E\u5EA6\u3002\n *\n * \u53C2\u6570\u9010\u9879\u5BF9\u9F50\u793E\u533A\u63D2\u4EF6 `dsh-composer-expand` \u7684 `.cpex-btn`\uFF08\u540C\u4E00\u4E2A\u69FD\u4F4D\n * `conversation.input.right`\u3001\u540C\u4E00\u4E2A order \u90BB\u4F4D\uFF09\u2014\u2014 \u4E24\u4E2A\u6309\u94AE\u5E76\u6392\uFF0C\u5FC5\u987B\u540C\u9AD8\u3001\n * \u540C\u5706\u89D2\u3001\u540C\u5185\u8FB9\u8DDD\u3001\u540C\u8FB9\u6846\u3001\u540C\u5E38\u6001\u900F\u660E\u5EA6\uFF0C\u5426\u5219\u4E00\u773C\u5C31\u770B\u5F97\u51FA\u662F\u4E24\u5BB6\u4EBA\u505A\u7684\u3002\n * \u7279\u522B\u8BB0\u4E00\u7B14\uFF1A\u8FB9\u6846**\u4E0D\u7528**\u4E3B\u9898\u4EE4\u724C `--dsw-alias-border-l2`\uFF08\u5B83\u66F4\u4EAE\uFF0C\u4F1A\u5448\u73B0\u6210\n * \u7528\u6237\u622A\u56FE\u91CC\u90A3\u5708\u7A81\u5140\u7684\u767D\u7EBF\uFF09\uFF0C\u800C\u662F\u548C\u5BF9\u65B9\u4E00\u6837\u7528\u4E2D\u6027\u534A\u900F\u660E\u7070\uFF0C\u660E\u6697\u4E3B\u9898\u4E0B\u90FD\u534F\u8C03\u3002\n */\n\n/** \u5165\u53E3\u6309\u94AE\u7684\u57FA\u7840\u7C7B\u540D\u3002 */\nexport const QUICK_BUTTON_CLASS = 'composer-ux-quick-button'\n\n/** \u4E0E .cpex-btn \u9010\u9879\u5BF9\u9F50\u3002 */\nconst QUICK_BUTTON_CSS = `\n.${QUICK_BUTTON_CLASS} {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n height: 24px;\n border: 1px solid rgba(127, 127, 137, .35);\n background: transparent;\n color: inherit;\n border-radius: 999px;\n padding: 0 9px;\n font-size: 12px;\n line-height: 1;\n cursor: pointer;\n opacity: .75;\n white-space: nowrap;\n font-variant-numeric: tabular-nums;\n transition: opacity .12s ease, background-color .12s ease;\n}\n.${QUICK_BUTTON_CLASS}:hover { opacity: 1; background: rgba(127, 127, 137, .12); }\n.${QUICK_BUTTON_CLASS}[aria-expanded=\"true\"] {\n opacity: 1;\n background: rgba(127, 127, 137, .18);\n border-color: rgba(127, 127, 137, .6);\n}\n.${QUICK_BUTTON_CLASS} svg { flex: 0 0 auto; }\n`\n\n/** \u6CE8\u5165\u5165\u53E3\u6309\u94AE\u6837\u5F0F\u8868\uFF1B\u8FD4\u56DE\u5378\u8F7D\u5668\uFF08\u968F\u63D2\u4EF6 fiber \u56DE\u6536\uFF09\u3002 */\nexport function installQuickButtonStyle(): () => void {\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dsh-composer-ux-quick-button'\n tag.textContent = QUICK_BUTTON_CSS\n document.head.appendChild(tag)\n return () => { tag.remove() }\n}\n", "/**\n * \u53F3\u952E\u83DC\u5355\u5BBF\u4E3B\uFF1A\u6CE8\u518C\u8FDB shell.overlay\uFF08root \u7EA7 list \u69FD\uFF09\uFF0C\u83DC\u5355\u6253\u5F00\u65F6\u6E32\u67D3\n * \u4E00\u4E2A fixed \u5B9A\u4F4D\u7684\u6D6E\u5C42\uFF1B\u5173\u95ED\u65F6\u6E32\u67D3 null\u3002\n */\nimport React, { useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport {\n MENU_ITEMS, type ComposerUxSettings, type MenuState, type MenuField,\n} from '../settings-contract.ts'\nimport type { MenuActionId } from './interceptors.ts'\nimport { menu, menuItem, menuItemDim, menuNote, menuSeparator, menuShortcut } from './styles.ts'\n\n/** \u53F3\u952E\u83DC\u5355\u6CE8\u5165\u9762\u3002 */\nexport interface ContextMenuInjected {\n hooks: {\n /** \u83DC\u5355\u6253\u5F00\u72B6\u6001\uFF08null = \u5173\u95ED\uFF09\u3002 */\n menu: SnapshotStore<MenuState | null>\n /** \u5F53\u524D\u8BBE\u7F6E\uFF08\u51B3\u5B9A\u54EA\u4E9B\u83DC\u5355\u9879\u542F\u7528\uFF09\u3002 */\n live: SnapshotStore<ComposerUxSettings>\n }\n actions: {\n /** \u6267\u884C\u4E00\u4E2A\u83DC\u5355\u52A8\u4F5C\uFF1Bresolve \u6210\u529F\u4E0E\u5426\u3002 */\n run: (id: MenuActionId) => Promise<{ ok: boolean; message?: string }>\n /** \u5173\u95ED\u83DC\u5355\u3002 */\n close: () => void\n /** \u5728\u83DC\u5355\u4E0A\u6302\u4E00\u6BB5\u77ED\u6682\u63D0\u793A\uFF08\u4FDD\u7559\u83DC\u5355\u6253\u5F00\uFF09\u3002 */\n note: (message: string | undefined) => void\n }\n}\n\nexport type ContextMenuHostProps =\n PropsRuntime<'shell.overlay'>\n & InjectFace<ContextMenuInjected>\n\n/** \u83DC\u5355\u7EC4\uFF1A\u4E0E\u56FE\u7247\u4E00\u81F4\u7684\u4E09\u7EC4\u5206\u9694\u5E03\u5C40\u3002 */\nconst GROUPS: readonly { readonly label: string; readonly shortcut: string; readonly field: MenuField; readonly id: MenuActionId | 'disabledOnly' }[][] = [\n [\n { label: '\u64A4\u9500', shortcut: 'Ctrl+Z', field: 'menuUndo', id: 'undo' },\n { label: '\u91CD\u505A', shortcut: 'Ctrl+Y', field: 'menuRedo', id: 'redo' },\n ],\n [\n { label: '\u526A\u5207', shortcut: 'Ctrl+X', field: 'menuCut', id: 'cut' },\n { label: '\u590D\u5236', shortcut: 'Ctrl+C', field: 'menuCopy', id: 'copy' },\n { label: '\u7C98\u8D34', shortcut: 'Ctrl+V', field: 'menuPaste', id: 'paste' },\n { label: '\u5220\u9664', shortcut: '', field: 'menuDelete', id: 'delete' },\n ],\n [\n { label: '\u5168\u9009', shortcut: 'Ctrl+A', field: 'menuSelectAll', id: 'selectAll' },\n ],\n]\n\nconst ITEM_STYLES: Record<MenuActionId, 'always' | 'selection'> = {\n undo: 'always',\n redo: 'always',\n cut: 'selection',\n copy: 'selection',\n paste: 'always',\n delete: 'selection',\n selectAll: 'always',\n}\n\n/** \u4E0E\u89C6\u53E3\u8FB9\u754C\u4FDD\u6301 8px\u3002 */\nfunction clamp(value: number, size: number, viewport: number): number {\n return Math.max(8, Math.min(value, viewport - size - 8))\n}\n\n/** \u6E32\u67D3\u53F3\u952E\u83DC\u5355\uFF1B\u65E0\u83DC\u5355\u65F6\u8FD4\u56DE null\u3002 */\nexport function ContextMenuHost({ useMenu, useLive, actions }: ContextMenuHostProps) {\n const menuState = useMenu(item => item)\n const settings = useLive(item => item)\n const ref = useRef<HTMLDivElement | null>(null)\n const [position, setPosition] = useState<{ x: number; y: number } | null>(null)\n\n // \u6253\u5F00\u540E\u6309\u5B9E\u9645\u5C3A\u5BF8\u94B3\u5236\u5728\u89C6\u53E3\u5185\u3002\n useLayoutEffect(() => {\n if (menuState === null) {\n setPosition(null)\n return\n }\n const el = ref.current\n if (el === null) return\n const rect = el.getBoundingClientRect()\n setPosition({\n x: clamp(menuState.x, rect.width, window.innerWidth),\n y: clamp(menuState.y, rect.height, window.innerHeight),\n })\n }, [menuState?.x, menuState?.y])\n\n // \u5916\u90E8\u70B9\u51FB / Escape / \u6EDA\u52A8 / \u7A97\u53E3\u53D8\u5316\u65F6\u5173\u95ED\u3002\n useEffect(() => {\n if (menuState === null) return\n const onPointerDown = (event: PointerEvent): void => {\n if (ref.current !== null && event.target instanceof Node && ref.current.contains(event.target)) return\n actions.close()\n }\n const onEscape = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape') return\n event.preventDefault()\n event.stopPropagation()\n actions.close()\n }\n window.addEventListener('pointerdown', onPointerDown, true)\n window.addEventListener('keydown', onEscape, true)\n window.addEventListener('scroll', actions.close, true)\n window.addEventListener('resize', actions.close)\n return () => {\n window.removeEventListener('pointerdown', onPointerDown, true)\n window.removeEventListener('keydown', onEscape, true)\n window.removeEventListener('scroll', actions.close, true)\n window.removeEventListener('resize', actions.close)\n }\n }, [menuState === null, actions])\n\n // \u63D0\u793A 3 \u79D2\u540E\u6E05\u9664\u3002\n useEffect(() => {\n if (menuState?.note === undefined) return\n const timer = setTimeout(() => { actions.note(undefined) }, 3000)\n return () => { clearTimeout(timer) }\n }, [menuState?.note])\n\n if (menuState === null) return null\n\n const onItemClick = (id: MenuActionId): void => {\n // \u7C98\u8D34\u82E5\u7F13\u5B58\u672A\u547D\u4E2D\u4F1A\u5B9E\u65F6\u8BFB\u53D6\u526A\u8D34\u677F\uFF0C\u53EF\u80FD\u77ED\u6682\u7B49\u5F85\u6388\u6743\uFF0C\u7ED9\u51FA\u8FDB\u884C\u4E2D\u53CD\u9988\u3002\n if (id === 'paste') actions.note('\u6B63\u5728\u8BFB\u53D6\u526A\u8D34\u677F\u2026')\n // \u4E0D\u8BA9\u6309\u94AE\u62A2\u8D70\u7126\u70B9\uFF0C\u4FDD\u7559\u8F93\u5165\u6846\u9009\u533A\u3002\n void actions.run(id).then((result) => {\n if (result.ok) actions.close()\n else actions.note(result.message ?? '\u64CD\u4F5C\u5931\u8D25')\n })\n }\n\n const groups = GROUPS\n .map(group => group.filter(item => settings[item.field] === true))\n .filter(group => group.length > 0)\n\n return (\n <div\n ref={ref}\n role=\"menu\"\n style={{\n ...menu,\n left: position?.x ?? menuState.x,\n top: position?.y ?? menuState.y,\n }}\n >\n {groups.map((group, groupIndex) => (\n <React.Fragment key={group[0]!.field}>\n {groupIndex > 0 && <div role=\"separator\" style={menuSeparator} />}\n {group.map(item => {\n const needsSelection = ITEM_STYLES[item.id] === 'selection'\n const disabled = needsSelection && !menuState.hasSelection\n const style = disabled ? menuItemDim : menuItem\n return (\n <button\n key={item.field}\n type=\"button\"\n role=\"menuitem\"\n disabled={disabled}\n style={style}\n onMouseDown={(event) => { event.preventDefault() }}\n onClick={() => { onItemClick(item.id) }}\n >\n <span>{item.label}</span>\n {item.shortcut !== '' && <span style={menuShortcut}>{item.shortcut}</span>}\n </button>\n )\n })}\n </React.Fragment>\n ))}\n {menuState.note !== undefined && <div style={menuNote}>{menuState.note}</div>}\n </div>\n )\n}\n", "/**\n * \u5185\u8054\u6837\u5F0F\u5DE5\u5177\uFF1A\u53EA\u4F7F\u7528 DSH Web \u7684 --dsw-* \u8BBE\u8BA1\u4EE4\u724C\uFF0C\u6DF1\u6D45\u4E3B\u9898\u81EA\u9002\u5E94\u3002\n */\nimport type { CSSProperties } from 'react'\n\n/** \u9875\u9762\u5361\u7247\u3002 */\nexport const card: CSSProperties = {\n background: 'var(--dsw-alias-bg-layer-2)',\n border: '0.5px solid var(--dsw-alias-border-l2)',\n borderRadius: 12,\n padding: '14px 16px',\n marginBottom: 12,\n}\n\n/** \u5361\u7247\u6807\u9898\u3002 */\nexport const cardTitle: CSSProperties = {\n color: 'var(--dsw-alias-label-primary)',\n fontSize: 14,\n fontWeight: 600,\n margin: '0 0 4px',\n}\n\n/** \u8BF4\u660E\u6587\u5B57\u3002 */\nexport const description: CSSProperties = {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 12,\n lineHeight: 1.6,\n margin: '0 0 12px',\n}\n\n/** \u8BBE\u7F6E\u884C\u3002 */\nexport const row: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n minHeight: 40,\n padding: '7px 0',\n borderTop: '0.5px solid var(--dsw-alias-border-l2)',\n}\n\n/** \u884C\u5185\u6807\u7B7E\u533A\u3002 */\nexport const rowText: CSSProperties = {\n minWidth: 0,\n flex: 1,\n}\n\n/** \u884C\u6807\u9898\u3002 */\nexport const rowTitle: CSSProperties = {\n color: 'var(--dsw-alias-label-primary)',\n fontSize: 13,\n lineHeight: 1.4,\n}\n\n/** \u884C\u8BF4\u660E\u3002 */\nexport const rowDesc: CSSProperties = {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 11,\n lineHeight: 1.4,\n marginTop: 2,\n}\n\n/** \u952E\u4F4D\u663E\u793A\u80F6\u56CA\u3002 */\nexport const kbd: CSSProperties = {\n color: 'var(--dsw-alias-label-primary)',\n background: 'var(--dsw-alias-bg-layer-1)',\n border: '0.5px solid var(--dsw-alias-border-l2)',\n borderRadius: 6,\n padding: '3px 8px',\n fontSize: 12,\n fontFamily: 'var(--dsw-font-family)',\n whiteSpace: 'nowrap',\n}\n\n/** \u9884\u8BBE/\u52A8\u4F5C\u5C0F\u6309\u94AE\u3002 */\nexport const pill: CSSProperties = {\n background: 'var(--dsw-alias-interactive-bg-hover)',\n color: 'var(--dsw-alias-label-secondary)',\n border: '0.5px solid var(--dsw-alias-border-l2)',\n borderRadius: 999,\n padding: '4px 10px',\n fontSize: 12,\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n}\n\n/** \u9009\u4E2D\u6001\u6309\u94AE\u3002 */\nexport const pillActive: CSSProperties = {\n ...pill,\n color: 'var(--dsw-alias-button-primary-fill)',\n borderColor: 'var(--dsw-alias-button-primary-fill)',\n}\n\n/** \u5355\u884C\u6587\u672C\u8F93\u5165\uFF08\u8DDF\u968F\u4E3B\u9898\u4EE4\u724C\uFF09\u3002 */\nexport const textInput: CSSProperties = {\n background: 'var(--dsw-alias-bg-layer-1)',\n color: 'var(--dsw-alias-label-primary)',\n border: '0.5px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n padding: '6px 9px',\n fontSize: 12,\n lineHeight: 1.4,\n width: '100%',\n minWidth: 0,\n boxSizing: 'border-box',\n flex: 1,\n}\n\n/** \u63D0\u793A/\u9519\u8BEF\u6587\u5B57\u3002 */\nexport const hintError: CSSProperties = {\n color: 'var(--dsw-alias-state-error-primary)',\n fontSize: 12,\n lineHeight: 1.5,\n margin: '6px 0 0',\n}\n\n/** \u63D0\u793A\u6587\u5B57\uFF08\u4E2D\u6027\uFF09\u3002 */\nexport const hintInfo: CSSProperties = {\n color: 'var(--dsw-alias-label-secondary)',\n fontSize: 12,\n lineHeight: 1.5,\n margin: '6px 0 0',\n}\n\n/** \u83DC\u5355\uFF08\u4E0E\u56FE\u7247\u4E00\u81F4\u7684\u6DF1\u8272\u5706\u89D2\u83DC\u5355\uFF09\uFF1B\u80CC\u666F\u53D6\u81EA\u5B98\u65B9\u83DC\u5355\u4EE4\u724C\u3002 */\nexport const menu: CSSProperties = {\n position: 'fixed',\n zIndex: 9999,\n minWidth: 200,\n background: 'var(--dsw-specific-menu)',\n border: '0.5px solid var(--dsw-alias-border-l1)',\n borderRadius: 10,\n boxShadow: 'var(--dsw-elevation-prominent)',\n padding: 5,\n pointerEvents: 'auto',\n userSelect: 'none',\n}\n\n/** \u83DC\u5355\u9879\u3002 */\nexport const menuItem: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 24,\n padding: '6px 10px',\n borderRadius: 6,\n fontSize: 13,\n color: 'var(--dsw-alias-label-primary)',\n cursor: 'pointer',\n background: 'transparent',\n border: 'none',\n width: '100%',\n textAlign: 'left',\n}\n\nexport const menuItemDim: CSSProperties = {\n ...menuItem,\n color: 'var(--dsw-alias-label-dimmed)',\n cursor: 'default',\n}\n\n/** \u83DC\u5355\u9879\u5FEB\u6377\u952E\u3002 */\nexport const menuShortcut: CSSProperties = {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 12,\n fontFamily: 'var(--dsw-font-family)',\n}\n\n/** \u83DC\u5355\u5206\u9694\u7EBF\u3002 */\nexport const menuSeparator: CSSProperties = {\n height: 0,\n borderTop: '0.5px solid var(--dsw-alias-border-l2)',\n margin: '4px 8px',\n}\n\n/** \u83DC\u5355\u5E95\u90E8\u63D0\u793A\u3002 */\nexport const menuNote: CSSProperties = {\n color: 'var(--dsw-alias-state-warn-label)',\n fontSize: 11,\n lineHeight: 1.4,\n padding: '4px 10px 2px',\n}\n\n// \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\uFF1A\u8F93\u5165\u5361\u7247\u91CC\u7684\u5165\u53E3\u6309\u94AE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// \u6309\u94AE\u6837\u5F0F**\u6545\u610F\u4E0D\u653E\u5728\u8FD9\u91CC**\uFF1A\u5B83\u9700\u8981 hover \u4E0E\u5C55\u5F00\u6001\uFF0C\u884C\u5185\u6837\u5F0F\u8868\u8FBE\u4E0D\u4E86\uFF0C\u800C\u4E14\n// \u8981\u4E0E\u65C1\u8FB9\u5B98\u65B9\u300C\u5C55\u5F00\u300D\u6309\u94AE\uFF08dsh-composer-expand \u7684 .cpex-btn\uFF09\u9010\u9879\u5BF9\u9F50\u3002\n// \u89C1 `quick-style.ts` \u7684\u6CE8\u5165\u6837\u5F0F\u8868\u3002\n\n// \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\uFF1A\u5C55\u5F00\u9762\u677F \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** \u9762\u677F\u5BB9\u5668\uFF08fixed \u5B9A\u4F4D\uFF0C\u951A\u70B9\u5728\u5165\u53E3\u6309\u94AE\u4E0A\u65B9\uFF09\u3002 */\nexport const quickPanel: CSSProperties = {\n position: 'fixed',\n zIndex: 9999,\n width: 420,\n maxWidth: 'calc(100vw - 24px)',\n maxHeight: 'min(60vh, 520px)',\n display: 'flex',\n flexDirection: 'column',\n background: 'var(--dsw-specific-menu)',\n border: '0.5px solid var(--dsw-alias-border-l1)',\n borderRadius: 12,\n boxShadow: 'var(--dsw-elevation-prominent)',\n pointerEvents: 'auto',\n overflow: 'hidden',\n}\n\n/** \u9762\u677F\u9876\u90E8\u533A\uFF08\u6807\u9898 + \u6863\u4F4D + \u4F18\u5316\u6309\u94AE\uFF09\u3002 */\nexport const quickPanelHead: CSSProperties = {\n padding: '10px 12px 8px',\n borderBottom: '0.5px solid var(--dsw-alias-border-l2)',\n display: 'flex',\n flexDirection: 'column',\n gap: 8,\n}\n\n/** \u9762\u677F\u6807\u9898\u884C\u3002 */\nexport const quickPanelTitleRow: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 8,\n}\n\n/** \u9762\u677F\u6807\u9898\u3002 */\nexport const quickPanelTitle: CSSProperties = {\n color: 'var(--dsw-alias-label-primary)',\n fontSize: 13,\n fontWeight: 600,\n}\n\n/** \u6863\u4F4D\u5206\u6BB5\u63A7\u4EF6\u3002 */\nexport const quickTierRow: CSSProperties = {\n display: 'inline-flex',\n gap: 2,\n padding: 2,\n borderRadius: 999,\n background: 'var(--dsw-alias-bg-layer-1)',\n border: '0.5px solid var(--dsw-alias-border-l2)',\n}\n\n/** \u5355\u4E2A\u6863\u4F4D\u6309\u94AE\u3002 */\nexport const quickTierButton: CSSProperties = {\n border: 'none',\n background: 'transparent',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 11,\n lineHeight: 1,\n padding: '4px 8px',\n borderRadius: 999,\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n}\n\n/** \u9009\u4E2D\u6863\u4F4D\u3002\n * \u524D\u666F\u5FC5\u987B\u7528\u914D\u5BF9\u4EE4\u724C `label-primary-foreground`\uFF1A`button-primary-fill` \u53D6\u81EA\n * `brand-primary`\uFF0C\u6D45\u8272\u4E3B\u9898\u4E0B\u662F\u58A8\u8272/\u6DF1\u8272\uFF0C**\u6DF1\u8272\u4E3B\u9898\u4E0B\u5B83\u662F\u767D**\u2014\u2014\u6B64\u65F6\u5199\u6B7B\n * `#fff` \u5C31\u662F\u767D\u5E95\u767D\u5B57\uFF080.2.0 \u771F\u8E29\u8FC7\uFF09\u3002\u5B98\u65B9 ui-primitives/Button \u7684\u6210\u5BF9\u5199\u6CD5\n * \u5C31\u662F fill + label-primary-foreground\u3002 */\nexport const quickTierButtonActive: CSSProperties = {\n ...quickTierButton,\n background: 'var(--dsw-alias-button-primary-fill)',\n color: 'var(--dsw-alias-label-primary-foreground)',\n}\n\n/** \u4E3B\u884C\u52A8\u6309\u94AE\uFF08\u4F18\u5316\u63D0\u793A\u8BCD\uFF09\u3002\u540C\u4E0A\uFF1Afill \u4E0E\u524D\u666F\u5FC5\u987B\u6210\u5BF9\u3002 */\nexport const quickPrimaryButton: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 6,\n width: '100%',\n padding: '7px 12px',\n borderRadius: 8,\n border: '0.5px solid var(--dsw-alias-button-primary-fill)',\n background: 'var(--dsw-alias-button-primary-fill)',\n color: 'var(--dsw-alias-label-primary-foreground)',\n fontSize: 12,\n cursor: 'pointer',\n}\n\n/** \u4E3B\u884C\u52A8\u6309\u94AE\uFF08\u4E0D\u53EF\u7528\uFF09\uFF1A\u4E0E\u5B98\u65B9 .primary:disabled \u4E00\u81F4\u7528 0.4\u3002 */\nexport const quickPrimaryButtonDisabled: CSSProperties = {\n ...quickPrimaryButton,\n opacity: 0.4,\n cursor: 'default',\n}\n\n/** \u6761\u76EE\u5217\u8868\u5BB9\u5668\uFF08\u53EF\u6EDA\u52A8\uFF09\u3002 */\nexport const quickList: CSSProperties = {\n overflowY: 'auto',\n padding: '6px 6px 8px',\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n}\n\n/** \u4E00\u6761\u5FEB\u6377\u6307\u4EE4\u3002\n * \u6CE8\u610F\uFF1A\u8FD9\u4E00\u884C\u91CC\u8FD8\u6709\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u52FE\u9009\u6846\uFF0C\u6240\u4EE5\u6309\u94AE\u5FC5\u987B\u53EF\u88AB\u538B\u7F29\n * \uFF08flex 1 1 auto + minWidth 0\uFF09\uFF0C\u5426\u5219\u957F\u9884\u89C8\u4F1A\u628A\u52FE\u9009\u6846\u6324\u51FA\u9762\u677F\n * \uFF08width:100% \u4F1A\u5403\u6EE1\u6574\u884C\uFF0C0.2.0 \u771F\u8E29\u8FC7\uFF09\u3002 */\nexport const quickItem: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '5px 8px',\n borderRadius: 7,\n cursor: 'pointer',\n background: 'transparent',\n border: 'none',\n flex: '1 1 auto',\n minWidth: 0,\n textAlign: 'left',\n}\n\n/** \u6761\u76EE\u540D\u79F0\u3002 */\nexport const quickItemLabel: CSSProperties = {\n color: 'var(--dsw-alias-label-primary)',\n fontSize: 12,\n flex: '0 0 auto',\n whiteSpace: 'nowrap',\n}\n\n/** \u6761\u76EE\u5185\u5BB9\u9884\u89C8\u3002 */\nexport const quickItemPreview: CSSProperties = {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 11,\n flex: '1 1 auto',\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n}\n\n/** \u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u52FE\u9009\u533A\u3002 */\nexport const quickAlwaysLabel: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n gap: 4,\n flex: '0 0 auto',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 11,\n whiteSpace: 'nowrap',\n cursor: 'pointer',\n}\n\n/** \u52FE\u9009\u6846\u3002 */\nexport const quickAlwaysBox: CSSProperties = {\n margin: 0,\n cursor: 'pointer',\n}\n\n/** \u9762\u677F\u5E95\u90E8\u63D0\u793A\u6761\u3002 */\nexport const quickPanelFoot: CSSProperties = {\n padding: '5px 12px 7px',\n borderTop: '0.5px solid var(--dsw-alias-border-l2)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 8,\n}\n\n/** \u9762\u677F\u91CC\u7684\u63D0\u793A\u6587\u5B57\u3002 */\nexport const quickNotice: CSSProperties = {\n color: 'var(--dsw-alias-state-warn-label)',\n fontSize: 11,\n lineHeight: 1.4,\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n}\n\n/** \u9762\u677F\u91CC\u7684\u6B21\u8981\u8BF4\u660E\u3002 */\nexport const quickFootHint: CSSProperties = {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 11,\n whiteSpace: 'nowrap',\n flex: '0 0 auto',\n}\n\n/** \u7A7A\u5217\u8868\u5360\u4F4D\u3002 */\nexport const quickEmpty: CSSProperties = {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 12,\n lineHeight: 1.6,\n padding: '14px 10px',\n textAlign: 'center',\n}\n\n// \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\uFF1A\u5206\u7C7B\uFF080.3.0 \u8D77\u7684\u4E24\u7EA7\u7ED3\u6784\uFF09 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** \u5206\u7C7B\u5207\u6362\u884C\uFF08\u9762\u677F\u91CC\u5728\u6863\u4F4D\u884C\u4E0B\u65B9\uFF09\u3002 */\nexport const quickCategoryRow: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n flexWrap: 'wrap',\n}\n\n/** \u5355\u4E2A\u5206\u7C7B\u6807\u7B7E\u3002 */\nexport const quickCategoryTab: CSSProperties = {\n border: '0.5px solid var(--dsw-alias-border-l2)',\n background: 'transparent',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 11,\n lineHeight: 1,\n padding: '4px 8px',\n borderRadius: 999,\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n maxWidth: 160,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n}\n\n/** \u9009\u4E2D\u7684\u5206\u7C7B\u6807\u7B7E\u3002\n * \u53EA\u6539\u8FB9\u6846\u4E0E\u6587\u5B57\u8272\uFF0C**\u4E0D\u7528\u5B9E\u8272\u586B\u5145**\uFF1A\u8FD9\u6837\u4E0D\u9700\u8981\u586B/\u524D\u666F\u6210\u5BF9\u4EE4\u724C\uFF0C\n * \u4E5F\u5C31\u4E0D\u4F1A\u91CD\u6F14 0.2.0 \u90A3\u6B21\u300C\u6DF1\u8272\u4E3B\u9898\u767D\u5E95\u767D\u5B57\u300D\u3002 */\nexport const quickCategoryTabActive: CSSProperties = {\n ...quickCategoryTab,\n border: '0.5px solid var(--dsw-alias-brand-primary)',\n color: 'var(--dsw-alias-label-primary)',\n fontWeight: 600,\n}\n\n/** \u300C\uFF0B \u5206\u7C7B\u300D\u5C0F\u6309\u94AE\u3002 */\nexport const quickCategoryAdd: CSSProperties = {\n ...quickCategoryTab,\n color: 'var(--dsw-alias-label-tertiary)',\n padding: '4px 7px',\n cursor: 'pointer',\n}\n", "/**\n * \u8BBE\u7F6E\u9762\u677F\u5C3A\u5BF8\u624B\u67C4\uFF1A\u56DB\u8FB9\u53EF\u62D6 + \u53F3\u4E0B\u89D2\u6293\u624B\u3002\n *\n * **\u4E3A\u4EC0\u4E48\u7528 `createPortal` \u6302\u8FDB\u9762\u677F\u5185\u90E8\uFF0C\u800C\u4E0D\u662F\u5728 `shell.overlay` \u91CC\u5BF9\u51C6\u5750\u6807\u753B**\n * \uFF080.2.0 \u6574\u6BB5\u529F\u80FD\u5931\u6548\u7684\u539F\u56E0\uFF0C\u52A1\u5FC5\u522B\u6539\u56DE\u53BB\uFF09\uFF1A\n * `shell.overlay` \u88AB\u5B98\u65B9\u5C01\u5728 `ui-layout` \u7684\n * `.overlayLayer { position:absolute; inset:0; z-index:20 }` \u91CC\u3002`position` +\n * `z-index` \u8BA9\u5B83**\u81EA\u6210\u5C42\u53E0\u4E0A\u4E0B\u6587**\uFF0C\u91CC\u9762\u7684\u5143\u7D20\u65E0\u8BBA z-index \u5199\u591A\u5927\u90FD\u51FA\u4E0D\u53BB\uFF0C\n * \u6C38\u8FDC\u6392\u5728\u8BBE\u7F6E\u5F39\u7A97\uFF08`.overlay` z-index:1000\uFF09\u4E0B\u9762\uFF0C\u88AB\u5168\u5C4F\u906E\u7F69\n * \uFF08`.mask { position:absolute; inset:0 }`\uFF09\u5403\u6389\u9F20\u6807 \u21D2 \u624B\u67C4\u6839\u672C\u6293\u4E0D\u5230\u3002\n * \u6302\u8FDB\u9762\u677F\u5185\u90E8\u5C31\u5B8C\u5168\u4E0D\u9700\u8981\u6BD4\u5C42\u53E0\uFF1A\u5B83\u5728\u6700\u9AD8\u90A3\u4E00\u5C42\u7684**\u91CC\u9762**\u3002\n *\n * \u9644\u5E26\u597D\u5904\uFF1A\u5B9A\u4F4D\u7531\u300C\u89C6\u53E3\u5750\u6807 + \u8F6E\u8BE2\u91CD\u7B97\u300D\u53D8\u6210\u300C\u9762\u677F\u5185\u7684\u7EDD\u5BF9\u5B9A\u4F4D\u300D\uFF0C\u9762\u677F\u79FB\u52A8/\n * \u6EDA\u52A8/\u6539\u5C3A\u5BF8\u90FD\u81EA\u52A8\u8DDF\u968F\uFF0C\u4E0D\u518D\u9700\u8981 250ms \u7684\u77E9\u5F62\u91CD\u7B97\uFF08\u8F6E\u8BE2\u53EA\u7528\u6765\u53D1\u73B0\u9762\u677F\u51FA\u73B0\uFF09\u3002\n *\n * \u672C\u7EC4\u4EF6\u4ECD\u6CE8\u518C\u5728 `shell.overlay`\u2014\u2014\u5B83\u53EA\u662F**\u6E32\u67D3\u51FA\u53E3**\u5728\u90A3\u91CC\uFF08\u4E3A\u4E86\u62FF\u5230\n * `useLive` \u4E0E\u5199\u5165\u52A8\u4F5C\uFF09\uFF0C\u5B9E\u9645 DOM \u901A\u8FC7 portal \u843D\u5728\u9762\u677F\u5185\u3002\n */\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport { PANEL_HEIGHT_FIELD, PANEL_WIDTH_FIELD, activeSections, type ComposerUxSettings } from '../settings-contract.ts'\nimport {\n RESIZE_EDGE_CLASS, RESIZE_GRIP_CLASS, RESIZE_LAYER_CLASS, RESIZE_OUTLINE_CLASS,\n RESIZE_OUTLINE_STYLE, clampPanelHeight, clampPanelWidth, findSettingsPanel, handleBox,\n type ResizeEdge,\n} from './panel.ts'\n\nexport interface PanelResizeInjected {\n hooks: { live: SnapshotStore<ComposerUxSettings> }\n actions: {\n /** \u5199\u4E00\u4E2A\u5B57\u6BB5\uFF08boolean \u6216 number\uFF09\u3002 */\n setField: (field: string, value: boolean | number) => void\n }\n}\n\nexport type PanelResizeProps = PropsRuntime<'shell.overlay'> & InjectFace<PanelResizeInjected>\n\n/** \u62D6\u62FD\u8D77\u59CB\u72B6\u6001\uFF08move/up \u95ED\u5305\u5171\u4EAB\uFF09\u3002 */\ninterface DragStart {\n readonly edge: ResizeEdge\n readonly x: number\n readonly y: number\n readonly left: number\n readonly top: number\n readonly width: number\n readonly height: number\n}\n\n/** \u53EF\u62D6\u62FD\u7684\u56DB\u8FB9 + \u53F3\u4E0B\u89D2\u3002 */\nconst EDGES: readonly ResizeEdge[] = ['left', 'right', 'top', 'bottom', 'br']\n\n/** \u6E32\u67D3\u8BBE\u7F6E\u9762\u677F\u5C3A\u5BF8\u624B\u67C4\uFF1B\u65E0\u9762\u677F\u6216\u5F00\u5173\u5173\u95ED\u65F6\u4E0D\u6E32\u67D3\u3002 */\nexport function PanelResizeHandles({ useLive, actions }: PanelResizeProps) {\n const settings = useLive(value => ({\n // \u300C\u8BBE\u7F6E\u9762\u677F\u300D\u680F\uFF08\u6216\u603B\u5F00\u5173\uFF09\u5173\u7740\u65F6\u6574\u5757\u505C\u7528 \u2014\u2014 \u4E0E\u5BFC\u822A\u6EDA\u52A8\u90A3\u5904\u7528\u540C\u4E00\u4E2A\u5224\u636E\u3002\n sectionOn: activeSections(value).panel,\n panelResize: value.panelResize,\n panelWidth: value.panelWidth,\n panelHeight: value.panelHeight,\n }))\n const enabled = settings.sectionOn === true && settings.panelResize === true\n const [panel, setPanel] = useState<HTMLElement | null>(null)\n const [active, setActive] = useState<ResizeEdge | null>(null)\n const dragRef = useRef<DragStart | null>(null)\n\n // \u53D1\u73B0/\u5931\u53BB\u8BBE\u7F6E\u5BF9\u8BDD\u6846\uFF08\u5B98\u65B9 shell \u5143\u7D20\u6302\u8F7D React \u611F\u77E5\u4E0D\u5230\uFF0C\u6545\u8F6E\u8BE2\uFF1B\n // \u53EA\u5728\u300C\u6709\u6CA1\u6709\u9762\u677F\u300D\u771F\u7684\u53D8\u5316\u65F6\u624D setState\uFF0C\u907F\u514D\u65E0\u8C13\u91CD\u6E32\u67D3\uFF09\u3002\n useEffect(() => {\n if (!enabled) {\n setPanel(null)\n return\n }\n let current: HTMLElement | null = null\n const probe = (): void => {\n const found = findSettingsPanel()\n if (found === current) return\n current = found\n setPanel(found)\n }\n probe()\n const timer = setInterval(probe, 250)\n return () => { clearInterval(timer) }\n }, [enabled])\n\n // \u5957\u7528\u6301\u4E45\u5316\u5C3A\u5BF8\uFF1A\u9762\u677F\u51FA\u73B0\u65F6\u3001\u4EE5\u53CA**\u5C3A\u5BF8\u8BBE\u7F6E\u53D8\u5316\u65F6**\uFF08\u8FD9\u6837\u8BBE\u7F6E\u9875\u91CC\u70B9\n // \u300C\u5C3A\u5BF8\u9884\u8BBE\u300D\u5F53\u573A\u5C31\u53D8\uFF0C\u4E0D\u5FC5\u5173\u6389\u8BBE\u7F6E\u518D\u91CD\u5F00\uFF09\u3002\u8BBE\u7F6E\u88AB\u6E05\u7A7A\u65F6\u79FB\u9664\u5185\u8054\u6837\u5F0F\uFF0C\n // \u56DE\u843D\u5230\u5B98\u65B9\u9ED8\u8BA4 800\u3002\n useEffect(() => {\n if (panel === null) return\n const width = settings.panelWidth\n const height = settings.panelHeight\n if (width === undefined) panel.style.removeProperty('width')\n else panel.style.width = `${clampPanelWidth(width)}px`\n if (height === undefined) panel.style.removeProperty('height')\n else panel.style.height = `${clampPanelHeight(height)}px`\n }, [panel, settings.panelWidth, settings.panelHeight])\n\n if (!enabled || panel === null) return null\n\n const onPointerDown = (edge: ResizeEdge, event: React.PointerEvent): void => {\n event.preventDefault()\n event.stopPropagation()\n const el = panel\n const rect = el.getBoundingClientRect()\n // \u628A\u300C\u5C45\u4E2D flex \u5B50\u9879\u300D\u8F6C\u6210\u56FA\u5B9A\u5B9A\u4F4D\u540E\u518D\u62D6\uFF1A\u5C45\u4E2D\u7684\u5143\u7D20\u4E00\u6539\u5BBD\u5EA6\u4F1A**\u4E24\u4FA7\u540C\u65F6\n // \u4F38\u7F29**\uFF0C\u62D6\u53F3\u8FB9\u5DE6\u8FB9\u4E5F\u8DDF\u7740\u52A8\uFF0C\u624B\u611F\u662F\u9519\u7684\u3002\u8F6C\u6210 fixed \u4E4B\u540E\u62D6\u54EA\u8FB9\u5C31\u53EA\u52A8\u54EA\u8FB9\u3002\n el.style.position = 'fixed'\n el.style.margin = '0'\n el.style.left = `${rect.left}px`\n el.style.top = `${rect.top}px`\n el.style.width = `${rect.width}px`\n el.style.height = `${rect.height}px`\n\n const start: DragStart = {\n edge, x: event.clientX, y: event.clientY,\n left: rect.left, top: rect.top, width: rect.width, height: rect.height,\n }\n dragRef.current = start\n setActive(edge)\n document.body.style.cursor = String(handleBox(edge).cursor ?? 'default')\n document.body.style.userSelect = 'none'\n\n const onMove = (move: PointerEvent): void => {\n if (dragRef.current !== start) return\n move.preventDefault()\n const dx = move.clientX - start.x\n const dy = move.clientY - start.y\n let { left, top, width, height } = start\n if (edge === 'right' || edge === 'br') width = clampPanelWidth(start.width + dx)\n if (edge === 'bottom' || edge === 'br') height = clampPanelHeight(start.height + dy)\n if (edge === 'left') {\n width = clampPanelWidth(start.width - dx)\n left = start.left + (start.width - width)\n }\n if (edge === 'top') {\n height = clampPanelHeight(start.height - dy)\n top = start.top + (start.height - height)\n }\n el.style.left = `${Math.round(left)}px`\n el.style.top = `${Math.round(top)}px`\n el.style.width = `${Math.round(width)}px`\n el.style.height = `${Math.round(height)}px`\n }\n const onUp = (): void => {\n window.removeEventListener('pointermove', onMove)\n window.removeEventListener('pointerup', onUp)\n dragRef.current = null\n setActive(null)\n const box = el.getBoundingClientRect()\n actions.setField(PANEL_WIDTH_FIELD, Math.round(clampPanelWidth(box.width)))\n actions.setField(PANEL_HEIGHT_FIELD, Math.round(clampPanelHeight(box.height)))\n document.body.style.removeProperty('cursor')\n document.body.style.removeProperty('user-select')\n }\n window.addEventListener('pointermove', onMove)\n window.addEventListener('pointerup', onUp)\n }\n\n return createPortal(\n <div className={RESIZE_LAYER_CLASS} data-composer-ux-resize>\n <div className={RESIZE_OUTLINE_CLASS} style={RESIZE_OUTLINE_STYLE} />\n {EDGES.map(edge => (\n <div\n key={edge}\n className={edge === 'br' ? RESIZE_GRIP_CLASS : RESIZE_EDGE_CLASS}\n data-active={active === edge ? 'true' : undefined}\n title={edge === 'br' ? '\u62D6\u52A8\u6539\u9762\u677F\u5927\u5C0F' : undefined}\n style={handleBox(edge)}\n onPointerDown={event => { onPointerDown(edge, event) }}\n >\n {edge === 'br' && (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden>\n <path\n d=\"M11 1 1 11M11 6 6 11\"\n stroke=\"currentColor\"\n strokeWidth=\"1.3\"\n strokeLinecap=\"round\"\n />\n </svg>\n )}\n </div>\n ))}\n </div>,\n panel,\n )\n}\n", "/**\n * \u8BBE\u7F6E\u9875\u300C\u8F93\u5165\u4F53\u9A8C\u300D\u3002\n *\n * \u7248\u5F0F\u5BF9\u9F50\u793E\u533A\u63D2\u4EF6 @linxin666/dsh-web-all \u7684\u300CWeb \u63D2\u4EF6\u300D\u9875\uFF1A\n * \u9876\u90E8\u5E38\u663E\uFF1A\u4E2D\u6587\u540D + \u4E00\u884C\u63CF\u8FF0\uFF08\u5185\u5D4C\u82F1\u6587\u5305\u540D dsh-composer-ux\uFF09+ \u603B\u5F00\u5173\uFF1B\n * \u5176\u4E0B\u4E09\u4E2A\u680F\u76EE\uFF08\u952E\u4F4D / \u53F3\u952E\u83DC\u5355 / \u8BBE\u7F6E\u9762\u677F\uFF09\u4E3A\u6298\u53E0\u5361\uFF0C\u6807\u9898\u884C\u53EA\u653E\u4E00\u53E5\n * \u6982\u89C8\uFF0C\u957F\u8BF4\u660E\u4E0E\u5177\u4F53\u63A7\u4EF6\u90FD\u5728\u5C55\u5F00\u540E\u7684\u5185\u5BB9\u533A\u91CC\uFF1B\u9ED8\u8BA4\u5168\u90E8\u6298\u53E0\u3001\u4E0D\u8BB0\u5FC6\u3002\n */\nimport React, { useEffect, useRef, useState, type CSSProperties } from 'react'\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SettingsSectionOwnerProps } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport {\n DEFAULT_CATEGORY_NAME, DEFAULT_HEADER_NAME, ENABLED_FIELD, HEADER_ENABLED_FIELD,\n HEADER_NAME_FIELD, HEADER_NAME_MAX, HEADER_ROUTES_FIELD, HEADER_VALUE_FIELD, HEADER_VALUE_MAX,\n MENU_ITEMS, MENU_MODES, MENU_MODE_FIELD, NEWLINE_PRESETS, OPTIMIZER_TIERS, OPTIMIZER_TIER_FIELD,\n PANEL_HEIGHT_FIELD,\n PANEL_RESIZE_FIELD, PANEL_WIDTH_FIELD, QUICK_CATEGORY_MAX,\n QUICK_CATEGORY_NAME_MAX, QUICK_LABEL_MAX,\n QUICK_PROMPT_MAX, QUICK_TEXT_MAX, REPO_URL, RESTART_API_PATH, SEND_PRESETS,\n KEYS_ENABLED_FIELD, MENU_ENABLED_FIELD, PANEL_ENABLED_FIELD, QUICK_ENABLED_FIELD,\n TERMINAL_ENABLED_FIELD, activeSections,\n insertModeOf, newQuickPromptId, newSessionId, optimizerPromptFieldOf,\n type ComposerUxSettings, type MenuField, type OptimizerTier, type QuickPrompt,\n type QuickPromptBook, type SettingsField,\n} from '../settings-contract.ts'\nimport {\n bookCounts, withCategoryAdded, withCategoryMoved, withCategoryRemoved, withCategoryRenamed,\n withInsertMode, withPromptAdded, withPromptMoved, withPromptMovedToCategory, withPromptPatched,\n withPromptRemoved,\n} from './prompt-book.ts'\nimport {\n TERMINAL_API_PATH, TERMINAL_BASH_PATH_FIELD, TERMINAL_MODES, TERMINAL_MODE_FIELD,\n sanitizeTerminalCandidates,\n} from '../terminal/contracts.ts'\nimport { AddPromptRow } from './AddPromptRow.tsx'\nimport { OptimizerPromptEditor } from './OptimizerPromptEditor.tsx'\nimport { InsertModeControl } from './InsertModeControl.tsx'\nimport { PillChoice } from './PillChoice.tsx'\nimport {\n evaluateRecordedKey, displayChord, type ChordEvent,\n} from './chords.ts'\nimport {\n description, hintError, hintInfo, kbd, pill, pillActive, row, rowDesc, rowText, rowTitle,\n textInput,\n} from './styles.ts'\n\n/** \u8BBE\u7F6E\u9875\u6CE8\u5165\u9762\u3002 */\nexport interface SettingsSectionInjected {\n hooks: {\n /** \u5F53\u524D\u89E3\u6790\u540E\u7684\u8BBE\u7F6E\u5FEB\u7167\u3002 */\n live: SnapshotStore<ComposerUxSettings>\n /** \u5FEB\u6377\u6307\u4EE4\u672C\uFF08\u771F\u76F8\u5728\u78C1\u76D8\u90A3\u4EFD quick-prompts.json\uFF1B\u8FD9\u91CC\u53EA\u662F\u5B83\u7684\u5BA2\u6237\u7AEF\u5FEB\u7167\uFF09\u3002 */\n book: SnapshotStore<QuickPromptBook>\n /** '' = \u6B63\u5E38\uFF1B'saving' = \u6B63\u5728\u5199\uFF1B\u5176\u4F59 = \u4E0A\u4E00\u6B21\u7684\u9519\u8BEF\u6587\u6848\u3002 */\n bookStatus: SnapshotStore<string>\n /**\n * \u8BBE\u7F6E\u5199\u5165\u7684\u8BF4\u660E\u884C\uFF1A'' = \u6B63\u5E38\uFF1B\u5176\u4F59\u662F\"\u88AB\u62D2 / \u5199\u4E86\u4F46\u6CA1\u751F\u6548\"\u7684\u539F\u56E0\u3002\n * \u5B58\u5728\u7684\u610F\u4E49\u5C31\u662F\u8BA9\u300C\u70B9\u4E86\u6CA1\u53CD\u5E94\u300D\u8FD9\u79CD\u6545\u969C\u81F3\u5C11\u8BF4\u5F97\u51FA\u8BDD\uFF08\u89C1 client.tsx \u7684 setField\uFF09\u3002\n */\n writeNotice: SnapshotStore<string>\n }\n actions: {\n /** \u5199\u4E00\u4E2A\u5B57\u6BB5\uFF08\u952E\u4F4D\u4E3A\u89C4\u8303\u4E32\uFF0C\u5F00\u5173\u4E3A\u5E03\u5C14\uFF0C\u5C3A\u5BF8\u4E3A\u6570\u5B57\uFF09\u3002 */\n setField: (field: SettingsField, value: unknown) => void\n /** \u6E05\u7A7A\u4E00\u4E2A\u5B57\u6BB5\uFF08\u56DE\u843D\u5230 schema \u9ED8\u8BA4\uFF09\u3002 */\n clearField: (field: SettingsField) => void\n /** \u5168\u90E8\u6062\u590D\u9ED8\u8BA4\uFF08\u6E05\u7A7A\u7528\u6237\u8986\u76D6\uFF0C\u56DE\u843D\u5230 schema \u9ED8\u8BA4\uFF1B\u5FEB\u6377\u6307\u4EE4\u53E6\u89C1 resetBook\uFF09\u3002 */\n resetAll: () => void\n /** \u6574\u672C\u5199\u56DE\uFF08\u7F16\u8F91\u5668\u91CC\u7684\u300C\u4FDD\u5B58\u4FEE\u6539\u300D\uFF09\u3002 */\n saveBook: (next: QuickPromptBook) => void\n /** \u4ECE\u78C1\u76D8\u91CD\u65B0\u8BFB\u53D6\uFF08\u522B\u7684\u7A97\u53E3\u6539\u8FC7\u65F6\u7684\u515C\u5E95\uFF09\u3002 */\n reloadBook: () => void\n /** \u6062\u590D\u5185\u7F6E 9 \u6761\uFF08\u5199\u56DE\u9ED8\u8BA4\u672C\uFF09\u3002 */\n resetBook: () => void\n /** \u5173\u6389\u9876\u90E8\u90A3\u6761\u5199\u5165\u5931\u8D25/\u672A\u751F\u6548\u7684\u8BF4\u660E\u3002 */\n dismissNotice: () => void\n }\n}\n\nexport type SettingsSectionProps =\n PropsRuntime<'settings.section'>\n & SettingsSectionOwnerProps\n & InjectFace<SettingsSectionInjected>\n\n/** \u5C55\u5F00\u533A\u5185\u7684\u5BFC\u8BED\u3002 */\nconst bodyLead: CSSProperties = { ...description, margin: '12px 0' }\n\n/** \u6298\u53E0\u7BAD\u5934\uFF08\u5185\u8054 SVG\uFF0C\u5C55\u5F00\u65F6\u9760\u7236\u7EA7 class \u65CB\u8F6C 180\u00B0\uFF09\u3002 */\nfunction Chevron() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M3.25 5.5L7 9.25L10.75 5.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.4\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )\n}\n\n/**\n * \u53EF\u6298\u53E0\u680F\u76EE\uFF1A\u6807\u9898\u884C\u5DE6\u4FA7\u662F\u5C55\u5F00\u6309\u94AE\uFF08\u6574\u5757\u53EF\u70B9\uFF09\uFF0C\u53F3\u4FA7\u662F**\u8FD9\u4E00\u680F\u7684\u5F00\u5173**\u4E0E\u4ECE\u5C5E\u63A7\u4EF6\uFF1B\n * \u9ED8\u8BA4\u6298\u53E0\u4E14\u4E0D\u8BB0\u5FC6\u5C55\u5F00\u72B6\u6001\uFF08\u6BCF\u6B21\u6253\u5F00\u8BBE\u7F6E\u9875\u90FD\u56DE\u5230\u6298\u53E0\uFF09\u3002\n */\nfunction FoldCard(props: {\n name: string\n summary: string\n /** \u8FD9\u4E00\u680F\u7684\u5F00\u5173\uFF08\u516D\u680F\u90FD\u6709\uFF09\u3002\u5173\u6389\u65F6\u6982\u89C8\u524D\u4F1A\u52A0\u300C\u672A\u542F\u7528 \u00B7 \u300D\uFF0C\u5361\u7247\u63CF\u8FB9\u53D8\u865A\u7EBF\u3002 */\n toggle?: { readonly checked: boolean; readonly onChange: (next: boolean) => void }\n /** \u6807\u9898\u884C\u53F3\u4FA7\u3001\u5F00\u5173\u5DE6\u8FB9\u7684\u4ECE\u5C5E\u63A7\u4EF6\uFF08\u4E09\u6863 / \u5C0F\u5F00\u5173\uFF09\u3002 */\n controls?: React.ReactNode\n children: React.ReactNode\n}) {\n const [open, setOpen] = useState(false)\n const off = props.toggle !== undefined && props.toggle.checked === false\n return (\n <section className={[\n 'dsh-ux-card',\n open ? 'dsh-ux-cardOpen' : '',\n off ? 'dsh-ux-cardOff' : '',\n ].filter(part => part !== '').join(' ')}>\n {/*\n \u6807\u9898\u884C\u5206\u6210\u4E24\u5757\uFF1A\u5DE6\u8FB9\u6574\u5757\u662F\"\u5C55\u5F00\"\u6309\u94AE\uFF08\u6574\u884C\u53EF\u70B9\uFF0C\u952E\u76D8\u53EF\u8FBE\uFF09\uFF0C\u53F3\u8FB9\u662F\u4ECE\u5C5E\u63A7\u4EF6 + \u672C\u680F\u5F00\u5173\u3002\n \u4E0D\u80FD\u5728 <button> \u91CC\u585E\u6309\u94AE\uFF08HTML \u4E0D\u5141\u8BB8\u3001\u70B9\u51FB\u4E5F\u4F1A\u5192\u6CE1\u6210\"\u5C55\u5F00\"\uFF09\uFF0C\u6240\u4EE5\u62C6\u6210\u5144\u5F1F\u8282\u70B9\u3002\n */}\n <div className=\"dsh-ux-cardHeaderRow\">\n <button\n type=\"button\"\n className=\"dsh-ux-cardHeader\"\n aria-expanded={open}\n onClick={() => { setOpen(current => !current) }}\n >\n <span className=\"dsh-ux-cardHeadText\">\n <span className=\"dsh-ux-cardName\">{props.name}</span>\n <span className=\"dsh-ux-cardDescription\">\n {off ? `\u672A\u542F\u7528 \u00B7 ${props.summary}` : props.summary}\n </span>\n </span>\n <span className={open ? 'dsh-ux-cardChevron dsh-ux-cardChevronOpen' : 'dsh-ux-cardChevron'}>\n <Chevron />\n </span>\n </button>\n <span className=\"dsh-ux-cardControls\">\n {props.controls}\n {props.toggle !== undefined && (\n <Switch\n small\n label={`${props.name}\uFF1A\u542F\u7528\u8FD9\u4E00\u680F`}\n checked={props.toggle.checked}\n onChange={props.toggle.onChange}\n />\n )}\n </span>\n </div>\n {open && <div className=\"dsh-ux-cardBody\">{props.children}</div>}\n </section>\n )\n}\n\n/** \u952E\u4F4D\u884C\uFF1A\u5F53\u524D\u503C + \u9884\u8BBE + \u5F55\u5236 + \u6E05\u9664\u3002 */\nfunction KeyRow(props: {\n title: string\n desc: string\n value: string\n presets: readonly string[]\n conflict: (chord: string) => boolean\n onChange: (chord: string) => void\n /** \u5C55\u5F00\u533A\u91CC\u7684\u7B2C\u4E00\u884C\uFF1A\u4E0D\u753B\u4E0A\u8FB9\u6846\uFF08\u5185\u5BB9\u533A\u81EA\u5DF1\u6709\u4E00\u6761\u5206\u9694\u7EBF\uFF09\u3002 */\n first?: boolean\n}) {\n const { title, desc, value, presets, conflict, onChange, first } = props\n const [recording, setRecording] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n useEffect(() => {\n if (!recording) return\n const onKeyDown = (event: KeyboardEvent): void => {\n // \u5F55\u5236\u671F\u95F4\u541E\u6389\u6240\u6709\u6309\u952E\uFF0C\u907F\u514D\u6C61\u67D3\u8F93\u5165\u6846\u6216\u9875\u9762\u3002\n event.preventDefault()\n event.stopPropagation()\n if (event.isComposing) return\n const result = evaluateRecordedKey(event as unknown as ChordEvent)\n if (result.kind === 'ignore') return\n if (result.kind === 'cancel') {\n setRecording(false)\n setError(null)\n return\n }\n if (result.kind === 'clear') {\n setRecording(false)\n setError(null)\n onChange('')\n return\n }\n if (result.kind === 'reject') {\n setError(result.message)\n return\n }\n if (conflict(result.chord)) {\n setRecording(false)\n setError('\u53D1\u9001\u4E0E\u6362\u884C\u4E0D\u80FD\u8BBE\u4E3A\u76F8\u540C\u6309\u952E\uFF08\u53EF\u5148\u7ED9\u53E6\u4E00\u4FA7\u6362\u952E\uFF0C\u518D\u7ED1\u5B9A\u8BE5\u952E\uFF09\u3002')\n return\n }\n setRecording(false)\n setError(null)\n onChange(result.chord)\n }\n window.addEventListener('keydown', onKeyDown, true)\n return () => { window.removeEventListener('keydown', onKeyDown, true) }\n }, [recording, conflict, onChange])\n\n const base = first === true ? { ...row, borderTop: 'none' } : row\n\n return (\n <div style={{ ...base, flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>{title}</div>\n <div style={rowDesc}>{desc}</div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>\n <span style={kbd}>{displayChord(value)}</span>\n {!recording && presets.map(preset => (\n <button\n key={preset}\n type=\"button\"\n style={value === preset ? pillActive : pill}\n onClick={() => { setError(null); onChange(preset) }}\n >\n {displayChord(preset)}\n </button>\n ))}\n {!recording && value !== '' && (\n <button type=\"button\" style={pill} onClick={() => { setError(null); onChange('') }}>\n \u6E05\u9664\n </button>\n )}\n <button\n type=\"button\"\n style={recording ? pillActive : pill}\n onClick={() => { setRecording(true); setError(null) }}\n >\n {recording ? '\u8BF7\u6309\u4E0B\u65B0\u7EC4\u5408\u952E\u2026' : '\u81EA\u5B9A\u4E49\u2026'}\n </button>\n {recording && (\n <button type=\"button\" style={pill} onClick={() => { setRecording(false); setError(null) }}>\n Esc \u53D6\u6D88\n </button>\n )}\n {error !== null && (\n <span style={{ color: 'var(--dsw-alias-state-error-primary)', fontSize: 12 }}>{error}</span>\n )}\n </div>\n </div>\n )\n}\n\n/**\n * \u5F00\u5173\uFF08\u80F6\u56CA\u6ED1\u5757\uFF09\u3002\n *\n * \u62BD\u51FA\u6765\u662F\u56E0\u4E3A\u5B83\u73B0\u5728\u6709\u4E24\u4E2A\u5C3A\u7801\uFF1A\u5361\u7247\u5185\u5BB9\u533A\u91CC\u7528 `md`\uFF0836\u00D720\uFF09\uFF0C\u6298\u53E0\u5361**\u6807\u9898\u884C**\u91CC\n * \u7528 `sm`\uFF0830\u00D716\uFF0C\u8DDF 11px \u7684\u6807\u9898\u5B57\u4E00\u884C\u653E\u5F97\u4E0B\uFF09\u3002\u5F00\u5173\u753B\u4E24\u904D\u8FDF\u65E9\u4F1A\u5206\u53C9\u3002\n */\nfunction Switch(props: {\n checked: boolean\n onChange: (next: boolean) => void\n /** \u65E0\u969C\u788D\u540D\u5B57\uFF08\u6807\u9898\u884C\u91CC\u7684\u5F00\u5173\u6CA1\u6709\u53EF\u89C1\u6587\u5B57\uFF0C\u5FC5\u987B\u7ED9\uFF09\u3002 */\n label: string\n small?: boolean\n}) {\n const { checked, onChange, label, small = false } = props\n const width = small ? 30 : 36\n const height = small ? 16 : 20\n const knob = small ? 12 : 14\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={label}\n title={label}\n onClick={() => { onChange(!checked) }}\n style={{\n width,\n height,\n borderRadius: 999,\n border: '0.5px solid var(--dsw-alias-border-l2)',\n cursor: 'pointer',\n background: checked\n ? 'var(--dsw-alias-button-primary-fill)'\n : 'var(--dsw-alias-interactive-bg-hover)',\n position: 'relative',\n flex: '0 0 auto',\n padding: 0,\n }}\n >\n <span\n style={{\n position: 'absolute',\n top: small ? 1 : 2,\n left: checked ? width - knob - (small ? 1 : 2) : (small ? 1 : 2),\n width: knob,\n height: knob,\n borderRadius: '50%',\n background: checked\n ? 'var(--dsw-alias-label-primary-foreground)'\n : 'var(--dsw-alias-label-secondary)',\n transition: 'left 0.12s ease',\n }}\n />\n </button>\n )\n}\n\n/** \u6807\u9898\u884C\u91CC\u7684\"\u6587\u5B57 + \u5C0F\u5F00\u5173\"\uFF08\u300C\u5BFC\u822A\u6EDA\u52A8\u300D\u300C\u8FB9\u7F18\u7F29\u653E\u300D\u8FD9\u7C7B\uFF09\u3002 */\nfunction MiniToggle(props: {\n label: string\n checked: boolean\n onChange: (next: boolean) => void\n}) {\n return (\n <span className=\"dsh-ux-miniToggle\">\n <span className=\"dsh-ux-miniToggleLabel\">{props.label}</span>\n <Switch small label={props.label} checked={props.checked} onChange={props.onChange} />\n </span>\n )\n}\n\n/** \u5F00\u5173\u884C\u3002 */\nfunction ToggleRow(props: {\n label: string\n desc?: string\n checked: boolean\n onChange: (next: boolean) => void\n /** \u5C55\u5F00\u533A\u91CC\u7684\u7B2C\u4E00\u884C\uFF1A\u4E0D\u753B\u4E0A\u8FB9\u6846\u3002 */\n first?: boolean\n}) {\n const { label, desc, checked, onChange, first } = props\n return (\n <div style={first === true ? { ...row, borderTop: 'none' } : row}>\n <div style={rowText}>\n <div style={rowTitle}>{label}</div>\n {desc !== undefined && desc !== '' && <div style={rowDesc}>{desc}</div>}\n </div>\n <Switch label={label} checked={checked} onChange={onChange} />\n </div>\n )\n}\n\n/** \u6587\u672C\u5B57\u6BB5\u884C\uFF1A\u6807\u9898 + \u8BF4\u660E + \u8F93\u5165\u6846\uFF08\u53EF\u9009\u52A8\u4F5C\u6309\u94AE\uFF09\u3002\n * \u8F93\u5165\u8FC7\u7A0B\u4E2D\u53EA\u6539\u672C\u5730\u8349\u7A3F\uFF0C\u5931\u7126\u6216\u56DE\u8F66\u624D\u843D\u76D8\u2014\u2014\u907F\u514D\u6BCF\u6572\u4E00\u4E2A\u5B57\u5C31\u5199\u4E00\u6B21\u914D\u7F6E\u6587\u4EF6\u3002 */\nfunction TextFieldRow(props: {\n title: string\n desc: string\n value: string\n placeholder?: string\n maxLength: number\n onChange: (next: string) => void\n action?: { label: string; onClick: () => void }\n /** \u5C55\u5F00\u533A\u91CC\u7684\u7B2C\u4E00\u884C\uFF1A\u4E0D\u753B\u4E0A\u8FB9\u6846\u3002 */\n first?: boolean\n}) {\n const { title, desc, value, placeholder, maxLength, onChange, action, first } = props\n const [draft, setDraft] = useState(value)\n const focused = useRef(false)\n\n // \u53EA\u5728\u6CA1\u6709\u7126\u70B9\u65F6\u8DDF\u968F\u5916\u90E8\u503C\uFF1A\u5199\u76D8\u662F\u5F02\u6B65\u5F80\u8FD4\uFF0C\u8F93\u5165\u4E2D\u540C\u6B65\u4F1A\u628A\u7528\u6237\u6B63\u5728\u6253\u7684\u5B57\u56DE\u6EDA\u3002\n useEffect(() => {\n if (!focused.current) setDraft(value)\n }, [value])\n\n const commit = (): void => {\n if (draft === value) return\n onChange(draft.trim())\n }\n\n const base = first === true ? { ...row, borderTop: 'none' } : row\n\n return (\n <div style={{ ...base, flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>{title}</div>\n <div style={rowDesc}>{desc}</div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n <input\n type=\"text\"\n value={draft}\n placeholder={placeholder ?? ''}\n maxLength={maxLength}\n spellCheck={false}\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n onFocus={() => { focused.current = true }}\n onChange={event => { setDraft(event.target.value) }}\n onBlur={() => { focused.current = false; commit() }}\n onKeyDown={event => {\n if (event.key !== 'Enter') return\n event.preventDefault()\n commit()\n event.currentTarget.blur()\n }}\n style={textInput}\n />\n {action !== undefined && (\n <button type=\"button\" style={pill} onClick={action.onClick}>{action.label}</button>\n )}\n </div>\n </div>\n )\n}\n\n/** \u5FEB\u6377\u6307\u4EE4\u7F16\u8F91\u533A\uFF1A\u672C\u5730\u8349\u7A3F + \u663E\u5F0F\u4FDD\u5B58\uFF08\u907F\u514D\u6BCF\u6572\u4E00\u4E2A\u5B57\u5C31\u5199\u4E00\u6B21\u914D\u7F6E\u6587\u4EF6\uFF09\u3002 */\n/**\n * \u5FEB\u6377\u6307\u4EE4\u7F16\u8F91\u5668\uFF080.3.0 \u8D77\u7684\u5206\u7C7B\u4E24\u7EA7\u7ED3\u6784\uFF09\u3002\n *\n * \u7F16\u8F91\u5728**\u672C\u5730\u8349\u7A3F**\u4E0A\u505A\uFF1A\u8349\u7A3F\u7528 `prompt-book.ts` \u90A3\u5957\u7EAF\u51FD\u6570\u6539\uFF08\u4E0E\u670D\u52A1\u7AEF\u540C\u4E00\u5957\u903B\u8F91\uFF09\uFF0C\n * \u53EA\u6709\u70B9\u300C\u4FDD\u5B58\u4FEE\u6539\u300D\u624D\u6574\u672C\u5199\u56DE \u2014\u2014 \u5426\u5219\u6BCF\u6572\u4E00\u4E2A\u5B57\u5C31\u662F\u4E00\u6B21 HTTP + \u4E00\u6B21\u539F\u5B50\u5199\u3002\n *\n * \u4FDD\u5B58\u540E\u5BBF\u4E3B\u4F1A\u56DE\u8BFB\u78C1\u76D8\u771F\u5B9E\u5185\u5BB9\u5E76\u8986\u76D6\u672C\u5730\u5FEB\u7167\uFF0C\u8349\u7A3F\u8DDF\u7740\u5B83\u8D70\uFF1A\u4E8E\u662F\u300C\u7A7A\u6B63\u6587\u7684\u6761\u76EE\u88AB\n * \u51C0\u5316\u4E22\u5F03\u300D\u8FD9\u7C7B\u6536\u7A84\u4F1A\u5728\u754C\u9762\u4E0A\u7ACB\u523B\u663E\u73B0\uFF0C\u800C\u4E0D\u662F\u7B49\u5230\u4E0B\u6B21\u6253\u5F00\u8BBE\u7F6E\u624D\u53D1\u73B0\u4E0D\u4E00\u6837\u3002\n */\nfunction QuickPromptsEditor(props: {\n book: QuickPromptBook\n status: string\n onSave: (next: QuickPromptBook) => void\n onReset: () => void\n onReload: () => void\n}) {\n const [draft, setDraft] = useState<QuickPromptBook>(() => props.book)\n const [activeId, setActiveId] = useState(() => props.book.categories[0]?.id ?? '')\n const [dirty, setDirty] = useState(false)\n const [newName, setNewName] = useState('')\n /** \u4E0A\u4E00\u6B21\u4FDD\u5B58\u65F6\u8DF3\u8FC7\u7A7A\u6761\u76EE\u7684\u8BF4\u660E\uFF08\u7A7A\u4E32 = \u65E0\uFF09\u3002 */\n const [note, setNote] = useState('')\n\n // \u672C\u5730\u6CA1\u6709\u672A\u4FDD\u5B58\u4FEE\u6539\u65F6\u8DDF\u968F\u5916\u90E8\u5FEB\u7167\u3002\n useEffect(() => {\n if (dirty) return\n setDraft(props.book)\n if (!props.book.categories.some(category => category.id === activeId)) {\n setActiveId(props.book.categories[0]?.id ?? '')\n }\n }, [props.book, dirty, activeId])\n\n const edit = (next: QuickPromptBook): void => {\n setDirty(true)\n setDraft(next)\n }\n const current = draft.categories.find(category => category.id === activeId) ?? draft.categories[0]\n const counts = bookCounts(draft)\n const saving = props.status === 'saving'\n const failed = props.status !== '' && props.status !== 'saving'\n\n const rowBox: CSSProperties = {\n display: 'flex', flexDirection: 'column', gap: 6,\n padding: 8, borderRadius: 8,\n border: '0.5px solid var(--dsw-alias-border-l2)',\n background: 'var(--dsw-alias-bg-layer-1)',\n }\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>\n {/* \u5206\u7C7B\u5207\u6362 + \u65B0\u589E */}\n <div style={{ display: 'flex', alignItems: 'center', gap: 4, flexWrap: 'wrap' }}>\n {draft.categories.map(category => (\n <button\n key={category.id}\n type=\"button\"\n style={category.id === current?.id ? pillActive : pill}\n onClick={() => { setActiveId(category.id) }}\n >\n {category.name}\uFF08{category.prompts.length}\uFF09\n </button>\n ))}\n <input\n type=\"text\"\n value={newName}\n placeholder=\"\u65B0\u5206\u7C7B\u540D\"\n maxLength={QUICK_CATEGORY_NAME_MAX}\n spellCheck={false}\n onChange={event => { setNewName(event.target.value) }}\n style={{ ...textInput, flex: '0 0 110px' }}\n />\n <button\n type=\"button\"\n style={pill}\n disabled={draft.categories.length >= QUICK_CATEGORY_MAX}\n onClick={() => {\n edit(withCategoryAdded(draft, newName === '' ? DEFAULT_CATEGORY_NAME : newName))\n setNewName('')\n }}\n >\n + \u52A0\u5206\u7C7B\n </button>\n </div>\n\n {current === undefined && (\n <p style={rowDesc}>\u8FD8\u6CA1\u6709\u5206\u7C7B\u3002\u5148\u52A0\u4E00\u4E2A\u5206\u7C7B\uFF0C\u518D\u5F80\u91CC\u653E\u6761\u76EE\u3002</p>\n )}\n\n {current !== undefined && (\n <>\n {/* \u5F53\u524D\u5206\u7C7B\uFF1A\u6539\u540D / \u6362\u4F4D / \u5220\u9664 */}\n <div style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>\n <input\n type=\"text\"\n value={current.name}\n aria-label=\"\u5206\u7C7B\u540D\"\n maxLength={QUICK_CATEGORY_NAME_MAX}\n spellCheck={false}\n onChange={event => { edit(withCategoryRenamed(draft, current.id, event.target.value)) }}\n style={{ ...textInput, flex: '0 0 150px' }}\n />\n <button type=\"button\" style={pill} title=\"\u5206\u7C7B\u4E0A\u79FB\" onClick={() => { edit(withCategoryMoved(draft, current.id, -1)) }}>\u2191</button>\n <button type=\"button\" style={pill} title=\"\u5206\u7C7B\u4E0B\u79FB\" onClick={() => { edit(withCategoryMoved(draft, current.id, 1)) }}>\u2193</button>\n <button\n type=\"button\"\n style={pill}\n title=\"\u5220\u9664\u8FD9\u4E2A\u5206\u7C7B\uFF08\u8FDE\u540C\u5B83\u91CC\u9762\u7684\u6761\u76EE\uFF09\"\n onClick={() => { edit(withCategoryRemoved(draft, current.id)) }}\n >\n \u2715 \u5220\u9664\u5206\u7C7B\n </button>\n <span style={rowDesc}>{current.prompts.length} / {QUICK_PROMPT_MAX} \u6761</span>\n </div>\n\n {current.prompts.map(prompt => (\n <div key={prompt.id} style={rowBox}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>\n <input\n type=\"text\"\n value={prompt.label}\n placeholder=\"\u540D\u79F0\uFF0C\u5982\uFF1A\u4EC5\u8BF4\u660E\u539F\u56E0\"\n maxLength={QUICK_LABEL_MAX}\n spellCheck={false}\n onChange={event => { edit(withPromptPatched(draft, current.id, prompt.id, { label: event.target.value })) }}\n style={{ ...textInput, flex: '0 0 150px' }}\n />\n <InsertModeControl\n label={prompt.label}\n mode={insertModeOf(prompt)}\n onChange={mode => { edit(withInsertMode(draft, prompt.id, mode)) }}\n />\n <span style={{ flex: 1 }} />\n <button type=\"button\" style={pill} title=\"\u4E0A\u79FB\" onClick={() => { edit(withPromptMoved(draft, current.id, prompt.id, -1)) }}>\u2191</button>\n <button type=\"button\" style={pill} title=\"\u4E0B\u79FB\" onClick={() => { edit(withPromptMoved(draft, current.id, prompt.id, 1)) }}>\u2193</button>\n <button type=\"button\" style={pill} title=\"\u5220\u9664\u8FD9\u6761\" onClick={() => { edit(withPromptRemoved(draft, current.id, prompt.id)) }}>\u2715</button>\n </div>\n <textarea\n value={prompt.prompt}\n placeholder=\"\u63D0\u793A\u8BCD\u6B63\u6587\uFF1A\u70B9\u51FB\u8BE5\u6761\u76EE\u65F6\u63D2\u5165\u8F93\u5165\u6846\uFF1B\u52FE\u4E86\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u5219\u5728\u53D1\u9001\u65F6\u81EA\u52A8\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E\"\n maxLength={QUICK_TEXT_MAX}\n spellCheck={false}\n rows={Math.min(4, Math.max(2, Math.ceil(prompt.prompt.length / 46)))}\n onChange={event => { edit(withPromptPatched(draft, current.id, prompt.id, { prompt: event.target.value })) }}\n style={{ ...textInput, resize: 'vertical', fontFamily: 'inherit', lineHeight: 1.5 }}\n />\n </div>\n ))}\n\n {/* \u5217\u8868\u6700\u4E0B\u8FB9\u7684\u300C\uFF0B\u300D\uFF1A\u65B0\u5EFA / \u628A\u522B\u7684\u5206\u7C7B\u7684\u6761\u76EE\u79FB\u52A8\u5230\u8FD9\u91CC\uFF08\u4E0E\u9762\u677F\u540C\u4E00\u7EC4\u4EF6\uFF09 */}\n <AddPromptRow\n book={draft}\n categoryId={current.id}\n onAdd={() => { edit(withPromptAdded(draft, current.id)) }}\n onMove={promptId => { edit(withPromptMovedToCategory(draft, promptId, current.id)) }}\n />\n </>\n )}\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>\n <button\n type=\"button\"\n style={dirty ? pillActive : pill}\n disabled={!dirty || saving}\n onClick={() => {\n // \u5148\u628A\u6B63\u6587\u4E3A\u7A7A\u7684\u6761\u76EE\u5254\u6389**\u5E76\u8BF4\u660E**\uFF1A\u51C0\u5316\u7AEF\u4E5F\u4F1A\u4E22\u5B83\u4EEC\uFF0C\u4F46\u82E5\u8BA9\u7528\u6237\u81EA\u5DF1\u53D1\u73B0\n // \u300C\u6211\u52A0\u7684\u8FD9\u6761\u600E\u4E48\u6CA1\u4E86\u300D\uFF0C\u90A3\u662F\u4E00\u6B21\u8BF4\u4E0D\u6E05\u7684\u9759\u9ED8\u4E22\u5931\u3002\n const next: QuickPromptBook = {\n version: draft.version,\n categories: draft.categories.map(category => ({\n ...category,\n prompts: category.prompts.filter(prompt => prompt.prompt.trim() !== ''),\n })),\n }\n const skipped = counts.prompts - bookCounts(next).prompts\n setNote(skipped > 0 ? `\u5DF2\u8DF3\u8FC7 ${String(skipped)} \u6761\u6B63\u6587\u4E3A\u7A7A\u7684\u6761\u76EE` : '')\n props.onSave(next)\n setDirty(false)\n }}\n >\n {saving ? '\u4FDD\u5B58\u4E2D\u2026' : (dirty ? '\u4FDD\u5B58\u4FEE\u6539' : '\u5DF2\u4FDD\u5B58')}\n </button>\n <button type=\"button\" style={pill} onClick={() => { props.onReload() }}>\u91CD\u65B0\u8BFB\u53D6</button>\n <button type=\"button\" style={pill} onClick={() => { props.onReset() }}>\u6062\u590D\u5185\u7F6E 9 \u6761</button>\n <span style={rowDesc}>\n \u5171 {counts.categories} \u4E2A\u5206\u7C7B \u00B7 {counts.prompts} \u6761 \u00B7 \u6BCF\u6B21 {counts.always} \u6761 \u00B7 \u4EC5\u9996\u6B21 {counts.first} \u6761\n {note === '' ? '' : ` \u00B7 ${note}`}\n {failed ? ` \u00B7 ${props.status}` : ''}\n </span>\n </div>\n <p style={rowDesc}>\n \u6570\u636E\u5B58\u5728 <code>~/.dsh/quick-prompts.json</code>\uFF08\u4E0E\u4F1A\u8BDD\u3001\u9879\u76EE\u65E0\u5173\uFF0C\u53EF\u5355\u72EC\u5907\u4EFD\u6216\u624B\u5DE5\u7F16\u8F91\uFF0C\n \u6539\u5B8C\u70B9\u300C\u91CD\u65B0\u8BFB\u53D6\u300D\u5373\u53EF\u52A0\u8F7D\uFF09\u3002\n </p>\n </div>\n )\n}\n\n/** \u5019\u9009\u6309\u94AE\u7684\u6837\u5F0F\uFF1A\u4E0E\u80F6\u56CA\u540C\u6E90\uFF0C\u4F46\u8981\u80FD\u663E\u793A\u957F\u8DEF\u5F84\u3002 */\nconst candidatePill: CSSProperties = {\n ...pill,\n textAlign: 'left',\n maxWidth: '100%',\n overflowWrap: 'anywhere',\n lineHeight: 1.4,\n}\n\n/**\n * \u300C\u9ED8\u8BA4\u7EC8\u7AEF\u300D\u5361\u7247\u5185\u5BB9\uFF08Windows\uFF1A\u628A\u7EC8\u7AEF\u7684 pwsh \u6362\u6210 Git Bash\uFF09\u3002\n *\n * \u4E0E\u5176\u5B83\u5361\u7247\u7684\u533A\u522B\uFF1A\u72B6\u6001\u3001\u5019\u9009\u8868\u3001\u5F53\u524D\u751F\u6548 shell \u4E09\u9879\u90FD\u662F**\u5BBF\u4E3B\u534A**\u5199\u7684\n * \uFF08settings \u91CC\u7684 terminalStatus / terminalCandidates / terminalEffective\uFF0C\u89C1 HOST_OWNED_FIELDS\uFF09\uFF0C\n * \u8FD9\u91CC\u53EA\u8BFB\u5C55\u793A\uFF1B\u7528\u6237\u80FD\u6539\u7684\u53EA\u6709\u300C\u6863\u4F4D\u300D\u4E0E\u300C\u8DEF\u5F84\u300D\u4E24\u9879\u3002\n */\nfunction DefaultTerminalBody(props: {\n readonly settings: ComposerUxSettings\n readonly setField: (field: SettingsField, value: unknown) => void\n /** \u6863\u4F4D\u80F6\u56CA\u5DF2\u7ECF\u642C\u5230\u6298\u53E0\u5361\u6807\u9898\u884C\u65F6\u4F20 true\uFF08\u5185\u5BB9\u533A\u4E0D\u518D\u91CD\u590D\u4E00\u4EFD\uFF09\u3002 */\n readonly hideMode?: boolean\n}) {\n const { settings, setField, hideMode = false } = props\n const [note, setNote] = useState('')\n const [busy, setBusy] = useState(false)\n const candidates = settings.terminalCandidates\n\n if (settings.terminalEffective === 'unsupported') {\n return (\n <p style={hintInfo}>\n \u672C\u63D2\u4EF6\u53EA\u5728 Windows \u4E0A\u63A5\u7BA1\u7EC8\u7AEF\uFF08Windows \u4E0A DSH \u9ED8\u8BA4\u7ED9\u6A21\u578B\u7684\u662F PowerShell\uFF09\u3002\u5F53\u524D\u5E73\u53F0\u4E0D\u9700\u8981\u5B83\uFF0C\n \u8FD9\u91CC\u7684\u8BBE\u7F6E\u4E0D\u4F1A\u751F\u6548\u3002\n </p>\n )\n }\n\n /** \u70B9\u300C\u81EA\u52A8\u53D1\u73B0\u300D\uFF1A\u8BA9\u5BBF\u4E3B\u534A\u91CD\u65B0\u626B\u4E00\u904D\u672C\u673A\uFF08\u6D4F\u89C8\u5668\u78B0\u4E0D\u5230\u6587\u4EF6\u7CFB\u7EDF\uFF09\u3002 */\n const discover = async (): Promise<void> => {\n setBusy(true)\n setNote('')\n try {\n const response = await fetch(TERMINAL_API_PATH, { method: 'POST' })\n const parsed = await response.json() as { candidates?: unknown }\n const found = sanitizeTerminalCandidates(parsed.candidates)\n setNote(found.length === 0\n ? '\u6CA1\u6709\u627E\u5230\u53EF\u7528\u7684 bash\uFF08WSL \u7684 bash.exe \u4F1A\u88AB\u5FFD\u7565\uFF0C\u5B83\u6309 Linux \u89C4\u5219\u89E3\u91CA\u8DEF\u5F84\uFF09'\n : `\u627E\u5230 ${String(found.length)} \u4E2A\u5019\u9009\uFF0C\u5DF2\u5217\u5728\u4E0B\u65B9`)\n } catch (error: unknown) {\n setNote(`\u81EA\u52A8\u53D1\u73B0\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`)\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <>\n {!hideMode && (\n <div style={{ ...row, borderTop: 'none', flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>\u7EC8\u7AEF\u5DE5\u5177</div>\n <div style={rowDesc}>\n {TERMINAL_MODES.find(item => item.id === settings.terminalMode)?.hint ?? ''}\n </div>\n </div>\n <PillChoice\n items={TERMINAL_MODES}\n value={settings.terminalMode}\n onChange={mode => { setField(TERMINAL_MODE_FIELD, mode) }}\n ariaLabel=\"\u7EC8\u7AEF\u5DE5\u5177\"\n />\n </div>\n )}\n\n {settings.terminalMode !== 'pwsh' && (<>\n <TextFieldRow\n title=\"Git Bash \u8DEF\u5F84\"\n desc=\"\u7559\u7A7A = \u7528\u81EA\u52A8\u63A2\u6D4B\u5230\u7684\u90A3\u4E00\u4E2A\uFF08\u5148\u627E git\uFF0C\u518D\u7531\u540C\u4E00\u4E2A\u5B89\u88C5\u53CD\u63A8 bash\uFF09\"\n value={settings.terminalBashPath}\n placeholder=\"\u7559\u7A7A = \u81EA\u52A8\"\n maxLength={400}\n onChange={next => { setField(TERMINAL_BASH_PATH_FIELD, next) }}\n action={{ label: busy ? '\u63A2\u6D4B\u4E2D\u2026' : '\u81EA\u52A8\u53D1\u73B0', onClick: () => { void discover() } }}\n />\n {candidates.length > 0 && (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: 2 }}>\n {candidates.map(candidate => (\n <button\n key={candidate.path}\n type=\"button\"\n title={candidate.path}\n style={candidate.path === settings.terminalBashPath ? { ...candidatePill, ...pillActive } : candidatePill}\n onClick={() => { setField(TERMINAL_BASH_PATH_FIELD, candidate.path) }}\n >\n {candidate.label}\uFF1A{candidate.path}{candidate.explicit ? '\uFF08\u4F60\u586B\u7684\uFF09' : ''}\n </button>\n ))}\n </div>\n )}\n {note !== '' && <p style={hintInfo}>{note}</p>}\n </>)}\n\n <p style={hintInfo}>\n \u72B6\u6001\uFF1A{settings.terminalStatus === '' ? '\u7B49\u5F85\u5BBF\u4E3B\u534A\u63A2\u6D4B\u2026' : settings.terminalStatus}\n </p>\n <p style={hintInfo}>\n \u00B7 \u6362\u6210 Git Bash \u540E\uFF0C\u6A21\u578B\u770B\u5230\u7684\u7EC8\u7AEF\u5DE5\u5177\u5C31\u53EB bash\uFF08\u547D\u4EE4\u6309 bash/POSIX \u5199\uFF09\uFF0CPowerShell \u90A3\u4E2A\u5DE5\u5177\n \u4F1A\u4ECE\u5B83\u7684\u5DE5\u5177\u5217\u8868\u91CC\u6D88\u5931 \u2014\u2014 \u4E00\u4E2A\u4F1A\u8BDD\u53EA\u9762\u5BF9\u4E00\u4E2A\u7EC8\u7AEF\u5DE5\u5177\u3002\n </p>\n <p style={hintInfo}>\n \u00B7 \u6539\u6863\u4F4D\u4F1A\u7ACB\u523B\u91CD\u65B0\u4E0B\u53D1\u7ED9\u6B63\u5728\u8DD1\u7684\u4F1A\u8BDD\u3002\u4F46\u4F1A\u8BDD\u5386\u53F2\u91CC\u53EF\u80FD\u8FD8\u7559\u7740\u65E7\u5DE5\u5177\u540D\uFF1A\u5982\u679C\u54EA\u513F\u62A5\u4E86\n unknown tool \u4E4B\u7C7B\u7684\u9519\uFF0C\u8BA9\u6A21\u578B\u6539\u7528 bash \u91CD\u8BD5\u5373\u53EF\uFF0C\u4E0D\u5F71\u54CD\u4F1A\u8BDD\u672C\u8EAB\u3002\n </p>\n <p style={hintInfo}>\n \u00B7 \u53EA\u5BF9 Windows \u751F\u6548\uFF1BWSL \u7684 bash.exe \u4F1A\u88AB\u4E3B\u52A8\u6392\u9664\uFF08\u5B83\u628A D:\\ \u8FD9\u7C7B\u8DEF\u5F84\u89E3\u91CA\u6210 /mnt/d\uFF0C\u4E0E\u6A21\u578B\u624B\u91CC\u7684\n Windows \u5DE5\u4F5C\u76EE\u5F55\u4E0D\u517C\u5BB9\uFF09\u3002\u6C99\u7BB1\u3001\u5BA1\u6279\u3001\u8D85\u65F6\u4E0E\u8F93\u51FA\u622A\u65AD\u7684\u884C\u4E3A\u4E0E DSH \u81EA\u5E26\u7EC8\u7AEF\u4E00\u81F4\u3002\n </p>\n </>\n )\n}\n\n/**\n * \u300C\u91CD\u542F DSH\u300D\uFF1A\u62AC\u5934\u53F3\u7AEF\u4E00\u679A\u6309\u94AE + \u62AC\u5934\u6B63\u4E0B\u65B9\u7684\u786E\u8BA4\u6761\u3002\n *\n * \u673A\u5236\uFF08\u5BBF\u4E3B\u534A\uFF0C\u89C1 `src/restart.ts`\uFF09\u7167\u642C\u63D2\u4EF6\u5E02\u573A\uFF1A\u5206\u79BB\u4E00\u4E2A node \u52A9\u624B\u8FDB\u7A0B \u2192 \u81EA\u5DF1\u9000\u51FA \u2192\n * \u52A9\u624B\u7B49\u7AEF\u53E3\u771F\u7684\u7A7A\u51FA\u6765 \u2192 \u7528\u9690\u85CF\u63A7\u5236\u53F0\u7684 PowerShell \u8D77\u65B0\u5BBF\u4E3B \u2192 20 \u79D2\u5185\u786E\u8BA4\u7AEF\u53E3\u6709\u4EBA\u76D1\u542C\u3002\n * \u754C\u9762\u8FD9\u4E00\u4FA7\u53EA\u7BA1\u4E09\u4EF6\u4E8B\uFF1A**\u4E24\u6B65\u786E\u8BA4**\u3001\u628A\"\u4F1A\u600E\u4E48\u91CD\u542F / \u6709\u51E0\u4E2A\u4F1A\u8BDD\u5728\u8DD1\"\u8BF4\u6E05\u695A\u3001\n * \u91CD\u542F\u540E\u9760 `boot` \u53F7\u53D8\u4E86\u5224\u65AD\u65B0\u8FDB\u7A0B\u771F\u7684\u8D77\u6765\u4E86\uFF0C\u7136\u540E\u5237\u65B0\u9875\u9762\u3002\n *\n * \u4E3A\u4EC0\u4E48\u662F\u4E24\u6B65\u786E\u8BA4\u800C\u4E0D\u662F\u5E02\u573A\u90A3\u6837\u4E00\u70B9\u5C31\u8D70\uFF1A\u5E02\u573A\u90A3\u679A\u6309\u94AE\u53EA\u51FA\u73B0\u5728\u300C\u6709\u5F85\u91CD\u542F\u7684\u4E1C\u897F\u300D\u7684\u6A2A\u5E45\u91CC\n * \uFF08\u90A3\u4E00\u523B\u4F60\u624B\u91CC\u6CA1\u522B\u7684\u4E8B\uFF09\uFF0C\u800C\u8FD9\u679A\u5E38\u9A7B\u5728\u62AC\u5934\uFF0C\u4EFB\u4F55\u65F6\u5019\u90FD\u80FD\u70B9\u5230 \u2014\u2014 \u5305\u62EC\u4F60\u6B63\u8DD1\u7740\u4E00\u8F6E\u957F\u751F\u6210\u3002\n */\n\n/** \u5BBF\u4E3B\u534A\u544A\u8BC9\u754C\u9762\u7684\u4E8B\u5B9E\u3002 */\ninterface RestartFacts {\n /** \u5F53\u524D\u6709\u51E0\u4E2A\u4F1A\u8BDD\u5728\u8DD1\uFF08\u91CD\u542F\u4F1A\u628A\u5B83\u4EEC\u6253\u65AD\uFF09\u3002 */\n readonly running: number\n /** \u4F1A\u600E\u4E48\u91CD\u542F\uFF08\u91CD\u653E\u7528\u7684\u547D\u4EE4\uFF0C\u7ED9\u7528\u6237\u770B\u4E00\u773C\uFF09\u3002 */\n readonly command: string\n /** \u8BCA\u65AD\u65E5\u5FD7\u843D\u70B9\uFF08\u5931\u8D25\u65F6\u544A\u8BC9\u7528\u6237\u53BB\u54EA\u770B\uFF09\u3002 */\n readonly logHint: string\n /** \u975E null = \u8FD9\u4E2A\u5BBF\u4E3B\u4E0D\u8BE5\u88AB\u4ECE\u754C\u9762\u91CC\u6740\u6389\uFF08\u8C03\u8BD5\u5668 / systemd\uFF09\u3002 */\n readonly blocked: string | null\n /** \u8FD9\u6B21\u542F\u52A8\u7684\u6807\u8BC6\uFF1Bnull = \u5BBF\u4E3B\u534A\u8FD8\u662F 0.5.0 \u4E4B\u524D\u90A3\u7248\uFF08\u6CA1\u6709\u8FD9\u4E2A\u5B57\u6BB5\uFF09\u3002 */\n readonly boot: string | null\n}\n\ntype RestartStage = 'idle' | 'asking' | 'restarting' | 'failed'\n\ninterface RestartController {\n readonly stage: RestartStage\n readonly detail: string\n readonly blocked: string | null\n ask(): void\n confirm(): void\n cancel(): void\n}\n\n/** \u6700\u591A\u7B49 60 \u79D2\uFF1A\u65B0\u5BBF\u4E3B\u8D77\u6765\u7EA6 7 \u79D2\uFF0C\u4F46\u6162\u4E86\u4E5F\u4E0D\u8BE5\u8BA9\u7528\u6237\u5BF9\u7740\"\u6B63\u5728\u91CD\u542F\"\u65E0\u9650\u5E72\u7B49\u3002 */\nconst RESTART_WAIT_MS = 60_000\n/** \u8F6E\u8BE2\u95F4\u9694\uFF08\u5BF9\u9F50\u63D2\u4EF6\u5E02\u573A\uFF1A1.5 \u79D2\u95EE\u4E00\u6B21\u72B6\u6001\uFF09\u3002 */\nconst RESTART_POLL_MS = 1_500\n\n/** \u300C\u4E0D\u8BE5\u4ECE\u754C\u9762\u91CC\u6740\u6389\u300D\u7684\u539F\u56E0\u6587\u6848\u3002 */\nfunction blockedText(blocked: string): string {\n if (blocked === 'debugger') {\n return '\u8FD9\u4E2A\u5BBF\u4E3B\u6B63\u88AB\u8C03\u8BD5\u5668\u9644\u7740\uFF1A\u4ECE\u754C\u9762\u91CC\u6740\u6389\u5B83\u53EA\u4F1A\u8FDE\u8C03\u8BD5\u4F1A\u8BDD\u4E00\u8D77\u4E22\u6389\uFF0C\u8BF7\u4ECE IDE \u6216\u7EC8\u7AEF\u505C\u6B62\u5B83\u518D\u542F\u52A8\u3002'\n }\n if (blocked.startsWith('supervised:')) {\n return `\u8FD9\u4E2A\u5BBF\u4E3B\u7531 ${blocked.slice('supervised:'.length)} \u5F53\u670D\u52A1\u5728\u8DD1\uFF0C\u91CD\u542F\u8BE5\u5F52\u5B83\u7BA1`\n + '\uFF08\u5B83\u4F1A\u8FDE\u540C\u6574\u4E2A cgroup \u4E00\u8D77\u6536\u6389\uFF0C\u63D2\u4EF6\u81EA\u5DF1\u91CD\u542F\u53EA\u4F1A\u8BA9\u670D\u52A1\u518D\u4E5F\u8D77\u4E0D\u6765\uFF09\u3002'\n }\n return `\u8FD9\u4E2A\u5BBF\u4E3B\u5F53\u524D\u4E0D\u5141\u8BB8\u4ECE\u754C\u9762\u91CD\u542F\uFF08${blocked}\uFF09\u3002`\n}\n\n/** \u91CD\u542F\u6309\u94AE\u7684\u72B6\u6001\u673A\uFF1A\u8BFB\u72B6\u6001 \u2192 \u786E\u8BA4 \u2192 \u6392\u91CD\u542F \u2192 \u7B49\u65B0\u8FDB\u7A0B\u3002 */\nfunction useRestart(): RestartController {\n const [stage, setStage] = useState<RestartStage>('idle')\n const [detail, setDetail] = useState('')\n const [blocked, setBlocked] = useState<string | null>(null)\n\n /** \u8BFB\u5BBF\u4E3B\u534A\u7684\u72B6\u6001\uFF1B`{ error }` = \u8BFB\u4E0D\u5230\uFF08HTTP \u5931\u8D25 / \u8FDE\u63A5\u65AD\u4E86\uFF09\u3002 */\n const readFacts = async (): Promise<RestartFacts | { error: string }> => {\n const response = await fetch(RESTART_API_PATH, { cache: 'no-store' })\n if (!response.ok) return { error: `HTTP ${String(response.status)}` }\n const parsed = await response.json() as Record<string, unknown>\n return {\n running: typeof parsed.running === 'number' ? parsed.running : 0,\n command: typeof parsed.command === 'string' ? parsed.command : '',\n logHint: typeof parsed.logHint === 'string' ? parsed.logHint : '',\n blocked: typeof parsed.blocked === 'string' ? parsed.blocked : null,\n boot: typeof parsed.boot === 'string' ? parsed.boot : null,\n }\n }\n\n /** \u7B49\u65B0\u8FDB\u7A0B\u8D77\u6765\uFF1A`boot` \u53F7\u4E00\u53D8\u5C31\u5237\u65B0\u9875\u9762\u3002 */\n const awaitNewBoot = async (previousBoot: string | null, logHint: string): Promise<void> => {\n const deadline = Date.now() + RESTART_WAIT_MS\n while (Date.now() < deadline) {\n await new Promise<void>(done => { setTimeout(done, RESTART_POLL_MS) })\n try {\n const facts = await readFacts()\n if ('error' in facts) continue\n // \u65E7\u7248\u5BBF\u4E3B\u6CA1\u6709 boot \u5B57\u6BB5\uFF1A\u53EA\u8981\u62FF\u5230\u4EFB\u4F55\u4E00\u4E2A\u53F7\uFF0C\u5C31\u8BF4\u660E\u65B0\u8FDB\u7A0B\u5DF2\u7ECF\u63A5\u7BA1\u4E86\u8FD9\u4E2A\u7AEF\u53E3\u3002\n if (facts.boot !== null && facts.boot !== previousBoot) {\n location.reload()\n return\n }\n } catch {\n // \u65B0\u8FDB\u7A0B\u8FD8\u6CA1\u8D77\u6765\uFF08\u8FDE\u63A5\u88AB\u62D2\uFF09\uFF1A\u6B63\u5E38\uFF0C\u7EE7\u7EED\u7B49\u3002\n }\n }\n setStage('failed')\n setDetail('\u7B49\u4E86 60 \u79D2\u4E5F\u6CA1\u7B49\u5230\u65B0\u8FDB\u7A0B\u3002\u8BF7\u624B\u52A8\u8FD0\u884C restart-webui.bat \u91CD\u542F\u4E00\u6B21\u3002'\n + (logHint === '' ? '' : `\u5BBF\u4E3B\u534A\u7684\u8BCA\u65AD\u65E5\u5FD7\u5728 ${logHint}\u3002`))\n }\n\n /** \u7B2C\u4E00\u6B65\uFF1A\u8BFB\"\u4F1A\u600E\u4E48\u91CD\u542F\u3001\u73B0\u5728\u6709\u51E0\u4E2A\u4F1A\u8BDD\u5728\u8DD1\"\u3002 */\n const ask = (): void => {\n setStage('asking')\n setDetail('\u6B63\u5728\u8BFB\u53D6\u91CD\u542F\u65B9\u5F0F\u2026')\n void (async () => {\n try {\n const facts = await readFacts()\n if ('error' in facts) {\n setStage('failed')\n setDetail(`\u8BFB\u4E0D\u5230\u91CD\u542F\u72B6\u6001\uFF08${facts.error}\uFF09\u2014\u2014 \u5BBF\u4E3B\u534A\u53EF\u80FD\u8FD8\u6CA1\u6362\u5230\u5E26\u8FD9\u6761\u8DEF\u7531\u7684\u7248\u672C\uFF0C`\n + '\u8BF7\u5148\u624B\u52A8\u8FD0\u884C\u4E00\u6B21 restart-webui.bat\u3002')\n return\n }\n setBlocked(facts.blocked)\n if (facts.blocked !== null) {\n setStage('failed')\n setDetail(blockedText(facts.blocked))\n return\n }\n setStage('asking')\n // \u5BBF\u4E3B\u534A\u6CA1\u6709 boot \u5B57\u6BB5 = \u8FD8\u662F\u4E0A\u4E00\u7248\uFF08\u65B0\u8DEF\u7531\u8981\u91CD\u542F\u540E\u624D\u52A0\u8F7D\uFF09\u3002\u8FD9\u65F6\u5982\u5B9E\u8BF4\u660E\uFF1A\n // \u8FD9\u4E00\u6B21\u4F1A\u8D70\u65E7\u673A\u5236\uFF0C\u800C\u4E14\u91CD\u542F\u4E4B\u540E\u6309\u94AE\u624D\u53D8\u6210\u65B0\u7248 \u2014\u2014 \u522B\u8BA9\u7528\u6237\u4EE5\u4E3A\u6CA1\u751F\u6548\u3002\n setDetail((facts.boot === null\n ? '\u5BBF\u4E3B\u534A\u8FD8\u662F\u4E0A\u4E00\u7248\uFF1A\u8FD9\u6B21\u91CD\u542F\u4F1A\u8D70\u65E7\u673A\u5236\uFF08\u5199\u811A\u672C + \u81EA\u5DF1\u9000\u51FA\uFF09\uFF0C\u91CD\u542F\u4E4B\u540E\u6309\u94AE\u5C31\u662F\u65B0\u7248\u4E86\u3002'\n : `\u91CD\u542F\u65B9\u5F0F\uFF1A${facts.command}\u3002`)\n + `\u5F53\u524D\u6709 ${String(facts.running)} \u4E2A\u4F1A\u8BDD\u5728\u8DD1 \u2014\u2014 \u91CD\u542F\u4F1A\u6253\u65AD\u5B83\u4EEC\uFF08\u5305\u62EC\u6B63\u5728\u751F\u6210\u7684\u90A3\u4E00\u8F6E\uFF09\u3002`)\n } catch (error: unknown) {\n setStage('failed')\n setDetail(`\u8BFB\u4E0D\u5230\u91CD\u542F\u72B6\u6001\uFF1A${error instanceof Error ? error.message : String(error)}`)\n }\n })()\n }\n\n /** \u7B2C\u4E8C\u6B65\uFF1A\u786E\u8BA4\u540E\u8BA9\u5BBF\u4E3B\u534A\u6392\u91CD\u542F\uFF0C\u7136\u540E\u7B49\u65B0\u8FDB\u7A0B\u3002 */\n const confirm = (): void => {\n setStage('restarting')\n setDetail('\u5DF2\u53D1\u51FA\u91CD\u542F\u8BF7\u6C42 \u2014\u2014 \u6B63\u5728\u7B49\u65B0\u8FDB\u7A0B\u8D77\u6765\uFF08\u8FD9\u4E2A\u9875\u9762\u4F1A\u81EA\u5DF1\u56DE\u6765\uFF09\u2026')\n void (async () => {\n let previousBoot: string | null = null\n let logHint = ''\n try {\n const before = await readFacts()\n if (!('error' in before)) {\n previousBoot = before.boot\n logHint = before.logHint\n }\n } catch {\n // \u8BFB\u4E0D\u5230\u4E5F\u65E0\u6240\u8C13\uFF1A\u4E0B\u9762\u7684\u8F6E\u8BE2\u53EA\u9700\u8981\"\u53F7\u53D8\u4E86\"\u8FD9\u4E00\u4E2A\u6761\u4EF6\u3002\n }\n try {\n const response = await fetch(RESTART_API_PATH, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: '{}',\n })\n const parsed = await response.json() as { ok?: boolean; error?: string }\n if (response.status !== 202 && parsed.ok !== true) {\n setStage('failed')\n setDetail(`\u91CD\u542F\u6CA1\u6210\u529F\uFF1A${parsed.error ?? `HTTP ${String(response.status)}`}`\n + ' \u2014\u2014 \u8BF7\u624B\u52A8\u8FD0\u884C restart-webui.bat\u3002')\n return\n }\n } catch {\n // \u5BBF\u4E3B\u53EF\u80FD\u6B7B\u5728\u54CD\u5E94\u53D1\u5B8C\u4E4B\u524D\uFF1A\u90A3\u4E0D\u662F\u5931\u8D25\uFF0C\u7EE7\u7EED\u7B49\u65B0\u8FDB\u7A0B\u3002\n }\n await awaitNewBoot(previousBoot, logHint)\n })()\n }\n\n const cancel = (): void => {\n setStage('idle')\n setDetail('')\n }\n\n return { stage, detail, blocked, ask, confirm, cancel }\n}\n\n/** \u62AC\u5934\u53F3\u7AEF\u90A3\u679A\u6309\u94AE\uFF08\u5728 GitHub \u94FE\u63A5\u5DE6\u8FB9\uFF09\u3002 */\nfunction RestartButton({ restart }: { readonly restart: RestartController }) {\n const busy = restart.stage === 'restarting' || restart.stage === 'asking'\n const blocked = restart.blocked\n return (\n <button\n type=\"button\"\n className=\"dsh-ux-restartButton\"\n disabled={busy || blocked !== null}\n title={blocked === null\n ? '\u91CD\u542F DSH\uFF1A\u8BA9\u5BBF\u4E3B\u534A\u7684\u65B0\u4EE3\u7801\uFF08\u9ED8\u8BA4\u7EC8\u7AEF\u3001\u952E\u4F4D schema\uFF09\u751F\u6548\u3002\u70B9\u4E00\u4E0B\u4F1A\u5148\u8BA9\u4F60\u786E\u8BA4\u4E00\u6B21\u3002'\n : blockedText(blocked)}\n onClick={() => { restart.ask() }}\n >\n {restart.stage === 'restarting' ? '\u91CD\u542F\u4E2D\u2026' : '\u91CD\u542F DSH'}\n </button>\n )\n}\n\n/** \u62AC\u5934\u6B63\u4E0B\u65B9\u7684\u786E\u8BA4\u6761\uFF08\u5E02\u573A\u90A3\u4E2A\u300CN \u9879\u53D8\u66F4\u9700\u91CD\u542F\u300D\u6A2A\u5E45\u7684\u4F4D\u7F6E\uFF09\u3002 */\nfunction RestartBanner({ restart }: { readonly restart: RestartController }) {\n if (restart.stage === 'idle') return null\n const failed = restart.stage === 'failed'\n return (\n <div className={failed ? 'dsh-ux-restartBanner dsh-ux-restartBannerFailed' : 'dsh-ux-restartBanner'}>\n <span className=\"dsh-ux-restartBannerText\">{restart.detail}</span>\n {restart.stage === 'asking' && (\n <span className=\"dsh-ux-restartBannerActions\">\n <button type=\"button\" className=\"dsh-ux-restartGo\" onClick={() => { restart.confirm() }}>\u786E\u8BA4\u91CD\u542F</button>\n <button type=\"button\" className=\"dsh-ux-restartCancel\" onClick={() => { restart.cancel() }}>\u53D6\u6D88</button>\n </span>\n )}\n {failed && (\n <span className=\"dsh-ux-restartBannerActions\">\n <button type=\"button\" className=\"dsh-ux-restartCancel\" onClick={() => { restart.cancel() }}>\u77E5\u9053\u4E86</button>\n </span>\n )}\n </div>\n )\n}\n\n/** \u8BBE\u7F6E\u9875\u4E3B\u4F53\u3002 */\nexport function SettingsSection({ useLive, useBook, useBookStatus, useWriteNotice, actions }: SettingsSectionProps) {\n const settings = useLive(item => item)\n const book = useBook(item => item)\n const bookStatus = useBookStatus(item => item)\n /** '' = \u5199\u5165\u6B63\u5E38\uFF1B\u5176\u4F59\u662F\"\u88AB\u62D2 / \u5199\u4E86\u4F46\u8FD0\u884C\u65F6\u6CA1\u53D8\"\u7684\u8BF4\u660E\uFF08\u89C1 client.tsx \u7684 setField\uFF09\u3002 */\n const writeNotice = useWriteNotice(item => item)\n const [conflict, setConflict] = useState<string | null>(null)\n // \u91CD\u542F\u6309\u94AE\u5728\u62AC\u5934\u3001\u786E\u8BA4\u6761\u5728\u62AC\u5934\u6B63\u4E0B\u65B9 \u2014\u2014 \u4E24\u5904\u8981\u8BFB\u540C\u4E00\u4EFD\u72B6\u6001\uFF0C\u6240\u4EE5\u72B6\u6001\u63D0\u5230\u8FD9\u4E00\u5C42\u3002\n const restart = useRestart()\n /**\n * \u516D\u680F\u5404\u81EA\u7684\u5F00\u5173\u72B6\u6001\uFF08\u603B\u5F00\u5173 + \u680F\u5F00\u5173\uFF09\uFF0C\u516D\u5F20\u5361\u7684\u6807\u9898\u884C\u4E0E\u5185\u5BB9\u90FD\u8BFB\u5B83\u3002\n *\n * \u5355\u9879\u90FD\u8D70 `activeSections` \u800C\u4E0D\u662F\u5728\u8FD9\u91CC\u5404\u5199\u4E00\u904D `settings.enabled && \u2026`\uFF1A\n * \u6F0F\u6389\u603B\u95F8\u662F\u8FD9\u5957\u4E24\u5C42\u7EA7\u5F00\u5173\u6700\u5BB9\u6613\u72AF\u7684\u9519\uFF0C\u5224\u636E\u53EA\u80FD\u6709\u4E00\u5904\u3002\n */\n const sections = activeSections(settings)\n\n const setKey = (side: 'send' | 'newline', chord: string): void => {\n const other = side === 'send' ? settings.newlineKey : settings.sendKey\n if (chord !== '' && chord === other) {\n setConflict(chord)\n return\n }\n setConflict(null)\n actions.setField(side === 'send' ? 'sendKey' : 'newlineKey', chord)\n }\n\n const conflictHint = conflict !== null\n ? `\u300C${displayChord(conflict)}\u300D\u5DF2\u88AB\u53E6\u4E00\u4FA7\u5360\u7528\uFF0C\u8BF7\u5148\u4E3A\u53E6\u4E00\u4FA7\u9009\u62E9\u5176\u5B83\u6309\u952E\u3002`\n : null\n\n const menuEnabled = MENU_ITEMS.filter(item => settings[item.field]).length\n const keySummary = `\u53D1\u9001 ${displayChord(settings.sendKey)} \u00B7 \u6362\u884C ${displayChord(settings.newlineKey)}`\n // \u4E09\u6863\u5404\u81EA\u7684\u6458\u8981\uFF1A\u4E00\u773C\u770B\u51FA\u53F3\u952E\u4F1A\u5F39\u54EA\u4E00\u79CD\u83DC\u5355\uFF0C\u4EE5\u53CA\u81EA\u5B9A\u4E49\u6863\u5F53\u524D\u5F00\u4E86\u51E0\u9879\u3002\n const menuSummary = settings.menuMode === 'official'\n ? '\u5F53\u524D\uFF1A\u5B98\u65B9\u4E0D\u4ECB\u5165'\n : settings.menuMode === 'browser'\n ? '\u5F53\u524D\uFF1A\u6D4F\u89C8\u5668\u83DC\u5355\uFF08\u7C98\u8D34\u514D\u6388\u6743\uFF09'\n : `\u5F53\u524D\uFF1A\u81EA\u5B9A\u4E49\u83DC\u5355 \u00B7 ${menuEnabled} / ${MENU_ITEMS.length} \u9879\u5F00\u542F`\n const panelSummary = `\u8FB9\u7F18\u7F29\u653E ${settings.panelResize ? '\u5F00' : '\u5173'}`\n + ` \u00B7 ${settings.panelWidth}\u00D7${settings.panelHeight}`\n // \u8BF7\u6C42\u5934\u680F\u76EE\u7684\u6982\u89C8\u76F4\u63A5\u590D\u7528\u5BBF\u4E3B\u534A\u5199\u56DE\u6765\u7684\u6267\u884C\u7ED3\u679C\uFF08'\u5DF2\u5199\u5165 opencode-go' \u8FD9\u7C7B\uFF09\u3002\n const headerSummary = settings.headerEnabled\n ? (settings.headerStatus === '' ? '\u5DF2\u542F\u7528' : settings.headerStatus)\n : '\u672A\u542F\u7528'\n const quickCounts = bookCounts(book)\n const quickSummary = `${quickCounts.categories} \u4E2A\u5206\u7C7B \u00B7 ${quickCounts.prompts} \u6761`\n + ` \u00B7 \u6BCF\u6B21 ${quickCounts.always} \u00B7 \u4EC5\u9996\u6B21 ${quickCounts.first}`\n + ` \u00B7 \u4F18\u5316\u6863\u4F4D ${OPTIMIZER_TIERS.find(item => item.id === settings.optimizerTier)?.label ?? '\u9AD8\u7EA7'}`\n const headerStatusText = settings.headerEnabled\n ? (settings.headerStatus === '' ? '\u7B49\u5F85\u9996\u6B21\u5199\u5165\u2026' : settings.headerStatus)\n : '\u672A\u542F\u7528\uFF08\u6253\u5F00\u4E0A\u65B9\u5F00\u5173\u5373\u5199\u5165\uFF09'\n // \u7EC8\u7AEF\u5361\u7247\u7684\u6982\u89C8\uFF1A\u76F4\u63A5\u590D\u7528\u5BBF\u4E3B\u534A\u5199\u56DE\u6765\u7684\u72B6\u6001\uFF08'\u5DF2\u751F\u6548\uFF1A\u2026' / '\u6CA1\u627E\u5230\u53EF\u7528\u7684 bash' \u8FD9\u7C7B\uFF09\u3002\n // \u300C\u8FD9\u4E00\u680F\u6CA1\u542F\u7528\u300D\u4F18\u5148\u4E8E\u5BBF\u4E3B\u534A\u7684\u72B6\u6001 \u2014\u2014 \u6CA1\u5F00\u7684\u65F6\u5019\u72B6\u6001\u884C\u5199\u7684\u662F\"\u672A\u542F\u7528\"\uFF0C\u4F46\u90A3\u53E5\u8BDD\u5728\u6982\u89C8\u91CC\n // \u4E0D\u5982\u300C\u672A\u542F\u7528\u300D\u56DB\u4E2A\u5B57\u76F4\u767D\uFF08FoldCard \u4F1A\u518D\u52A0\u4E00\u6B21\u524D\u7F00\uFF0C\u6240\u4EE5\u8FD9\u91CC\u53EA\u7ED9\u88AB\u5173\u6389\u65F6\u7684\u6863\u4F4D\u63CF\u8FF0\uFF09\u3002\n const terminalSummary = sections.terminal === false\n ? (settings.terminalMode === 'pwsh' ? '\u4FDD\u6301 PowerShell' : '\u6253\u5F00\u540E\u63A5\u7BA1\u7EC8\u7AEF')\n : settings.terminalEffective === 'unsupported'\n ? '\u975E Windows\uFF1A\u4E0D\u9700\u8981'\n : settings.terminalMode === 'pwsh'\n ? '\u5F53\u524D\uFF1A\u4FDD\u6301 PowerShell'\n : (settings.terminalEffective === 'bash' ? '\u5F53\u524D\uFF1AGit Bash' : '\u5F53\u524D\uFF1APowerShell\uFF08\u672A\u63A5\u7BA1\uFF09')\n\n return (\n <div style={{ padding: '4px 2px' }}>\n {/* \u9876\u90E8\u5E38\u663E\u533A\uFF1A\u4E2D\u6587\u540D + \u5185\u5D4C\u82F1\u6587\u5305\u540D\u7684\u4E00\u884C\u63CF\u8FF0 + \u603B\u5F00\u5173\u3002 */}\n <section className=\"dsh-ux-card\">\n <div className=\"dsh-ux-cardHeaderStatic\">\n <span className=\"dsh-ux-cardHeadText\">\n <h2 className=\"dsh-ux-cardName\">\u8F93\u5165\u4F53\u9A8C</h2>\n <p className=\"dsh-ux-cardDescription\">\n dsh-composer-ux \u00B7 \u4E3B\u804A\u5929\u8F93\u5165\u6846\u7684\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u4E0E\u8BBE\u7F6E\u9762\u677F\uFF1B\u8BBE\u7F6E\u5373\u65F6\u751F\u6548\u5E76\u6301\u4E45\u4FDD\u5B58\u3002\n </p>\n </span>\n {/*\n \u300C\u91CD\u542F DSH\u300D\u653E\u5728\u62AC\u5934\u53F3\u7AEF\u3001GitHub \u94FE\u63A5\u5DE6\u8FB9\uFF1A\u8FD9\u662F\u8BBE\u7F6E\u9875\u7B2C\u4E00\u773C\u5C31\u626B\u5230\u7684\u4F4D\u7F6E\uFF0C\n \u800C\u5B83\u8981\u89E3\u51B3\u7684\u95EE\u9898\uFF08\u5BBF\u4E3B\u534A\u6539\u4E86\u8981\u91CD\u542F\u624D\u751F\u6548\uFF09\u6070\u597D\u662F\u7528\u6237\u70B9\u8FDB\u8BBE\u7F6E\u9875\u65F6\u6700\u60F3\u505A\u7684\u4E8B\u3002\n \u786E\u8BA4\u6761\u5728\u62AC\u5934\u6B63\u4E0B\u65B9\uFF08\u89C1\u4E0B\u9762\u7684 RestartBanner\uFF09\uFF0C\u8DDF\u5E02\u573A\u7684\u300C\u5F85\u91CD\u542F\u300D\u6A2A\u5E45\u540C\u4E00\u4E2A\u4F4D\u7F6E\u3002\n */}\n <span className=\"dsh-ux-cardActions\">\n <RestartButton restart={restart} />\n {/*\n \u4ED3\u5E93\u5165\u53E3\uFF1A\u7528\u771F\u5B9E\u7684 <a>\uFF08\u65B0\u6807\u7B7E\u6253\u5F00\u3001\u4E0D\u5E26 referrer\uFF09\uFF0C\u5730\u5740\u6765\u81EA\u5951\u7EA6\u91CC\u7684 REPO_URL \u2014\u2014\n \u5BA2\u6237\u7AEF\u4E0D\u8BB8\u786C\u7F16\u7801\u7B2C\u4E8C\u4EFD\u5730\u5740\uFF0C\u5426\u5219\u6539\u4E86\u4ED3\u5E93\u4E24\u5904\u4F1A\u5206\u53C9\uFF08\u6709\u6D4B\u8BD5\u76EF\u7740\uFF09\u3002\n */}\n <a\n className=\"dsh-ux-cardLink\"\n href={REPO_URL}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n title=\"\u5728 GitHub \u4E0A\u67E5\u770B\u8FD9\u4E2A\u63D2\u4EF6\uFF08\u65B0\u6807\u7B7E\u6253\u5F00\uFF09\"\n >\n GitHub <span aria-hidden=\"true\">\u2197</span>\n </a>\n </span>\n </div>\n <RestartBanner restart={restart} />\n {/*\n \u5199\u5165\u5931\u8D25 / \u5199\u4E86\u4F46\u6CA1\u751F\u6548\u7684\u8BF4\u660E\u6761\uFF1A\u4E0E\u300C\u91CD\u542F DSH\u300D\u6A2A\u5E45\u540C\u4E00\u4E2A\u4F4D\u7F6E\u3001\u540C\u4E00\u5957\u6837\u5F0F\u3002\n \u4E3A\u4EC0\u4E48\u503C\u5F97\u5360\u8FD9\u4E2A\u4F4D\u7F6E\uFF1A2026-09-23 \u7684\u771F\u673A\u4E8B\u6545\u91CC\uFF0C\u8BBE\u7F6E\u5199\u5165\u88AB\u4E00\u628A\u5B64\u513F\u5199\u5165\u9501\u6321\u4F4F\uFF0C\n \u7528\u6237\u770B\u5230\u7684\u53EA\u6709\"\u5F00\u5173\u4E0D\u52A8\"\uFF0C**\u4E00\u53E5\u63D0\u793A\u90FD\u6CA1\u6709**\uFF0C\u6392\u67E5\u53EA\u80FD\u9760\u7FFB\u5BBF\u4E3B\u65E5\u5FD7\u3002\n \u6240\u4EE5\u8FD9\u6761\u6A2A\u5E45\u7684\u4F5C\u7528\u662F\u8BA9\u4E0B\u4E00\u6B21\u540C\u7C7B\u6545\u969C\u5F53\u573A\u8BF4\u5F97\u51FA\u8BDD\uFF08\u5224\u636E\u89C1 client.tsx \u7684 setField\uFF09\u3002\n */}\n {writeNotice !== '' && (\n <div className=\"dsh-ux-restartBanner dsh-ux-restartBannerFailed\" role=\"status\">\n <span className=\"dsh-ux-restartBannerText\">\u8BBE\u7F6E\u672A\u751F\u6548\uFF1A{writeNotice}</span>\n <span className=\"dsh-ux-restartBannerActions\">\n <button type=\"button\" className=\"dsh-ux-restartCancel\" onClick={() => { actions.dismissNotice() }}>\n \u77E5\u9053\u4E86\n </button>\n </span>\n </div>\n )}\n <div className=\"dsh-ux-cardBody\">\n <ToggleRow\n first\n label=\"\u542F\u7528\u8F93\u5165\u589E\u5F3A\"\n desc=\"\u5173\u95ED\u540E\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u4E0E\u8BBE\u7F6E\u9762\u677F\u6EDA\u52A8/\u7F29\u653E\u5168\u90E8\u505C\u7528\uFF08\u672C\u9875\u4FDD\u7559\u7528\u4E8E\u91CD\u65B0\u5F00\u542F\uFF09\"\n checked={settings.enabled}\n onChange={next => { actions.setField(ENABLED_FIELD, next) }}\n />\n {!settings.enabled && (\n <p style={hintInfo}>\n \u5DF2\u505C\u7528\uFF1A\u53D1\u9001/\u6362\u884C\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u3001\u8BBE\u7F6E\u9762\u677F\u6EDA\u52A8\u4E0E\u8FB9\u7F18\u7F29\u653E\u5747\u4E0D\u518D\u751F\u6548\uFF0C\u8F93\u5165\u6846\u6062\u590D DSH \u539F\u751F\u884C\u4E3A\u3002\n \u6253\u5F00\u4E0A\u65B9\u5F00\u5173\u5373\u53EF\u4E00\u952E\u6062\u590D\uFF1B\u6240\u6709\u8BBE\u7F6E\u503C\u4ECD\u4FDD\u7559\u3002\n </p>\n )}\n </div>\n </section>\n\n {settings.enabled && (<>\n <FoldCard\n name=\"\u952E\u4F4D\"\n summary={keySummary}\n toggle={{\n checked: sections.keys,\n onChange: next => { actions.setField(KEYS_ENABLED_FIELD, next) },\n }}\n >\n <p style={bodyLead}>\n \u652F\u6301\u5E38\u7528\u9884\u8BBE\uFF0C\u4E5F\u53EF\u4EE5\u70B9\u51FB\u300C\u81EA\u5B9A\u4E49\u2026\u300D\u540E\u76F4\u63A5\u6309\u4E0B\u4EFB\u610F\u7EC4\u5408\u952E\u5F55\u5236\uFF08Esc \u53D6\u6D88\uFF0CBackspace \u6E05\u9664\uFF09\u3002\n \u672A\u7ED1\u5B9A\u7684 Enter \u7CFB\u6309\u952E\u4E0D\u4F1A\u89E6\u53D1\u53D1\u9001\u6216\u6362\u884C\uFF1BCtrl+Enter / \u2318+Enter \u672A\u88AB\u7ED1\u5B9A\u65F6\u4FDD\u7559\u539F\u300C\u52A0\u901F\u63D0\u4EA4\u300D\u884C\u4E3A\uFF1B\n \u4E2D\u6587\u8F93\u5165\u6CD5\u7EC4\u5408\u671F\u95F4\u4E0D\u53D7\u5F71\u54CD\u3002\n </p>\n <KeyRow\n first\n title=\"\u53D1\u9001\u952E\"\n desc=\"\u6309\u4E0B\u540E\u53D1\u9001\u5F53\u524D\u8F93\u5165\"\n value={settings.sendKey}\n presets={SEND_PRESETS}\n conflict={chord => chord !== '' && chord === settings.newlineKey}\n onChange={chord => { setKey('send', chord) }}\n />\n <KeyRow\n title=\"\u6362\u884C\u952E\"\n desc=\"\u6309\u4E0B\u540E\u5728\u8F93\u5165\u5185\u6362\u884C\"\n value={settings.newlineKey}\n presets={NEWLINE_PRESETS}\n conflict={chord => chord !== '' && chord === settings.sendKey}\n onChange={chord => { setKey('newline', chord) }}\n />\n {conflictHint !== null && <p style={hintError}>{conflictHint}</p>}\n <div style={{ marginTop: 10 }}>\n <button\n type=\"button\"\n style={pill}\n onClick={() => { setConflict(null); actions.resetAll() }}\n >\n \u6062\u590D\u9ED8\u8BA4\n </button>\n </div>\n </FoldCard>\n\n {/*\n \u4E09\u6863\u8BF4\u660E\u4E0E\u90A3 7 \u4E2A\u6761\u76EE\u5F00\u5173**\u90FD\u5728\u5361\u5185**\uFF0C\u4E14\u6309\u5F53\u524D\u6863\u4F4D\u53EA\u663E\u793A\u76F8\u5173\u7684\u90A3\u90E8\u5206\n \uFF08\u7528\u6237\u8981\u6C42\uFF1A\u70B9\u5B98\u65B9\u770B\u5B98\u65B9\u7684\u3001\u70B9\u6D4F\u89C8\u5668\u770B\u6D4F\u89C8\u5668\u7684\u3001\u70B9\u81EA\u5B9A\u4E49\u770B\u81EA\u5B9A\u4E49\u7684\uFF09\u3002\n 0.5.0 \u5148\u505A\u7684\u662F\u300C7 \u9879\u5F00\u5173\u642C\u5230\u6807\u9898\u884C\u7684\u300E7 \u9879 \u25BC\u300F\u6761\u300D\uFF0C\u7528\u6237\u770B\u8FC7\u771F\u5B9E\u754C\u9762\u540E\u6539\u56DE\u5361\u5185\uFF1A\n \u90A3 7 \u9879\u672C\u6765\u5C31\u53EA\u5BF9\u300C\u81EA\u5B9A\u4E49\u300D\u6863\u6709\u610F\u4E49\uFF0C\u6446\u5728\u6807\u9898\u884C\u7B49\u4E8E\u5728\u4EFB\u4F55\u6863\u4F4D\u90FD\u80FD\u6539\u4E00\u5806\u5F53\u65F6\u4E0D\u751F\u6548\u7684\u4E1C\u897F\u3002\n */}\n <FoldCard\n name=\"\u53F3\u952E\u83DC\u5355\"\n summary={menuSummary}\n toggle={{\n checked: sections.menu,\n onChange: next => { actions.setField(MENU_ENABLED_FIELD, next) },\n }}\n >\n <p style={bodyLead}>\n \u53F3\u952E\u70B9\u51FB\u8F93\u5165\u6846\u65F6\u5F39\u51FA\u54EA\u4E00\u79CD\u83DC\u5355\u3002\u53EA\u5F71\u54CD\u53F3\u952E\uFF0C\u4E0D\u5F71\u54CD\u952E\u4F4D\u4E0E\u5176\u5B83\u529F\u80FD\u3002\n </p>\n <div style={{ ...row, borderTop: 'none', flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>\u83DC\u5355\u6765\u6E90</div>\n </div>\n <PillChoice\n items={MENU_MODES}\n value={settings.menuMode}\n onChange={mode => { actions.setField(MENU_MODE_FIELD, mode) }}\n ariaLabel=\"\u53F3\u952E\u83DC\u5355\u6765\u6E90\"\n />\n </div>\n {settings.menuMode === 'official' && (\n <p style={hintInfo}>\n <strong>\u5B98\u65B9</strong>\uFF1A\u672C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u4ECB\u5165\uFF0CDSH \u4E0E\u5176\u5B83\u63D2\u4EF6\u81EA\u5DF1\u7684\u53F3\u952E\u5904\u7406\u539F\u6837\u751F\u6548\n \uFF08DSH \u5B98\u65B9\u8F93\u5165\u6846\u672C\u8EAB\u6CA1\u6709\u53F3\u952E\u83DC\u5355\uFF0C\u6240\u4EE5\u901A\u5E38\u770B\u5230\u7684\u5C31\u662F\u6D4F\u89C8\u5668\u7684\u83DC\u5355\uFF09\u3002\n </p>\n )}\n {settings.menuMode === 'browser' && (\n <p style={hintInfo}>\n <strong>\u6D4F\u89C8\u5668</strong>\uFF1A\u56FA\u5B9A\u7528\u6D4F\u89C8\u5668\u81EA\u5E26\u7684\u83DC\u5355\uFF08\u6837\u5B50\u968F\u6D4F\u89C8\u5668\u800C\u53D8\uFF09\uFF0C\u5E76\u5728\u672C\u63D2\u4EF6\u8FD9\u4E00\u5C42\n \u6321\u4F4F\u5176\u5B83\u63D2\u4EF6\u7684\u83DC\u5355\uFF1B\u597D\u5904\u662F\u7C98\u8D34\u514D\u6388\u6743\u3001\u96F6\u914D\u7F6E\u3002\n </p>\n )}\n {settings.menuMode === 'custom' && (\n <>\n <p style={hintInfo}>\n <strong>\u81EA\u5B9A\u4E49</strong>\uFF1A\u7528\u672C\u63D2\u4EF6\u56FA\u5B9A\u6837\u5F0F\u7684\u83DC\u5355\uFF08\u672A\u9009\u4E2D\u6587\u672C\u65F6\u300C\u526A\u5207 / \u590D\u5236 / \u5220\u9664\u300D\u7F6E\u7070\uFF09\u3002\n \u8FD9\u4E00\u6863\u7684\u300C\u7C98\u8D34\u300D\u8981\u8BFB\u526A\u8D34\u677F\uFF0C\u6D4F\u89C8\u5668\u4F1A\u5148\u8981\u4E00\u6B21\u6388\u6743\u2014\u2014\u4E09\u5BB6\u6D4F\u89C8\u5668\u7684\u5904\u7406\u4E0D\u4E00\u6837\uFF1A\n </p>\n <p style={hintInfo}>\n \u00B7 Chrome / Edge\uFF08\u8C37\u6B4C / \u5FAE\u8F6F\u6D4F\u89C8\u5668\uFF09\uFF1A\u5F39\u51FA\u540E\u70B9\u300C\u5141\u8BB8\u300D\u5373\u53EF\uFF0C\u4E4B\u540E\u4F1A\u8BB0\u4F4F\u8FD9\u4E2A\u7AD9\u70B9\u3001\u4E0D\u518D\u95EE\u3002\n \u8981\u6539\u6216\u64A4\u9500\u6388\u6743\uFF1A\u70B9\u5730\u5740\u680F\u6700\u5DE6\u8FB9\u7684\u7F51\u7AD9\u56FE\u6807 \u2192 \u7F51\u7AD9\u8BBE\u7F6E\uFF08Edge \u53EB\u300C\u6B64\u7AD9\u70B9\u7684\u6743\u9650\u300D\uFF09\u2192 \u526A\u8D34\u677F\uFF1B\n \u4E5F\u53EF\u4EE5\u76F4\u63A5\u5728\u5730\u5740\u680F\u8F93\u5165 chrome://settings/content/clipboard\uFF08Edge \u8F93\u5165\n edge://settings/content/clipboard\uFF09\u3002\n </p>\n <p style={hintInfo}>\n \u00B7 Firefox\uFF1A\u4E0D\u5141\u8BB8\u7F51\u9875\u9759\u9ED8\u8BFB\u526A\u8D34\u677F\u2014\u2014\u4F60\u70B9\u672C\u63D2\u4EF6\u7684\u300C\u7C98\u8D34\u300D\u540E\uFF0C\u5B83\u4F1A\u5148\u5F39\u4E00\u4E2A\u53EA\u6709\u300C\u7C98\u8D34(P)\u300D\n \u4E00\u9879\u7684\u5C0F\u7A97\uFF08\u7EA6 1 \u79D2\u540E\u624D\u53EF\u70B9\uFF09\uFF0C\u70B9\u5B83\u624D\u5B8C\u6210\u8FD9\u6B21\u7C98\u8D34\u3002\u8FD9\u662F Firefox \u7684\u5B89\u5168\u673A\u5236\uFF0C\u63D2\u4EF6\u5173\u4E0D\u6389\n \uFF08\u5B9E\u6D4B\uFF1Aabout:config \u91CC\u7684\u526A\u8D34\u677F\u9996\u9009\u9879\u5BF9\u5B83\u65E0\u6548\uFF09\u3002\u4E0D\u60F3\u591A\u8FD9\u4E00\u6B65\u5C31\u76F4\u63A5\u6309 Ctrl+V\uFF0C\n \u6216\u628A\u4E0A\u9762\u7684\u300C\u83DC\u5355\u6765\u6E90\u300D\u6362\u6210\u300C\u6D4F\u89C8\u5668 / \u5B98\u65B9\u300D\u6863\u2014\u2014\u90A3\u4E24\u6863\u7528\u7684\u662F\u6D4F\u89C8\u5668\u81EA\u5DF1\u7684\u7C98\u8D34\u3002\n </p>\n <p style={hintInfo}>\n \u6CE8\u610F\uFF1Achrome://\u3001edge:// \u8FD9\u4E9B\u5730\u5740\u6D4F\u89C8\u5668\u4E0D\u5141\u8BB8\u505A\u6210\u7F51\u9875\u91CC\u7684\u94FE\u63A5\uFF0C\u53EA\u80FD\u624B\u8F93\uFF0C\n \u6216\u590D\u5236\u4E0A\u9762\u90A3\u4E32\u7C98\u8D34\u5230\u5730\u5740\u680F\u3002\n </p>\n <div style={{ ...row, flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>\u83DC\u5355\u6761\u76EE</div>\n <div style={rowDesc}>\u8FD9 7 \u4E2A\u5F00\u5173\u51B3\u5B9A\u81EA\u5B9A\u4E49\u83DC\u5355\u91CC\u51FA\u73B0\u54EA\u4E9B\u6761\u76EE\uFF0C\u5173\u6389\u7684\u4E0D\u663E\u793A\u3002</div>\n </div>\n </div>\n {MENU_ITEMS.map((item, index) => (\n <ToggleRow\n key={item.field}\n first={index === 0}\n label={item.label}\n desc={item.shortcut !== '' ? `\u5FEB\u6377\u952E ${item.shortcut}` : ''}\n checked={settings[item.field]}\n onChange={next => { actions.setField(item.field as MenuField, next) }}\n />\n ))}\n <div style={{ padding: '8px 0 2px' }}>\n <button\n type=\"button\"\n style={pill}\n onClick={() => { for (const item of MENU_ITEMS) actions.setField(item.field as MenuField, true) }}\n >\n \u5168\u90E8\u5F00\u542F\n </button>\n </div>\n </>\n )}\n </FoldCard>\n\n <FoldCard\n name=\"\u5FEB\u6377\u6307\u4EE4\"\n summary={quickSummary}\n toggle={{\n checked: sections.quick,\n onChange: next => { actions.setField(QUICK_ENABLED_FIELD, next) },\n }}\n >\n <p style={bodyLead}>\n \u8F93\u5165\u6846\u5DE5\u5177\u884C\u91CC\u90A3\u4E2A\u300C\u5FEB\u6377\u6307\u4EE4\u300D\u6309\u94AE\u70B9\u5F00\u5C31\u662F\u8FD9\u5F20\u6E05\u5355\uFF1A\u70B9\u6761\u76EE\u628A\u5185\u5BB9\u63D2\u5165\u8F93\u5165\u6846\u3002\n \u6BCF\u6761\u53F3\u4FA7\u7684\u4E09\u9009\u4E00\u51B3\u5B9A<strong>\u53D1\u9001\u65F6\u600E\u4E48\u9644\u52A0</strong>\uFF1A\n \u300C\u5173\u300D= \u53EA\u63D2\u5165\u4E0D\u9644\u52A0\uFF1B\u300C\u6BCF\u6B21\u300D= \u6BCF\u6B21\u53D1\u9001\u90FD\u9644\u52A0\u5230\u6D88\u606F<strong>\u672B\u5C3E</strong>\uFF1B\n \u300C\u4EC5\u9996\u6B21\u300D= \u53EA\u5728<strong>\u8FD9\u4E2A\u4F1A\u8BDD\u7684\u7B2C\u4E00\u6761\u6D88\u606F</strong>\u4E0A\u9644\u52A0\uFF08\u4E4B\u540E\u4E0D\u518D\u9644\u52A0\uFF0C\u5237\u65B0\u9875\u9762\u4E5F\u4E0D\u4F1A\u91CD\u590D\uFF09\u3002\n \u591A\u6761\u6309\u5217\u8868\u987A\u5E8F\u62FC\u63A5\uFF0C\u8F93\u5165\u6846\u91CC\u4E0D\u63D0\u524D\u663E\u793A\u3002\n \u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\u4F1A\u7528\u53E6\u4E00\u4E2A AI \u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u6574\u7406\u6210\u4E00\u6761\u80FD\u76F4\u63A5\u53D1\u51FA\u53BB\u7684\u6E05\u6670\u6307\u4EE4\uFF0C\n \u7ED3\u679C\u76F4\u63A5\u5199\u56DE\u8F93\u5165\u6846\uFF08Ctrl+Z \u53EF\u8FD8\u539F\uFF09\u2014\u2014\u4E0D\u4F1A\u6C61\u67D3\u5F53\u524D\u5BF9\u8BDD\uFF0C\u4E5F\u4E0D\u5360\u4F60\u7684\u5BF9\u8BDD\u8F6E\u6B21\u3002\n 0.6.0 \u8D77\u5B83\u4E0D\u518D\"\u81EA\u7531\u6539\u5199\"\uFF1A\u5B83\u53EA\u80FD\u4EA7\u51FA<strong>\u80FD\u6307\u56DE\u4F60\u539F\u8BDD\u67D0\u4E00\u53E5\u8BDD</strong>\u7684\u6761\u76EE\uFF0C\n \u5BBF\u4E3B\u9010\u6761\u505A\u5B57\u9762\u6BD4\u5BF9\uFF0C\u5BF9\u4E0D\u4E0A\u5C31\u4E22\u6389\u90A3\u4E00\u6761\u5E76\u5728\u72B6\u6001\u884C\u91CC\u8BB0\u8D26 \u2014\u2014\n \u6240\u4EE5\"\u66FF\u4F60\u53D1\u660E\u4E00\u6761\u4F60\u6CA1\u8BF4\u8FC7\u7684\u9700\u6C42\"\u5728\u7ED3\u6784\u4E0A\u505A\u4E0D\u5230\u3002\u4E0B\u9762\u53EF\u4EE5\u6539\u6BCF\u4E00\u6863\u7528\u7684\u63D0\u793A\u8BCD\u3002\n </p>\n <div style={{ ...row, borderTop: 'none', flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>\u4F18\u5316\u5F3A\u5EA6</div>\n <div style={rowDesc}>\n {OPTIMIZER_TIERS.find(item => item.id === settings.optimizerTier)?.hint ?? ''}\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>\n {OPTIMIZER_TIERS.map(item => (\n <button\n key={item.id}\n type=\"button\"\n title={item.hint}\n style={settings.optimizerTier === item.id ? pillActive : pill}\n onClick={() => { actions.setField(OPTIMIZER_TIER_FIELD, item.id as OptimizerTier) }}\n >\n {item.label}\n </button>\n ))}\n </div>\n </div>\n <OptimizerPromptEditor\n tier={settings.optimizerTier}\n value={settings[optimizerPromptFieldOf(settings.optimizerTier) as keyof ComposerUxSettings] as string}\n onChange={next => { actions.setField(optimizerPromptFieldOf(settings.optimizerTier) as SettingsField, next) }}\n />\n <div style={{ ...row, borderTop: 'none', flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>\u5FEB\u6377\u6307\u4EE4\u6E05\u5355</div>\n <div style={rowDesc}>\n \u5206\u7C7B\u5728\u8FD9\u91CC\u7BA1\u7406\uFF08\u9762\u677F\u91CC\u53EA\u505A\u5207\u6362\uFF09\uFF1B\u5185\u7F6E 9 \u6761\u53EF\u4EE5\u76F4\u63A5\u7528\uFF0C\u6539\u5B8C\u8BB0\u5F97\u70B9\u300C\u4FDD\u5B58\u4FEE\u6539\u300D\u3002\n </div>\n </div>\n <QuickPromptsEditor\n book={book}\n status={bookStatus}\n onSave={next => { actions.saveBook(next) }}\n onReload={() => { actions.reloadBook() }}\n onReset={() => { actions.resetBook() }}\n />\n </div>\n </FoldCard>\n\n <FoldCard\n name=\"\u8BBE\u7F6E\u9762\u677F\"\n summary={panelSummary}\n toggle={{\n checked: sections.panel,\n onChange: next => { actions.setField(PANEL_ENABLED_FIELD, next) },\n }}\n // \u53EA\u7559\u300C\u8FB9\u7F18\u7F29\u653E\u300D\uFF1A\u5BFC\u822A\u6EDA\u52A8\u5DF2\u7531 DSH 0.1.7 \u5B98\u65B9\u8BBE\u7F6E\u9875\u81EA\u5E26\uFF0C\u672C\u63D2\u4EF6\u4E0D\u518D\u63D0\u4F9B\u90A3\u4E2A\u5F00\u5173\u3002\n controls={(\n <MiniToggle\n label=\"\u8FB9\u7F18\u7F29\u653E\"\n checked={settings.panelResize}\n onChange={next => { actions.setField(PANEL_RESIZE_FIELD, next) }}\n />\n )}\n >\n <p style={bodyLead}>\n \u5BFC\u822A\u5217\u7684\u6EDA\u52A8\u7531 DSH \u5B98\u65B9\u7684\u8BBE\u7F6E\u9875\u81EA\u5DF1\u8D1F\u8D23\uFF0C\u672C\u63D2\u4EF6\u4E0D\u518D\u4ECB\u5165\u3002\n \u5F00\u542F\u300C\u8FB9\u7F18\u8C03\u6574\u5927\u5C0F\u300D\u540E\uFF0C\u628A\u9F20\u6807\u79FB\u5230\u8BBE\u7F6E\u9762\u677F\u7684\u8FB9\u6216\u89D2\u4E0A\uFF08\u51FA\u73B0\u9AD8\u4EAE\u6216\u5149\u6807\u53D8\u5316\uFF09\u62D6\u52A8\u5373\u53EF\u6539\u53D8\u9762\u677F\u5927\u5C0F\uFF0C\n \u5C3A\u5BF8\u4F1A\u8BB0\u4F4F\uFF0C\u4E0B\u6B21\u6253\u5F00\u4FDD\u6301\u3002\uFF08\u8FD9\u4E2A\u5F00\u5173\u5728\u6807\u9898\u884C\u4E0A\u3002\uFF09\n </p>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', marginTop: 10 }}>\n <span style={rowDesc}>\u5C3A\u5BF8\u9884\u8BBE\uFF1A</span>\n <button\n type=\"button\"\n style={pill}\n onClick={() => { actions.clearField(PANEL_WIDTH_FIELD); actions.clearField(PANEL_HEIGHT_FIELD) }}\n >\n \u9ED8\u8BA4\uFF08800\uFF09\n </button>\n <button\n type=\"button\"\n style={settings.panelWidth === 640 && settings.panelHeight === 600 ? pillActive : pill}\n onClick={() => {\n actions.setField(PANEL_WIDTH_FIELD, 640)\n actions.setField(PANEL_HEIGHT_FIELD, 600)\n }}\n >\n \u7D27\u51D1\uFF08640\u00D7600\uFF09\n </button>\n <button\n type=\"button\"\n style={settings.panelWidth === 1040 && settings.panelHeight === 760 ? pillActive : pill}\n onClick={() => {\n actions.setField(PANEL_WIDTH_FIELD, 1040)\n actions.setField(PANEL_HEIGHT_FIELD, 760)\n }}\n >\n \u5BBD\u655E\uFF081040\u00D7760\uFF09\n </button>\n </div>\n </FoldCard>\n\n <FoldCard\n name=\"OpenCode \u8BF7\u6C42\u5934\"\n summary={headerSummary}\n // \u8FD9\u4E00\u680F\u6CA1\u6709\u65B0\u952E\uFF1A\u539F\u6765\u7684\u300C\u9644\u52A0\u8BF7\u6C42\u5934\u300D\u672C\u6765\u5C31\u662F\"\u8FD9\u4E00\u680F\u8981\u4E0D\u8981\u751F\u6548\"\uFF0C\u76F4\u63A5\u5F53\u5361\u7EA7\u5F00\u5173\u3002\n toggle={{\n checked: sections.header,\n onChange: next => { actions.setField(HEADER_ENABLED_FIELD, next) },\n }}\n >\n {/* \u7528\u6237\u5B9E\u6D4B\u8E29\u8FC7\u7684\u5751\uFF0C\u653E\u533A\u5757\u6700\u524D\u9762\uFF1A\u8FD9\u4E00\u680F\u662F\u4E3A\u4E86 OpenCode \u7684 API \u5730\u5740\u670D\u52A1\u7684\uFF0C\n \u7528 DSH \u81EA\u5E26\u7684\u5730\u5740\u914D\u7F6E\u53D1\u56FE\u7247\u4F1A\u62A5\u9519\u3002 */}\n <p style={hintError}>\n \u26A0\uFE0F \u8BF7\u4F7F\u7528\u81EA\u5B9A\u4E49\u7684 OpenCode API \u5730\u5740\uFF0C\u4E0D\u8981\u7528 DSH \u81EA\u5E26\u7684 API \u5730\u5740\u914D\u7F6E\uFF1A\n \u7528\u81EA\u5E26\u7684\u914D\u7F6E\u65E0\u6CD5\u4E0A\u4F20\u56FE\u7247\uFF0C\u4E00\u65E6\u53D1\u9001\u56FE\u7247\u5C31\u4F1A\u62A5\u9519\u3002\n </p>\n <p style={bodyLead}>\n OpenCode \u7684\u63A5\u53E3\u8981\u6C42\u5BA2\u6237\u7AEF\u6BCF\u6B21\u8BF7\u6C42\u90FD\u5E26\u4E0A\u4E00\u4E2A\u7A33\u5B9A\u7684\u4F1A\u8BDD ID \u8BF7\u6C42\u5934\uFF08\u5B98\u65B9 Go \u6587\u6863\n \u300C\u53EF\u4EE5\u5728\u54EA\u91CC\u4F7F\u7528\uFF1F\u300D\u7B2C 3 \u6761\uFF1A\u4E3A\u6BCF\u6BB5\u5BF9\u8BDD\u5728 x-opencode-session \u4E2D\u53D1\u9001\u4F1A\u8BDD ID\uFF0C\n \u4EE5\u4FBF\u5176\u4F18\u5316\u8DEF\u7531\u4E0E\u63D0\u793A\u8BCD\u7F13\u5B58\uFF09\u3002DSH \u7684\u8BBE\u7F6E\u9875\u4E0D\u63D0\u4F9B\u8BF7\u6C42\u5934\u7F16\u8F91\u5668\uFF0C\u6240\u4EE5\u8FD9\u91CC\u76F4\u63A5\u628A\u5B83\u5199\u8FDB\n llm-pi-ai \u7684 provider \u914D\u7F6E\u2014\u2014\u4E0B\u4E00\u6B21\u6A21\u578B\u8BF7\u6C42\u5C31\u751F\u6548\uFF0C\u4E0D\u7528\u91CD\u542F\uFF0C\u4E5F\u4E0D\u7528\u624B\u5DE5\u6539 settings.yaml\u3002\n \u53EA\u5BF9 llm-pi-ai \u91CC\u300C\u5DF2\u5B58\u5728\u300D\u7684 opencode \u7CFB\u8DEF\u7531\u751F\u6548\uFF0C\u4E0D\u4F1A\u51ED\u7A7A\u65B0\u5EFA provider\uFF1B\n \u603B\u5F00\u5173\u5173\u95ED\u6216\u672C\u680F\u76EE\u505C\u7528\u65F6\uFF0C\u5199\u5165\u7684\u5934\u4F1A\u81EA\u52A8\u64A4\u9500\u3002\n </p>\n <TextFieldRow\n title=\"\u5934\u540D\"\n desc={`\u9ED8\u8BA4 ${DEFAULT_HEADER_NAME}\uFF08OpenCode \u5B98\u65B9\u8981\u6C42\u7684\u90A3\u4E00\u4E2A\uFF09`}\n value={settings.headerName}\n placeholder={DEFAULT_HEADER_NAME}\n maxLength={HEADER_NAME_MAX}\n onChange={next => { actions.setField(HEADER_NAME_FIELD, next) }}\n />\n <TextFieldRow\n title=\"\u503C\"\n desc=\"\u6240\u6709\u5BF9\u8BDD\u5171\u7528\u8FD9\u4E00\u4E2A\u503C\uFF1B\u7559\u7A7A\u65F6\u9996\u6B21\u542F\u7528\u4F1A\u81EA\u52A8\u751F\u6210\u4E00\u4E2A UUID \u5E76\u4FDD\u5B58\u6CBF\u7528\"\n value={settings.headerValue}\n placeholder=\"\u7559\u7A7A = \u81EA\u52A8\u751F\u6210\"\n maxLength={HEADER_VALUE_MAX}\n onChange={next => { actions.setField(HEADER_VALUE_FIELD, next) }}\n action={{\n label: '\u91CD\u65B0\u751F\u6210',\n onClick: () => { actions.setField(HEADER_VALUE_FIELD, newSessionId()) },\n }}\n />\n <TextFieldRow\n title=\"\u4F5C\u7528\u8DEF\u7531\"\n desc=\"\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u7559\u7A7A = \u81EA\u52A8\u5339\u914D OpenCode \u8DEF\u7531\uFF08\u540D\u5B57\u4EE5 opencode \u5F00\u5934\uFF0C\u6216 baseURL \u6307\u5411 opencode.ai\uFF09\"\n value={settings.headerRoutes}\n placeholder=\"\u7559\u7A7A = \u81EA\u52A8\uFF08opencode* \u6216 opencode.ai \u7AEF\u70B9\uFF09\"\n maxLength={HEADER_VALUE_MAX}\n onChange={next => { actions.setField(HEADER_ROUTES_FIELD, next) }}\n />\n <p style={hintInfo}>\u72B6\u6001\uFF1A{headerStatusText}</p>\n </FoldCard>\n\n <FoldCard\n name=\"\u9ED8\u8BA4\u7EC8\u7AEF\"\n summary={terminalSummary}\n toggle={{\n checked: sections.terminal,\n onChange: next => { actions.setField(TERMINAL_ENABLED_FIELD, next) },\n }}\n // \u4E09\u6863\u4ECE\u5185\u5BB9\u533A\u642C\u5230\u6807\u9898\u884C\uFF08\u5B83\u6BD4\u5F00\u5173\u66F4\u9002\u5408\u5F53\"\u8FD9\u4E00\u680F\u5F53\u524D\u662F\u4EC0\u4E48\u72B6\u6001\"\u7684\u5C55\u793A\uFF09\u3002\n controls={(\n <PillChoice\n compact\n items={TERMINAL_MODES}\n value={settings.terminalMode}\n onChange={mode => { actions.setField(TERMINAL_MODE_FIELD, mode) }}\n ariaLabel=\"\u7EC8\u7AEF\u5DE5\u5177\"\n />\n )}\n >\n <p style={bodyLead}>\n Windows \u4E0A DSH \u7ED9\u6A21\u578B\u7684\u7EC8\u7AEF\u5DE5\u5177\u662F PowerShell\uFF0C\u800C\u6A21\u578B\u5BF9 bash \u8BED\u6CD5\u7684\u628A\u63E1\u660E\u663E\u66F4\u597D\u3002\u8FD9\u4E00\u680F\u628A\u7EC8\u7AEF\n \u6362\u6210 Git Bash\uFF1A\u6A21\u578B\u770B\u5230\u7684\u5DE5\u5177\u5C31\u53EB bash\u3001PowerShell \u90A3\u4E2A\u5DE5\u5177\u4F1A\u4ECE\u5B83\u7684\u5DE5\u5177\u5217\u8868\u91CC\u6D88\u5931\uFF0C\n \u547D\u4EE4\u91CC\u7684\u8DEF\u5F84\u4E0E\u5F15\u53F7\u6309 bash \u89C4\u5219\u5199\u3002\u672C\u673A\u4E0D\u9700\u8981\u88C5 Git for Windows \u5230\u9ED8\u8BA4\u76EE\u5F55\u2014\u2014\u63A2\u6D4B\u4F1A\u5148\u627E\n git\uFF0C\u518D\u7531\u540C\u4E00\u4E2A\u5B89\u88C5\u53CD\u63A8 bash\u3002\uFF08\u6863\u4F4D\u5728\u6807\u9898\u884C\u4E0A\uFF1A\u81EA\u52A8 / Git Bash / PowerShell\u3002\uFF09\n </p>\n <DefaultTerminalBody settings={settings} setField={actions.setField} hideMode />\n </FoldCard>\n </>)}\n </div>\n )\n}\n", "/**\n * \u6761\u76EE\u5217\u8868**\u6700\u4E0B\u8FB9**\u90A3\u4E00\u884C\u300C\uFF0B\u300D\uFF1A\u70B9\u5F00\u5206\u300C\u65B0\u5EFA / \u79FB\u52A8\u300D\u3002\n *\n * \u300C\u79FB\u52A8\u300D\u5217\u51FA**\u5176\u5B83\u5206\u7C7B**\u91CC\u7684\u5168\u90E8\u6761\u76EE\uFF08`\u5206\u7C7B\u540D \u00B7 \u6761\u76EE\u540D`\uFF09\uFF0C\u70B9\u5B83\u5C31\u628A\u90A3\u6761\u79FB\u8FDB\n * \u5F53\u524D\u5206\u7C7B\uFF08\u8FFD\u52A0\u5230\u672B\u5C3E\uFF0C\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u6807\u8BB0\u8DDF\u7740\u8D70\uFF09\u3002\u83DC\u5355\u5185\u5BB9\u662F\u8DDF\u7740\u5206\u7C7B\u53D8\u7684\uFF0C\u6240\u4EE5\n * \u5207\u6362\u5206\u7C7B\u65F6\u4F1A\u81EA\u52A8\u6536\u8D77\uFF1B\u70B9\u5916\u9762\u6216\u6309 Escape \u4E5F\u6536\u8D77\u3002\n *\n * \u9762\u677F\u4E0E\u8BBE\u7F6E\u9875\u5171\u7528\u540C\u4E00\u4E2A\u7EC4\u4EF6\uFF1A\u9762\u677F\u7A7A\u95F4\u7D27\u5F20\uFF08variant='panel' \u66F4\u7D27\u51D1\uFF09\uFF0C\u8BBE\u7F6E\u9875\u7528\n * \u5361\u7247\u98CE\u683C\uFF08variant='settings'\uFF09\u3002\u4E24\u8FB9\u884C\u4E3A\u5FC5\u987B\u4E00\u81F4\uFF0C\u6240\u4EE5\u4E0D\u8BA9\u5B83\u4EEC\u5404\u5199\u4E00\u5957\u3002\n */\nimport React, { useEffect, useRef, useState } from 'react'\nimport type { CSSProperties } from 'react'\nimport type { QuickPromptBook } from '../settings-contract.ts'\nimport { promptsElsewhere } from './prompt-book.ts'\n\n/** \u7EC4\u4EF6\u7684\u6CE8\u5165\u9762\uFF08\u653E\u5728\u4E24\u8FB9\u5404\u81EA\u7684\u6570\u636E\u6E90\u4E4B\u4E0A\uFF1A\u8BBE\u7F6E\u9875\u4F20\u8349\u7A3F\uFF0C\u9762\u677F\u4F20\u7EBF\u4E0A\u672C\uFF09\u3002 */\nexport interface AddPromptRowProps {\n /** \u5F53\u524D\u8FD9\u672C\uFF1B\u300C\u79FB\u52A8\u300D\u83DC\u5355\u8981\u4ECE\u4E2D\u5217\u51FA\u5176\u5B83\u5206\u7C7B\u7684\u6761\u76EE\u3002 */\n book: QuickPromptBook\n /** \u6761\u76EE\u5C06\u843D\u5230\u8FD9\u4E2A\u5206\u7C7B\u3002 */\n categoryId: string\n /** \u65B0\u5EFA\u4E00\u6761\uFF08\u7531\u8C03\u7528\u65B9\u51B3\u5B9A\u600E\u4E48\u843D\u76D8\uFF1A\u8BBE\u7F6E\u9875\u8FDB\u8349\u7A3F\uFF0C\u9762\u677F\u76F4\u63A5\u5199\uFF09\u3002 */\n onAdd: () => void\n /** \u628A\u8FD9\u6761\u4ECE\u5B83\u6240\u5728\u5206\u7C7B\u79FB\u5230\u8FD9\u91CC\u3002 */\n onMove: (promptId: string) => void\n /** \u89C6\u89C9\u53D8\u4F53\uFF1A\u9762\u677F\u66F4\u7D27\u51D1\u3002 */\n variant?: 'panel' | 'settings'\n}\n\nconst rowBase: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n width: '100%',\n borderRadius: 8,\n border: '0.5px dashed var(--dsw-alias-border-l2)',\n background: 'transparent',\n color: 'var(--dsw-alias-label-tertiary)',\n cursor: 'pointer',\n textAlign: 'left',\n}\n\nconst choiceBase: CSSProperties = {\n padding: '4px 9px',\n borderRadius: 999,\n border: '0.5px solid var(--dsw-alias-border-l2)',\n background: 'transparent',\n color: 'var(--dsw-alias-label-primary)',\n fontSize: 11,\n lineHeight: 1.2,\n cursor: 'pointer',\n}\n\nconst candidateBase: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n width: '100%',\n padding: '4px 6px',\n borderRadius: 6,\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n textAlign: 'left',\n}\n\n/** \u300C\uFF0B \u65B0\u5EFA / \u79FB\u52A8\u300D\u90A3\u4E00\u884C\u3002 */\nexport function AddPromptRow({\n book, categoryId, onAdd, onMove, variant = 'settings',\n}: AddPromptRowProps) {\n const [mode, setMode] = useState<'closed' | 'choose' | 'move'>('closed')\n const ref = useRef<HTMLDivElement | null>(null)\n\n // \u6362\u5206\u7C7B\u5C31\u6536\u8D77\uFF1A\u83DC\u5355\u91CC\u7684\u5019\u9009\u662F\u300C\u5176\u5B83\u5206\u7C7B\u300D\uFF0C\u7559\u7740\u4F1A\u663E\u793A\u4E0A\u4E00\u4E2A\u5206\u7C7B\u5224\u65AD\u51FA\u6765\u7684\u5217\u8868\u3002\n useEffect(() => { setMode('closed') }, [categoryId])\n\n useEffect(() => {\n if (mode === 'closed') return\n const onPointerDown = (event: PointerEvent): void => {\n if (ref.current !== null && event.target instanceof Node && ref.current.contains(event.target)) return\n setMode('closed')\n }\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') setMode('closed')\n }\n document.addEventListener('pointerdown', onPointerDown, true)\n document.addEventListener('keydown', onKeyDown, true)\n return () => {\n document.removeEventListener('pointerdown', onPointerDown, true)\n document.removeEventListener('keydown', onKeyDown, true)\n }\n }, [mode])\n\n const compact = variant === 'panel'\n const candidates = mode === 'move' ? promptsElsewhere(book, categoryId) : []\n\n return (\n <div ref={ref} style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>\n <button\n type=\"button\"\n aria-expanded={mode !== 'closed'}\n title=\"\u65B0\u5EFA\u4E00\u6761\uFF0C\u6216\u628A\u522B\u7684\u5206\u7C7B\u91CC\u7684\u6761\u76EE\u79FB\u52A8\u5230\u8FD9\u91CC\"\n style={{\n ...rowBase,\n padding: compact ? '4px 8px' : '7px 9px',\n fontSize: compact ? 11 : 12,\n }}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { setMode(mode === 'closed' ? 'choose' : 'closed') }}\n >\n <span aria-hidden>\uFF0B</span>\n <span>{mode === 'closed' ? '\u65B0\u5EFA / \u79FB\u52A8' : '\u6536\u8D77'}</span>\n </button>\n\n {mode !== 'closed' && (\n <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>\n <button\n type=\"button\"\n style={choiceBase}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { setMode('closed'); onAdd() }}\n >\n \uFF0B \u65B0\u5EFA\u4E00\u6761\n </button>\n <button\n type=\"button\"\n style={mode === 'move' ? { ...choiceBase, borderColor: 'var(--dsw-alias-brand-primary)' } : choiceBase}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { setMode(mode === 'move' ? 'choose' : 'move') }}\n >\n \u2192 \u628A\u522B\u7684\u5206\u7C7B\u7684\u6761\u76EE\u79FB\u52A8\u5230\u8FD9\u91CC\n </button>\n </div>\n )}\n\n {mode === 'move' && (\n <div\n style={{\n display: 'flex', flexDirection: 'column', gap: 2,\n maxHeight: 190, overflowY: 'auto',\n border: '0.5px solid var(--dsw-alias-border-l2)',\n borderRadius: 8, padding: 4,\n }}\n >\n {candidates.length === 0 && (\n <span style={{ color: 'var(--dsw-alias-label-tertiary)', fontSize: 11, padding: '4px 6px' }}>\n \u522B\u7684\u5206\u7C7B\u91CC\u8FD8\u6CA1\u6709\u6761\u76EE\u53EF\u4EE5\u79FB\u52A8\u3002\n </span>\n )}\n {candidates.map(candidate => (\n <button\n key={candidate.prompt.id}\n type=\"button\"\n title={`${candidate.categoryName} \u00B7 ${candidate.prompt.prompt}`}\n style={candidateBase}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => {\n setMode('closed')\n onMove(candidate.prompt.id)\n }}\n >\n <span style={{ color: 'var(--dsw-alias-label-tertiary)', fontSize: 11, flex: '0 0 auto' }}>\n {candidate.categoryName}\n </span>\n <span style={{ color: 'var(--dsw-alias-label-tertiary)', flex: '0 0 auto' }}>\u00B7</span>\n <span\n style={{\n color: 'var(--dsw-alias-label-primary)', fontSize: 12,\n minWidth: 0, flex: '1 1 auto', overflow: 'hidden',\n textOverflow: 'ellipsis', whiteSpace: 'nowrap',\n }}\n >\n {candidate.prompt.label}\n </span>\n {candidate.prompt.always && (\n <span style={{ color: 'var(--dsw-alias-label-tertiary)', fontSize: 10, flex: '0 0 auto' }}>\n \u9ED8\u8BA4\u63D2\u5165\n </span>\n )}\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n", "/**\n * \u63D0\u793A\u8BCD\u4F18\u5316\u5668\u7684\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF08\u4E09\u6863\uFF09+ \u7528\u6237\u6D88\u606F\u6784\u9020\u3002\n *\n * \u6765\u6E90\u4E0E\u6388\u6743\uFF1A\u521D\u7248\u90A3\u4E09\u6863\u6587\u672C\u9010\u5B57\u53D6\u81EA WestFox-AwA/dsh-prompt-optimizer \u7684 `lib/index.js` \u91CC\n * **`LEGACY_V011`** \u8FD9\u4E2A\u5E38\u91CF\uFF08BSD-3-Clause\uFF0C\u4F5C\u8005\u300C\u5543\u8F6E\u80CE\u7684\u897F\u72D0\u300D\uFF09\u2014\u2014 \u5B83\u81EA\u5DF1\u7684\u6CE8\u91CA\u5199\u7740\n * \"\u9010\u5B57\u8282\u53D6\u81EA 0.1.1 \u7684 system \u63D0\u793A\u8BCD\"\uFF0C\u53EA\u5728\u56DE\u9000\u7B56\u7565 `v011-ptc` \u4E0B\u4F7F\u7528\uFF0C\u5BF9\u65B9\u9ED8\u8BA4\u7B56\u7565\n * \uFF08`STRATEGY_DEFAULT = 'v6'`\uFF09\u8D70\u7684\u662F `buildSystem()` \u53E6\u4E00\u5957\u3002\n * 0.6.0 \u8D77\u6309\u5BF9\u65B9 **0.6 \u7EBF**\uFF08`po06/lib/interpreter.js` \u7684 `SYSTEM_PROMPT` +\n * `validateProvenance`\uFF09\u7684\u673A\u5236\u91CD\u5199\uFF0C\u672C\u63D2\u4EF6\u81EA\u8EAB\u4ECD\u6309 MIT \u53D1\u5E03\u3002\n *\n * \u2500\u2500 \u4E3A\u4EC0\u4E48\u6362\u6210\u8FD9\u5957\uFF08\u5BF9\u65B9\u7684\u771F\u95EE\u9898\uFF0C\u4E5F\u662F\u6211\u4EEC\u7684\uFF09\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * \u65E7\u7248\u662F**\u81EA\u7531\u6539\u5199\u5668**\uFF1A\u6A21\u578B\u76F4\u63A5\u5410\u4E00\u6761\u6210\u54C1\u547D\u4EE4\uFF0C\u5BBF\u4E3B\u53EA\u80FD\u6574\u6BB5\u7167\u6536\u3002\u4E8E\u662F\"\u6A21\u578B\u66FF\u7528\u6237\u53D1\u660E\n * \u4E86\u4E00\u6761\u8981\u6C42\"\u8FD9\u4EF6\u4E8B\u5728\u7ED3\u6784\u4E0A\u65E0\u6CD5\u88AB\u53D1\u73B0 \u2014\u2014 \u63D0\u793A\u8BCD\u91CC\u5199\u5341\u904D\"\u4E0D\u8BB8\u65B0\u589E\u9700\u6C42\"\u4E5F\u6CA1\u7528\uFF0C\u56E0\u4E3A\n * \u6CA1\u6709\u4EFB\u4F55**\u53EF\u673A\u68B0\u6838\u5BF9**\u7684\u5224\u636E\u3002\n *\n * 0.6 \u7684\u529E\u6CD5\uFF1A\u628A\"\u4FE1\u4EFB\u95EE\u9898\"\u53D8\u6210\"\u5B57\u7B26\u4E32\u6BD4\u5BF9\u95EE\u9898\"\u3002\n * \u00B7 \u6A21\u578B\u4E0D\u518D\u81EA\u7531\u5199\uFF0C\u53EA\u4EA7\u51FA**\u6761\u76EE**\uFF1B\n * \u00B7 \u6BCF\u6761 `rewrite` / `requirement` / `quality` \u5FC5\u987B\u9644 `quote` \u2014\u2014 \u4E00\u6BB5**\u5728\u7528\u6237\u539F\u8BDD\u91CC\n * \u9010\u5B57\u5B58\u5728**\u7684\u5B50\u4E32\uFF08\u7167\u6284\uFF0C\u4E0D\u8BB8\u6539\u5199\u3001\u4E0D\u8BB8\u8865\u6807\u70B9\uFF09\uFF1B\n * \u00B7 \u5BBF\u4E3B\u5728 `optimizer-assemble.ts` \u91CC\u505A\u5B57\u9762\u5B50\u4E32\u6BD4\u5BF9\uFF0C**\u5BF9\u4E0D\u4E0A\u5C31\u4E22\u90A3\u4E00\u6761\u5E76\u8BB0\u8D26**\uFF1B\n * \u00B7 `rewrite` \u6309\u5F15\u6587\u5728\u539F\u8BDD\u91CC\u7684**\u4F4D\u7F6E**\u56DE\u586B\uFF0C\u6CA1\u88AB\u8986\u76D6\u7684\u90E8\u5206\u539F\u6837\u4FDD\u7559\u3002\n * \u8FD9\u6837\"\u51ED\u7A7A\u52A0\u9700\u6C42\"\u4E0D\u518D\u662F\u4FE1\u4EFB\u95EE\u9898\uFF1A\u5B83\u62FF\u4E0D\u51FA\u9010\u5B57\u4F9D\u636E\u3002\n *\n * \u6863\u4F4D\u8BED\u4E49\u4E5F\u7167\u642C\u5BF9\u65B9\u7684\u8BF4\u6CD5\uFF1A**\u6863\u4F4D = \u4F9D\u636E\u9884\u7B97**\uFF08\u5141\u8BB8\u8865\u5230\u4EC0\u4E48\u7A0B\u5EA6\u3001\u6210\u54C1\u5141\u8BB8\u591A\u957F\uFF09\uFF0C\n * \u800C\u4E0D\u662F\"\u6362\u4E00\u79CD\u6587\u98CE\"\u3002\u6E29\u5EA6\u4ECD\u6CBF\u7528\u521D\u7248\u5B9E\u6D4B\u503C\uFF080.2 / 0.3 / 0.3\uFF09\u3002\n *\n * \u672C\u6A21\u5757\u96F6 import\uFF0Chost \u534A\u4E0E\u6D4B\u8BD5\u5171\u7528\u3002\n */\n\n/** \u4F20\u8BDD\u8005\u4EBA\u8BBE\uFF1A\u4E3A\u4EC0\u4E48\u5FC5\u987B\u5355\u72EC\u6210\u6BB5\u2014\u2014\u88F8\u6587\u672C\u4F1A\u88AB\u6A21\u578B\u5F53\u6210\u300C\u5BF9\u5B83\u8BF4\u7684\u8BDD\u300D\u800C\u5F00\u59CB\u5BF9\u8BDD\u3002 */\nconst RELAY_ROLE = [\n '\u3010\u4F60\u662F\u8C01\u3011\u4F60\u662F\u4E00\u4E2A**\u4F20\u8BDD\u5668/\u610F\u56FE\u8865\u5168\u5668**\uFF0C\u7AD9\u5728\u7528\u6237\u4E0E\"\u5DE5\u4F5C AI\"\u4E4B\u95F4\uFF1A',\n ' \u7528\u6237 \u2192\uFF08\u4F60\uFF1A\u628A\u7528\u6237\u7684\u610F\u601D\u6574\u7406\u6210\u6761\u76EE\u5E76\u7ED9\u51FA\u9010\u5B57\u4F9D\u636E\uFF09\u2192 \u5BBF\u4E3B\uFF08\u88C5\u914D\u6210\u4E00\u6761\u547D\u4EE4\uFF09\u2192 \u5DE5\u4F5C AI\u3002',\n '\u4F60\u7684\u4EA7\u51FA**\u4E0D\u4F1A**\u88AB\u76F4\u63A5\u5C55\u793A\u7ED9\u7528\u6237\uFF0C\u4E5F\u4E0D\u4F1A\u88AB\u539F\u6837\u53D1\u51FA\uFF1A\u5BBF\u4E3B\u4F1A\u7528\u4F60\u7ED9\u7684**\u9010\u5B57\u5F15\u6587**',\n '\u5728\u539F\u8BDD\u91CC\u5B9A\u4F4D\u3001\u53EA\u91C7\u7EB3\u80FD\u6838\u5BF9\u7684\u6761\u76EE\uFF0C\u518D\u88C5\u914D\u6210\u4E00\u6761\u547D\u4EE4\u4EA4\u7ED9\u5DE5\u4F5C AI\u3002',\n '\u3010\u4F60\u4E0D\u662F\u8C01\u3011\u4F60\u4E0D\u662F\u5728\u548C\u7528\u6237\u804A\u5929\uFF0C\u4E5F\u4E0D\u662F\u5728\u56DE\u7B54\u7528\u6237\uFF1A',\n '- \u4E0D\u8981\u56DE\u5E94\u3001\u4E0D\u8981\u56DE\u7B54\u7528\u6237\u7684\u8981\u6C42\uFF0C\u4E5F\u4E0D\u8981\u66FF\u7528\u6237\u5B8C\u6210\u4EFB\u52A1\uFF08\u4E0D\u8981\u76F4\u63A5\u7ED9\u51FA\u4EE3\u7801/\u7B54\u6848/\u7ED3\u679C\uFF09\u3002',\n '- \u4E0D\u8981\u4EE5\u52A9\u624B\u53E3\u543B\u5BF9\u7528\u6237\u8BF4\u8BDD\uFF08\"\u597D\u7684\"\"\u6536\u5230\"\"\u6211\u53EF\u4EE5\u5E2E\u4F60\"\"\u5EFA\u8BAE\u4F60\u2026\"\"\u9700\u8981\u6211\u2026\u5417\"\uFF09\u3002',\n '- \u4E0D\u8981\u628A\u7528\u6237\u53D1\u6765\u7684\u6587\u5B57\u5F53\u6210\"\u5BF9\u4F60\u8BF4\u7684\u8BDD\"\u6765\u56DE\u5E94\uFF1B\u5B83\u53EA\u662F\u4F60\u8981\u8F6C\u8FBE\u7684\u5185\u5BB9\u3002',\n '- \u4E0D\u8981\u5411\u7528\u6237\u63D0\u95EE\u3002\u8981\u6F84\u6E05\u65F6\uFF0C\u5199\u6210**\u7ED9\u5DE5\u4F5C AI \u7684\u6307\u4EE4**\uFF1A',\n ' \"\u82E5 X \u4E0D\u660E\u786E\uFF0C\u5148\u8BFB Y \u6216\u5148\u5411\u6211\u786E\u8BA4\uFF0C\u4E0D\u8981\u81EA\u884C\u5047\u8BBE\"\u3002',\n].join('\\n')\n\n/**\n * \u4F9D\u636E\u7EAA\u5F8B \u2014\u2014 \u8FD9\u5957\u673A\u5236\u7684\u5168\u90E8\u4EF7\u503C\u6240\u5728\u3002\n *\n * \u6BCF\u6761\u90FD\u5BF9\u5E94\u4E00\u4E2A**\u5BBF\u4E3B\u771F\u7684\u4F1A\u6267\u884C**\u7684\u68C0\u67E5\uFF08\u89C1 optimizer-assemble.ts\uFF09\uFF1A\n * \u6CA1\u6709\u5F15\u6587 \u2192 \u4E22\u8FD9\u4E00\u6761\uFF1B\u5F15\u6587\u4E0D\u662F\u5B57\u9762\u5B50\u4E32 \u2192 \u4E22\u8FD9\u4E00\u6761\uFF1B\u6761\u6570\u8D85\u4E0A\u9650 \u2192 \u622A\u65AD\u540E\u9762\u5E76\u8BB0\u8D26\u3002\n * \u63D0\u793A\u8BCD\u91CC\u5199\"\u5FC5\u987B\"\u800C\u5BBF\u4E3B\u4E0D\u67E5\uFF0C\u5C31\u662F\u7A7A\u8BDD\uFF1B\u8FD9\u91CC\u4E24\u8FB9\u662F\u914D\u5957\u7684\u3002\n */\nconst EVIDENCE_RULES = [\n '\u3010\u4F9D\u636E\u7EAA\u5F8B\uFF08\u5BBF\u4E3B\u4F1A\u9010\u6761\u673A\u68B0\u6838\u5BF9\uFF0C\u5199\u9519\u5C31\u4E22\u8FD9\u4E00\u6761\uFF09\u3011',\n '1. `rewrite` / `requirement` / `quality` **\u5FC5\u987B**\u5E26 `quote`\uFF1A\u4E00\u6BB5\u5728\u3010\u7528\u6237\u539F\u8BDD\u3011\u91CC',\n ' **\u9010\u5B57\u5B58\u5728**\u7684\u5B50\u4E32 \u2014\u2014 \u7167\u6284\uFF0C\u4E0D\u8981\u6539\u5199\u3001\u4E0D\u8981\u8865\u6807\u70B9\u3001\u4E0D\u8981\u7FFB\u8BD1\u3002\u5BBF\u4E3B\u505A\u5B57\u9762\u5B50\u4E32\u6BD4\u5BF9\uFF0C',\n ' \u5BF9\u4E0D\u4E0A\u5C31\u4E22\u6389\u90A3\u4E00\u6761\uFF08\u4E0D\u4F1A\u62A5\u9519\u7ED9\u4F60\uFF0C\u4E5F\u4E0D\u4F1A\u6709\u4EBA\u63D0\u9192\u4F60\uFF09\u3002',\n '2. **\u4E0D\u8BB8\u51ED\u7A7A\u65B0\u589E**\uFF1A\u4EA7\u54C1\u76EE\u6807\u3001\u529F\u80FD\u3001\u786C\u7EA6\u675F\uFF08\"\u5FC5\u987B\u79BB\u7EBF\"\"\u7981\u6B62\u8054\u7F51\"\"\u53EA\u80FD\u7528\u67D0\u4E2A\u5E93\"',\n ' \"\u5FC5\u987B\u652F\u6301\u79FB\u52A8\u7AEF\"\uFF09\u4E00\u5F8B\u4E0D\u8BB8\u7531\u4F60\u51B3\u5B9A\u3002\u4F60\u53EA\u80FD\u8865**\u80FD\u4ECE\u539F\u8BDD\u67D0\u4E00\u53E5\u76F4\u63A5\u63A8\u51FA**\u7684\u6700\u4F4E\u8981\u6C42\uFF0C',\n ' \u5E76\u4E14\u5FC5\u987B\u5F15\u7528\u90A3\u4E00\u53E5\u3002',\n '3. \u4E0D\u786E\u5B9A\u3001\u4F1A\u5F71\u54CD\u7ED3\u679C\u3001\u4E14\u53EA\u6709\u7528\u6237\u80FD\u5B9A\u7684\u53D6\u820D \u2192 \u5199 `unknown`\uFF08`unknownClass` =',\n ' \"user_preference\"\uFF09\uFF0C**\u4E0D\u8981\u66FF\u7528\u6237\u731C**\uFF0C\u4E5F\u4E0D\u8981\u5199\"\u6309\u6700\u4FDD\u5B88\u7406\u89E3\u6267\u884C\"\u3002',\n ' \u5728\u8BB8\u53EF\u8303\u56F4\u5185\u8BFB\u4EE3\u7801\u5C31\u80FD\u786E\u5B9A\u7684\u4E8B\u5B9E\u5199 \"lookupable_fact\"\uFF1B\u53EF\u9006\u7684\u5B9E\u73B0\u7EC6\u8282',\n ' \uFF08\u95F4\u8DDD\u3001\u547D\u540D\u3001\u5E93\u7684\u5185\u90E8\u7528\u6CD5\uFF09\u5199 \"implementation_detail\"\u3002',\n '4. \u4E0D\u5F97\u865A\u6784\u9879\u76EE\u4E8B\u5B9E\uFF08\u6587\u4EF6\u5185\u5BB9\u3001\u76EE\u5F55\u7ED3\u6784\u3001\u4F9D\u8D56\u7248\u672C\uFF09\u3002\u4F60\u6CA1\u8BFB\u5230\u7684\u4E1C\u897F\u4E0D\u5B58\u5728\u3002',\n].join('\\n')\n\n/** \u5199\u6B63\u6587\u65F6\u7684\u6587\u98CE\u7EAA\u5F8B\uFF1A\u8FD9\u4E9B `text` \u4F1A\u88AB\u62FC\u8FDB\u6700\u7EC8\u547D\u4EE4\uFF0C\u8BFB\u8005\u53EA\u6709\u5DE5\u4F5C AI \u4E00\u4E2A\u3002 */\nconst STYLE_RULES = [\n '\u3010\u5199 text \u7684\u7EAA\u5F8B\u3011\u4F60\u7684 text \u4F1A\u88AB\u5BBF\u4E3B\u62FC\u8FDB\u6700\u7EC8\u547D\u4EE4\uFF0C\u8BFB\u8005\u53EA\u6709\"\u5DE5\u4F5C AI\"\u4E00\u4E2A\uFF1A',\n '- \u7948\u4F7F\u53E5\u3001\u76F4\u7ED9\u8981\u6C42\u3001\u53EF\u6267\u884C\uFF1B\u4E2D\u6587\u8FDB\u4E2D\u6587\u51FA\u3002',\n '- \u4E0D\u8981\u5143\u8BDD\u8BED\u4E0E\u5143\u6807\u9898\uFF08\"\u4F18\u5316\u540E\u7684\u63D0\u793A\u8BCD\"\"\u6539\u5199\u540E\"\"\u8BF4\u660E\"\"\u4EE5\u4E0B\u662F\u2026\"\uFF09\u3002',\n '- \u4E0D\u8981\u63D0\u5230\"\u7528\u6237/\u539F\u6587/\u4E0A\u9762\u7684\u8BDD\"\uFF0C\u4E5F\u4E0D\u8981\u5199\"\u6211\u6765\u5E2E\u4F60\u2026\"\u3002',\n '- \u4E0D\u8981\u5199\u6D41\u7A0B\u4EEA\u5F0F\u3001\u901A\u7528\u6559\u5B66\u3001\u9A8C\u6536\u5957\u8BDD\uFF08\"\u8BF7\u786E\u4FDD\u4EE3\u7801\u8D28\u91CF\"\u8FD9\u79CD\u6CA1\u6709\u6307\u5411\u7684\u8BDD\uFF09\u3002',\n '- `rewrite` \u7684 text \u662F**\u66FF\u6362\u6389\u90A3\u6BB5\u5F15\u6587**\u7684\u6B63\u6587\uFF0C\u6240\u4EE5\u53EA\u5199\u90A3\u6BB5\u8BDD\u672C\u8EAB\uFF0C\u4E0D\u8981\u5E26\u524D\u7F00\u540E\u7F00\u3002',\n].join('\\n')\n\n/**\n * \u8F93\u51FA\u5951\u7EA6\uFF1A**\u6C38\u8FDC\u8FFD\u52A0\u5728\u6700\u540E\u4E00\u6BB5**\uFF0C\u4E14\u4E0D\u968F\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u6539\u53D8\u3002\n *\n * \u4E3A\u4EC0\u4E48\u4E0D\u8BA9\u5B83\u88AB\u6539\uFF1A\u5BBF\u4E3B\u6309\u8FD9\u4EFD\u5951\u7EA6\u89E3\u6790\uFF1B\u5951\u7EA6\u4E00\u6539\uFF0C\"\u9010\u5B57\u4F9D\u636E\"\u5C31\u6CA1\u4EBA\u6821\u9A8C\u4E86\uFF0C\n * \u6574\u5957\u673A\u5236\u9000\u5316\u6210\"\u4FE1\u4EFB\u6A21\u578B\"\u3002\u8BBE\u7F6E\u9875\u7684\u8BF4\u660E\u91CC\u5BF9\u6B64\u6709\u660E\u793A\u3002\n * \u653E\u6700\u540E\u662F\u56E0\u4E3A\u6A21\u578B\u5BF9**\u6700\u540E\u4E00\u6761\u6307\u4EE4**\u7684\u670D\u4ECE\u5EA6\u6700\u9AD8\uFF08\u5BF9\u65B9 0.6 \u7684 `askTail` \u540C\u7406\uFF09\u3002\n */\nexport const OPTIMIZER_OUTPUT_CONTRACT = [\n '\u3010\u8F93\u51FA\u5951\u7EA6\uFF08\u56FA\u5B9A\uFF0C\u4E0D\u53EF\u66F4\u6539\uFF09\u3011',\n '\u53EA\u8F93\u51FA\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u4E0D\u8981 Markdown \u4EE3\u7801\u5757\u3001\u4E0D\u8981\u5728 JSON \u524D\u540E\u5199\u4EFB\u4F55\u5B57\uFF1A',\n '{\"items\":[{\"kind\":\"rewrite\",\"quote\":\"\u539F\u8BDD\u91CC\u9010\u5B57\u5B58\u5728\u7684\u7247\u6BB5\",\"text\":\"\u66FF\u6362\u6389\u8BE5\u7247\u6BB5\u7684\u6B63\u6587\"}]}',\n '\u5B57\u6BB5\u4E0E\u53D6\u503C\uFF08`kind` \u53EA\u80FD\u662F\u8FD9\u516D\u79CD\uFF09\uFF1A',\n '- rewrite\uFF1A\u8BED\u8A00\u5C42\u4FEE\u590D\u3002`quote` \u5FC5\u586B\uFF1B\u540C\u4E00\u6BB5\u539F\u8BDD\u6700\u591A\u4E00\u6761 rewrite\uFF0C\u4E0D\u8981\u91CD\u53E0\u3002',\n '- requirement\uFF1A\u4ECE `quote` \u76F4\u63A5\u63A8\u51FA\u7684\u8865\u5168\u8981\u6C42\uFF08\u9A8C\u6536\u6807\u51C6/\u786C\u7EA6\u675F\uFF09\u3002`quote` \u5FC5\u586B\u3002',\n '- quality\uFF1A\u5BF9\u539F\u8BDD\u91CC\u8D28\u91CF\u8BCD\u7684\u89E3\u91CA\u3002`quote` \u5FC5\u586B\uFF08\u5C31\u586B\u90A3\u51E0\u4E2A\u8D28\u91CF\u5B57\uFF09\u3002',\n '- unknown\uFF1A\u672A\u51B3\u9879\u3002\u5FC5\u987B\u5E26 `unknownClass`\uFF08user_preference / lookupable_fact /',\n ' implementation_detail\uFF09\uFF0C\u53EF\u9009 `blocking`\uFF08true/false\uFF0C\u662F\u5426\u6321\u4F4F\u4E0B\u4E00\u6B65\uFF09\u3002',\n '- plan\uFF1A\u5206\u9636\u6BB5\u6267\u884C\u8BA1\u5212\uFF08\u4EC5\"\u6781\u7AEF\"\u6863\u7528\uFF09\u3002',\n '- risk\uFF1A\u591A\u60C5\u51B5\u9884\u6848\uFF08\u4EC5\"\u6781\u7AEF\"\u6863\u7528\uFF09\uFF0C\u6BCF\u6761\u6309\"\u89E6\u53D1\u4FE1\u53F7 \u2192 \u5E94\u5BF9 \u2192 \u7981\u6B62\u52A8\u4F5C\"\u5199\u3002',\n '\u9650\u5236\uFF1A`text` \u6BCF\u6761\u4E0D\u8D85\u8FC7 300 \u5B57\uFF1B`items` \u603B\u5171\u4E0D\u8D85\u8FC7 12 \u6761\uFF1Bid \u4E0D\u9700\u8981\u7ED9\u3002',\n '\u6CA1\u6709\u53EF\u8865\u7684\u5185\u5BB9\u65F6\uFF0C\u8F93\u51FA {\"items\":[]} \u2014\u2014 \u4F46**\u5148\u60F3\u6E05\u695A**\uFF1A\u7528\u6237\u8FD9\u4E00\u8F6E\u7684\u539F\u8BDD\u91CC',\n '\u771F\u7684\u6CA1\u6709\u4EFB\u4F55\u53EF\u6838\u5BF9\u7684\u8865\u5168\u5417\uFF1F',\n].join('\\n')\n\n/** \u6A21\u578B\u53EF\u4EE5\u4EA7\u51FA\u7684\u6761\u76EE\u79CD\u7C7B\uFF08\u5BBF\u4E3B\u53EA\u8BA4\u8FD9\u4E9B\uFF0C\u5176\u4F59\u6574\u6761\u4E22\u5F03\u5E76\u8BB0\u8D26\uFF09\u3002 */\nexport const OPTIMIZE_ITEM_KINDS = ['rewrite', 'requirement', 'quality', 'unknown', 'plan', 'risk'] as const\n\n/** \u6A21\u578B\u53EF\u4EE5\u4EA7\u51FA\u7684\u672A\u51B3\u9879\u5206\u7C7B\uFF08\u7F3A\u7701\u6309\"\u53EA\u6709\u7528\u6237\u80FD\u5B9A\"\u5904\u7406\uFF0C\u4E0E\u5BF9\u65B9 0.6 \u540C\u53E3\u5F84\uFF09\u3002 */\nexport const OPTIMIZE_UNKNOWN_CLASSES = ['user_preference', 'lookupable_fact', 'implementation_detail'] as const\n\n/** \u5355\u6B21\u4EA7\u51FA\u5141\u8BB8\u7684\u6700\u5927\u6761\u76EE\u6570\uFF08\u8D85\u51FA\u90E8\u5206\u622A\u65AD\u5E76\u8BB0\u8D26\uFF0C\u800C\u4E0D\u662F\u6574\u8F6E\u4F5C\u5E9F\uFF09\u3002 */\nexport const OPTIMIZE_MAX_ITEMS = 12\n\n/** \u5355\u6761 `text` \u7684\u5B57\u7B26\u4E0A\u9650\uFF08\u8D85\u51FA\u5C31\u5730\u622A\u65AD\u5E76\u8BB0\u8D26\uFF09\u3002 */\nexport const OPTIMIZE_ITEM_MAX_CHARS = 300\n\n/**\n * \u5404\u6863\u7684\u4EFB\u52A1\u6BB5\uFF08**\u53EF\u88AB\u8BBE\u7F6E\u9875\u91CC\u7684\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u6574\u4F53\u66FF\u6362**\u7684\u90A3\u90E8\u5206\uFF09\u3002\n *\n * \u4E09\u6863\u7684\u5DEE\u522B\u662F\"\u5141\u8BB8\u8865\u5230\u54EA\u4E00\u5C42\"\uFF0C\u4E0D\u662F\"\u6362\u4E00\u79CD\u8BED\u6C14\"\uFF1A\n * \u00B7 basic \u2014\u2014 \u53EA\u78B0\u8BED\u8A00\uFF1B\u4E0D\u4EA7\u51FA requirement / plan / risk\u3002\n * \u00B7 advanced \u2014\u2014 \u5141\u8BB8\u8865\"\u80FD\u6307\u56DE\u539F\u8BDD\u67D0\u53E5\"\u7684\u5FC5\u8981\u8981\u6C42\uFF0C\u5E76\u5BF9\u8D28\u91CF\u8BCD\u4F5C\u89E3\u91CA\u3002\n * \u00B7 extreme \u2014\u2014 \u518D\u52A0\u5206\u9636\u6BB5\u8BA1\u5212\u4E0E\u9884\u6848\u3002\n */\nconst TIER_TASKS: Record<string, readonly string[]> = {\n basic: [\n '\u3010\u672C\u8F6E\u4EFB\u52A1\uFF1A\u53EA\u505A\u8BED\u8A00\u5C42\u4FEE\u590D\u3011',\n '\u7528\u6237\u539F\u8BDD\u53EF\u80FD\u6709\u75C5\u53E5\u3001\u6307\u4EE3\u4E0D\u660E\u3001\u7528\u8BCD\u542B\u7CCA\u3002\u628A\u5B83\u6539\u5199\u6210\u901A\u987A\u3001\u7CBE\u786E\u3001\u65E0\u6B67\u4E49\u7684**\u540C\u4E00\u6BB5\u8BDD**\u3002',\n '\u53EA\u4EA7\u51FA `rewrite`\uFF08\u53EF\u4EE5\u6309\u53E5\u5B50\u62C6\u6210\u591A\u6761\uFF0C\u6BCF\u6761\u5F15\u7528\u539F\u8BDD\u91CC\u5BF9\u5E94\u90A3\u4E00\u53E5\uFF09\u3002',\n '\u4E25\u7981\u4EA7\u51FA requirement / plan / risk\uFF1A\u8FD9\u4E00\u6863**\u4E0D\u65B0\u589E\u4EFB\u4F55\u8981\u6C42**\uFF0C\u53EA\u628A\u8BDD\u8BF4\u660E\u767D\u3002',\n '\u539F\u8BDD\u786E\u6709\u6B67\u4E49\u3001\u4E14\u6B67\u4E49\u4F1A\u5BFC\u81F4\u505A\u9519\u65F6\uFF0C\u624D\u8865\u4E00\u6761 `unknown`\uFF08unknownClass \u53D6',\n 'user_preference \u6216 lookupable_fact\uFF09\uFF1B\u786E\u5B9E\u6CA1\u6709\u53EF\u8865\u7684\u5C31\u8F93\u51FA\u7A7A\u6570\u7EC4\u3002',\n '\u957F\u5EA6\u7EAA\u5F8B\uFF1A\u6210\u54C1\u4E0D\u8D85\u8FC7\u539F\u8BDD\u7684 1.4 \u500D\uFF1B\u539F\u8BDD 30 \u5B57\u4EE5\u5185\u65F6\u4E0D\u8D85\u8FC7 60 \u5B57\u3002',\n ],\n advanced: [\n '\u3010\u672C\u8F6E\u4EFB\u52A1\uFF1A\u5728\u4E0D\u52A8\u76EE\u6807\u7684\u524D\u63D0\u4E0B\u628A\u547D\u4EE4\u8BF4\u6E05\u695A\u3011',\n '\u7528\u6237\u539F\u8BDD\u542B\u7CCA\u3001\u7F3A\u5173\u952E\u7EA6\u675F\u3002\u4F60\u8981\u8865\u7684\u662F\"\u7528\u6237\u663E\u7136\u60F3\u8981\u3001\u4F46\u6CA1\u8BF4\u51FA\u53E3\"\u7684\u5FC5\u8981\u4FE1\u606F\uFF0C',\n '\u8BA9\u5B83\u4E00\u6B21\u505A\u5BF9 \u2014\u2014 \u4F46\u6BCF\u4E00\u6761\u90FD\u5FC5\u987B\u662F**\u4ECE\u539F\u8BDD\u67D0\u4E00\u53E5\u76F4\u63A5\u63A8\u51FA**\u7684\uFF0C\u5E76\u5F15\u7528\u90A3\u4E00\u53E5\u3002',\n '\u5141\u8BB8\u4EA7\u51FA\uFF1A',\n '- `rewrite`\uFF1A\u628A\u542B\u7CCA\u3001\u6709\u75C5\u53E5\u7684\u5730\u65B9\u8BF4\u6E05\u695A\uFF08\u540C\u4E00\u6BB5\u539F\u8BDD\u6700\u591A\u4E00\u6761\uFF09\u3002',\n '- `requirement`\uFF1A\u4ECE\u539F\u8BDD\u76F4\u63A5\u63A8\u51FA\u7684\u6700\u4F4E\u4EA4\u4ED8\u8981\u6C42\u4E0E\u9A8C\u6536\u6807\u51C6\uFF08\"\u6539\u5B8C\u80FD\u8DD1\u8D77\u6765\"\"\u9875\u9762\u80FD\u6253\u5F00\"',\n ' \u8FD9\u7C7B\u53EF\u89C2\u6D4B\u7684\u8BDD\uFF09\uFF0C\u5199\u6210\u5BF9\u5DE5\u4F5C AI \u7684\u8981\u6C42\u800C\u4E0D\u662F\u8BC4\u8BBA\u3002\u6BCF\u6761\u90FD\u8981\u80FD\u6307\u56DE\u539F\u8BDD\u91CC\u7684\u67D0\u4E00\u53E5\u3002',\n '- `quality`\uFF1A\u7528\u6237\u8BF4\u7684\u8D28\u91CF\u8BCD\uFF08\"\u597D\u770B\u70B9\"\"\u9AD8\u7EA7\u611F\"\"\u6D41\u7545\"\uFF09\u2192 \u89E3\u91CA\u6210\u53EF\u89C2\u5BDF\u7684\u8981\u6C42\u3002',\n ' \u5B83\u662F**\u89E3\u91CA**\uFF0C\u4E0D\u662F\u65B0\u589E\u76EE\u6807\uFF1A\u4E00\u6761\u8D28\u91CF\u8BCD\u6700\u591A\u4E00\u6761 quality\u3002',\n '- `unknown`\uFF1A\u53EA\u6709\u7528\u6237\u80FD\u5B9A\u7684\u53D6\u820D\uFF08user_preference\uFF09/ \u8BE5\u53BB\u67E5\u8BC1\u7684\u4E8B\u5B9E\uFF08lookupable_fact\uFF09\u3002',\n '\u7981\u6B62\uFF1A\u65B0\u589E\u529F\u80FD\u3001\u65B0\u76EE\u6807\u3001\u65B0\u4F9D\u8D56\uFF1B\u865A\u6784\u9879\u76EE\u4E8B\u5B9E\uFF1B\u5199\u7528\u6237\u6CA1\u6388\u6743\u7684\u6280\u672F\u9009\u578B\u3002',\n '\u6570\u91CF\u7EAA\u5F8B\uFF1Arequirement \u6700\u591A 3 \u6761\uFF0Cquality \u6700\u591A 2 \u6761\uFF0Cunknown \u6700\u591A 2 \u6761\u3002',\n ],\n extreme: [\n '\u3010\u672C\u8F6E\u4EFB\u52A1\uFF1A\u628A\u8BC9\u6C42\u56FA\u5316\u6210\u4E00\u6761\u53EF\u76F4\u63A5\u6267\u884C\u7684\u547D\u4EE4\u3011',\n '\u8FD9\u6B21\u662F\u591A\u6B65\u6267\u884C\u7684\u590D\u6742\u4EFB\u52A1\uFF0C\u5DE5\u4F5C AI \u4F1A\u7167\u8FD9\u6761\u547D\u4EE4\u5E72\uFF0C\u7528\u6237\u4E0D\u4F1A\u518D\u8865\u5145\u3002',\n '\u5728\"\u9AD8\u7EA7\"\u6863\u5141\u8BB8\u7684\u5168\u90E8\u6761\u76EE\u7684\u57FA\u7840\u4E0A\uFF0C\u518D\u52A0\u4E24\u7C7B\uFF08\u90FD\u8981\u4EE5\u7528\u6237\u5728\u7ED9\u5DE5\u4F5C AI \u4E0B\u547D\u4EE4\u7684\u53E3\u543B\u5199\uFF09\uFF1A',\n '- `plan`\uFF1A\u5206\u9636\u6BB5\u6267\u884C\u8BA1\u5212\u3002\u6BCF\u9636\u6BB5\u5199\u6E05\u52A8\u4F5C\u4E0E\u4EA7\u51FA\uFF0C\u5E76\u5199\u660E\u7EAA\u5F8B\uFF08\u5148\u9A8C\u8BC1\u518D\u6539\u3001\u5931\u8D25\u5373\u56DE\u9000\u3001',\n ' \u4E0D\u64C5\u81EA\u6269\u5927\u8303\u56F4\u3001\u6539\u5B8C\u7ED9\u51FA\u8BC1\u636E\uFF09\u3002',\n '- `risk`\uFF1A\u591A\u60C5\u51B5\u9884\u6848 2~4 \u6761\uFF0C\u6BCF\u6761\u5199\u6210\"\u5982\u679C\u51FA\u73B0 <\u89E6\u53D1\u4FE1\u53F7>\uFF0C\u5C31\u5148 <\u5E94\u5BF9\u52A8\u4F5C>\uFF0C',\n ' \u4E0D\u8981 <\u7981\u6B62\u52A8\u4F5C>\"\u3002',\n '\u8FD8\u8981\u5224\u65AD\u8FD9\u6B21\u4EFB\u52A1\u662F\u5426\u503C\u5F97\u8BA9\u5DE5\u4F5C AI \u7528 goal / todo / \u8BA1\u5212\u6A21\u5F0F\u8DDF\u8E2A\uFF0C\u5E76\u628A\u7ED3\u8BBA\u5199\u6210',\n '`requirement` \u7684\u4E00\u90E8\u5206\uFF08\u4F8B\u5982\"\u8BF7\u5148\u5EFA\u7ACB goal\uFF1A\u2026\uFF0C\u518D\u6309\u4E0B\u5217\u9636\u6BB5\u63A8\u8FDB\"\uFF09\uFF1B\u4E0D\u9700\u8981\u5C31\u5B8C\u5168\u4E0D\u63D0\u3002',\n '\u94C1\u5F8B\uFF1A\u4E0D\u5F97\u865A\u6784\u9879\u76EE\u4E8B\u5B9E\u3002\u9700\u8981\u9879\u76EE\u4E8B\u5B9E\u65F6\u5199\u6210\"\u5148\u8BFB\u53D6/\u786E\u8BA4 X\"\u7684\u67E5\u8BC1\u52A8\u4F5C\u3002',\n '\u6570\u91CF\u7EAA\u5F8B\uFF1Aplan \u6700\u591A 1 \u6761\uFF0Crisk \u6700\u591A 4 \u6761\uFF0Crequirement \u6700\u591A 3 \u6761\u3002',\n ],\n}\n\n/** \u6863\u4F4D id \u4E0E\u7CFB\u7EDF\u63D0\u793A / \u6E29\u5EA6\u7684\u5BF9\u5E94\u8868\u3002 */\nexport const OPTIMIZER_SPECS = {\n basic: {\n temperature: 0.2,\n system: [RELAY_ROLE, TIER_TASKS.basic!.join('\\n'), EVIDENCE_RULES, STYLE_RULES].join('\\n\\n'),\n },\n advanced: {\n temperature: 0.3,\n system: [RELAY_ROLE, TIER_TASKS.advanced!.join('\\n'), EVIDENCE_RULES, STYLE_RULES].join('\\n\\n'),\n },\n extreme: {\n temperature: 0.3,\n system: [RELAY_ROLE, TIER_TASKS.extreme!.join('\\n'), EVIDENCE_RULES, STYLE_RULES].join('\\n\\n'),\n },\n} as const\n\n/** \u6863\u4F4D id \u8054\u5408\uFF08\u4E0E settings-contract \u7684 OptimizerTier \u4E00\u81F4\uFF0C\u6B64\u5904\u4E0D import \u4EE5\u514D\u5FAA\u73AF\uFF09\u3002 */\nexport type OptimizerSpecTier = keyof typeof OPTIMIZER_SPECS\n\n/** \u672A\u77E5\u6863\u4F4D\u56DE\u843D\u5230\u9ED8\u8BA4\u6863\uFF08\u4E0E `DEFAULT_OPTIMIZER_TIER` \u540C\u503C\uFF1B\u6B64\u5904\u4E0D import \u4EE5\u514D\u5FAA\u73AF\uFF09\u3002 */\nconst FALLBACK_TIER = 'advanced'\n\n/** \u53D6\u4E00\u4E2A\u6863\u4F4D\u7684\u8BF4\u660E\uFF08\u672A\u77E5\u6863\u8D70\u9ED8\u8BA4\u6863\uFF09\u3002 */\nfunction specOf(tier: string): { temperature: number; system: string } {\n return OPTIMIZER_SPECS[tier as OptimizerSpecTier] ?? OPTIMIZER_SPECS[FALLBACK_TIER as OptimizerSpecTier]\n}\n\n/**\n * \u7EC4\u88C5\u4E00\u6B21\u4F18\u5316\u7684 system \u63D0\u793A\u8BCD\u3002\n *\n * \u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\uFF08\u8BBE\u7F6E\u9875\u53EF\u7F16\u8F91\uFF09**\u6574\u4F53\u66FF\u6362**\u4EFB\u52A1\u6BB5\uFF0C\u4F46\u8F93\u51FA\u5951\u7EA6\u6C38\u8FDC\u8FFD\u52A0\u5728\u672B\u5C3E \u2014\u2014\n * \u5951\u7EA6\u662F\u5BBF\u4E3B\u89E3\u6790\u7684\u4F9D\u636E\uFF0C\u88AB\u6539\u6389\u6574\u5957\u673A\u5236\u5C31\u5931\u6548\uFF08\u8BBE\u7F6E\u9875\u5BF9\u6B64\u6709\u8BF4\u660E\uFF09\u3002\n * @param tier - \u5F3A\u5EA6\u6863\u4F4D\uFF1B\u672A\u77E5\u503C\u8D70 advanced\uFF08\u9ED8\u8BA4\u6863\uFF09\u3002\n * @param custom - \u8BBE\u7F6E\u9875\u91CC\u7684\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\uFF1B\u7A7A\u4E32 = \u7528\u5185\u7F6E\u90A3\u4EFD\u3002\n * @returns \u8BE5\u6863\u4F4D\u7684\u5B8C\u6574\u7CFB\u7EDF\u63D0\u793A\u8BCD\u3002\n */\nexport function buildOptimizeSystem(tier: string, custom = ''): string {\n const body = custom.trim() === '' ? specOf(tier).system : custom.trim()\n return `${body}\\n\\n${OPTIMIZER_OUTPUT_CONTRACT}`\n}\n\n/**\n * \u7EC4\u88C5\u4E00\u6B21\u4F18\u5316\u7684 temperature\u3002\n * @param tier - \u5F3A\u5EA6\u6863\u4F4D\uFF1B\u672A\u77E5\u503C\u8D70 advanced\u3002\n * @returns \u8BE5\u6863\u4F4D\u7684\u91C7\u6837\u6E29\u5EA6\u3002\n */\nexport function buildOptimizeTemperature(tier: string): number {\n return specOf(tier).temperature\n}\n\n/**\n * \u8FD9\u6B21\u7528\u7684\u662F\u81EA\u5B9A\u4E49\u8FD8\u662F\u5185\u7F6E\u63D0\u793A\u8BCD\uFF08\u56DE\u4F20\u7ED9\u9762\u677F\uFF0C\u65B9\u4FBF\u7528\u6237\u786E\u8BA4\u81EA\u5DF1\u90A3\u4EFD\u771F\u7684\u751F\u6548\u4E86\uFF09\u3002\n * @param custom - \u8BBE\u7F6E\u9875\u91CC\u7684\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u3002\n * @returns 'custom' = \u7528\u4E86\u7528\u6237\u90A3\u4EFD\uFF1B'builtin' = \u7528\u4E86\u5185\u7F6E\u90A3\u4EFD\u3002\n */\nexport function optimizePromptSource(custom: string): 'custom' | 'builtin' {\n return String(custom ?? '').trim() === '' ? 'builtin' : 'custom'\n}\n\n/**\n * \u4F20\u8BDD\u6846\u67B6\uFF1A\u628A\u7528\u6237\u539F\u8BDD\u5305\u6210\u300C\u5F85\u8F6C\u8FBE\u5185\u5BB9\u300D\u800C\u4E0D\u662F\u300C\u5BF9\u4F60\u8BF4\u7684\u8BDD\u300D\u3002\n *\n * \u8FD9\u662F\u539F\u4F5C\u8005\u4FEE\u300C\u4F18\u5316 AI \u4EE5\u4E3A\u81EA\u5DF1\u5728\u548C\u7528\u6237\u5BF9\u8BDD\u300D\u7684\u5173\u952E\u4E00\u62DB \u2014\u2014 \u88F8\u6587\u672C\u4F1A\u88AB\u5F53\u6210\n * \u5BF9\u8BDD\u8F93\u5165\uFF0C\u4E8E\u662F\u6A21\u578B\u5F00\u59CB\u56DE\u5E94\u4F60\u800C\u4E0D\u662F\u66FF\u4F60\u8F6C\u8FBE\u3002\n * @param original - \u8F93\u5165\u6846\u91CC\u7684\u539F\u8BDD\u3002\n * @param options - `retry`\uFF1A\u4E0A\u4E00\u6B21\u4EA7\u51FA\u4E3A\u7A7A\uFF0C\u6309\u5BF9\u65B9 0.6 \u7684 `retryEmpty` \u518D\u70B9\u4E00\u904D\u89C4\u5219\n * \uFF08\u5BF9\u65B9\u7684\u771F\u673A\u6559\u8BAD\uFF1A\u77ED\u6D88\u606F/\u8001\u4F1A\u8BDD\u4F1A\u53CD\u590D\"\u601D\u8003\u5B8C\u6210\u5374\u6CA1\u6709\u4EA7\u51FA\"\uFF09\u3002\n * @returns \u76F4\u63A5\u4F5C\u4E3A user \u6D88\u606F\u53D1\u9001\u7684\u6587\u672C\u3002\n */\nexport function buildOptimizeUser(\n original: string,\n options: { readonly retry?: boolean; readonly reason?: string } = {},\n): string {\n const parts = [\n '\u3010\u5F85\u8F6C\u8FBE\u5185\u5BB9\u3011\u4E0B\u9762\u662F\"\u7528\u6237\"\u53D1\u7ED9\u6211\u7684\u539F\u8BDD\u3002**\u5B83\u4E0D\u662F\u8BF4\u7ED9\u4F60\u542C\u7684**\uFF0C\u4F60\u4E0D\u9700\u8981\u56DE\u5E94\u5B83\u3001\u4E5F\u4E0D\u9700\u8981\u66FF\u7528\u6237\u53BB\u505A\u8FD9\u4EF6\u4E8B\u3002',\n '<\u539F\u6587>',\n String(original ?? ''),\n '</\u539F\u6587>',\n '',\n '\u3010\u4F60\u7684\u4EFB\u52A1\u3011\u6309\u7CFB\u7EDF\u63D0\u793A\u8BCD\u7684\u89C4\u5219\uFF0C\u628A\u4E0A\u9762\u7684\u539F\u8BDD\u62C6\u6210**\u6761\u76EE**\u5E76\u7ED9\u6BCF\u6761\u9644\u4E0A**\u9010\u5B57\u5F15\u6587**\u3002',\n '- \u53EA\u8F93\u51FA\u90A3\u4EFD JSON \u5951\u7EA6\u8981\u6C42\u7684\u4E1C\u897F\uFF1B\u4E0D\u8981\u56DE\u5E94\u6211\u3001\u4E0D\u8981\u56DE\u7B54\u95EE\u9898\u3001\u4E0D\u8981\u8C22\u5E55\u3001\u4E0D\u8981\u89E3\u91CA\u4F60\u505A\u4E86\u4EC0\u4E48\u3002',\n '- \u8BFB\u8005\u53EA\u6709\"\u5DE5\u4F5C AI\"\u4E00\u4E2A\uFF0C\u800C\u4F60\u7684\u4EA7\u51FA\u4F1A\u5148\u7ECF\u5BBF\u4E3B\u9010\u6761\u6838\u5BF9\u5F15\u6587\u3002',\n ]\n if (options.retry === true) {\n parts.push(\n '',\n `\u3010\u91CD\u8981\uFF1A\u4F60\u4E0A\u4E00\u6B21\u7684\u8F93\u51FA\u662F\u7A7A\u7684${options.reason ? `\uFF08${options.reason}\uFF09` : ''}\u3011`,\n '\u4E0A\u4E00\u6B21\u4F60\u6CA1\u6709\u7ED9\u51FA\u4EFB\u4F55\u6761\u76EE\uFF0C\u8FD9\u4E00\u8F6E\u56E0\u6B64**\u6CA1\u6709\u4EFB\u4F55\u8865\u5168**\u53EF\u4EE5\u4EA4\u7ED9\u5DE5\u4F5C AI\u3002',\n '\u8BF7\u6309\u7CFB\u7EDF\u63D0\u793A\u8BCD\u7684\u786C\u89C4\u5219\u91CD\u505A\uFF1A**\u54EA\u6015\u7528\u6237\u53EA\u5199\u4E86\u4E00\u4E24\u4E2A\u5B57\uFF0C\u4E5F\u8981\u5C3D\u91CF\u628A\u5B83\u62C6\u6210\u53EF\u5F15\u7528\u7684\u6761\u76EE**',\n '\uFF08\u81F3\u5C11\u4E00\u6761 `rewrite`\uFF0C\u6216\u4E00\u6761 `quality` / `unknown`\uFF09\uFF1B\u786E\u5B9E\u6CA1\u6709\u53EF\u8865\u7684\u5185\u5BB9\u65F6\u624D\u8F93\u51FA {\"items\":[]}\u3002',\n '\u53EA\u8F93\u51FA JSON\u3002',\n )\n }\n return parts.join('\\n')\n}\n", "/**\n * \u8BBE\u7F6E\u9875\u91CC\u7684\u300C\u672C\u6863\u63D0\u793A\u8BCD\u300D\u7F16\u8F91\u5668\uFF080.6.0 \u8D77\uFF09\u3002\n *\n * \u4E3A\u4EC0\u4E48\u9700\u8981\u5B83\uFF1A0.6.0 \u628A\u63D0\u793A\u8BCD\u4F18\u5316\u6539\u6210\u4E86\u300C\u6A21\u578B\u53EA\u4EA7\u6761\u76EE\u3001\u5BBF\u4E3B\u6309\u9010\u5B57\u4F9D\u636E\u6838\u5BF9\u540E\u88C5\u914D\u300D\n * \uFF08\u505A\u6CD5\u53D6\u81EA WestFox-AwA/dsh-prompt-optimizer \u7684 0.6 \u7EBF\uFF09\u3002\u6A21\u578B\u884C\u4E3A\u4E0D\u5408\u53E3\u5473\u65F6\uFF0C\n * \u7528\u6237\u552F\u4E00\u80FD\u8C03\u7684\u5C31\u662F\u90A3\u4EFD\u4EFB\u52A1\u63D0\u793A\u8BCD \u2014\u2014 \u6240\u4EE5\u5FC5\u987B\u53EF\u7F16\u8F91\u3001\u53EF\u6062\u590D\u3001\u4E14\u80FD\u770B\u89C1\u5185\u7F6E\u90A3\u4EFD\u957F\u4EC0\u4E48\u6837\u3002\n *\n * \u4E24\u6761\u523B\u610F\u7684\u8BBE\u8BA1\uFF1A\n * \u00B7 **\u7559\u7A7A = \u7528\u5185\u7F6E**\uFF1A\u7A7A\u4E32\u65E2\u662F\"\u6CA1\u81EA\u5B9A\u4E49\"\u7684\u8868\u793A\uFF0C\u4E5F\u662F\u300C\u6062\u590D\u5185\u7F6E\u300D\u8981\u5199\u56DE\u7684\u503C\uFF0C\n * \u4E0D\u5FC5\u518D\u591A\u4E00\u4E2A\"\u662F\u5426\u81EA\u5B9A\u4E49\"\u7684\u5F00\u5173\uFF08\u591A\u4E00\u4E2A\u5F00\u5173\u5C31\u591A\u4E00\u79CD\u81EA\u76F8\u77DB\u76FE\u7684\u72B6\u6001\uFF09\u3002\n * \u00B7 **JSON \u8F93\u51FA\u5951\u7EA6\u4E0D\u7ED9\u6539**\uFF1A\u5BBF\u4E3B\u6309\u5B83\u89E3\u6790\u6761\u76EE\u3001\u505A\u9010\u5B57\u4F9D\u636E\u6BD4\u5BF9\uFF1B\u5951\u7EA6\u88AB\u6539\u6389\uFF0C\n * \"\u4E0D\u8BB8\u51ED\u7A7A\u65B0\u589E\u9700\u6C42\"\u5C31\u9000\u5316\u6210\u4E00\u53E5\u7A7A\u8BDD\u3002\u6240\u4EE5\u8FD9\u91CC\u660E\u8BF4\uFF0C\u5E76\u628A\u5951\u7EA6\u7559\u5728\u63D2\u4EF6\u91CC\u8FFD\u52A0\u3002\n */\nimport {\n OPTIMIZER_PROMPT_MAX, OPTIMIZER_TIERS,\n type OptimizerTier,\n} from '../settings-contract.ts'\nimport { OPTIMIZER_SPECS, OPTIMIZER_OUTPUT_CONTRACT } from '../optimizer-prompt.ts'\nimport { pill, row, rowDesc, rowText, rowTitle, textInput } from './styles.ts'\n\n/** \u7EC4\u4EF6\u5165\u53C2\u3002 */\nexport interface OptimizerPromptEditorProps {\n /** \u5F53\u524D\u6863\u4F4D\uFF08\u51B3\u5B9A\u7F16\u8F91\u54EA\u4E00\u4EFD\u3001\u4EE5\u53CA\"\u8F7D\u5165\u5185\u7F6E\u7248\"\u8F7D\u5165\u54EA\u4E00\u4EFD\uFF09\u3002 */\n readonly tier: OptimizerTier\n /** \u8BE5\u6863\u4F4D\u5F53\u524D\u7684\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\uFF08'' = \u7528\u5185\u7F6E\uFF09\u3002 */\n readonly value: string\n /** \u5199\u56DE\u8BE5\u6863\u4F4D\u7684\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u3002 */\n readonly onChange: (next: string) => void\n}\n\n/** \u5185\u7F6E\u7684\u4EFB\u52A1\u63D0\u793A\u8BCD\u6B63\u6587\uFF08**\u4E0D\u542B**\u8F93\u51FA\u5951\u7EA6\u2014\u2014\u5951\u7EA6\u7531\u5BBF\u4E3B\u8FFD\u52A0\uFF0C\u89C1\u6587\u4EF6\u5934\u6CE8\u91CA\uFF09\u3002 */\nexport function builtinTaskPrompt(tier: string): string {\n return OPTIMIZER_SPECS[tier as OptimizerTier]?.system ?? OPTIMIZER_SPECS.advanced.system\n}\n\n/**\n * \u5F53\u524D\u6863\u4F4D\u7684\u63D0\u793A\u8BCD\u7F16\u8F91\u5757\u3002\n * @param props - \u6863\u4F4D\u3001\u5F53\u524D\u503C\u3001\u5199\u56DE\u56DE\u8C03\u3002\n */\nexport function OptimizerPromptEditor({ tier, value, onChange }: OptimizerPromptEditorProps) {\n const label = OPTIMIZER_TIERS.find(item => item.id === tier)?.label ?? tier\n const custom = value.trim() !== ''\n return (\n <div style={{ ...row, borderTop: 'none', flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>\n {`\u672C\u6863\u63D0\u793A\u8BCD\uFF08${label}\uFF09`}\n <span style={{ marginLeft: 8, opacity: 0.75 }}>{custom ? '\u81EA\u5B9A\u4E49' : '\u5185\u7F6E'}</span>\n </div>\n <div style={rowDesc}>\n \u7559\u7A7A = \u7528\u63D2\u4EF6\u5185\u7F6E\u90A3\u4EFD\u3002\u6539\u7684\u662F\u300C\u4EFB\u52A1\u4E0E\u98CE\u683C\u300D\u8FD9\u6BB5\uFF1B\n {' '}<strong>JSON \u8F93\u51FA\u5951\u7EA6</strong>\u7531\u63D2\u4EF6\u5728\u672B\u5C3E\u8FFD\u52A0\u3001\u4E0D\u5728\u8FD9\u91CC\u6539 \u2014\u2014\n \u5BBF\u4E3B\u9760\u5B83\u9010\u6761\u6838\u5BF9\u300C\u6BCF\u6761\u8865\u5168\u90FD\u6307\u56DE\u4F60\u539F\u8BDD\u91CC\u7684\u67D0\u53E5\u300D\uFF0C\u5951\u7EA6\u88AB\u6539\u6389\u8FD9\u5957\u6821\u9A8C\u5C31\u6CA1\u4E86\u3002\n </div>\n </div>\n <textarea\n value={value}\n placeholder={'\u7559\u7A7A = \u7528\u5185\u7F6E\u63D0\u793A\u8BCD\u3002\u70B9\u4E0B\u9762\u7684\u300C\u8F7D\u5165\u5185\u7F6E\u7248\u300D\u53EF\u4EE5\u5148\u628A\u5185\u7F6E\u90A3\u4EFD\u6284\u8FDB\u6765\u518D\u6539\u3002'}\n maxLength={OPTIMIZER_PROMPT_MAX}\n spellCheck={false}\n rows={value.trim() === '' ? 3 : Math.min(16, Math.max(6, Math.ceil(value.length / 60)))}\n onChange={event => { onChange(event.target.value) }}\n style={{ ...textInput, resize: 'vertical', fontFamily: 'inherit', lineHeight: 1.5 }}\n />\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>\n <button\n type=\"button\"\n style={pill}\n title=\"\u628A\u5185\u7F6E\u90A3\u4EFD\u4EFB\u52A1\u63D0\u793A\u8BCD\u6284\u8FDB\u8F93\u5165\u6846\uFF0C\u65B9\u4FBF\u5728\u6B64\u57FA\u7840\u4E0A\u6539\"\n onClick={() => { onChange(builtinTaskPrompt(tier)) }}\n >\n \u8F7D\u5165\u5185\u7F6E\u7248\n </button>\n <button\n type=\"button\"\n style={pill}\n disabled={!custom}\n title=\"\u6E05\u7A7A\u81EA\u5B9A\u4E49\uFF0C\u6539\u7528\u5185\u7F6E\u63D0\u793A\u8BCD\"\n onClick={() => { onChange('') }}\n >\n \u6062\u590D\u5185\u7F6E\n </button>\n <span style={{ ...rowDesc, flex: '1 1 auto' }}>\n {`\u5F53\u524D\u5B57\u6570 ${String(value.length)} / ${String(OPTIMIZER_PROMPT_MAX)}`}\n </span>\n </div>\n <details>\n <summary style={{ ...rowDesc, cursor: 'pointer' }}>\u770B\u63D2\u4EF6\u56FA\u5B9A\u8FFD\u52A0\u7684\u90A3\u6BB5\u8F93\u51FA\u5951\u7EA6</summary>\n <pre style={{ ...rowDesc, whiteSpace: 'pre-wrap', margin: '6px 0 0' }}>{OPTIMIZER_OUTPUT_CONTRACT}</pre>\n </details>\n </div>\n )\n}\n", "/**\n * \u901A\u7528\u300CN \u9009\u4E00\u300D\u80F6\u56CA\u63A7\u4EF6\uFF1A\u4E00\u884C\u4E92\u65A5\u5C0F\u80F6\u56CA\uFF0C\u9009\u4E2D\u6001\u53EA\u6539\u8FB9\u6846\u4E0E\u6587\u5B57\u8272\u3002\n *\n * \u4E3A\u4EC0\u4E48\u62BD\u51FA\u6765\u5171\u7528\uFF1A\u63D2\u5165\u6A21\u5F0F\uFF08\u5173 / \u6BCF\u6B21 / \u4EC5\u9996\u6B21\uFF09\u4E0E\u53F3\u952E\u83DC\u5355\u6A21\u5F0F\uFF08\u5B98\u65B9 / \u6D4F\u89C8\u5668 / \u81EA\u5B9A\u4E49\uFF09\n * \u662F\u540C\u4E00\u79CD\u4EA4\u4E92\u2014\u2014\u4E00\u7EC4\u4E92\u65A5\u9009\u9879\u3001\u5F53\u524D\u9879\u9AD8\u4EAE\u3001\u6BCF\u9879\u7528\u60AC\u505C\u63D0\u793A\u8BF4\u6E05\u5B83\u505A\u4EC0\u4E48\u3002\u8BA9\u4E24\u5904\u6E32\u67D3\u540C\u4E00\u4E2A\n * \u7EC4\u4EF6\uFF0C\u6837\u5F0F\u4E0E\u65E0\u969C\u788D\u884C\u4E3A\u5C31\u4E0D\u4F1A\u5404\u5199\u4E00\u904D\u7136\u540E\u6162\u6162\u5206\u53C9\u3002\n *\n * \u9009\u4E2D\u6001\u4E3A\u4EC0\u4E48\u4E0D\u7528\u5B9E\u8272\u586B\u5145\uFF1A\u5B9E\u8272\u8981\u914D\u300C\u586B\u5145 + \u524D\u666F\u300D\u4E24\u4E2A\u4EE4\u724C\uFF0C0.2.0 \u5C31\u56E0\u4E3A\u53EA\u5199\u4E86\u4E00\u534A\u800C\u5728\n * \u6DF1\u8272\u4E3B\u9898\u4E0B\u53D8\u6210\u767D\u5E95\u767D\u5B57\u3002\u53EA\u6539\u8FB9\u6846\u548C\u6587\u5B57\u8272\u5C31\u4E0D\u5FC5\u914D\u5BF9\uFF0C\u4E5F\u5C31\u4E0D\u4F1A\u91CD\u6F14\u3002\n */\nimport React from 'react'\nimport type { CSSProperties } from 'react'\n\n/** \u4E00\u4E2A\u9009\u9879\u3002 */\nexport interface PillChoiceItem<T extends string> {\n readonly id: T\n readonly label: string\n /** \u60AC\u505C\u63D0\u793A\uFF1A\u8FD9\u4E00\u6863\u5230\u5E95\u505A\u4EC0\u4E48\u3002 */\n readonly hint: string\n}\n\n/** \u7EC4\u4EF6\u6CE8\u5165\u9762\u3002 */\nexport interface PillChoiceProps<T extends string> {\n /** \u9009\u9879\uFF08\u6570\u7EC4\u987A\u5E8F\u5373\u754C\u9762\u987A\u5E8F\uFF09\u3002 */\n readonly items: readonly PillChoiceItem<T>[]\n /** \u5F53\u524D\u9009\u4E2D\u7684\u90A3\u4E2A\u3002 */\n readonly value: T\n /** \u7528\u6237\u9009\u4E86\u53E6\u4E00\u4E2A\u3002 */\n readonly onChange: (value: T) => void\n /** \u65E0\u969C\u788D\u7EC4\u540D\uFF08\u540C\u4E00\u5C4F\u53EF\u80FD\u6709\u591A\u4E2A\u8FD9\u6837\u7684\u63A7\u4EF6\uFF0C\u8981\u80FD\u5206\u8FA8\uFF09\u3002 */\n readonly ariaLabel: string\n /** \u9762\u677F\u91CC\u66F4\u7D27\u51D1\uFF08\u7A7A\u95F4\u7D27\u5F20\uFF09\u3002 */\n readonly compact?: boolean\n}\n\nconst base: CSSProperties = {\n border: '0.5px solid var(--dsw-alias-border-l2)',\n background: 'transparent',\n color: 'var(--dsw-alias-label-tertiary)',\n borderRadius: 999,\n cursor: 'pointer',\n lineHeight: 1,\n whiteSpace: 'nowrap',\n}\n\n/** \u9009\u4E2D\u6001\u53EA\u6539\u8FB9\u6846\u4E0E\u6587\u5B57\u8272\uFF0C\u4E0D\u7528\u5B9E\u8272\u586B\u5145\uFF08\u89C1\u6587\u4EF6\u5934\u8BF4\u660E\uFF09\u3002 */\nconst active: CSSProperties = {\n ...base,\n border: '0.5px solid var(--dsw-alias-brand-primary)',\n color: 'var(--dsw-alias-label-primary)',\n fontWeight: 600,\n}\n\n/** \u6E32\u67D3\u4E00\u7EC4\u4E92\u65A5\u80F6\u56CA\u3002 */\nexport function PillChoice<T extends string>({\n items, value, onChange, ariaLabel, compact = false,\n}: PillChoiceProps<T>) {\n return (\n <div\n role=\"group\"\n aria-label={ariaLabel}\n style={{ display: 'inline-flex', alignItems: 'center', gap: 2, flex: '0 0 auto' }}\n >\n {items.map(item => (\n <button\n key={item.id}\n type=\"button\"\n title={item.hint}\n aria-pressed={value === item.id}\n style={{\n ...(value === item.id ? active : base),\n fontSize: compact ? 10 : 11,\n padding: compact ? '3px 5px' : '4px 7px',\n }}\n // \u4E0D\u8BA9\u6309\u94AE\u62A2\u8D70\u8F93\u5165\u6846\u91CC\u53EF\u80FD\u5B58\u5728\u7684\u9009\u533A\uFF08\u4E0E\u5DE5\u5177\u884C\u5176\u5B83\u6309\u94AE\u4E00\u81F4\uFF09\u3002\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { onChange(item.id) }}\n >\n {item.label}\n </button>\n ))}\n </div>\n )\n}\n", "/**\n * \u63D2\u5165\u6A21\u5F0F\u7684\u4E09\u9009\u4E00\u63A7\u4EF6\uFF08\u5173 / \u6BCF\u6B21 / \u4EC5\u9996\u6B21\uFF09\uFF1A\u9762\u677F\u4E0E\u8BBE\u7F6E\u9875\u5171\u7528\u3002\n *\n * \u4E3A\u4EC0\u4E48\u662F**\u4E00\u4E2A**\u63A7\u4EF6\u800C\u4E0D\u662F\u4E24\u4E2A\u52FE\u9009\u6846\uFF1A\u300C\u6BCF\u6B21\u300D\u4E0E\u300C\u4EC5\u9996\u6B21\u300D\u4E92\u76F8\u6392\u65A5\uFF0C\u4E24\u4E2A\u72EC\u7ACB\u52FE\u9009\u6846\n * \u5C31\u80FD\u9020\u51FA\u300C\u540C\u65F6\u53C8\u6BCF\u6B21\u53C8\u4EC5\u9996\u6B21\u300D\u7684\u77DB\u76FE\u72B6\u6001\u3002\u8FD9\u91CC\u53EA\u53D1\u51FA\u4E00\u4E2A mode\uFF0C\u7531\n * `withInsertMode` \u4E00\u6B21\u628A\u4E24\u4E2A\u6807\u5FD7\u5199\u5BF9\u3002\n *\n * \u6E32\u67D3\u4EA4\u7ED9\u901A\u7528\u7684 `PillChoice`\uFF08\u53F3\u952E\u83DC\u5355\u6A21\u5F0F\u4E5F\u7528\u540C\u4E00\u4E2A\uFF0C\u89C1\u8BE5\u6587\u4EF6\uFF09\u3002\n */\nimport React from 'react'\nimport { INSERT_MODES, type InsertMode } from '../settings-contract.ts'\nimport { PillChoice } from './PillChoice.tsx'\n\n/** \u7EC4\u4EF6\u6CE8\u5165\u9762\u3002 */\nexport interface InsertModeControlProps {\n /** \u5F53\u524D\u6A21\u5F0F\u3002 */\n readonly mode: InsertMode\n /** \u7528\u6237\u9009\u4E86\u53E6\u4E00\u4E2A\u6A21\u5F0F\u3002 */\n readonly onChange: (mode: InsertMode) => void\n /** \u9762\u677F\u91CC\u66F4\u7D27\u51D1\uFF08\u7A7A\u95F4\u7D27\u5F20\uFF09\u3002 */\n readonly compact?: boolean\n /** \u65E0\u969C\u788D\u6807\u7B7E\uFF1A\u5217\u8868\u91CC\u533A\u5206\u662F\u54EA\u4E00\u6761\uFF08\u540C\u4E00\u5C4F\u4F1A\u6709\u5F88\u591A\u4E2A\uFF09\u3002 */\n readonly label?: string\n}\n\n/** \u300C\u5173 / \u6BCF\u6B21 / \u4EC5\u9996\u6B21\u300D\u3002 */\nexport function InsertModeControl({ mode, onChange, compact = false, label }: InsertModeControlProps) {\n return (\n <PillChoice\n items={INSERT_MODES}\n value={mode}\n onChange={onChange}\n compact={compact}\n ariaLabel={label === undefined ? '\u53D1\u9001\u65F6\u63D2\u5165' : `\u53D1\u9001\u65F6\u63D2\u5165\uFF08${label}\uFF09`}\n />\n )\n}\n", "/**\n * \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u6309\u94AE\uFF1A\u5750\u5728\u5B98\u65B9\u8F93\u5165\u5361\u7247\u5DE5\u5177\u884C\u91CC\u300C\u5C55\u5F00\u300D\u6309\u94AE\u7684\u65C1\u8FB9\n * \uFF08\u69FD\u4F4D `conversation.input.right`\uFF0Corder 89 < \u5C55\u5F00\u7684 90\uFF09\uFF0C\u5F62\u72B6\u4E0E\u5B83\u540C\u6B3E\u80F6\u56CA\u3002\n *\n * \u672C\u7EC4\u4EF6\u53EA\u505A\u4E09\u4EF6\u4E8B\uFF1A\n * 1. \u628A\u5B98\u65B9\u7684 `inputActions` \u4E0E\u5F53\u524D\u8349\u7A3F\u6295\u9012\u7ED9 quick-commands \u6865\u63A5\n * \uFF08\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u7684\u53D1\u9001\u62E6\u622A\u5FC5\u987B\u62FF\u5230\u5B83\u4EEC\uFF0C\u62E6\u622A\u5668\u6D3B\u5728 React \u4E4B\u5916\uFF09\uFF1B\n * 2. \u6E32\u67D3\u6309\u94AE\u3001\u70B9\u51FB\u540E\u628A\u81EA\u8EAB\u77E9\u5F62\u4EA4\u7ED9\u9762\u677F\u505A\u951A\u70B9\uFF1B\n * 3. \u628A\u9762\u677F\u7684\u5F00\u5408\u72B6\u6001\u53CD\u5C04\u5230 `aria-expanded`\u3002\n */\nimport React, { useEffect, useRef } from 'react'\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport { activeSections, type ComposerUxSettings } from '../settings-contract.ts'\nimport { publishInputBridge, releaseInputBridge, type InputActionsLike } from './quick-commands.ts'\nimport { QUICK_BUTTON_CLASS } from './quick-style.ts'\n\n/** \u9762\u677F\u951A\u70B9\uFF1A\u6309\u94AE\u7684\u89C6\u53E3\u77E9\u5F62\uFF08\u9762\u677F\u636E\u6B64\u8D34\u5728\u4E0A\u65B9\uFF09\u3002 */\nexport interface QuickPanelAnchor {\n readonly left: number\n readonly bottom: number\n readonly width: number\n}\n\n/** \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u6CE8\u5165\u9762\u3002 */\nexport interface QuickCommandsInjected {\n hooks: {\n /** \u5F53\u524D\u8BBE\u7F6E\uFF08\u603B\u5F00\u5173\u4E0E\u5FEB\u6377\u6307\u4EE4\u5217\u8868\uFF09\u3002 */\n live: SnapshotStore<ComposerUxSettings>\n /** \u9762\u677F\u951A\u70B9\uFF1Bnull = \u9762\u677F\u5173\u95ED\u3002 */\n panel: SnapshotStore<QuickPanelAnchor | null>\n }\n actions: {\n /** \u4EE5\u7ED9\u5B9A\u951A\u70B9\u6253\u5F00\u9762\u677F\uFF1B\u5DF2\u5F00\u5219\u5173\u95ED\uFF08\u70B9\u6309\u94AE\u5373\u5F00\u5408\uFF09\u3002 */\n toggle: (anchor: QuickPanelAnchor) => void\n }\n}\n\nexport type QuickCommandsButtonProps =\n PropsRuntime<'conversation.input.right'>\n & InjectFace<QuickCommandsInjected>\n\n/** \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u5165\u53E3\u6309\u94AE\u3002 */\nexport function QuickCommandsButton({\n useInput, inputActions, sessionId, useSession, useLive, usePanel, actions,\n}: QuickCommandsButtonProps) {\n const settings = useLive(item => item)\n const anchor = usePanel(item => item)\n const draft = useInput(state => state.draft)\n /**\n * \u4F1A\u8BDD\u662F\u4E0D\u662F\u8FD8\u6CA1\u6709\u4EFB\u4F55\u6D88\u606F \u2014\u2014 \u300C\u4EC5\u9996\u6B21\u63D2\u5165\u300D\u7684\u5224\u636E\u3002\n *\n * `useSession` \u662F `conversation.input.right`\uFF08scope: session\uFF09\u7684\u6807\u51C6 props\uFF0C\u4E0E\u672C\u7EC4\u4EF6\n * \u5DF2\u7ECF\u5728\u7528\u7684 `useInput` \u6765\u81EA\u540C\u4E00\u4EFD\u5951\u7EA6\uFF0C\u6240\u4EE5\u65E0\u6761\u4EF6\u8C03\u7528\u5B83\uFF1B\u9009\u62E9\u5668\u91CC\u518D\u6321\u4E00\u5C42 undefined\n * \uFF08\u9009\u62E9\u5668\u629B\u9519\u4F1A\u76F4\u63A5\u628A React \u6E32\u67D3\u6253\u65AD\uFF0C\u8FD9\u91CC\u4E0D\u503C\u5F97\u5192\u9669\uFF09\u3002\n */\n const blank = useSession(state => state?.blank === true)\n const ref = useRef<HTMLButtonElement | null>(null)\n\n // \u6BCF\u6B21\u6E32\u67D3\u628A\u5B98\u65B9\u8F93\u5165\u52A8\u4F5C\u3001\u8349\u7A3F\u4E0E\u300C\u4F1A\u8BDD\u8FD8\u662F\u7A7A\u7684\u300D\u6295\u9012\u7ED9\u6865\u63A5\uFF1A\n // \u62E6\u622A\u5668\u8981\u5728 React \u4E4B\u5916\u8BFB\u5B83\u4EEC\uFF0C\u800C\u8FD9\u4E9B\u53EA\u6709\u69FD\u4F4D\u80FD\u62FF\u5230\u3002\n useEffect(() => {\n const sid = typeof sessionId === 'string' ? sessionId : ''\n publishInputBridge({\n actions: (inputActions ?? null) as InputActionsLike | null,\n draft: typeof draft === 'string' ? draft : '',\n sessionId: sid,\n blank: blank === true,\n })\n return () => { releaseInputBridge(sid) }\n }, [inputActions, draft, sessionId, blank])\n\n // \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u680F\uFF08\u6216\u603B\u5F00\u5173\uFF09\u5173\u7740\u65F6\u8FD9\u679A\u6309\u94AE\u6574\u4E2A\u4E0D\u51FA\u73B0\u3002\n if (!activeSections(settings).quick) return null\n\n const open = anchor !== null\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={QUICK_BUTTON_CLASS}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n title=\"\u5FEB\u6377\u6307\u4EE4\uFF1A\u4E00\u952E\u63D2\u5165\u5E38\u7528\u63D0\u793A\u8BCD\uFF0C\u6216\u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u4F18\u5316\u6210\u4E00\u6761\u6E05\u6670\u7684\u6307\u4EE4\"\n // \u6837\u5F0F\u5168\u90E8\u6765\u81EA\u6CE8\u5165\u7684\u6837\u5F0F\u8868\uFF08\u89C1 quick-style.ts\uFF09\uFF1A\u4E0E\u65C1\u8FB9\u5B98\u65B9\u300C\u5C55\u5F00\u300D\u6309\u94AE\n // \u9010\u9879\u5BF9\u9F50\uFF0C\u4E14 hover / \u5C55\u5F00\u6001\u53EA\u6709\u6837\u5F0F\u8868\u80FD\u8868\u8FBE\u3002\n // \u4E0D\u8BA9\u6309\u94AE\u62A2\u8D70\u62D6\u52A8\u65F6\u53EF\u80FD\u5B58\u5728\u7684\u8F93\u5165\u6846\u9009\u533A\uFF08\u4E0E\u5B98\u65B9\u5DE5\u5177\u884C\u4E00\u81F4\uFF09\u3002\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => {\n const rect = ref.current?.getBoundingClientRect()\n actions.toggle({\n left: rect?.left ?? 0,\n bottom: rect?.bottom ?? 0,\n width: rect?.width ?? 0,\n })\n }}\n >\n <svg\n viewBox=\"0 0 16 16\"\n width=\"12\"\n height=\"12\"\n aria-hidden\n >\n <path\n d=\"M9.2 1.2 3.4 9.1h3.5l-0.9 5.7 6-8.1H8.4l0.8-5.5Z\"\n fill=\"currentColor\"\n />\n </svg>\n <span>\u5FEB\u6377\u6307\u4EE4</span>\n </button>\n )\n}\n", "/**\n * \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u5C55\u5F00\u9762\u677F\uFF1A\u6CE8\u518C\u8FDB shell.overlay\uFF08root \u7EA7\u6D6E\u5C42\uFF0C\u4E0D\u53D7\u8F93\u5165\u5361\u7247\u88C1\u526A\uFF09\u3002\n *\n * \u9762\u677F\u5F62\u6001\uFF080.3.0 \u8D77\u662F**\u5206\u7C7B\u4E24\u7EA7**\u7ED3\u6784\uFF09\uFF1A\n * - \u9876\u90E8\uFF1A\u300C\u2728 \u4F18\u5316\u63D0\u793A\u8BCD\u300D\u4E3B\u6309\u94AE + \u4E09\u6863\u5F3A\u5EA6\u5206\u6BB5\u63A7\u4EF6\uFF1B\n * - \u5206\u7C7B\u884C\uFF1A\u4E00\u4E2A\u5206\u7C7B\u4E00\u4E2A\u6807\u7B7E\uFF0C\u70B9\u5B83\u5207\u6362\uFF1B\u300C\uFF0B \u65B0\u5206\u7C7B\u300D\u76F4\u63A5\u52A0\u4E00\u4E2A\uFF08\u6539\u540D/\u5220\u9664\u5728\u8BBE\u7F6E\u9875\uFF0C\n * \u9762\u677F\u4FDD\u6301\u8F7B\u91CF\uFF0C\u907F\u514D\u5728\u8FD9\u91CC\u585E\u4E00\u5957\u91CD\u547D\u540D UI\uFF09\uFF1B\n * - \u4E2D\u90E8\uFF1A\u5F53\u524D\u5206\u7C7B\u7684\u6761\u76EE \u2014\u2014 \u70B9\u6761\u76EE\u628A\u5185\u5BB9\u63D2\u5165\u8F93\u5165\u6846\uFF0C\u53F3\u4FA7\u4E09\u9009\u4E00\u662F\u63D2\u5165\u6A21\u5F0F\n * \uFF08\u5173 / \u6BCF\u6B21 / \u4EC5\u9996\u6B21\uFF09\uFF1B\u5217\u8868\u6700\u4E0B\u8FB9\u90A3\u4E00\u884C\u300C\uFF0B\u300D\u8D1F\u8D23\u65B0\u5EFA\u4E0E\u8DE8\u5206\u7C7B\u79FB\u52A8\u3002\n * \uFF08\u52FE\u4E0A\u540E\u70B9\u53D1\u9001\u65F6\u81EA\u52A8\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E\uFF0C**\u8DE8\u5206\u7C7B\u751F\u6548**\uFF09\uFF1B\n * - \u5E95\u90E8\uFF1A\u72B6\u6001\u63D0\u793A + \u6307\u8DEF\u8BBE\u7F6E\u9875\u3002\n */\nimport React, { useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport {\n DEFAULT_CATEGORY_NAME, OPTIMIZER_TIERS, QUICK_CATEGORY_MAX, insertModeOf,\n type ComposerUxSettings, type InsertMode, type OptimizerTier, type QuickPromptBook,\n} from '../settings-contract.ts'\nimport { bookCounts } from './prompt-book.ts'\nimport { AddPromptRow } from './AddPromptRow.tsx'\nimport { InsertModeControl } from './InsertModeControl.tsx'\nimport type { QuickPanelAnchor } from './QuickCommandsButton.tsx'\nimport {\n quickAlwaysBox, quickAlwaysLabel, quickCategoryAdd, quickCategoryRow, quickCategoryTab,\n quickCategoryTabActive, quickEmpty, quickFootHint, quickItem, quickItemLabel,\n quickItemPreview, quickList, quickNotice, quickPanel, quickPanelFoot, quickPanelHead,\n quickPanelTitle, quickPanelTitleRow, quickPrimaryButton, quickPrimaryButtonDisabled,\n quickTierButton, quickTierButtonActive, quickTierRow,\n} from './styles.ts'\n\n/** \u9762\u677F\u6CE8\u5165\u9762\u3002 */\nexport interface QuickPanelInjected {\n hooks: {\n /** \u5F53\u524D\u8BBE\u7F6E\uFF08\u6863\u4F4D + \u603B\u5F00\u5173\uFF09\u3002 */\n live: SnapshotStore<ComposerUxSettings>\n /** \u9762\u677F\u951A\u70B9\uFF1Bnull = \u9762\u677F\u5173\u95ED\u3002 */\n panel: SnapshotStore<QuickPanelAnchor | null>\n /** \u662F\u5426\u6709\u4E00\u6B21\u4F18\u5316\u5728\u98DE\u3002 */\n busy: SnapshotStore<boolean>\n /** \u9762\u677F\u72B6\u6001\u63D0\u793A\uFF08\u7A7A\u4E32 = \u65E0\uFF09\u3002 */\n notice: SnapshotStore<string>\n /** \u5FEB\u6377\u6307\u4EE4\u672C\uFF08\u771F\u76F8\u5728\u78C1\u76D8\u90A3\u4EFD quick-prompts.json\uFF09\u3002 */\n book: SnapshotStore<QuickPromptBook>\n /** '' = \u6B63\u5E38\uFF1B'saving' = \u6B63\u5728\u5199\uFF1B\u5176\u4F59 = \u4E0A\u4E00\u6B21\u7684\u9519\u8BEF\u6587\u6848\u3002 */\n bookStatus: SnapshotStore<string>\n }\n actions: {\n /** \u5173\u95ED\u9762\u677F\u3002 */\n close: () => void\n /** \u628A\u4E00\u6BB5\u6587\u672C\u63D2\u8FDB\u8F93\u5165\u6846\u3002 */\n insert: (text: string) => void\n /** \u7528\u5F53\u524D\u8F93\u5165\u6846\u5185\u5BB9\u8DD1\u4E00\u6B21\u4F18\u5316\uFF0C\u7ED3\u679C\u5199\u56DE\u8F93\u5165\u6846\u3002 */\n optimize: () => void\n /** \u5207\u6362\u4F18\u5316\u6863\u4F4D\u3002 */\n setTier: (tier: OptimizerTier) => void\n /** \u8BBE\u7F6E\u67D0\u6761\u7684\u63D2\u5165\u6A21\u5F0F\uFF08\u5173 / \u6BCF\u6B21 / \u4EC5\u9996\u6B21\uFF1B\u6309 id \u8DE8\u5206\u7C7B\u627E\uFF09\u3002 */\n setInsertMode: (promptId: string, mode: InsertMode) => void\n /** \u65B0\u589E\u4E00\u4E2A\u5206\u7C7B\uFF08\u540D\u5B57\u7531\u8BBE\u7F6E\u9875\u518D\u6539\uFF09\u3002 */\n addCategory: (name: string) => void\n /** \u5728\u5F53\u524D\u5206\u7C7B\u91CC\u65B0\u5EFA\u4E00\u6761\uFF08\u5360\u4F4D\u6B63\u6587\uFF0C\u5177\u4F53\u5185\u5BB9\u5230\u8BBE\u7F6E\u9875\u6539\uFF09\u3002 */\n addPrompt: (categoryId: string) => void\n /** \u628A\u67D0\u6761\u4ECE\u5B83\u6240\u5728\u5206\u7C7B\u79FB\u5230\u76EE\u6807\u5206\u7C7B\uFF08\u300C\u79FB\u52A8\u5230\u8FD9\u91CC\u300D\uFF09\u3002 */\n movePrompt: (promptId: string, toCategoryId: string) => void\n /** \u4ECE\u78C1\u76D8\u91CD\u8BFB\uFF08\u6587\u4EF6\u88AB\u624B\u5DE5\u6539\u8FC7\u65F6\u7684\u515C\u5E95\uFF09\u3002 */\n reloadBook: () => void\n }\n}\n\nexport type QuickCommandsPanelProps =\n PropsRuntime<'shell.overlay'>\n & InjectFace<QuickPanelInjected>\n\n/** \u4E0E\u89C6\u53E3\u8FB9\u754C\u4FDD\u6301\u7684\u95F4\u8DDD\u3002 */\nconst MARGIN = 8\n/** \u9762\u677F\u4E0E\u951A\u70B9\u6309\u94AE\u4E4B\u95F4\u7684\u95F4\u8DDD\u3002 */\nconst GAP = 8\n\n/** \u5C55\u5F00\u9762\u677F\u3002 */\nexport function QuickCommandsPanel({\n useLive, usePanel, useBusy, useNotice, useBook, useBookStatus, actions,\n}: QuickCommandsPanelProps) {\n const settings = useLive(item => item)\n const anchor = usePanel(item => item)\n const busy = useBusy(item => item)\n const notice = useNotice(item => item)\n const book = useBook(item => item)\n const status = useBookStatus(item => item)\n const ref = useRef<HTMLDivElement | null>(null)\n const [position, setPosition] = useState<{ left: number; top: number } | null>(null)\n const [activeId, setActiveId] = useState('')\n\n const counts = bookCounts(book)\n const categories = book.categories\n const active = categories.find(category => category.id === activeId) ?? categories[0]\n\n // \u8D34\u951A\u70B9\u6309\u94AE\u4E0A\u65B9\uFF1B\u653E\u4E0D\u4E0B\u5C31\u7FFB\u5230\u4E0B\u65B9\uFF1B\u5DE6\u53F3\u94B3\u5236\u5728\u89C6\u53E3\u5185\u3002\n useLayoutEffect(() => {\n if (anchor === null) {\n setPosition(null)\n return\n }\n const el = ref.current\n const height = el === null ? 320 : el.getBoundingClientRect().height\n const width = el === null ? 420 : el.getBoundingClientRect().width\n const left = Math.max(MARGIN, Math.min(anchor.left, window.innerWidth - width - MARGIN))\n const above = anchor.bottom - height - GAP\n const top = above >= MARGIN ? above : Math.min(anchor.bottom + GAP, window.innerHeight - height - MARGIN)\n setPosition({ left, top: Math.max(MARGIN, top) })\n }, [anchor?.left, anchor?.bottom, counts.prompts, categories.length, busy])\n\n // \u5916\u90E8\u70B9\u51FB / Escape / \u6EDA\u52A8 / \u7F29\u653E\u65F6\u5173\u95ED\uFF08\u4E0E\u53F3\u952E\u83DC\u5355\u540C\u4E00\u5957\u89C4\u5219\uFF09\u3002\n useEffect(() => {\n if (anchor === null) return\n const onPointerDown = (event: PointerEvent): void => {\n if (ref.current !== null && event.target instanceof Node && ref.current.contains(event.target)) return\n // \u70B9\u5165\u53E3\u6309\u94AE\u672C\u8EAB\u7531\u5B83\u81EA\u5DF1 toggle\uFF0C\u8FD9\u91CC\u8BA9\u8DEF\uFF0C\u514D\u5F97\u300C\u5173\u4E86\u53C8\u5F00\u300D\u3002\n if (event.target instanceof Element && event.target.closest('.composer-ux-quick-button') !== null) return\n actions.close()\n }\n const onEscape = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape') return\n event.preventDefault()\n event.stopPropagation()\n actions.close()\n }\n window.addEventListener('pointerdown', onPointerDown, true)\n window.addEventListener('keydown', onEscape, true)\n window.addEventListener('resize', actions.close)\n return () => {\n window.removeEventListener('pointerdown', onPointerDown, true)\n window.removeEventListener('keydown', onEscape, true)\n window.removeEventListener('resize', actions.close)\n }\n }, [anchor === null, actions])\n\n if (anchor === null) return null\n\n const tier = settings.optimizerTier\n const items = active?.prompts ?? []\n const failure = status !== '' && status !== 'saving' ? status : ''\n\n return (\n <div\n ref={ref}\n role=\"dialog\"\n aria-label=\"\u5FEB\u6377\u6307\u4EE4\"\n style={{ ...quickPanel, left: position?.left ?? anchor.left, top: position?.top ?? anchor.bottom }}\n >\n <div style={quickPanelHead}>\n <div style={quickPanelTitleRow}>\n <span style={quickPanelTitle}>\u5FEB\u6377\u6307\u4EE4</span>\n <div style={quickTierRow} role=\"group\" aria-label=\"\u4F18\u5316\u5F3A\u5EA6\">\n {OPTIMIZER_TIERS.map(item => (\n <button\n key={item.id}\n type=\"button\"\n title={item.hint}\n aria-pressed={tier === item.id}\n style={tier === item.id ? quickTierButtonActive : quickTierButton}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { actions.setTier(item.id) }}\n >\n {item.label}\n </button>\n ))}\n </div>\n </div>\n <button\n type=\"button\"\n disabled={busy}\n title=\"\u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u4EA4\u7ED9\u53E6\u4E00\u4E2A AI \u6574\u7406\u6210\u4E00\u6761\u53EF\u4EE5\u76F4\u63A5\u53D1\u51FA\u53BB\u7684\u6E05\u6670\u6307\u4EE4\uFF0C\u7ED3\u679C\u76F4\u63A5\u5199\u56DE\u8F93\u5165\u6846\u3002\u5B83\u53EA\u80FD\u4EA7\u51FA\u80FD\u6307\u56DE\u4F60\u539F\u8BDD\u67D0\u4E00\u53E5\u7684\u8865\u5168\uFF0C\u6307\u4E0D\u56DE\u53BB\u7684\u4F1A\u88AB\u4E22\u6389\u5E76\u8BB0\u8D26\"\n style={busy ? quickPrimaryButtonDisabled : quickPrimaryButton}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { actions.optimize() }}\n >\n <span aria-hidden>\u2728</span>\n <span>{busy ? '\u4F18\u5316\u4E2D\u2026' : '\u4F18\u5316\u63D0\u793A\u8BCD'}</span>\n </button>\n <div style={quickCategoryRow}>\n {categories.map(category => (\n <button\n key={category.id}\n type=\"button\"\n title={`${category.name}\uFF08${String(category.prompts.length)} \u6761\uFF09`}\n aria-pressed={category.id === active?.id}\n style={category.id === active?.id ? quickCategoryTabActive : quickCategoryTab}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { setActiveId(category.id) }}\n >\n {category.name}\n </button>\n ))}\n <button\n type=\"button\"\n style={quickCategoryAdd}\n disabled={categories.length >= QUICK_CATEGORY_MAX}\n title=\"\u65B0\u589E\u4E00\u4E2A\u5206\u7C7B\uFF08\u540D\u5B57\u5230\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C\u300D\u91CC\u6539\uFF09\"\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => {\n actions.addCategory(DEFAULT_CATEGORY_NAME)\n }}\n >\n \uFF0B\n </button>\n </div>\n </div>\n\n <div style={quickList}>\n {items.length === 0 && (\n <div style={quickEmpty}>\n \u8FD9\u4E2A\u5206\u7C7B\u91CC\u8FD8\u6CA1\u6709\u6761\u76EE\u3002<br />\n \u5728\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C \u2192 \u5FEB\u6377\u6307\u4EE4\u6E05\u5355\u300D\u91CC\u6DFB\u52A0\u3002\n </div>\n )}\n {items.map(item => (\n <div key={item.id} style={{ display: 'flex', alignItems: 'center', gap: 4 }}>\n <button\n type=\"button\"\n title={item.prompt}\n style={quickItem}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { actions.insert(item.prompt) }}\n >\n <span style={quickItemLabel}>{item.label}</span>\n <span style={quickItemPreview}>{item.prompt.replace(/\\s+/g, ' ')}</span>\n </button>\n <InsertModeControl\n compact\n label={item.label}\n mode={insertModeOf(item)}\n onChange={mode => { actions.setInsertMode(item.id, mode) }}\n />\n </div>\n ))}\n {active !== undefined && (\n <AddPromptRow\n variant=\"panel\"\n book={book}\n categoryId={active.id}\n onAdd={() => { actions.addPrompt(active.id) }}\n onMove={promptId => { actions.movePrompt(promptId, active.id) }}\n />\n )}\n </div>\n\n <div style={quickPanelFoot}>\n <span style={quickNotice} role=\"status\">{notice !== '' ? notice : failure}</span>\n <span\n style={quickFootHint}\n title=\"\u6570\u636E\u5728 ~/.dsh/quick-prompts.json\"\n >\n {counts.categories} \u5206\u7C7B \u00B7 {counts.prompts} \u6761\n </span>\n </div>\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Browser half\uFF1A\u6CE8\u518C\u8BBE\u7F6E\u9875\uFF08settings.section\uFF09\u3001\u53F3\u952E\u83DC\u5355\u4E0E\u8BBE\u7F6E\u9762\u677F\u62D6\u62FD\n * \u624B\u67C4\uFF08shell.overlay\uFF09\uFF0C\u5E76\u5B89\u88C5\u8F93\u5165\u6846\u62E6\u622A\u5668\uFF08\u952E\u4F4D + \u53F3\u952E\u83DC\u5355\uFF09\u4E0E\u9762\u677F\n * \u6EDA\u52A8\u6837\u5F0F\u3002\n */\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport {\n DEFAULT_SETTINGS, ENABLED_FIELD, HEADER_ENABLED_FIELD, HEADER_NAME_FIELD,\n HEADER_ROUTES_FIELD, HEADER_VALUE_FIELD, KEYS_ENABLED_FIELD, MENU_ENABLED_FIELD,\n MENU_FIELDS, MENU_MODE_FIELD, MENU_NATIVE_FIELD, NAMESPACE,\n NEWLINE_KEY_FIELD, OPTIMIZER_TIER_FIELD, PANEL_ENABLED_FIELD, PANEL_RESIZE_FIELD,\n PANEL_WIDTH_FIELD, PANEL_HEIGHT_FIELD, QUICK_ENABLED_FIELD, SEND_KEY_FIELD, TERMINAL_ENABLED_FIELD,\n activeSections, sanitizeSettings,\n alwaysQuickPrompts, appendBatchForSend, defaultQuickBook,\n type ComposerUxSettings, type InsertMode, type MenuState, type OptimizerTier, type QuickPrompt,\n type QuickPromptBook, type SettingsField,\n} from './settings-contract.ts'\n// \u7EC8\u7AEF\u5B57\u6BB5\u7684\u5E38\u91CF\u4F4F\u5728\u7EC8\u7AEF\u5951\u7EA6\u91CC\uFF08settings-contract \u53EA\u662F\u628A\u5B83\u4EEC\u5E76\u8FDB\u8BBE\u7F6E\u5951\u7EA6\uFF09\u3002\nimport { TERMINAL_BASH_PATH_FIELD, TERMINAL_MODE_FIELD } from './terminal/contracts.ts'\nimport {\n loadPromptBook, savePromptBook, withCategoryAdded, withCategoryMoved,\n withCategoryRemoved, withCategoryRenamed, withInsertMode, withPromptAdded, withPromptMoved,\n withPromptMovedToCategory, withPromptPatched, withPromptRemoved,\n} from './client/prompt-book.ts'\nimport { installInterceptors, runMenuAction } from './client/interceptors.ts'\nimport { installPanelResizeStyle } from './client/panel.ts'\nimport { installSettingsCardStyle } from './client/settings-style.ts'\nimport { installQuickButtonStyle } from './client/quick-style.ts'\nimport { ContextMenuHost } from './client/ContextMenuHost.tsx'\nimport { PanelResizeHandles } from './client/PanelResizeHandles.tsx'\nimport { SettingsSection } from './client/SettingsSection.tsx'\nimport { QuickCommandsButton, type QuickPanelAnchor } from './client/QuickCommandsButton.tsx'\nimport { QuickCommandsPanel } from './client/QuickCommandsPanel.tsx'\nimport {\n focusComposer, insertIntoDraft, optimizeDraft, replaceDraft, currentBlankSession, currentDraft,\n} from './client/quick-commands.ts'\n\nexport const name = 'composer-ux'\n/**\n * \u53EA\u786C\u4F9D\u8D56 `slots`\u3002\n *\n * \u8BBE\u7F6E\u670D\u52A1\u6362\u4E86\u540D\u5B57\u4E0E\u5F62\u72B6\uFF0C\u800C\u4E14**\u4E0D\u80FD\u540C\u65F6\u5199\u8FDB `inject`**\uFF1A\n * 0.1.6 \u53CA\u4EE5\u524D = `ctx.settingsScope.bind({ namespace })`\n * 0.1.7 \u8D77 = `ctx.configForms.get(namespace)`\n * \u8C01\u5728\u5BF9\u65B9\u90A3\u4E00\u4EE3\u90FD\u4E0D\u5B58\u5728\uFF0C\u9759\u6001 inject \u4E00\u65E6\u5199\u9519\uFF0C\u63D2\u4EF6\u5C31\u6C38\u8FDC\u7B49\u4E0D\u5230\u4F9D\u8D56\u800C\u6574\u5757\u4E0D\u6302\u8F7D\n * \uFF08\u8BBE\u7F6E\u9875\u3001\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u3001\u5FEB\u6377\u6307\u4EE4\u4E00\u8D77\u6D88\u5931\uFF09\u3002\u6240\u4EE5\u8FD9\u91CC\u53EA\u786C\u4F9D\u8D56 slots\uFF0C\n * \u4E24\u4E2A\u540D\u5B57\u5404\u7528 `ctx.inject` \u7B49\u4E00\u6B21\uFF0C\u8C01\u5148\u5230\u5C31\u7528\u8C01\uFF08\u89C1 `adoptSettings`\uFF09\u3002\n */\nexport const inject = ['slots']\n\n/** \u4E00\u4E2A\u8BBE\u7F6E\u4F5C\u7528\u57DF\u7684\u6700\u5C0F\u7528\u6CD5\uFF1A\u4E24\u4EE3 `SettingsScope` / `ConfigForm` \u7684\u4EA4\u96C6\u3002 */\ninterface SettingsScopeLike {\n getSnapshot(): { status: string; value?: unknown }\n subscribe(listener: () => void): () => void\n set(field: string, value: unknown): Promise<unknown>\n unset(field: string): Promise<unknown>\n mutate(ops: readonly { op: 'set' | 'unset'; path: readonly string[]; value?: unknown }[]): Promise<unknown>\n}\n\n/**\n * \u8BBE\u7F6E\u670D\u52A1\u7F3A\u5E2D\u65F6\u7684\u66FF\u8EAB\uFF1A\u754C\u9762\u4EE5\u9ED8\u8BA4\u503C\u7167\u5E38\u53EF\u7528\u3002\n *\n * \u5B58\u5728\u7684\u610F\u4E49\u662F\"\u964D\u7EA7\u800C\u4E0D\u662F\u6D88\u5931\"\u2014\u2014\u4E24\u4EE3 DSH \u90FD\u6709\u8FD9\u4E2A\u670D\u52A1\uFF0C\u6240\u4EE5\u5B83\u53EA\u5728\n * \u7EC4\u5408\u91CC\u6839\u672C\u6CA1\u6709\u8BBE\u7F6E provider \u65F6\u515C\u5E95\u3002\n */\nconst NULL_SCOPE: SettingsScopeLike = {\n getSnapshot: () => ({ status: 'unavailable', value: undefined }),\n subscribe: () => () => {},\n set: async () => false,\n unset: async () => false,\n mutate: async () => false,\n}\n\n/** \u5BA2\u6237\u7AEF\u63D2\u4EF6\u5165\u53E3\u3002 */\nexport function apply(ctx: any): void {\n const slots = ctx.slots\n\n const live = createSnapshotStore<ComposerUxSettings>({ ...DEFAULT_SETTINGS })\n const menu = createSnapshotStore<MenuState | null>(null)\n const panel = createSnapshotStore<QuickPanelAnchor | null>(null)\n const optimizing = createSnapshotStore<boolean>(false)\n const panelNotice = createSnapshotStore<string>('')\n /**\n * \u8BBE\u7F6E\u5199\u5165\u7684\u8BF4\u660E\u884C\uFF1B'' = \u6B63\u5E38\u3002\u6E32\u67D3\u5728\u8BBE\u7F6E\u5361\u7247\u9876\u90E8\uFF08\u4E0E\u300C\u91CD\u542F DSH\u300D\u6A2A\u5E45\u540C\u4F4D\u7F6E\uFF09\u3002\n *\n * \u5B58\u5728\u7684\u7406\u7531\uFF1A`ConfigForm.set` \u8FD4\u56DE `true` \u53EA\u4EE3\u8868\u5BBF\u4E3B**\u6536\u4E0B**\u4E86\u8FD9\u6B21\u5199\u5165\uFF0C\u4E0D\u4FDD\u8BC1\u8FD0\u884C\u65F6\n * \u7684\u6D3B\u503C\u8DDF\u7740\u53D8\u3002\u771F\u673A\u4E8B\u6545\uFF082026-09-23\uFF09\u91CC\uFF0C\u8BBE\u7F6E\u5199\u5165\u88AB\u4E00\u628A\u5B64\u513F\u9501\u6321\u4F4F\uFF0C\u7528\u6237\u80FD\u770B\u5230\u7684\n * \u53EA\u6709\"\u5F00\u5173\u4E0D\u52A8\"\u2014\u2014\u4E00\u53E5\u63D0\u793A\u90FD\u6CA1\u6709\u3002\u6240\u4EE5\u5E03\u5C14\u5B57\u6BB5\u5199\u5B8C\u56DE\u8BFB\u4E00\u6B21\uFF0C\u5BF9\u4E0D\u4E0A\u5C31\u628A\u8BDD\u8BF4\u51FA\u6765\u3002\n */\n const writeNotice = createSnapshotStore<string>('')\n\n /** \u5F53\u524D\u8BBE\u7F6E\u4F5C\u7528\u57DF\uFF1B\u771F\u7684\u90A3\u4E2A\u5230\u4E86\u4E4B\u540E\u88AB `adoptSettings` \u6362\u6389\uFF08\u89C1\u6587\u4EF6\u4E0A\u65B9 inject \u90A3\u6BB5\uFF09\u3002 */\n let scope: SettingsScopeLike = NULL_SCOPE\n\n const sync = (): void => {\n const snapshot = scope.getSnapshot()\n live.set(snapshot.status === 'ready' && snapshot.value !== undefined\n ? { ...DEFAULT_SETTINGS, ...sanitizeSettings(snapshot.value) }\n : { ...DEFAULT_SETTINGS })\n }\n sync()\n\n /**\n * \u8BA4\u9886\u7B2C\u4E00\u4E2A\u51FA\u73B0\u7684\u8BBE\u7F6E\u670D\u52A1\u3002\n *\n * 0.1.7 \u7684 `ConfigForm.set/unset/mutate` \u8FD4\u56DE `Promise<boolean>`\uFF08`false` = \u5BBF\u4E3B\u62D2\u7EDD\uFF0C\n * \u4F8B\u5982\u5B57\u6BB5\u4E0D\u662F volatile\u3001\u6216\u4FEE\u8BA2\u53F7\u88AB\u522B\u4EBA\u62A2\u5148\uFF09\uFF1B0.1.6 \u8FD4\u56DE `Promise<void>`\u3002\n * \u6240\u4EE5\u8FD9\u91CC\u53EA\u5728\u660E\u786E\u62FF\u5230 `false` \u65F6\u8BB0\u4E00\u6761\u8B66\u544A\uFF0C\u4E24\u4EE3\u90FD\u4E0D\u4F1A\u8BEF\u62A5\u3002\n */\n let adopted = false\n const adoptSettings = (service: unknown, shape: 'get' | 'bind'): void => {\n if (adopted || service === null || service === undefined) return\n const api = service as {\n get?: (namespace: string) => unknown\n bind?: (spec: { namespace: string }) => unknown\n }\n const next = shape === 'get' ? api.get?.(NAMESPACE) : api.bind?.({ namespace: NAMESPACE })\n if (next === null || next === undefined) return\n if (typeof (next as SettingsScopeLike).getSnapshot !== 'function') return\n adopted = true\n scope = next as SettingsScopeLike\n sync()\n ctx.effect(() => scope.subscribe(sync), 'composer-ux: settings sync')\n }\n /**\n * \u7B49\u4E00\u4E2A\u670D\u52A1\u51FA\u73B0\uFF08cordis \u7684 `inject` \u8BED\u4E49\uFF09\u3002\n *\n * `ctx.inject` \u7406\u8BBA\u4E0A\u4E00\u5B9A\u5728\uFF08\u5BBF\u4E3B\u534A\u4E5F\u5728\u7528\uFF09\uFF0C\u4F46\u5B83\u662F\u8FD9\u4E00\u5757\u552F\u4E00\u4F1A\u8BA9 apply \u629B\u51FA\u7684\u8C03\u7528 \u2014\u2014\n * \u629B\u51FA\u610F\u5473\u7740\u6574\u5757\u6D88\u5931\uFF0C\u6240\u4EE5\u7F3A\u5E2D\u65F6\u9759\u9ED8\u8DF3\u8FC7\uFF1A\u4E0B\u9762\u7684\"\u76F4\u63A5\u8BFB\u4E00\u6B21\"\u515C\u5E95\u4ECD\u4F1A\u8BA4\u9886\u5DF2\u5230\u4F4D\u7684\u670D\u52A1\u3002\n */\n const whenService = (deps: string[], callback: (view: Record<string, unknown>) => void): void => {\n if (typeof ctx.inject !== 'function') return\n try {\n ctx.inject(deps, callback)\n } catch (error: unknown) {\n console.warn('[composer-ux] settings service inject failed', error)\n }\n }\n whenService(['configForms'], view => { adoptSettings(view.configForms, 'get') })\n whenService(['settingsScope'], view => { adoptSettings(view.settingsScope, 'bind') })\n /**\n * \u76F4\u63A5\u8BFB\u4E00\u6B21\u5C5E\u6027\uFF0C\u4E24\u4EE3\u5404\u8BD5\u4E00\u6B21\uFF08`adoptSettings` \u5185\u90E8\u6709 `adopted` \u95F8\uFF0C\u4E0D\u4F1A\u91CD\u590D\u8BA4\u9886\uFF09\u3002\n *\n * \u5FC5\u987B\u5305 try\uFF1Acordis \u7684\u4E0A\u4E0B\u6587\u4EE3\u7406\u5BF9**\u672A\u51FA\u73B0\u5728 inject \u91CC**\u7684\u670D\u52A1\u540D\u76F4\u63A5\u629B\u51FA\n * `cannot get property \"X\" without inject`\u3002\u672C\u63D2\u4EF6\u53EA\u58F0\u660E `inject = ['slots']`\uFF0C\n * \u6240\u4EE5\u5728\u7F3A\u8FD9\u4E00\u4EE3\u670D\u52A1\u7684 DSH \u4E0A\uFF080.1.6 \u6CA1\u6709 `configForms`\u30010.1.7 \u6CA1\u6709\n * `settingsScope`\uFF09\uFF0C\u88F8\u8BFB\u5C5E\u6027\u4F1A\u8BA9\u6574\u4E2A apply \u629B\u51FA \u2014\u2014 \u8BBE\u7F6E\u9875\u3001\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u3001\n * \u5FEB\u6377\u6307\u4EE4\u4E00\u8D77\u6D88\u5931\uFF0C\u6B63\u662F\u4E0A\u9762\u6CE8\u91CA\u8981\u907F\u514D\u7684\u90A3\u79CD\"\u6574\u5757\u4E0D\u6302\u8F7D\"\u3002\n */\n const peekService = (name: string): unknown => {\n try {\n return (ctx as Record<string, unknown>)[name]\n } catch {\n return undefined\n }\n }\n adoptSettings(peekService('configForms'), 'get')\n adoptSettings(peekService('settingsScope'), 'bind')\n\n /**\n * \u5199\u5165\u4E00\u4E2A\u5B57\u6BB5\uFF1B\u88AB\u5BBF\u4E3B\u62D2\u7EDD\uFF08\u65B0\u7248\u8FD4\u56DE false\uFF09\u65F6\u5728\u63A7\u5236\u53F0\u7559\u75D5\uFF0C\u5E76\u628A\u539F\u56E0\u7559\u7ED9\u8BBE\u7F6E\u9875\u3002\n *\n * \u4E3A\u4EC0\u4E48\u8FD8\u8981**\u56DE\u8BFB\u6821\u9A8C**\uFF1A`ConfigForm.set` \u8FD4\u56DE `true` \u53EA\u8BF4\u660E\u5BBF\u4E3B\u6536\u4E0B\u4E86\u5199\u5165\uFF0C\u4E0D\u4FDD\u8BC1\n * \u8FD0\u884C\u65F6\u7684\u6D3B\u503C\u8DDF\u7740\u53D8\u3002\u771F\u673A\u4E0A\u51FA\u73B0\u8FC7\u4E24\u79CD\"\u70B9\u4E86\u6CA1\u53CD\u5E94\"\uFF1A\n * \u00B7 \u5199\u5165\u88AB\u62D2\uFF08false\uFF09\u2014\u2014 profile \u7684\u5199\u5165\u9501\u88AB\u5360/\u662F\u5B64\u513F\u9501\uFF0C\u7B49 2 \u79D2\u8D85\u65F6\uFF1B\n * \u00B7 \u5199\u5165\u843D\u76D8\u3001\u4F46\u8FDB\u7A0B\u91CC\u7684\u6D3B\u503C\u6CA1\u63A5\u4F4F \u2014\u2014 \u754C\u9762\u7EE7\u7EED\u663E\u793A\u65E7\u503C\u3002\n * \u4E24\u79CD\u90FD\u8981\u91CD\u542F\uFF08\u6216\u624B\u5DE5\u56DE\u6536\u9501\uFF09\u624D\u80FD\u6062\u590D\uFF0C\u800C\u7528\u6237\u552F\u4E00\u7684\u7EBF\u7D22\u5C31\u662F\"\u5F00\u5173\u4E0D\u52A8\"\u3002\u6240\u4EE5\u8FD9\u91CC\n * \u56DE\u8BFB\u4E00\u6B21\uFF0C\u5BF9\u4E0D\u4E0A\u5C31\u628A\u8BF4\u660E\u6302\u5230\u8BBE\u7F6E\u9875\u9876\u90E8\u3002\n *\n * \u4E3A\u4EC0\u4E48\u53EA\u6821\u9A8C\u5E03\u5C14\u5B57\u6BB5\uFF1A\u5E03\u5C14\u4E0D\u4F1A\u88AB\u51C0\u5316\u5C42\u5939\u53D6\uFF0C\u4E5F\u6CA1\u6709\"\u5199\u5165\u540C\u4E00\u4E2A\u503C\"\u7684\u6B63\u5E38\u573A\u666F\uFF0C\n * \u4E8E\u662F\"\u56DE\u8BFB\u4ECD\u4E0D\u7B49\u4E8E\u521A\u5199\u7684\u503C\"\u5C31\u662F\u660E\u786E\u5F02\u5E38\uFF1B\u5C3A\u5BF8/\u6587\u672C\u6709\u5939\u53D6\u4E0E\u622A\u65AD\uFF0C\u62FF\u5B83\u4EEC\u5224\u7B49\u4F1A\u8BEF\u62A5\u3002\n */\n const WRITE_READBACK_MS = 1200\n const setField = (field: SettingsField, value: unknown): void => {\n writeNotice.set('')\n const verify = typeof value === 'boolean'\n void scope.set(field, value as never).then((accepted: unknown) => {\n if (accepted === false) {\n console.warn('[composer-ux] settings write refused', field)\n writeNotice.set(\n `\u5199\u5165\u300C${field}\u300D\u88AB\u5BBF\u4E3B\u62D2\u7EDD\u3002\u5E38\u89C1\u539F\u56E0\uFF1Aprofile \u7684\u5199\u5165\u9501\u88AB\u5360\u7528\uFF0C\u6216\u662F\u4E00\u628A\u5B64\u513F\u9501`\n + '\uFF08\u786C\u6740\u91CD\u542F\u7559\u4E0B\u7684\uFF09\u2014\u2014\u89C1 README\u300C\u8BBE\u7F6E\u5199\u4E0D\u8FDB\u53BB\u300D\u4E00\u8282\uFF1B\u91CD\u542F DSH \u540E\u4ECD\u65E0\u6548\uFF0C'\n + '\u5C31\u624B\u5DE5\u5220\u6389 profiles/<\u4F60\u7684 profile>/package.json.lock\u3002',\n )\n return\n }\n if (!verify) return\n setTimeout(() => {\n const now = (live.getSnapshot() as unknown as Record<string, unknown>)[field]\n if (now === value) return\n console.warn('[composer-ux] settings write had no visible effect', field, now, value)\n writeNotice.set(\n `\u5199\u5165\u300C${field}\u300D\u5DF2\u88AB\u5BBF\u4E3B\u63A5\u53D7\uFF0C\u4F46\u8FD0\u884C\u65F6\u7684\u503C\u6CA1\u6709\u53D8\u5316\uFF08\u4ECD\u662F ${String(now)}\uFF09\u3002`\n + '\u914D\u7F6E\u53EF\u80FD\u5DF2\u7ECF\u843D\u76D8\uFF0C\u53EA\u662F\u8FD9\u4E2A\u8FDB\u7A0B\u6CA1\u63A5\u4F4F\u2014\u2014\u91CD\u542F DSH \u5373\u53EF\u751F\u6548\u3002',\n )\n }, WRITE_READBACK_MS)\n }, (error: unknown) => {\n console.error('[composer-ux] settings write failed', error)\n writeNotice.set(`\u5199\u5165\u300C${field}\u300D\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`)\n })\n }\n const clearField = (field: SettingsField): void => {\n void scope.unset(field).then((accepted: unknown) => {\n if (accepted === false) console.warn('[composer-ux] settings clear refused', field)\n }, (error: unknown) => {\n console.error('[composer-ux] settings clear failed', error)\n })\n }\n\n // \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\u5B58\u50A8\uFF08\u5206\u7C7B\u7ED3\u6784\uFF1B\u771F\u76F8\u5728 $DSH_HOME/quick-prompts.json\uFF09 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n //\n // \u8BFB\uFF1Aapply \u65F6\u62C9\u4E00\u6B21\u3002\u5199\uFF1A\u5148\u4E50\u89C2\u66F4\u65B0\u672C\u5730\u5FEB\u7167\u8BA9\u754C\u9762\u7ACB\u523B\u54CD\u5E94\uFF0C\u518D\u628A\u6574\u672C POST \u4E0A\u53BB\uFF1B\n // \u5931\u8D25\u5C31\u4EE5\u78C1\u76D8\u4E3A\u51C6\u56DE\u6EDA\u2014\u2014\u4E0D\u8BA9\u300C\u754C\u9762\u663E\u793A\u7684\u300D\u548C\u300C\u6587\u4EF6\u91CC\u7684\u300D\u957F\u671F\u4E0D\u4E00\u81F4\u3002\n const book = createSnapshotStore<QuickPromptBook>(defaultQuickBook())\n /** '' = \u6B63\u5E38\uFF1B'saving' = \u6B63\u5728\u5199\uFF1B\u5176\u4F59 = \u4E0A\u4E00\u6B21\u7684\u9519\u8BEF\u6587\u6848\u3002 */\n const bookStatus = createSnapshotStore<string>('')\n\n const reloadBook = async (): Promise<void> => {\n const reply = await loadPromptBook()\n if (reply.ok && reply.book !== undefined) {\n book.set(reply.book)\n bookStatus.set('')\n return\n }\n bookStatus.set(reply.error ?? '\u8BFB\u53D6\u5FEB\u6377\u6307\u4EE4\u5931\u8D25')\n }\n\n const commitBook = (next: QuickPromptBook): void => {\n book.set(next)\n bookStatus.set('saving')\n void savePromptBook(next).then(\n (reply) => {\n if (reply.ok && reply.book !== undefined) {\n // \u7528\u5BBF\u4E3B\u56DE\u8BFB\u7684**\u78C1\u76D8\u771F\u5B9E\u5185\u5BB9**\u8986\u76D6\u672C\u5730\uFF1A\u4EFB\u4F55\u88AB\u6536\u7A84/\u4E22\u5F03\u7684\u5B57\u6BB5\u7ACB\u523B\u53EF\u89C1\u3002\n book.set(reply.book)\n bookStatus.set('')\n return\n }\n bookStatus.set(reply.error ?? '\u4FDD\u5B58\u5931\u8D25')\n void reloadBook()\n },\n (error: unknown) => {\n bookStatus.set(error instanceof Error ? error.message : String(error))\n void reloadBook()\n },\n )\n }\n\n void reloadBook()\n\n const bookActions = {\n reload: (): void => { void reloadBook() },\n addCategory: (name: string): void => { commitBook(withCategoryAdded(book.getSnapshot(), name)) },\n renameCategory: (id: string, name: string): void => {\n commitBook(withCategoryRenamed(book.getSnapshot(), id, name))\n },\n removeCategory: (id: string): void => { commitBook(withCategoryRemoved(book.getSnapshot(), id)) },\n moveCategory: (id: string, delta: number): void => {\n commitBook(withCategoryMoved(book.getSnapshot(), id, delta))\n },\n addPrompt: (categoryId: string): void => { commitBook(withPromptAdded(book.getSnapshot(), categoryId)) },\n patchPrompt: (categoryId: string, id: string, patch: { label?: string; prompt?: string }): void => {\n commitBook(withPromptPatched(book.getSnapshot(), categoryId, id, patch))\n },\n removePrompt: (categoryId: string, id: string): void => {\n commitBook(withPromptRemoved(book.getSnapshot(), categoryId, id))\n },\n movePrompt: (categoryId: string, id: string, delta: number): void => {\n commitBook(withPromptMoved(book.getSnapshot(), categoryId, id, delta))\n },\n resetBook: (): void => { commitBook(defaultQuickBook()) },\n /** \u628A\u67D0\u6761\u4ECE\u5B83\u6240\u5728\u5206\u7C7B\u79FB\u5230\u76EE\u6807\u5206\u7C7B\uFF08\u300C\u79FB\u52A8\u5230\u8FD9\u91CC\u300D\uFF1A\u8FFD\u52A0\u5230\u76EE\u6807\u672B\u5C3E\uFF09\u3002 */\n movePromptToCategory: (promptId: string, toCategoryId: string): void => {\n commitBook(withPromptMovedToCategory(book.getSnapshot(), promptId, toCategoryId))\n },\n /** \u8BBE\u7F6E\u9875\u300C\u4FDD\u5B58\u300D\uFF1A\u628A\u7F16\u8F91\u5668\u91CC\u7684\u6574\u672C\u4E00\u6B21\u5199\u56DE\uFF08\u800C\u4E0D\u662F\u6BCF\u6572\u4E00\u4E2A\u5B57\u5C31\u5199\u76D8\uFF09\u3002 */\n saveBook: (next: QuickPromptBook): void => { commitBook(next) },\n }\n\n const resetAll = (): void => {\n // \u6CE8\u610F\uFF1A\u5BBF\u4E3B\u534A\u7684\u8BB0\u8D26\u5B57\u6BB5\uFF08HOST_OWNED_FIELDS\uFF09\u6545\u610F\u4E0D\u5728\u540D\u5355\u91CC\u2014\u2014\u6E05\u6389\u5B83\u4EEC\u4F1A\u8BA9\n // \u5DF2\u7ECF\u5199\u5165 llm-pi-ai \u7684\u8BF7\u6C42\u5934\u5931\u53BB\u8BB0\u8D26\uFF0C\u4ECE\u800C\u6C38\u8FDC\u64A4\u9500\u4E0D\u6389\u3002\n // \u5FEB\u6377\u6307\u4EE4\u4E5F\u4E0D\u5728\u540D\u5355\u91CC\uFF1A\u5B83\u7684\u771F\u76F8\u5DF2\u7ECF\u642C\u5230 quick-prompts.json\uFF08\u89C1 bookActions.resetBook\uFF09\uFF0C\n // \u800C\u8BBE\u7F6E\u6587\u6863\u91CC\u90A3\u4EFD 0.2.x \u7684\u65E7\u503C\u662F**\u8FC1\u79FB\u7684\u79CD\u5B50**\uFF0C\u6545\u610F\u7559\u7740\u4E0D\u6E05\u2014\u2014\u4E07\u4E00\u56DE\u6EDA\u5230\u65E7\u7248\u8FD8\u80FD\u770B\u5230\u3002\n void scope.mutate(\n [\n ENABLED_FIELD, SEND_KEY_FIELD, NEWLINE_KEY_FIELD, ...MENU_FIELDS,\n MENU_MODE_FIELD,\n // \u65E7\u7684\u5E03\u5C14\u5B57\u6BB5\u4E5F\u4E00\u5E76\u6E05\u6389\uFF1A\u5B83\u53EA\u662F\u8FC1\u79FB\u7EBF\u7D22\uFF0C\u7559\u7740\u4F1A\u628A\u300C\u6062\u590D\u9ED8\u8BA4\u300D\u540E\u7684\u6863\u4F4D\u53C8\u62C9\u56DE\u65E7\u503C\u3002\n MENU_NATIVE_FIELD,\n PANEL_RESIZE_FIELD, PANEL_WIDTH_FIELD, PANEL_HEIGHT_FIELD,\n HEADER_ENABLED_FIELD, HEADER_NAME_FIELD, HEADER_VALUE_FIELD, HEADER_ROUTES_FIELD,\n OPTIMIZER_TIER_FIELD,\n // 0.5.0 \u65B0\u589E\u7684\u7528\u6237\u914D\u7F6E\uFF1A\u7EC8\u7AEF\u6863\u4F4D/\u8DEF\u5F84\uFF08\u300C\u6062\u590D\u9ED8\u8BA4\u300D\u4E5F\u8BE5\u628A\u5B83\u4EEC\u6062\u590D\uFF09\u3002\n TERMINAL_MODE_FIELD, TERMINAL_BASH_PATH_FIELD,\n // \u4E94\u680F\u5F00\u5173\u4E5F\u6E05\u6389\uFF1A\u6E05\u6389 = \u56DE\u5230\"\u4ECE\u6CA1\u78B0\u8FC7\u8FD9\u4E00\u680F\"\u21D2 \u5168\u5173\uFF08\u65B0\u88C5\u9ED8\u8BA4\u7684\u6837\u5B50\uFF09\u3002\n // \u82E5\u4E0D\u6E05\uFF0C\u6062\u590D\u9ED8\u8BA4\u4E4B\u540E\u516D\u680F\u8FD8\u4F1A\u4FDD\u6301\u4E4B\u524D\u6253\u5F00\u7684\u72B6\u6001\uFF0C\u4E0E\"\u9ED8\u8BA4\u5173\"\u7684\u8BED\u4E49\u4E0D\u7B26\u3002\n KEYS_ENABLED_FIELD, MENU_ENABLED_FIELD, QUICK_ENABLED_FIELD,\n PANEL_ENABLED_FIELD, TERMINAL_ENABLED_FIELD,\n // 0.5.0 \u91CC\u90A3\u4E2A\u300C\u53EF\u9009\u91CD\u542F\u547D\u4EE4\u300D\u5B57\u6BB5\u5DF2\u7ECF\u5220\u6389\uFF0C\u4F46\u8001\u6587\u6863\u91CC\u53EF\u80FD\u8FD8\u7559\u7740\u503C\uFF1A\n // \u987A\u624B\u6E05\u6389\uFF0C\u514D\u5F97\u5B83\u6C38\u8FDC\u8EBA\u5728\u8BBE\u7F6E\u6587\u4EF6\u91CC\u6CA1\u4EBA\u8BA4\u8BC6\u3002\n 'restartCommand',\n ].map(field => ({ op: 'unset', path: [field] })),\n ).catch((error: unknown) => {\n console.error('[composer-ux] settings reset failed', error)\n })\n bookActions.resetBook()\n }\n\n // \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\u4E0E\u63D0\u793A\u8BCD\u4F18\u5316 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** \u9762\u677F\u5E95\u90E8\u7684\u77ED\u63D0\u793A\uFF1B\u5230\u65F6\u81EA\u52A8\u6D88\u5931\uFF08\u4E0E\u53F3\u952E\u83DC\u5355\u7684 note \u540C\u4E00\u5957\u8DEF\uFF09\u3002 */\n let noticeTimer: ReturnType<typeof setTimeout> | undefined\n const note = (message: string, ms = 4500): void => {\n panelNotice.set(message)\n if (noticeTimer !== undefined) clearTimeout(noticeTimer)\n if (message === '') return\n noticeTimer = setTimeout(() => { panelNotice.set('') }, ms)\n }\n ctx.effect(() => () => {\n if (noticeTimer !== undefined) clearTimeout(noticeTimer)\n }, 'composer-ux: quick notice timer')\n\n const quickActions = {\n toggle: (anchor: { left: number; bottom: number; width: number }): void => {\n if (panel.getSnapshot() !== null) {\n panel.set(null)\n panelNotice.set('')\n return\n }\n panelNotice.set('')\n panel.set(anchor)\n },\n close: (): void => {\n panel.set(null)\n panelNotice.set('')\n },\n insert: (text: string): void => {\n if (insertIntoDraft(text)) focusComposer()\n },\n optimize: (): void => {\n if (optimizing.getSnapshot()) return\n const draft = currentDraft()\n if (draft.trim() === '') {\n note('\u8F93\u5165\u6846\u662F\u7A7A\u7684\uFF1A\u5148\u5199\u70B9\u4EC0\u4E48\uFF0C\u518D\u70B9\u4F18\u5316')\n return\n }\n optimizing.set(true)\n note('\u6B63\u5728\u4F18\u5316\u2026')\n void optimizeDraft(draft, live.getSnapshot().optimizerTier).then(\n (result) => {\n optimizing.set(false)\n if (!result.ok) {\n note(`\u4F18\u5316\u5931\u8D25\uFF1A${result.error ?? '\u672A\u77E5\u539F\u56E0'}`)\n return\n }\n replaceDraft(result.text ?? '')\n focusComposer()\n // \u72B6\u6001\u884C\u5982\u5B9E\u4EA4\u4EE3\u8FD9\u4E00\u8F6E\u5230\u5E95\u53D1\u751F\u4E86\u4EC0\u4E48\uFF080.6.0 \u8D77\u5BBF\u4E3B\u4F1A\u56DE\u62A5\u8BB0\u8D26\u4FE1\u606F\uFF09\uFF1A\n // \u7528\u4E86\u51E0\u4E2A\u6761\u76EE\u3001\u4E22\u4E86\u51E0\u6761\u3001\u8D70\u6CA1\u8D70\u964D\u7EA7/\u91CD\u8BD5 \u2014\u2014 \u7528\u6237\u636E\u6B64\u5224\u65AD\u8FD9\u6B21\u4F18\u5316\u53EF\u4E0D\u53EF\u4FE1\u3002\n const bits: string[] = []\n if (result.fallback === true) bits.push('\u6A21\u578B\u6CA1\u6309\u6761\u76EE\u5951\u7EA6\u8F93\u51FA\uFF0C\u5DF2\u6574\u6BB5\u7167\u6536\uFF08\u672A\u6821\u9A8C\u4F9D\u636E\uFF09')\n else bits.push(`${String(result.itemCount ?? 0)} \u6761\u8865\u5168`)\n const lost = result.dropped?.length ?? 0\n if (lost > 0) bits.push(`\u4E22\u5F03 ${String(lost)} \u6761`)\n if (result.promptSource === 'custom') bits.push('\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD')\n if (result.retried === true) bits.push('\u91CD\u8BD5\u8FC7\u4E00\u6B21')\n note(`\u5DF2\u5199\u56DE\u8F93\u5165\u6846\uFF08${result.route}\uFF09\u00B7 ${bits.join(' \u00B7 ')} \u00B7 Ctrl+Z \u53EF\u8FD8\u539F`)\n },\n (error: unknown) => {\n optimizing.set(false)\n note(`\u4F18\u5316\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`)\n },\n )\n },\n setTier: (tier: OptimizerTier): void => { setField(OPTIMIZER_TIER_FIELD, tier) },\n /**\n * \u8BBE\u7F6E\u67D0\u6761\u7684\u63D2\u5165\u6A21\u5F0F\uFF08\u5173 / \u6BCF\u6B21 / \u4EC5\u9996\u6B21\uFF09\u3002\n *\n * \u754C\u9762\u4E0A\u53EA\u6709\u8FD9\u4E00\u4E2A\u5165\u53E3\uFF1A\u4E24\u4E2A\u4E92\u65A5\u6807\u5FD7\u7531 `withInsertMode` **\u4E00\u6B21\u5199\u5BF9**\uFF0C\n * \u4E0D\u7ED9\u300C\u53C8\u6BCF\u6B21\u53C8\u4EC5\u9996\u6B21\u300D\u7559\u7F1D\u3002\n */\n setInsertMode: (promptId: string, mode: InsertMode): void => {\n commitBook(withInsertMode(book.getSnapshot(), promptId, mode))\n },\n }\n\n // \u8BBE\u7F6E\u9875\u6761\u76EE\u3002\n slots.inject('settings.section', () => slots.register({\n name: 'settings.section',\n id: 'composer-ux',\n order: 40,\n label: '\u8F93\u5165\u4F53\u9A8C',\n inject: () => ({\n hooks: { live, book, bookStatus, writeNotice },\n actions: {\n setField, clearField, resetAll,\n saveBook: bookActions.saveBook,\n reloadBook: bookActions.reload,\n resetBook: bookActions.resetBook,\n dismissNotice: () => { writeNotice.set('') },\n },\n }),\n }, SettingsSection))\n\n // \u53F3\u952E\u83DC\u5355\u6D6E\u5C42\uFF08shell.overlay \u662F root \u7EA7 list \u69FD\uFF1B\u5149\u6807\u5C42\u672C\u8EAB\u70B9\u51FB\u7A7F\u900F\uFF0C\u83DC\u5355\u81EA\u8425 pointer-events\uFF09\u3002\n slots.inject('shell.overlay', () => slots.register({\n name: 'shell.overlay',\n id: 'composer-ux-menu',\n inject: () => ({\n hooks: { menu, live },\n actions: {\n run: runMenuAction,\n close: () => { menu.set(null) },\n note: (message: string | undefined) => {\n const current = menu.getSnapshot()\n if (current === null) return\n menu.set({ ...current, note: message })\n },\n },\n }),\n }, ContextMenuHost))\n\n // \u8BBE\u7F6E\u9762\u677F\u8FB9\u7F18\u62D6\u62FD\u624B\u67C4\u3002\n slots.inject('shell.overlay', () => slots.register({\n name: 'shell.overlay',\n id: 'composer-ux-panel-resize',\n inject: () => ({ hooks: { live }, actions: { setField } }),\n }, PanelResizeHandles))\n\n // \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u5165\u53E3\u6309\u94AE\uFF1A\u4E0E\u5B98\u65B9\u300C\u5C55\u5F00\u300D\u6309\u94AE\u540C\u6392\uFF08order 89 < \u5C55\u5F00\u7684 90\uFF09\u3002\n slots.inject('conversation.input.right', () => slots.register({\n name: 'conversation.input.right',\n id: 'composer-ux-quick',\n order: 89,\n label: '\u5FEB\u6377\u6307\u4EE4',\n inject: () => ({\n hooks: { live, panel },\n actions: { toggle: quickActions.toggle },\n }),\n }, QuickCommandsButton))\n\n // \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u5C55\u5F00\u9762\u677F\uFF1A\u8D70 root \u7EA7\u6D6E\u5C42\uFF0C\u4E0D\u53D7\u8F93\u5165\u5361\u7247\u88C1\u526A\u3002\n slots.inject('shell.overlay', () => slots.register({\n name: 'shell.overlay',\n id: 'composer-ux-quick-panel',\n inject: () => ({\n hooks: { live, panel, busy: optimizing, notice: panelNotice, book, bookStatus },\n actions: {\n toggle: quickActions.toggle,\n close: quickActions.close,\n insert: quickActions.insert,\n optimize: quickActions.optimize,\n setTier: quickActions.setTier,\n setInsertMode: quickActions.setInsertMode,\n addCategory: bookActions.addCategory,\n renameCategory: bookActions.renameCategory,\n removeCategory: bookActions.removeCategory,\n moveCategory: bookActions.moveCategory,\n addPrompt: bookActions.addPrompt,\n movePrompt: bookActions.movePromptToCategory,\n reloadBook: bookActions.reload,\n },\n }),\n }, QuickCommandsPanel))\n\n // \u8BBE\u7F6E\u9875\u6298\u53E0\u5361\u7247\u6837\u5F0F\uFF08\u5E38\u9A7B\uFF1B\u53EA\u7BA1\u8BBE\u7F6E\u9875\u5916\u89C2\uFF0C\u4E0E\u603B\u5F00\u5173\u65E0\u5173\uFF09\u3002\n ctx.effect(() => installSettingsCardStyle(), 'composer-ux: settings card style')\n\n // \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u5165\u53E3\u6309\u94AE\u6837\u5F0F\u8868\uFF08\u4E0E\u65C1\u8FB9\u5B98\u65B9\u300C\u5C55\u5F00\u300D\u6309\u94AE\u9010\u9879\u5BF9\u9F50\uFF09\u3002\n ctx.effect(() => installQuickButtonStyle(), 'composer-ux: quick button style')\n\n // \u8BBE\u7F6E\u9762\u677F\u5C3A\u5BF8\u624B\u67C4\u6837\u5F0F\uFF08\u5E38\u9A7B\uFF1B\u300C\u8BBE\u7F6E\u9762\u677F\u300D\u680F\u5173\u6389\u65F6\u624B\u67C4\u7EC4\u4EF6\u81EA\u5DF1\u8FD4\u56DE null\uFF0C\u6837\u5F0F\u7559\u7740\u65E0\u526F\u4F5C\u7528\uFF09\u3002\n // 0.6.0 \u8D77\u8FD9\u91CC\u53EA\u5269\u5C3A\u5BF8\u624B\u67C4\uFF1A\u5BFC\u822A\u5217\u6EDA\u52A8\u7531 DSH 0.1.7 \u7684\u5B98\u65B9\u8BBE\u7F6E\u9875\u81EA\u5E26\u3002\n ctx.effect(() => installPanelResizeStyle(), 'composer-ux: panel resize style')\n\n // \u952E\u4F4D\u62E6\u622A + \u53F3\u952E\u83DC\u5355\u6253\u5F00 + \u5B98\u65B9\u53D1\u9001\u6309\u94AE\u4E0A\u7684\u6761\u76EE\u9644\u52A0\uFF08\u4E09\u4EF6\u4E8B\u5171\u7528\u8FD9\u4E00\u7EC4\u6355\u83B7\u76D1\u542C\uFF09\u3002\n // \u5B89\u88C5\u6761\u4EF6\u653E\u5BBD\u6210\"\u4E09\u680F\u91CC\u4EFB\u610F\u4E00\u680F\u5F00\u7740\"\uFF0C\u5404\u81EA\u5728\u81EA\u5DF1\u7684\u5904\u7406\u51FD\u6570\u91CC\u6309\u680F\u5224\u65AD \u2014\u2014\n // \u514D\u5F97\u53EA\u5F00\u300C\u5FEB\u6377\u6307\u4EE4\u300D\u65F6\u8FDE\u5B98\u65B9\u53D1\u9001\u6309\u94AE\u90A3\u6761\u8DEF\u90FD\u4E0D\u88C5\uFF08\u90A3\u6837\u9644\u52A0\u5C31\u5931\u6548\u4E86\uFF09\u3002\n ctx.effect(() => {\n let dispose: (() => void) | null = null\n const syncInterceptors = (): void => {\n const settings = live.getSnapshot()\n const sections = activeSections(settings)\n const wanted = sections.keys || sections.menu || sections.quick\n if (wanted && dispose === null) {\n dispose = installInterceptors({\n settings: () => live.getSnapshot(),\n // \u300C\u4EC5\u9996\u6B21\u300D\u7531\u8FD9\u91CC\u51B3\u5B9A\u662F\u5426\u7B97\u8FDB\u8FD9\u4E00\u6279\uFF1A\u4F1A\u8BDD\u8FD8\u662F\u7A7A\u7684\uFF08blank\uFF09\u624D\u5E26\u4E0A\u3002\n // \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u680F\u5173\u6389\u65F6\u8FD9\u91CC\u76F4\u63A5\u7ED9\u7A7A\u6279\u6B21 \u2014\u2014 \u8FD9\u662F\u552F\u4E00\u4E00\u5904\"\u5173\u6389\u5C31\u4E0D\u9644\u52A0\"\u7684\u95F8\uFF0C\n // \u952E\u4F4D\u53D1\u9001\u4E0E\u5B98\u65B9\u6309\u94AE\u4E24\u6761\u8DEF\u90FD\u4ECE\u8FD9\u91CC\u53D6\u6279\u6B21\uFF0C\u4E0D\u9700\u8981\u5404\u5199\u4E00\u904D\u3002\n promptsForSend: () => (activeSections(live.getSnapshot()).quick\n ? appendBatchForSend(book.getSnapshot(), currentBlankSession())\n : []),\n setMenu: state => { menu.set(state) },\n menuOpen: () => menu.getSnapshot() !== null,\n })\n } else if (!wanted) {\n dispose?.()\n dispose = null\n }\n // \u53EA\u8981\u4E0D\u662F\u300C\u81EA\u5B9A\u4E49\u300D\u6863\uFF0C\u5C31\u6E05\u6389\u53EF\u80FD\u8FD8\u5F00\u7740\u7684\u81EA\u5B9A\u4E49\u83DC\u5355\uFF08\u5B98\u65B9 / \u6D4F\u89C8\u5668\u4E24\u6863\u90FD\u4E0D\u8BE5\u7559\u4E0B\u5B83\uFF09\u3002\n if (settings.menuMode !== 'custom' || !sections.menu) menu.set(null)\n // \u5FEB\u6377\u6307\u4EE4\u680F\u5173\u6389\u65F6\u6309\u94AE\u672C\u8EAB\u4E5F\u4F1A\u6D88\u5931\uFF08\u7EC4\u4EF6\u91CC\u6309\u5F00\u5173\u8FD4\u56DE null\uFF09\uFF0C\n // \u6D6E\u5C42\u5FC5\u987B\u8DDF\u7740\u4E00\u8D77\u6536\uFF0C\u5426\u5219\u4F1A\u7559\u4E0B\u4E00\u4E2A\u6CA1\u6709\u951A\u70B9\u7684\u9762\u677F\u3002\n if (!sections.quick) panel.set(null)\n }\n syncInterceptors()\n const unsubscribe = live.subscribe(syncInterceptors)\n return () => {\n unsubscribe()\n dispose?.()\n dispose = null\n }\n }, 'composer-ux: input interceptors')\n}\n", "/**\n * bash \u63A2\u6D4B\uFF08\u7EAF\u51FD\u6570\uFF0C\u96F6 import\uFF0Chost \u4E0E\u6D4B\u8BD5\u5171\u7528\uFF09\u3002\n *\n * \u4E3A\u4EC0\u4E48\u4E0D\u80FD\"\u626B PATH \u91CC\u7684 bash.exe \u5C31\u5B8C\u4E8B\"\uFF1A\n *\n * 1. **Windows \u4E0A `bash.exe` \u6709\u4E24\u4E2A\u6765\u6E90\uFF0C\u5176\u4E2D\u4E00\u4E2A\u5FC5\u987B\u6392\u9664\u3002**\n * `C:\\Windows\\System32\\bash.exe` \u4E0E `\u2026\\Microsoft\\WindowsApps\\bash.exe` \u662F WSL \u7684\n * \u542F\u52A8\u5668\u3002\u628A\u5B83\u4EA4\u7ED9\u6A21\u578B\uFF0C\u7B49\u4E8E\u628A Windows \u8DEF\u5F84\u4F53\u7CFB\u6362\u6389\uFF1A`D:\\a\\b` \u8981\u5199\u6210 `/mnt/d/a/b`\uFF0C\n * \u76D8\u7B26\u3001\u53CD\u659C\u6760\u3001`%TEMP%` \u5168\u90FD\u4E0D\u901A\uFF0C\u800C\u6A21\u578B\u624B\u91CC\u8FD8\u62FF\u7740 Windows \u98CE\u683C\u7684\u8DEF\u5F84\u4E0E\u5DE5\u4F5C\u76EE\u5F55\u3002\n * \u6240\u4EE5\u8FD9\u91CC\u662F**\u786C\u6392\u9664**\uFF08`isWslBash`\uFF09\uFF0C\u4E0D\u662F\"\u6392\u5E8F\u9760\u540E\"\u3002\n *\n * 2. **Git for Windows \u4E0D\u4E00\u5B9A\u88C5\u5728 Program Files\u3002** \u5B89\u88C5\u5668\u4EE5\u7BA1\u7406\u5458\u8FD0\u884C\u65F6\u9ED8\u8BA4\u843D\n * `C:\\Program Files\\Git`\uFF0C**\u4EE5\u666E\u901A\u7528\u6237\u8FD0\u884C\u65F6\u9ED8\u8BA4\u843D `%LOCALAPPDATA%\\Programs\\Git`**\uFF1B\n * \u8FD8\u6709 Scoop / Chocolatey / GitHub Desktop \u5185\u5D4C / \u81EA\u89E3\u538B PortableGit \u7B49\u6765\u6E90\u3002\n * \u672C\u673A\u5C31\u662F\u53CD\u4F8B\uFF1AGit \u88C5\u5728 `D:\\Git`\uFF08\u53EA\u6709\u56E0\u4E3A `D:\\Git\\cmd` \u5728 PATH \u4E0A\u624D\u88AB\u627E\u5230\uFF09\u3002\n * \u6240\u4EE5\u63A2\u6D4B\u662F**\u5148\u627E git\uFF0C\u518D\u7531\u540C\u4E00\u4E2A\u5B89\u88C5\u53CD\u63A8 bash**\uFF0C\u518D\u53E0\u52A0\u4E00\u4EFD\"\u5E38\u89C1\u6765\u6E90\"\u5019\u9009\u8868\u3002\n *\n * 3. **Niubash\uFF08\u725B bash\uFF0C`niu.exe`\uFF09\u662F\u5019\u9009\u800C\u4E0D\u662F\u9ED8\u8BA4\u3002** \u5B83\u7684\u547D\u4EE4\u96C6\uFF08winuxcmd\uFF09\u5BF9\n * \u975E ASCII \u53C2\u6570\u7684\u5904\u7406\u6709\u95EE\u9898\uFF08\u5B9E\u6D4B\uFF1A`grep <\u4E2D\u6587\u6587\u4EF6\u540D>` \u76F4\u63A5 `cannot open` \u5E76\u4EE5\n * `0xC0000409` \u9000\u51FA\uFF09\uFF0C\u6240\u4EE5\u6392\u5728\u771F Git Bash \u4E4B\u540E\uFF0C\u4F46\u4ECD\u7136\u5217\u51FA\u6765 \u2014\u2014 \u7528\u6237\u53EF\u80FD\u7279\u610F\u9009\u4E86\u5B83\u3002\n *\n * \u8986\u76D6\u7684\u6765\u6E90\uFF08\u987A\u5E8F\u5373\u4F18\u5148\u7EA7\uFF0C\u540C\u7C7B\u5185\u4FDD\u6301\u8FD9\u91CC\u7684\u5148\u540E\uFF09\uFF1A\n * \u663E\u5F0F\u8DEF\u5F84 \u2192 PATH \u4E0A\u7684 git \u53CD\u63A8 \u2192 Program Files / x86 / W6432 / `%LOCALAPPDATA%\\Programs`\n * \u2192 Scoop \u2192 Chocolatey \u4FBF\u643A\u5305 \u2192 GitHub Desktop \u5185\u5D4C \u2192 \u65E7 GitHub \u7684 PortableGit\n * \u2192 Visual Studio \u5185\u5D4C \u2192 MSYS2 \u2192 Cygwin \u2192 **\u5404\u76D8\u7B26\u6839\u4E0B\u7684 Git / PortableGit / msys64 / cygwin64**\n * \u2192 Niubash \u2192 PATH \u515C\u5E95\u3002\n *\n * \u5E26\u7248\u672C\u53F7\u7684\u6765\u6E90\uFF08GitHub Desktop \u7684 `app-*`\u3001\u65E7 GitHub \u7684 `PortableGit_*`\u3001VS \u7684\n * `<\u5E74\u4EFD>\\<\u7248\u672C>`\uFF09\u9700\u8981\"\u5217\u4E00\u773C\u5B50\u76EE\u5F55\"\uFF0C\u6240\u4EE5\u8F93\u5165\u91CC\u591A\u4E86\u4E00\u4E2A\u53EF\u6CE8\u5165\u7684 `listDirs`\uFF1B\n * **\u4E0D\u6CE8\u5165\u5C31\u9000\u5316\u6210\u7EAF\u5B58\u5728\u6027\u68C0\u67E5**\uFF08\u4E0D\u8BFB\u76EE\u5F55\uFF09\u3002\u5168\u7A0B\u4E0D\u8FD0\u884C\u4EFB\u4F55\u8FDB\u7A0B\uFF1A\u7248\u672C\u63A2\u6D4B\u5C5E\u4E8E\u5BBF\u4E3B\u534A\u3002\n */\n\n/** \u5019\u9009\u7684\u79CD\u7C7B\uFF08\u51B3\u5B9A\u6392\u5E8F\u6743\u91CD\u4E0E\u9ED8\u8BA4\u6807\u7B7E\uFF09\u3002 */\nexport type BashKind = 'git' | 'msys2' | 'cygwin' | 'niubash' | 'path'\n\n/** \u4E00\u4E2A\u5019\u9009 shell\u3002 */\nexport interface BashCandidate {\n /** \u5F52\u4E00\u5316\u540E\u7684\u7EDD\u5BF9\u8DEF\u5F84\uFF08\u6B63\u659C\u6760\uFF09\uFF0C\u53EF\u76F4\u63A5\u843D\u76D8\u4E0E\u56DE\u663E\u3002 */\n readonly path: string\n readonly kind: BashKind\n /** \u7ED9\u7528\u6237\u770B\u7684\u6765\u6E90\u6807\u7B7E\uFF08\u5177\u4F53\u6765\u6E90\u4F18\u5148\uFF0C\u4F8B\u5982 'Scoop \u7684 git'\uFF0C\u5426\u5219\u7528\u79CD\u7C7B\u6807\u7B7E\uFF09\u3002 */\n readonly label: string\n /** \u662F\u5426\u662F\u7528\u6237\u5728\u8BBE\u7F6E\u91CC\u663E\u5F0F\u6307\u5B9A\u7684\uFF08\u754C\u9762\u6807\u6CE8\u300C\u4F60\u6307\u5B9A\u7684\u300D\uFF0C\u4E14\u6392\u5E8F\u6C38\u8FDC\u5728\u6700\u524D\uFF09\u3002 */\n readonly explicit: boolean\n}\n\n/** \u88AB\u786C\u6392\u9664\u7684\u8DEF\u5F84\u53CA\u539F\u56E0\uFF08\u8BBE\u7F6E\u9875\u8981\u5982\u5B9E\u8BF4\u660E\"\u4E3A\u4EC0\u4E48\u4E0D\u9009\u5B83\"\uFF09\u3002 */\nexport interface ExcludedPath {\n readonly path: string\n readonly reason: string\n}\n\n/** \u663E\u5F0F\u8DEF\u5F84\uFF08\u8BBE\u7F6E\u91CC\u586B\u7684\uFF09\u7684\u72B6\u6001\u3002 */\nexport interface ExplicitState {\n readonly path: string\n readonly state: 'ok' | 'missing' | 'wsl'\n}\n\n/** \u63A2\u6D4B\u7684\u8F93\u5165\uFF08\u5168\u90E8\u53EF\u6CE8\u5165\uFF0C\u6D4B\u8BD5\u91CC\u7ED9\u5047\u5B9E\u73B0\u5373\u53EF\uFF09\u3002 */\nexport interface DiscoverInput {\n /** \u8DEF\u5F84\u662F\u5426\u5B58\u5728\u3002 */\n readonly exists: (path: string) => boolean\n /** \u6309\u987A\u5E8F\u7684 PATH \u6761\u76EE\uFF08\u672A\u6E05\u6D17\uFF09\u3002 */\n readonly pathEntries: readonly string[]\n /** \u73AF\u5883\u53D8\u91CF\u53D6\u503C\u3002 */\n readonly env: (name: string) => string | undefined\n /** \u8BBE\u7F6E\u91CC\u663E\u5F0F\u586B\u7684 bash \u8DEF\u5F84\uFF08\u53EF\u7A7A\uFF09\u3002 */\n readonly explicitPath?: string\n /**\n * \u5217\u51FA\u67D0\u4E2A\u76EE\u5F55\u4E0B\u7684**\u5B50\u76EE\u5F55\u540D**\uFF08\u53EA\u7528\u4E8E\u5E26\u7248\u672C\u53F7\u7684\u6765\u6E90\uFF1AGitHub Desktop / \u65E7 GitHub / VS\uFF09\u3002\n * \u4E0D\u6CE8\u5165\u3001\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u6CA1\u6709\u6743\u9650\u65F6\u90FD\u5F53\u4F5C\"\u7A7A\"\uFF0C\u63A2\u6D4B\u9000\u5316\u6210\u7EAF\u5B58\u5728\u6027\u68C0\u67E5\u3002\n */\n readonly listDirs?: (parent: string) => readonly string[]\n}\n\n/** \u63A2\u6D4B\u7ED3\u679C\u3002 */\nexport interface DiscoverResult {\n /** \u6309\u4F18\u5148\u7EA7\u6392\u597D\u5E8F\u3001\u5DF2\u53BB\u91CD\u3001\u5DF2\u5254\u9664 WSL \u7684\u5019\u9009\u3002 */\n readonly candidates: readonly BashCandidate[]\n /** \u88AB\u786C\u6392\u9664\u7684\u8DEF\u5F84\uFF08\u5F53\u524D\u53EA\u6709 WSL\uFF09\u3002 */\n readonly excluded: readonly ExcludedPath[]\n /** \u663E\u5F0F\u8DEF\u5F84\u7684\u72B6\u6001\uFF1B\u6CA1\u586B\u5C31\u662F undefined\u3002 */\n readonly explicit?: ExplicitState\n}\n\n/** WSL \u6392\u9664\u539F\u56E0\uFF08\u8BBE\u7F6E\u9875\u76F4\u63A5\u5C55\u793A\u8FD9\u53E5\u8BDD\uFF09\u3002 */\nexport const WSL_REASON = 'WSL \u7684 bash\uFF1A\u5B83\u6309 Linux \u89C4\u5219\u89E3\u91CA\u8DEF\u5F84\uFF08D:\\\\x \u8981\u5199\u6210 /mnt/d/x\uFF09\uFF0C'\n + '\u4E0E\u6A21\u578B\u624B\u91CC\u7684 Windows \u5DE5\u4F5C\u76EE\u5F55\u4E0D\u517C\u5BB9\uFF0C\u6545\u4E0D\u91C7\u7528'\n\n/** \u5F52\u4E00\u5316\uFF1A\u53CD\u659C\u6760\u8F6C\u6B63\u659C\u6760\u3001\u53BB\u6389\u5305\u88F9\u5F15\u53F7\u4E0E\u7ED3\u5C3E\u659C\u6760\u3001\u5408\u5E76\u91CD\u590D\u5206\u9694\u7B26\u3002 */\nexport function normalizePath(value: string): string {\n const trimmed = value.trim().replace(/^\"|\"$/g, '')\n const slashed = trimmed.replace(/\\\\/g, '/').replace(/\\/{2,}/g, '/')\n return slashed.length > 1 ? slashed.replace(/\\/+$/, '') : slashed\n}\n\n/** \u662F\u5426 WSL \u7684 bash\uFF08System32 \u7684\u542F\u52A8\u5668\u4E0E WindowsApps \u7684\u522B\u540D\uFF09\u3002 */\nexport function isWslBash(value: string): boolean {\n const path = normalizePath(value).toLowerCase()\n return /\\/windows\\/system32\\/bash\\.exe$/.test(path) || /\\/windowsapps\\/bash\\.exe$/.test(path)\n}\n\n/** \u6309\u8DEF\u5F84\u5F62\u6001\u5224\u65AD\u79CD\u7C7B\uFF08\u663E\u5F0F\u8DEF\u5F84\u4E5F\u80FD\u56E0\u6B64\u62FF\u5230\u6B63\u786E\u7684\u6807\u7B7E\u4E0E\u4F18\u5148\u7EA7\uFF09\u3002 */\nexport function candidateKindOf(value: string): BashKind {\n const path = normalizePath(value).toLowerCase()\n if (path.endsWith('/niu.exe') || path.includes('/niubash/')) return 'niubash'\n if (path.includes('/msys64/') || path.includes('/msys32/') || path.includes('/msys2/')) return 'msys2'\n if (path.includes('/cygwin')) return 'cygwin'\n // `PortableGit` \u4E5F\u7B97 git\uFF08\u6B63\u5219\u91CC\u628A\u53EF\u9009\u524D\u7F00\u5199\u4E0A\uFF09\uFF0C\u53EA\u662F\u6807\u7B7E\u4E0D\u540C\u3002\n if (/(^|\\/)(portable)?git(\\/|$)/.test(path)) return 'git'\n return 'path'\n}\n\n/** \u79CD\u7C7B \u2192 \u754C\u9762\u6807\u7B7E\uFF08\u5177\u4F53\u6765\u6E90\u6CA1\u7ED9\u65F6\u7528\u5B83\uFF09\u3002 */\nexport function kindLabel(kind: BashKind): string {\n switch (kind) {\n case 'git': return 'Git for Windows'\n case 'msys2': return 'MSYS2'\n case 'cygwin': return 'Cygwin'\n case 'niubash': return 'Niubash\uFF08\u725B bash\uFF09'\n default: return 'PATH'\n }\n}\n\n/** \u79CD\u7C7B\u6392\u5E8F\u6743\u91CD\uFF08\u6570\u5B57\u8D8A\u5C0F\u8D8A\u4F18\u5148\uFF09\uFF1Bniubash \u4F4E\u4E8E MSYS2/Cygwin\uFF0C\u9AD8\u4E8E\u6742\u9879 PATH\u3002 */\nconst KIND_RANK: Record<BashKind, number> = { git: 0, msys2: 1, cygwin: 2, niubash: 3, path: 4 }\n\n/** \u76D8\u7B26\u626B\u63CF\u7684\u5B57\u6BCD\uFF08\u8DF3\u8FC7 A:/B: \u8F6F\u9A71\u4F4D\uFF09\u3002 */\nconst DRIVE_LETTERS = 'CDEFGHIJKLMNOPQRSTUVWXYZ'\n\n/** \u4ECE PATH \u6761\u76EE\u91CC\u8BA4\u51FA git \u5B89\u88C5\u6839\uFF08`<root>\\cmd` / `<root>\\bin` / `<root>\\mingw64\\bin` \u90FD\u5F52\u5230 root\uFF09\u3002 */\nfunction gitRootOf(entry: string): string | undefined {\n const path = normalizePath(entry)\n if (path === '') return undefined\n const lower = path.toLowerCase()\n for (const suffix of ['/mingw64/bin', '/mingw32/bin', '/usr/bin', '/cmd', '/bin']) {\n if (lower.endsWith(suffix)) return path.slice(0, path.length - suffix.length)\n }\n return path\n}\n\n/** \u4E00\u4E2A\u5B89\u88C5\u6839\u4E0B\u6240\u6709\u53EF\u80FD\u7684 bash \u4F4D\u7F6E\uFF08\u987A\u5E8F\u5373\u4F18\u5148\u7EA7\uFF09\u3002 */\nfunction bashPathsUnder(root: string): readonly string[] {\n return [`${root}/bin/bash.exe`, `${root}/usr/bin/bash.exe`, `${root}/mingw64/bin/bash.exe`]\n}\n\n/**\n * `usr/bin` / `mingw64/bin` \u4E0B\u7684 bash \u662F**\u88F8\u672C\u4F53**\uFF1A\u76F4\u63A5\u8DD1\u5B83\u4E0D\u4F1A\u51C6\u5907 MSYS \u73AF\u5883\u3002\n *\n * \u672C\u673A\u5B9E\u6D4B\uFF08`D:\\Git` \u4E24\u4E2A\u90FD\u8DD1\u4E86\u4E00\u904D\uFF09\uFF1A`bin\\bash.exe` \u7ED9\u51FA `MSYSTEM=MINGW64`\u3001\n * `PATH` \u524D\u7F6E `/mingw64/bin:/usr/bin`\uFF0C`head` / `grep` / `uname` \u90FD\u5728\uFF08\u4E2D\u6587\u6587\u4EF6\u540D\u5F53\u53C2\u6570\u4E5F\u6B63\u5E38\uFF09\uFF1B\n * \u800C `usr\\bin\\bash.exe` \u7684 `MSYSTEM` \u4E3A\u7A7A\u3001`PATH` \u53EA\u6709\u7EE7\u627F\u6765\u7684 Windows PATH\uFF08\u91CC\u9762\u53EA\u6709 `D:\\Git\\cmd`\uFF09\uFF0C\n * \u4E8E\u662F `head` / `grep` / `uname` **\u5168\u90E8 command not found** \u2014\u2014 \u4EA4\u7ED9\u6A21\u578B\u5C31\u662F\u5927\u9762\u79EF\u5931\u8D25\u3002\n *\n * \u6240\u4EE5\uFF1A\u540C\u4E00\u4E2A\u6839\u4E0B\u53EA\u8981\u6709 `bin/bash.exe`\uFF0C\u5C31\u4E0D\u518D\u5217\u8FD9\u4E2A\u88F8\u672C\u4F53\uFF08\u7528\u6237\u4ECD\u53EF\u624B\u586B\uFF09\u3002\n * \u6CA1\u6709 `bin/bash.exe` \u5144\u5F1F\u7684\uFF08\u4F8B\u5982 MSYS2 \u53EA\u63D0\u4F9B `usr\\bin\\bash.exe`\uFF09\u7167\u5E38\u5217\u51FA\u3002\n * @param value \u5019\u9009\u8DEF\u5F84\u3002\n * @returns \u5B89\u88C5\u6839\uFF1B\u4E0D\u662F\u88F8\u672C\u4F53\u65F6 undefined\u3002\n */\nexport function unpreparedBashRoot(value: string): string | undefined {\n const match = /^(.*)\\/(usr|mingw32|mingw64)\\/bin\\/bash\\.exe$/i.exec(normalizePath(value))\n return match?.[1]\n}\n\n/** \u4E00\u4E2A\u5019\u9009\u6765\u6E90\uFF1A\u4E00\u7EC4\u5B89\u88C5\u6839 + \u53EF\u9009\u7684\u5177\u4F53\u6807\u7B7E\u3002 */\ninterface SourceGroup {\n readonly roots: readonly string[]\n readonly label?: string\n}\n\n/**\n * \u63A2\u6D4B\u5019\u9009 bash\u3002\n * @param input \u6CE8\u5165\u7684 exists/PATH/\u73AF\u5883\u53D8\u91CF\uFF0C\u4EE5\u53CA\u53EF\u9009\u7684 listDirs\uFF08\u5217\u5B50\u76EE\u5F55\uFF09\u3002\n * @returns \u5019\u9009\u3001\u88AB\u6392\u9664\u7684\u8DEF\u5F84\u3001\u663E\u5F0F\u8DEF\u5F84\u72B6\u6001\u3002\n */\nexport function discoverBashCandidates(input: DiscoverInput): DiscoverResult {\n const seen = new Set<string>()\n const excluded: ExcludedPath[] = []\n const ordered: BashCandidate[] = []\n\n /** \u5217\u5B50\u76EE\u5F55\uFF1B\u6CA1\u6709\u6CE8\u5165\u3001\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u6CA1\u6743\u9650\u90FD\u5F53\u7A7A\u3002 */\n const dirsOf = (parent: string): readonly string[] => {\n if (input.listDirs === undefined) return []\n try {\n return input.listDirs(parent)\n } catch {\n return []\n }\n }\n\n /** \u8BB0\u4E00\u4E2A\u5019\u9009\uFF1BWSL \u4E00\u5F8B\u8F6C\u6210\u6392\u9664\u9879\uFF0C\u91CD\u590D\u8DEF\u5F84\u53EA\u7559\u7B2C\u4E00\u6B21\uFF08\u5373\u4F18\u5148\u7EA7\u6700\u9AD8\u7684\u90A3\u4E00\u6B21\uFF09\u3002 */\n const consider = (raw: string, label?: string, isExplicit = false): void => {\n const path = normalizePath(raw)\n if (path === '') return\n if (isWslBash(path)) {\n // \u53EA\u5728\u5B83**\u786E\u5B9E\u5B58\u5728**\u65F6\u62A5\"\u5DF2\u6392\u9664\"\uFF1A\u5426\u5219\u6BCF\u53F0\u673A\u5668\u90FD\u4F1A\u51ED\u7A7A\u591A\u51FA\u4E00\u6761 WSL \u8B66\u544A\u3002\n if (!input.exists(path)) return\n if (!excluded.some(item => item.path.toLowerCase() === path.toLowerCase())) {\n excluded.push({ path, reason: WSL_REASON })\n }\n return\n }\n // \u88F8\u672C\u4F53\uFF08usr/bin\u3001mingw64/bin\uFF09\uFF1A\u540C\u6839\u4E0B\u5DF2\u6709\u4F1A\u51C6\u5907\u73AF\u5883\u7684 `bin/bash.exe` \u65F6\u4E0D\u518D\u4F5C\u4E3A\u5019\u9009\uFF0C\n // \u514D\u5F97\u7528\u6237\u70B9\u5230\u4E00\u4E2A\"\u547D\u4EE4\u5168\u627E\u4E0D\u5230\"\u7684 shell\u3002**\u663E\u5F0F\u8DEF\u5F84\u4E0D\u53D7\u6B64\u9650**\uFF1A\u90A3\u662F\u7528\u6237\u81EA\u5DF1\u7684\u9009\u62E9\u3002\n if (!isExplicit) {\n const root = unpreparedBashRoot(path)\n if (root !== undefined && input.exists(`${root}/bin/bash.exe`)) return\n }\n const key = path.toLowerCase()\n if (seen.has(key)) return\n if (!input.exists(path)) return\n seen.add(key)\n const kind = candidateKindOf(path)\n ordered.push({ path, kind, label: label ?? kindLabel(kind), explicit: isExplicit })\n }\n\n /** \u4E00\u7EC4\u6765\u6E90\uFF1A\u53EA\u8BD5\u5B58\u5728\u7684\u5B89\u88C5\u6839\uFF0C\u518D\u628A\u8BE5\u6839\u4E0B\u6240\u6709\u53EF\u80FD\u7684 bash \u4F4D\u7F6E\u4E22\u7ED9 consider\u3002 */\n const addGroup = (group: SourceGroup): void => {\n for (const root of group.roots) {\n if (root === '' || !input.exists(root)) continue\n for (const path of bashPathsUnder(root)) consider(path, group.label)\n }\n }\n\n // 1) \u663E\u5F0F\u8DEF\u5F84\uFF1A\u7528\u6237\u81EA\u5DF1\u586B\u7684\uFF0C\u4F18\u5148\u7EA7\u6700\u9AD8\uFF08\u586B\u9519\u4E5F\u4F1A\u5982\u5B9E\u62A5\u544A\uFF09\u3002\n const explicitRaw = normalizePath(input.explicitPath ?? '')\n let explicit: ExplicitState | undefined\n if (explicitRaw !== '') {\n if (isWslBash(explicitRaw)) {\n explicit = { path: explicitRaw, state: 'wsl' }\n // \u7528\u6237\u660E\u786E\u586B\u4E86 WSL\uFF1A\u8981\u8BA9\u4ED6\u770B\u5230\"\u4E3A\u4EC0\u4E48\u4E0D\u91C7\u7528\"\uFF0C\u800C\u4E0D\u662F\u770B\u5230\u5019\u9009\u91CC\u6084\u6084\u5C11\u4E86\u4E00\u6761\u3002\n if (input.exists(explicitRaw)) excluded.push({ path: explicitRaw, reason: WSL_REASON })\n } else if (input.exists(explicitRaw)) explicit = { path: explicitRaw, state: 'ok' }\n else explicit = { path: explicitRaw, state: 'missing' }\n }\n\n const entries = input.pathEntries\n .map(entry => normalizePath(entry))\n .filter(entry => entry !== '')\n const env = (name: string): string | undefined => {\n const value = input.env(name)\n return value === undefined || value === '' ? undefined : normalizePath(value)\n }\n\n const programFiles = env('ProgramFiles') ?? 'C:/Program Files'\n const programFilesX86 = env('ProgramFiles(x86)') ?? 'C:/Program Files (x86)'\n const programW6432 = env('ProgramW6432')\n const localAppData = env('LOCALAPPDATA')\n const home = env('USERPROFILE') ?? env('HOME')\n const scoop = env('SCOOP') ?? (home === undefined ? undefined : `${home}/scoop`)\n const choco = env('ChocolateyInstall')\n ?? (env('ProgramData') === undefined ? 'C:/ProgramData/chocolatey' : `${env('ProgramData') as string}/chocolatey`)\n\n // \u5E26\u7248\u672C\u53F7\u7684\u6765\u6E90\uFF1A\u5217\u4E00\u773C\u5B50\u76EE\u5F55\uFF0C\u6309\u540D\u5B57**\u5012\u5E8F**\uFF08`app-3.4.3` \u8FD9\u79CD\u540D\u5B57\uFF0C\u65B0\u7684\u6392\u5728\u524D\u9762\uFF09\u3002\n const versioned: string[] = []\n if (localAppData !== undefined) {\n const desktop = `${localAppData}/GitHubDesktop`\n for (const dir of [...dirsOf(desktop)].sort().reverse()) {\n if (dir.startsWith('app-')) versioned.push(`${desktop}/${dir}/resources/app/git`)\n }\n const github = `${localAppData}/GitHub`\n for (const dir of [...dirsOf(github)].sort().reverse()) {\n if (dir.startsWith('PortableGit')) versioned.push(`${github}/${dir}`)\n }\n }\n const vsRoot = `${programFiles}/Microsoft Visual Studio`\n for (const year of dirsOf(vsRoot)) {\n const yearRoot = `${vsRoot}/${year}`\n for (const edition of dirsOf(yearRoot)) {\n versioned.push(`${yearRoot}/${edition}/Common7/IDE/CommonExtensions/Microsoft/TeamFoundation/Team Explorer/Git`)\n }\n }\n\n // \u5404\u76D8\u7B26\u6839\u4E0B\u7684\u5E38\u89C1\u540D\u5B57\uFF1A\u8986\u76D6\"\u88C5\u5728 D:\\Git / D:\\PortableGit / \u81EA\u5DF1\u89E3\u538B\"\u7684\u60C5\u51B5\u3002\n const drives: string[] = []\n for (const letter of DRIVE_LETTERS) {\n const root = `${letter}:`\n if (input.exists(`${root}/`)) drives.push(root)\n }\n const driveRoots = (names: readonly string[]): readonly string[] =>\n drives.flatMap(root => names.map(name => `${root}/${name}`))\n\n const groups: readonly SourceGroup[] = [\n // 2) PATH \u4E0A\u8BA4\u51FA\u6765\u7684 git \u6839 \u2014\u2014 \u90A3\u624D\u662F\u7528\u6237\u5B9E\u9645\u5728\u7528\u7684\u90A3\u4EFD\u3002\n ...entries.map(entry => gitRootOf(entry))\n .filter((root): root is string => root !== undefined)\n .map(root => ({ roots: [root] })),\n // 3) \u5B98\u65B9\u5B89\u88C5\u5668\u7684\u4E24\u4E2A\u9ED8\u8BA4\u843D\u70B9 + 32 \u4F4D / \u91CD\u5B9A\u5411\u540E\u7684 Program Files\u3002\n { roots: [programFiles, programFilesX86, programW6432, localAppData === undefined ? undefined : `${localAppData}/Programs`]\n .filter((base): base is string => base !== undefined)\n .map(base => `${base}/Git`) },\n // 4) Scoop\uFF08`scoop install git` \u4F1A\u5E26\u4E00\u4EFD bash\uFF09\u3002\n ...(scoop === undefined ? [] : [{ roots: [`${scoop}/apps/git/current`, `${scoop}/apps/git`], label: 'Scoop \u7684 git' }]),\n // 5) Chocolatey \u7684\u4FBF\u643A\u5305\uFF08`git.install` \u88C5\u7684\u4ECD\u5728 Program Files\uFF0C\u4E0A\u9762\u90A3\u6761\u5DF2\u8986\u76D6\uFF09\u3002\n { roots: [`${choco}/lib/git.portable/tools`, `${choco}/lib/git.portable/tools/git`], label: 'Chocolatey \u4FBF\u643A\u5305' },\n // 6) GitHub Desktop / \u65E7 GitHub for Windows / Visual Studio \u81EA\u5E26\uFF08\u90FD\u5E26\u7248\u672C\u53F7\uFF0C\u9760 listDirs\uFF09\u3002\n { roots: versioned.filter(path => path.includes('GitHubDesktop')), label: 'GitHub Desktop \u5185\u5D4C' },\n { roots: versioned.filter(path => path.includes('/GitHub/PortableGit')), label: 'GitHub PortableGit' },\n { roots: versioned.filter(path => path.includes('/Microsoft Visual Studio/')), label: 'Visual Studio \u5185\u5D4C' },\n // 7) MSYS2 / Cygwin \u7684\u5E38\u89C1\u4F4D\u7F6E\uFF08\u542B\u5404\u76D8\u7B26\u6839\u4E0B\u7684\u540C\u540D\u76EE\u5F55\uFF09\u3002\n { roots: [`${programFiles}/msys64`, 'C:/msys64', ...driveRoots(['msys64'])], label: 'MSYS2' },\n { roots: [`${programFiles}/cygwin64`, 'C:/cygwin64', 'C:/cygwin', ...driveRoots(['cygwin64', 'cygwin'])], label: 'Cygwin' },\n // 8) \u5404\u76D8\u7B26\u6839\u4E0B\u7684 Git / PortableGit\uFF08\u88C5\u5728 D:\\Git\u3001D:\\PortableGit \u8FD9\u7C7B\uFF09\u3002\n { roots: driveRoots(['Git', 'Program Files/Git', 'Program Files (x86)/Git']), label: 'Git for Windows' },\n { roots: driveRoots(['PortableGit']), label: 'PortableGit\uFF08\u81EA\u89E3\u538B\uFF09' },\n ]\n for (const group of groups) addGroup(group)\n\n // 9) Niubash\uFF08\u7528\u6237\u53EF\u80FD\u7279\u610F\u88C5\u7684 bash \u517C\u5BB9\u73AF\u5883\uFF09\u3002\u5B83\u7684\u53EF\u6267\u884C\u6587\u4EF6\u53EB `niu.exe` \u4E14\u5C31\u5728\u6839\u76EE\u5F55\uFF0C\n // \u4E0D\u7B26\u5408\"\u5B89\u88C5\u6839 / bin|usr/bin|mingw64/bin\"\u7684\u5F62\u72B6\uFF0C\u6240\u4EE5\u5355\u72EC\u8003\u8651\uFF0C\u4E0D\u80FD\u585E\u8FDB\u5206\u7EC4\u3002\n if (localAppData !== undefined) consider(`${localAppData}/Programs/Niubash/niu.exe`, 'Niubash\uFF08\u725B bash\uFF09')\n\n // 10) PATH \u515C\u5E95\uFF1A\u6700\u5BB9\u6613\u547D\u4E2D\u7684\u662F WSL\uFF0C\u9760 consider() \u91CC\u7684 isWslBash \u62E6\u6389\u3002\n for (const entry of entries) consider(`${entry}/bash.exe`)\n\n // \u663E\u5F0F\u8DEF\u5F84\u4E5F\u4EA4\u7ED9 consider \u53C2\u4E0E\u53BB\u91CD\uFF1B\u5B83\u9760 `explicit` \u6807\u8BB0\u5728\u6392\u5E8F\u91CC\u62FF\u7B2C\u4E00\uFF0C\n // \u800C\u4E0D\u662F\u9760\u5728\u6570\u7EC4\u91CC\u63D2\u961F \u2014\u2014 \u5426\u5219\u540C\u4E00\u6761\u8DEF\u5F84\u53EF\u80FD\u51FA\u73B0\u4E24\u6B21\u3002\n if (explicit?.state === 'ok') consider(explicit.path, undefined, true)\n\n // \u6392\u5E8F\uFF1A\u663E\u5F0F\u4F18\u5148 \u2192 \u79CD\u7C7B\u6743\u91CD \u2192 \u540C\u4E00\u7EC4\u5185\u4FDD\u6301\u4E0A\u9762\u7684\u641C\u7D22\u5148\u540E\u3002\n const ranked = ordered\n .map((candidate, index) => ({ candidate, index }))\n .sort((a, b) => {\n if (a.candidate.explicit !== b.candidate.explicit) return a.candidate.explicit ? -1 : 1\n const rank = KIND_RANK[a.candidate.kind] - KIND_RANK[b.candidate.kind]\n return rank !== 0 ? rank : a.index - b.index\n })\n .map(item => item.candidate)\n\n return {\n candidates: ranked,\n excluded,\n ...(explicit === undefined ? {} : { explicit }),\n }\n}\n\n/**\n * \u9ED8\u8BA4\u9009\u8C01\uFF1A\u5019\u9009\u8868\u91CC\u7684\u7B2C\u4E00\u4E2A\uFF08\u63A2\u6D4B\u987A\u5E8F\u5DF2\u7ECF\u628A\"\u663E\u5F0F\u8DEF\u5F84 \u2192 \u771F Git Bash \u2192 \u5176\u5B83\"\u6392\u597D\u4E86\uFF09\u3002\n * @param result \u63A2\u6D4B\u7ED3\u679C\u3002\n * @returns \u8DEF\u5F84\uFF1B\u4E00\u4E2A\u5019\u9009\u90FD\u6CA1\u6709\u65F6\u8FD4\u56DE\u7A7A\u4E32\u3002\n */\nexport function defaultBashPath(result: DiscoverResult): string {\n return result.candidates[0]?.path ?? ''\n}\n", "/**\n * \u300C\u9ED8\u8BA4\u7EC8\u7AEF\u300D\u7684\u516C\u5171\u5951\u7EA6\uFF1A\u8BBE\u7F6E\u5B57\u6BB5\u3001\u4E09\u6863\u5143\u6570\u636E\u3001\u5019\u9009\u5F62\u72B6\u3001\u51C0\u5316\u4E0E\"\u6700\u7EC8\u7528\u8C01\"\u7684\u5224\u5B9A\u3002\n *\n * \u96F6 import\uFF08host \u4E0E client \u4E24\u534A\u5171\u7528\uFF0C\u8DE8\u7AEF\u4E0D\u5171\u4EAB\u4EFB\u4F55\u8FD0\u884C\u65F6\u8EAB\u4EFD\uFF09\u3002\n *\n * \u8FD9\u91CC\u7684\u5B57\u6BB5\u5206\u4E24\u7C7B\uFF0C**\u4E0D\u8981\u6DF7**\uFF1A\n * - \u7528\u6237\u914D\u7F6E\uFF1A`terminalMode` / `terminalBashPath` \u2014\u2014 \u7531\u8BBE\u7F6E\u9875\u5199\uFF0C\u5BBF\u4E3B\u534A\u8BFB\uFF1B\n * - \u5BBF\u4E3B\u534A\u81EA\u6301\uFF1A`terminalCandidates` / `terminalStatus` / `terminalEffective` \u2014\u2014\n * \u53EA\u7531\u5BBF\u4E3B\u534A\u5199\uFF08\u63A2\u6D4B\u7ED3\u679C\u4E0E\u8FD0\u884C\u72B6\u6001\uFF09\uFF0C\u8BBE\u7F6E\u9875\u53EA\u8BFB\u5C55\u793A\uFF1B\u300C\u6062\u590D\u9ED8\u8BA4\u300D\u4E0D\u5F97\u6E05\u7A7A\u5B83\u4EEC\n * \uFF08\u89C1 settings-contract \u7684 HOST_OWNED_FIELDS\uFF09\uFF0C\u5426\u5219\u754C\u9762\u4F1A\u5931\u53BB\u63A2\u6D4B\u7ED3\u679C\u4E0E\u72B6\u6001\u3002\n */\nimport type { BashCandidate, BashKind, DiscoverResult, ExplicitState } from './discover.ts'\nimport { defaultBashPath, discoverBashCandidates, normalizePath } from './discover.ts'\n\n/** \u7528\u6237\u914D\u7F6E\u5B57\u6BB5\uFF1A\u7EC8\u7AEF\u6863\u4F4D\u3002 */\nexport const TERMINAL_MODE_FIELD = 'terminalMode'\n\n/** \u7528\u6237\u914D\u7F6E\u5B57\u6BB5\uFF1AGit Bash \u8DEF\u5F84\uFF08\u7559\u7A7A = \u7528\u63A2\u6D4B\u5230\u7684\u7B2C\u4E00\u4E2A\u5019\u9009\uFF09\u3002 */\nexport const TERMINAL_BASH_PATH_FIELD = 'terminalBashPath'\n\n/** \u5BBF\u4E3B\u534A\u81EA\u6301\uFF1A\u63A2\u6D4B\u5230\u7684\u5019\u9009\u5217\u8868\u3002 */\nexport const TERMINAL_CANDIDATES_FIELD = 'terminalCandidates'\n\n/** \u5BBF\u4E3B\u534A\u81EA\u6301\uFF1A\u72B6\u6001\u884C\uFF08\u5F53\u524D\u751F\u6548 shell / \u4E3A\u4EC0\u4E48\u6CA1\u751F\u6548\uFF09\u3002 */\nexport const TERMINAL_STATUS_FIELD = 'terminalStatus'\n\n/** \u5BBF\u4E3B\u534A\u81EA\u6301\uFF1A\u5F53\u524D\u5B9E\u9645\u751F\u6548\u7684 shell\uFF08'bash' / 'pwsh'\uFF09\u3002 */\nexport const TERMINAL_EFFECTIVE_FIELD = 'terminalEffective'\n\n/** \u5BBF\u4E3B\u534A\u6CE8\u518C\u7684\u72B6\u6001/\u53D1\u73B0\u63A5\u53E3\u8DEF\u5F84\uFF08\u5BA2\u6237\u7AEF\u534A\u8BFB\u5199\uFF09\u3002 */\nexport const TERMINAL_API_PATH = '/composer-ux/terminal'\n\n/** \u6863\u4F4D\u3002 */\nexport type TerminalMode = 'auto' | 'gitbash' | 'pwsh'\n\n/** \u4E09\u6863\u5143\u6570\u636E\uFF08\u6570\u7EC4\u987A\u5E8F\u5373\u754C\u9762\u987A\u5E8F\uFF09\u3002 */\nexport const TERMINAL_MODES: readonly {\n readonly id: TerminalMode\n readonly label: string\n readonly hint: string\n}[] = [\n {\n id: 'auto',\n label: '\u81EA\u52A8',\n hint: '\u63A2\u6D4B\u5230 Git Bash \u5C31\u7528\u5B83\uFF08\u627E\u4E0D\u5230\u5219\u4FDD\u6301 PowerShell\uFF09\uFF1B\u5F00\u7BB1\u5373\u7528\uFF0C\u4E0D\u7528\u624B\u586B\u8DEF\u5F84',\n },\n {\n id: 'gitbash',\n label: 'Git Bash',\n hint: '\u5F3A\u5236\u6362\u6210 Git Bash\uFF1B\u6CA1\u63A2\u6D4B\u5230\u5C31\u56DE\u843D PowerShell\uFF0C\u5E76\u5728\u72B6\u6001\u884C\u5199\u660E\u539F\u56E0',\n },\n {\n id: 'pwsh',\n label: 'PowerShell',\n hint: '\u4FDD\u6301 DSH \u9ED8\u8BA4\uFF08\u672C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u78B0\u7EC8\u7AEF\u5DE5\u5177\u9762\uFF09',\n },\n]\n\n/** \u9ED8\u8BA4\u6863\u4F4D\uFF1A\u81EA\u52A8\uFF08\u96F6\u914D\u7F6E\u5373\u5F97\u6536\u76CA\uFF0C\u4E14\u627E\u4E0D\u5230 bash \u65F6\u4E0D\u4F1A\u628A\u73AF\u5883\u5F04\u574F\uFF09\u3002 */\nexport const DEFAULT_TERMINAL_MODE: TerminalMode = 'auto'\n\n/** \u843D\u76D8\u7684\u5019\u9009\u5F62\u72B6\uFF08\u6BD4\u63A2\u6D4B\u7ED3\u679C\u591A\u4E00\u70B9\uFF1Akind \u4E0E explicit \u4F9B\u754C\u9762\u6807\u6CE8\uFF09\u3002 */\nexport interface TerminalCandidate {\n readonly path: string\n readonly label: string\n readonly kind: BashKind\n readonly explicit: boolean\n}\n\n/** \u6536\u7A84\u6863\u4F4D\u3002 */\nexport function terminalModeFrom(value: unknown): TerminalMode {\n return value === 'auto' || value === 'gitbash' || value === 'pwsh' ? value : DEFAULT_TERMINAL_MODE\n}\n\n/** \u63A2\u6D4B\u7ED3\u679C \u2192 \u843D\u76D8\u5019\u9009\uFF08\u53BB\u6389\u8FD0\u884C\u671F\u624D\u77E5\u9053\u7684\u5B57\u6BB5\uFF09\u3002 */\nexport function candidatesToStored(candidates: readonly BashCandidate[]): readonly TerminalCandidate[] {\n return candidates.map(candidate => ({\n path: candidate.path,\n label: candidate.label,\n kind: candidate.kind,\n explicit: candidate.explicit,\n }))\n}\n\n/** \u6536\u7A84\u843D\u76D8\u5019\u9009\uFF08\u9632\u810F\u6570\u636E\uFF1B\u4E0A\u9650 20 \u6761\u591F\u7528\uFF09\u3002 */\nexport function sanitizeTerminalCandidates(value: unknown): readonly TerminalCandidate[] {\n if (!Array.isArray(value)) return []\n const out: TerminalCandidate[] = []\n const seen = new Set<string>()\n for (const item of value) {\n if (out.length >= 20) break\n if (typeof item !== 'object' || item === null) continue\n const row = item as Record<string, unknown>\n const path = typeof row.path === 'string' ? normalizePath(row.path).slice(0, 400) : ''\n if (path === '') continue\n const key = path.toLowerCase()\n if (seen.has(key)) continue\n seen.add(key)\n const label = typeof row.label === 'string' ? row.label.slice(0, 40) : ''\n const kind = row.kind === 'git' || row.kind === 'msys2' || row.kind === 'cygwin'\n || row.kind === 'niubash' || row.kind === 'path' ? row.kind : 'path'\n out.push({ path, label: label === '' ? 'PATH' : label, kind, explicit: row.explicit === true })\n }\n return out\n}\n\n/**\n * \u8FD9\u4E00\u8F6E\u5B9E\u9645\u8BE5\u7528\u54EA\u4E2A bash\u3002\n *\n * \u4E09\u6863\u7684\u5DEE\u522B\u53EA\u5728\u8FD9\u91CC\uFF0C\u522B\u5728\u8C03\u7528\u5904\u518D\u5224\u4E00\u6B21\uFF1A\n * - `pwsh`\uFF1A\u4E0D\u7528 bash\uFF08\u8FD4\u56DE\u7A7A\u4E32\uFF09\uFF1B\n * - `gitbash` / `auto`\uFF1A\u4F18\u5148\u7528\u6237\u586B\u7684\u8DEF\u5F84\uFF0C\u5176\u6B21\u5019\u9009\u8868\u7B2C\u4E00\u4E2A\uFF08\u63A2\u6D4B\u987A\u5E8F\u5DF2\u6392\u597D\uFF1A\n * \u663E\u5F0F \u2192 Git Bash \u2192 MSYS2/Cygwin \u2192 Niubash \u2192 PATH\uFF09\uFF1B\n * - \u4E24\u8005\u90FD\u4E0D\u8981\u6C42\"\u5FC5\u987B\u627E\u5230\"\uFF1A\u627E\u4E0D\u5230\u65F6\u8FD4\u56DE\u7A7A\u4E32\uFF0C\u7531\u8C03\u7528\u65B9\u56DE\u843D PowerShell\n * \uFF08`auto` \u9759\u9ED8\u56DE\u843D\uFF0C`gitbash` \u4F1A\u5728\u72B6\u6001\u884C\u91CC\u8BF4\u660E\u2014\u2014\u5DEE\u522B\u53EA\u662F\"\u8981\u4E0D\u8981\u89E3\u91CA\"\uFF09\u3002\n * @param mode \u5F53\u524D\u6863\u4F4D\u3002\n * @param bashPath \u7528\u6237\u586B\u7684\u8DEF\u5F84\uFF08\u53EF\u7A7A\uFF09\u3002\n * @param candidates \u5BBF\u4E3B\u534A\u4E0A\u6B21\u63A2\u6D4B\u5230\u7684\u5019\u9009\u3002\n * @returns \u53EF\u6267\u884C\u6587\u4EF6\u8DEF\u5F84\uFF1B\u7A7A\u4E32\u8868\u793A\u8FD9\u4E00\u8F6E\u4E0D\u7528 bash\u3002\n */\nexport function activeBashPath(\n mode: TerminalMode,\n bashPath: string,\n candidates: readonly TerminalCandidate[],\n explicitState?: ExplicitState,\n): string {\n if (mode === 'pwsh') return ''\n const explicit = normalizePath(bashPath)\n // \u663E\u5F0F\u8DEF\u5F84\u53EA\u6709\u5728\"\u786E\u5B9E\u5B58\u5728\"\uFF08\u6216\u8C03\u7528\u65B9\u5DF2\u7ECF\u9A8C\u8BC1\u8FC7\u3001\u6CA1\u7ED9\u72B6\u6001\uFF09\u65F6\u624D\u538B\u8FC7\u63A2\u6D4B\u7ED3\u679C\u3002\n if (explicit !== '' && (explicitState === undefined || explicitState.state === 'ok')) return explicit\n return defaultBashPath({ candidates, excluded: [] })\n}\n\n/** \u63A2\u6D4B\uFF08\u628A\u5199\u6B7B\u7684\u73AF\u5883\u8BFB\u53D6\u96C6\u4E2D\u5728\u8FD9\u91CC\uFF0C\u5176\u4F59\u903B\u8F91\u90FD\u5728\u7EAF\u51FD\u6570\u91CC\uFF09\u3002 */\nexport function probeBash(\n explicitPath: string,\n pathValue: string,\n env: (name: string) => string | undefined,\n exists: (path: string) => boolean,\n listDirs?: (parent: string) => readonly string[],\n): DiscoverResult {\n return discoverBashCandidates({\n exists,\n pathEntries: pathValue.split(';'),\n env,\n explicitPath,\n ...(listDirs === undefined ? {} : { listDirs }),\n })\n}\n\n/** \u72B6\u6001\u884C\u7684\u8F93\u5165\uFF08\u5BBF\u4E3B\u534A\u7B97\u597D\u8FD9\u4E9B\u4E8B\u5B9E\uFF0C\u6587\u6848\u672C\u8EAB\u662F\u7EAF\u51FD\u6570\uFF0C\u4FBF\u4E8E\u5355\u6D4B\uFF09\u3002 */\nexport interface StatusInput {\n /** `process.platform`\u3002 */\n readonly platform: string\n readonly mode: TerminalMode\n /** \u63A2\u6D4B\u5230\u7684\u5019\u9009\uFF08\u5DF2\u6392\u5E8F\uFF09\u3002 */\n readonly candidates: readonly TerminalCandidate[]\n /** \u88AB\u786C\u6392\u9664\u7684 WSL \u8DEF\u5F84\u6761\u6570\u3002 */\n readonly excludedCount: number\n /** \u7528\u6237\u663E\u5F0F\u586B\u7684\u8DEF\u5F84\u72B6\u6001\uFF08\u6CA1\u586B\u5219 undefined\uFF09\u3002 */\n readonly explicit?: ExplicitState\n /** \u8FD9\u4E00\u8F6E\u5B9E\u9645\u751F\u6548\u7684 shell\u3002 */\n readonly effective: 'bash' | 'pwsh' | 'unsupported'\n /** \u751F\u6548\u65F6\u7528\u7684\u5177\u4F53\u8DEF\u5F84\uFF08effective \u4E3A bash \u65F6\u7ED9\u51FA\uFF09\u3002 */\n readonly effectivePath?: string\n /** \u4E0B\u53D1\u5230 agent \u65F6\u9047\u5230\u7684\u5931\u8D25\u539F\u56E0\uFF08restrict/register \u5931\u8D25\uFF09\u3002 */\n readonly failure?: string\n /**\n * \u8FD9\u4E00\u8F6E**\u6CA1\u80FD\u771F\u7684\u6362\u4E0A**\uFF08\u4F8B\u5982 `tools.register` \u5931\u8D25\uFF0Crestrict \u5DF2\u56DE\u6EDA\uFF09\u3002\n *\n * \u7528\u6765\u628A\u90A3\u53E5\"\u5019\u9009\u4E0D\u53EF\u7528\"\u6362\u6210\u51C6\u786E\u8BF4\u6CD5\uFF1A\u5019\u9009\u662F\u6709\u7684\u3001bash \u4E5F\u5B58\u5728\uFF0C\u53EA\u662F\u6CA1\u88C5\u4E0A\u3002\n */\n readonly deliveryFailed?: boolean\n /**\n * \u63A5\u7BA1**\u4E4B\u524D**\u7684\u81EA\u68C0\u6CA1\u901A\u8FC7\uFF082026-09-25 \u65B0\u589E\uFF09\uFF1A\u539F\u56E0\u3002\n *\n * \u4E0E `deliveryFailed` \u662F\u4E24\u4EF6\u4E8B\uFF1A\u90A3\u6761\u662F\"\u8BD5\u4E86\u4F46\u6CA1\u88C5\u4E0A\"\uFF0C\u8FD9\u6761\u662F\"\u9884\u68C0\u5C31\u6CA1\u8FC7\u3001\u6839\u672C\u6CA1\u8BD5\"\u2014\u2014\n * \u7528\u4E8E\u684C\u9762\u7248\u53D7\u9650\u7B56\u7565\u4E0B\u4F1A\u51FA\u73B0\u7684 `0xC0000142`\uFF08\u6C99\u7BB1 runner \u5728\u6253\u5305\u5F62\u6001\u8D77\u4E0D\u6765\uFF09\uFF0C\n * \u90A3\u65F6\u82E5\u7167\u65E7\u63A5\u7BA1\u4F1A\u628A\u8BE5\u4F1A\u8BDD\u7684 shell \u6253\u6B7B\uFF0C\u6240\u4EE5\u5B81\u53EF\u4FDD\u6301 PowerShell\u3002\n */\n readonly probeFailed?: string\n}\n\n/**\n * \u751F\u6210\u72B6\u6001\u884C\uFF08\u8BBE\u7F6E\u9875\u76F4\u63A5\u5C55\u793A\u8FD9\u53E5\u8BDD\uFF09\u3002\n *\n * \u539F\u5219\uFF1A**\u53EA\u8BF4\u4E8B\u5B9E\uFF0C\u4E0D\u7ED9\u5EFA\u8BAE**\u3002\u751F\u6548\u65F6\u7ED9\u51FA\u8DEF\u5F84\u4E0E\u6765\u6E90\uFF1B\u4E0D\u751F\u6548\u65F6\u89E3\u91CA\u4E3A\u4EC0\u4E48\n * \uFF08\u6CA1\u627E\u5230 / \u8DEF\u5F84\u4E0D\u5B58\u5728 / \u5E73\u53F0\u4E0D\u5BF9\uFF09\uFF0C\u5E76\u4E14\u660E\u786E\u8BF4\u51FA\"\u5DF2\u6392\u9664 WSL\"\u8FD9\u79CD\u6211\u4EEC\u4E3B\u52A8\u505A\u7684\u51B3\u5B9A\u3002\n * @param input \u4E8B\u5B9E\u3002\n * @returns \u4E00\u884C\u4E2D\u6587\u72B6\u6001\uFF08\u6700\u957F 400 \u5B57\u7B26\uFF0C\u4E0E schema \u4E0A\u9650\u4E00\u81F4\uFF09\u3002\n */\nexport function terminalStatusText(input: StatusInput): string {\n const text = (() => {\n if (input.platform !== 'win32') {\n return `\u672C\u63D2\u4EF6\u53EA\u5728 Windows \u4E0A\u63A5\u7BA1\u7EC8\u7AEF\uFF08\u5F53\u524D\u5E73\u53F0 ${input.platform}\uFF09\uFF0C\u6B64\u5904\u4E0D\u751F\u6548`\n }\n if (input.mode === 'pwsh') {\n return '\u4FDD\u6301 DSH \u9ED8\u8BA4\uFF08PowerShell\uFF09\u2014\u2014\u672C\u63D2\u4EF6\u4E0D\u4ECB\u5165\u7EC8\u7AEF\u5DE5\u5177\u9762'\n }\n if (input.probeFailed !== undefined && input.probeFailed !== '') {\n return `\u5DF2\u542F\u7528\uFF0C\u4F46\u81EA\u68C0\u672A\u901A\u8FC7\uFF1A${input.probeFailed} \u2014\u2014 \u4E3A\u907F\u514D\u628A\u4F1A\u8BDD\u7684 shell \u6253\u6B7B\uFF0C\u6682\u4E0D\u63A5\u7BA1\uFF08\u4FDD\u6301 PowerShell\uFF09`\n }\n if (input.effective === 'bash') {\n const path = input.effectivePath ?? ''\n const candidate = input.candidates.find(item => item.path === path)\n const suffix = input.explicit?.state === 'missing'\n ? `\uFF08\u4F60\u586B\u7684\u8DEF\u5F84\u4E0D\u5B58\u5728\uFF1A${input.explicit.path}\uFF09`\n : input.explicit?.state === 'wsl'\n ? `\uFF08\u4F60\u586B\u7684\u662F WSL \u7684 bash\uFF1A${input.explicit.path}\uFF09`\n : ''\n return `\u5DF2\u751F\u6548\uFF1A${path}${candidate === undefined ? '' : `\uFF08${candidate.label}\uFF09`}${suffix}`\n }\n if (input.candidates.length === 0) {\n const excluded = input.excludedCount > 0 ? `\uFF08\u5DF2\u6392\u9664 ${input.excludedCount} \u4E2A WSL \u7684 bash.exe\uFF09` : ''\n return `\u6CA1\u627E\u5230\u53EF\u7528\u7684 bash${excluded}\uFF0C\u6682\u65F6\u4FDD\u6301 PowerShell`\n }\n if (input.deliveryFailed === true) {\n return '\u627E\u5230\u4E86 bash \u4F46\u6CA1\u80FD\u6362\u4E0A\uFF08\u5DF2\u56DE\u6EDA\uFF0Cpwsh \u7167\u65E7\u53EF\u7528\uFF09\uFF0C\u6682\u65F6\u4FDD\u6301 PowerShell'\n }\n return `\u5019\u9009\u4E0D\u53EF\u7528\uFF0C\u6682\u65F6\u4FDD\u6301 PowerShell`\n })()\n const failure = input.failure === undefined || input.failure === '' ? '' : `\uFF1B\u4E0B\u53D1\u5931\u8D25\uFF1A${input.failure}`\n return `${text}${failure}`.slice(0, 400)\n}\n", "/**\n * dsh-composer-ux \u516C\u5171\u5951\u7EA6\uFF1A\u8BBE\u7F6E\u5B57\u6BB5\u3001\u9ED8\u8BA4\u503C\u3001\u5C55\u793A\u5143\u6570\u636E\u3002\n * \u672C\u6A21\u5757\u5FC5\u987B\u96F6 import\uFF08host \u4E0E client \u4E24\u534A\u5171\u7528\uFF0C\u8DE8\u7AEF\u4E0D\u5171\u4EAB\u4EFB\u4F55\u8FD0\u884C\u65F6\u8EAB\u4EFD\uFF09\u3002\n *\n * \u552F\u4E00\u7684\u4F8B\u5916\u662F `./terminal/` \u4E0B\u90A3\u51E0\u4E2A**\u7EAF\u51FD\u6570**\u6A21\u5757\uFF08\u96F6\u5916\u90E8\u4F9D\u8D56\u3001\u65E0 DOM\u3001\u65E0 node API\uFF09\uFF0C\n * \u300C\u9ED8\u8BA4\u7EC8\u7AEF\u300D\u7684\u5B57\u6BB5\u4E0E\u5224\u5B9A\u653E\u5728\u90A3\u91CC\uFF0C\u8FD9\u91CC\u53EA\u628A\u5B83\u4EEC\u5E76\u8FDB\u8BBE\u7F6E\u5951\u7EA6\u3002\n */\nimport {\n DEFAULT_TERMINAL_MODE, TERMINAL_BASH_PATH_FIELD, TERMINAL_CANDIDATES_FIELD,\n TERMINAL_EFFECTIVE_FIELD, TERMINAL_MODE_FIELD, TERMINAL_STATUS_FIELD,\n sanitizeTerminalCandidates, terminalModeFrom,\n type TerminalCandidate, type TerminalMode,\n} from './terminal/contracts.ts'\n\n/** Host settings namespace\uFF08\u5C0F\u5199\u5B57\u6BCD/\u6570\u5B57/\u8FDE\u5B57\u7B26\uFF09\u3002 */\nexport const NAMESPACE = 'composer-ux'\n\n/**\n * \u4ED3\u5E93\u5730\u5740\uFF1A\u8BBE\u7F6E\u9875\u62AC\u5934\u90A3\u4E2A\u300CGitHub \u2197\u300D\u94FE\u63A5\u7528\u5B83\u3002\n *\n * \u5FC5\u987B\u4E0E `package.json` \u7684 `repository.url` \u4E00\u81F4 \u2014\u2014 `test/client-registration.mjs`\n * \u6709\u4E00\u6761\u62A4\u680F\u76EF\u7740\u4E24\u5904\uFF0C\u514D\u5F97\u5404\u5199\u4E00\u4EFD\u7136\u540E\u6162\u6162\u5206\u53C9\uFF08\u5BA2\u6237\u7AEF\u4E5F\u4E0D\u8BB8\u786C\u7F16\u7801\u7B2C\u4E8C\u4EFD\u5730\u5740\uFF09\u3002\n */\nexport const REPO_URL = 'https://github.com/fangwen9527/dsh-composer-ux'\n\n// \u2500\u2500 \u300C\u91CD\u542F DSH\u300D\u6309\u94AE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// \u4E3A\u4EC0\u4E48\u8FD9\u4EF6\u4E8B\u5FC5\u987B\u843D\u5728\u5BBF\u4E3B\u534A\uFF1A\u53EA\u6709\u5BBF\u4E3B\u8FDB\u7A0B\u80FD\u628A\u81EA\u5DF1\u91CD\u65B0\u62C9\u8D77\u6765\uFF08\u6D4F\u89C8\u5668\u78B0\u4E0D\u5230\u8FDB\u7A0B\uFF09\u3002\n// \u673A\u5236\u7167\u642C\u63D2\u4EF6\u5E02\u573A\uFF08\u5206\u79BB\u4E00\u4E2A node \u52A9\u624B\u8FDB\u7A0B\u3001\u7B49\u7AEF\u53E3\u7A7A\u95F2\u3001\u7528\u9690\u85CF\u63A7\u5236\u53F0\u7684 PowerShell \u8D77\u65B0\u5BBF\u4E3B\uFF09\uFF0C\n// \u5168\u90E8\u7EC6\u8282\u5728 `src/restart.ts`\u3002\u8FD9\u91CC\u53EA\u6709\u4E24\u7AEF\u5171\u7528\u7684\u90A3\u4E00\u4E2A\u5E38\u91CF\u3002\n// 0.5.0 \u91CC\u90A3\u4E2A\u300C\u53EF\u9009\u91CD\u542F\u547D\u4EE4\u300D\u5B57\u6BB5\u5DF2\u53BB\u6389\uFF1A\u673A\u5236\u8DB3\u591F\u53EF\u9760\u4E4B\u540E\u5B83\u53EA\u5269\"\u591A\u4E00\u4E2A\u4F1A\u586B\u9519\u7684\u5730\u65B9\"\u3002\n\n/** \u91CD\u542F\u63A5\u53E3\u8DEF\u5F84\uFF08\u5BBF\u4E3B\u534A\u6CE8\u518C\uFF0C\u5BA2\u6237\u7AEF\u534A\u8C03\u7528\uFF09\u3002 */\nexport const RESTART_API_PATH = '/composer-ux/restart'\n\n/** \u5168\u5C40\u603B\u5F00\u5173\u5B57\u6BB5\u540D\u3002 */\nexport const ENABLED_FIELD = 'enabled'\n\n// \u2500\u2500 \u300C\u6BCF\u4E00\u680F\u4E00\u4E2A\u5F00\u5173\u300D \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// \u516D\u5F20\u6298\u53E0\u5361\u5404\u6709\u4E00\u4E2A\"\u8FD9\u4E00\u680F\u8981\u4E0D\u8981\u751F\u6548\"\u7684\u5F00\u5173\uFF0C**\u9ED8\u8BA4\u5173**\uFF1B\u603B\u5F00\u5173\uFF08`enabled`\uFF09\u9ED8\u8BA4\u5F00\uFF0C\n// \u5B83\u662F\u4E00\u9053\u603B\u95F8\uFF1A`enabled && \u8BE5\u680F\u5F00\u5173` \u624D\u751F\u6548\u3002\n//\n// \u4E3A\u4EC0\u4E48\u8981\u6709\"\u4ECE\u6CA1\u78B0\u8FC7\u7684\u680F\u624D\u9ED8\u8BA4\u5173\"\u8FD9\u6761\u8FC1\u79FB\u89C4\u5219\uFF08\u7528\u6237\u62CD\u677F A \u65B9\u6848\uFF09\uFF1A\u672C\u63D2\u4EF6\u5DF2\u7ECF\u53D1\u5E03\u8FC7\uFF0C\n// \u8001\u7528\u6237\u8BBE\u7F6E\u6587\u6863\u91CC\u5168\u662F\"\u6211\u6B63\u5728\u7528\"\u7684\u75D5\u8FF9\u3002\u82E5\u4E00\u5F8B\u9ED8\u8BA4\u5173\uFF0C\u5347\u7EA7\u90A3\u4E00\u523B\u4ED6\u7684\u952E\u4F4D\u5C31\u56DE\u5230 DSH \u539F\u751F\u3001\n// OpenCode \u8DEF\u7531\u76F4\u63A5 400\uFF08\u8BF7\u6C42\u5934\u4E0D\u518D\u6CE8\u5165\uFF09\u3001Git Bash \u6362\u56DE PowerShell \u2014\u2014 \u5168\u662F\u8981\u7528\u5230\u624D\u53D1\u73B0\u7684\u7834\u574F\u3002\n// \u6240\u4EE5\uFF1A**\u8FD9\u4E00\u680F\u7684\u503C\u4E0D\u7B49\u4E8E\"\u4ECE\u6CA1\u78B0\u8FC7\u7684\u6837\u5B50\" \u21D2 \u8BA4\u5B9A\u78B0\u8FC7 \u21D2 \u5F00**\uFF08\u5224\u636E\u89C1 `sectionEnabledOf`\uFF09\u3002\n// \u5168\u65B0\u5B89\u88C5\uFF08\u4EC0\u4E48\u75D5\u8FF9\u90FD\u6CA1\u6709\uFF09\u56E0\u6B64\u662F\u516D\u680F\u5168\u5173\u3002\u89C4\u5219\u7684\u5B9E\u73B0\u5728\u4E0B\u9762 `sectionEnabledOf`\u3002\n//\n// \u300COpenCode \u8BF7\u6C42\u5934\u300D\u90A3\u4E00\u680F**\u6CA1\u6709\u65B0\u952E**\uFF1A\u5B83\u539F\u6765\u7684 `headerEnabled`\uFF08\u9ED8\u8BA4 false\uFF09\u672C\u6765\u5C31\u662F\n// \"\u8FD9\u4E00\u680F\u8981\u4E0D\u8981\u751F\u6548\"\uFF0C\u76F4\u63A5\u642C\u5230\u6807\u9898\u884C\u5F53\u5361\u7EA7\u5F00\u5173\uFF0C\u4E0D\u518D\u9020\u4E00\u4E2A\u540C\u4E49\u7684\u952E\u3002\n\n/** \u300C\u952E\u4F4D\u300D\u680F\u5F00\u5173\u3002 */\nexport const KEYS_ENABLED_FIELD = 'keysEnabled'\n/** \u300C\u53F3\u952E\u83DC\u5355\u300D\u680F\u5F00\u5173\u3002 */\nexport const MENU_ENABLED_FIELD = 'menuEnabled'\n/** \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u680F\u5F00\u5173\u3002 */\nexport const QUICK_ENABLED_FIELD = 'quickEnabled'\n/** \u300C\u8BBE\u7F6E\u9762\u677F\u300D\u680F\u5F00\u5173\u3002 */\nexport const PANEL_ENABLED_FIELD = 'panelEnabled'\n/** \u300C\u9ED8\u8BA4\u7EC8\u7AEF\u300D\u680F\u5F00\u5173\u3002 */\nexport const TERMINAL_ENABLED_FIELD = 'terminalEnabled'\n\n/** \u952E\u4F4D\u5B57\u6BB5\u540D\u3002 */\nexport const SEND_KEY_FIELD = 'sendKey'\nexport const NEWLINE_KEY_FIELD = 'newlineKey'\n\n/**\n * \u8BBE\u7F6E\u9762\u677F\u5B57\u6BB5\u540D\u3002\n *\n * 0.6.0 \u8D77**\u6CA1\u6709** `panelScroll`\uFF1ADSH 0.1.7 \u7684\u5B98\u65B9\u8BBE\u7F6E\u9875\u7ED9\u5BFC\u822A\u5217\u81EA\u5E26\n * `overflow-y: auto`\uFF08`ui-settings-general` \u7684 `.navList`\uFF09\uFF0C\u6211\u4EEC\u90A3\u5957\n * `html.dsh-ux-panel-scroll` \u6CE8\u5165\u6837\u5F0F\u5DF2\u88AB\u5B98\u65B9\u53D6\u4EE3\uFF0C\u6545\u6574\u9879\u5220\u9664\u3002\n */\nexport const PANEL_RESIZE_FIELD = 'panelResize'\nexport const PANEL_WIDTH_FIELD = 'panelWidth'\nexport const PANEL_HEIGHT_FIELD = 'panelHeight'\n\n/** \u53F3\u952E\u83DC\u5355\u5F00\u5173\u5B57\u6BB5\u540D\u3002 */\nexport const MENU_FIELDS = [\n 'menuUndo',\n 'menuRedo',\n 'menuCut',\n 'menuCopy',\n 'menuPaste',\n 'menuDelete',\n 'menuSelectAll',\n] as const\n\nexport type MenuField = (typeof MENU_FIELDS)[number]\n\n/**\n * \u53F3\u952E\u83DC\u5355\u6A21\u5F0F\u5B57\u6BB5\u540D\uFF080.5.0 \u8D77\u4E09\u6863\uFF09\u3002\n *\n * 0.2.x\uFF5E0.4.0 \u7528\u7684\u662F\u5E03\u5C14 `menuNative`\uFF1Atrue = \u6D4F\u89C8\u5668\u539F\u751F\u83DC\u5355\u3001false = \u81EA\u5B9A\u4E49\u83DC\u5355\u3002\n * \u5E03\u5C14\u53EA\u6709\u4E24\u4F4D\uFF0C\u8868\u8FBE\u4E0D\u4E86\u300C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u4ECB\u5165\u300D\uFF08\u4E0D\u6321\u522B\u7684\u63D2\u4EF6\u7684\u83DC\u5355\uFF09\u8FD9\u4E00\u6863\uFF0C\u6240\u4EE5\u6362\u6210\n * \u5B57\u7B26\u4E32\u4E09\u6863\u3002\u65E7\u5B57\u6BB5**\u53EA\u4F5C\u4E3A\u8FC1\u79FB\u7EBF\u7D22\u4FDD\u7559**\uFF1A\u672C\u5B57\u6BB5\u4E3A\u7A7A\u65F6\u6309\u65E7\u5B57\u6BB5\u63A8\u65AD\uFF08\u89C1 `menuModeFrom`\uFF09\u3002\n */\nexport const MENU_MODE_FIELD = 'menuMode'\n\n/** 0.2.x\uFF5E0.4.0 \u7684\u65E7\u5B57\u6BB5\u540D\uFF1A\u8FC1\u79FB\u7EBF\u7D22\uFF0C0.5.0 \u8D77\u4E0D\u518D\u5199\u5B83\u3002 */\nexport const MENU_NATIVE_FIELD = 'menuNative'\n\n/** \u53F3\u952E\u83DC\u5355\u6A21\u5F0F\uFF1A\u5B98\u65B9\u4E0D\u4ECB\u5165 / \u6D4F\u89C8\u5668\u83DC\u5355 / \u81EA\u5B9A\u4E49\u83DC\u5355\u3002 */\nexport type MenuMode = 'official' | 'browser' | 'custom'\n\n/** \u4E09\u6863\u7684\u5143\u6570\u636E\uFF08\u6570\u7EC4\u987A\u5E8F\u5373\u754C\u9762\u987A\u5E8F\uFF09\u3002 */\nexport const MENU_MODES: readonly {\n readonly id: MenuMode\n readonly label: string\n readonly hint: string\n}[] = [\n {\n id: 'official',\n label: '\u5B98\u65B9',\n hint: '\u672C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u4ECB\u5165\uFF1ADSH \u4E0E\u5176\u5B83\u63D2\u4EF6\u81EA\u5DF1\u7684\u53F3\u952E\u5904\u7406\u539F\u6837\u751F\u6548\uFF08DSH \u5B98\u65B9\u8F93\u5165\u6846\u672C\u8EAB\u6CA1\u6709\u53F3\u952E\u83DC\u5355\uFF0C\u901A\u5E38\u770B\u5230\u7684\u5C31\u662F\u6D4F\u89C8\u5668\u7684\u83DC\u5355\uFF09',\n },\n {\n id: 'browser',\n label: '\u6D4F\u89C8\u5668',\n hint: '\u56FA\u5B9A\u4F7F\u7528\u6D4F\u89C8\u5668\u81EA\u5E26\u7684\u83DC\u5355\uFF0C\u5E76\u5728\u672C\u63D2\u4EF6\u8FD9\u4E00\u5C42\u6321\u4F4F\u5176\u5B83\u63D2\u4EF6\u7684\u83DC\u5355\uFF1B\u7C98\u8D34\u514D\u6388\u6743\u3001\u96F6\u914D\u7F6E',\n },\n {\n id: 'custom',\n label: '\u81EA\u5B9A\u4E49',\n hint: '\u4F7F\u7528\u672C\u63D2\u4EF6\u7684\u56FA\u5B9A\u6837\u5F0F\u83DC\u5355\uFF1B\u672A\u9009\u4E2D\u6587\u672C\u65F6\u300C\u526A\u5207 / \u590D\u5236 / \u5220\u9664\u300D\u7F6E\u7070\uFF0C\u7C98\u8D34\u9700\u8981\u6D4F\u89C8\u5668\u526A\u8D34\u677F\u6388\u6743',\n },\n]\n\n/**\n * \u5B9A\u51FA\u53F3\u952E\u83DC\u5355\u6A21\u5F0F\uFF1A\u65B0\u5B57\u6BB5\u4F18\u5148\uFF0C\u5176\u6B21\u6309\u65E7\u5E03\u5C14\u63A8\u65AD\uFF0C\u90FD\u6CA1\u6709\u5C31\u7528\u9ED8\u8BA4\u6863\u3002\n *\n * \u4E09\u79CD\u60C5\u51B5\u5224\u65AD\u5F97\u51FA\u6765\uFF0C\u662F\u56E0\u4E3A\u5BBF\u4E3B\u534A\u628A\u65E7\u5B57\u6BB5\u58F0\u660E\u6210**\u53EF\u9009**\uFF08\u6CA1\u6709 `.default(false)`\uFF09\uFF1A\n * \u300C\u4ECE\u6CA1\u78B0\u8FC7\u90A3\u4E2A\u5F00\u5173\u300D\u4E0E\u300C\u660E\u786E\u5173\u4E86\u5B83\u300D\u5728\u6587\u6863\u91CC\u957F\u5F97\u4E0D\u4E00\u6837\uFF08\u952E\u4E0D\u5B58\u5728 / \u952E\u4E3A false\uFF09\uFF0C\n * \u524D\u8005\u843D\u5230\u65B0\u9ED8\u8BA4\u6863\uFF08\u5B98\u65B9\u4E0D\u4ECB\u5165\uFF09\uFF0C\u540E\u8005\u4FDD\u6301\u539F\u6765\u7684\u81EA\u5B9A\u4E49\u83DC\u5355\u3002\n * @param storedMode - \u6587\u6863\u91CC\u7684\u65B0\u5B57\u6BB5\u503C\uFF08\u53EF\u80FD\u662F\u810F\u6570\u636E\uFF09\u3002\n * @param legacyNative - \u6587\u6863\u91CC\u7684\u65E7\u5E03\u5C14\u503C\uFF08\u53EF\u80FD\u4E0D\u5B58\u5728\uFF09\u3002\n * @returns \u4E09\u6863\u4E4B\u4E00\u3002\n */\nexport function menuModeFrom(storedMode: unknown, legacyNative: unknown): MenuMode {\n if (storedMode === 'official' || storedMode === 'browser' || storedMode === 'custom') return storedMode\n if (legacyNative === true) return 'browser'\n if (legacyNative === false) return 'custom'\n return DEFAULT_SETTINGS.menuMode\n}\n\n// \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\u4E0E\u63D0\u793A\u8BCD\u4F18\u5316 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** \u5FEB\u6377\u6307\u4EE4\u5217\u8868\u5B57\u6BB5\u540D\u3002 */\nexport const QUICK_PROMPTS_FIELD = 'quickPrompts'\n\n/** \u4F18\u5316\u5F3A\u5EA6\u6863\u4F4D\u5B57\u6BB5\u540D\u3002 */\nexport const OPTIMIZER_TIER_FIELD = 'optimizerTier'\n\n/** \u5355\u4E2A\u5206\u7C7B\u5185\u7684\u6761\u6570\u4E0A\u9650\u3002 */\nexport const QUICK_PROMPT_MAX = 60\n\n/** \u5206\u7C7B\u6570\u4E0A\u9650\u3002 */\nexport const QUICK_CATEGORY_MAX = 20\n\n/** \u5206\u7C7B\u540D\u7684\u5B57\u7B26\u4E0A\u9650\u3002 */\nexport const QUICK_CATEGORY_NAME_MAX = 40\n\n/** \u5355\u6761\u300C\u540D\u79F0\u300D\u7684\u5B57\u7B26\u4E0A\u9650\u3002 */\nexport const QUICK_LABEL_MAX = 40\n\n/**\n * \u5355\u6761\u300C\u63D0\u793A\u8BCD\u300D\u7684\u5B57\u7B26\u4E0A\u9650\u3002\n *\n * 0.3.0 \u8D77\u5FEB\u6377\u6307\u4EE4\u6539\u5B58 `$DSH_HOME/quick-prompts.json`\uFF0C\u4E0D\u518D\u53D7\u8BBE\u7F6E\u6587\u6863\u7684\u4F53\u79EF\u7EA6\u675F\uFF0C\n * \u6240\u4EE5\u8FD9\u91CC\u4ECE 4000 \u63D0\u5230 20 \u4E07\u2014\u2014\u53EA\u505A\u300C\u522B\u628A\u51E0\u767E MB \u585E\u8FDB\u6765\u300D\u7684\u9632\u5446\uFF0C\u6B63\u5E38\u63D0\u793A\u8BCD\u4E0D\u518D\u88AB\u622A\u65AD\u3002\n */\nexport const QUICK_TEXT_MAX = 200_000\n\n/**\n * \u9001\u53BB\u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\u7684\u539F\u6587\u4E0A\u9650\u3002\n *\n * \u4E0E\u539F `QUICK_TEXT_MAX * 2`\uFF08= 8000\uFF09\u7B49\u503C\uFF1A\u62AC\u9AD8\u7B49\u5FEB\u6377\u6307\u4EE4\u7684\u5B58\u50A8\u4E0A\u9650\u65F6**\u4E0D\u80FD**\n * \u987A\u5E26\u628A\u4F18\u5316\u8BF7\u6C42\u7684\u8F93\u5165\u4E0A\u9650\u4E5F\u62AC\u4E0A\u53BB\uFF0C\u5426\u5219\u8D85\u957F\u6587\u672C\u4F1A\u88AB\u4E22\u7ED9\u6A21\u578B\u3002\n */\nexport const OPTIMIZE_TEXT_MAX = 8_000\n\n/**\n * \u5FEB\u6377\u6307\u4EE4\u5B58\u50A8\u7684 HTTP \u8DEF\u5F84\uFF08\u5BBF\u4E3B\u534A\u6CE8\u518C\uFF0C\u5BA2\u6237\u7AEF\u534A\u8BFB\u5199\uFF09\u3002\n *\n * \u4E3A\u4EC0\u4E48\u5B58\u50A8\u4E5F\u5FC5\u987B\u8D70 HTTP\uFF1A\u6D4F\u89C8\u5668\u4FA7\u6CA1\u6709\u6587\u4EF6\u7CFB\u7EDF\uFF0C\u800C\u300C\u7528\u6237\u5185\u5BB9\u300D\u9700\u8981\u4E00\u4EFD\n * \u5168\u5C40\u3001\u4E0E\u4F1A\u8BDD/\u9879\u76EE\u65E0\u5173\u7684\u843D\u70B9\uFF0C\u53EA\u6709\u5BBF\u4E3B\u534A\u80FD\u63D0\u4F9B\u3002\n */\nexport const QUICK_PROMPTS_API_PATH = '/composer-ux/prompts'\n\n/** \u6587\u4EF6\u683C\u5F0F\u7248\u672C\uFF1B\u4E0E lnyuqian/dsh-quick-prompts \u7684 v2 \u5BF9\u9F50\uFF08\u89C1 bookToFile \u6CE8\u91CA\uFF09\u3002 */\nexport const QUICK_BOOK_VERSION = 2\n\n/** \u8FC1\u79FB/\u515C\u5E95\u5206\u7C7B\u540D\u3002 */\nexport const DEFAULT_CATEGORY_NAME = '\u9ED8\u8BA4'\n\n/** \u4F18\u5316\u7ED3\u679C\u957F\u5EA6\u4E0A\u9650\uFF08\u8D85\u8FC7\u89C6\u4E3A\u5F02\u5E38\u4EA7\u51FA\uFF0C\u622A\u65AD\u5E76\u63D0\u793A\uFF09\u3002 */\nexport const OPTIMIZE_OUTPUT_MAX = 12000\n\n/**\n * \u5BBF\u4E3B\u534A\u4E3A\u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\u6CE8\u518C\u7684 HTTP \u63A5\u53E3\u8DEF\u5F84\u3002\n *\n * \u4E3A\u4EC0\u4E48\u5FC5\u987B\u8D70 HTTP\uFF1A\u51FA\u7F51\u8BF7\u6C42\u7531\u5BBF\u4E3B\u7684\u6A21\u578B\u9002\u914D\u5668\u53D1\u51FA\uFF08\u6D4F\u89C8\u5668\u4FA7\u78B0\u4E0D\u5230\u6A21\u578B\u8DEF\u7531\uFF09\uFF0C\n * \u800C\u5BBF\u4E3B\u534A <-> \u5BA2\u6237\u7AEF\u534A\u4E4B\u95F4\u6CA1\u6709\u522B\u7684\u53D7\u652F\u6301\u901A\u9053 \u2014\u2014 \u4E0E\n * WestFox-AwA/dsh-prompt-optimizer \u7684\u505A\u6CD5\u4E00\u81F4\u3002\n */\nexport const OPTIMIZER_API_PATH = '/composer-ux/optimize'\n\n/**\n * \u4E00\u6761\u5FEB\u6377\u6307\u4EE4\u3002\n *\n * `always` \u5C31\u662F\u754C\u9762\u4E0A\u7684\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\uFF1A\u52FE\u4E0A\u4E4B\u540E\uFF0C\u70B9\u53D1\u9001\u65F6\u8FD9\u6761\u63D0\u793A\u8BCD\u4F1A\u88AB\n * \u81EA\u52A8\u62FC\u5230\u6D88\u606F**\u672B\u5C3E**\u4E00\u8D77\u53D1\u51FA\u53BB\uFF08\u8F93\u5165\u6846\u91CC\u4E0D\u63D0\u524D\u663E\u793A\uFF09\uFF0C\u89C1\n * `client/quick-commands.ts` \u7684 `appendAlwaysPrompts()`\u3002\n */\nexport interface QuickPrompt {\n /** \u7A33\u5B9A id\uFF1A\u7F16\u8F91\u540D\u79F0/\u5185\u5BB9\u65F6\u4E0D\u53D8\uFF0C\u7528\u4E8E\u52FE\u9009\u72B6\u6001\u4E0E\u5217\u8868 diff\u3002 */\n readonly id: string\n /** \u6309\u94AE\u4E0A\u663E\u793A\u7684\u540D\u79F0\u3002 */\n readonly label: string\n /** \u70B9\u51FB\u540E\u63D2\u5165\u8F93\u5165\u6846\u7684\u63D0\u793A\u8BCD\u6B63\u6587\u3002 */\n readonly prompt: string\n /** \u300C\u6BCF\u6B21\u300D\uFF1A\u6BCF\u6B21\u53D1\u9001\u90FD\u81EA\u52A8\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E\u3002\u4E0E `firstOnly` \u4E92\u65A5\u3002 */\n readonly always: boolean\n /**\n * \u300C\u4EC5\u9996\u6B21\u300D\uFF1A\u53EA\u5728**\u8FD9\u4E2A\u4F1A\u8BDD\u7684\u7B2C\u4E00\u6761\u6D88\u606F**\u4E0A\u9644\u52A0\u3002\n *\n * \u5224\u636E\u662F\u4F1A\u8BDD\u5FEB\u7167\u7684 `blank`\uFF08\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u4EFB\u4F55\u6D88\u606F\uFF09\u2014\u2014\u53D1\u5B8C\u7B2C\u4E00\u6761\u5B83\u81EA\u5DF1\u5C31\u53D8\u6210 false\uFF0C\n * \u6240\u4EE5\u4E0D\u9700\u8981\u6211\u4EEC\u81EA\u5DF1\u8BB0\u300C\u8FD9\u6B21\u4F1A\u8BDD\u9644\u52A0\u8FC7\u6CA1\u6709\u300D\uFF0C\u5237\u65B0\u9875\u9762\u4E5F\u4E0D\u4F1A\u91CD\u590D\u9644\u52A0\u3002\n * \u4E0E `always` \u4E92\u65A5\uFF08\u754C\u9762\u4E0A\u662F\u4E09\u9009\u4E00\uFF09\u3002\n */\n readonly firstOnly: boolean\n}\n\n/** \u63D2\u5165\u6A21\u5F0F\uFF1A\u754C\u9762\u4E0A\u90A3\u6761\u4E09\u9009\u4E00\u3002 */\nexport type InsertMode = 'never' | 'always' | 'first'\n\n/** \u4E09\u9009\u4E00\u7684\u5143\u6570\u636E\uFF08\u6570\u7EC4\u987A\u5E8F\u5373\u754C\u9762\u987A\u5E8F\uFF09\u3002 */\nexport const INSERT_MODES: readonly {\n readonly id: InsertMode\n readonly label: string\n readonly hint: string\n}[] = [\n { id: 'never', label: '\u5173', hint: '\u70B9\u6761\u76EE\u53EA\u63D2\u5165\u8F93\u5165\u6846\uFF0C\u53D1\u9001\u65F6\u4E0D\u9644\u52A0' },\n { id: 'always', label: '\u6BCF\u6B21', hint: '\u6BCF\u6B21\u53D1\u9001\u90FD\u628A\u8FD9\u6761\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E' },\n { id: 'first', label: '\u4EC5\u9996\u6B21', hint: '\u53EA\u5728\u5F53\u524D\u4F1A\u8BDD\u7684\u7B2C\u4E00\u6761\u6D88\u606F\u4E0A\u9644\u52A0' },\n]\n\n/**\n * \u8BFB\u4E00\u6761\u7684\u63D2\u5165\u6A21\u5F0F\u3002\n *\n * \u4E24\u4E2A\u6807\u5FD7\u90FD\u662F true \u65F6\u6309\u300C\u6BCF\u6B21\u300D\u5904\u7406\uFF08\u624B\u5DE5\u7F16\u8F91\u7684\u6587\u4EF6\u53EF\u80FD\u5199\u6210\u8FD9\u6837\uFF1B\u300C\u6BCF\u6B21\u300D\u672C\u6765\u5C31\n * \u5305\u542B\u7B2C\u4E00\u6B21\uFF09\uFF0C\u5E76\u4E14\u4E0B\u4E00\u6B21\u5199\u76D8\u4F1A\u628A\u4E92\u65A5\u6027\u4FEE\u6B63\u56DE\u6765\u3002\n */\nexport function insertModeOf(prompt: Pick<QuickPrompt, 'always' | 'firstOnly'>): InsertMode {\n if (prompt.always) return 'always'\n if (prompt.firstOnly) return 'first'\n return 'never'\n}\n\n/**\n * \u4F18\u5316\u5F3A\u5EA6\u6863\u4F4D\u3002\n *\n * \u63D0\u793A\u8BCD\u521D\u7248\u9010\u5B57\u63D0\u53D6\u81EA WestFox-AwA/dsh-prompt-optimizer\uFF08BSD-3-Clause\uFF0C\u4F5C\u8005\u300C\u5543\u8F6E\u80CE\u7684\u897F\u72D0\u300D\uFF09\uFF1B\n * 0.6.0 \u8D77\u6309\u5BF9\u65B9 **0.6 \u7EBF**\uFF08`po06/lib/interpreter.js`\uFF09\u7684\u673A\u5236\u91CD\u5199\uFF1A\u6A21\u578B\u4E0D\u518D\u81EA\u7531\u6539\u5199\uFF0C\n * \u800C\u662F\u4EA7\u51FA\u300C\u53EF\u5B9A\u4F4D\u5230\u539F\u8BDD\u67D0\u4E00\u6BB5\u300D\u7684\u6761\u76EE\uFF0C\u7531\u5BBF\u4E3B\u9010\u6761\u505A\u5B57\u9762\u6BD4\u5BF9\u540E\u518D\u88C5\u914D\u6210\u4E00\u6761\u547D\u4EE4\u3002\n * \u6863\u4F4D\u8BED\u4E49\u4E5F\u968F\u4E4B\u5BF9\u9F50\u5BF9\u65B9\u300C\u6863\u4F4D = \u4F9D\u636E\u9884\u7B97\u300D\u7684\u8BF4\u6CD5\uFF08\u89C1 `optimizer-prompt.ts`\uFF09\u3002\n */\nexport type OptimizerTier = 'basic' | 'advanced' | 'extreme'\n\n/** \u6863\u4F4D\u5143\u6570\u636E\uFF08\u987A\u5E8F\u5373\u754C\u9762\u987A\u5E8F\uFF09\u3002 */\nexport const OPTIMIZER_TIERS: readonly {\n readonly id: OptimizerTier\n readonly label: string\n readonly hint: string\n}[] = [\n { id: 'basic', label: '\u666E\u901A', hint: '\u53EA\u505A\u8BED\u8A00\u5C42\u4FEE\u590D\uFF1A\u75C5\u53E5\u3001\u9519\u522B\u5B57\u3001\u6307\u4EE3\u4E0E\u542B\u7CCA\u8BCD\uFF0C\u4E0D\u65B0\u589E\u4EFB\u4F55\u9700\u6C42\uFF0C\u7BC7\u5E45\u7EA6\u4E3A\u539F\u6587 1.4 \u500D\u3002' },\n { id: 'advanced', label: '\u9AD8\u7EA7', hint: '\u5728\u4E0D\u52A8\u76EE\u6807\u7684\u524D\u63D0\u4E0B\uFF0C\u628A\u300C\u4F60\u663E\u7136\u60F3\u8981\u3001\u4F46\u6CA1\u8BF4\u51FA\u53E3\u300D\u7684\u5FC5\u8981\u8981\u6C42\u8865\u6210\u5BF9 AI \u7684\u8981\u6C42\uFF0C\u6BCF\u6761\u90FD\u8981\u6307\u56DE\u4F60\u539F\u8BDD\u91CC\u7684\u67D0\u4E00\u53E5\u3002' },\n { id: 'extreme', label: '\u6781\u7AEF', hint: '\u6309\u590D\u6742\u4EFB\u52A1\u5904\u7406\uFF1A\u5728\u4E0A\u9762\u57FA\u7840\u4E0A\u518D\u52A0\u5206\u9636\u6BB5\u6267\u884C\u8BA1\u5212\u4E0E 2~4 \u79CD\u60C5\u51B5\u7684\u9884\u6848\u3002' },\n]\n\n/** \u9ED8\u8BA4\u6863\u4F4D\u3002 */\nexport const DEFAULT_OPTIMIZER_TIER: OptimizerTier = 'advanced'\n\n/**\n * \u6BCF\u4E2A\u6863\u4F4D\u7684\u300C\u81EA\u5B9A\u4E49\u7CFB\u7EDF\u63D0\u793A\u8BCD\u300D\u5B57\u6BB5\u540D\u3002\n *\n * \u4E3A\u4EC0\u4E48\u662F\u4E09\u4E2A\u5E73\u94FA\u5B57\u7B26\u4E32\u800C\u4E0D\u662F\u4E00\u4E2A\u5BF9\u8C61\uFF1A\u4E0E\u672C\u63D2\u4EF6\u5176\u5B83\u53EF\u7F16\u8F91\u9879\u4E00\u81F4\uFF08\u8BBE\u7F6E\u9875\u6309\u5B57\u6BB5\u540D\u8BFB\u5199\u3001\n * \u5BBF\u4E3B\u534A\u7684 schema \u4E5F\u662F\u5E73\u94FA key\uFF09\uFF0C\u4E14**\u7559\u7A7A = \u7528\u5185\u7F6E\u90A3\u4EFD**\u8FD9\u4E2A\u8BED\u4E49\u7528\u7A7A\u4E32\u8868\u8FBE\u6700\u76F4\u63A5 \u2014\u2014\n * \u4E0D\u9700\u8981\u989D\u5916\u4E00\u4E2A\"\u662F\u5426\u81EA\u5B9A\u4E49\"\u7684\u5E03\u5C14\uFF08\u591A\u4E00\u4E2A\u5E03\u5C14\u5C31\u591A\u4E00\u79CD\u81EA\u76F8\u77DB\u76FE\u7684\u72B6\u6001\uFF09\u3002\n */\nexport const OPTIMIZER_PROMPT_FIELDS = {\n basic: 'optimizerPromptBasic',\n advanced: 'optimizerPromptAdvanced',\n extreme: 'optimizerPromptExtreme',\n} as const\n\n/** \u5168\u90E8\u6863\u4F4D\u7684\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u5B57\u6BB5\u540D\uFF08\u987A\u5E8F\u5373\u6863\u4F4D\u987A\u5E8F\uFF09\u3002 */\nexport const OPTIMIZER_PROMPT_FIELD_LIST: readonly string[] =\n OPTIMIZER_TIERS.map(item => OPTIMIZER_PROMPT_FIELDS[item.id])\n\n/**\n * \u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u7684\u5B57\u6570\u4E0A\u9650\u3002\n *\n * \u4E0E `QUICK_TEXT_MAX` \u4E0D\u540C\uFF1A\u8FD9\u91CC\u5B58\u7684\u662F**\u6A21\u578B\u6307\u4EE4**\u800C\u4E0D\u662F\u7528\u6237\u5185\u5BB9\uFF0C\u5185\u7F6E\u90A3\u4E09\u4EFD\u90FD\u5728 3\u20135 KB\uFF0C\n * \u7ED9 2 \u4E07\u5B57\u7B26\u8DB3\u591F\u5BB9\u7EB3\u7528\u6237\u7684\u6539\u5199\uFF0C\u53C8\u80FD\u6321\u4F4F\"\u628A\u8BBE\u7F6E\u6587\u6863\u6491\u6210\u4E00\u672C\u4E66\"\u3002\n */\nexport const OPTIMIZER_PROMPT_MAX = 20_000\n\n/**\n * \u6309\u6863\u4F4D\u53D6\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u7684\u5B57\u6BB5\u540D\u3002\n * @param tier - \u6863\u4F4D id\uFF1B\u672A\u77E5\u503C\u56DE\u843D\u5230\u9ED8\u8BA4\u6863\uFF08\u4E0E `buildOptimizeSystem` \u540C\u4E00\u53E3\u5F84\uFF09\u3002\n * @returns \u8BE5\u6863\u4F4D\u5BF9\u5E94\u7684\u8BBE\u7F6E\u5B57\u6BB5\u540D\u3002\n */\nexport function optimizerPromptFieldOf(tier: string): string {\n return OPTIMIZER_PROMPT_FIELDS[tier as OptimizerTier] ?? OPTIMIZER_PROMPT_FIELDS[DEFAULT_OPTIMIZER_TIER]\n}\n\n/**\n * \u5185\u7F6E\u7684 9 \u6761\u5FEB\u6377\u6307\u4EE4 = \u7528\u6237\u53E3\u8FF0\u7684 4 \u6761 + \u63D0\u53D6\u81EA congyaqwq/dsh-quick-prompts \u7684 5 \u6761\u3002\n *\n * \u8BF4\u660E\uFF08\u5982\u5B9E\u8BB0\u5F55\u8C03\u7814\u7ED3\u679C\uFF09\uFF1A\u53E6\u5916\u4E24\u4E2A\u540C\u540D\u63D2\u4EF6 lcsdg / lnyuqian \u7684\n * dsh-quick-prompts **\u4E0D\u5E26\u5185\u7F6E\u6307\u4EE4**\uFF08\u5217\u8868\u9ED8\u8BA4\u662F\u7A7A\u7684\uFF0C\u9760\u7528\u6237\u81EA\u5EFA\uFF09\uFF0C\n * \u6240\u4EE5\u4ECE\u5B83\u4EEC\u90A3\u91CC\u6CA1\u6709\u53EF\u63D0\u53D6\u7684\u6761\u76EE\u3002\n */\nexport const DEFAULT_QUICK_PROMPTS: readonly QuickPrompt[] = [\n { id: 'builtin-1', label: '\u4E00\u95EE\u4E00\u7B54', prompt: '\u4F60\u4E0D\u61C2\u7684\u5C31\u95EE\u6211\uFF0C\u4E00\u95EE\u4E00\u7B54\uFF1B\u540C\u65F6\u8BF4\u6E05\u695A\u4F60\u4E3A\u4EC0\u4E48\u8981\u95EE\u8BE5\u95EE\u9898\uFF1B\u76F4\u5230\u4F60\u5BF9\u6211\u7684\u76EE\u6807\u6709\u660E\u786E\u8BA4\u77E5\u540E\u518D\u5F00\u59CB\u5E72\u6D3B\u3002', always: false, firstOnly: false },\n { id: 'builtin-2', label: '\u4EA4\u63A5\u6587\u6863', prompt: '\u628A\u8FD9\u6B21\u4EFB\u52A1\u3001\u5DF2\u5B8C\u6210\u5185\u5BB9\u3001\u5F53\u524D\u5361\u70B9\u3001\u4E0B\u4E00\u6B65\u8BA1\u5212\u3001\u8E29\u8FC7\u7684\u5751\uFF0C\u6574\u7406\u6210\u4E00\u4EFD\u4EA4\u63A5\u6587\u6863\uFF0C\u5199\u7ED9\u65B0\u4F1A\u8BDD\u770B\u3002', always: false, firstOnly: false },\n { id: 'builtin-3', label: '\u4EC5\u8BF4\u660E\u539F\u56E0', prompt: '\u4EC5\u8BF4\u660E\u539F\u56E0\uFF0C\u4E0D\u8981\u505A\u5176\u4ED6\u52A8\u4F5C\u3002', always: false, firstOnly: false },\n { id: 'builtin-4', label: '\u5206\u6790\u540E\u76F4\u63A5\u5E72', prompt: '\u5206\u6790\u539F\u56E0\uFF0C\u7136\u540E\u76F4\u63A5\u5F00\u59CB\u5E72\u6D3B\uFF0C\u4E0D\u9700\u8981\u8FC7\u95EE\u6211\u3002', always: false, firstOnly: false },\n { id: 'builtin-5', label: '\u63D0\u4EA4\u4EE3\u7801', prompt: '\u8BF7\u5E2E\u6211\u63D0\u4EA4\u4EE3\u7801\uFF1A\u68C0\u67E5\u5F53\u524D git \u53D8\u66F4\uFF0C\u751F\u6210\u89C4\u8303\u7684 commit message \u5E76\u6267\u884C\u63D0\u4EA4\u3002', always: false, firstOnly: false },\n { id: 'builtin-6', label: '\u7ED9\u65B9\u6848', prompt: '\u8BF7\u9488\u5BF9\u4E0A\u9762\u7684\u95EE\u9898\u7ED9\u51FA\u4E00\u4E2A\u5B8C\u6574\u65B9\u6848\uFF0C\u5305\u62EC\u601D\u8DEF\u3001\u6B65\u9AA4\u3001\u6CE8\u610F\u4E8B\u9879\u548C\u98CE\u9669\u3002', always: false, firstOnly: false },\n { id: 'builtin-7', label: '\u89E3\u91CA\u4EE3\u7801', prompt: '\u8BF7\u89E3\u91CA\u8FD9\u6BB5\u4EE3\u7801\u7684\u4F5C\u7528\u548C\u5B9E\u73B0\u601D\u8DEF\u3002', always: false, firstOnly: false },\n { id: 'builtin-8', label: '\u5199\u6D4B\u8BD5', prompt: '\u8BF7\u4E3A\u4E0B\u9762\u7684\u4EE3\u7801\u7F16\u5199\u5355\u5143\u6D4B\u8BD5\u3002', always: false, firstOnly: false },\n { id: 'builtin-9', label: '\u4EE3\u7801\u5BA1\u67E5', prompt: '\u8BF7\u5BF9\u4E0B\u9762\u7684\u4EE3\u7801\u8FDB\u884C\u4EE3\u7801\u5BA1\u67E5\uFF0C\u6307\u51FA\u95EE\u9898\u5E76\u7ED9\u51FA\u6539\u8FDB\u5EFA\u8BAE\u3002', always: false, firstOnly: false },\n]\n\n/** \u751F\u6210\u4E00\u6761\u65B0\u5FEB\u6377\u6307\u4EE4\u7684 id\uFF08\u65F6\u95F4\u6233 + \u968F\u673A\u540E\u7F00\uFF0C\u907F\u514D\u4E0E\u65E2\u6709 id \u78B0\u649E\uFF09\u3002 */\nexport function newQuickPromptId(): string {\n return `qp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`\n}\n\n// \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\uFF1A\u5206\u7C7B\u7ED3\u6784\u4E0E\u6587\u4EF6\u6620\u5C04 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// 0.3.0 \u8D77\u5FEB\u6377\u6307\u4EE4\u4E0D\u518D\u5B58\u5728\u8BBE\u7F6E\u6587\u6863\u91CC\uFF0C\u800C\u662F\u5B58\u5728 `$DSH_HOME/quick-prompts.json`\u3002\n// \u539F\u56E0\u662F\u8BBE\u7F6E\u6587\u6863\u5BF9**\u6570\u7EC4**\u662F\u300C\u6574\u4EFD\u66FF\u6362\u300D\u3001\u4E14\u53D7 schema \u957F\u5EA6\u4E0A\u9650\u7EA6\u675F\uFF08\u65E7 4000 \u5B57\u4F1A\u9759\u9ED8\n// \u622A\u65AD\uFF09\uFF0C\u800C\u5FEB\u6377\u6307\u4EE4\u662F\u7528\u6237\u5185\u5BB9\u3001\u4F1A\u5199\u5F88\u957F\u7684\u63D0\u793A\u8BCD\u3002\u4E13\u7528\u6587\u4EF6\u8FD8\u4FBF\u4E8E\u5355\u72EC\u5907\u4EFD\u4E0E\u8FC1\u79FB\u3002\n//\n// \u6587\u4EF6\u5B57\u6BB5\u540D\u4E0E lnyuqian/dsh-quick-prompts \u5BF9\u9F50\uFF08categories / name / title / text /\n// autoSend / order\uFF09\uFF0C\u8FD9\u6837\u540C\u4E00\u4E2A\u6587\u4EF6\u4E24\u8FB9\u90FD\u8BFB\u5F97\u61C2\uFF1A\u5185\u90E8\u7528 label/prompt/always\uFF0C\n// \u53EA\u5728\u6587\u4EF6\u8FB9\u754C\u6620\u5C04\uFF08\u89C1 bookToFile / asPromptRow\uFF09\u3002\n// \u26A0\uFE0F \u4F46**\u4E0D\u8981\u540C\u65F6\u88C5\u4E24\u4E2A\u63D2\u4EF6**\u2014\u2014\u540C\u4E00\u4E2A\u6587\u4EF6\u4E24\u4E2A\u5199\u8005\u4F1A\u4E92\u76F8\u8986\u76D6\uFF0C\u800C\u5B83\u90A3\u8FB9\u662F\u975E\u539F\u5B50\u5199\u3002\n\n/** \u751F\u6210\u4E00\u4E2A\u65B0\u5206\u7C7B id\u3002 */\nexport function newQuickCategoryId(): string {\n return `qc-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`\n}\n\n/** \u4E00\u4E2A\u5206\u7C7B\uFF1A\u540D\u5B57 + \u5B83\u81EA\u5DF1\u7684\u6761\u76EE\u5217\u8868\uFF08\u987A\u5E8F\u5373\u663E\u793A\u987A\u5E8F\uFF09\u3002 */\nexport interface QuickPromptCategory {\n readonly id: string\n readonly name: string\n readonly prompts: readonly QuickPrompt[]\n}\n\n/** \u5168\u5C40\u5FEB\u6377\u6307\u4EE4\u672C\uFF1A\u5206\u7C7B\u4E24\u7EA7\u7ED3\u6784\uFF0C\u843D\u76D8\u6210\u4E00\u4EFD JSON \u6587\u4EF6\u3002 */\nexport interface QuickPromptBook {\n readonly version: number\n readonly categories: readonly QuickPromptCategory[]\n}\n\n/** \u5185\u7F6E\u9ED8\u8BA4\u672C\uFF1A\u4E00\u4E2A\u300C\u9ED8\u8BA4\u300D\u5206\u7C7B\u88C5\u90A3 9 \u6761\u3002 */\nexport function defaultQuickBook(): QuickPromptBook {\n return {\n version: QUICK_BOOK_VERSION,\n categories: [{ id: 'cat-default', name: DEFAULT_CATEGORY_NAME, prompts: DEFAULT_QUICK_PROMPTS }],\n }\n}\n\n/** \u6587\u4EF6\u91CC\u7684\u5206\u7C7B\u5F62\u72B6\uFF08\u5199\u76D8\u7528\uFF1B\u4E0E\u53C2\u8003\u5B9E\u73B0\u540C\u540D\u5B57\u6BB5\uFF09\u3002 */\nexport interface QuickCategoryFileRow {\n readonly id: string\n readonly name: string\n readonly prompts: readonly {\n readonly id: string\n readonly title: string\n readonly text: string\n readonly autoSend: boolean\n /** \u300C\u4EC5\u9996\u6B21\u300D\u6807\u5FD7\uFF08\u6211\u4EEC\u7684\u6269\u5C55\u952E\uFF1B\u53C2\u8003\u5B9E\u73B0\u4F1A\u5FFD\u7565\u5B83\uFF0C\u5199\u56DE\u65F6\u53EF\u80FD\u4E22\u6389\uFF09\u3002 */\n readonly autoSendFirst?: boolean\n readonly order: number\n }[]\n}\n\n/** \u6536\u7A84\u4E00\u6761\uFF1A\u5185\u90E8\u5B57\u6BB5\u540D\uFF08label/prompt/always\uFF09\u4E0E\u6587\u4EF6\u5B57\u6BB5\u540D\uFF08title/text/autoSend\uFF09\u90FD\u8BA4\u3002 */\nfunction asPromptRow(value: unknown): { readonly prompt: QuickPrompt; readonly order?: number } | undefined {\n if (typeof value !== 'object' || value === null) return undefined\n const row = value as Record<string, unknown>\n const either = (first: unknown, second: unknown): string => {\n const picked = typeof first === 'string' && first !== '' ? first : second\n return typeof picked === 'string' ? picked : ''\n }\n const prompt = either(row.prompt, row.text).slice(0, QUICK_TEXT_MAX).trim()\n if (prompt === '') return undefined\n const label = either(row.label, row.title).slice(0, QUICK_LABEL_MAX).trim()\n const id = typeof row.id === 'string' && row.id !== '' ? row.id.slice(0, 64) : newQuickPromptId()\n const order = typeof row.order === 'number' && Number.isFinite(row.order)\n ? Math.max(1, Math.round(row.order))\n : undefined\n return {\n prompt: {\n id,\n label: label === '' ? prompt.slice(0, 12) : label,\n prompt,\n always: row.always === true || row.autoSend === true,\n firstOnly: row.firstOnly === true || row.autoSendFirst === true,\n },\n order,\n }\n}\n\n/** \u6536\u7A84\u4E00\u4E2A\u5217\u8868\uFF1A\u6309 id \u53BB\u91CD\u4FDD\u5E8F\u3001\u6309 order \u5347\u5E8F\uFF08\u6CA1\u6709 order \u7684\u4FDD\u6301\u539F\u76F8\u5BF9\u4F4D\u7F6E\uFF09\u3001\u9650\u91CF\u3002 */\nfunction toPromptList(values: readonly unknown[]): readonly QuickPrompt[] {\n const rows: { prompt: QuickPrompt; order?: number; index: number }[] = []\n for (const value of values) {\n const row = asPromptRow(value)\n if (row !== undefined) rows.push({ ...row, index: rows.length })\n }\n rows.sort((a, b) => {\n const left = a.order ?? Number.MAX_SAFE_INTEGER\n const right = b.order ?? Number.MAX_SAFE_INTEGER\n return left === right ? a.index - b.index : left - right\n })\n const seen = new Set<string>()\n const out: QuickPrompt[] = []\n for (const row of rows) {\n if (out.length >= QUICK_PROMPT_MAX) break\n if (seen.has(row.prompt.id)) continue\n seen.add(row.prompt.id)\n out.push(row.prompt)\n }\n return out\n}\n\n/**\n * \u628A\u4EFB\u610F\u6765\u6E90\u6536\u7A84\u6210\u4E00\u672C\uFF08\u6587\u4EF6\u5185\u5BB9\u3001HTTP \u8BF7\u6C42\u4F53\u90FD\u8D70\u8FD9\u91CC\uFF09\u3002\n * @param value \u4EFB\u610F\u503C\u3002\n * @returns \u6536\u7A84\u540E\u7684\u672C\uFF1B**\u8BA4\u4E0D\u51FA\u7684\u5F62\u72B6\u8FD4\u56DE undefined** \u2014\u2014 \u8C03\u7528\u65B9\u5FC5\u987B\u628A\u5B83\u5F53\u6210\u635F\u574F\uFF0C\n * \u7EDD\u4E0D\u80FD\u56DE\u9000\u6210\u7A7A\u672C\u518D\u5199\u56DE\u53BB\uFF08\u90A3\u4F1A\u628A\u7528\u6237\u6570\u636E\u62B9\u6389\uFF09\u3002\n */\nexport function sanitizeBook(value: unknown): QuickPromptBook | undefined {\n if (typeof value !== 'object' || value === null) return undefined\n const source = value as Record<string, unknown>\n\n // v1 \u5E73\u94FA\uFF08\u88F8\u6570\u7EC4\uFF0C\u6216 { prompts: [...] }\uFF09\uFF1A\u5347\u7EA7\u6210\u4E00\u4E2A\u300C\u9ED8\u8BA4\u300D\u5206\u7C7B\u3002\n const flat = Array.isArray(value) ? value : (Array.isArray(source.prompts) ? source.prompts : undefined)\n if (flat !== undefined) {\n const prompts = toPromptList(flat)\n return {\n version: QUICK_BOOK_VERSION,\n categories: prompts.length === 0\n ? []\n : [{ id: 'cat-default', name: DEFAULT_CATEGORY_NAME, prompts }],\n }\n }\n\n if (!Array.isArray(source.categories)) return undefined\n const seen = new Set<string>()\n const categories: QuickPromptCategory[] = []\n for (const raw of source.categories) {\n if (categories.length >= QUICK_CATEGORY_MAX) break\n if (typeof raw !== 'object' || raw === null) continue\n const row = raw as Record<string, unknown>\n const prompts = toPromptList(Array.isArray(row.prompts) ? row.prompts : [])\n // \u7A7A\u5206\u7C7B**\u4FDD\u7559**\uFF08\u8FD9\u70B9\u4E0E\u53C2\u8003\u5B9E\u73B0\u4E0D\u540C\uFF09\uFF1A\u9762\u677F\u7684\u300C\uFF0B\u300D\u53EA\u662F\u65B0\u5EFA\u4E00\u4E2A\u5206\u7C7B\uFF0C\u7528\u6237\u63A5\u4E0B\u6765\n // \u624D\u4F1A\u5F80\u91CC\u653E\u6761\u76EE\uFF1B\u82E5\u5728\u8FD9\u91CC\u4E22\u6389\uFF0C\u70B9\u300C\uFF0B\u300D\u5C31\u4F1A\u770B\u8D77\u6765\u6BEB\u65E0\u53CD\u5E94\uFF080.3.0 \u771F\u673A\u4E0A\u8E29\u5230\uFF09\u3002\n // \u7A7A\u5206\u7C7B\u5728\u6587\u4EF6\u91CC\u4E5F\u662F\u5408\u6CD5\u72B6\u6001\uFF0C\u6570\u91CF\u4E0A\u9650\u7531 QUICK_CATEGORY_MAX \u515C\u4F4F\u3002\n const wanted = typeof row.id === 'string' && row.id !== '' ? row.id.slice(0, 64) : newQuickCategoryId()\n const id = seen.has(wanted) ? newQuickCategoryId() : wanted\n seen.add(id)\n const name = (typeof row.name === 'string' ? row.name : '').slice(0, QUICK_CATEGORY_NAME_MAX).trim()\n categories.push({ id, name: name === '' ? DEFAULT_CATEGORY_NAME : name, prompts })\n }\n return { version: QUICK_BOOK_VERSION, categories }\n}\n\n/** \u5185\u90E8\u7ED3\u6784 \u2192 \u6587\u4EF6\u7ED3\u6784\uFF08\u5199\u76D8\u65F6\u7528\uFF1B\u987A\u5E8F\u5373 order\uFF09\u3002 */\nexport function bookToFile(book: QuickPromptBook): { version: number; categories: readonly QuickCategoryFileRow[] } {\n return {\n version: QUICK_BOOK_VERSION,\n categories: book.categories.map(category => ({\n id: category.id,\n name: category.name,\n prompts: category.prompts.map((prompt, index) => ({\n id: prompt.id,\n title: prompt.label,\n text: prompt.prompt,\n autoSend: prompt.always,\n // \u300C\u4EC5\u9996\u6B21\u300D\u662F\u6211\u4EEC\u52A0\u7684\u952E\uFF0C\u53EA\u5728\u4E3A\u771F\u65F6\u5199\u51FA\u6765\uFF1A\u6587\u4EF6\u5F62\u72B6\u5C3D\u91CF\u8D34\u8FD1\u53C2\u8003\u5B9E\u73B0\u3002\n ...(prompt.firstOnly ? { autoSendFirst: true } : {}),\n order: index + 1,\n })),\n })),\n }\n}\n\n/** \u8DE8\u5206\u7C7B\u62CD\u5E73\uFF08\u9762\u677F\u5217\u8868\u3001\u603B\u6761\u6570\u7EDF\u8BA1\u7528\uFF09\u3002 */\nexport function flattenQuickPrompts(book: QuickPromptBook): readonly QuickPrompt[] {\n return book.categories.flatMap(category => category.prompts)\n}\n\n/** \u53EA\u53D6\u300C\u6BCF\u6B21\u300D\u7684\u90A3\u4E9B\uFF08\u6BCF\u6B21\u53D1\u9001\u90FD\u9644\u52A0\uFF1B\u8DE8\u6240\u6709\u5206\u7C7B\uFF09\u3002 */\nexport function alwaysQuickPrompts(book: QuickPromptBook): readonly QuickPrompt[] {\n return flattenQuickPrompts(book).filter(prompt => insertModeOf(prompt) === 'always')\n}\n\n/** \u53EA\u53D6\u300C\u4EC5\u9996\u6B21\u300D\u7684\u90A3\u4E9B\uFF08\u8DE8\u6240\u6709\u5206\u7C7B\uFF09\u3002 */\nexport function firstOnlyQuickPrompts(book: QuickPromptBook): readonly QuickPrompt[] {\n return flattenQuickPrompts(book).filter(prompt => insertModeOf(prompt) === 'first')\n}\n\n/**\n * \u8FD9\u4E00\u6B21\u53D1\u9001\u8981\u9644\u52A0\u7684\u6279\u6B21\u3002\n *\n * @param book \u5F53\u524D\u8FD9\u672C\u3002\n * @param blank \u4F1A\u8BDD\u5FEB\u7167\u7684 `blank`\uFF1Atrue = \u8FD9\u4E2A\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u4EFB\u4F55\u6D88\u606F\uFF08\u4E5F\u5C31\u662F\u7B2C\u4E00\u6761\uFF09\u3002\n * @returns \u987A\u5E8F = \u300C\u6BCF\u6B21\u300D\u7684\u90A3\u4E9B\uFF0C\u518D\u8DDF\u4E0A\u300C\u4EC5\u9996\u6B21\u300D\u7684\u90A3\u4E9B\uFF08\u4EC5\u9996\u6B21\u53EA\u5728\u7B2C\u4E00\u6761\u4E0A\u51FA\u73B0\uFF09\u3002\n */\nexport function appendBatchForSend(book: QuickPromptBook, blank: boolean): readonly QuickPrompt[] {\n const every = alwaysQuickPrompts(book)\n if (!blank) return every\n return [...every, ...firstOnlyQuickPrompts(book)]\n}\n\n// \u2500\u2500 OpenCode \u8BF7\u6C42\u5934 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// OpenCode \u7684\u63A5\u53E3\u8981\u6C42\u5BA2\u6237\u7AEF\u6BCF\u6B21\u8BF7\u6C42\u90FD\u5E26\u4E00\u4E2A\u7A33\u5B9A\u7684\u4F1A\u8BDD ID \u8BF7\u6C42\u5934\n// \uFF08\u5B98\u65B9 Go \u6587\u6863\u300C\u53EF\u4EE5\u5728\u54EA\u91CC\u4F7F\u7528\uFF1F\u300D\u7B2C 3 \u6761\uFF09\u3002DSH \u7684 Models \u8BBE\u7F6E\u9875\u660E\u786E\u4E0D\u63D0\u4F9B\n// \u8BF7\u6C42\u5934\u7F16\u8F91\u5668\uFF0C\u6240\u4EE5\u672C\u63D2\u4EF6\u628A\u8FD9\u4E00\u9879\u5199\u8FDB llm-pi-ai \u7684 provider profile.headers \u2014\u2014\n// \u90A3\u662F DSH \u91CC\u552F\u4E00\u53D7\u652F\u6301\u7684\u51FA\u7F51\u8BF7\u6C42\u5934\u5165\u53E3\uFF08\u4F1A\u5728 pi-ai \u4FA7\u6700\u540E\u5408\u5E76\uFF0C\u4E0B\u4E00\u6B21\u8BF7\u6C42\u751F\u6548\uFF09\u3002\n\n/** \u8BF7\u6C42\u5934\u680F\u76EE\u5B57\u6BB5\u540D\u3002 */\nexport const HEADER_ENABLED_FIELD = 'headerEnabled'\nexport const HEADER_NAME_FIELD = 'headerName'\nexport const HEADER_VALUE_FIELD = 'headerValue'\n/** \u4F5C\u7528\u8DEF\u7531\u540D\u5355\uFF08\u9017\u53F7/\u7A7A\u683C\u5206\u9694\uFF09\uFF1B\u7559\u7A7A = \u81EA\u52A8\u5339\u914D OpenCode \u8DEF\u7531\uFF08\u89C1 OPENCODE_ROUTE_PREFIX / OPENCODE_HOSTS\uFF09\u3002 */\nexport const HEADER_ROUTES_FIELD = 'headerRoutes'\n\n/** \u5BBF\u4E3B\u534A\u8BB0\u8D26\uFF1A\u4E0A\u6B21\u5B9E\u9645\u5199\u5165\u7684\u5934\u540D\u4E0E\u503C\uFF08\u51B3\u5B9A\u505C\u7528/\u6539\u540D\u65F6\u64A4\u9500\u54EA\u4E9B\u952E\uFF09\u3002 */\nexport const HEADER_APPLIED_NAME_FIELD = 'headerAppliedName'\nexport const HEADER_APPLIED_VALUE_FIELD = 'headerAppliedValue'\n\n/** \u5BBF\u4E3B\u534A\u5199\u5165\u7684\u6267\u884C\u7ED3\u679C\uFF1B\u8BBE\u7F6E\u9875\u53EA\u8BFB\u5C55\u793A\u3002 */\nexport const HEADER_STATUS_FIELD = 'headerStatus'\n\n/**\n * \u53EA\u5728\u5BBF\u4E3B\u534A\u7EF4\u62A4\u7684\u5B57\u6BB5\uFF1A\u8BBE\u7F6E\u9875\u300C\u6062\u590D\u9ED8\u8BA4\u300D\u4E0D\u5F97\u6E05\u7A7A\u5B83\u4EEC\uFF0C\n * \u5426\u5219\u5DF2\u5199\u5165\u7684\u5934\u4F1A\u5931\u53BB\u8BB0\u8D26\u3001\u6C38\u8FDC\u64A4\u9500\u4E0D\u6389\u3002\n *\n * \u300C\u9ED8\u8BA4\u7EC8\u7AEF\u300D\u7684\u4E09\u4E2A\u81EA\u6301\u5B57\u6BB5\u540C\u7406\uFF1A\u5019\u9009\u8868\u4E0E\u72B6\u6001\u662F**\u5BBF\u4E3B\u534A\u7684\u63A2\u6D4B\u7ED3\u679C**\uFF0C\n * \u6E05\u6389\u4E4B\u540E\u754C\u9762\u4F1A\u53D8\u6210\"\u6CA1\u63A2\u6D4B\u8FC7\"\u7684\u6837\u5B50\uFF08\u800C\u5B9E\u9645\u8FD8\u5728\u7528\u67D0\u4E2A bash\uFF09\uFF0C\n * \u7528\u6237\u70B9\u4E00\u6B21\u300C\u6062\u590D\u9ED8\u8BA4\u300D\u5C31\u4F1A\u770B\u5230\u81EA\u76F8\u77DB\u76FE\u7684\u72B6\u6001\u3002\n */\nexport const HOST_OWNED_FIELDS = [\n HEADER_APPLIED_NAME_FIELD,\n HEADER_APPLIED_VALUE_FIELD,\n HEADER_STATUS_FIELD,\n TERMINAL_CANDIDATES_FIELD,\n TERMINAL_STATUS_FIELD,\n TERMINAL_EFFECTIVE_FIELD,\n] as const\n\n/** \u8BF7\u6C42\u5934\u6700\u7EC8\u843D\u5730\u7684\u8BBE\u7F6E\u547D\u540D\u7A7A\u95F4\uFF08\u7531 llm-pi-ai \u6CE8\u518C\uFF09\u3002 */\nexport const LLM_NAMESPACE = 'llm-pi-ai'\n\n/**\n * \u81EA\u52A8\u5339\u914D\u7684\u4E24\u6761\u5224\u636E\uFF08\u6EE1\u8DB3\u5176\u4E00\u5373\u7B97 OpenCode \u8DEF\u7531\uFF09\uFF1A\n * 1. \u8DEF\u7531\u540D\u4EE5 `opencode` \u5F00\u5934\u2014\u2014DSH \u5185\u7F6E\u7684 `opencode-go` \u5C31\u5C5E\u4E8E\u8FD9\u79CD\uFF0C\n * \u5B83\u7684 baseURL \u7531 pi-ai \u76EE\u5F55\u5185\u7F6E\uFF0C\u914D\u7F6E\u91CC\u8BFB\u4E0D\u5230\uFF0C\u53EA\u80FD\u9760\u540D\u5B57\u3002\n * 2. \u8BE5\u8DEF\u7531\u7684 `baseURL` \u4E3B\u673A\u662F opencode.ai\uFF08\u542B\u5B50\u57DF\uFF09\u2014\u2014\u7528\u6237\u81EA\u5EFA\u8DEF\u7531\u5E38\u8D77\u4EFB\u610F\u540D\u5B57\n * \uFF08\u4F8B\u5982 `go`\uFF09\uFF0C\u4F46\u7AEF\u70B9\u7167\u6837\u662F OpenCode\uFF0C\u6309 URL \u8BA4\u6BD4\u6309\u540D\u5B57\u8BA4\u53EF\u9760\u3002\n */\nexport const OPENCODE_ROUTE_PREFIX = 'opencode'\n\n/** \u5224\u636E 2 \u7528\u7684\u4E3B\u673A\u540D\uFF08\u542B\u5B50\u57DF\uFF09\u3002 */\nexport const OPENCODE_HOSTS = ['opencode.ai'] as const\n\n/** \u5934\u540D\u9ED8\u8BA4\u503C = OpenCode \u5B98\u65B9\u8981\u6C42\u7684\u90A3\u4E00\u4E2A\u3002 */\nexport const DEFAULT_HEADER_NAME = 'x-opencode-session'\n\n/** \u5934\u503C\u957F\u5EA6\u4E0A\u9650\uFF08HTTP \u5934\u4E0E\u8BBE\u7F6E\u6587\u6863\u90FD\u4E0D\u5B9C\u8FC7\u957F\uFF09\u3002 */\nexport const HEADER_VALUE_MAX = 200\n\n/** \u5934\u540D\u957F\u5EA6\u4E0A\u9650\u3002 */\nexport const HEADER_NAME_MAX = 64\n\n/** \u5168\u90E8\u53EF\u6301\u4E45\u5316\u5B57\u6BB5\u3002 */\nexport type SettingsField =\n | typeof ENABLED_FIELD\n | typeof KEYS_ENABLED_FIELD\n | typeof MENU_ENABLED_FIELD\n | typeof QUICK_ENABLED_FIELD\n | typeof PANEL_ENABLED_FIELD\n | typeof TERMINAL_ENABLED_FIELD\n | typeof SEND_KEY_FIELD\n | typeof NEWLINE_KEY_FIELD\n | typeof PANEL_RESIZE_FIELD\n | typeof PANEL_WIDTH_FIELD\n | typeof PANEL_HEIGHT_FIELD\n | typeof MENU_NATIVE_FIELD\n | typeof MENU_MODE_FIELD\n | typeof HEADER_ENABLED_FIELD\n | typeof HEADER_NAME_FIELD\n | typeof HEADER_VALUE_FIELD\n | typeof HEADER_ROUTES_FIELD\n | typeof QUICK_PROMPTS_FIELD\n | typeof OPTIMIZER_TIER_FIELD\n | typeof OPTIMIZER_PROMPT_FIELDS.basic\n | typeof OPTIMIZER_PROMPT_FIELDS.advanced\n | typeof OPTIMIZER_PROMPT_FIELDS.extreme\n | typeof TERMINAL_MODE_FIELD\n | typeof TERMINAL_BASH_PATH_FIELD\n | MenuField\n\n/** \u9F20\u6807\u53F3\u952E\u83DC\u5355\u6253\u5F00\u65F6\u7684\u4E00\u6B21\u5FEB\u7167\uFF08\u542B\u4F4D\u7F6E\u4E0E\u9009\u62E9\u72B6\u6001\uFF09\u3002 */\nexport interface MenuState {\n /** \u89C6\u53E3\u5750\u6807\u3002 */\n readonly x: number\n readonly y: number\n /** \u53F3\u952E\u65F6\u8F93\u5165\u6846\u5185\u662F\u5426\u6709\u975E\u6298\u53E0\u9009\u533A\uFF08\u51B3\u5B9A\u526A\u5207/\u590D\u5236/\u5220\u9664\u662F\u5426\u53EF\u7528\uFF09\u3002 */\n readonly hasSelection: boolean\n /** \u7C98\u8D34\u5931\u8D25\u65F6\u7684\u77ED\u6682\u63D0\u793A\u3002 */\n readonly note?: string\n}\n\n/** \u89E3\u6790\u540E\u7684\u8BBE\u7F6E\u3002 */\nexport interface ComposerUxSettings {\n /** \u5168\u5C40\u603B\u5F00\u5173\uFF1Afalse \u65F6\u672C\u63D2\u4EF6\u6240\u6709\u529F\u80FD\u505C\u7528\u3002\u9ED8\u8BA4**\u5F00**\u3002 */\n enabled: boolean\n /**\n * \u516D\u680F\u5404\u81EA\u7684\u5F00\u5173\uFF1A`enabled && \u8BE5\u680F\u5F00\u5173` \u624D\u751F\u6548\u3002\u9ED8\u8BA4**\u5173**\uFF08\u8001\u7528\u6237\u6309\"\u78B0\u8FC7\u6CA1\"\u8FC1\u79FB\uFF0C\u89C1\n * `sectionEnabledOf`\uFF09\u3002\u300COpenCode \u8BF7\u6C42\u5934\u300D\u90A3\u4E00\u680F\u76F4\u63A5\u7528 `headerEnabled`\uFF0C\u6CA1\u6709\u5355\u72EC\u7684\u952E\u3002\n */\n keysEnabled: boolean\n menuEnabled: boolean\n quickEnabled: boolean\n panelEnabled: boolean\n terminalEnabled: boolean\n /** \u53D1\u9001\u952E\u4F4D\u89C4\u8303\u4E32\uFF08\u5982 'Enter'\u3001'Ctrl+Enter'\u3001''=\u65E0\uFF09\u3002 */\n sendKey: string\n /** \u6362\u884C\u952E\u4F4D\u89C4\u8303\u4E32\u3002 */\n newlineKey: string\n menuUndo: boolean\n menuRedo: boolean\n menuCut: boolean\n menuCopy: boolean\n menuPaste: boolean\n menuDelete: boolean\n menuSelectAll: boolean\n /**\n * \u53F3\u952E\u83DC\u5355\u6A21\u5F0F\uFF08\u5B98\u65B9\u4E0D\u4ECB\u5165 / \u6D4F\u89C8\u5668\u83DC\u5355 / \u81EA\u5B9A\u4E49\u83DC\u5355\uFF09\u3002\n * \u6587\u6863\u91CC\u6CA1\u6709\u8FD9\u4E2A\u5B57\u6BB5\u65F6\u6309\u65E7\u5E03\u5C14 `menuNative` \u63A8\u65AD\uFF0C\u89C1 `menuModeFrom`\u3002\n */\n menuMode: MenuMode\n /** \u8BBE\u7F6E\u9762\u677F\uFF1A\u5141\u8BB8\u62D6\u62FD\u8FB9\u7F18\u8C03\u6574\u5927\u5C0F\u3002 */\n panelResize: boolean\n /** \u8BBE\u7F6E\u9762\u677F\u5BBD\uFF08px\uFF09\uFF1B\u7F3A\u7701\u4F7F\u7528\u5B98\u65B9\u9ED8\u8BA4 800\u3002 */\n panelWidth?: number\n /** \u8BBE\u7F6E\u9762\u677F\u9AD8\uFF08px\uFF09\uFF1B\u7F3A\u7701\u4F7F\u7528\u5B98\u65B9\u9ED8\u8BA4 min(800, \u89C6\u53E3-48)\u3002 */\n panelHeight?: number\n /** OpenCode \u8BF7\u6C42\u5934\uFF1A\u542F\u7528\u540E\u5199\u8FDB llm-pi-ai \u7684 opencode \u7CFB\u8DEF\u7531\u3002 */\n headerEnabled: boolean\n /** \u5934\u540D\uFF08\u9ED8\u8BA4 x-opencode-session\uFF09\u3002 */\n headerName: string\n /** \u5934\u503C\uFF1B\u7559\u7A7A\u65F6\u9996\u6B21\u542F\u7528\u7531\u5BBF\u4E3B\u534A\u751F\u6210\u4E00\u4E2A\u7A33\u5B9A ID \u5E76\u843D\u76D8\u6CBF\u7528\u3002 */\n headerValue: string\n /** \u4F5C\u7528\u8DEF\u7531\u540D\u5355\uFF1B\u7559\u7A7A = \u81EA\u52A8\u5339\u914D opencode \u7CFB\u8DEF\u7531\uFF08\u53EA\u52A8\u5DF2\u5B58\u5728\u7684\u8DEF\u7531\uFF09\u3002 */\n headerRoutes: string\n /** \u5BBF\u4E3B\u534A\u8BB0\u8D26\u5B57\u6BB5\uFF08\u8BBE\u7F6E\u9875\u53EA\u8BFB\uFF09\u3002 */\n headerAppliedName: string\n headerAppliedValue: string\n /** \u5BBF\u4E3B\u534A\u5199\u5165\u7ED3\u679C\uFF08\u8BBE\u7F6E\u9875\u53EA\u8BFB\uFF09\u3002 */\n headerStatus: string\n /** \u5FEB\u6377\u6307\u4EE4\u5217\u8868\uFF08\u987A\u5E8F\u5373\u9762\u677F\u4E0E\u8BBE\u7F6E\u9875\u91CC\u7684\u663E\u793A\u987A\u5E8F\uFF09\u3002 */\n quickPrompts: readonly QuickPrompt[]\n /** \u63D0\u793A\u8BCD\u4F18\u5316\u5F3A\u5EA6\u6863\u4F4D\u3002 */\n optimizerTier: OptimizerTier\n /**\n * \u4E09\u6863\u7684**\u81EA\u5B9A\u4E49**\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF1B\u7559\u7A7A = \u7528 `optimizer-prompt.ts` \u91CC\u7684\u5185\u7F6E\u90A3\u4EFD\u3002\n *\n * \u6539\u7684\u662F\u300C\u4EFB\u52A1\u4E0E\u98CE\u683C\u300D\u90A3\u4E00\u6BB5\uFF1BJSON \u8F93\u51FA\u5951\u7EA6\u7531\u63D2\u4EF6\u5728\u672B\u5C3E\u8FFD\u52A0\u3001\u4E0D\u7531\u8FD9\u91CC\u63A7\u5236\n * \uFF08\u5B83\u7684\u4F5C\u7528\u662F\u8BA9\u5BBF\u4E3B\u80FD\u6309\u9010\u5B57\u4F9D\u636E\u6821\u9A8C\u6BCF\u4E00\u6761\uFF0C\u88AB\u6539\u6389\u6574\u4E2A\u673A\u5236\u5C31\u5931\u6548\u4E86\uFF09\u3002\n */\n optimizerPromptBasic: string\n optimizerPromptAdvanced: string\n optimizerPromptExtreme: string\n /**\n * \u300C\u9ED8\u8BA4\u7EC8\u7AEF\u300D\u6863\u4F4D\uFF1A\u81EA\u52A8 / Git Bash / PowerShell\u3002\u53EA\u5BF9 Windows \u751F\u6548\n * \uFF08\u975E Windows \u4E0A\u5BBF\u4E3B\u534A\u76F4\u63A5\u8DF3\u8FC7\uFF0C\u5361\u7247\u663E\u793A\"\u4E0D\u9700\u8981\"\uFF09\u3002\n */\n terminalMode: TerminalMode\n /** \u7528\u6237\u6307\u5B9A\u7684 Git Bash \u8DEF\u5F84\uFF1B\u7559\u7A7A = \u7528\u63A2\u6D4B\u5230\u7684\u7B2C\u4E00\u4E2A\u5019\u9009\u3002 */\n terminalBashPath: string\n /** \u5BBF\u4E3B\u534A\u63A2\u6D4B\u5230\u7684\u5019\u9009\uFF08\u53EA\u8BFB\u5C55\u793A\uFF0C\u89C1 HOST_OWNED_FIELDS\uFF09\u3002 */\n terminalCandidates: readonly TerminalCandidate[]\n /** \u5BBF\u4E3B\u534A\u5199\u7684\u72B6\u6001\u884C\uFF1A\u5F53\u524D\u751F\u6548 shell / \u4E3A\u4EC0\u4E48\u6CA1\u751F\u6548\uFF08\u53EA\u8BFB\u5C55\u793A\uFF09\u3002 */\n terminalStatus: string\n /** \u5BBF\u4E3B\u534A\u5199\u7684\u5F53\u524D\u751F\u6548 shell\uFF1A'bash' / 'pwsh'\uFF08\u53EA\u8BFB\u5C55\u793A\uFF09\u3002 */\n terminalEffective: string\n}\n\n/** \u9ED8\u8BA4\u503C = DSH Web \u73B0\u72B6\uFF08Enter \u53D1\u9001\u3001Shift+Enter \u6362\u884C\u3001\u53F3\u952E\u83DC\u5355\u5168\u5F00\uFF09\u3002 */\nexport const DEFAULT_SETTINGS: ComposerUxSettings = {\n // \u603B\u5F00\u5173\u9ED8\u8BA4\u5F00\uFF1A\u5B83\u53EA\u662F\u603B\u95F8\uFF0C\u771F\u6B63\"\u8981\u4E0D\u8981\u7528\u8FD9\u4E00\u680F\"\u7531\u4E0B\u9762\u4E94\u4E2A\u5F00\u5173\u51B3\u5B9A\uFF08\u9ED8\u8BA4\u5173\uFF09\u3002\n enabled: true,\n // \u4E94\u680F\u9ED8\u8BA4\u5173\uFF08\u8001\u6587\u6863\u7531 sectionEnabledOf \u8FC1\u79FB\u6210\"\u78B0\u8FC7\u5C31\u5F00\"\uFF09\u3002\n keysEnabled: false,\n menuEnabled: false,\n quickEnabled: false,\n panelEnabled: false,\n terminalEnabled: false,\n sendKey: 'Enter',\n newlineKey: 'Shift+Enter',\n menuUndo: true,\n menuRedo: true,\n menuCut: true,\n menuCopy: true,\n menuPaste: true,\n menuDelete: true,\n menuSelectAll: true,\n menuMode: 'official',\n panelResize: true,\n headerEnabled: false,\n headerName: DEFAULT_HEADER_NAME,\n headerValue: '',\n headerRoutes: '',\n headerAppliedName: '',\n headerAppliedValue: '',\n headerStatus: '',\n quickPrompts: DEFAULT_QUICK_PROMPTS,\n optimizerTier: DEFAULT_OPTIMIZER_TIER,\n // \u7A7A\u4E32 = \u7528\u5185\u7F6E\u63D0\u793A\u8BCD\u3002\u9ED8\u8BA4\u5FC5\u987B\u662F\u7A7A\u4E32\uFF1A\u5B83\u540C\u65F6\u5C31\u662F\u300C\u6062\u590D\u5185\u7F6E\u300D\u8981\u5199\u56DE\u53BB\u7684\u503C\u3002\n optimizerPromptBasic: '',\n optimizerPromptAdvanced: '',\n optimizerPromptExtreme: '',\n terminalMode: DEFAULT_TERMINAL_MODE,\n terminalBashPath: '',\n terminalCandidates: [],\n terminalStatus: '',\n terminalEffective: '',\n}\n\n/**\n * \u516D\u680F\u91CC\u54EA\u51E0\u680F\u751F\u6548\uFF1A**\u603B\u5F00\u5173 +\uFF08OpenCode \u90A3\u680F\u7528\u81EA\u5DF1\u7684 `headerEnabled`\uFF09+ \u8BE5\u680F\u5F00\u5173**\u3002\n *\n * \u5BBF\u4E3B\u534A\u4E0E\u5BA2\u6237\u7AEF\u534A\u90FD\u8D70\u8FD9\u4E00\u4E2A\u51FD\u6570\uFF0C\u514D\u5F97\u6709\u4EBA\u53EA\u770B\u4E86\u680F\u5F00\u5173\u3001\u5FD8\u4E86\u603B\u95F8\uFF08\u6216\u8005\u53CD\u8FC7\u6765\uFF09\u3002\n */\nexport function activeSections(settings: ComposerUxSettings): {\n readonly keys: boolean\n readonly menu: boolean\n readonly quick: boolean\n readonly panel: boolean\n readonly header: boolean\n readonly terminal: boolean\n} {\n const on = settings.enabled\n return {\n keys: on && settings.keysEnabled,\n menu: on && settings.menuEnabled,\n quick: on && settings.quickEnabled,\n panel: on && settings.panelEnabled,\n header: on && settings.headerEnabled,\n terminal: on && settings.terminalEnabled,\n }\n}\n\n/** \u8BBE\u7F6E\u9875\u300C\u952E\u4F4D\u300D\u4E00\u8282\u7684\u9884\u8BBE\u3002 */\nexport const SEND_PRESETS: readonly string[] = ['Enter', 'Ctrl+Enter', 'Alt+Enter', 'Shift+Enter']\nexport const NEWLINE_PRESETS: readonly string[] = ['Shift+Enter', 'Enter', 'Ctrl+Enter', 'Alt+Enter']\n\n/** \u53F3\u952E\u83DC\u5355\u6761\u76EE\uFF08\u987A\u5E8F\u5373\u663E\u793A\u987A\u5E8F\uFF1Bshortcut \u4E0E\u56FE\u7247\u4E00\u81F4\uFF09\u3002 */\nexport const MENU_ITEMS: readonly {\n readonly field: MenuField\n readonly label: string\n readonly shortcut: string\n}[] = [\n { field: 'menuUndo', label: '\u64A4\u9500', shortcut: 'Ctrl+Z' },\n { field: 'menuRedo', label: '\u91CD\u505A', shortcut: 'Ctrl+Y' },\n { field: 'menuCut', label: '\u526A\u5207', shortcut: 'Ctrl+X' },\n { field: 'menuCopy', label: '\u590D\u5236', shortcut: 'Ctrl+C' },\n { field: 'menuPaste', label: '\u7C98\u8D34', shortcut: 'Ctrl+V' },\n { field: 'menuDelete', label: '\u5220\u9664', shortcut: '' },\n { field: 'menuSelectAll', label: '\u5168\u9009', shortcut: 'Ctrl+A' },\n]\n\n/**\n * \u751F\u6210\u4E00\u4E2A\u7A33\u5B9A\u7684\u4F1A\u8BDD ID\uFF08UUID v4\uFF1B\u65E0 crypto \u65F6\u9000\u56DE\u7B49\u4EF7\u7684\u968F\u673A\u5341\u516D\u8FDB\u5236\uFF09\u3002\n * \u503C\u672C\u8EAB\u4E0D\u53C2\u4E0E\u9274\u6743\uFF0C\u53EA\u7528\u4E8E\u8BA9\u7F51\u5173\u628A\u540C\u4E00\u6BB5\u5BF9\u8BDD\u56FA\u5B9A\u5230\u540C\u4E00\u4E2A\u4E0A\u6E38\uFF0C\u6545 Math.random \u515C\u5E95\u53EF\u63A5\u53D7\u3002\n * @returns 36 \u5B57\u7B26\u7684 UUID \u5B57\u7B26\u4E32\u3002\n */\nexport function newSessionId(): string {\n const bag = globalThis as unknown as { crypto?: { randomUUID?: () => string } }\n if (typeof bag.crypto?.randomUUID === 'function') return bag.crypto.randomUUID()\n const hex = (count: number): string => Array.from(\n { length: count },\n () => Math.floor(Math.random() * 16).toString(16),\n ).join('')\n return `${hex(8)}-${hex(4)}-4${hex(3)}-a${hex(3)}-${hex(12)}`\n}\n\n/** \u89E3\u6790\u300C\u4F5C\u7528\u8DEF\u7531\u300D\u6587\u672C\uFF1A\u9017\u53F7 / \u7A7A\u683C / \u6362\u884C\u5206\u9694\uFF0C\u53BB\u91CD\u4FDD\u5E8F\u3002 */\nexport function parseRouteList(text: string): readonly string[] {\n const parts = text.split(/[\\s,\uFF0C\u3001]+/).map(item => item.trim()).filter(item => item !== '')\n return [...new Set(parts)]\n}\n\n/**\n * \u6BCF\u680F\u7684\"\u7528\u6237\u78B0\u8FC7\u6CA1\"\u5224\u636E\uFF08\u8FC1\u79FB\u89C4\u5219\u7528\uFF0C\u89C1\u6587\u4EF6\u4E0A\u65B9\u90A3\u6BB5\u8BF4\u660E\uFF09\u3002\n *\n * \u26A0\uFE0F \u5224\u636E\u5FC5\u987B\u662F\u300C**\u503C\u4E0D\u7B49\u4E8E\"\u4ECE\u6CA1\u78B0\u8FC7\"\u7684\u6837\u5B50**\u300D\uFF0C\u4E0D\u80FD\u662F\u300C\u952E\u5B58\u5728\u300D\uFF1A\n * `settings.get()` \u7ED9\u7684\u662F**\u5DF2\u89E3\u6790**\u7684\u503C\uFF08schema \u9ED8\u8BA4\u503C + \u7EC4\u5408 base + \u7528\u6237\u5C42\uFF09\uFF0C\n * \u6240\u4EE5\u4ECE\u6CA1\u78B0\u8FC7\u7684\u4EBA\u7684\u6587\u6863\u91CC\u4E5F\u7167\u6837\u6709 `sendKey: 'Enter'`\u3001`panelScroll: true` \u8FD9\u4E9B\u9ED8\u8BA4\u503C \u2014\u2014\n * \u6309\"\u952E\u5B58\u5728\"\u5224\u65AD\u4F1A\u8BA9\u5168\u65B0\u5B89\u88C5\u516D\u680F\u5168\u5F00\uFF0C\u4E0E\"\u9ED8\u8BA4\u5173\"\u6B63\u597D\u76F8\u53CD\u3002\n * \uFF08\u7B2C\u4E00\u7248\u5C31\u5199\u6210\u4E86\"\u952E\u5B58\u5728\"\uFF0C\u662F\u63A8\u7406 + \u6D4B\u8BD5\u5F53\u573A\u902E\u4F4F\u7684\uFF0C\u6CE8\u91CA\u7559\u5728\u8FD9\u91CC\u9632\u590D\u53D1\u3002\uFF09\n *\n * \u53E6\u5916\uFF1A\u5BBF\u4E3B\u534A\u81EA\u6301\u5B57\u6BB5\uFF08`terminalStatus` / `terminalCandidates` / `terminalEffective` /\n * `headerApplied*`\uFF09**\u4E0D\u8BB8**\u5F53\u5224\u636E \u2014\u2014 \u5B83\u4EEC\u662F\u63D2\u4EF6\u81EA\u5DF1\u5199\u7684\uFF0C\u5168\u65B0\u5B89\u88C5\u4E5F\u4F1A\u51FA\u73B0\u3002\n *\n * \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u680F\u8FD8\u6709\u4E00\u4E2A\u6587\u6863\u91CC\u770B\u4E0D\u51FA\u6765\u7684\u4FE1\u53F7\uFF1A0.3.0 \u8D77\u6761\u76EE\u642C\u5230\u4E86 `quick-prompts.json`\uFF0C\n * \u7528\u8FC7\u7684\u4EBA\u548C\u6CA1\u7528\u8FC7\u7684\u4EBA\u7684\u8BBE\u7F6E\u6587\u6863\u53EF\u4EE5\u4E00\u6A21\u4E00\u6837\u3002\u90A3\u4E00\u6761\u7531\u5BBF\u4E3B\u534A\u8BFB\u6587\u4EF6\u540E**\u4E00\u6B21\u6027\u5199\u56DE\u6587\u6863**\n * \uFF08\u89C1 `src/host.ts` \u7684 `migrateQuickSection`\uFF09\uFF0C\u6240\u4EE5\u8FD9\u91CC\u53EA\u5269\"\u6587\u6863\u91CC\u7684\u5217\u8868\u88AB\u6539\u8FC7\"\u8FD9\u4E00\u6B21\u7EA7\u4FE1\u53F7\u3002\n */\nconst SECTION_SIGNALS: Readonly<Record<string, (source: Record<string, unknown>) => boolean>> = {\n [KEYS_ENABLED_FIELD]: source =>\n touched(source, SEND_KEY_FIELD, DEFAULT_SETTINGS.sendKey)\n || touched(source, NEWLINE_KEY_FIELD, DEFAULT_SETTINGS.newlineKey),\n // \u300C\u5B98\u65B9\u300D\uFF1D\u672C\u63D2\u4EF6\u4E0D\u4ECB\u5165\uFF0C\u7B49\u4EF7\u4E8E\u5173\uFF1B\u6240\u4EE5\u53EA\u6709\u9009\u8FC7\u53E6\u5916\u4E24\u6863\u624D\u7B97\"\u78B0\u8FC7\"\u3002\n // \uFF08`menuModeFrom` \u5BF9\"\u4E24\u4E2A\u952E\u90FD\u6CA1\u6709\"\u7ED9\u7684\u5C31\u662F 'official'\uFF0C\u5929\u7136\u6EE1\u8DB3\"\u7F3A\u7701 = \u9ED8\u8BA4\"\u3002\uFF09\n [MENU_ENABLED_FIELD]: source =>\n menuModeFrom(source[MENU_MODE_FIELD], source[MENU_NATIVE_FIELD]) !== 'official',\n [QUICK_ENABLED_FIELD]: source =>\n (Array.isArray(source[QUICK_PROMPTS_FIELD])\n && source[QUICK_PROMPTS_FIELD].length !== DEFAULT_QUICK_PROMPTS.length)\n || touched(source, OPTIMIZER_TIER_FIELD, DEFAULT_OPTIMIZER_TIER),\n [PANEL_ENABLED_FIELD]: source =>\n touched(source, PANEL_RESIZE_FIELD, true)\n || source[PANEL_WIDTH_FIELD] !== undefined\n || source[PANEL_HEIGHT_FIELD] !== undefined,\n [TERMINAL_ENABLED_FIELD]: source =>\n touched(source, TERMINAL_MODE_FIELD, DEFAULT_TERMINAL_MODE)\n || touched(source, TERMINAL_BASH_PATH_FIELD, ''),\n}\n\n/**\n * \u8FD9\u4E2A\u952E\u5728\u6587\u6863\u91CC**\u51FA\u73B0\u8FC7**\uFF0C\u4E14\u503C\u4E0D\u7B49\u4E8E\"\u4ECE\u6CA1\u78B0\u8FC7\u7684\u6837\u5B50\"\u3002\n *\n * \u4E24\u4E2A\u6761\u4EF6\u7F3A\u4E00\u4E0D\u53EF\uFF0C\u800C\u4E14\u7B2C\u4E8C\u534A\u6781\u6613\u6F0F\uFF1A\u6587\u6863\u91CC\u6CA1\u6709\u8FD9\u4E2A\u952E\u65F6\u503C\u662F `undefined`\uFF0C\n * \u62FF\u5B83\u53BB\u6BD4\u9ED8\u8BA4\u503C\u4F1A\u5F97\u51FA\"\u4E0D\u76F8\u7B49 \u21D2 \u78B0\u8FC7\"\uFF08`'' !== 'Enter'`\u3001`undefined !== true` \u90FD\u662F\u771F\uFF09\uFF0C\n * \u4E8E\u662F\u5168\u65B0\u5B89\u88C5\u516D\u680F\u5168\u5F00 \u2014\u2014 \u4E0E\"\u9ED8\u8BA4\u5173\"\u6B63\u597D\u76F8\u53CD\u3002\u7B2C\u4E00\u7248\u5C31\u662F\u8FD9\u4E48\u5199\u7684\uFF0C\u88AB\u6D4B\u8BD5\u5F53\u573A\u902E\u4F4F\u3002\n */\nfunction touched(source: Record<string, unknown>, field: string, untouched: unknown): boolean {\n const value = source[field]\n return value !== undefined && value !== untouched\n}\n\n/**\n * \u7B97\u51FA\u4E00\u680F\u5F00\u5173\u7684\u503C\uFF1A\u663E\u5F0F\u5199\u8FC7\u5C31\u542C\u5B83\u7684\uFF0C\u5426\u5219\u6309\"\u7528\u6237\u78B0\u8FC7\u6CA1\"\u63A8\u65AD\u3002\n * @param field \u680F\u5F00\u5173\u5B57\u6BB5\u540D\u3002\n * @param source \u8BBE\u7F6E\u6587\u6863\uFF08\u89E3\u6790\u540E\u7684\u503C\uFF1B\u7F3A\u7701\u7684\u952E\u4F1A\u88AB schemastery \u7701\u6389\uFF0C\u6240\u4EE5 undefined \u5C31\u662F\"\u6CA1\u5199\u8FC7\"\uFF09\u3002\n * @returns \u8BE5\u680F\u662F\u5426\u751F\u6548\u3002\n */\nexport function sectionEnabledOf(field: string, source: Record<string, unknown>): boolean {\n const explicit = source[field]\n if (typeof explicit === 'boolean') return explicit\n const signal = SECTION_SIGNALS[field]\n return signal === undefined ? false : signal(source)\n}\n\n/** \u8BBE\u7F6E\u6570\u636E\u51C0\u5316\uFF1A\u628A\u7EBF\u4E0A\u503C\u6536\u7A84\u4E3A\u5B89\u5168\u5F62\u72B6\uFF08\u9632\u810F\u6570\u636E\uFF09\u3002 */\nexport function sanitizeSettings(value: unknown): ComposerUxSettings {\n const source = (typeof value === 'object' && value !== null ? value : {}) as Record<string, unknown>\n const asString = (field: string): string => {\n const v = source[field]\n return typeof v === 'string' && v.length > 0 && v.length <= 64 ? v : ''\n }\n const asText = (field: string, max: number): string => {\n const v = source[field]\n return typeof v === 'string' && v.length <= max ? v : ''\n }\n /**\n * \u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u4E13\u7528\uFF1A**\u8D85\u4E0A\u9650\u5C31\u622A\u65AD**\uFF0C\u800C\u4E0D\u662F\u50CF `asText` \u90A3\u6837\u6574\u4EFD\u4E22\u6389\u3002\n *\n * \u4E3A\u4EC0\u4E48\u8FD9\u91CC\u4E0E headerName \u90A3\u6761\u76F8\u53CD\uFF1A\u5934\u540D\u975E\u6CD5\u662F\"\u5199\u8FDB\u53BB\u4F1A\u51FA\u7F51\u51FA\u9519\"\uFF0C\u4E22\u6389\u662F\u5BF9\u7684\uFF1B\n * \u800C\u63D0\u793A\u8BCD\u662F**\u7528\u6237\u81EA\u5DF1\u6572\u7684\u5185\u5BB9**\uFF0C\u9759\u9ED8\u4E22\u5F03\u7B49\u4E8E\u628A\u4ED6\u7684\u5DE5\u4F5C\u5F04\u6CA1\u4E86\u3002\u622A\u65AD\u81F3\u5C11\u7559\u5F97\u4E0B\u5927\u534A\uFF0C\n * \u4E14\u8BBE\u7F6E\u9875\u91CC\u5F53\u573A\u770B\u5F97\u89C1\u88AB\u622A\u65AD\u540E\u7684\u6837\u5B50\uFF08textarea \u6709 maxLength\uFF0C\u6B63\u5E38\u6839\u672C\u8D70\u4E0D\u5230\u8FD9\u91CC\uFF0C\n * \u53EA\u6709\u624B\u6539 settings.yaml \u624D\u4F1A\uFF09\u3002\n */\n const asPrompt = (field: string, max: number): string => {\n const v = source[field]\n return typeof v === 'string' ? v.slice(0, max) : ''\n }\n const asBool = (field: string): boolean => {\n const v = source[field]\n return typeof v === 'boolean' ? v : (DEFAULT_SETTINGS as unknown as Record<string, unknown>)[field] as boolean\n }\n const asSize = (field: string): number | undefined => {\n const v = source[field]\n return typeof v === 'number' && Number.isFinite(v) && v >= 320 && v <= 4000 ? Math.round(v) : undefined\n }\n /**\n * \u51C0\u5316\u5FEB\u6377\u6307\u4EE4\u5217\u8868\uFF1A\u9010\u6761\u6536\u7A84\u5F62\u72B6\uFF0C\u4E22\u6389\u6B8B\u7F3A\u9879\uFF0C\u5E76\u6309 id \u53BB\u91CD\u4FDD\u5E8F\u3002\n * \u5B57\u6BB5\u7F3A\u5931 / \u4E0D\u662F\u6570\u7EC4\uFF08\u9996\u6B21\u542F\u7528\uFF09\u2192 \u56DE\u843D\u5230\u5185\u7F6E 9 \u6761\uFF1B\u5B57\u6BB5\u662F\u6570\u7EC4\u5C31\u7167\u5B83\u6765\uFF0C\n * \u7A7A\u6570\u7EC4\u4E5F\u662F\u5408\u6CD5\u72B6\u6001\uFF08\u7528\u6237\u628A\u6761\u76EE\u5168\u5220\u5149\uFF0C\u5C31\u5E94\u5F53\u4FDD\u6301\u5168\u7A7A\uFF0C\u4E0D\u518D\u81EA\u52A8\u5192\u51FA\u6765\uFF09\u3002\n */\n const asQuickPrompts = (): readonly QuickPrompt[] => {\n const raw = source[QUICK_PROMPTS_FIELD]\n if (!Array.isArray(raw)) return DEFAULT_QUICK_PROMPTS\n const seen = new Set<string>()\n const out: QuickPrompt[] = []\n for (const item of raw) {\n if (out.length >= QUICK_PROMPT_MAX) break\n if (typeof item !== 'object' || item === null) continue\n const row = item as Record<string, unknown>\n const prompt = typeof row.prompt === 'string' ? row.prompt.slice(0, QUICK_TEXT_MAX).trim() : ''\n if (prompt === '') continue\n const label = typeof row.label === 'string' ? row.label.slice(0, QUICK_LABEL_MAX).trim() : ''\n const id = typeof row.id === 'string' && row.id !== '' ? row.id.slice(0, 64) : newQuickPromptId()\n if (seen.has(id)) continue\n seen.add(id)\n out.push({\n id,\n label: label === '' ? prompt.slice(0, 12) : label,\n prompt,\n always: row.always === true,\n firstOnly: row.firstOnly === true,\n })\n }\n return out\n }\n const asTier = (): OptimizerTier => {\n const v = source[OPTIMIZER_TIER_FIELD]\n return v === 'basic' || v === 'advanced' || v === 'extreme' ? v : DEFAULT_OPTIMIZER_TIER\n }\n return {\n enabled: asBool(ENABLED_FIELD),\n // \u4E94\u680F\u5F00\u5173\uFF1A\u663E\u5F0F\u5199\u8FC7\u542C\u5B83\u7684\uFF0C\u5426\u5219\u6309\"\u7528\u6237\u78B0\u8FC7\u6CA1\"\u8FC1\u79FB\uFF08\u89C1 sectionEnabledOf\uFF09\u3002\n keysEnabled: sectionEnabledOf(KEYS_ENABLED_FIELD, source),\n menuEnabled: sectionEnabledOf(MENU_ENABLED_FIELD, source),\n quickEnabled: sectionEnabledOf(QUICK_ENABLED_FIELD, source),\n panelEnabled: sectionEnabledOf(PANEL_ENABLED_FIELD, source),\n terminalEnabled: sectionEnabledOf(TERMINAL_ENABLED_FIELD, source),\n sendKey: asString(SEND_KEY_FIELD),\n newlineKey: asString(NEWLINE_KEY_FIELD),\n menuUndo: asBool('menuUndo'),\n menuRedo: asBool('menuRedo'),\n menuCut: asBool('menuCut'),\n menuCopy: asBool('menuCopy'),\n menuPaste: asBool('menuPaste'),\n menuDelete: asBool('menuDelete'),\n menuSelectAll: asBool('menuSelectAll'),\n menuMode: menuModeFrom(source[MENU_MODE_FIELD], source[MENU_NATIVE_FIELD]),\n panelResize: asBool(PANEL_RESIZE_FIELD),\n panelWidth: asSize(PANEL_WIDTH_FIELD),\n panelHeight: asSize(PANEL_HEIGHT_FIELD),\n headerEnabled: asBool(HEADER_ENABLED_FIELD),\n // \u5934\u540D\u7559\u7A7A\u662F\u4E0D\u5408\u6CD5\u72B6\u6001\uFF08\u5BBF\u4E3B\u534A\u4F1A\u62D2\u7EDD\u5199\u5165\u5E76\u628A\u539F\u56E0\u5199\u8FDB headerStatus\uFF09\uFF0C\n // \u6545\u51C0\u5316\u53EA\u505A\u957F\u5EA6\u6536\u7A84\u3001\u4FDD\u7559\u539F\u6837\uFF0C\u8BA9\u7528\u6237\u770B\u5F97\u89C1\u81EA\u5DF1\u8F93\u9519\u4E86\u4EC0\u4E48\u3002\n headerName: asText(HEADER_NAME_FIELD, HEADER_NAME_MAX),\n headerValue: asText(HEADER_VALUE_FIELD, HEADER_VALUE_MAX),\n headerRoutes: asText(HEADER_ROUTES_FIELD, HEADER_VALUE_MAX),\n headerAppliedName: asText(HEADER_APPLIED_NAME_FIELD, HEADER_NAME_MAX),\n headerAppliedValue: asText(HEADER_APPLIED_VALUE_FIELD, HEADER_VALUE_MAX),\n headerStatus: asText(HEADER_STATUS_FIELD, HEADER_VALUE_MAX),\n quickPrompts: asQuickPrompts(),\n optimizerTier: asTier(),\n optimizerPromptBasic: asPrompt(OPTIMIZER_PROMPT_FIELDS.basic, OPTIMIZER_PROMPT_MAX),\n optimizerPromptAdvanced: asPrompt(OPTIMIZER_PROMPT_FIELDS.advanced, OPTIMIZER_PROMPT_MAX),\n optimizerPromptExtreme: asPrompt(OPTIMIZER_PROMPT_FIELDS.extreme, OPTIMIZER_PROMPT_MAX),\n terminalMode: terminalModeFrom(source[TERMINAL_MODE_FIELD]),\n // \u8DEF\u5F84\u53EA\u505A\u957F\u5EA6\u4E0E\u5F52\u4E00\u5316\u6536\u7A84\uFF0C\u4E0D\u5728\u8FD9\u91CC\u5224\"\u5B58\u4E0D\u5B58\u5728\"\u2014\u2014\u90A3\u662F\u5BBF\u4E3B\u534A\u7684\u63A2\u6D4B\u7ED3\u8BBA\uFF0C\n // \u7531\u72B6\u6001\u884C\u544A\u8BC9\u7528\u6237\uFF08\u7528\u6237\u770B\u5F97\u89C1\u81EA\u5DF1\u586B\u4E86\u4EC0\u4E48\uFF0C\u6BD4\u6084\u6084\u6E05\u7A7A\u597D\uFF09\u3002\n terminalBashPath: asText(TERMINAL_BASH_PATH_FIELD, 400),\n terminalCandidates: sanitizeTerminalCandidates(source[TERMINAL_CANDIDATES_FIELD]),\n terminalStatus: asText(TERMINAL_STATUS_FIELD, 400),\n terminalEffective: asText(TERMINAL_EFFECTIVE_FIELD, 16),\n }\n}\n", "/**\n * \u5FEB\u6377\u6307\u4EE4\u7684**\u5BA2\u6237\u7AEF**\u8BFB\u5199\u5C42\u3002\n *\n * \u4E24\u4EF6\u4E8B\uFF1A\n * 1. \u7ECF\u5BBF\u4E3B\u8DEF\u7531 `/composer-ux/prompts` \u8BFB\u3001\u5199\u6574\u672C\uFF08\u6D4F\u89C8\u5668\u6CA1\u6709\u6587\u4EF6\u7CFB\u7EDF\uFF0C\u53EA\u80FD\u8D70 HTTP\uFF09\uFF1B\n * 2. \u4E00\u7EC4**\u7EAF**\u7F16\u8F91\u51FD\u6570\uFF08\u589E\u5220\u6539\u79FB\uFF09\uFF0C\u5168\u90E8\u4E0D\u53EF\u53D8\u2014\u2014\u5217\u8868\u64CD\u4F5C\u6700\u5BB9\u6613\u51FA\u300C\u539F\u5730\u6539\u574F\u300D\u7684\n * bug\uFF0C\u7EAF\u51FD\u6570\u8BA9\u5B83\u80FD\u5728 node \u91CC\u76F4\u63A5\u6D4B\uFF08\u89C1 test/quick-store.mjs \u7B2C 10 \u8282\uFF09\u3002\n *\n * \u4FDD\u5B58\u7B56\u7565\uFF1A\u5148\u4E50\u89C2\u66F4\u65B0\u672C\u5730\u5FEB\u7167\u8BA9 UI \u7ACB\u523B\u54CD\u5E94\uFF0C\u518D\u628A\u6574\u672C POST \u4E0A\u53BB\uFF1B**\u5931\u8D25\u5C31\u4EE5\u78C1\u76D8\n * \u4E3A\u51C6\u56DE\u6EDA**\u2014\u2014\u7EDD\u4E0D\u8BA9\u300C\u754C\u9762\u663E\u793A\u7684\u300D\u548C\u300C\u6587\u4EF6\u91CC\u7684\u300D\u957F\u671F\u4E0D\u4E00\u81F4\u3002\n */\nimport {\n DEFAULT_CATEGORY_NAME, QUICK_CATEGORY_MAX, QUICK_CATEGORY_NAME_MAX, QUICK_LABEL_MAX,\n QUICK_PROMPTS_API_PATH, QUICK_PROMPT_MAX, QUICK_TEXT_MAX,\n insertModeOf, newQuickCategoryId, newQuickPromptId, sanitizeBook,\n type InsertMode, type QuickPrompt, type QuickPromptBook, type QuickPromptCategory,\n} from '../settings-contract.ts'\n\n/** \u8DEF\u7531\u5E94\u7B54\uFF08\u6210\u529F\u4E0E\u5931\u8D25\u90FD\u8D70\u540C\u4E00\u5F62\u72B6\uFF0C\u4FBF\u4E8E\u7EDF\u4E00\u5904\u7406\uFF09\u3002 */\nexport interface PromptBookReply {\n readonly ok: boolean\n readonly book?: QuickPromptBook\n readonly error?: string\n /** \u78C1\u76D8\u4E0A\u7684\u771F\u5B9E\u8DEF\u5F84\uFF08\u5C55\u793A\u7ED9\u7528\u6237\uFF0C\u4FBF\u4E8E\u624B\u5DE5\u7F16\u8F91/\u5907\u4EFD\uFF09\u3002 */\n readonly file?: string\n /** \u574F\u6587\u4EF6\u88AB\u9694\u79BB\u540E\u7684\u8DEF\u5F84\uFF08\u975E\u7A7A\u8BF4\u660E\u51FA\u4E86\u95EE\u9898\u3001\u4E14\u539F\u6587\u4EF6\u5DF2\u4FDD\u4F4F\uFF09\u3002 */\n readonly quarantined?: string\n}\n\nasync function requestBook(method: 'GET' | 'POST', body?: unknown): Promise<PromptBookReply> {\n try {\n const response = await fetch(QUICK_PROMPTS_API_PATH, {\n method,\n headers: body === undefined ? undefined : { 'content-type': 'application/json' },\n body: body === undefined ? undefined : JSON.stringify(body),\n })\n const text = await response.text()\n let parsed: unknown\n try {\n parsed = JSON.parse(text)\n } catch {\n return { ok: false, error: `\u670D\u52A1\u7AEF\u8FD4\u56DE\u7684\u4E0D\u662F JSON\uFF08HTTP ${String(response.status)}\uFF09` }\n }\n const row = (typeof parsed === 'object' && parsed !== null ? parsed : {}) as Record<string, unknown>\n const book = sanitizeBook(row.book)\n const textOf = (value: unknown): string | undefined => (typeof value === 'string' && value !== '' ? value : undefined)\n return {\n ok: row.ok === true,\n ...(book === undefined ? {} : { book }),\n ...(textOf(row.error) === undefined ? {} : { error: textOf(row.error) }),\n ...(textOf(row.file) === undefined ? {} : { file: textOf(row.file) }),\n ...(textOf(row.quarantined) === undefined ? {} : { quarantined: textOf(row.quarantined) }),\n }\n } catch (error: unknown) {\n return { ok: false, error: error instanceof Error ? error.message : String(error) }\n }\n}\n\n/** \u8BFB\u6574\u672C\uFF08\u9996\u6B21\u8BFB\u53D6\u4F1A\u89E6\u53D1\u5BBF\u4E3B\u534A\u7684\u4E00\u6B21\u6027\u8FC1\u79FB\uFF09\u3002 */\nexport function loadPromptBook(): Promise<PromptBookReply> {\n return requestBook('GET')\n}\n\n/** \u5199\u6574\u672C\uFF08\u5BBF\u4E3B\u534A\u4F1A\u505A\u539F\u5B50\u5199\uFF1B\u574F\u6587\u4EF6\u65F6\u5B83\u4F1A\u62D2\u7EDD\u5199\u5165\u5E76\u62A5\u9519\uFF09\u3002 */\nexport function savePromptBook(book: QuickPromptBook): Promise<PromptBookReply> {\n return requestBook('POST', { book })\n}\n\n// \u2500\u2500 \u7EAF\u7F16\u8F91\u51FD\u6570\uFF08\u5168\u90E8\u4E0D\u53EF\u53D8\uFF0C\u8FD4\u56DE\u65B0\u672C\uFF09 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** \u6309 id \u627E\u5206\u7C7B\u3002 */\nexport function categoryOf(book: QuickPromptBook, categoryId: string): QuickPromptCategory | undefined {\n return book.categories.find(category => category.id === categoryId)\n}\n\n/** \u6309 id \u627E\u6761\u76EE\uFF08\u8DE8\u5206\u7C7B\uFF1A\u9762\u677F\u91CC\u7684\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u52FE\u9009\u4E0D\u5E26\u5206\u7C7B\u4E0A\u4E0B\u6587\uFF09\u3002 */\nexport function findPrompt(\n book: QuickPromptBook,\n promptId: string,\n): { readonly category: QuickPromptCategory; readonly prompt: QuickPrompt } | undefined {\n for (const category of book.categories) {\n const prompt = category.prompts.find(item => item.id === promptId)\n if (prompt !== undefined) return { category, prompt }\n }\n return undefined\n}\n\n/** \u7EDF\u8BA1\uFF08\u9762\u677F\u5934\u90E8\u4E0E\u8BBE\u7F6E\u9875\u7528\uFF09\u3002`always` = \u6BCF\u6B21\uFF0C`first` = \u4EC5\u9996\u6B21\u3002 */\nexport function bookCounts(book: QuickPromptBook): {\n readonly categories: number\n readonly prompts: number\n readonly always: number\n readonly first: number\n} {\n const prompts = book.categories.flatMap(category => category.prompts)\n return {\n categories: book.categories.length,\n prompts: prompts.length,\n always: prompts.filter(prompt => insertModeOf(prompt) === 'always').length,\n first: prompts.filter(prompt => insertModeOf(prompt) === 'first').length,\n }\n}\n\nfunction mapCategory(\n book: QuickPromptBook,\n categoryId: string,\n edit: (category: QuickPromptCategory) => QuickPromptCategory,\n): QuickPromptBook {\n return {\n version: book.version,\n categories: book.categories.map(category => (category.id === categoryId ? edit(category) : category)),\n }\n}\n\n/** \u65B0\u589E\u5206\u7C7B\uFF08\u540D\u5B57\u53BB\u7A7A\u767D\uFF1B\u8D85\u8FC7\u4E0A\u9650\u5219\u4E0D\u52A8\u4F5C\u5E76\u8FD4\u56DE\u539F\u672C\uFF09\u3002 */\nexport function withCategoryAdded(book: QuickPromptBook, name: string): QuickPromptBook {\n if (book.categories.length >= QUICK_CATEGORY_MAX) return book\n const clean = name.trim().slice(0, QUICK_CATEGORY_NAME_MAX)\n return {\n version: book.version,\n categories: [...book.categories, { id: newQuickCategoryId(), name: clean === '' ? DEFAULT_CATEGORY_NAME : clean, prompts: [] }],\n }\n}\n\n/** \u6539\u5206\u7C7B\u540D\uFF08\u7A7A\u540D\u56DE\u843D\u5230\u9ED8\u8BA4\u540D\uFF0C\u907F\u514D\u51FA\u73B0\u70B9\u4E0D\u4E2D\u7684\u7A7A\u6807\u7B7E\uFF09\u3002 */\nexport function withCategoryRenamed(book: QuickPromptBook, categoryId: string, name: string): QuickPromptBook {\n const clean = name.trim().slice(0, QUICK_CATEGORY_NAME_MAX)\n return mapCategory(book, categoryId, category => ({ ...category, name: clean === '' ? DEFAULT_CATEGORY_NAME : clean }))\n}\n\n/** \u5220\u5206\u7C7B\uFF08\u8FDE\u5E26\u5B83\u91CC\u9762\u7684\u6761\u76EE\u4E00\u8D77\u5220\uFF09\u3002 */\nexport function withCategoryRemoved(book: QuickPromptBook, categoryId: string): QuickPromptBook {\n return { version: book.version, categories: book.categories.filter(category => category.id !== categoryId) }\n}\n\n/** \u5206\u7C7B\u6362\u4F4D\uFF08delta = -1 \u4E0A\u79FB / +1 \u4E0B\u79FB\uFF09\uFF1B\u8D8A\u754C\u65F6\u539F\u6837\u8FD4\u56DE\u3002 */\nexport function withCategoryMoved(book: QuickPromptBook, categoryId: string, delta: number): QuickPromptBook {\n const index = book.categories.findIndex(category => category.id === categoryId)\n const next = index + delta\n if (index < 0 || next < 0 || next >= book.categories.length) return book\n const categories = [...book.categories]\n const [moved] = categories.splice(index, 1)\n categories.splice(next, 0, moved)\n return { version: book.version, categories }\n}\n\n/**\n * \u5728\u6307\u5B9A\u5206\u7C7B\u91CC\u52A0\u4E00\u6761\u65B0\u6761\u76EE\u3002\n *\n * \u6B63\u6587\u7ED9\u7684\u662F**\u5360\u4F4D\u6587\u6848**\u800C\u4E0D\u662F\u7A7A\u4E32\uFF1A\u7A7A\u6B63\u6587\u7684\u6761\u76EE\u4F1A\u88AB\u51C0\u5316\u4E22\u6389\uFF08`asPromptRow` \u8981\u6C42\u6B63\u6587\n * \u975E\u7A7A\uFF09\uFF0C\u800C\u9762\u677F\u91CC\u7684\u300C\u65B0\u5EFA\u300D\u662F**\u7ACB\u5373\u5199\u76D8**\u7684\u2014\u2014\u7ED9\u7A7A\u6B63\u6587\u7684\u8BDD\u5B83\u4F1A\u5F53\u573A\u6D88\u5931\u3001\u770B\u8D77\u6765\u50CF\u574F\u6389\u4E86\u3002\n * \u8BBE\u7F6E\u9875\u540C\u6837\u7528\u5B83\uFF0C\u4E8E\u662F\u4E24\u8FB9\u884C\u4E3A\u4E00\u81F4\uFF1A\u65B0\u5EFA\u51FA\u6765\u7684\u662F\u4E00\u6761\u300C\u65B0\u6307\u4EE4 /\uFF08\u5F85\u586B\u5199\uFF09\u300D\uFF0C\u628A\u6B63\u6587\n * \u66FF\u6362\u6389\u5373\u53EF\u3002\n */\nexport function withPromptAdded(book: QuickPromptBook, categoryId: string): QuickPromptBook {\n return mapCategory(book, categoryId, (category) => {\n if (category.prompts.length >= QUICK_PROMPT_MAX) return category\n return {\n ...category,\n prompts: [...category.prompts, {\n id: newQuickPromptId(), label: '\u65B0\u6307\u4EE4', prompt: '\uFF08\u5F85\u586B\u5199\uFF09', always: false, firstOnly: false,\n }],\n }\n })\n}\n\n/**\n * \u6539\u6761\u76EE\u5B57\u6BB5\u3002\n *\n * `prompt` \u7A7A\u4E32\u662F**\u5408\u6CD5\u4E2D\u95F4\u6001**\uFF08\u7528\u6237\u6B63\u5728\u7F16\u8F91\uFF09\uFF0C\u6545\u8FD9\u91CC\u4E0D\u505A\u300C\u7A7A\u5C31\u4E22\u6389\u300D\u7684\u6536\u7A84\u2014\u2014\n * \u6536\u7A84\u53D1\u751F\u5728\u5199\u76D8\u4E0E\u51C0\u5316\u65F6\uFF08`sanitizeBook` \u4F1A\u4E22\u6389\u7A7A\u6B63\u6587\u7684\u6761\u76EE\uFF09\uFF0C\u754C\u9762\u4E0A\u4F1A\u8868\u73B0\u4E3A\n * \u300C\u4FDD\u5B58\u540E\u7A7A\u6761\u76EE\u6D88\u5931\u300D\uFF0C\u8FD9\u662F\u671F\u671B\u884C\u4E3A\u3002\n */\nexport function withPromptPatched(\n book: QuickPromptBook,\n categoryId: string,\n promptId: string,\n patch: Partial<Pick<QuickPrompt, 'label' | 'prompt' | 'always' | 'firstOnly'>>,\n): QuickPromptBook {\n return mapCategory(book, categoryId, (category) => ({\n ...category,\n prompts: category.prompts.map((prompt) => {\n if (prompt.id !== promptId) return prompt\n const label = patch.label === undefined ? prompt.label : patch.label.slice(0, QUICK_LABEL_MAX)\n const text = patch.prompt === undefined ? prompt.prompt : patch.prompt.slice(0, QUICK_TEXT_MAX)\n const always = patch.always === undefined ? prompt.always : patch.always\n const firstOnly = patch.firstOnly === undefined ? prompt.firstOnly : patch.firstOnly\n return { id: prompt.id, label, prompt: text, always, firstOnly }\n }),\n }))\n}\n\n/**\n * \u8BBE\u7F6E\u4E00\u6761\u7684\u63D2\u5165\u6A21\u5F0F\uFF08\u754C\u9762\u4E0A\u7684\u4E09\u9009\u4E00\uFF09\u3002\n *\n * **\u4E24\u4E2A\u4E92\u65A5\u6807\u5FD7\u5FC5\u987B\u4E00\u6B21\u5199\u5BF9**\u2014\u2014\u5206\u522B\u5199\u5C31\u53EF\u80FD\u7559\u4E0B\u300C\u53C8\u6BCF\u6B21\u53C8\u4EC5\u9996\u6B21\u300D\u7684\u77DB\u76FE\u72B6\u6001\uFF0C\n * \u6240\u4EE5\u754C\u9762\u53EA\u5141\u8BB8\u901A\u8FC7\u8FD9\u91CC\u6539\u6A21\u5F0F\uFF0C\u4E0D\u76F4\u63A5\u6539\u90A3\u4E24\u4E2A\u5E03\u5C14\u3002\n *\n * @returns \u65B0\u672C\uFF1B\u6761\u76EE\u4E0D\u5B58\u5728\u3001\u6216\u6A21\u5F0F\u6CA1\u53D8\u5316\u65F6**\u539F\u6837\u8FD4\u56DE\u4F20\u5165\u5BF9\u8C61**\uFF08\u907F\u514D\u65E0\u610F\u4E49\u5199\u76D8\uFF09\u3002\n */\nexport function withInsertMode(book: QuickPromptBook, promptId: string, mode: InsertMode): QuickPromptBook {\n const hit = findPrompt(book, promptId)\n if (hit === undefined) return book\n if (insertModeOf(hit.prompt) === mode) return book\n return withPromptPatched(book, hit.category.id, promptId, {\n always: mode === 'always',\n firstOnly: mode === 'first',\n })\n}\n\n/** \u5220\u6761\u76EE\u3002 */\nexport function withPromptRemoved(book: QuickPromptBook, categoryId: string, promptId: string): QuickPromptBook {\n return mapCategory(book, categoryId, category => ({\n ...category,\n prompts: category.prompts.filter(prompt => prompt.id !== promptId),\n }))\n}\n\n/** \u6761\u76EE\u6362\u4F4D\uFF1B\u8D8A\u754C\u65F6**\u8FD4\u56DE\u4F20\u5165\u7684\u90A3\u4E2A\u5BF9\u8C61**\uFF08\u8C03\u7528\u65B9\u636E\u6B64\u907F\u514D\u65E0\u610F\u4E49\u7684\u5199\u76D8\uFF09\u3002 */\nexport function withPromptMoved(book: QuickPromptBook, categoryId: string, promptId: string, delta: number): QuickPromptBook {\n const category = categoryOf(book, categoryId)\n if (category === undefined) return book\n const index = category.prompts.findIndex(prompt => prompt.id === promptId)\n const next = index + delta\n if (index < 0 || next < 0 || next >= category.prompts.length) return book\n const prompts = [...category.prompts]\n const [moved] = prompts.splice(index, 1)\n prompts.splice(next, 0, moved)\n return mapCategory(book, categoryId, target => ({ ...target, prompts }))\n}\n\n/** \u52FE\u9009/\u53D6\u6D88\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\uFF08\u6309 id \u8DE8\u5206\u7C7B\u627E\uFF09\u3002 */\nexport function withAlwaysToggled(book: QuickPromptBook, promptId: string, value: boolean): QuickPromptBook {\n const hit = findPrompt(book, promptId)\n if (hit === undefined) return book\n return withPromptPatched(book, hit.category.id, promptId, { always: value })\n}\n\n/** \u300C\u79FB\u52A8\u5230\u8FD9\u91CC\u300D\u83DC\u5355\u7684\u6570\u636E\u6E90\uFF1A\u5176\u5B83\u5206\u7C7B\u91CC\u7684\u5168\u90E8\u6761\u76EE\uFF08\u5E26\u6765\u6E90\u5206\u7C7B\u540D\uFF09\u3002 */\nexport function promptsElsewhere(\n book: QuickPromptBook,\n categoryId: string,\n): readonly { readonly categoryId: string; readonly categoryName: string; readonly prompt: QuickPrompt }[] {\n return book.categories\n .filter(category => category.id !== categoryId)\n .flatMap(category => category.prompts.map(prompt => ({\n categoryId: category.id,\n categoryName: category.name,\n prompt,\n })))\n}\n\n/**\n * \u628A\u4E00\u4E2A\u6761\u76EE\u4ECE**\u5B83\u5F53\u524D\u6240\u5728\u7684\u5206\u7C7B**\u79FB\u5230\u76EE\u6807\u5206\u7C7B\uFF0C\u8FFD\u52A0\u5230\u76EE\u6807\u672B\u5C3E\u3002\n *\n * \u53EA\u6309 id \u627E\u6761\u76EE\uFF08\u8C03\u7528\u65B9\u4E0D\u5FC5\u77E5\u9053\u5B83\u5728\u54EA\u4E2A\u5206\u7C7B\uFF09\uFF1A\u9762\u677F\u91CC\u300C\u5F53\u524D\u5206\u7C7B\u300D\u662F\u6807\u7B7E\u51B3\u5B9A\u7684\uFF0C\n * \u8BBE\u7F6E\u9875\u6BCF\u4E2A\u5206\u7C7B\u5404\u6709\u4E00\u4EFD\u5217\u8868\u2014\u2014\u6309 id \u627E\u80FD\u5C11\u4E00\u4E2A\u53C2\u6570\uFF0C\u4E5F\u5C11\u4E00\u7C7B\u300C\u4F20\u9519\u6765\u6E90\u300D\u7684 bug\u3002\n *\n * @returns \u65B0\u672C\uFF1B\u4E0B\u5217\u60C5\u51B5**\u539F\u6837\u8FD4\u56DE\u4F20\u5165\u5BF9\u8C61**\uFF08\u8C03\u7528\u65B9\u636E\u6B64\u907F\u514D\u65E0\u610F\u4E49\u7684\u5199\u76D8\uFF09\uFF1A\n * \u6761\u76EE\u4E0D\u5B58\u5728\u3001\u76EE\u6807\u5206\u7C7B\u4E0D\u5B58\u5728\u3001\u76EE\u6807\u5C31\u662F\u5B83\u73B0\u5728\u6240\u5728\u7684\u5206\u7C7B\u3001\u76EE\u6807\u5206\u7C7B\u5DF2\u6EE1\u3002\n */\nexport function withPromptMovedToCategory(\n book: QuickPromptBook,\n promptId: string,\n toCategoryId: string,\n): QuickPromptBook {\n const hit = findPrompt(book, promptId)\n if (hit === undefined || hit.category.id === toCategoryId) return book\n const target = categoryOf(book, toCategoryId)\n if (target === undefined || target.prompts.length >= QUICK_PROMPT_MAX) return book\n return {\n version: book.version,\n categories: book.categories.map((category) => {\n if (category.id === hit.category.id) {\n return { ...category, prompts: category.prompts.filter(prompt => prompt.id !== promptId) }\n }\n if (category.id === toCategoryId) {\n // \u539F\u6837\u642C\u540C\u4E00\u4E2A\u5BF9\u8C61\uFF1Aid / \u540D\u79F0 / \u6B63\u6587 / \u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u6807\u8BB0\u90FD\u8DDF\u7740\u8D70\u3002\n return { ...category, prompts: [...category.prompts, hit.prompt] }\n }\n return category\n }),\n }\n}\n", "/**\n * \u952E\u4F4D\u89C4\u8303\u4E32\uFF1A\u4FEE\u9970\u952E\u6309 Ctrl+Alt+Shift+Meta \u987A\u5E8F + \u4E3B\u952E\uFF0C\u7528 '+' \u8FDE\u63A5\u3002\n * \u4E3B\u952E\u53D6\u503C\u4F18\u5148\u7269\u7406\u7801\uFF08KeyJ\u2192J\u3001Digit3\u21923\uFF09\uFF0C\u5176\u4F59\u7528\u6807\u51C6\u6309\u952E\u540D\uFF08Enter\u3001Space\u3001F2...\uFF09\u3002\n */\n\n/** \u4E00\u6B21\u6309\u952E\u4E8B\u4EF6\u7684\u53EA\u8BFB\u6295\u5F71\uFF08KeyboardEvent \u7684\u6700\u5C0F\u5F62\u72B6\uFF09\u3002 */\nexport interface ChordEvent {\n readonly ctrlKey: boolean\n readonly altKey: boolean\n readonly shiftKey: boolean\n readonly metaKey: boolean\n readonly code: string\n readonly key: string\n}\n\n/** \u4FEE\u9970\u952E\u672C\u8EAB\uFF08\u4E0D\u5E94\u4F5C\u4E3A\u4E3B\u952E\u53C2\u4E0E\u7ED1\u5B9A\uFF09\u3002 */\nconst MODIFIER_KEYS = new Set(['Control', 'Alt', 'Shift', 'Meta', 'AltGraph'])\n\n/** \u5E38\u89C1\u6807\u70B9\u4E3B\u952E\u7684\u53CB\u597D\u540D\u3002 */\nconst CODE_LABELS: Readonly<Record<string, string>> = {\n Slash: '/',\n Backslash: '\\\\',\n BracketLeft: '[',\n BracketRight: ']',\n Semicolon: ';',\n Quote: \"'\",\n Comma: ',',\n Period: '.',\n Backquote: '`',\n Minus: '-',\n Equal: '=',\n Space: 'Space',\n}\n\n/** \u628A\u4E00\u6B21\u6309\u952E\u4E8B\u4EF6\u7F16\u7801\u4E3A\u89C4\u8303\u4E32\uFF1B\u7EAF\u4FEE\u9970\u952E\u8FD4\u56DE ''\u3002 */\nexport function encodeChord(event: ChordEvent): string {\n const parts: string[] = []\n if (event.ctrlKey) parts.push('Ctrl')\n if (event.altKey) parts.push('Alt')\n if (event.shiftKey) parts.push('Shift')\n if (event.metaKey) parts.push('Meta')\n const mainKey = normalizeMainKey(event)\n if (mainKey === '') return ''\n parts.push(mainKey)\n return parts.join('+')\n}\n\n/** \u4E3B\u952E\u540D\uFF1A\u5B57\u6BCD/\u6570\u5B57\u7528\u7269\u7406\u7801\u5F52\u4E00\uFF0C\u5176\u4F59\u7528\u6807\u51C6\u540D\u3002 */\nfunction normalizeMainKey(event: ChordEvent): string {\n const code = event.code\n if (code.startsWith('Key')) return code.slice(3)\n if (code.startsWith('Digit')) return code.slice(5)\n if (CODE_LABELS[code] !== undefined) return CODE_LABELS[code] as string\n // F1..F24 \u53CA Enter/Tab/Arrow* /Backspace/Delete \u7B49 code \u672C\u8EAB\u5373\u6807\u51C6\u540D\u3002\n return code !== '' ? code : event.key\n}\n\n/** \u662F\u5426\u7EAF\u4FEE\u9970\u952E\u6309\u4E0B\uFF08\u7528\u4E8E\u5FFD\u7565 Ctrl/Alt/Shift \u5355\u72EC\u6309\u4E0B\uFF09\u3002 */\nexport function isModifierOnly(event: ChordEvent): boolean {\n return MODIFIER_KEYS.has(event.key)\n}\n\n/** \u4E3B\u952E\u662F\u5426\u5C5E\u4E8E\u300C\u6253\u5B57\u7C7B\u300D\u6309\u952E\uFF08\u672A\u88AB\u8BB0\u5F55\u89C4\u5219\u5141\u8BB8\u7684\u88F8\u952E\uFF09\u3002 */\nconst BARE_ALLOWED = new Set([\n 'Enter', 'Space', 'Tab', 'Backspace', 'Delete', 'Insert', 'Home', 'End',\n 'PageUp', 'PageDown', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight',\n])\n\n/** \u88F8\u952E\uFF08\u65E0\u4EFB\u4F55\u4FEE\u9970\u952E\uFF09\u662F\u5426\u5141\u8BB8\u7ED1\u5B9A\u3002 */\nexport function isBareKeyAllowed(chord: string): boolean {\n if (chord.includes('+')) return true\n if (BARE_ALLOWED.has(chord)) return true\n return /^F\\d{1,2}$/.test(chord)\n}\n\n/** \u89E3\u6790\u89C4\u8303\u4E32 \u2192 \u53CD\u5411\u4E8B\u4EF6\u521D\u59CB\u5316\u53C2\u6570\uFF08\u7528\u4E8E\u5408\u6210\u56DE\u653E\uFF09\u3002 */\nexport function chordToInit(chord: string): KeyboardEventInit {\n const parts = chord.split('+').filter(Boolean)\n const init: KeyboardEventInit = {\n ctrlKey: false,\n altKey: false,\n shiftKey: false,\n metaKey: false,\n bubbles: true,\n cancelable: true,\n }\n const key = parts.pop() ?? ''\n init.key = key\n // \u4E3B\u952E\u7684 code \u53CD\u63A8\uFF08\u5C3D\u529B\u8FD8\u539F\uFF1B\u4EC5\u5F71\u54CD IME/\u7269\u7406\u7801\u8BFB\u53D6\uFF0C\u4E0D\u5C5E\u5173\u952E\u8DEF\u5F84\uFF09\u3002\n init.code = key.length === 1 ? (/^[A-Z]$/.test(key) ? `Key${key}` : key) : key\n for (const part of parts) {\n if (part === 'Ctrl') init.ctrlKey = true\n else if (part === 'Alt') init.altKey = true\n else if (part === 'Shift') init.shiftKey = true\n else if (part === 'Meta') init.metaKey = true\n }\n return init\n}\n\n/** \u952E\u4F4D\u662F\u5426\u5C5E\u4E8E Enter \u5BB6\u65CF\uFF08\u62E6\u622A\u5668\u53EA\u63A5\u7BA1\u8FD9\u4E9B\u7EC4\u5408\uFF09\u3002 */\nexport function isEnterFamily(chord: string): boolean {\n return chord === 'Enter' || chord.endsWith('+Enter')\n}\n\n/** \u8BB0\u5F55\u65F6\u5408\u6CD5\u6027\u68C0\u67E5\u7ED3\u679C\u3002 */\nexport type RecordResult =\n | { kind: 'ok'; chord: string }\n | { kind: 'cancel' }\n | { kind: 'clear' }\n | { kind: 'ignore' }\n | { kind: 'reject'; message: string }\n\n/** \u68C0\u67E5\u5F55\u5236\u6309\u952E\uFF1A\u7ED3\u679C\u4E3A ok \u65F6\u8FD4\u56DE\u53EF\u5199\u5165\u7684\u89C4\u8303\u4E32\u3002 */\nexport function evaluateRecordedKey(event: ChordEvent): RecordResult {\n if (isModifierOnly(event)) return { kind: 'ignore' }\n if (event.code === 'Escape' || event.key === 'Escape') return { kind: 'cancel' }\n // Backspace/Delete = \u6E05\u9664\u7ED1\u5B9A\uFF08\u4E0E\u300C\u65E0\u300D\u7B49\u4EF7\uFF0C\u4F46\u8BED\u4E49\u66F4\u660E\u663E\uFF09\u3002\n if (event.code === 'Backspace' || event.code === 'Delete') return { kind: 'clear' }\n const chord = encodeChord(event)\n if (chord === '') return { kind: 'ignore' }\n if (!isBareKeyAllowed(chord)) {\n return {\n kind: 'reject',\n message: '\u5355\u4E2A\u5B57\u6BCD/\u6570\u5B57\u952E\u4F1A\u4E0E\u6253\u5B57\u51B2\u7A81\uFF0C\u8BF7\u914D\u5408 Ctrl / Alt / Shift \u4F7F\u7528\uFF0C\u6216\u9009\u62E9 Enter\u3002',\n }\n }\n return { kind: 'ok', chord }\n}\n\n/** \u952E\u4F4D\u663E\u793A\u6587\u672C\uFF1A'' \u2192 \u65E0\u3002 */\nexport function displayChord(chord: string): string {\n return chord === '' ? '\u65E0' : chord\n}\n", "/**\n * \u5FEB\u6377\u6307\u4EE4\u4E0E\u300C\u53D1\u9001\u65F6\u9644\u52A0\u6761\u76EE\u300D\u7684\u8FD0\u884C\u65F6\u6865\u63A5\u3002\n *\n * \u4E3A\u4EC0\u4E48\u9700\u8981\u8FD9\u4E2A\u6A21\u5757\uFF1A\u8F93\u5165\u6846\u62E6\u622A\u5668\uFF08interceptors.ts\uFF09\u6D3B\u5728\u7EAF DOM / \u6355\u83B7\u9636\u6BB5\u91CC\uFF0C\n * \u62FF\u4E0D\u5230 React \u69FD\u4F4D\u624D\u6709\u7684 `inputActions` \u4E0E InputState \u8349\u7A3F\uFF1B\u800C\u300C\u70B9\u53D1\u9001\u65F6\u81EA\u52A8\u628A\n * \u63D0\u793A\u8BCD\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E\u300D\u4E24\u6837\u90FD\u8981\u7528 \u2014\u2014 \u5F97\u77E5\u9053\u5F53\u524D\u8349\u7A3F\u662F\u4EC0\u4E48\uFF0C\u518D\u628A\u9644\u52A0\u540E\u7684\u6574\u6BB5\u5199\n * \u56DE\u7F16\u8F91\u5668\u3002\u4E8E\u662F\u7531 `conversation.input.right` \u7684\u6309\u94AE\u7EC4\u4EF6\u5728\u6BCF\u6B21\u6E32\u67D3\u65F6\u628A\u8FD9\u4E24\u6837\u4E1C\u897F\n * \u6295\u9012\u5230\u8FD9\u91CC\uFF0C\u62E6\u622A\u5668\u540C\u6B65\u8BFB\u53D6\u3002\n *\n * \u6CE8\u610F\u5206\u5DE5\uFF1A**\u300C\u54EA\u4E9B\u6761\u76EE\u8BE5\u9644\u52A0\u300D\u4E0D\u5728\u8FD9\u91CC\u5224\u65AD**\uFF0C\u7531\u8C03\u7528\u65B9\n * `appendBatchForSend(book, currentBlankSession())` \u51B3\u5B9A\uFF08\u300C\u6BCF\u6B21\u300D\u5168\u5E26\u4E0A\uFF0C\n * \u300C\u4EC5\u9996\u6B21\u300D\u53EA\u5728\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u6D88\u606F\u65F6\u5E26\u4E0A\uFF09\uFF1B\u672C\u6A21\u5757\u53EA\u8D1F\u8D23\u628A\u90A3\u4E00\u6279\u62FC\u4E0A\u53BB\u3001\u5199\u56DE\u53BB\u3002\n * 0.4.0 \u66FE\u5728\u4E00\u4E2A\u51FD\u6570\u91CC\u5224\u65AD\u4E86\u4E24\u6B21\uFF0C\u89C1 `withPromptsAppended` \u7684\u8BF4\u660E\u3002\n *\n * \u672C\u6A21\u5757\u96F6 React \u4F9D\u8D56\uFF0C\u53EF\u88AB\u62E6\u622A\u5668\u4E0E\u7EC4\u4EF6\u5171\u7528\u3002\n */\nimport type { QuickPrompt } from '../settings-contract.ts'\nimport { OPTIMIZER_API_PATH } from '../settings-contract.ts'\n\n/** \u5B98\u65B9\u516C\u5F00\u8F93\u5165\u52A8\u4F5C\u91CC\u672C\u6A21\u5757\u7528\u5230\u7684\u4E24\u4E2A\uFF08\u89C1 DSH \u7684 InputActions \u5951\u7EA6\uFF09\u3002 */\nexport interface InputActionsLike {\n /** \u6574\u4F53\u66FF\u6362\u8349\u7A3F\uFF08\u5B98\u65B9\u652F\u6301\u7684\u7A0B\u5E8F\u5316\u5199\u5165\u8DEF\u5F84\uFF09\u3002 */\n setDraft: (text: string) => void\n}\n\n/** \u8349\u7A3F\u6765\u6E90\uFF1A\u69FD\u4F4D\u5FEB\u7167\uFF08\u6743\u5A01\uFF09> DOM \u515C\u5E95\u3002 */\ninterface BridgeState {\n actions: InputActionsLike | null\n draft: string\n sessionId: string\n /**\n * \u4F1A\u8BDD\u662F\u5426\u8FD8**\u6CA1\u6709\u4EFB\u4F55\u6D88\u606F**\uFF08\u69FD\u4F4D\u7ED9\u7684 `SessionSnapshot.blank`\uFF09\u3002\n *\n * \u300C\u4EC5\u9996\u6B21\u63D2\u5165\u300D\u5C31\u9760\u5B83\uFF1A\u53D1\u5B8C\u7B2C\u4E00\u6761\u5B83\u81EA\u5DF1\u4F1A\u53D8\u6210 false\uFF0C\u6240\u4EE5\u4E0D\u5FC5\u81EA\u5DF1\u8BB0\u300C\u672C\u4F1A\u8BDD\u9644\u52A0\u8FC7\n * \u6CA1\u6709\u300D\uFF0C\u5237\u65B0\u9875\u9762\u4E5F\u4E0D\u4F1A\u91CD\u590D\u9644\u52A0\u3002\u53D6\u4E0D\u5230\u4F1A\u8BDD\u65F6\u6309 false \u5904\u7406\uFF08\u5B81\u53EF\u4E0D\u9644\u52A0\uFF0C\u4E5F\u4E0D\u8BEF\u9644\u52A0\uFF09\u3002\n */\n blank: boolean\n}\n\n/** \u8F93\u5165\u6846\u6839\u5143\u7D20\u7684\u9009\u62E9\u5668\uFF08\u4E0E interceptors.ts \u4FDD\u6301\u4E00\u81F4\uFF09\u3002 */\nconst COMPOSER_SELECTOR = '[data-composer-input]'\n\n/** \u8F93\u5165\u5361\u7247\u9009\u62E9\u5668\uFF08\u5B98\u65B9\u5728 InputBar \u4E0A\u5199\u7684\u6807\u8BB0\uFF09\u3002 */\nconst CARD_SELECTOR = '[data-composer-card]'\n\nconst state: BridgeState = { actions: null, draft: '', sessionId: '', blank: false }\n\n/**\n * \u69FD\u4F4D\u7EC4\u4EF6\u6BCF\u6B21\u6E32\u67D3\u6295\u9012\u4E00\u6B21\u6865\u63A5\u6570\u636E\u3002\n * @param next - \u672C\u4F1A\u8BDD\u7684\u8F93\u5165\u52A8\u4F5C\u3001\u5F53\u524D\u8349\u7A3F\u3001\u670D\u52A1\u7AEF\u4F1A\u8BDD id\u3001\u4EE5\u53CA\u4F1A\u8BDD\u662F\u5426\u8FD8\u6CA1\u6709\u6D88\u606F\u3002\n */\nexport function publishInputBridge(next: {\n readonly actions: InputActionsLike | null\n readonly draft: string\n readonly sessionId: string\n readonly blank: boolean\n}): void {\n state.actions = next.actions\n state.draft = next.draft\n state.sessionId = next.sessionId\n state.blank = next.blank\n}\n\n/**\n * \u5378\u8F7D\u65F6\u64A4\u4E0B\u6865\u63A5\uFF0C\u907F\u514D\u300C\u5207\u8D70\u7684\u4F1A\u8BDD\u300D\u7559\u4E0B\u7684\u65E7 actions \u88AB\u540E\u7EED\u624B\u52BF\u8BEF\u7528\u3002\n * \u53EA\u6E05\u81EA\u5DF1\u90A3\u4EFD\uFF1A\u540C\u4E00\u4E2A\u4F1A\u8BDD\u53EF\u80FD\u5148\u540E\u6302\u8F7D\u591A\u4E2A\u69FD\u4F4D\u6761\u76EE\u3002\n * @param sessionId - \u5378\u8F7D\u65B9\u6240\u5C5E\u4F1A\u8BDD id\u3002\n */\nexport function releaseInputBridge(sessionId: string): void {\n if (state.sessionId !== sessionId) return\n state.actions = null\n state.draft = ''\n state.sessionId = ''\n state.blank = false\n}\n\n/** \u5F53\u524D\u4F1A\u8BDD\u662F\u4E0D\u662F\u8FD8\u6CA1\u6709\u4EFB\u4F55\u6D88\u606F\uFF08\u300C\u4EC5\u9996\u6B21\u63D2\u5165\u300D\u7684\u5224\u636E\uFF09\u3002 */\nexport function currentBlankSession(): boolean {\n return state.blank === true\n}\n\n/** DOM \u515C\u5E95\u8BFB\u8349\u7A3F\uFF08\u69FD\u4F4D\u672A\u6302\u8F7D\u65F6\u7684\u6700\u540E\u624B\u6BB5\uFF09\u3002 */\nfunction draftFromDom(): string {\n const el = document.querySelector(COMPOSER_SELECTOR)\n if (!(el instanceof HTMLElement)) return ''\n return el.innerText.replace(/\\n+$/, '')\n}\n\n/** \u5F53\u524D\u8349\u7A3F\uFF1A\u6709\u69FD\u4F4D\u5C31\u4FE1\u69FD\u4F4D\u5FEB\u7167\uFF0C\u5426\u5219\u8BFB DOM\u3002 */\nexport function currentDraft(): string {\n return state.actions === null ? draftFromDom() : state.draft\n}\n\n/** \u5F53\u524D\u4F1A\u8BDD id\uFF08'' = \u65E0\u4F1A\u8BDD\uFF09\u3002 */\nexport function currentSessionId(): string {\n return state.sessionId\n}\n\n/**\n * \u628A\u8FD9\u4E00\u6B21\u8981\u9644\u52A0\u7684\u6761\u76EE\u62FC\u5230\u539F\u6587**\u672B\u5C3E**\u3002\n *\n * \u89C4\u5219\uFF08\u4E0E\u7528\u6237\u786E\u8BA4\u8FC7\u7684\u8BED\u4E49\u4E00\u81F4\uFF09\uFF1A\n * - \u591A\u6761\u6309\u5217\u8868\u987A\u5E8F\u62FC\u63A5\uFF0C\u6761\u76EE\u4E4B\u95F4\u7A7A\u4E00\u884C\uFF1B\n * - \u539F\u6587\u4E3A\u7A7A\u65F6**\u4E0D\u9644\u52A0** \u2014\u2014 \u6CA1\u6709\u300C\u4F60\u7684\u6D88\u606F\u300D\u53EF\u9644\u52A0\uFF0C\u6B64\u65F6\u5E94\u5F53\u4EA4\u8FD8\u5B98\u65B9\u539F\u8BED\u4E49\n * \uFF08\u7A7A\u8F93\u5165\u7684 Enter \u5728\u5B98\u65B9\u90A3\u91CC\u662F\u522B\u7684\u52A8\u4F5C\uFF0C\u62A2\u8FC7\u6765\u4F1A\u8BA9\u4EBA\u610F\u5916\uFF09\uFF1B\n * - \u6279\u6B21\u4E3A\u7A7A\u65F6\u8FD4\u56DE null\uFF1B\n * - **\u5DF2\u7ECF\u4EE5\u540C\u4E00\u6BB5\u540E\u7F00\u7ED3\u5C3E\u65F6\u8FD4\u56DE null\uFF08\u5E42\u7B49\uFF09** \u2014\u2014 \u4E07\u4E00\u53D1\u9001\u90A3\u4E00\u6B65\u6CA1\u6210\uFF0C\u7B2C\u4E8C\u6B21\n * \u70B9\u51FB\u4E0D\u4F1A\u628A\u540C\u4E00\u6BB5\u63D0\u793A\u8BCD\u518D\u53E0\u4E00\u904D\uFF0C\u800C\u662F\u76F4\u63A5\u653E\u884C\u5B98\u65B9\u53D1\u9001\uFF080.2.0 \u7684\u5931\u63A7\u75C7\u72B6\u5C31\u662F\n * \u300C\u4E00\u76F4\u70B9\u4E00\u76F4\u63D2\u5165\u300D\uFF0C\u8FD9\u6761\u62A4\u680F\u8BA9\u5B83\u53D8\u6210\u300C\u518D\u70B9\u4E00\u6B21\u5C31\u53D1\u51FA\u53BB\u300D\uFF09\u3002\n *\n * \u26A0\uFE0F **\u8FD9\u91CC\u7EDD\u4E0D\u80FD\u518D\u6309\u63D2\u5165\u6A21\u5F0F\u8FC7\u6EE4\u4E00\u904D**\uFF1A\u8FD9\u4E00\u6279\u91CC\u8BE5\u6709\u8C01\uFF0C\u5DF2\u7531\u8C03\u7528\u65B9\n * `appendBatchForSend(book, blank)` \u51B3\u5B9A\u30020.4.0 \u5C31\u662F\u5728\u8FD9\u91CC\u4E22\u8FC7\u529F\u80FD\u7684 \u2014\u2014 \u672C\u51FD\u6570\u5F53\u65F6\n * \u53EB `withAlwaysPrompts`\uFF0C\u5185\u90E8\u53C8\u6309 `always === true` \u8FC7\u6EE4\u4E86\u4E00\u6B21\uFF0C\u540E\u679C\u662F\uFF1A\n * \u00B7 \u65B0\u4F1A\u8BDD\u7B2C\u4E00\u6761\u91CC\u300C\u4EC5\u9996\u6B21\u300D\u7684\u6761\u76EE\u88AB\u8FD9\u5C42\u8FC7\u6EE4\u4E22\u6389\uFF0C\u53EA\u5269\u300C\u6BCF\u6B21\u300D\u7684\uFF1B\n * \u00B7 \u82E5\u4E00\u6761\u300C\u6BCF\u6B21\u300D\u90FD\u6CA1\u6709\uFF0C`picked.length === 0` \u76F4\u63A5\u8FD4\u56DE null\uFF0C\u7B2C\u4E00\u6761\u4EC0\u4E48\u90FD\u4E0D\u9644\u3002\n * \u6A21\u5F0F\u5224\u65AD\u53EA\u5141\u8BB8\u6709\u4E00\u5904\uFF08`settings-contract.ts` \u7684 `insertModeOf`\uFF09\u3002\n * @param draft - \u5F53\u524D\u8349\u7A3F\u539F\u6587\u3002\n * @param prompts - \u8FD9\u4E00\u6B21\u8981\u9644\u52A0\u7684\u6761\u76EE\uFF08\u8C03\u7528\u65B9\u5DF2\u51B3\u5B9A\uFF0C\u542B\u8DE8\u5206\u7C7B\u987A\u5E8F\uFF09\u3002\n * @returns \u62FC\u63A5\u540E\u7684\u5B8C\u6574\u8349\u7A3F\uFF1B\u65E0\u9700\u9644\u52A0\u65F6\u4E3A null\u3002\n */\nexport function withPromptsAppended(draft: string, prompts: readonly QuickPrompt[]): string | null {\n const picked = prompts.filter(item => item.prompt.trim() !== '')\n if (picked.length === 0) return null\n const base = draft.replace(/\\s+$/, '')\n if (base === '') return null\n const suffix = picked.map(item => item.prompt.trim()).join('\\n\\n')\n if (base.endsWith(suffix)) return null\n return `${base}\\n\\n${suffix}`\n}\n\n/**\n * \u628A\u8FD9\u4E00\u6B21\u8981\u9644\u52A0\u7684\u6761\u76EE\u5199\u56DE\u7F16\u8F91\u5668\u3002\n *\n * \u53EA\u8D1F\u8D23\u5199\u5165\uFF0C\u4E0D\u8D1F\u8D23\u53D1\u9001\uFF1A\u53D1\u9001\u52A8\u4F5C\u4EA4\u8FD8\u5B98\u65B9\u624B\u52BF\uFF08\u89C1 interceptors.ts \u7684\u4E24\u6761\u8DEF\u5F84\uFF09\uFF0C\n * \u8FD9\u6837\u300C\u53D1\u9001 / \u6392\u961F / \u6253\u65AD\u300D\u7684\u8BED\u4E49\u5B8C\u5168\u7531\u5B98\u65B9\u51B3\u5B9A\uFF0C\u672C\u63D2\u4EF6\u4E0D\u505A\u7B2C\u4E8C\u5957\u5224\u65AD\u3002\n * @param prompts - \u8FD9\u4E00\u6B21\u8981\u9644\u52A0\u7684\u6761\u76EE\uFF08\u6765\u81EA `deps.promptsForSend()`\uFF09\u3002\n * @returns true = \u5DF2\u5199\u5165\uFF08\u8C03\u7528\u65B9\u5E94\u7EE7\u7EED\u8D70\u5B98\u65B9\u53D1\u9001\u624B\u52BF\uFF09\uFF1Bfalse = \u65E0\u9700\u9644\u52A0\u3002\n */\nexport function applyPromptsForSend(prompts: readonly QuickPrompt[]): boolean {\n const actions = state.actions\n if (actions === null) return false\n const next = withPromptsAppended(currentDraft(), prompts)\n if (next === null) return false\n actions.setDraft(next)\n return true\n}\n\n/** \u628A\u4E00\u6BB5\u6587\u672C\u63D2\u8FDB\u8F93\u5165\u6846\uFF08\u6761\u76EE\u70B9\u51FB\u63D2\u5165\u7528\uFF1B\u539F\u6709\u5185\u5BB9\u4FDD\u7559\uFF0C\u65B0\u5185\u5BB9\u53E6\u8D77\u4E00\u884C\uFF09\u3002 */\nexport function insertIntoDraft(text: string): boolean {\n const actions = state.actions\n const body = text.trim()\n if (actions === null || body === '') return false\n const draft = currentDraft()\n const next = draft.trim() === '' ? body : `${draft.replace(/\\s+$/, '')}\\n${body}`\n actions.setDraft(next)\n return true\n}\n\n/** \u6574\u4F53\u66FF\u6362\u8349\u7A3F\uFF08\u4F18\u5316\u7ED3\u679C\u5199\u56DE\u7528\uFF09\u3002 */\nexport function replaceDraft(text: string): boolean {\n const actions = state.actions\n if (actions === null) return false\n actions.setDraft(text)\n return true\n}\n\n/** \u628A\u7126\u70B9\u4EA4\u8FD8\u8F93\u5165\u6846\uFF08\u63D2\u5165/\u5199\u56DE\u4E4B\u540E\u8C03\u7528\uFF0C\u65B9\u4FBF\u63A5\u7740\u6253\u5B57\uFF09\u3002 */\nexport function focusComposer(): void {\n const el = document.querySelector(COMPOSER_SELECTOR)\n if (el instanceof HTMLElement) el.focus({ preventScroll: true })\n}\n\n/**\n * \u627E\u51FA\u8FD9\u6B21\u70B9\u51FB\u843D\u5728\u7684**\u5B98\u65B9\u53D1\u9001\u4E3B\u6309\u94AE**\uFF1B\u4E0D\u662F\u53D1\u9001\u952E\u65F6\u8FD4\u56DE null\u3002\n *\n * \u4E3A\u4EC0\u4E48\u8FD4\u56DE\u5143\u7D20\u800C\u4E0D\u662F\u5E03\u5C14\uFF1A\u8C03\u7528\u65B9\u8981\u62FF\u5B83**\u91CD\u653E\u4E00\u6B21\u70B9\u51FB**\uFF08\u89C1 interceptors.ts\uFF09\u3002\n * \u8FD9\u91CC\u5FC5\u987B\u8FD4\u56DE\u771F\u6B63\u7684 `<button>`\uFF0C\u800C\u4E0D\u662F `event.target` \u2014\u2014 \u53D1\u9001\u952E\u662F\u4E2A\u5706\u5F62\u6309\u94AE\uFF0C\n * \u89C6\u89C9\u4E2D\u5FC3\u5C31\u662F\u91CC\u9762\u7684 `<svg>` / `<path>`\uFF0C\u800C **SVG \u5143\u7D20\u6CA1\u6709 `.click()`**\u3002\n * 0.2.0 \u5C31\u662F\u56E0\u4E3A\u628A `event.target` \u5F53\u6309\u94AE\u7528\u3001`click()` \u629B TypeError \u800C\u6CA1\u53D1\u9001\uFF0C\n * \u75C7\u72B6\u662F\u300C\u70B9\u4E86\u53EA\u63D2\u5165\u3001\u4E0D\u53D1\u9001\uFF0C\u4E00\u76F4\u70B9\u4E00\u76F4\u63D2\u5165\u300D\u3002\n *\n * \u4E3A\u4EC0\u4E48\u6562\u6309\u7ED3\u6784\u5224\u522B\uFF1A\u53D1\u9001\u952E\u4E0E\u505C\u6B62\u952E\u5171\u7528\u540C\u4E00\u4E2A\u4F4D\u7F6E\uFF08\u5361\u7247\u91CC\u6700\u540E\u4E00\u4E2A button\uFF09\uFF0C\n * \u53EA\u80FD\u9760\u56FE\u5F62\u533A\u5206 \u2014\u2014 \u505C\u6B62\u6E32\u67D3 `<rect>`\uFF08\u65B9\u5757\uFF09\uFF0C\u53D1\u9001\u6E32\u67D3 `<path>`\uFF08\u7BAD\u5934\uFF09\u3002\n * \u6309\u56FE\u5F62\u5224\u522B\u4E0E\u754C\u9762\u6587\u6848\u3001\u8BED\u8A00\u90FD\u65E0\u5173\uFF0C\u4E2D\u82F1\u6587\u73AF\u5883\u4E00\u81F4\u3002\n * @param target - \u4E8B\u4EF6\u76EE\u6807\uFF08\u53EF\u80FD\u662F\u6309\u94AE\u672C\u8EAB\uFF0C\u4E5F\u53EF\u80FD\u662F\u5B83\u5185\u90E8\u7684\u56FE\u6807\uFF09\u3002\n * @returns \u5B98\u65B9\u53D1\u9001\u4E3B\u6309\u94AE\uFF1B\u65E0\u6CD5\u786E\u5B9A\u65F6 null\uFF08\u6B64\u65F6\u8C03\u7528\u65B9\u5FC5\u987B**\u4E0D\u62E6\u622A**\uFF09\u3002\n */\nexport function sendButtonOf(target: EventTarget | null): HTMLButtonElement | null {\n if (!(target instanceof Element)) return null\n const card = target.closest(CARD_SELECTOR)\n if (card === null) return null\n const buttons = card.querySelectorAll('button')\n if (buttons.length === 0) return null\n const last = buttons[buttons.length - 1]!\n // \u5FC5\u987B\u662F\u771F\u6B63\u7684 <button>\uFF1A\u62FF\u5230\u7684\u82E5\u662F svg\uFF0C\u91CD\u653E\u70B9\u51FB\u4F1A\u5931\u8D25\u3002\n if (!(last instanceof HTMLButtonElement)) return null\n if (last !== target && !last.contains(target)) return null\n if (last.disabled) return null\n // \u505C\u6B62\u952E\uFF1A\u65B9\u5757\u56FE\u6807\u3002\u53D1\u9001\u952E\uFF1A\u7BAD\u5934 path\u3002\n if (last.querySelector('svg rect') !== null) return null\n if (last.querySelector('svg path') === null) return null\n return last\n}\n\n/** \u4E00\u6761\u88AB\u5BBF\u4E3B\u4E22\u6389\u7684\u6761\u76EE\uFF08\u9762\u677F\u636E\u6B64\u5982\u5B9E\u544A\u8BC9\u7528\u6237\"\u4E22\u4E86\u51E0\u6761\u3001\u4E3A\u4EC0\u4E48\"\uFF09\u3002 */\nexport interface OptimizeDropped {\n readonly id: string\n readonly kind: string\n readonly reason: string\n}\n\n/** \u4E00\u6B21\u4F18\u5316\u7684\u7ED3\u679C\u3002 */\nexport interface OptimizeOutcome {\n readonly ok: boolean\n /** \u6210\u529F\u65F6\uFF1A\u4F18\u5316\u540E\u7684\u6B63\u6587\u3002 */\n readonly text?: string\n /** \u5931\u8D25\u65F6\uFF1A\u7ED9\u7528\u6237\u770B\u7684\u4E00\u53E5\u8BDD\u539F\u56E0\u3002 */\n readonly error?: string\n /** \u6210\u529F\u65F6\uFF1A\u5B9E\u9645\u4F7F\u7528\u7684\u8DEF\u7531\uFF08\u7528\u4E8E\u300C\u4F18\u5316\u6CA1\u751F\u6548\u300D\u65F6\u7684\u6392\u67E5\uFF09\u3002 */\n readonly route?: string\n /** 0.6.0 \u8D77\uFF1A\u901A\u8FC7\u9010\u5B57\u4F9D\u636E\u6821\u9A8C\u3001\u771F\u7684\u8FDB\u5165\u6210\u54C1\u7684\u6761\u76EE\u6570\u3002 */\n readonly itemCount?: number\n /** 0.6.0 \u8D77\uFF1A\u88AB\u4E22\u6389\u7684\u6761\u76EE\uFF08\u5F15\u6587\u5BF9\u4E0D\u4E0A\u539F\u8BDD / \u8D85\u4E0A\u9650 / \u8D85\u7BC7\u5E45\u9884\u7B97\uFF09\u3002 */\n readonly dropped?: readonly OptimizeDropped[]\n /** 0.6.0 \u8D77\uFF1A\u5BBF\u4E3B\u7ED9\u7684\u8B66\u544A\uFF08\u622A\u65AD\u3001\u5FFD\u7565\u7684 op\u3001\u9884\u7B97\u964D\u7EA7\u2026\u2026\uFF09\u3002 */\n readonly warnings?: readonly string[]\n /** 0.6.0 \u8D77\uFF1Atrue = \u964D\u7EA7\u8DEF\u5F84\uFF08\u6A21\u578B\u6CA1\u6309 JSON \u5951\u7EA6\u8F93\u51FA\uFF0C\u6574\u6BB5\u7167\u6536\uFF0C\u672A\u505A\u4F9D\u636E\u6821\u9A8C\uFF09\u3002 */\n readonly fallback?: boolean\n /** 0.6.0 \u8D77\uFF1Atrue = \u7A7A\u4EA7\u51FA\u540E\u91CD\u8BD5\u8FC7\u4E00\u6B21\u3002 */\n readonly retried?: boolean\n /** 0.6.0 \u8D77\uFF1A'custom' = \u7528\u4E86\u8BBE\u7F6E\u9875\u91CC\u90A3\u4EFD\u63D0\u793A\u8BCD\uFF1B'builtin' = \u5185\u7F6E\u90A3\u4EFD\u3002 */\n readonly promptSource?: string\n /** 0.6.0 \u8D77\uFF1A\u88AB rewrite \u8986\u76D6\u6389\u7684\u539F\u8BDD\u5B57\u7B26\u6570\u3002 */\n readonly rewrittenChars?: number\n}\n\n/** \u628A\u5BBF\u4E3B\u56DE\u7684 `dropped` \u6536\u7A84\u6210\u5B89\u5168\u5F62\u72B6\uFF08\u54CD\u5E94\u4F53\u6309\u4E0D\u53EF\u4FE1\u8F93\u5165\u5904\u7406\uFF09\u3002 */\nfunction droppedOf(value: unknown): readonly OptimizeDropped[] {\n if (!Array.isArray(value)) return []\n const out: OptimizeDropped[] = []\n for (const entry of value) {\n if (typeof entry !== 'object' || entry === null) continue\n const row = entry as Record<string, unknown>\n out.push({\n id: typeof row.id === 'string' ? row.id : '',\n kind: typeof row.kind === 'string' ? row.kind : '',\n reason: typeof row.reason === 'string' ? row.reason : '',\n })\n }\n return out\n}\n\n/** \u628A\u5BBF\u4E3B\u56DE\u7684 `warnings` \u6536\u7A84\u6210\u5B57\u7B26\u4E32\u6570\u7EC4\u3002 */\nfunction warningsOf(value: unknown): readonly string[] {\n if (!Array.isArray(value)) return []\n return value.filter((entry): entry is string => typeof entry === 'string')\n}\n\n/**\n * \u8BF7\u5BBF\u4E3B\u534A\u8DD1\u4E00\u6B21\u72EC\u7ACB\u4F18\u5316\u3002\n *\n * \u4E3A\u4EC0\u4E48\u662F\u4E00\u6B21 HTTP \u5F80\u8FD4\uFF1A\u51FA\u7F51\u8BF7\u6C42\u7531\u5BBF\u4E3B\u7684\u6A21\u578B\u9002\u914D\u5668\u53D1\u51FA\uFF0C\u6D4F\u89C8\u5668\u4FA7\u78B0\u4E0D\u5230\u6A21\u578B\u8DEF\u7531\uFF1B\n * \u5BBF\u4E3B <-> \u5BA2\u6237\u7AEF\u4E4B\u95F4\u6CA1\u6709\u522B\u7684\u53D7\u652F\u6301\u901A\u9053\uFF08\u4E0E WestFox \u7684\u63D2\u4EF6\u540C\u6784\uFF09\u3002\n * @param text - \u8F93\u5165\u6846\u91CC\u7684\u539F\u6587\u3002\n * @param tier - \u5F3A\u5EA6\u6863\u4F4D\u3002\n * @returns \u4F18\u5316\u7ED3\u679C\uFF1B\u7F51\u7EDC\u5C42\u5931\u8D25\u4E5F\u5F52\u4E00\u6210 `ok: false` \u800C\u4E0D\u629B\u3002\n */\nexport async function optimizeDraft(text: string, tier: string): Promise<OptimizeOutcome> {\n const body = text.trim()\n if (body === '') return { ok: false, error: '\u8F93\u5165\u6846\u662F\u7A7A\u7684\uFF0C\u5148\u5199\u70B9\u4EC0\u4E48\u518D\u4F18\u5316' }\n let response: Response\n try {\n response = await fetch(OPTIMIZER_API_PATH, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ text: body, tier }),\n })\n } catch (error) {\n return { ok: false, error: `\u8FDE\u4E0D\u4E0A\u5BBF\u4E3B\u534A\u7684\u4F18\u5316\u63A5\u53E3\uFF1A${error instanceof Error ? error.message : String(error)}` }\n }\n if (!response.ok) {\n return { ok: false, error: `\u5BBF\u4E3B\u534A\u8FD4\u56DE HTTP ${response.status}\uFF08\u63D2\u4EF6\u53EF\u80FD\u8FD8\u6CA1\u91CD\u542F\u751F\u6548\uFF09` }\n }\n let payload: unknown\n try {\n payload = await response.json()\n } catch {\n return { ok: false, error: '\u5BBF\u4E3B\u534A\u8FD4\u56DE\u7684\u4E0D\u662F JSON' }\n }\n const record = (typeof payload === 'object' && payload !== null ? payload : {}) as Record<string, unknown>\n const retried = record.retried === true\n if (record.ok !== true) {\n const message = typeof record.error === 'string' && record.error !== '' ? record.error : '\u4F18\u5316\u5931\u8D25'\n return { ok: false, error: message, retried }\n }\n const optimized = typeof record.text === 'string' ? record.text.trim() : ''\n if (optimized === '') return { ok: false, error: '\u6A21\u578B\u6CA1\u6709\u4EA7\u51FA\u4EFB\u4F55\u5185\u5BB9', retried }\n const route = `${String(record.provider ?? '')}/${String(record.model ?? '')}`\n return {\n ok: true,\n text: optimized,\n route,\n itemCount: typeof record.itemCount === 'number' ? record.itemCount : 0,\n dropped: droppedOf(record.dropped),\n warnings: warningsOf(record.warnings),\n fallback: record.fallback === true,\n retried,\n promptSource: typeof record.promptSource === 'string' ? record.promptSource : '',\n rewrittenChars: typeof record.rewrittenChars === 'number' ? record.rewrittenChars : 0,\n }\n}\n", "/** \u8F93\u5165\u6846\u62E6\u622A\u5668\uFF1A\u63A5\u7BA1 Enter \u5BB6\u65CF\u952E\u4F4D\uFF08\u53D1\u9001/\u6362\u884C\uFF09\u4E0E\u53F3\u952E\u83DC\u5355\u3002\n * \u4E0E React \u65E0\u5173\uFF1A\u57FA\u4E8E\u300C\u6355\u83B7\u9636\u6BB5 + \u76EE\u6807\u9650\u5B9A + \u5408\u6210\u56DE\u653E\u300D\u7684\u62E6\u622A\u6A21\u578B\u3002\n *\n * \u952E\u4F4D\u89C4\u5219\uFF08\u603B\u62EC\uFF09\uFF1A\n * - \u8BB0\u5F55\u76EE\u6807\u53EA\u5728\u4E3B\u804A\u5929\u8F93\u5165\u6846 [data-composer-input] \u5185\uFF1B\n * - IME \u7EC4\u5408\u671F\u95F4\uFF08isComposing / keyCode 229\uFF09\u4E00\u5F8B\u653E\u884C\uFF0C\u7EDD\u4E0D\u5F71\u54CD\u4E2D\u6587\u8F93\u5165\uFF1B\n * - '/' '@' \u89E6\u53D1\u5668\u83DC\u5355\u6216\u4EFB\u4F55\u8F93\u5165\u6846 overlay \u6253\u5F00\u65F6\u653E\u884C Enter\uFF0C\u8BA9\u83DC\u5355\u4EF2\u88C1\u4F18\u5148\uFF1B\n * - \u547D\u4E2D\u300C\u53D1\u9001\u952E\u4F4D\u300D\u2192 \u56DE\u653E\u5E26 Ctrl \u52A0\u901F\u8BED\u4E49\u4E4B\u5916\u7684\u666E\u901A Enter\uFF08\u8D70\u5B98\u65B9\u63D0\u4EA4\u7BA1\u7EBF\uFF09\uFF1B\n * - \u547D\u4E2D\u300C\u6362\u884C\u952E\u4F4D\u300D\u2192 \u56DE\u653E Shift+Enter\uFF08\u5B98\u65B9\u6362\u884C\u7BA1\u7EBF\uFF09\uFF1B\n * - Ctrl+Enter / Meta+Enter \u82E5\u672A\u88AB\u7ED1\u5B9A\uFF0C\u5219\u56DE\u653E\u539F\u7EC4\u5408\uFF0C\u4FDD\u7559\u5B98\u65B9\u300C\u52A0\u901F\u63D0\u4EA4\u300D\u884C\u4E3A\uFF1B\n * - \u5176\u4F59 Enter \u5BB6\u65CF\u7EC4\u5408\uFF1A\u6D88\u8017\u4F46\u4E0D\u52A8\u4F5C\uFF08\u7528\u6237\u663E\u5F0F\u53D6\u6D88\u7684\u539F\u751F\u8BED\u4E49\uFF09\u3002\n *\n * \u5173\u952E\u5B88\u536B\uFF1A\u5408\u6210\u56DE\u653E\u4E8B\u4EF6\u4E5F\u5FC5\u987B\u7ECF\u8FC7 window \u6355\u83B7\u76D1\u542C\u5668\uFF0C\u56E0\u6B64\u56DE\u653E\u671F\u95F4\u7528\n * \u540C\u6B65\u6807\u5FD7\u8DF3\u8FC7\u81EA\u8EAB\u62E6\u622A\uFF0C\u5426\u5219\u53D1\u9001/\u6362\u884C\u56DE\u653E\u4F1A\u65E0\u9650\u81EA\u89E6\u53D1\u3002\n */\nimport {\n chordToInit, encodeChord, isEnterFamily, type ChordEvent,\n} from './chords.ts'\nimport { applyPromptsForSend, sendButtonOf } from './quick-commands.ts'\nimport { activeSections, type ComposerUxSettings, type MenuState, type QuickPrompt } from '../settings-contract.ts'\n\nexport interface InterceptorDeps {\n /** \u540C\u6B65\u8BFB\u53D6\u5F53\u524D\u89E3\u6790\u540E\u7684\u8BBE\u7F6E\uFF08\u62E6\u622A\u5668\u975E React \u73AF\u5883\uFF09\u3002 */\n readonly settings: () => ComposerUxSettings\n /**\n * \u540C\u6B65\u8BFB\u53D6**\u8FD9\u4E00\u6B21\u53D1\u9001\u8981\u9644\u52A0\u7684\u6761\u76EE**\uFF08\u8DE8\u5206\u7C7B\uFF09\u3002\n *\n * 0.3.0 \u8D77\u5FEB\u6377\u6307\u4EE4\u5B58\u5728 quick-prompts.json \u91CC\uFF0C\u4E0D\u518D\u5C5E\u4E8E\u8BBE\u7F6E\u6587\u6863\uFF0C\u6240\u4EE5\u8FD9\u91CC\u5355\u72EC\u8981\u4E00\u4E2A\n * \u53D6\u503C\u51FD\u6570\u3002\u300C\u4EC5\u9996\u6B21\u300D\u7684\u6761\u76EE\u662F\u5426\u7B97\u5728\u5185\uFF0C\u7531\u8C03\u7528\u65B9\u5728\u8FD9\u4E2A\u51FD\u6570\u91CC\u7ED3\u5408\u300C\u4F1A\u8BDD\u662F\u5426\u8FD8\u6CA1\u6709\n * \u6D88\u606F\u300D\u51B3\u5B9A\uFF08\u89C1 client.tsx \u7684 `appendBatchForSend(book, currentBlankSession())`\uFF09\u2014\u2014\n * \u62E6\u622A\u5668\u53EA\u8D1F\u8D23\u628A\u62FF\u5230\u7684\u8FD9\u4E00\u6279\u9644\u52A0\u4E0A\u53BB\u3002\n */\n readonly promptsForSend: () => readonly QuickPrompt[]\n /** \u6253\u5F00 / \u5173\u95ED\u53F3\u952E\u83DC\u5355\u3002 */\n readonly setMenu: (state: MenuState | null) => void\n /** \u81EA\u5B9A\u4E49\u83DC\u5355\u5F53\u524D\u662F\u5426\u6253\u5F00\uFF08\u539F\u751F\u83DC\u5355\u6A21\u5F0F\u4E0B\u9700\u8981\u6E05\u6389\uFF09\u3002 */\n readonly menuOpen: () => boolean\n}\n\nconst INPUT_SELECTOR = '[data-composer-input]'\nconst OVERLAY_SELECTOR = '[data-trigger-menu], [data-conversation-composer-overlay]'\n\n/** \u76EE\u6807\u662F\u5426\u843D\u5728\u4E3B\u804A\u5929\u8F93\u5165\u6846\u53CA\u5176\u5185\u90E8\u3002 */\nfunction findComposerRoot(target: EventTarget | null): HTMLElement | null {\n if (!(target instanceof Element)) return null\n return target.closest<HTMLElement>(INPUT_SELECTOR)\n}\n\n/** \u89E6\u53D1\u5668\u83DC\u5355\uFF08'/' '@'\uFF09\u6216\u8F93\u5165\u6846 overlay \u662F\u5426\u6253\u5F00\u3002 */\nfunction overlayOpen(): boolean {\n return document.querySelector(OVERLAY_SELECTOR) !== null\n}\n\n/** \u56DE\u653E\u8FDB\u884C\u4E2D\u6807\u5FD7\uFF1A\u5408\u6210\u4E8B\u4EF6\u56DE\u5230\u6355\u83B7\u76D1\u542C\u5668\u65F6\u8DF3\u8FC7\u81EA\u8EAB\u62E6\u622A\u3002 */\nlet replaying = false\n\n/** \u5B98\u65B9\u53D1\u9001\u6309\u94AE\u7684\u300C\u5148\u5199\u56DE\u3001\u518D\u91CD\u653E\u300D\u6807\u5FD7\uFF08\u907F\u514D\u5408\u6210\u70B9\u51FB\u88AB\u81EA\u5DF1\u518D\u62E6\u4E00\u6B21\uFF09\u3002 */\nlet replayingSendClick = false\n\n/** \u53F3\u952E\u65F6\u9884\u8BFB\u6210\u529F\u7684\u526A\u8D34\u677F\u6587\u672C\u7F13\u5B58\uFF08null = \u672A\u9884\u8BFB/\u9884\u8BFB\u5931\u8D25\uFF09\u3002 */\nlet pasteCache: string | null = null\n\n/** \u5728\u53F3\u952E\u624B\u52BF\u91CC\u53D1\u8D77\u4E00\u6B21\u9759\u9ED8\u9884\u8BFB\uFF1A\u6388\u6743\u6D6E\u7A97\u6B64\u523B\u51FA\u73B0\uFF0C\u7528\u6237\u987A\u624B\u70B9\u4E00\u6B21\u5373\u53EF\u3002 */\nfunction prefetchClipboard(): void {\n pasteCache = null\n const readText = (navigator as Navigator & { clipboard?: { readText?: () => Promise<string> } }).clipboard?.readText\n if (typeof readText !== 'function') return\n readText.call(navigator.clipboard).then(\n (text: string) => { pasteCache = text },\n () => { pasteCache = null },\n )\n}\n\n/** \u5411\u8F93\u5165\u6846\u6839\u5143\u7D20\u6D3E\u53D1\u5408\u6210\u6309\u952E\uFF08\u89E6\u53D1 Lexical \u81EA\u8EAB\u952E\u76D8\u7BA1\u7EBF\uFF09\u3002 */\nfunction dispatchKey(root: HTMLElement, init: KeyboardEventInit): void {\n replaying = true\n try {\n root.dispatchEvent(new KeyboardEvent('keydown', init))\n } finally {\n replaying = false\n }\n}\n\n/** \u662F\u5426\u8FDB\u5165 IME \u7EC4\u5408\uFF08\u5408\u6210\u4E8B\u4EF6\u9700\u4E0E\u771F\u5B9E\u6309\u952E\u8D70\u540C\u4E00\u5B88\u536B\uFF09\u3002 */\nfunction composing(event: KeyboardEvent): boolean {\n // oxlint-disable-next-line typescript/no-deprecated\n return event.isComposing || event.keyCode === 229\n}\n\n/** \u5B89\u88C5\u4E24\u4E2A\u6355\u83B7\u9636\u6BB5\u62E6\u622A\u5668\uFF1B\u8FD4\u56DE\u5378\u8F7D\u5668\u3002 */\nexport function installInterceptors(deps: InterceptorDeps): () => void {\n const onKeyDown = (event: KeyboardEvent): void => {\n if (replaying) return\n // \u300C\u952E\u4F4D\u300D\u680F\uFF08\u6216\u603B\u5F00\u5173\uFF09\u5173\u7740\u65F6\u5B8C\u5168\u4E0D\u4ECB\u5165\uFF1AEnter \u5BB6\u65CF\u6309 DSH \u539F\u751F\u884C\u4E3A\u8D70\u3002\n if (!activeSections(deps.settings()).keys) return\n const root = findComposerRoot(event.target)\n if (root === null) return\n if (composing(event)) return\n const chord = encodeChord(event as unknown as ChordEvent)\n if (!isEnterFamily(chord)) return\n // \u83DC\u5355/overlay \u6253\u5F00\u65F6\uFF0CEnter \u8981\u7ED9\u83DC\u5355\u4EF2\u88C1\uFF08\u8865\u5168\u9009\u62E9\u3001\u5F39\u5C42\u5173\u95ED\uFF09\u8BA9\u8DEF\u3002\n if (overlayOpen()) return\n\n const settings = deps.settings()\n const gesture = chord === settings.sendKey\n ? 'send'\n : chord === settings.newlineKey\n ? 'newline'\n : (chord === 'Ctrl+Enter' || chord === 'Meta+Enter') ? 'accelerated'\n : 'none'\n\n event.preventDefault()\n event.stopPropagation()\n // \u957F\u6309\u8FDE\u53D1\uFF1A\u6D88\u8017\u4E00\u6B21\u5373\u53EF\uFF08\u53D1\u9001\u9632\u673A\u67AA\u95E8\u4E0E\u5B98\u65B9\u4E00\u81F4\uFF0C\u6362\u884C\u8FDE\u53D1\u65E0\u610F\u4E49\uFF09\u3002\n if (event.repeat) return\n\n if (gesture === 'send') {\n // \u53D1\u9001\u65F6\u9644\u52A0\u6761\u76EE\uFF1A\u5148\u628A promptsForSend() \u7ED9\u51FA\u7684\u90A3\u4E00\u6279\u5199\u56DE\u7F16\u8F91\u5668\u672B\u5C3E\uFF0C\u518D\u56DE\u653E\u53D1\u9001\n // \u624B\u52BF \u2014\u2014 \u5B98\u65B9\u624B\u52BF\u7167\u65E7\uFF08\u542B\u8FD0\u884C\u4E2D\u300C\u6392\u961F / \u6253\u65AD\u300D\u7684\u5224\u5B9A\uFF09\uFF0C\u672C\u63D2\u4EF6\u4E0D\u505A\u7B2C\u4E8C\u5957\u5224\u65AD\u3002\n // \u539F\u6587\u4E3A\u7A7A\u65F6 applyPromptsForSend \u8FD4\u56DE false\uFF0C\u4E00\u5207\u7167\u65E7\u3002\n // \u26A0\uFE0F \u8FD9\u4E00\u6279\u91CC\u300C\u8BE5\u6709\u8C01\u300D\u5DF2\u7531 promptsForSend()\uFF08= appendBatchForSend + blank\uFF09\u5B9A\u597D\uFF0C\n // \u5199\u56DE\u8FD9\u4E00\u6B65\u4E0D\u5F97\u518D\u6309\u63D2\u5165\u6A21\u5F0F\u8FC7\u6EE4\uFF080.4.0 \u5728\u8FD9\u91CC\u4E22\u8FC7\u300C\u4EC5\u9996\u6B21\u300D\uFF09\u3002\n applyPromptsForSend(deps.promptsForSend())\n dispatchKey(root, chordToInit('Enter'))\n } else if (gesture === 'newline') {\n dispatchKey(root, chordToInit('Shift+Enter'))\n } else if (gesture === 'accelerated') {\n dispatchKey(root, chordToInit('Ctrl+Enter'))\n }\n // gesture === 'none'\uFF1A\u6D88\u8017\u4F46\u65E0\u52A8\u4F5C\u3002\n }\n\n const onContextMenu = (event: MouseEvent): void => {\n const root = findComposerRoot(event.target)\n if (root === null) return\n const settings = deps.settings()\n // \u300C\u53F3\u952E\u83DC\u5355\u300D\u680F\uFF08\u6216\u603B\u5F00\u5173\uFF09\u5173\u7740\u65F6\u672C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u4ECB\u5165 \u2014\u2014 \u4E0E\u4E0B\u9762\u7684\u300C\u5B98\u65B9\u300D\u6863\u540C\u4E00\u6761\u51FA\u53E3\u3002\n if (!activeSections(settings).menu) return\n const mode = settings.menuMode\n // \u5B98\u65B9\u6863\uFF1A\u672C\u63D2\u4EF6**\u5B8C\u5168\u4E0D\u4ECB\u5165** \u2014\u2014 \u65E2\u4E0D preventDefault \u4E5F\u4E0D stopImmediatePropagation\uFF0C\n // DSH \u5B98\u65B9\u4E0E\u5176\u5B83\u63D2\u4EF6\u81EA\u5DF1\u7684\u53F3\u952E\u5904\u7406\u539F\u6837\u751F\u6548\u3002\uFF08DSH \u5B98\u65B9\u8F93\u5165\u6846\u672C\u8EAB\u6CA1\u6709\u53F3\u952E\u83DC\u5355\uFF0C\n // \u6240\u4EE5\u901A\u5E38\u770B\u5230\u7684\u5C31\u662F\u6D4F\u89C8\u5668\u83DC\u5355\u3002\uFF09\u5DF2\u6253\u5F00\u7684\u81EA\u5B9A\u4E49\u83DC\u5355\u7531 client.tsx \u5728\u5207\u6863\u65F6\u5173\u6389\u3002\n if (mode === 'official') return\n // \u6D4F\u89C8\u5668\u6863\uFF1A\u4E0D\u8BA9\u7B2C\u4E09\u65B9\u63D2\u4EF6\uFF08\u5982 dsh-paste-input-plus \u7684\u300C\u53EA\u6709\u590D\u5236\u300D\u83DC\u5355\uFF09\u5403\u6389\n // contextmenu\u2014\u2014\u6211\u4EEC\u6392\u5728 capture \u9636\u6BB5\u5148\u6267\u884C\uFF0CstopImmediatePropagation \u540E\n // \u4E8B\u4EF6\u5230\u4E0D\u4E86 bubble \u9636\u6BB5\u7684\u63D2\u4EF6\u76D1\u542C\u5668\uFF1B\u4F46\u4E0D preventDefault\uFF0C\u6D4F\u89C8\u5668\u539F\u751F\u83DC\u5355\u7167\u5E38\u51FA\u73B0\u3002\n if (mode === 'browser') {\n if (deps.menuOpen()) deps.setMenu(null)\n event.stopImmediatePropagation()\n event.stopPropagation()\n return\n }\n // \u81EA\u5B9A\u4E49\u6863\uFF1A\u4E24\u4EF6\u4E8B\u90FD\u505A\u2014\u2014preventDefault \u6389\u6D4F\u89C8\u5668\u83DC\u5355\uFF08\u6539\u7531\u672C\u63D2\u4EF6\u63A5\u7BA1\uFF09\uFF0C\n // \u5E76\u4E14\u548C\u300C\u6D4F\u89C8\u5668\u300D\u6863\u4E00\u6837 stopImmediatePropagation \u6321\u4F4F\u540C\u4E00\u5C42\u91CC\u5176\u5B83\u63D2\u4EF6\u7684\u6355\u83B7\u76D1\u542C\u3002\n // \u5426\u5219\u4E24\u8FB9\u4F1A\u5404\u5F39\u4E00\u4E2A\u83DC\u5355\u3002\u62E6\u5230\u7684\u662F**\u522B\u7684\u63D2\u4EF6**\uFF0C\u4E0D\u5F71\u54CD\u6211\u4EEC\u81EA\u5DF1\uFF1A\u672C\u63D2\u4EF6\u7684\u83DC\u5355\u7EC4\u4EF6\n // \u53EA\u76D1\u542C pointerdown / keydown / scroll / resize\uFF08\u89C1 ContextMenuHost\uFF09\u3002\n event.preventDefault()\n event.stopImmediatePropagation()\n event.stopPropagation()\n const selection = window.getSelection()\n const hasSelection = selection !== null\n && !selection.isCollapsed\n && selection.anchorNode !== null\n && root.contains(selection.anchorNode)\n deps.setMenu({ x: event.clientX, y: event.clientY, hasSelection })\n // \u8D81\u7740\u53F3\u952E\u7684\u7528\u6237\u624B\u52BF\u8FD8\u5728\uFF0C\u9759\u9ED8\u9884\u8BFB\u526A\u8D34\u677F\uFF08\u6388\u6743\u6D6E\u7A97\u6B64\u523B\u5F39\u51FA\uFF0C\u70B9\u4E00\u6B21\u5373\u56FA\u5316\uFF09\u3002\n prefetchClipboard()\n }\n\n /**\n * \u5B98\u65B9\u300C\u53D1\u9001\u300D\u6309\u94AE\u4E0A\u7684\u6761\u76EE\u9644\u52A0\u3002\n *\n * \u5B98\u65B9\u4E3B\u6309\u94AE\u8D70\u7684\u662F\u5305\u5185\u90E8\u7684 keyboard.submit\uFF08\u6CA1\u6709\u5BF9\u5916\u7684\u62E6\u622A\u94A9\u5B50\uFF09\uFF0C\u6240\u4EE5\u53EA\u80FD\u5728\n * \u6355\u83B7\u9636\u6BB5\u8BA4\u4E0B\u8FD9\u6B21\u70B9\u51FB\u3002\u8BA4\u4E0B\u4E4B\u540E\u4E0D\u53BB\u81EA\u5DF1\u8C03 submit \u2014\u2014 \u800C\u662F\u5148\u628A\u9644\u52A0\u5185\u5BB9\u5199\u56DE\u7F16\u8F91\u5668\u3001\n * \u518D\u7528\u540C\u4E00\u4E2A\u6309\u94AE\u91CD\u653E\u4E00\u6B21\u70B9\u51FB\uFF0C\u8BA9\u5B98\u65B9\u7684 primarySubmitMode\uFF08\u53D1\u9001 / \u6392\u961F / \u6253\u65AD\uFF09\n * \u539F\u6837\u751F\u6548\u3002\n *\n * \u4E24\u6761\u5FC5\u987B\u5B88\u4F4F\u7684\u7EAA\u5F8B\uFF080.2.0 \u5728\u8FD9\u4E24\u5904\u90FD\u51FA\u8FC7\u4E8B\uFF09\uFF1A\n * 1. \u91CD\u653E\u7684\u5FC5\u987B\u662F `sendButtonOf()` \u8FD4\u56DE\u7684**\u771F <button>**\uFF0C\u4E0D\u80FD\u662F event.target\n * \u2014\u2014 \u70B9\u5728\u5706\u5F62\u6309\u94AE\u7684\u89C6\u89C9\u4E2D\u5FC3\u65F6 target \u662F\u5185\u90E8\u7684 svg\uFF0Csvg \u6CA1\u6709 `.click()`\uFF0C\n * \u4F1A\u629B TypeError\uFF0C\u7ED3\u679C\u5C31\u662F\u300C\u5DF2\u63D2\u5165\u4F46\u6CA1\u53D1\u9001\u300D\u3002\n * 2. \u53EA\u6709\u5728\u786E\u8BA4\u80FD\u91CD\u653E\u4E4B\u540E\u624D preventDefault/stopPropagation\uFF1B\u62FF\u4E0D\u5230\u6309\u94AE\u5C31\u76F4\u63A5\n * \u653E\u884C\uFF0C\u7EDD\u4E0D\u628A\u7528\u6237\u8FD9\u6B21\u70B9\u51FB\u541E\u6389\u3002\n */\n const onClickSend = (event: MouseEvent): void => {\n if (replayingSendClick) return\n const button = sendButtonOf(event.target)\n if (button === null) return\n if (!applyPromptsForSend(deps.promptsForSend())) return\n event.preventDefault()\n event.stopPropagation()\n replayingSendClick = true\n try {\n button.click()\n } finally {\n replayingSendClick = false\n }\n }\n\n window.addEventListener('keydown', onKeyDown, true)\n window.addEventListener('contextmenu', onContextMenu, true)\n window.addEventListener('click', onClickSend, true)\n return () => {\n window.removeEventListener('keydown', onKeyDown, true)\n window.removeEventListener('contextmenu', onContextMenu, true)\n window.removeEventListener('click', onClickSend, true)\n }\n}\n\n/** \u53F3\u952E\u83DC\u5355\u52A8\u4F5C id\uFF08\u4E0E MENU_ITEMS \u5BF9\u5E94\uFF09\u3002 */\nexport type MenuActionId = 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'delete' | 'selectAll'\n\nexport interface MenuActionResult {\n readonly ok: boolean\n readonly message?: string\n}\n\n/** \u5728\u5F53\u524D\u8F93\u5165\u6846\u4E0A\u6267\u884C\u4E00\u4E2A\u53F3\u952E\u83DC\u5355\u52A8\u4F5C\u3002 */\nexport async function runMenuAction(id: MenuActionId): Promise<MenuActionResult> {\n const root = document.querySelector<HTMLElement>(INPUT_SELECTOR)\n if (root === null) return { ok: false, message: '\u627E\u4E0D\u5230\u8F93\u5165\u6846' }\n if (!document.activeElement || !root.contains(document.activeElement)) {\n if (root.isConnected) {\n root.focus({ preventScroll: true })\n }\n }\n switch (id) {\n case 'undo':\n dispatchKey(root, chordToInit('Ctrl+Z'))\n return { ok: true }\n case 'redo':\n dispatchKey(root, chordToInit('Ctrl+Y'))\n return { ok: true }\n case 'copy':\n return { ok: document.execCommand('copy') }\n case 'cut':\n return { ok: document.execCommand('cut') }\n case 'delete':\n return { ok: document.execCommand('delete') }\n case 'selectAll':\n return { ok: document.execCommand('selectAll') }\n case 'paste':\n return pasteText(root)\n }\n}\n\n/** \u5E26\u8D85\u65F6\u7684 Promise\uFF08\u7528\u4E8E\u7B49\u5F85\u526A\u8D34\u677F\u6388\u6743\u5F39\u7A97\uFF09\u3002 */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => { reject(new Error('clipboard-read timeout')) }, ms)\n promise.then(\n (value) => { clearTimeout(timer); resolve(value) },\n (error: unknown) => { clearTimeout(timer); reject(error) },\n )\n })\n}\n\nfunction isClipboardTimeout(error: unknown): boolean {\n return error instanceof Error && error.message === 'clipboard-read timeout'\n}\n\n/** \u5F53\u524D\u6D4F\u89C8\u5668\u662F\u4E0D\u662F Firefox\uFF08\u5B83\u5BF9\u8BFB\u526A\u8D34\u677F\u6709\u989D\u5916\u7684\u786E\u8BA4\u5F39\u7A97\uFF0C\u89C1 FIREFOX_TIP\uFF09\u3002 */\nfunction isFirefox(): boolean {\n return typeof navigator !== 'undefined' && /Firefox\\//.test(navigator.userAgent)\n}\n\n/**\n * Firefox \u7684\u8BFB\u526A\u8D34\u677F\u786E\u8BA4\u5F39\u7A97\u8BF4\u660E\u3002\n *\n * \u5B9E\u6D4B\u66F4\u6B63\uFF080.4.0\uFF0C\u7528\u6237\u5728 Firefox \u4E0A\u9A8C\u8FC7\uFF09\uFF1A\u8FD9\u4E2A\u5F39\u7A97**\u4E0D\u662F**\u6743\u9650\u9762\u677F\u3001\u4E5F**\u4E0D\u80FD**\u7528\n * `about:config` \u91CC\u7684\u9996\u9009\u9879\u5173\u6389\u2014\u2014\u5B83\u662F Firefox \u7684\u5B89\u5168\u673A\u5236\uFF1A\u7F51\u9875\u8BFB\u526A\u8D34\u677F\u8981\u5148\u5F39\u4E00\u4E2A\u53EA\u6709\n * \u300C\u7C98\u8D34(P)\u300D\u4E00\u9879\u7684\u4E34\u65F6\u5C0F\u7A97\uFF08\u7EA6 1 \u79D2\u540E\u624D\u53EF\u70B9\uFF09\uFF0C\u7528\u6237\u70B9\u4E86\u624D\u5B8C\u6210\u8BFB\u53D6\u3002\u6309 MDN \u7684\u8BF4\u660E\uFF0C\n * \u53EA\u6709\u6D4F\u89C8\u5668\u6269\u5C55\u51ED `clipboardRead` \u6743\u9650\u624D\u80FD\u514D\u6389\u5B83\uFF1BFirefox 147 \u8D77\u666E\u901A\u7F51\u9875\u8D70\u5B8C\u8FD9\u4E2A\u5F39\u7A97\n * \u4E5F\u53EF\u4EE5\u8BFB\u3002\u80FD\u9760\u6539\u8BBE\u7F6E\u514D\u6389\u5B83\u7684\u53EA\u6709 `dom.events.testing.asyncClipboard` \u8FD9\u7C7B**\u6D4B\u8BD5\u7528**\u5F00\u5173\uFF0C\n * \u90A3\u7B49\u4E8E\u5141\u8BB8\u4EFB\u4F55\u7F51\u7AD9\u9759\u9ED8\u8BFB\u526A\u8D34\u677F\uFF0C\u6211\u4EEC\u4E0D\u5728\u754C\u9762\u4E0A\u6559\u8FD9\u4E2A\u3002\n */\nconst FIREFOX_TIP = 'Firefox \u4E0D\u5141\u8BB8\u7F51\u9875\u9759\u9ED8\u8BFB\u526A\u8D34\u677F\uFF1A\u8BF7\u5728\u5F39\u51FA\u7684\u300C\u7C98\u8D34(P)\u300D\u5C0F\u7A97\u4E0A\u70B9\u4E00\u4E0B\uFF08\u7EA6 1 \u79D2\u540E\u624D\u53EF\u70B9\uFF0C\u8FD9\u662F Firefox \u7684\u5B89\u5168\u673A\u5236\uFF0C\u63D2\u4EF6\u5173\u4E0D\u6389\uFF09\uFF1B\u4E0D\u60F3\u591A\u8FD9\u4E00\u6B65\u5C31\u76F4\u63A5\u6309 Ctrl+V'\n\n/** \u7C98\u8D34\uFF1A\u8BFB\u526A\u8D34\u677F\u540E\u5728\u5149\u6807\u5904\u63D2\u5165\u7EAF\u6587\u672C\u3002\n * \u6D4F\u89C8\u5668\u5B89\u5168\u6A21\u578B\uFF1A\u5199\u526A\u8D34\u677F\uFF08\u590D\u5236/\u526A\u5207\uFF09\u514D\u6388\u6743\uFF0C\u8BFB\u526A\u8D34\u677F\uFF08\u7C98\u8D34\uFF09\u5FC5\u987B\u6388\u6743\uFF0C\n * \u4EFB\u4F55\u7F51\u9875\u90FD\u65E0\u6CD5\u7ED5\u8FC7\u3002Chrome / Edge \u662F**\u6309\u7AD9\u70B9**\u6388\u6743\uFF0C\u5141\u8BB8\u4E00\u6B21\u540E\u8BB0\u4F4F\u8BE5\u7AD9\u70B9\u3001\u4E4B\u540E\u9759\u9ED8\u53EF\u7528\uFF1B\n * Firefox \u6CA1\u6709\u8FD9\u79CD\u300C\u8BB0\u4F4F\u300D\uFF0C\u6BCF\u6B21\u8BFB\u90FD\u8981\u7528\u6237\u70B9\u4E00\u4E0B\u5B83\u81EA\u5DF1\u5F39\u7684\u300C\u7C98\u8D34(P)\u300D\u5C0F\u7A97\uFF08\u89C1 FIREFOX_TIP\uFF09\u3002\n * \u4F18\u5148\u4F7F\u7528\u53F3\u952E\u65F6\u9884\u8BFB\u7684\u7F13\u5B58\uFF08\u6388\u6743\u5DF2\u88AB\u70B9\u51FB\u8FC7\u4E00\u6B21\uFF0C\u65E0\u611F\uFF09\uFF0C\u5931\u8D25\u518D\u5B9E\u65F6\u8BFB\u53D6\u3002\n */\nasync function pasteText(root: HTMLElement): Promise<MenuActionResult> {\n const insertText = (text: string): MenuActionResult => {\n if (!document.activeElement || !root.contains(document.activeElement)) {\n root.focus({ preventScroll: true })\n }\n if (text === '') return { ok: true }\n return { ok: document.execCommand('insertText', false, text) }\n }\n // \u7F13\u5B58\u547D\u4E2D\uFF1A\u53F3\u952E\u65F6\u6388\u6743\u5DF2\u5B8C\u6210\uFF0C\u76F4\u63A5\u63D2\u5165\uFF08\u53EF\u80FD\u4E3A\u7A7A\u5B57\u7B26\u4E32\uFF0C\u6B64\u65F6\u8D70\u5B9E\u65F6\u8BFB\u53D6\uFF09\u3002\n if (pasteCache !== null && pasteCache !== '') {\n const text = pasteCache\n pasteCache = null\n return insertText(text)\n }\n if (typeof navigator === 'undefined' || navigator.clipboard === undefined\n || typeof navigator.clipboard.readText !== 'function') {\n return { ok: false, message: '\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u8BFB\u53D6\u526A\u8D34\u677F\uFF0C\u8BF7\u7528 Ctrl+V \u7C98\u8D34' }\n }\n // \u6743\u9650\u9884\u68C0\uFF1A\u5DF2\u88AB\u660E\u786E\u62D2\u7EDD\u65F6\u76F4\u63A5\u7ED9\u6062\u590D\u6307\u5F15\uFF08\u907F\u514D\u5047\u6B7B\u6216\u8BEF\u5BFC\uFF09\u3002\n const permissions = (navigator as {\n permissions?: { query?: (descriptor: { name: string }) => Promise<{ state: string }> }\n }).permissions\n if (permissions?.query) {\n try {\n const result = await permissions.query({ name: 'clipboard-read' })\n if (result.state === 'denied') {\n if (isFirefox()) return { ok: false, message: FIREFOX_TIP }\n return {\n ok: false,\n message: '\u6D4F\u89C8\u5668\u5DF2\u62D2\u7EDD\u526A\u8D34\u677F\u8BFB\u53D6\uFF1A\u70B9\u51FB\u5730\u5740\u680F\u5DE6\u4FA7\u56FE\u6807 \u2192 \u7AD9\u70B9\u8BBE\u7F6E \u2192 \u526A\u8D34\u677F \u2192 \u5141\u8BB8\uFF1B\u6216\u76F4\u63A5\u6309 Ctrl+V',\n }\n }\n } catch {\n // \u4E0D\u652F\u6301\u8BE5\u6743\u9650\u67E5\u8BE2\uFF1A\u7EE7\u7EED\u5C1D\u8BD5\u8BFB\u53D6\u3002\n }\n }\n let text: string\n try {\n // \u7B49\u5F85\u6388\u6743\u5F39\u7A97\u53EF\u80FD\u8F83\u4E45\uFF08\u8981\u7528\u6237\u70B9\u51FB\uFF09\uFF0C\u4E0D\u7528\u77ED\u8D85\u65F6\u8BEF\u62A5\u5931\u8D25\uFF1B15 \u79D2\u65E0\u54CD\u5E94\n // \u624D\u63D0\u793A\uFF0C\u907F\u514D\u83DC\u5355\u6C38\u4E45\u6302\u8D77\u3002\n text = await withTimeout(navigator.clipboard.readText(), 15000)\n } catch (error) {\n if (isFirefox()) {\n return { ok: false, message: FIREFOX_TIP }\n }\n if (isClipboardTimeout(error)) {\n return {\n ok: false,\n message: '\u7B49\u5F85\u6D4F\u89C8\u5668\u6388\u6743\u8D85\u65F6\uFF1A\u8BF7\u5728\u5F39\u51FA\u63D0\u793A\u4E2D\u9009\u62E9\u300C\u5141\u8BB8\u300D\uFF08\u82E5\u672A\u51FA\u73B0\uFF0C\u70B9\u5730\u5740\u680F\u5DE6\u4FA7\u56FE\u6807\u5F00\u542F\uFF09\uFF0C\u6216\u6309 Ctrl+V',\n }\n }\n return {\n ok: false,\n message: '\u672A\u83B7\u526A\u8D34\u677F\u8BFB\u53D6\u6388\u6743\uFF1A\u70B9\u51FB\u5730\u5740\u680F\u5DE6\u4FA7\u56FE\u6807 \u2192 \u7AD9\u70B9\u8BBE\u7F6E \u2192 \u526A\u8D34\u677F \u2192 \u5141\u8BB8\uFF1B\u6216\u76F4\u63A5\u6309 Ctrl+V \u7C98\u8D34',\n }\n }\n if (!document.activeElement || !root.contains(document.activeElement)) {\n root.focus({ preventScroll: true })\n }\n if (text === '') return { ok: true }\n return { ok: document.execCommand('insertText', false, text) }\n}\n", "/**\r\n * \u8BBE\u7F6E\u9762\u677F\u589E\u5F3A\uFF1A\u5BFC\u822A\u5217\u6EDA\u52A8\u6837\u5F0F + \u9762\u677F\u5C3A\u5BF8\u8C03\u6574\u624B\u67C4\u3002\r\n *\r\n * \u5B98\u65B9\u9762\u677F\u7ED3\u6784\uFF08ui-settings-general SettingsRoot\uFF09\uFF1A\r\n * .overlay\uFF08position:fixed; inset:0; **z-index:1000**\uFF09\r\n * \u251C\u2500\u2500 .mask\uFF08position:absolute; inset:0\uFF09\u2500\u2500 \u5168\u5C4F\u906E\u7F69\r\n * \u2514\u2500\u2500 [role=\"dialog\"][aria-modal=\"true\"] \u2500\u2500 .panel\uFF08position:relative; width:800; overflow:hidden\uFF09\r\n * \u251C\u2500\u2500 <nav> \u2500\u2500 \u6807\u9898 + navList\uFF08\u6761\u76EE\u8F83\u591A\u65F6\u6EA2\u51FA\uFF09\r\n * \u2514\u2500\u2500 <div> \u2500\u2500 header + .options\uFF08\u672C\u8EAB overflow-y:auto\uFF09\r\n *\r\n * \u26A0\uFE0F \u5C42\u53E0\u4E0A\u4E0B\u6587\u9677\u9631\uFF080.2.0 \u6574\u6BB5\u529F\u80FD\u56E0\u6B64\u5931\u6548\uFF0C\u52A1\u5FC5\u8BB0\u4F4F\uFF09\uFF1A\r\n * \u672C\u63D2\u4EF6\u80FD\u6302\u6D6E\u5C42\u7684\u4F4D\u7F6E\u53EA\u6709 `shell.overlay`\uFF0C\u800C\u5B83\u88AB\u5B98\u65B9\u5C01\u5728\r\n * `ui-layout` \u7684 `.overlayLayer { position:absolute; inset:0; z-index:20 }` \u91CC \u2014\u2014\r\n * `position` + `z-index` \u4F7F\u5B83**\u81EA\u6210\u5C42\u53E0\u4E0A\u4E0B\u6587**\uFF0C\u91CC\u9762\u7684\u5143\u7D20\u518D\u600E\u4E48\u628A z-index\r\n * \u5199\u6210 9998 \u4E5F**\u9003\u4E0D\u51FA\u53BB**\uFF0C\u6C38\u8FDC\u6392\u5728\u8BBE\u7F6E\u5F39\u7A97\uFF081000\uFF09\u4E0B\u9762\uFF0C\u88AB\u5168\u5C4F\u906E\u7F69\u5403\u6389\u9F20\u6807\u3002\r\n * \u6240\u4EE5\uFF1A**\u51E1\u662F\u7ED9\u8BBE\u7F6E\u5F39\u7A97\u505A\u6D6E\u5C42\uFF0C\u5FC5\u987B\u628A\u624B\u67C4\u6302\u8FDB\u9762\u677F\u5185\u90E8**\uFF08`createPortal` \u5230\r\n * panel\uFF09\uFF0C\u800C\u4E0D\u662F\u5728 shell.overlay \u91CC\u5BF9\u51C6\u5750\u6807\u753B\u3002\r\n */\r\nimport type { CSSProperties } from 'react'\r\n\r\n/** \u8BBE\u7F6E\u5BF9\u8BDD\u6846\u9009\u62E9\u5668\uFF08\u9762\u677F\u4E3A\u300C\u5E26 nav \u5B50\u5143\u7D20\u7684 aria-modal \u5BF9\u8BDD\u6846\u300D\uFF0C\u5728\u5E94\u7528\r\n * \u91CC\u552F\u4E00\uFF1A\u5176\u5B83\u5BF9\u8BDD\u6846\uFF08\u5BA1\u6279\u3001\u6A21\u578B\u7F16\u8F91\u5668\u7B49\uFF09\u4E0D\u4EE5 nav \u4E3A\u76F4\u63A5\u5B50\u5143\u7D20\uFF09\u3002 */\r\nexport const PANEL_SELECTOR = '[role=\"dialog\"][aria-modal=\"true\"]:has(> nav)'\r\n\r\n\r\n/** \u624B\u67C4\u5C42\u7C7B\u540D\uFF08\u7531\u4E0B\u65B9\u6CE8\u5165\u6837\u5F0F\u8868\u5B9A\u4E49\uFF09\u3002 */\r\nexport const RESIZE_LAYER_CLASS = 'dsh-ux-resize-layer'\r\n/** \u56DB\u8FB9\u63CF\u8FB9\uFF08\u7EAF\u89C6\u89C9\uFF0C\u4E0D\u5403\u6307\u9488\uFF09\u3002 */\r\nexport const RESIZE_OUTLINE_CLASS = 'dsh-ux-resize-outline'\r\n/** \u53EF\u62D6\u62FD\u7684\u8FB9\u3002 */\r\nexport const RESIZE_EDGE_CLASS = 'dsh-ux-resize-edge'\r\n/** \u53EF\u62D6\u62FD\u7684\u53F3\u4E0B\u89D2\u6293\u624B\u3002 */\r\nexport const RESIZE_GRIP_CLASS = 'dsh-ux-resize-grip'\r\n\r\n/** \u53EF\u62D6\u62FD\u7684\u4F4D\u7F6E\u3002 */\r\nexport type ResizeEdge = 'left' | 'right' | 'top' | 'bottom' | 'br'\r\n\r\n/** \u8FB9\u7684\u6293\u53D6\u5E26\u5BBD\uFF08\u53EF\u89C1\u63CF\u8FB9\u662F 1px\uFF0C\u8FD9 8px \u662F\"\u597D\u6293\"\u7684\u4F59\u91CF\uFF09\u3002 */\r\nconst BAND = 8\r\n/** \u8FB9\u6761\u4E24\u7AEF\u907F\u8BA9\u91CF\uFF0C\u8BA9\u5706\u89D2\u5904\u4E0D\u51FA\u73B0\u538B\u7EBF\u7684\u76F4\u89D2\u3002 */\r\nconst INSET = 14\r\n/** \u53F3\u4E0B\u89D2\u6293\u624B\u5C3A\u5BF8\u3002 */\r\nconst GRIP = 26\r\n\r\n/**\r\n * \u4E00\u6761\u624B\u67C4\u5728**\u9762\u677F\u5185\u90E8**\u7684\u7EDD\u5BF9\u5B9A\u4F4D\u76D2\u3002\r\n *\r\n * \u523B\u610F\u4E0D\u4F7F\u7528\u89C6\u53E3\u5750\u6807\uFF1A\u624B\u67C4\u662F\u9762\u677F\u7684\u5B50\u5143\u7D20\uFF08\u6302\u8FDB\u9762\u677F\u5185\u90E8\uFF09\uFF0C\u6240\u4EE5\u5B9A\u4F4D\u5168\u90E8\u76F8\u5BF9\r\n * \u9762\u677F\u672C\u8EAB \u2014\u2014 \u9762\u677F\u79FB\u52A8\u3001\u6EDA\u52A8\u3001\u6539\u5C3A\u5BF8\u90FD\u4F1A\u81EA\u52A8\u8DDF\u968F\uFF0C\u4E0D\u9700\u8981\u4EFB\u4F55\u91CD\u7B97\u6216\u8F6E\u8BE2\u3002\r\n * @param edge - \u8FB9\u6216\u53F3\u4E0B\u89D2\u3002\r\n * @returns \u8BE5\u624B\u67C4\u7684 CSS \u5B9A\u4F4D\u5C5E\u6027\u3002\r\n */\r\nexport function handleBox(edge: ResizeEdge): CSSProperties {\r\n switch (edge) {\r\n case 'left': return { left: 0, top: INSET, bottom: INSET, width: BAND, cursor: 'ew-resize' }\r\n case 'right': return { right: 0, top: INSET, bottom: INSET, width: BAND, cursor: 'ew-resize' }\r\n case 'top': return { top: 0, left: INSET, right: INSET, height: BAND, cursor: 'ns-resize' }\r\n case 'bottom': return { bottom: 0, left: INSET, right: INSET, height: BAND, cursor: 'ns-resize' }\r\n case 'br': return { right: 8, bottom: 8, width: GRIP, height: GRIP, cursor: 'nwse-resize' }\r\n }\r\n}\r\n\r\n/** \u56DB\u8FB9\u63CF\u8FB9\u5C42\uFF1A\u8D34\u7740\u9762\u677F\u5706\u89D2\u753B\u4E00\u5708 1px \u7EC6\u7EBF\uFF08\u7EAF\u89C6\u89C9\uFF0C`pointer-events: none`\uFF09\u3002 */\r\nexport const RESIZE_OUTLINE_STYLE: CSSProperties = {\r\n position: 'absolute',\r\n inset: 0,\r\n // \u8DDF\u968F\u9762\u677F\u81EA\u8EAB\u7684\u5706\u89D2\uFF08\u5B98\u65B9 .panel \u662F 32px\uFF09\u2014\u2014\u7528 inherit \u800C\u4E0D\u662F\u5199\u6B7B\u6570\u5B57\uFF0C\r\n // \u5B98\u65B9\u6539\u5706\u89D2\u65F6\u8FD9\u91CC\u81EA\u52A8\u8DDF\u4E0A\u3002\r\n borderRadius: 'inherit',\r\n border: '1px solid rgba(127, 127, 137, .28)',\r\n pointerEvents: 'none',\r\n}\r\n\r\n/**\r\n * \u5C3A\u5BF8\u624B\u67C4\u6837\u5F0F\u3002\r\n *\r\n * \u624B\u67C4\u5C42\u6302\u5728**\u8BBE\u7F6E\u9762\u677F\u5185\u90E8**\uFF08\u89C1\u6587\u4EF6\u5934\u7684\u5C42\u53E0\u4E0A\u4E0B\u6587\u8BF4\u660E\uFF09\uFF0C\u6240\u4EE5\u8FD9\u4E9B\u89C4\u5219\u91CC\u7684\r\n * \u5B9A\u4F4D\u4E00\u5F8B\u76F8\u5BF9\u9762\u677F\uFF1B`pointer-events` \u5728\u5C42\u4E0A\u5173\u6389\u3001\u53EA\u5728\u5177\u4F53\u624B\u67C4\u4E0A\u6253\u5F00\uFF0C\r\n * \u514D\u5F97\u6574\u5C42\u5403\u6389\u9762\u677F\u672C\u8EAB\u7684\u70B9\u51FB\u3002\r\n *\r\n * \u26A0\uFE0F 0.6.0 \u5220\u6389\u4E86\u8FD9\u91CC\u53E6\u4E00\u534A\u300C\u5BFC\u822A\u5217\u6EDA\u52A8\u300D\u6837\u5F0F\uFF08\u539F PANEL_CSS +\r\n * `html.dsh-ux-panel-scroll` \u95E8\u63A7\uFF09\uFF1ADSH 0.1.7 \u7684\u5B98\u65B9\u8BBE\u7F6E\u9875\u5DF2\u7ECF\u7ED9 `.navList`\r\n * \u81EA\u5E26 `overflow-y: auto`\uFF0C\u6211\u4EEC\u518D\u6CE8\u5165\u4E00\u5957\u5C31\u6210\u4E86\u91CD\u590D\u5B9E\u73B0\uFF0C\u6545\u6574\u9879\u79FB\u9664\u3002\r\n */\r\nconst RESIZE_CSS = `\r\n.${RESIZE_LAYER_CLASS} { position: absolute; inset: 0; pointer-events: none; }\r\n.${RESIZE_EDGE_CLASS}, .${RESIZE_GRIP_CLASS} {\r\n position: absolute;\r\n pointer-events: auto;\r\n background: transparent;\r\n border-radius: 6px;\r\n transition: background-color .12s ease, color .12s ease;\r\n touch-action: none;\r\n}\r\n.${RESIZE_EDGE_CLASS}:hover { background: rgba(127, 127, 137, .22); }\r\n.${RESIZE_EDGE_CLASS}[data-active=\"true\"] { background: rgba(127, 127, 137, .3); }\r\n.${RESIZE_GRIP_CLASS} {\r\n display: flex;\r\n align-items: flex-end;\r\n justify-content: flex-end;\r\n padding: 3px;\r\n color: rgba(127, 127, 137, .55);\r\n}\r\n.${RESIZE_GRIP_CLASS}:hover { color: rgba(127, 127, 137, .95); background: rgba(127, 127, 137, .16); }\r\n`\r\n\r\n/** \u6CE8\u5165\u5C3A\u5BF8\u624B\u67C4\u6837\u5F0F\u8868\uFF1B\u8FD4\u56DE\u5378\u8F7D\u5668\u3002 */\r\nexport function installPanelResizeStyle(): () => void {\r\n const tag = document.createElement('style')\r\n tag.dataset.plugin = 'dsh-composer-ux-panel'\r\n tag.textContent = RESIZE_CSS\r\n document.head.appendChild(tag)\r\n return () => {\r\n tag.remove()\r\n }\r\n}\r\n\r\n/** \u67E5\u8BE2\u5F53\u524D\u6253\u5F00\u7684\u8BBE\u7F6E\u5BF9\u8BDD\u6846\u3002 */\r\nexport function findSettingsPanel(): HTMLElement | null {\r\n return document.querySelector<HTMLElement>(PANEL_SELECTOR)\r\n}\r\n\r\n/** \u5C3A\u5BF8\u8303\u56F4\u94B3\u5236\uFF08\u4E0E host schema \u4E00\u81F4\uFF09\u3002 */\r\nexport function clampPanelWidth(width: number): number {\r\n return Math.max(560, Math.min(width, Math.max(800, window.innerWidth - 48)))\r\n}\r\n\r\nexport function clampPanelHeight(height: number): number {\r\n return Math.max(320, Math.min(height, Math.max(400, window.innerHeight - 48)))\r\n}\r\n\r\n/** \u6301\u4E45\u5316\u5C3A\u5BF8\uFF08\u5199\u5165\u8BBE\u7F6E\uFF1B\u5931\u8D25\u9759\u9ED8\u2014\u2014\u4E0B\u6B21\u6253\u5F00\u56DE\u9000\u9ED8\u8BA4\uFF09\u3002 */\r\nexport function persistPanelSize(\r\n width: number,\r\n height: number,\r\n setField: (field: string, value: boolean | number) => void,\r\n): void {\r\n setField('panelWidth', clampPanelWidth(width))\r\n setField('panelHeight', clampPanelHeight(height))\r\n}\r\n", "/**\n * \u8BBE\u7F6E\u9875\u6298\u53E0\u5361\u7247\u6837\u5F0F\u3002\n *\n * \u89C2\u611F\u5BF9\u9F50\u793E\u533A\u63D2\u4EF6 @linxin666/dsh-web-all \u7684 SettingsCard\uFF1A12px \u5706\u89D2\u3001\n * 1px \u63CF\u8FB9\uFF08hover \u53D8 --dsw-alias-label-dimmed\uFF09\u3001\u5C55\u5F00\u65F6\u6362\u5E95\u8272\u5E76\u663E\u793A\u5206\u9694\u7EBF\u3001\n * \u53F3\u4FA7 chevron \u65CB\u8F6C 180\u00B0\u3002\u7C7B\u540D\u7EDF\u4E00 dsh-ux- \u524D\u7F00\uFF0C\u907F\u514D\u4E0E\u5BBF\u4E3B CSS Modules \u51B2\u7A81\u3002\n */\n\nconst CARD_CSS = `\n.dsh-ux-card {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-3);\n border-radius: 12px;\n margin-bottom: 12px;\n transition: border-color .16s, background .16s;\n}\n.dsh-ux-card:hover { border-color: var(--dsw-alias-label-dimmed); }\n.dsh-ux-cardOpen {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n.dsh-ux-cardHeader {\n appearance: none;\n box-sizing: border-box;\n flex: 1;\n min-width: 0;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n background: 0 0;\n border: 0;\n border-radius: 12px;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n}\n.dsh-ux-cardHeader:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n/* \u6807\u9898\u884C = \u5DE6\u8FB9\"\u5C55\u5F00\"\u6309\u94AE\uFF08\u5360\u6EE1\u5269\u4F59\u5BBD\u5EA6\uFF09+ \u53F3\u8FB9\u4ECE\u5C5E\u63A7\u4EF6\u4E0E\u672C\u680F\u5F00\u5173\u3002\n \u4E0D\u80FD\u5728 <button> \u91CC\u585E\u6309\u94AE\uFF0C\u6240\u4EE5\u4E24\u8005\u662F\u5144\u5F1F\u8282\u70B9\u3002 */\n.dsh-ux-cardHeaderRow {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px;\n padding-right: 12px;\n}\n.dsh-ux-cardControls {\n align-items: center;\n display: inline-flex;\n flex: none;\n flex-wrap: wrap;\n gap: 8px;\n}\n/* \u6807\u9898\u884C\u91CC\u7684\"\u6587\u5B57 + \u5C0F\u5F00\u5173\"\uFF08\u5BFC\u822A\u6EDA\u52A8 / \u8FB9\u7F18\u7F29\u653E\uFF09\u3002 */\n.dsh-ux-miniToggle {\n align-items: center;\n color: var(--dsw-alias-label-secondary);\n display: inline-flex;\n flex: none;\n font-size: 11px;\n gap: 5px;\n white-space: nowrap;\n}\n/* \u672A\u542F\u7528\uFF1A\u6807\u9898\u884C\u91CC\u8BF4\u6E05\u695A\uFF0C\u6B63\u6587\u538B\u6697\uFF0C\u8BA9\u4EBA\u4E00\u773C\u770B\u51FA\"\u8FD9\u4E00\u680F\u73B0\u5728\u4E0D\u751F\u6548\"\u3002 */\n.dsh-ux-cardOff { border-style: dashed; }\n.dsh-ux-cardOff .dsh-ux-cardBody { opacity: .6; }\n.dsh-ux-cardHeaderStatic {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n}\n.dsh-ux-cardHeadText {\n display: flex;\n flex-direction: column;\n flex: 1;\n gap: 4px;\n min-width: 0;\n}\n.dsh-ux-cardName {\n color: var(--dsw-alias-label-primary);\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n margin: 0;\n}\n.dsh-ux-cardDescription {\n color: var(--dsw-alias-label-secondary);\n font-size: 13px;\n line-height: 1.5;\n margin: 0;\n}\n.dsh-ux-cardLink {\n align-items: center;\n color: var(--dsw-alias-label-secondary);\n display: inline-flex;\n flex: none;\n font-size: 12px;\n gap: 4px;\n text-decoration: none;\n white-space: nowrap;\n}\n.dsh-ux-cardLink:hover {\n color: var(--dsw-alias-brand-primary);\n text-decoration: underline;\n}\n/* \u62AC\u5934\u53F3\u7AEF\u90A3\u4E00\u7EC4\uFF1A\u91CD\u542F\u6309\u94AE + GitHub \u94FE\u63A5\uFF0C\u4E24\u679A\u90FD\u4E0D\u53C2\u4E0E\u6536\u7F29\u3002 */\n.dsh-ux-cardActions {\n align-items: center;\n display: inline-flex;\n flex: none;\n gap: 10px;\n}\n.dsh-ux-restartButton {\n appearance: none;\n background: 0 0;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n flex: none;\n font: inherit;\n font-size: 12px;\n line-height: 1;\n padding: 6px 12px;\n transition: border-color .16s, color .16s, background .16s;\n white-space: nowrap;\n}\n.dsh-ux-restartButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n border-color: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-brand-primary);\n}\n.dsh-ux-restartButton:disabled {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n opacity: .7;\n}\n/* \u786E\u8BA4\u6761\uFF1A\u62AC\u5934\u6B63\u4E0B\u65B9\u7684\u4E00\u6761\uFF0C\u4F4D\u7F6E\u5BF9\u9F50\u5E02\u573A\u7684\u300CN \u9879\u53D8\u66F4\u9700\u91CD\u542F\u300D\u6A2A\u5E45\u3002 */\n.dsh-ux-restartBanner {\n align-items: center;\n background: var(--dsw-alias-bg-layer-2);\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n display: flex;\n gap: 10px;\n margin: 0 16px 12px;\n padding: 10px 12px;\n}\n.dsh-ux-restartBannerFailed { border-color: var(--dsw-alias-state-error-primary); }\n.dsh-ux-restartBannerText {\n color: var(--dsw-alias-label-secondary);\n flex: 1;\n font-size: 12px;\n line-height: 1.5;\n min-width: 0;\n}\n.dsh-ux-restartBannerFailed .dsh-ux-restartBannerText { color: var(--dsw-alias-state-error-primary); }\n.dsh-ux-restartBannerActions {\n align-items: center;\n display: inline-flex;\n flex: none;\n gap: 8px;\n}\n.dsh-ux-restartGo {\n appearance: none;\n background: var(--dsw-alias-button-primary-fill);\n border: 0;\n border-radius: 999px;\n color: var(--dsw-alias-label-primary-foreground);\n cursor: pointer;\n font: inherit;\n font-size: 12px;\n line-height: 1;\n padding: 7px 14px;\n white-space: nowrap;\n}\n.dsh-ux-restartGo:hover { background: var(--dsw-alias-brand-primary); }\n.dsh-ux-restartCancel {\n appearance: none;\n background: 0 0;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 12px;\n line-height: 1;\n padding: 7px 14px;\n white-space: nowrap;\n}\n.dsh-ux-restartCancel:hover {\n border-color: var(--dsw-alias-label-dimmed);\n color: var(--dsw-alias-label-primary);\n}\n.dsh-ux-cardChevron {\n color: var(--dsw-alias-label-tertiary);\n flex: none;\n transition: transform .16s;\n}\n.dsh-ux-cardChevronOpen { transform: rotate(180deg); }\n.dsh-ux-cardBody {\n border-top: 1px solid var(--dsw-alias-border-l2);\n margin: 0 16px;\n padding-bottom: 8px;\n}\n`\n\n/** \u6CE8\u5165\u5361\u7247\u6837\u5F0F\u8868\uFF1B\u8FD4\u56DE\u5378\u8F7D\u5668\uFF08\u968F\u63D2\u4EF6 fiber \u56DE\u6536\uFF09\u3002 */\nexport function installSettingsCardStyle(): () => void {\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dsh-composer-ux-settings'\n tag.textContent = CARD_CSS\n document.head.appendChild(tag)\n return () => { tag.remove() }\n}\n", "/**\n * \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u5165\u53E3\u6309\u94AE\u7684\u6837\u5F0F\u8868\u3002\n *\n * \u4E3A\u4EC0\u4E48\u4E0D\u7528\u884C\u5185\u6837\u5F0F\uFF08React `style`\uFF09\uFF1A\u5B83\u8868\u8FBE\u4E0D\u4E86 `:hover` / `[aria-expanded]`\n * \u8FD9\u7C7B\u72B6\u6001\uFF0C\u800C\u300C\u548C\u65C1\u8FB9\u7684\u5B98\u65B9\u6309\u94AE\u957F\u5F97\u4E00\u6837\u300D\u6070\u6070\u8981\u9760 hover \u4E0E\u5E38\u6001\u900F\u660E\u5EA6\u3002\n *\n * \u53C2\u6570\u9010\u9879\u5BF9\u9F50\u793E\u533A\u63D2\u4EF6 `dsh-composer-expand` \u7684 `.cpex-btn`\uFF08\u540C\u4E00\u4E2A\u69FD\u4F4D\n * `conversation.input.right`\u3001\u540C\u4E00\u4E2A order \u90BB\u4F4D\uFF09\u2014\u2014 \u4E24\u4E2A\u6309\u94AE\u5E76\u6392\uFF0C\u5FC5\u987B\u540C\u9AD8\u3001\n * \u540C\u5706\u89D2\u3001\u540C\u5185\u8FB9\u8DDD\u3001\u540C\u8FB9\u6846\u3001\u540C\u5E38\u6001\u900F\u660E\u5EA6\uFF0C\u5426\u5219\u4E00\u773C\u5C31\u770B\u5F97\u51FA\u662F\u4E24\u5BB6\u4EBA\u505A\u7684\u3002\n * \u7279\u522B\u8BB0\u4E00\u7B14\uFF1A\u8FB9\u6846**\u4E0D\u7528**\u4E3B\u9898\u4EE4\u724C `--dsw-alias-border-l2`\uFF08\u5B83\u66F4\u4EAE\uFF0C\u4F1A\u5448\u73B0\u6210\n * \u7528\u6237\u622A\u56FE\u91CC\u90A3\u5708\u7A81\u5140\u7684\u767D\u7EBF\uFF09\uFF0C\u800C\u662F\u548C\u5BF9\u65B9\u4E00\u6837\u7528\u4E2D\u6027\u534A\u900F\u660E\u7070\uFF0C\u660E\u6697\u4E3B\u9898\u4E0B\u90FD\u534F\u8C03\u3002\n */\n\n/** \u5165\u53E3\u6309\u94AE\u7684\u57FA\u7840\u7C7B\u540D\u3002 */\nexport const QUICK_BUTTON_CLASS = 'composer-ux-quick-button'\n\n/** \u4E0E .cpex-btn \u9010\u9879\u5BF9\u9F50\u3002 */\nconst QUICK_BUTTON_CSS = `\n.${QUICK_BUTTON_CLASS} {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n height: 24px;\n border: 1px solid rgba(127, 127, 137, .35);\n background: transparent;\n color: inherit;\n border-radius: 999px;\n padding: 0 9px;\n font-size: 12px;\n line-height: 1;\n cursor: pointer;\n opacity: .75;\n white-space: nowrap;\n font-variant-numeric: tabular-nums;\n transition: opacity .12s ease, background-color .12s ease;\n}\n.${QUICK_BUTTON_CLASS}:hover { opacity: 1; background: rgba(127, 127, 137, .12); }\n.${QUICK_BUTTON_CLASS}[aria-expanded=\"true\"] {\n opacity: 1;\n background: rgba(127, 127, 137, .18);\n border-color: rgba(127, 127, 137, .6);\n}\n.${QUICK_BUTTON_CLASS} svg { flex: 0 0 auto; }\n`\n\n/** \u6CE8\u5165\u5165\u53E3\u6309\u94AE\u6837\u5F0F\u8868\uFF1B\u8FD4\u56DE\u5378\u8F7D\u5668\uFF08\u968F\u63D2\u4EF6 fiber \u56DE\u6536\uFF09\u3002 */\nexport function installQuickButtonStyle(): () => void {\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dsh-composer-ux-quick-button'\n tag.textContent = QUICK_BUTTON_CSS\n document.head.appendChild(tag)\n return () => { tag.remove() }\n}\n", "/**\n * \u53F3\u952E\u83DC\u5355\u5BBF\u4E3B\uFF1A\u6CE8\u518C\u8FDB shell.overlay\uFF08root \u7EA7 list \u69FD\uFF09\uFF0C\u83DC\u5355\u6253\u5F00\u65F6\u6E32\u67D3\n * \u4E00\u4E2A fixed \u5B9A\u4F4D\u7684\u6D6E\u5C42\uFF1B\u5173\u95ED\u65F6\u6E32\u67D3 null\u3002\n */\nimport React, { useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport {\n MENU_ITEMS, type ComposerUxSettings, type MenuState, type MenuField,\n} from '../settings-contract.ts'\nimport type { MenuActionId } from './interceptors.ts'\nimport { menu, menuItem, menuItemDim, menuNote, menuSeparator, menuShortcut } from './styles.ts'\n\n/** \u53F3\u952E\u83DC\u5355\u6CE8\u5165\u9762\u3002 */\nexport interface ContextMenuInjected {\n hooks: {\n /** \u83DC\u5355\u6253\u5F00\u72B6\u6001\uFF08null = \u5173\u95ED\uFF09\u3002 */\n menu: SnapshotStore<MenuState | null>\n /** \u5F53\u524D\u8BBE\u7F6E\uFF08\u51B3\u5B9A\u54EA\u4E9B\u83DC\u5355\u9879\u542F\u7528\uFF09\u3002 */\n live: SnapshotStore<ComposerUxSettings>\n }\n actions: {\n /** \u6267\u884C\u4E00\u4E2A\u83DC\u5355\u52A8\u4F5C\uFF1Bresolve \u6210\u529F\u4E0E\u5426\u3002 */\n run: (id: MenuActionId) => Promise<{ ok: boolean; message?: string }>\n /** \u5173\u95ED\u83DC\u5355\u3002 */\n close: () => void\n /** \u5728\u83DC\u5355\u4E0A\u6302\u4E00\u6BB5\u77ED\u6682\u63D0\u793A\uFF08\u4FDD\u7559\u83DC\u5355\u6253\u5F00\uFF09\u3002 */\n note: (message: string | undefined) => void\n }\n}\n\nexport type ContextMenuHostProps =\n PropsRuntime<'shell.overlay'>\n & InjectFace<ContextMenuInjected>\n\n/** \u83DC\u5355\u7EC4\uFF1A\u4E0E\u56FE\u7247\u4E00\u81F4\u7684\u4E09\u7EC4\u5206\u9694\u5E03\u5C40\u3002 */\nconst GROUPS: readonly { readonly label: string; readonly shortcut: string; readonly field: MenuField; readonly id: MenuActionId | 'disabledOnly' }[][] = [\n [\n { label: '\u64A4\u9500', shortcut: 'Ctrl+Z', field: 'menuUndo', id: 'undo' },\n { label: '\u91CD\u505A', shortcut: 'Ctrl+Y', field: 'menuRedo', id: 'redo' },\n ],\n [\n { label: '\u526A\u5207', shortcut: 'Ctrl+X', field: 'menuCut', id: 'cut' },\n { label: '\u590D\u5236', shortcut: 'Ctrl+C', field: 'menuCopy', id: 'copy' },\n { label: '\u7C98\u8D34', shortcut: 'Ctrl+V', field: 'menuPaste', id: 'paste' },\n { label: '\u5220\u9664', shortcut: '', field: 'menuDelete', id: 'delete' },\n ],\n [\n { label: '\u5168\u9009', shortcut: 'Ctrl+A', field: 'menuSelectAll', id: 'selectAll' },\n ],\n]\n\nconst ITEM_STYLES: Record<MenuActionId, 'always' | 'selection'> = {\n undo: 'always',\n redo: 'always',\n cut: 'selection',\n copy: 'selection',\n paste: 'always',\n delete: 'selection',\n selectAll: 'always',\n}\n\n/** \u4E0E\u89C6\u53E3\u8FB9\u754C\u4FDD\u6301 8px\u3002 */\nfunction clamp(value: number, size: number, viewport: number): number {\n return Math.max(8, Math.min(value, viewport - size - 8))\n}\n\n/** \u6E32\u67D3\u53F3\u952E\u83DC\u5355\uFF1B\u65E0\u83DC\u5355\u65F6\u8FD4\u56DE null\u3002 */\nexport function ContextMenuHost({ useMenu, useLive, actions }: ContextMenuHostProps) {\n const menuState = useMenu(item => item)\n const settings = useLive(item => item)\n const ref = useRef<HTMLDivElement | null>(null)\n const [position, setPosition] = useState<{ x: number; y: number } | null>(null)\n\n // \u6253\u5F00\u540E\u6309\u5B9E\u9645\u5C3A\u5BF8\u94B3\u5236\u5728\u89C6\u53E3\u5185\u3002\n useLayoutEffect(() => {\n if (menuState === null) {\n setPosition(null)\n return\n }\n const el = ref.current\n if (el === null) return\n const rect = el.getBoundingClientRect()\n setPosition({\n x: clamp(menuState.x, rect.width, window.innerWidth),\n y: clamp(menuState.y, rect.height, window.innerHeight),\n })\n }, [menuState?.x, menuState?.y])\n\n // \u5916\u90E8\u70B9\u51FB / Escape / \u6EDA\u52A8 / \u7A97\u53E3\u53D8\u5316\u65F6\u5173\u95ED\u3002\n useEffect(() => {\n if (menuState === null) return\n const onPointerDown = (event: PointerEvent): void => {\n if (ref.current !== null && event.target instanceof Node && ref.current.contains(event.target)) return\n actions.close()\n }\n const onEscape = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape') return\n event.preventDefault()\n event.stopPropagation()\n actions.close()\n }\n window.addEventListener('pointerdown', onPointerDown, true)\n window.addEventListener('keydown', onEscape, true)\n window.addEventListener('scroll', actions.close, true)\n window.addEventListener('resize', actions.close)\n return () => {\n window.removeEventListener('pointerdown', onPointerDown, true)\n window.removeEventListener('keydown', onEscape, true)\n window.removeEventListener('scroll', actions.close, true)\n window.removeEventListener('resize', actions.close)\n }\n }, [menuState === null, actions])\n\n // \u63D0\u793A 3 \u79D2\u540E\u6E05\u9664\u3002\n useEffect(() => {\n if (menuState?.note === undefined) return\n const timer = setTimeout(() => { actions.note(undefined) }, 3000)\n return () => { clearTimeout(timer) }\n }, [menuState?.note])\n\n if (menuState === null) return null\n\n const onItemClick = (id: MenuActionId): void => {\n // \u7C98\u8D34\u82E5\u7F13\u5B58\u672A\u547D\u4E2D\u4F1A\u5B9E\u65F6\u8BFB\u53D6\u526A\u8D34\u677F\uFF0C\u53EF\u80FD\u77ED\u6682\u7B49\u5F85\u6388\u6743\uFF0C\u7ED9\u51FA\u8FDB\u884C\u4E2D\u53CD\u9988\u3002\n if (id === 'paste') actions.note('\u6B63\u5728\u8BFB\u53D6\u526A\u8D34\u677F\u2026')\n // \u4E0D\u8BA9\u6309\u94AE\u62A2\u8D70\u7126\u70B9\uFF0C\u4FDD\u7559\u8F93\u5165\u6846\u9009\u533A\u3002\n void actions.run(id).then((result) => {\n if (result.ok) actions.close()\n else actions.note(result.message ?? '\u64CD\u4F5C\u5931\u8D25')\n })\n }\n\n const groups = GROUPS\n .map(group => group.filter(item => settings[item.field] === true))\n .filter(group => group.length > 0)\n\n return (\n <div\n ref={ref}\n role=\"menu\"\n style={{\n ...menu,\n left: position?.x ?? menuState.x,\n top: position?.y ?? menuState.y,\n }}\n >\n {groups.map((group, groupIndex) => (\n <React.Fragment key={group[0]!.field}>\n {groupIndex > 0 && <div role=\"separator\" style={menuSeparator} />}\n {group.map(item => {\n const needsSelection = ITEM_STYLES[item.id] === 'selection'\n const disabled = needsSelection && !menuState.hasSelection\n const style = disabled ? menuItemDim : menuItem\n return (\n <button\n key={item.field}\n type=\"button\"\n role=\"menuitem\"\n disabled={disabled}\n style={style}\n onMouseDown={(event) => { event.preventDefault() }}\n onClick={() => { onItemClick(item.id) }}\n >\n <span>{item.label}</span>\n {item.shortcut !== '' && <span style={menuShortcut}>{item.shortcut}</span>}\n </button>\n )\n })}\n </React.Fragment>\n ))}\n {menuState.note !== undefined && <div style={menuNote}>{menuState.note}</div>}\n </div>\n )\n}\n", "/**\n * \u5185\u8054\u6837\u5F0F\u5DE5\u5177\uFF1A\u53EA\u4F7F\u7528 DSH Web \u7684 --dsw-* \u8BBE\u8BA1\u4EE4\u724C\uFF0C\u6DF1\u6D45\u4E3B\u9898\u81EA\u9002\u5E94\u3002\n */\nimport type { CSSProperties } from 'react'\n\n/** \u9875\u9762\u5361\u7247\u3002 */\nexport const card: CSSProperties = {\n background: 'var(--dsw-alias-bg-layer-2)',\n border: '0.5px solid var(--dsw-alias-border-l2)',\n borderRadius: 12,\n padding: '14px 16px',\n marginBottom: 12,\n}\n\n/** \u5361\u7247\u6807\u9898\u3002 */\nexport const cardTitle: CSSProperties = {\n color: 'var(--dsw-alias-label-primary)',\n fontSize: 14,\n fontWeight: 600,\n margin: '0 0 4px',\n}\n\n/** \u8BF4\u660E\u6587\u5B57\u3002 */\nexport const description: CSSProperties = {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 12,\n lineHeight: 1.6,\n margin: '0 0 12px',\n}\n\n/** \u8BBE\u7F6E\u884C\u3002 */\nexport const row: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n minHeight: 40,\n padding: '7px 0',\n borderTop: '0.5px solid var(--dsw-alias-border-l2)',\n}\n\n/** \u884C\u5185\u6807\u7B7E\u533A\u3002 */\nexport const rowText: CSSProperties = {\n minWidth: 0,\n flex: 1,\n}\n\n/** \u884C\u6807\u9898\u3002 */\nexport const rowTitle: CSSProperties = {\n color: 'var(--dsw-alias-label-primary)',\n fontSize: 13,\n lineHeight: 1.4,\n}\n\n/** \u884C\u8BF4\u660E\u3002 */\nexport const rowDesc: CSSProperties = {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 11,\n lineHeight: 1.4,\n marginTop: 2,\n}\n\n/** \u952E\u4F4D\u663E\u793A\u80F6\u56CA\u3002 */\nexport const kbd: CSSProperties = {\n color: 'var(--dsw-alias-label-primary)',\n background: 'var(--dsw-alias-bg-layer-1)',\n border: '0.5px solid var(--dsw-alias-border-l2)',\n borderRadius: 6,\n padding: '3px 8px',\n fontSize: 12,\n fontFamily: 'var(--dsw-font-family)',\n whiteSpace: 'nowrap',\n}\n\n/** \u9884\u8BBE/\u52A8\u4F5C\u5C0F\u6309\u94AE\u3002 */\nexport const pill: CSSProperties = {\n background: 'var(--dsw-alias-interactive-bg-hover)',\n color: 'var(--dsw-alias-label-secondary)',\n border: '0.5px solid var(--dsw-alias-border-l2)',\n borderRadius: 999,\n padding: '4px 10px',\n fontSize: 12,\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n}\n\n/** \u9009\u4E2D\u6001\u6309\u94AE\u3002 */\nexport const pillActive: CSSProperties = {\n ...pill,\n color: 'var(--dsw-alias-button-primary-fill)',\n borderColor: 'var(--dsw-alias-button-primary-fill)',\n}\n\n/** \u5355\u884C\u6587\u672C\u8F93\u5165\uFF08\u8DDF\u968F\u4E3B\u9898\u4EE4\u724C\uFF09\u3002 */\nexport const textInput: CSSProperties = {\n background: 'var(--dsw-alias-bg-layer-1)',\n color: 'var(--dsw-alias-label-primary)',\n border: '0.5px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n padding: '6px 9px',\n fontSize: 12,\n lineHeight: 1.4,\n width: '100%',\n minWidth: 0,\n boxSizing: 'border-box',\n flex: 1,\n}\n\n/** \u63D0\u793A/\u9519\u8BEF\u6587\u5B57\u3002 */\nexport const hintError: CSSProperties = {\n color: 'var(--dsw-alias-state-error-primary)',\n fontSize: 12,\n lineHeight: 1.5,\n margin: '6px 0 0',\n}\n\n/** \u63D0\u793A\u6587\u5B57\uFF08\u4E2D\u6027\uFF09\u3002 */\nexport const hintInfo: CSSProperties = {\n color: 'var(--dsw-alias-label-secondary)',\n fontSize: 12,\n lineHeight: 1.5,\n margin: '6px 0 0',\n}\n\n/**\n * \u83DC\u5355\uFF08\u4E0E\u56FE\u7247\u4E00\u81F4\u7684\u6DF1\u8272\u5706\u89D2\u83DC\u5355\uFF09\uFF1B\u80CC\u666F\u53D6\u81EA\u5B98\u65B9\u83DC\u5355\u4EE4\u724C\u3002\n *\n * \u26A0\uFE0F **2026-09-25 \u4FEE\uFF080.1.7 \u517C\u5BB9\uFF09**\uFF1ADSH \u628A\u83DC\u5355\u9762\u6539\u6210\u4E86\u300C\u534A\u900F\u660E + \u6BDB\u73BB\u7483\u300D\u2014\u2014\n * \u5B98\u65B9\u6BCF\u4E00\u4E2A\u7ED8\u5236 `--dsw-specific-menu` \u7684\u6D6E\u5C42\u90FD**\u6210\u5BF9**\u8865\u4E00\u5C42\n * `backdrop-filter: var(--dsw-menu-backdrop-filter)`\uFF08\u5B9E\u6D4B `blur(40px) saturate(150%)`\uFF09\u3002\n * \u6211\u4EEC\u4EE5\u524D\u53EA\u6284\u4E86\u300C\u534A\u900F\u660E\u300D\u90A3\u4E00\u534A\u3001\u6F0F\u4E86\u78E8\u7802\uFF0C\u4E8E\u662F\u6D6E\u5C42\u6210\u4E86**\u4E00\u5757\u6CA1\u78E8\u7802\u7684\u73BB\u7483**\uFF1A\n * \u80CC\u540E\u6B63\u6587\u76F4\u63A5\u900F\u51FA\u6765\u3001\u5B57\u53E0\u5B57\u770B\u4E0D\u6E05\uFF08\u7528\u6237 2026-09-25 \u622A\u56FE\u62A5\u7684\u5C31\u662F\u8FD9\u4E2A\uFF09\u3002\n *\n * \u540C\u6279\u5BF9\u9F50\u5B98\u65B9\u7684\u53E6\u4E24\u6761\uFF1A\u2460 \u63CF\u8FB9\u8D70 elevation \u7684\u53D1\u4E1D\u7EBF\uFF08`border: 0` \u2014\u2014 \u5426\u5219\u5B9E\u7EBF\u8FB9\u6846\n * \u4F1A\u548C box-shadow \u91CC\u90A3 0.5px \u63CF\u8FB9\u53E0\u6210\u4E24\u6761\uFF09\uFF1B\u2461 \u5706\u89D2\u6539\u7528\u5B98\u65B9\u4EE4\u724C\u3002\n */\nexport const menu: CSSProperties = {\n position: 'fixed',\n // \u5B98\u65B9\u6D6E\u5C42\u7528 1100\uFF0C\u8FD9\u91CC**\u523B\u610F\u4FDD\u7559 9999**\uFF1A\u672C\u63D2\u4EF6\u7684\u6D6E\u5C42\u6302\u5728 `shell.overlay` \u8FD9\u4E2A\n // \u72EC\u7ACB\u5C42\u53E0\u4E0A\u4E0B\u6587\u91CC\uFF0C\u8981\u548C\u522B\u7684\u63D2\u4EF6\u62A2\u5C42\uFF0C\u964D\u4E0B\u53BB\u53EA\u4F1A\u88AB\u76D6\u4F4F\uFF08\u89C1 panel.ts \u6587\u4EF6\u5934\uFF09\u3002\n zIndex: 9999,\n minWidth: 200,\n background: 'var(--dsw-specific-menu)',\n backdropFilter: 'var(--dsw-menu-backdrop-filter)',\n border: 0,\n borderRadius: 'var(--dsw-radius-lg)',\n boxShadow: 'var(--dsw-elevation-prominent)',\n '--dsw-elevation-stroke-color': 'var(--dsw-alias-border-l1)',\n padding: 5,\n pointerEvents: 'auto',\n userSelect: 'none',\n} as CSSProperties\n\n/** \u83DC\u5355\u9879\u3002 */\nexport const menuItem: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 24,\n padding: '6px 10px',\n borderRadius: 6,\n fontSize: 13,\n color: 'var(--dsw-alias-label-primary)',\n cursor: 'pointer',\n background: 'transparent',\n border: 'none',\n width: '100%',\n textAlign: 'left',\n}\n\nexport const menuItemDim: CSSProperties = {\n ...menuItem,\n color: 'var(--dsw-alias-label-dimmed)',\n cursor: 'default',\n}\n\n/** \u83DC\u5355\u9879\u5FEB\u6377\u952E\u3002 */\nexport const menuShortcut: CSSProperties = {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 12,\n fontFamily: 'var(--dsw-font-family)',\n}\n\n/** \u83DC\u5355\u5206\u9694\u7EBF\u3002 */\nexport const menuSeparator: CSSProperties = {\n height: 0,\n borderTop: '0.5px solid var(--dsw-alias-border-l2)',\n margin: '4px 8px',\n}\n\n/** \u83DC\u5355\u5E95\u90E8\u63D0\u793A\u3002 */\nexport const menuNote: CSSProperties = {\n color: 'var(--dsw-alias-state-warn-label)',\n fontSize: 11,\n lineHeight: 1.4,\n padding: '4px 10px 2px',\n}\n\n// \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\uFF1A\u8F93\u5165\u5361\u7247\u91CC\u7684\u5165\u53E3\u6309\u94AE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// \u6309\u94AE\u6837\u5F0F**\u6545\u610F\u4E0D\u653E\u5728\u8FD9\u91CC**\uFF1A\u5B83\u9700\u8981 hover \u4E0E\u5C55\u5F00\u6001\uFF0C\u884C\u5185\u6837\u5F0F\u8868\u8FBE\u4E0D\u4E86\uFF0C\u800C\u4E14\n// \u8981\u4E0E\u65C1\u8FB9\u5B98\u65B9\u300C\u5C55\u5F00\u300D\u6309\u94AE\uFF08dsh-composer-expand \u7684 .cpex-btn\uFF09\u9010\u9879\u5BF9\u9F50\u3002\n// \u89C1 `quick-style.ts` \u7684\u6CE8\u5165\u6837\u5F0F\u8868\u3002\n\n// \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\uFF1A\u5C55\u5F00\u9762\u677F \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * \u9762\u677F\u5BB9\u5668\uFF08fixed \u5B9A\u4F4D\uFF0C\u951A\u70B9\u5728\u5165\u53E3\u6309\u94AE\u4E0A\u65B9\uFF09\u3002\n *\n * \u6750\u8D28\u4E0E\u63CF\u8FB9\u4E0E\u4E0A\u9762 `menu` \u5B8C\u5168\u540C\u4E00\u5957\uFF08\u534A\u900F\u660E\u586B\u5145 + \u5B98\u65B9\u4F34\u4FA3\u6A21\u7CCA + elevation \u53D1\u4E1D\u7EBF\uFF09\uFF0C\n * \u4E24\u5904\u5FC5\u987B\u4E00\u8D77\u6539 \u2014\u2014 \u53EA\u6539\u4E00\u5904\u5C31\u4F1A\u51FA\u73B0\u300C\u4E00\u4E2A\u6D6E\u5C42\u6E05\u695A\u3001\u53E6\u4E00\u4E2A\u8FD8\u5728\u900F\u300D\u3002\n * \u75C5\u56E0\u4E0E\u5B9E\u6D4B\u4F9D\u636E\u5199\u5728 `menu` \u7684\u6CE8\u91CA\u91CC\uFF0C\u4E0D\u91CD\u590D\u3002\n */\nexport const quickPanel: CSSProperties = {\n position: 'fixed',\n // \u540C `menu`\uFF1A\u523B\u610F\u4FDD\u7559 9999\uFF0C\u7406\u7531\u89C1\u90A3\u91CC\u3002\n zIndex: 9999,\n width: 420,\n maxWidth: 'calc(100vw - 24px)',\n maxHeight: 'min(60vh, 520px)',\n display: 'flex',\n flexDirection: 'column',\n background: 'var(--dsw-specific-menu)',\n backdropFilter: 'var(--dsw-menu-backdrop-filter)',\n border: 0,\n borderRadius: 'var(--dsw-radius-lg)',\n boxShadow: 'var(--dsw-elevation-prominent)',\n '--dsw-elevation-stroke-color': 'var(--dsw-alias-border-l1)',\n pointerEvents: 'auto',\n overflow: 'hidden',\n} as CSSProperties\n\n/** \u9762\u677F\u9876\u90E8\u533A\uFF08\u6807\u9898 + \u6863\u4F4D + \u4F18\u5316\u6309\u94AE\uFF09\u3002 */\nexport const quickPanelHead: CSSProperties = {\n padding: '10px 12px 8px',\n borderBottom: '0.5px solid var(--dsw-alias-border-l2)',\n display: 'flex',\n flexDirection: 'column',\n gap: 8,\n}\n\n/** \u9762\u677F\u6807\u9898\u884C\u3002 */\nexport const quickPanelTitleRow: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 8,\n}\n\n/** \u9762\u677F\u6807\u9898\u3002 */\nexport const quickPanelTitle: CSSProperties = {\n color: 'var(--dsw-alias-label-primary)',\n fontSize: 13,\n fontWeight: 600,\n}\n\n/** \u6863\u4F4D\u5206\u6BB5\u63A7\u4EF6\u3002 */\nexport const quickTierRow: CSSProperties = {\n display: 'inline-flex',\n gap: 2,\n padding: 2,\n borderRadius: 999,\n background: 'var(--dsw-alias-bg-layer-1)',\n border: '0.5px solid var(--dsw-alias-border-l2)',\n}\n\n/** \u5355\u4E2A\u6863\u4F4D\u6309\u94AE\u3002 */\nexport const quickTierButton: CSSProperties = {\n border: 'none',\n background: 'transparent',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 11,\n lineHeight: 1,\n padding: '4px 8px',\n borderRadius: 999,\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n}\n\n/** \u9009\u4E2D\u6863\u4F4D\u3002\n * \u524D\u666F\u5FC5\u987B\u7528\u914D\u5BF9\u4EE4\u724C `label-primary-foreground`\uFF1A`button-primary-fill` \u53D6\u81EA\n * `brand-primary`\uFF0C\u6D45\u8272\u4E3B\u9898\u4E0B\u662F\u58A8\u8272/\u6DF1\u8272\uFF0C**\u6DF1\u8272\u4E3B\u9898\u4E0B\u5B83\u662F\u767D**\u2014\u2014\u6B64\u65F6\u5199\u6B7B\n * `#fff` \u5C31\u662F\u767D\u5E95\u767D\u5B57\uFF080.2.0 \u771F\u8E29\u8FC7\uFF09\u3002\u5B98\u65B9 ui-primitives/Button \u7684\u6210\u5BF9\u5199\u6CD5\n * \u5C31\u662F fill + label-primary-foreground\u3002 */\nexport const quickTierButtonActive: CSSProperties = {\n ...quickTierButton,\n background: 'var(--dsw-alias-button-primary-fill)',\n color: 'var(--dsw-alias-label-primary-foreground)',\n}\n\n/** \u4E3B\u884C\u52A8\u6309\u94AE\uFF08\u4F18\u5316\u63D0\u793A\u8BCD\uFF09\u3002\u540C\u4E0A\uFF1Afill \u4E0E\u524D\u666F\u5FC5\u987B\u6210\u5BF9\u3002 */\nexport const quickPrimaryButton: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 6,\n width: '100%',\n padding: '7px 12px',\n borderRadius: 8,\n border: '0.5px solid var(--dsw-alias-button-primary-fill)',\n background: 'var(--dsw-alias-button-primary-fill)',\n color: 'var(--dsw-alias-label-primary-foreground)',\n fontSize: 12,\n cursor: 'pointer',\n}\n\n/** \u4E3B\u884C\u52A8\u6309\u94AE\uFF08\u4E0D\u53EF\u7528\uFF09\uFF1A\u4E0E\u5B98\u65B9 .primary:disabled \u4E00\u81F4\u7528 0.4\u3002 */\nexport const quickPrimaryButtonDisabled: CSSProperties = {\n ...quickPrimaryButton,\n opacity: 0.4,\n cursor: 'default',\n}\n\n/** \u6761\u76EE\u5217\u8868\u5BB9\u5668\uFF08\u53EF\u6EDA\u52A8\uFF09\u3002 */\nexport const quickList: CSSProperties = {\n overflowY: 'auto',\n padding: '6px 6px 8px',\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n}\n\n/** \u4E00\u6761\u5FEB\u6377\u6307\u4EE4\u3002\n * \u6CE8\u610F\uFF1A\u8FD9\u4E00\u884C\u91CC\u8FD8\u6709\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u52FE\u9009\u6846\uFF0C\u6240\u4EE5\u6309\u94AE\u5FC5\u987B\u53EF\u88AB\u538B\u7F29\n * \uFF08flex 1 1 auto + minWidth 0\uFF09\uFF0C\u5426\u5219\u957F\u9884\u89C8\u4F1A\u628A\u52FE\u9009\u6846\u6324\u51FA\u9762\u677F\n * \uFF08width:100% \u4F1A\u5403\u6EE1\u6574\u884C\uFF0C0.2.0 \u771F\u8E29\u8FC7\uFF09\u3002 */\nexport const quickItem: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '5px 8px',\n borderRadius: 7,\n cursor: 'pointer',\n background: 'transparent',\n border: 'none',\n flex: '1 1 auto',\n minWidth: 0,\n textAlign: 'left',\n}\n\n/** \u6761\u76EE\u540D\u79F0\u3002 */\nexport const quickItemLabel: CSSProperties = {\n color: 'var(--dsw-alias-label-primary)',\n fontSize: 12,\n flex: '0 0 auto',\n whiteSpace: 'nowrap',\n}\n\n/** \u6761\u76EE\u5185\u5BB9\u9884\u89C8\u3002 */\nexport const quickItemPreview: CSSProperties = {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 11,\n flex: '1 1 auto',\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n}\n\n/** \u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u52FE\u9009\u533A\u3002 */\nexport const quickAlwaysLabel: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n gap: 4,\n flex: '0 0 auto',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 11,\n whiteSpace: 'nowrap',\n cursor: 'pointer',\n}\n\n/** \u52FE\u9009\u6846\u3002 */\nexport const quickAlwaysBox: CSSProperties = {\n margin: 0,\n cursor: 'pointer',\n}\n\n/** \u9762\u677F\u5E95\u90E8\u63D0\u793A\u6761\u3002 */\nexport const quickPanelFoot: CSSProperties = {\n padding: '5px 12px 7px',\n borderTop: '0.5px solid var(--dsw-alias-border-l2)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 8,\n}\n\n/** \u9762\u677F\u91CC\u7684\u63D0\u793A\u6587\u5B57\u3002 */\nexport const quickNotice: CSSProperties = {\n color: 'var(--dsw-alias-state-warn-label)',\n fontSize: 11,\n lineHeight: 1.4,\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n}\n\n/** \u9762\u677F\u91CC\u7684\u6B21\u8981\u8BF4\u660E\u3002 */\nexport const quickFootHint: CSSProperties = {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 11,\n whiteSpace: 'nowrap',\n flex: '0 0 auto',\n}\n\n/** \u7A7A\u5217\u8868\u5360\u4F4D\u3002 */\nexport const quickEmpty: CSSProperties = {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 12,\n lineHeight: 1.6,\n padding: '14px 10px',\n textAlign: 'center',\n}\n\n// \u2500\u2500 \u5FEB\u6377\u6307\u4EE4\uFF1A\u5206\u7C7B\uFF080.3.0 \u8D77\u7684\u4E24\u7EA7\u7ED3\u6784\uFF09 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** \u5206\u7C7B\u5207\u6362\u884C\uFF08\u9762\u677F\u91CC\u5728\u6863\u4F4D\u884C\u4E0B\u65B9\uFF09\u3002 */\nexport const quickCategoryRow: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n flexWrap: 'wrap',\n}\n\n/** \u5355\u4E2A\u5206\u7C7B\u6807\u7B7E\u3002 */\nexport const quickCategoryTab: CSSProperties = {\n border: '0.5px solid var(--dsw-alias-border-l2)',\n background: 'transparent',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 11,\n lineHeight: 1,\n padding: '4px 8px',\n borderRadius: 999,\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n maxWidth: 160,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n}\n\n/** \u9009\u4E2D\u7684\u5206\u7C7B\u6807\u7B7E\u3002\n * \u53EA\u6539\u8FB9\u6846\u4E0E\u6587\u5B57\u8272\uFF0C**\u4E0D\u7528\u5B9E\u8272\u586B\u5145**\uFF1A\u8FD9\u6837\u4E0D\u9700\u8981\u586B/\u524D\u666F\u6210\u5BF9\u4EE4\u724C\uFF0C\n * \u4E5F\u5C31\u4E0D\u4F1A\u91CD\u6F14 0.2.0 \u90A3\u6B21\u300C\u6DF1\u8272\u4E3B\u9898\u767D\u5E95\u767D\u5B57\u300D\u3002 */\nexport const quickCategoryTabActive: CSSProperties = {\n ...quickCategoryTab,\n border: '0.5px solid var(--dsw-alias-brand-primary)',\n color: 'var(--dsw-alias-label-primary)',\n fontWeight: 600,\n}\n\n/** \u300C\uFF0B \u5206\u7C7B\u300D\u5C0F\u6309\u94AE\u3002 */\nexport const quickCategoryAdd: CSSProperties = {\n ...quickCategoryTab,\n color: 'var(--dsw-alias-label-tertiary)',\n padding: '4px 7px',\n cursor: 'pointer',\n}\n", "/**\n * \u8BBE\u7F6E\u9762\u677F\u5C3A\u5BF8\u624B\u67C4\uFF1A\u56DB\u8FB9\u53EF\u62D6 + \u53F3\u4E0B\u89D2\u6293\u624B\u3002\n *\n * **\u4E3A\u4EC0\u4E48\u7528 `createPortal` \u6302\u8FDB\u9762\u677F\u5185\u90E8\uFF0C\u800C\u4E0D\u662F\u5728 `shell.overlay` \u91CC\u5BF9\u51C6\u5750\u6807\u753B**\n * \uFF080.2.0 \u6574\u6BB5\u529F\u80FD\u5931\u6548\u7684\u539F\u56E0\uFF0C\u52A1\u5FC5\u522B\u6539\u56DE\u53BB\uFF09\uFF1A\n * `shell.overlay` \u88AB\u5B98\u65B9\u5C01\u5728 `ui-layout` \u7684\n * `.overlayLayer { position:absolute; inset:0; z-index:20 }` \u91CC\u3002`position` +\n * `z-index` \u8BA9\u5B83**\u81EA\u6210\u5C42\u53E0\u4E0A\u4E0B\u6587**\uFF0C\u91CC\u9762\u7684\u5143\u7D20\u65E0\u8BBA z-index \u5199\u591A\u5927\u90FD\u51FA\u4E0D\u53BB\uFF0C\n * \u6C38\u8FDC\u6392\u5728\u8BBE\u7F6E\u5F39\u7A97\uFF08`.overlay` z-index:1000\uFF09\u4E0B\u9762\uFF0C\u88AB\u5168\u5C4F\u906E\u7F69\n * \uFF08`.mask { position:absolute; inset:0 }`\uFF09\u5403\u6389\u9F20\u6807 \u21D2 \u624B\u67C4\u6839\u672C\u6293\u4E0D\u5230\u3002\n * \u6302\u8FDB\u9762\u677F\u5185\u90E8\u5C31\u5B8C\u5168\u4E0D\u9700\u8981\u6BD4\u5C42\u53E0\uFF1A\u5B83\u5728\u6700\u9AD8\u90A3\u4E00\u5C42\u7684**\u91CC\u9762**\u3002\n *\n * \u9644\u5E26\u597D\u5904\uFF1A\u5B9A\u4F4D\u7531\u300C\u89C6\u53E3\u5750\u6807 + \u8F6E\u8BE2\u91CD\u7B97\u300D\u53D8\u6210\u300C\u9762\u677F\u5185\u7684\u7EDD\u5BF9\u5B9A\u4F4D\u300D\uFF0C\u9762\u677F\u79FB\u52A8/\n * \u6EDA\u52A8/\u6539\u5C3A\u5BF8\u90FD\u81EA\u52A8\u8DDF\u968F\uFF0C\u4E0D\u518D\u9700\u8981 250ms \u7684\u77E9\u5F62\u91CD\u7B97\uFF08\u8F6E\u8BE2\u53EA\u7528\u6765\u53D1\u73B0\u9762\u677F\u51FA\u73B0\uFF09\u3002\n *\n * \u672C\u7EC4\u4EF6\u4ECD\u6CE8\u518C\u5728 `shell.overlay`\u2014\u2014\u5B83\u53EA\u662F**\u6E32\u67D3\u51FA\u53E3**\u5728\u90A3\u91CC\uFF08\u4E3A\u4E86\u62FF\u5230\n * `useLive` \u4E0E\u5199\u5165\u52A8\u4F5C\uFF09\uFF0C\u5B9E\u9645 DOM \u901A\u8FC7 portal \u843D\u5728\u9762\u677F\u5185\u3002\n */\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport { PANEL_HEIGHT_FIELD, PANEL_WIDTH_FIELD, activeSections, type ComposerUxSettings } from '../settings-contract.ts'\nimport {\n RESIZE_EDGE_CLASS, RESIZE_GRIP_CLASS, RESIZE_LAYER_CLASS, RESIZE_OUTLINE_CLASS,\n RESIZE_OUTLINE_STYLE, clampPanelHeight, clampPanelWidth, findSettingsPanel, handleBox,\n type ResizeEdge,\n} from './panel.ts'\n\nexport interface PanelResizeInjected {\n hooks: { live: SnapshotStore<ComposerUxSettings> }\n actions: {\n /** \u5199\u4E00\u4E2A\u5B57\u6BB5\uFF08boolean \u6216 number\uFF09\u3002 */\n setField: (field: string, value: boolean | number) => void\n }\n}\n\nexport type PanelResizeProps = PropsRuntime<'shell.overlay'> & InjectFace<PanelResizeInjected>\n\n/** \u62D6\u62FD\u8D77\u59CB\u72B6\u6001\uFF08move/up \u95ED\u5305\u5171\u4EAB\uFF09\u3002 */\ninterface DragStart {\n readonly edge: ResizeEdge\n readonly x: number\n readonly y: number\n readonly left: number\n readonly top: number\n readonly width: number\n readonly height: number\n}\n\n/** \u53EF\u62D6\u62FD\u7684\u56DB\u8FB9 + \u53F3\u4E0B\u89D2\u3002 */\nconst EDGES: readonly ResizeEdge[] = ['left', 'right', 'top', 'bottom', 'br']\n\n/** \u6E32\u67D3\u8BBE\u7F6E\u9762\u677F\u5C3A\u5BF8\u624B\u67C4\uFF1B\u65E0\u9762\u677F\u6216\u5F00\u5173\u5173\u95ED\u65F6\u4E0D\u6E32\u67D3\u3002 */\nexport function PanelResizeHandles({ useLive, actions }: PanelResizeProps) {\n const settings = useLive(value => ({\n // \u300C\u8BBE\u7F6E\u9762\u677F\u300D\u680F\uFF08\u6216\u603B\u5F00\u5173\uFF09\u5173\u7740\u65F6\u6574\u5757\u505C\u7528 \u2014\u2014 \u4E0E\u5BFC\u822A\u6EDA\u52A8\u90A3\u5904\u7528\u540C\u4E00\u4E2A\u5224\u636E\u3002\n sectionOn: activeSections(value).panel,\n panelResize: value.panelResize,\n panelWidth: value.panelWidth,\n panelHeight: value.panelHeight,\n }))\n const enabled = settings.sectionOn === true && settings.panelResize === true\n const [panel, setPanel] = useState<HTMLElement | null>(null)\n const [active, setActive] = useState<ResizeEdge | null>(null)\n const dragRef = useRef<DragStart | null>(null)\n\n // \u53D1\u73B0/\u5931\u53BB\u8BBE\u7F6E\u5BF9\u8BDD\u6846\uFF08\u5B98\u65B9 shell \u5143\u7D20\u6302\u8F7D React \u611F\u77E5\u4E0D\u5230\uFF0C\u6545\u8F6E\u8BE2\uFF1B\n // \u53EA\u5728\u300C\u6709\u6CA1\u6709\u9762\u677F\u300D\u771F\u7684\u53D8\u5316\u65F6\u624D setState\uFF0C\u907F\u514D\u65E0\u8C13\u91CD\u6E32\u67D3\uFF09\u3002\n useEffect(() => {\n if (!enabled) {\n setPanel(null)\n return\n }\n let current: HTMLElement | null = null\n const probe = (): void => {\n const found = findSettingsPanel()\n if (found === current) return\n current = found\n setPanel(found)\n }\n probe()\n const timer = setInterval(probe, 250)\n return () => { clearInterval(timer) }\n }, [enabled])\n\n // \u5957\u7528\u6301\u4E45\u5316\u5C3A\u5BF8\uFF1A\u9762\u677F\u51FA\u73B0\u65F6\u3001\u4EE5\u53CA**\u5C3A\u5BF8\u8BBE\u7F6E\u53D8\u5316\u65F6**\uFF08\u8FD9\u6837\u8BBE\u7F6E\u9875\u91CC\u70B9\n // \u300C\u5C3A\u5BF8\u9884\u8BBE\u300D\u5F53\u573A\u5C31\u53D8\uFF0C\u4E0D\u5FC5\u5173\u6389\u8BBE\u7F6E\u518D\u91CD\u5F00\uFF09\u3002\u8BBE\u7F6E\u88AB\u6E05\u7A7A\u65F6\u79FB\u9664\u5185\u8054\u6837\u5F0F\uFF0C\n // \u56DE\u843D\u5230\u5B98\u65B9\u9ED8\u8BA4 800\u3002\n useEffect(() => {\n if (panel === null) return\n const width = settings.panelWidth\n const height = settings.panelHeight\n if (width === undefined) panel.style.removeProperty('width')\n else panel.style.width = `${clampPanelWidth(width)}px`\n if (height === undefined) panel.style.removeProperty('height')\n else panel.style.height = `${clampPanelHeight(height)}px`\n }, [panel, settings.panelWidth, settings.panelHeight])\n\n if (!enabled || panel === null) return null\n\n const onPointerDown = (edge: ResizeEdge, event: React.PointerEvent): void => {\n event.preventDefault()\n event.stopPropagation()\n const el = panel\n const rect = el.getBoundingClientRect()\n // \u628A\u300C\u5C45\u4E2D flex \u5B50\u9879\u300D\u8F6C\u6210\u56FA\u5B9A\u5B9A\u4F4D\u540E\u518D\u62D6\uFF1A\u5C45\u4E2D\u7684\u5143\u7D20\u4E00\u6539\u5BBD\u5EA6\u4F1A**\u4E24\u4FA7\u540C\u65F6\n // \u4F38\u7F29**\uFF0C\u62D6\u53F3\u8FB9\u5DE6\u8FB9\u4E5F\u8DDF\u7740\u52A8\uFF0C\u624B\u611F\u662F\u9519\u7684\u3002\u8F6C\u6210 fixed \u4E4B\u540E\u62D6\u54EA\u8FB9\u5C31\u53EA\u52A8\u54EA\u8FB9\u3002\n el.style.position = 'fixed'\n el.style.margin = '0'\n el.style.left = `${rect.left}px`\n el.style.top = `${rect.top}px`\n el.style.width = `${rect.width}px`\n el.style.height = `${rect.height}px`\n\n const start: DragStart = {\n edge, x: event.clientX, y: event.clientY,\n left: rect.left, top: rect.top, width: rect.width, height: rect.height,\n }\n dragRef.current = start\n setActive(edge)\n document.body.style.cursor = String(handleBox(edge).cursor ?? 'default')\n document.body.style.userSelect = 'none'\n\n const onMove = (move: PointerEvent): void => {\n if (dragRef.current !== start) return\n move.preventDefault()\n const dx = move.clientX - start.x\n const dy = move.clientY - start.y\n let { left, top, width, height } = start\n if (edge === 'right' || edge === 'br') width = clampPanelWidth(start.width + dx)\n if (edge === 'bottom' || edge === 'br') height = clampPanelHeight(start.height + dy)\n if (edge === 'left') {\n width = clampPanelWidth(start.width - dx)\n left = start.left + (start.width - width)\n }\n if (edge === 'top') {\n height = clampPanelHeight(start.height - dy)\n top = start.top + (start.height - height)\n }\n el.style.left = `${Math.round(left)}px`\n el.style.top = `${Math.round(top)}px`\n el.style.width = `${Math.round(width)}px`\n el.style.height = `${Math.round(height)}px`\n }\n const onUp = (): void => {\n window.removeEventListener('pointermove', onMove)\n window.removeEventListener('pointerup', onUp)\n dragRef.current = null\n setActive(null)\n const box = el.getBoundingClientRect()\n actions.setField(PANEL_WIDTH_FIELD, Math.round(clampPanelWidth(box.width)))\n actions.setField(PANEL_HEIGHT_FIELD, Math.round(clampPanelHeight(box.height)))\n document.body.style.removeProperty('cursor')\n document.body.style.removeProperty('user-select')\n }\n window.addEventListener('pointermove', onMove)\n window.addEventListener('pointerup', onUp)\n }\n\n return createPortal(\n <div className={RESIZE_LAYER_CLASS} data-composer-ux-resize>\n <div className={RESIZE_OUTLINE_CLASS} style={RESIZE_OUTLINE_STYLE} />\n {EDGES.map(edge => (\n <div\n key={edge}\n className={edge === 'br' ? RESIZE_GRIP_CLASS : RESIZE_EDGE_CLASS}\n data-active={active === edge ? 'true' : undefined}\n title={edge === 'br' ? '\u62D6\u52A8\u6539\u9762\u677F\u5927\u5C0F' : undefined}\n style={handleBox(edge)}\n onPointerDown={event => { onPointerDown(edge, event) }}\n >\n {edge === 'br' && (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden>\n <path\n d=\"M11 1 1 11M11 6 6 11\"\n stroke=\"currentColor\"\n strokeWidth=\"1.3\"\n strokeLinecap=\"round\"\n />\n </svg>\n )}\n </div>\n ))}\n </div>,\n panel,\n )\n}\n", "/**\n * \u8BBE\u7F6E\u9875\u300C\u8F93\u5165\u4F53\u9A8C\u300D\u3002\n *\n * \u7248\u5F0F\u5BF9\u9F50\u793E\u533A\u63D2\u4EF6 @linxin666/dsh-web-all \u7684\u300CWeb \u63D2\u4EF6\u300D\u9875\uFF1A\n * \u9876\u90E8\u5E38\u663E\uFF1A\u4E2D\u6587\u540D + \u4E00\u884C\u63CF\u8FF0\uFF08\u5185\u5D4C\u82F1\u6587\u5305\u540D dsh-composer-ux\uFF09+ \u603B\u5F00\u5173\uFF1B\n * \u5176\u4E0B\u4E09\u4E2A\u680F\u76EE\uFF08\u952E\u4F4D / \u53F3\u952E\u83DC\u5355 / \u8BBE\u7F6E\u9762\u677F\uFF09\u4E3A\u6298\u53E0\u5361\uFF0C\u6807\u9898\u884C\u53EA\u653E\u4E00\u53E5\n * \u6982\u89C8\uFF0C\u957F\u8BF4\u660E\u4E0E\u5177\u4F53\u63A7\u4EF6\u90FD\u5728\u5C55\u5F00\u540E\u7684\u5185\u5BB9\u533A\u91CC\uFF1B\u9ED8\u8BA4\u5168\u90E8\u6298\u53E0\u3001\u4E0D\u8BB0\u5FC6\u3002\n */\nimport React, { useEffect, useRef, useState, type CSSProperties } from 'react'\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SettingsSectionOwnerProps } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport {\n DEFAULT_CATEGORY_NAME, DEFAULT_HEADER_NAME, ENABLED_FIELD, HEADER_ENABLED_FIELD,\n HEADER_NAME_FIELD, HEADER_NAME_MAX, HEADER_ROUTES_FIELD, HEADER_VALUE_FIELD, HEADER_VALUE_MAX,\n MENU_ITEMS, MENU_MODES, MENU_MODE_FIELD, NEWLINE_PRESETS, OPTIMIZER_TIERS, OPTIMIZER_TIER_FIELD,\n PANEL_HEIGHT_FIELD,\n PANEL_RESIZE_FIELD, PANEL_WIDTH_FIELD, QUICK_CATEGORY_MAX,\n QUICK_CATEGORY_NAME_MAX, QUICK_LABEL_MAX,\n QUICK_PROMPT_MAX, QUICK_TEXT_MAX, REPO_URL, RESTART_API_PATH, SEND_PRESETS,\n KEYS_ENABLED_FIELD, MENU_ENABLED_FIELD, PANEL_ENABLED_FIELD, QUICK_ENABLED_FIELD,\n TERMINAL_ENABLED_FIELD, activeSections,\n insertModeOf, newQuickPromptId, newSessionId, optimizerPromptFieldOf,\n type ComposerUxSettings, type MenuField, type OptimizerTier, type QuickPrompt,\n type QuickPromptBook, type SettingsField,\n} from '../settings-contract.ts'\nimport {\n bookCounts, withCategoryAdded, withCategoryMoved, withCategoryRemoved, withCategoryRenamed,\n withInsertMode, withPromptAdded, withPromptMoved, withPromptMovedToCategory, withPromptPatched,\n withPromptRemoved,\n} from './prompt-book.ts'\nimport {\n TERMINAL_API_PATH, TERMINAL_BASH_PATH_FIELD, TERMINAL_MODES, TERMINAL_MODE_FIELD,\n sanitizeTerminalCandidates,\n} from '../terminal/contracts.ts'\nimport { AddPromptRow } from './AddPromptRow.tsx'\nimport { OptimizerPromptEditor } from './OptimizerPromptEditor.tsx'\nimport { InsertModeControl } from './InsertModeControl.tsx'\nimport { PillChoice } from './PillChoice.tsx'\nimport {\n evaluateRecordedKey, displayChord, type ChordEvent,\n} from './chords.ts'\nimport {\n description, hintError, hintInfo, kbd, pill, pillActive, row, rowDesc, rowText, rowTitle,\n textInput,\n} from './styles.ts'\n\n/** \u8BBE\u7F6E\u9875\u6CE8\u5165\u9762\u3002 */\nexport interface SettingsSectionInjected {\n hooks: {\n /** \u5F53\u524D\u89E3\u6790\u540E\u7684\u8BBE\u7F6E\u5FEB\u7167\u3002 */\n live: SnapshotStore<ComposerUxSettings>\n /** \u5FEB\u6377\u6307\u4EE4\u672C\uFF08\u771F\u76F8\u5728\u78C1\u76D8\u90A3\u4EFD quick-prompts.json\uFF1B\u8FD9\u91CC\u53EA\u662F\u5B83\u7684\u5BA2\u6237\u7AEF\u5FEB\u7167\uFF09\u3002 */\n book: SnapshotStore<QuickPromptBook>\n /** '' = \u6B63\u5E38\uFF1B'saving' = \u6B63\u5728\u5199\uFF1B\u5176\u4F59 = \u4E0A\u4E00\u6B21\u7684\u9519\u8BEF\u6587\u6848\u3002 */\n bookStatus: SnapshotStore<string>\n /**\n * \u8BBE\u7F6E\u5199\u5165\u7684\u8BF4\u660E\u884C\uFF1A'' = \u6B63\u5E38\uFF1B\u5176\u4F59\u662F\"\u88AB\u62D2 / \u5199\u4E86\u4F46\u6CA1\u751F\u6548\"\u7684\u539F\u56E0\u3002\n * \u5B58\u5728\u7684\u610F\u4E49\u5C31\u662F\u8BA9\u300C\u70B9\u4E86\u6CA1\u53CD\u5E94\u300D\u8FD9\u79CD\u6545\u969C\u81F3\u5C11\u8BF4\u5F97\u51FA\u8BDD\uFF08\u89C1 client.tsx \u7684 setField\uFF09\u3002\n */\n writeNotice: SnapshotStore<string>\n }\n actions: {\n /** \u5199\u4E00\u4E2A\u5B57\u6BB5\uFF08\u952E\u4F4D\u4E3A\u89C4\u8303\u4E32\uFF0C\u5F00\u5173\u4E3A\u5E03\u5C14\uFF0C\u5C3A\u5BF8\u4E3A\u6570\u5B57\uFF09\u3002 */\n setField: (field: SettingsField, value: unknown) => void\n /** \u6E05\u7A7A\u4E00\u4E2A\u5B57\u6BB5\uFF08\u56DE\u843D\u5230 schema \u9ED8\u8BA4\uFF09\u3002 */\n clearField: (field: SettingsField) => void\n /** \u5168\u90E8\u6062\u590D\u9ED8\u8BA4\uFF08\u6E05\u7A7A\u7528\u6237\u8986\u76D6\uFF0C\u56DE\u843D\u5230 schema \u9ED8\u8BA4\uFF1B\u5FEB\u6377\u6307\u4EE4\u53E6\u89C1 resetBook\uFF09\u3002 */\n resetAll: () => void\n /** \u6574\u672C\u5199\u56DE\uFF08\u7F16\u8F91\u5668\u91CC\u7684\u300C\u4FDD\u5B58\u4FEE\u6539\u300D\uFF09\u3002 */\n saveBook: (next: QuickPromptBook) => void\n /** \u4ECE\u78C1\u76D8\u91CD\u65B0\u8BFB\u53D6\uFF08\u522B\u7684\u7A97\u53E3\u6539\u8FC7\u65F6\u7684\u515C\u5E95\uFF09\u3002 */\n reloadBook: () => void\n /** \u6062\u590D\u5185\u7F6E 9 \u6761\uFF08\u5199\u56DE\u9ED8\u8BA4\u672C\uFF09\u3002 */\n resetBook: () => void\n /** \u5173\u6389\u9876\u90E8\u90A3\u6761\u5199\u5165\u5931\u8D25/\u672A\u751F\u6548\u7684\u8BF4\u660E\u3002 */\n dismissNotice: () => void\n }\n}\n\nexport type SettingsSectionProps =\n PropsRuntime<'settings.section'>\n & SettingsSectionOwnerProps\n & InjectFace<SettingsSectionInjected>\n\n/** \u5C55\u5F00\u533A\u5185\u7684\u5BFC\u8BED\u3002 */\nconst bodyLead: CSSProperties = { ...description, margin: '12px 0' }\n\n/** \u6298\u53E0\u7BAD\u5934\uFF08\u5185\u8054 SVG\uFF0C\u5C55\u5F00\u65F6\u9760\u7236\u7EA7 class \u65CB\u8F6C 180\u00B0\uFF09\u3002 */\nfunction Chevron() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M3.25 5.5L7 9.25L10.75 5.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.4\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )\n}\n\n/**\n * \u53EF\u6298\u53E0\u680F\u76EE\uFF1A\u6807\u9898\u884C\u5DE6\u4FA7\u662F\u5C55\u5F00\u6309\u94AE\uFF08\u6574\u5757\u53EF\u70B9\uFF09\uFF0C\u53F3\u4FA7\u662F**\u8FD9\u4E00\u680F\u7684\u5F00\u5173**\u4E0E\u4ECE\u5C5E\u63A7\u4EF6\uFF1B\n * \u9ED8\u8BA4\u6298\u53E0\u4E14\u4E0D\u8BB0\u5FC6\u5C55\u5F00\u72B6\u6001\uFF08\u6BCF\u6B21\u6253\u5F00\u8BBE\u7F6E\u9875\u90FD\u56DE\u5230\u6298\u53E0\uFF09\u3002\n */\nfunction FoldCard(props: {\n name: string\n summary: string\n /** \u8FD9\u4E00\u680F\u7684\u5F00\u5173\uFF08\u516D\u680F\u90FD\u6709\uFF09\u3002\u5173\u6389\u65F6\u6982\u89C8\u524D\u4F1A\u52A0\u300C\u672A\u542F\u7528 \u00B7 \u300D\uFF0C\u5361\u7247\u63CF\u8FB9\u53D8\u865A\u7EBF\u3002 */\n toggle?: { readonly checked: boolean; readonly onChange: (next: boolean) => void }\n /** \u6807\u9898\u884C\u53F3\u4FA7\u3001\u5F00\u5173\u5DE6\u8FB9\u7684\u4ECE\u5C5E\u63A7\u4EF6\uFF08\u4E09\u6863 / \u5C0F\u5F00\u5173\uFF09\u3002 */\n controls?: React.ReactNode\n children: React.ReactNode\n}) {\n const [open, setOpen] = useState(false)\n const off = props.toggle !== undefined && props.toggle.checked === false\n return (\n <section className={[\n 'dsh-ux-card',\n open ? 'dsh-ux-cardOpen' : '',\n off ? 'dsh-ux-cardOff' : '',\n ].filter(part => part !== '').join(' ')}>\n {/*\n \u6807\u9898\u884C\u5206\u6210\u4E24\u5757\uFF1A\u5DE6\u8FB9\u6574\u5757\u662F\"\u5C55\u5F00\"\u6309\u94AE\uFF08\u6574\u884C\u53EF\u70B9\uFF0C\u952E\u76D8\u53EF\u8FBE\uFF09\uFF0C\u53F3\u8FB9\u662F\u4ECE\u5C5E\u63A7\u4EF6 + \u672C\u680F\u5F00\u5173\u3002\n \u4E0D\u80FD\u5728 <button> \u91CC\u585E\u6309\u94AE\uFF08HTML \u4E0D\u5141\u8BB8\u3001\u70B9\u51FB\u4E5F\u4F1A\u5192\u6CE1\u6210\"\u5C55\u5F00\"\uFF09\uFF0C\u6240\u4EE5\u62C6\u6210\u5144\u5F1F\u8282\u70B9\u3002\n */}\n <div className=\"dsh-ux-cardHeaderRow\">\n <button\n type=\"button\"\n className=\"dsh-ux-cardHeader\"\n aria-expanded={open}\n onClick={() => { setOpen(current => !current) }}\n >\n <span className=\"dsh-ux-cardHeadText\">\n <span className=\"dsh-ux-cardName\">{props.name}</span>\n <span className=\"dsh-ux-cardDescription\">\n {off ? `\u672A\u542F\u7528 \u00B7 ${props.summary}` : props.summary}\n </span>\n </span>\n <span className={open ? 'dsh-ux-cardChevron dsh-ux-cardChevronOpen' : 'dsh-ux-cardChevron'}>\n <Chevron />\n </span>\n </button>\n <span className=\"dsh-ux-cardControls\">\n {props.controls}\n {props.toggle !== undefined && (\n <Switch\n small\n label={`${props.name}\uFF1A\u542F\u7528\u8FD9\u4E00\u680F`}\n checked={props.toggle.checked}\n onChange={props.toggle.onChange}\n />\n )}\n </span>\n </div>\n {open && <div className=\"dsh-ux-cardBody\">{props.children}</div>}\n </section>\n )\n}\n\n/** \u952E\u4F4D\u884C\uFF1A\u5F53\u524D\u503C + \u9884\u8BBE + \u5F55\u5236 + \u6E05\u9664\u3002 */\nfunction KeyRow(props: {\n title: string\n desc: string\n value: string\n presets: readonly string[]\n conflict: (chord: string) => boolean\n onChange: (chord: string) => void\n /** \u5C55\u5F00\u533A\u91CC\u7684\u7B2C\u4E00\u884C\uFF1A\u4E0D\u753B\u4E0A\u8FB9\u6846\uFF08\u5185\u5BB9\u533A\u81EA\u5DF1\u6709\u4E00\u6761\u5206\u9694\u7EBF\uFF09\u3002 */\n first?: boolean\n}) {\n const { title, desc, value, presets, conflict, onChange, first } = props\n const [recording, setRecording] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n useEffect(() => {\n if (!recording) return\n const onKeyDown = (event: KeyboardEvent): void => {\n // \u5F55\u5236\u671F\u95F4\u541E\u6389\u6240\u6709\u6309\u952E\uFF0C\u907F\u514D\u6C61\u67D3\u8F93\u5165\u6846\u6216\u9875\u9762\u3002\n event.preventDefault()\n event.stopPropagation()\n if (event.isComposing) return\n const result = evaluateRecordedKey(event as unknown as ChordEvent)\n if (result.kind === 'ignore') return\n if (result.kind === 'cancel') {\n setRecording(false)\n setError(null)\n return\n }\n if (result.kind === 'clear') {\n setRecording(false)\n setError(null)\n onChange('')\n return\n }\n if (result.kind === 'reject') {\n setError(result.message)\n return\n }\n if (conflict(result.chord)) {\n setRecording(false)\n setError('\u53D1\u9001\u4E0E\u6362\u884C\u4E0D\u80FD\u8BBE\u4E3A\u76F8\u540C\u6309\u952E\uFF08\u53EF\u5148\u7ED9\u53E6\u4E00\u4FA7\u6362\u952E\uFF0C\u518D\u7ED1\u5B9A\u8BE5\u952E\uFF09\u3002')\n return\n }\n setRecording(false)\n setError(null)\n onChange(result.chord)\n }\n window.addEventListener('keydown', onKeyDown, true)\n return () => { window.removeEventListener('keydown', onKeyDown, true) }\n }, [recording, conflict, onChange])\n\n const base = first === true ? { ...row, borderTop: 'none' } : row\n\n return (\n <div style={{ ...base, flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>{title}</div>\n <div style={rowDesc}>{desc}</div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>\n <span style={kbd}>{displayChord(value)}</span>\n {!recording && presets.map(preset => (\n <button\n key={preset}\n type=\"button\"\n style={value === preset ? pillActive : pill}\n onClick={() => { setError(null); onChange(preset) }}\n >\n {displayChord(preset)}\n </button>\n ))}\n {!recording && value !== '' && (\n <button type=\"button\" style={pill} onClick={() => { setError(null); onChange('') }}>\n \u6E05\u9664\n </button>\n )}\n <button\n type=\"button\"\n style={recording ? pillActive : pill}\n onClick={() => { setRecording(true); setError(null) }}\n >\n {recording ? '\u8BF7\u6309\u4E0B\u65B0\u7EC4\u5408\u952E\u2026' : '\u81EA\u5B9A\u4E49\u2026'}\n </button>\n {recording && (\n <button type=\"button\" style={pill} onClick={() => { setRecording(false); setError(null) }}>\n Esc \u53D6\u6D88\n </button>\n )}\n {error !== null && (\n <span style={{ color: 'var(--dsw-alias-state-error-primary)', fontSize: 12 }}>{error}</span>\n )}\n </div>\n </div>\n )\n}\n\n/**\n * \u5F00\u5173\uFF08\u80F6\u56CA\u6ED1\u5757\uFF09\u3002\n *\n * \u62BD\u51FA\u6765\u662F\u56E0\u4E3A\u5B83\u73B0\u5728\u6709\u4E24\u4E2A\u5C3A\u7801\uFF1A\u5361\u7247\u5185\u5BB9\u533A\u91CC\u7528 `md`\uFF0836\u00D720\uFF09\uFF0C\u6298\u53E0\u5361**\u6807\u9898\u884C**\u91CC\n * \u7528 `sm`\uFF0830\u00D716\uFF0C\u8DDF 11px \u7684\u6807\u9898\u5B57\u4E00\u884C\u653E\u5F97\u4E0B\uFF09\u3002\u5F00\u5173\u753B\u4E24\u904D\u8FDF\u65E9\u4F1A\u5206\u53C9\u3002\n */\nfunction Switch(props: {\n checked: boolean\n onChange: (next: boolean) => void\n /** \u65E0\u969C\u788D\u540D\u5B57\uFF08\u6807\u9898\u884C\u91CC\u7684\u5F00\u5173\u6CA1\u6709\u53EF\u89C1\u6587\u5B57\uFF0C\u5FC5\u987B\u7ED9\uFF09\u3002 */\n label: string\n small?: boolean\n}) {\n const { checked, onChange, label, small = false } = props\n const width = small ? 30 : 36\n const height = small ? 16 : 20\n const knob = small ? 12 : 14\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={label}\n title={label}\n onClick={() => { onChange(!checked) }}\n style={{\n width,\n height,\n borderRadius: 999,\n border: '0.5px solid var(--dsw-alias-border-l2)',\n cursor: 'pointer',\n background: checked\n ? 'var(--dsw-alias-button-primary-fill)'\n : 'var(--dsw-alias-interactive-bg-hover)',\n position: 'relative',\n flex: '0 0 auto',\n padding: 0,\n }}\n >\n <span\n style={{\n position: 'absolute',\n top: small ? 1 : 2,\n left: checked ? width - knob - (small ? 1 : 2) : (small ? 1 : 2),\n width: knob,\n height: knob,\n borderRadius: '50%',\n background: checked\n ? 'var(--dsw-alias-label-primary-foreground)'\n : 'var(--dsw-alias-label-secondary)',\n transition: 'left 0.12s ease',\n }}\n />\n </button>\n )\n}\n\n/** \u6807\u9898\u884C\u91CC\u7684\"\u6587\u5B57 + \u5C0F\u5F00\u5173\"\uFF08\u300C\u5BFC\u822A\u6EDA\u52A8\u300D\u300C\u8FB9\u7F18\u7F29\u653E\u300D\u8FD9\u7C7B\uFF09\u3002 */\nfunction MiniToggle(props: {\n label: string\n checked: boolean\n onChange: (next: boolean) => void\n}) {\n return (\n <span className=\"dsh-ux-miniToggle\">\n <span className=\"dsh-ux-miniToggleLabel\">{props.label}</span>\n <Switch small label={props.label} checked={props.checked} onChange={props.onChange} />\n </span>\n )\n}\n\n/** \u5F00\u5173\u884C\u3002 */\nfunction ToggleRow(props: {\n label: string\n desc?: string\n checked: boolean\n onChange: (next: boolean) => void\n /** \u5C55\u5F00\u533A\u91CC\u7684\u7B2C\u4E00\u884C\uFF1A\u4E0D\u753B\u4E0A\u8FB9\u6846\u3002 */\n first?: boolean\n}) {\n const { label, desc, checked, onChange, first } = props\n return (\n <div style={first === true ? { ...row, borderTop: 'none' } : row}>\n <div style={rowText}>\n <div style={rowTitle}>{label}</div>\n {desc !== undefined && desc !== '' && <div style={rowDesc}>{desc}</div>}\n </div>\n <Switch label={label} checked={checked} onChange={onChange} />\n </div>\n )\n}\n\n/** \u6587\u672C\u5B57\u6BB5\u884C\uFF1A\u6807\u9898 + \u8BF4\u660E + \u8F93\u5165\u6846\uFF08\u53EF\u9009\u52A8\u4F5C\u6309\u94AE\uFF09\u3002\n * \u8F93\u5165\u8FC7\u7A0B\u4E2D\u53EA\u6539\u672C\u5730\u8349\u7A3F\uFF0C\u5931\u7126\u6216\u56DE\u8F66\u624D\u843D\u76D8\u2014\u2014\u907F\u514D\u6BCF\u6572\u4E00\u4E2A\u5B57\u5C31\u5199\u4E00\u6B21\u914D\u7F6E\u6587\u4EF6\u3002 */\nfunction TextFieldRow(props: {\n title: string\n desc: string\n value: string\n placeholder?: string\n maxLength: number\n onChange: (next: string) => void\n action?: { label: string; onClick: () => void }\n /** \u5C55\u5F00\u533A\u91CC\u7684\u7B2C\u4E00\u884C\uFF1A\u4E0D\u753B\u4E0A\u8FB9\u6846\u3002 */\n first?: boolean\n}) {\n const { title, desc, value, placeholder, maxLength, onChange, action, first } = props\n const [draft, setDraft] = useState(value)\n const focused = useRef(false)\n\n // \u53EA\u5728\u6CA1\u6709\u7126\u70B9\u65F6\u8DDF\u968F\u5916\u90E8\u503C\uFF1A\u5199\u76D8\u662F\u5F02\u6B65\u5F80\u8FD4\uFF0C\u8F93\u5165\u4E2D\u540C\u6B65\u4F1A\u628A\u7528\u6237\u6B63\u5728\u6253\u7684\u5B57\u56DE\u6EDA\u3002\n useEffect(() => {\n if (!focused.current) setDraft(value)\n }, [value])\n\n const commit = (): void => {\n if (draft === value) return\n onChange(draft.trim())\n }\n\n const base = first === true ? { ...row, borderTop: 'none' } : row\n\n return (\n <div style={{ ...base, flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>{title}</div>\n <div style={rowDesc}>{desc}</div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n <input\n type=\"text\"\n value={draft}\n placeholder={placeholder ?? ''}\n maxLength={maxLength}\n spellCheck={false}\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n onFocus={() => { focused.current = true }}\n onChange={event => { setDraft(event.target.value) }}\n onBlur={() => { focused.current = false; commit() }}\n onKeyDown={event => {\n if (event.key !== 'Enter') return\n event.preventDefault()\n commit()\n event.currentTarget.blur()\n }}\n style={textInput}\n />\n {action !== undefined && (\n <button type=\"button\" style={pill} onClick={action.onClick}>{action.label}</button>\n )}\n </div>\n </div>\n )\n}\n\n/** \u5FEB\u6377\u6307\u4EE4\u7F16\u8F91\u533A\uFF1A\u672C\u5730\u8349\u7A3F + \u663E\u5F0F\u4FDD\u5B58\uFF08\u907F\u514D\u6BCF\u6572\u4E00\u4E2A\u5B57\u5C31\u5199\u4E00\u6B21\u914D\u7F6E\u6587\u4EF6\uFF09\u3002 */\n/**\n * \u5FEB\u6377\u6307\u4EE4\u7F16\u8F91\u5668\uFF080.3.0 \u8D77\u7684\u5206\u7C7B\u4E24\u7EA7\u7ED3\u6784\uFF09\u3002\n *\n * \u7F16\u8F91\u5728**\u672C\u5730\u8349\u7A3F**\u4E0A\u505A\uFF1A\u8349\u7A3F\u7528 `prompt-book.ts` \u90A3\u5957\u7EAF\u51FD\u6570\u6539\uFF08\u4E0E\u670D\u52A1\u7AEF\u540C\u4E00\u5957\u903B\u8F91\uFF09\uFF0C\n * \u53EA\u6709\u70B9\u300C\u4FDD\u5B58\u4FEE\u6539\u300D\u624D\u6574\u672C\u5199\u56DE \u2014\u2014 \u5426\u5219\u6BCF\u6572\u4E00\u4E2A\u5B57\u5C31\u662F\u4E00\u6B21 HTTP + \u4E00\u6B21\u539F\u5B50\u5199\u3002\n *\n * \u4FDD\u5B58\u540E\u5BBF\u4E3B\u4F1A\u56DE\u8BFB\u78C1\u76D8\u771F\u5B9E\u5185\u5BB9\u5E76\u8986\u76D6\u672C\u5730\u5FEB\u7167\uFF0C\u8349\u7A3F\u8DDF\u7740\u5B83\u8D70\uFF1A\u4E8E\u662F\u300C\u7A7A\u6B63\u6587\u7684\u6761\u76EE\u88AB\n * \u51C0\u5316\u4E22\u5F03\u300D\u8FD9\u7C7B\u6536\u7A84\u4F1A\u5728\u754C\u9762\u4E0A\u7ACB\u523B\u663E\u73B0\uFF0C\u800C\u4E0D\u662F\u7B49\u5230\u4E0B\u6B21\u6253\u5F00\u8BBE\u7F6E\u624D\u53D1\u73B0\u4E0D\u4E00\u6837\u3002\n */\nfunction QuickPromptsEditor(props: {\n book: QuickPromptBook\n status: string\n onSave: (next: QuickPromptBook) => void\n onReset: () => void\n onReload: () => void\n}) {\n const [draft, setDraft] = useState<QuickPromptBook>(() => props.book)\n const [activeId, setActiveId] = useState(() => props.book.categories[0]?.id ?? '')\n const [dirty, setDirty] = useState(false)\n const [newName, setNewName] = useState('')\n /** \u4E0A\u4E00\u6B21\u4FDD\u5B58\u65F6\u8DF3\u8FC7\u7A7A\u6761\u76EE\u7684\u8BF4\u660E\uFF08\u7A7A\u4E32 = \u65E0\uFF09\u3002 */\n const [note, setNote] = useState('')\n\n // \u672C\u5730\u6CA1\u6709\u672A\u4FDD\u5B58\u4FEE\u6539\u65F6\u8DDF\u968F\u5916\u90E8\u5FEB\u7167\u3002\n useEffect(() => {\n if (dirty) return\n setDraft(props.book)\n if (!props.book.categories.some(category => category.id === activeId)) {\n setActiveId(props.book.categories[0]?.id ?? '')\n }\n }, [props.book, dirty, activeId])\n\n const edit = (next: QuickPromptBook): void => {\n setDirty(true)\n setDraft(next)\n }\n const current = draft.categories.find(category => category.id === activeId) ?? draft.categories[0]\n const counts = bookCounts(draft)\n const saving = props.status === 'saving'\n const failed = props.status !== '' && props.status !== 'saving'\n\n const rowBox: CSSProperties = {\n display: 'flex', flexDirection: 'column', gap: 6,\n padding: 8, borderRadius: 8,\n border: '0.5px solid var(--dsw-alias-border-l2)',\n background: 'var(--dsw-alias-bg-layer-1)',\n }\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>\n {/* \u5206\u7C7B\u5207\u6362 + \u65B0\u589E */}\n <div style={{ display: 'flex', alignItems: 'center', gap: 4, flexWrap: 'wrap' }}>\n {draft.categories.map(category => (\n <button\n key={category.id}\n type=\"button\"\n style={category.id === current?.id ? pillActive : pill}\n onClick={() => { setActiveId(category.id) }}\n >\n {category.name}\uFF08{category.prompts.length}\uFF09\n </button>\n ))}\n <input\n type=\"text\"\n value={newName}\n placeholder=\"\u65B0\u5206\u7C7B\u540D\"\n maxLength={QUICK_CATEGORY_NAME_MAX}\n spellCheck={false}\n onChange={event => { setNewName(event.target.value) }}\n style={{ ...textInput, flex: '0 0 110px' }}\n />\n <button\n type=\"button\"\n style={pill}\n disabled={draft.categories.length >= QUICK_CATEGORY_MAX}\n onClick={() => {\n edit(withCategoryAdded(draft, newName === '' ? DEFAULT_CATEGORY_NAME : newName))\n setNewName('')\n }}\n >\n + \u52A0\u5206\u7C7B\n </button>\n </div>\n\n {current === undefined && (\n <p style={rowDesc}>\u8FD8\u6CA1\u6709\u5206\u7C7B\u3002\u5148\u52A0\u4E00\u4E2A\u5206\u7C7B\uFF0C\u518D\u5F80\u91CC\u653E\u6761\u76EE\u3002</p>\n )}\n\n {current !== undefined && (\n <>\n {/* \u5F53\u524D\u5206\u7C7B\uFF1A\u6539\u540D / \u6362\u4F4D / \u5220\u9664 */}\n <div style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>\n <input\n type=\"text\"\n value={current.name}\n aria-label=\"\u5206\u7C7B\u540D\"\n maxLength={QUICK_CATEGORY_NAME_MAX}\n spellCheck={false}\n onChange={event => { edit(withCategoryRenamed(draft, current.id, event.target.value)) }}\n style={{ ...textInput, flex: '0 0 150px' }}\n />\n <button type=\"button\" style={pill} title=\"\u5206\u7C7B\u4E0A\u79FB\" onClick={() => { edit(withCategoryMoved(draft, current.id, -1)) }}>\u2191</button>\n <button type=\"button\" style={pill} title=\"\u5206\u7C7B\u4E0B\u79FB\" onClick={() => { edit(withCategoryMoved(draft, current.id, 1)) }}>\u2193</button>\n <button\n type=\"button\"\n style={pill}\n title=\"\u5220\u9664\u8FD9\u4E2A\u5206\u7C7B\uFF08\u8FDE\u540C\u5B83\u91CC\u9762\u7684\u6761\u76EE\uFF09\"\n onClick={() => { edit(withCategoryRemoved(draft, current.id)) }}\n >\n \u2715 \u5220\u9664\u5206\u7C7B\n </button>\n <span style={rowDesc}>{current.prompts.length} / {QUICK_PROMPT_MAX} \u6761</span>\n </div>\n\n {current.prompts.map(prompt => (\n <div key={prompt.id} style={rowBox}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>\n <input\n type=\"text\"\n value={prompt.label}\n placeholder=\"\u540D\u79F0\uFF0C\u5982\uFF1A\u4EC5\u8BF4\u660E\u539F\u56E0\"\n maxLength={QUICK_LABEL_MAX}\n spellCheck={false}\n onChange={event => { edit(withPromptPatched(draft, current.id, prompt.id, { label: event.target.value })) }}\n style={{ ...textInput, flex: '0 0 150px' }}\n />\n <InsertModeControl\n label={prompt.label}\n mode={insertModeOf(prompt)}\n onChange={mode => { edit(withInsertMode(draft, prompt.id, mode)) }}\n />\n <span style={{ flex: 1 }} />\n <button type=\"button\" style={pill} title=\"\u4E0A\u79FB\" onClick={() => { edit(withPromptMoved(draft, current.id, prompt.id, -1)) }}>\u2191</button>\n <button type=\"button\" style={pill} title=\"\u4E0B\u79FB\" onClick={() => { edit(withPromptMoved(draft, current.id, prompt.id, 1)) }}>\u2193</button>\n <button type=\"button\" style={pill} title=\"\u5220\u9664\u8FD9\u6761\" onClick={() => { edit(withPromptRemoved(draft, current.id, prompt.id)) }}>\u2715</button>\n </div>\n <textarea\n value={prompt.prompt}\n placeholder=\"\u63D0\u793A\u8BCD\u6B63\u6587\uFF1A\u70B9\u51FB\u8BE5\u6761\u76EE\u65F6\u63D2\u5165\u8F93\u5165\u6846\uFF1B\u52FE\u4E86\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u5219\u5728\u53D1\u9001\u65F6\u81EA\u52A8\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E\"\n maxLength={QUICK_TEXT_MAX}\n spellCheck={false}\n rows={Math.min(4, Math.max(2, Math.ceil(prompt.prompt.length / 46)))}\n onChange={event => { edit(withPromptPatched(draft, current.id, prompt.id, { prompt: event.target.value })) }}\n style={{ ...textInput, resize: 'vertical', fontFamily: 'inherit', lineHeight: 1.5 }}\n />\n </div>\n ))}\n\n {/* \u5217\u8868\u6700\u4E0B\u8FB9\u7684\u300C\uFF0B\u300D\uFF1A\u65B0\u5EFA / \u628A\u522B\u7684\u5206\u7C7B\u7684\u6761\u76EE\u79FB\u52A8\u5230\u8FD9\u91CC\uFF08\u4E0E\u9762\u677F\u540C\u4E00\u7EC4\u4EF6\uFF09 */}\n <AddPromptRow\n book={draft}\n categoryId={current.id}\n onAdd={() => { edit(withPromptAdded(draft, current.id)) }}\n onMove={promptId => { edit(withPromptMovedToCategory(draft, promptId, current.id)) }}\n />\n </>\n )}\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>\n <button\n type=\"button\"\n style={dirty ? pillActive : pill}\n disabled={!dirty || saving}\n onClick={() => {\n // \u5148\u628A\u6B63\u6587\u4E3A\u7A7A\u7684\u6761\u76EE\u5254\u6389**\u5E76\u8BF4\u660E**\uFF1A\u51C0\u5316\u7AEF\u4E5F\u4F1A\u4E22\u5B83\u4EEC\uFF0C\u4F46\u82E5\u8BA9\u7528\u6237\u81EA\u5DF1\u53D1\u73B0\n // \u300C\u6211\u52A0\u7684\u8FD9\u6761\u600E\u4E48\u6CA1\u4E86\u300D\uFF0C\u90A3\u662F\u4E00\u6B21\u8BF4\u4E0D\u6E05\u7684\u9759\u9ED8\u4E22\u5931\u3002\n const next: QuickPromptBook = {\n version: draft.version,\n categories: draft.categories.map(category => ({\n ...category,\n prompts: category.prompts.filter(prompt => prompt.prompt.trim() !== ''),\n })),\n }\n const skipped = counts.prompts - bookCounts(next).prompts\n setNote(skipped > 0 ? `\u5DF2\u8DF3\u8FC7 ${String(skipped)} \u6761\u6B63\u6587\u4E3A\u7A7A\u7684\u6761\u76EE` : '')\n props.onSave(next)\n setDirty(false)\n }}\n >\n {saving ? '\u4FDD\u5B58\u4E2D\u2026' : (dirty ? '\u4FDD\u5B58\u4FEE\u6539' : '\u5DF2\u4FDD\u5B58')}\n </button>\n <button type=\"button\" style={pill} onClick={() => { props.onReload() }}>\u91CD\u65B0\u8BFB\u53D6</button>\n <button type=\"button\" style={pill} onClick={() => { props.onReset() }}>\u6062\u590D\u5185\u7F6E 9 \u6761</button>\n <span style={rowDesc}>\n \u5171 {counts.categories} \u4E2A\u5206\u7C7B \u00B7 {counts.prompts} \u6761 \u00B7 \u6BCF\u6B21 {counts.always} \u6761 \u00B7 \u4EC5\u9996\u6B21 {counts.first} \u6761\n {note === '' ? '' : ` \u00B7 ${note}`}\n {failed ? ` \u00B7 ${props.status}` : ''}\n </span>\n </div>\n <p style={rowDesc}>\n \u6570\u636E\u5B58\u5728 <code>~/.dsh/quick-prompts.json</code>\uFF08\u4E0E\u4F1A\u8BDD\u3001\u9879\u76EE\u65E0\u5173\uFF0C\u53EF\u5355\u72EC\u5907\u4EFD\u6216\u624B\u5DE5\u7F16\u8F91\uFF0C\n \u6539\u5B8C\u70B9\u300C\u91CD\u65B0\u8BFB\u53D6\u300D\u5373\u53EF\u52A0\u8F7D\uFF09\u3002\n </p>\n </div>\n )\n}\n\n/** \u5019\u9009\u6309\u94AE\u7684\u6837\u5F0F\uFF1A\u4E0E\u80F6\u56CA\u540C\u6E90\uFF0C\u4F46\u8981\u80FD\u663E\u793A\u957F\u8DEF\u5F84\u3002 */\nconst candidatePill: CSSProperties = {\n ...pill,\n textAlign: 'left',\n maxWidth: '100%',\n overflowWrap: 'anywhere',\n lineHeight: 1.4,\n}\n\n/**\n * \u300C\u9ED8\u8BA4\u7EC8\u7AEF\u300D\u5361\u7247\u5185\u5BB9\uFF08Windows\uFF1A\u628A\u7EC8\u7AEF\u7684 pwsh \u6362\u6210 Git Bash\uFF09\u3002\n *\n * \u4E0E\u5176\u5B83\u5361\u7247\u7684\u533A\u522B\uFF1A\u72B6\u6001\u3001\u5019\u9009\u8868\u3001\u5F53\u524D\u751F\u6548 shell \u4E09\u9879\u90FD\u662F**\u5BBF\u4E3B\u534A**\u5199\u7684\n * \uFF08settings \u91CC\u7684 terminalStatus / terminalCandidates / terminalEffective\uFF0C\u89C1 HOST_OWNED_FIELDS\uFF09\uFF0C\n * \u8FD9\u91CC\u53EA\u8BFB\u5C55\u793A\uFF1B\u7528\u6237\u80FD\u6539\u7684\u53EA\u6709\u300C\u6863\u4F4D\u300D\u4E0E\u300C\u8DEF\u5F84\u300D\u4E24\u9879\u3002\n */\nfunction DefaultTerminalBody(props: {\n readonly settings: ComposerUxSettings\n readonly setField: (field: SettingsField, value: unknown) => void\n /** \u6863\u4F4D\u80F6\u56CA\u5DF2\u7ECF\u642C\u5230\u6298\u53E0\u5361\u6807\u9898\u884C\u65F6\u4F20 true\uFF08\u5185\u5BB9\u533A\u4E0D\u518D\u91CD\u590D\u4E00\u4EFD\uFF09\u3002 */\n readonly hideMode?: boolean\n}) {\n const { settings, setField, hideMode = false } = props\n const [note, setNote] = useState('')\n const [busy, setBusy] = useState(false)\n const candidates = settings.terminalCandidates\n\n if (settings.terminalEffective === 'unsupported') {\n return (\n <p style={hintInfo}>\n \u672C\u63D2\u4EF6\u53EA\u5728 Windows \u4E0A\u63A5\u7BA1\u7EC8\u7AEF\uFF08Windows \u4E0A DSH \u9ED8\u8BA4\u7ED9\u6A21\u578B\u7684\u662F PowerShell\uFF09\u3002\u5F53\u524D\u5E73\u53F0\u4E0D\u9700\u8981\u5B83\uFF0C\n \u8FD9\u91CC\u7684\u8BBE\u7F6E\u4E0D\u4F1A\u751F\u6548\u3002\n </p>\n )\n }\n\n /** \u70B9\u300C\u81EA\u52A8\u53D1\u73B0\u300D\uFF1A\u8BA9\u5BBF\u4E3B\u534A\u91CD\u65B0\u626B\u4E00\u904D\u672C\u673A\uFF08\u6D4F\u89C8\u5668\u78B0\u4E0D\u5230\u6587\u4EF6\u7CFB\u7EDF\uFF09\u3002 */\n const discover = async (): Promise<void> => {\n setBusy(true)\n setNote('')\n try {\n const response = await fetch(TERMINAL_API_PATH, { method: 'POST' })\n const parsed = await response.json() as { candidates?: unknown }\n const found = sanitizeTerminalCandidates(parsed.candidates)\n setNote(found.length === 0\n ? '\u6CA1\u6709\u627E\u5230\u53EF\u7528\u7684 bash\uFF08WSL \u7684 bash.exe \u4F1A\u88AB\u5FFD\u7565\uFF0C\u5B83\u6309 Linux \u89C4\u5219\u89E3\u91CA\u8DEF\u5F84\uFF09'\n : `\u627E\u5230 ${String(found.length)} \u4E2A\u5019\u9009\uFF0C\u5DF2\u5217\u5728\u4E0B\u65B9`)\n } catch (error: unknown) {\n setNote(`\u81EA\u52A8\u53D1\u73B0\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`)\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <>\n {!hideMode && (\n <div style={{ ...row, borderTop: 'none', flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>\u7EC8\u7AEF\u5DE5\u5177</div>\n <div style={rowDesc}>\n {TERMINAL_MODES.find(item => item.id === settings.terminalMode)?.hint ?? ''}\n </div>\n </div>\n <PillChoice\n items={TERMINAL_MODES}\n value={settings.terminalMode}\n onChange={mode => { setField(TERMINAL_MODE_FIELD, mode) }}\n ariaLabel=\"\u7EC8\u7AEF\u5DE5\u5177\"\n />\n </div>\n )}\n\n {settings.terminalMode !== 'pwsh' && (<>\n <TextFieldRow\n title=\"Git Bash \u8DEF\u5F84\"\n desc=\"\u7559\u7A7A = \u7528\u81EA\u52A8\u63A2\u6D4B\u5230\u7684\u90A3\u4E00\u4E2A\uFF08\u5148\u627E git\uFF0C\u518D\u7531\u540C\u4E00\u4E2A\u5B89\u88C5\u53CD\u63A8 bash\uFF09\"\n value={settings.terminalBashPath}\n placeholder=\"\u7559\u7A7A = \u81EA\u52A8\"\n maxLength={400}\n onChange={next => { setField(TERMINAL_BASH_PATH_FIELD, next) }}\n action={{ label: busy ? '\u63A2\u6D4B\u4E2D\u2026' : '\u81EA\u52A8\u53D1\u73B0', onClick: () => { void discover() } }}\n />\n {candidates.length > 0 && (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: 2 }}>\n {candidates.map(candidate => (\n <button\n key={candidate.path}\n type=\"button\"\n title={candidate.path}\n style={candidate.path === settings.terminalBashPath ? { ...candidatePill, ...pillActive } : candidatePill}\n onClick={() => { setField(TERMINAL_BASH_PATH_FIELD, candidate.path) }}\n >\n {candidate.label}\uFF1A{candidate.path}{candidate.explicit ? '\uFF08\u4F60\u586B\u7684\uFF09' : ''}\n </button>\n ))}\n </div>\n )}\n {note !== '' && <p style={hintInfo}>{note}</p>}\n </>)}\n\n <p style={hintInfo}>\n \u72B6\u6001\uFF1A{settings.terminalStatus === '' ? '\u7B49\u5F85\u5BBF\u4E3B\u534A\u63A2\u6D4B\u2026' : settings.terminalStatus}\n </p>\n <p style={hintInfo}>\n \u00B7 \u6362\u6210 Git Bash \u540E\uFF0C\u6A21\u578B\u770B\u5230\u7684\u7EC8\u7AEF\u5DE5\u5177\u5C31\u53EB bash\uFF08\u547D\u4EE4\u6309 bash/POSIX \u5199\uFF09\uFF0CPowerShell \u90A3\u4E2A\u5DE5\u5177\n \u4F1A\u4ECE\u5B83\u7684\u5DE5\u5177\u5217\u8868\u91CC\u6D88\u5931 \u2014\u2014 \u4E00\u4E2A\u4F1A\u8BDD\u53EA\u9762\u5BF9\u4E00\u4E2A\u7EC8\u7AEF\u5DE5\u5177\u3002\n </p>\n <p style={hintInfo}>\n \u00B7 \u6539\u6863\u4F4D\u4F1A\u7ACB\u523B\u91CD\u65B0\u4E0B\u53D1\u7ED9\u6B63\u5728\u8DD1\u7684\u4F1A\u8BDD\u3002\u4F46\u4F1A\u8BDD\u5386\u53F2\u91CC\u53EF\u80FD\u8FD8\u7559\u7740\u65E7\u5DE5\u5177\u540D\uFF1A\u5982\u679C\u54EA\u513F\u62A5\u4E86\n unknown tool \u4E4B\u7C7B\u7684\u9519\uFF0C\u8BA9\u6A21\u578B\u6539\u7528 bash \u91CD\u8BD5\u5373\u53EF\uFF0C\u4E0D\u5F71\u54CD\u4F1A\u8BDD\u672C\u8EAB\u3002\n </p>\n <p style={hintInfo}>\n \u00B7 \u53EA\u5BF9 Windows \u751F\u6548\uFF1BWSL \u7684 bash.exe \u4F1A\u88AB\u4E3B\u52A8\u6392\u9664\uFF08\u5B83\u628A D:\\ \u8FD9\u7C7B\u8DEF\u5F84\u89E3\u91CA\u6210 /mnt/d\uFF0C\u4E0E\u6A21\u578B\u624B\u91CC\u7684\n Windows \u5DE5\u4F5C\u76EE\u5F55\u4E0D\u517C\u5BB9\uFF09\u3002\u6C99\u7BB1\u3001\u5BA1\u6279\u3001\u8D85\u65F6\u4E0E\u8F93\u51FA\u622A\u65AD\u7684\u884C\u4E3A\u4E0E DSH \u81EA\u5E26\u7EC8\u7AEF\u4E00\u81F4\u3002\n </p>\n </>\n )\n}\n\n/**\n * \u300C\u91CD\u542F DSH\u300D\uFF1A\u62AC\u5934\u53F3\u7AEF\u4E00\u679A\u6309\u94AE + \u62AC\u5934\u6B63\u4E0B\u65B9\u7684\u786E\u8BA4\u6761\u3002\n *\n * \u673A\u5236\uFF08\u5BBF\u4E3B\u534A\uFF0C\u89C1 `src/restart.ts`\uFF09\u7167\u642C\u63D2\u4EF6\u5E02\u573A\uFF1A\u5206\u79BB\u4E00\u4E2A node \u52A9\u624B\u8FDB\u7A0B \u2192 \u81EA\u5DF1\u9000\u51FA \u2192\n * \u52A9\u624B\u7B49\u7AEF\u53E3\u771F\u7684\u7A7A\u51FA\u6765 \u2192 \u7528\u9690\u85CF\u63A7\u5236\u53F0\u7684 PowerShell \u8D77\u65B0\u5BBF\u4E3B \u2192 20 \u79D2\u5185\u786E\u8BA4\u7AEF\u53E3\u6709\u4EBA\u76D1\u542C\u3002\n * \u754C\u9762\u8FD9\u4E00\u4FA7\u53EA\u7BA1\u4E09\u4EF6\u4E8B\uFF1A**\u4E24\u6B65\u786E\u8BA4**\u3001\u628A\"\u4F1A\u600E\u4E48\u91CD\u542F / \u6709\u51E0\u4E2A\u4F1A\u8BDD\u5728\u8DD1\"\u8BF4\u6E05\u695A\u3001\n * \u91CD\u542F\u540E\u9760 `boot` \u53F7\u53D8\u4E86\u5224\u65AD\u65B0\u8FDB\u7A0B\u771F\u7684\u8D77\u6765\u4E86\uFF0C\u7136\u540E\u5237\u65B0\u9875\u9762\u3002\n *\n * \u4E3A\u4EC0\u4E48\u662F\u4E24\u6B65\u786E\u8BA4\u800C\u4E0D\u662F\u5E02\u573A\u90A3\u6837\u4E00\u70B9\u5C31\u8D70\uFF1A\u5E02\u573A\u90A3\u679A\u6309\u94AE\u53EA\u51FA\u73B0\u5728\u300C\u6709\u5F85\u91CD\u542F\u7684\u4E1C\u897F\u300D\u7684\u6A2A\u5E45\u91CC\n * \uFF08\u90A3\u4E00\u523B\u4F60\u624B\u91CC\u6CA1\u522B\u7684\u4E8B\uFF09\uFF0C\u800C\u8FD9\u679A\u5E38\u9A7B\u5728\u62AC\u5934\uFF0C\u4EFB\u4F55\u65F6\u5019\u90FD\u80FD\u70B9\u5230 \u2014\u2014 \u5305\u62EC\u4F60\u6B63\u8DD1\u7740\u4E00\u8F6E\u957F\u751F\u6210\u3002\n */\n\n/** \u5BBF\u4E3B\u534A\u544A\u8BC9\u754C\u9762\u7684\u4E8B\u5B9E\u3002 */\ninterface RestartFacts {\n /** \u5F53\u524D\u6709\u51E0\u4E2A\u4F1A\u8BDD\u5728\u8DD1\uFF08\u91CD\u542F\u4F1A\u628A\u5B83\u4EEC\u6253\u65AD\uFF09\u3002 */\n readonly running: number\n /** \u4F1A\u600E\u4E48\u91CD\u542F\uFF08\u91CD\u653E\u7528\u7684\u547D\u4EE4\uFF0C\u7ED9\u7528\u6237\u770B\u4E00\u773C\uFF09\u3002 */\n readonly command: string\n /** \u8BCA\u65AD\u65E5\u5FD7\u843D\u70B9\uFF08\u5931\u8D25\u65F6\u544A\u8BC9\u7528\u6237\u53BB\u54EA\u770B\uFF09\u3002 */\n readonly logHint: string\n /** \u975E null = \u8FD9\u4E2A\u5BBF\u4E3B\u4E0D\u8BE5\u88AB\u4ECE\u754C\u9762\u91CC\u6740\u6389\uFF08\u8C03\u8BD5\u5668 / systemd\uFF09\u3002 */\n readonly blocked: string | null\n /** \u8FD9\u6B21\u542F\u52A8\u7684\u6807\u8BC6\uFF1Bnull = \u5BBF\u4E3B\u534A\u8FD8\u662F 0.5.0 \u4E4B\u524D\u90A3\u7248\uFF08\u6CA1\u6709\u8FD9\u4E2A\u5B57\u6BB5\uFF09\u3002 */\n readonly boot: string | null\n}\n\ntype RestartStage = 'idle' | 'asking' | 'restarting' | 'failed'\n\ninterface RestartController {\n readonly stage: RestartStage\n readonly detail: string\n readonly blocked: string | null\n ask(): void\n confirm(): void\n cancel(): void\n}\n\n/** \u6700\u591A\u7B49 60 \u79D2\uFF1A\u65B0\u5BBF\u4E3B\u8D77\u6765\u7EA6 7 \u79D2\uFF0C\u4F46\u6162\u4E86\u4E5F\u4E0D\u8BE5\u8BA9\u7528\u6237\u5BF9\u7740\"\u6B63\u5728\u91CD\u542F\"\u65E0\u9650\u5E72\u7B49\u3002 */\nconst RESTART_WAIT_MS = 60_000\n/** \u8F6E\u8BE2\u95F4\u9694\uFF08\u5BF9\u9F50\u63D2\u4EF6\u5E02\u573A\uFF1A1.5 \u79D2\u95EE\u4E00\u6B21\u72B6\u6001\uFF09\u3002 */\nconst RESTART_POLL_MS = 1_500\n\n/** \u300C\u4E0D\u8BE5\u4ECE\u754C\u9762\u91CC\u6740\u6389\u300D\u7684\u539F\u56E0\u6587\u6848\u3002 */\nfunction blockedText(blocked: string): string {\n if (blocked === 'debugger') {\n return '\u8FD9\u4E2A\u5BBF\u4E3B\u6B63\u88AB\u8C03\u8BD5\u5668\u9644\u7740\uFF1A\u4ECE\u754C\u9762\u91CC\u6740\u6389\u5B83\u53EA\u4F1A\u8FDE\u8C03\u8BD5\u4F1A\u8BDD\u4E00\u8D77\u4E22\u6389\uFF0C\u8BF7\u4ECE IDE \u6216\u7EC8\u7AEF\u505C\u6B62\u5B83\u518D\u542F\u52A8\u3002'\n }\n if (blocked.startsWith('supervised:')) {\n return `\u8FD9\u4E2A\u5BBF\u4E3B\u7531 ${blocked.slice('supervised:'.length)} \u5F53\u670D\u52A1\u5728\u8DD1\uFF0C\u91CD\u542F\u8BE5\u5F52\u5B83\u7BA1`\n + '\uFF08\u5B83\u4F1A\u8FDE\u540C\u6574\u4E2A cgroup \u4E00\u8D77\u6536\u6389\uFF0C\u63D2\u4EF6\u81EA\u5DF1\u91CD\u542F\u53EA\u4F1A\u8BA9\u670D\u52A1\u518D\u4E5F\u8D77\u4E0D\u6765\uFF09\u3002'\n }\n return `\u8FD9\u4E2A\u5BBF\u4E3B\u5F53\u524D\u4E0D\u5141\u8BB8\u4ECE\u754C\u9762\u91CD\u542F\uFF08${blocked}\uFF09\u3002`\n}\n\n/** \u91CD\u542F\u6309\u94AE\u7684\u72B6\u6001\u673A\uFF1A\u8BFB\u72B6\u6001 \u2192 \u786E\u8BA4 \u2192 \u6392\u91CD\u542F \u2192 \u7B49\u65B0\u8FDB\u7A0B\u3002 */\nfunction useRestart(): RestartController {\n const [stage, setStage] = useState<RestartStage>('idle')\n const [detail, setDetail] = useState('')\n const [blocked, setBlocked] = useState<string | null>(null)\n\n /** \u8BFB\u5BBF\u4E3B\u534A\u7684\u72B6\u6001\uFF1B`{ error }` = \u8BFB\u4E0D\u5230\uFF08HTTP \u5931\u8D25 / \u8FDE\u63A5\u65AD\u4E86\uFF09\u3002 */\n const readFacts = async (): Promise<RestartFacts | { error: string }> => {\n const response = await fetch(RESTART_API_PATH, { cache: 'no-store' })\n if (!response.ok) return { error: `HTTP ${String(response.status)}` }\n const parsed = await response.json() as Record<string, unknown>\n return {\n running: typeof parsed.running === 'number' ? parsed.running : 0,\n command: typeof parsed.command === 'string' ? parsed.command : '',\n logHint: typeof parsed.logHint === 'string' ? parsed.logHint : '',\n blocked: typeof parsed.blocked === 'string' ? parsed.blocked : null,\n boot: typeof parsed.boot === 'string' ? parsed.boot : null,\n }\n }\n\n /** \u7B49\u65B0\u8FDB\u7A0B\u8D77\u6765\uFF1A`boot` \u53F7\u4E00\u53D8\u5C31\u5237\u65B0\u9875\u9762\u3002 */\n const awaitNewBoot = async (previousBoot: string | null, logHint: string): Promise<void> => {\n const deadline = Date.now() + RESTART_WAIT_MS\n while (Date.now() < deadline) {\n await new Promise<void>(done => { setTimeout(done, RESTART_POLL_MS) })\n try {\n const facts = await readFacts()\n if ('error' in facts) continue\n // \u65E7\u7248\u5BBF\u4E3B\u6CA1\u6709 boot \u5B57\u6BB5\uFF1A\u53EA\u8981\u62FF\u5230\u4EFB\u4F55\u4E00\u4E2A\u53F7\uFF0C\u5C31\u8BF4\u660E\u65B0\u8FDB\u7A0B\u5DF2\u7ECF\u63A5\u7BA1\u4E86\u8FD9\u4E2A\u7AEF\u53E3\u3002\n if (facts.boot !== null && facts.boot !== previousBoot) {\n location.reload()\n return\n }\n } catch {\n // \u65B0\u8FDB\u7A0B\u8FD8\u6CA1\u8D77\u6765\uFF08\u8FDE\u63A5\u88AB\u62D2\uFF09\uFF1A\u6B63\u5E38\uFF0C\u7EE7\u7EED\u7B49\u3002\n }\n }\n setStage('failed')\n setDetail('\u7B49\u4E86 60 \u79D2\u4E5F\u6CA1\u7B49\u5230\u65B0\u8FDB\u7A0B\u3002\u8BF7\u624B\u52A8\u8FD0\u884C restart-webui.bat \u91CD\u542F\u4E00\u6B21\u3002'\n + (logHint === '' ? '' : `\u5BBF\u4E3B\u534A\u7684\u8BCA\u65AD\u65E5\u5FD7\u5728 ${logHint}\u3002`))\n }\n\n /** \u7B2C\u4E00\u6B65\uFF1A\u8BFB\"\u4F1A\u600E\u4E48\u91CD\u542F\u3001\u73B0\u5728\u6709\u51E0\u4E2A\u4F1A\u8BDD\u5728\u8DD1\"\u3002 */\n const ask = (): void => {\n setStage('asking')\n setDetail('\u6B63\u5728\u8BFB\u53D6\u91CD\u542F\u65B9\u5F0F\u2026')\n void (async () => {\n try {\n const facts = await readFacts()\n if ('error' in facts) {\n setStage('failed')\n setDetail(`\u8BFB\u4E0D\u5230\u91CD\u542F\u72B6\u6001\uFF08${facts.error}\uFF09\u2014\u2014 \u5BBF\u4E3B\u534A\u53EF\u80FD\u8FD8\u6CA1\u6362\u5230\u5E26\u8FD9\u6761\u8DEF\u7531\u7684\u7248\u672C\uFF0C`\n + '\u8BF7\u5148\u624B\u52A8\u8FD0\u884C\u4E00\u6B21 restart-webui.bat\u3002')\n return\n }\n setBlocked(facts.blocked)\n if (facts.blocked !== null) {\n setStage('failed')\n setDetail(blockedText(facts.blocked))\n return\n }\n setStage('asking')\n // \u5BBF\u4E3B\u534A\u6CA1\u6709 boot \u5B57\u6BB5 = \u8FD8\u662F\u4E0A\u4E00\u7248\uFF08\u65B0\u8DEF\u7531\u8981\u91CD\u542F\u540E\u624D\u52A0\u8F7D\uFF09\u3002\u8FD9\u65F6\u5982\u5B9E\u8BF4\u660E\uFF1A\n // \u8FD9\u4E00\u6B21\u4F1A\u8D70\u65E7\u673A\u5236\uFF0C\u800C\u4E14\u91CD\u542F\u4E4B\u540E\u6309\u94AE\u624D\u53D8\u6210\u65B0\u7248 \u2014\u2014 \u522B\u8BA9\u7528\u6237\u4EE5\u4E3A\u6CA1\u751F\u6548\u3002\n setDetail((facts.boot === null\n ? '\u5BBF\u4E3B\u534A\u8FD8\u662F\u4E0A\u4E00\u7248\uFF1A\u8FD9\u6B21\u91CD\u542F\u4F1A\u8D70\u65E7\u673A\u5236\uFF08\u5199\u811A\u672C + \u81EA\u5DF1\u9000\u51FA\uFF09\uFF0C\u91CD\u542F\u4E4B\u540E\u6309\u94AE\u5C31\u662F\u65B0\u7248\u4E86\u3002'\n : `\u91CD\u542F\u65B9\u5F0F\uFF1A${facts.command}\u3002`)\n + `\u5F53\u524D\u6709 ${String(facts.running)} \u4E2A\u4F1A\u8BDD\u5728\u8DD1 \u2014\u2014 \u91CD\u542F\u4F1A\u6253\u65AD\u5B83\u4EEC\uFF08\u5305\u62EC\u6B63\u5728\u751F\u6210\u7684\u90A3\u4E00\u8F6E\uFF09\u3002`)\n } catch (error: unknown) {\n setStage('failed')\n setDetail(`\u8BFB\u4E0D\u5230\u91CD\u542F\u72B6\u6001\uFF1A${error instanceof Error ? error.message : String(error)}`)\n }\n })()\n }\n\n /** \u7B2C\u4E8C\u6B65\uFF1A\u786E\u8BA4\u540E\u8BA9\u5BBF\u4E3B\u534A\u6392\u91CD\u542F\uFF0C\u7136\u540E\u7B49\u65B0\u8FDB\u7A0B\u3002 */\n const confirm = (): void => {\n setStage('restarting')\n setDetail('\u5DF2\u53D1\u51FA\u91CD\u542F\u8BF7\u6C42 \u2014\u2014 \u6B63\u5728\u7B49\u65B0\u8FDB\u7A0B\u8D77\u6765\uFF08\u8FD9\u4E2A\u9875\u9762\u4F1A\u81EA\u5DF1\u56DE\u6765\uFF09\u2026')\n void (async () => {\n let previousBoot: string | null = null\n let logHint = ''\n try {\n const before = await readFacts()\n if (!('error' in before)) {\n previousBoot = before.boot\n logHint = before.logHint\n }\n } catch {\n // \u8BFB\u4E0D\u5230\u4E5F\u65E0\u6240\u8C13\uFF1A\u4E0B\u9762\u7684\u8F6E\u8BE2\u53EA\u9700\u8981\"\u53F7\u53D8\u4E86\"\u8FD9\u4E00\u4E2A\u6761\u4EF6\u3002\n }\n try {\n const response = await fetch(RESTART_API_PATH, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: '{}',\n })\n const parsed = await response.json() as { ok?: boolean; error?: string }\n if (response.status !== 202 && parsed.ok !== true) {\n setStage('failed')\n setDetail(`\u91CD\u542F\u6CA1\u6210\u529F\uFF1A${parsed.error ?? `HTTP ${String(response.status)}`}`\n + ' \u2014\u2014 \u8BF7\u624B\u52A8\u8FD0\u884C restart-webui.bat\u3002')\n return\n }\n } catch {\n // \u5BBF\u4E3B\u53EF\u80FD\u6B7B\u5728\u54CD\u5E94\u53D1\u5B8C\u4E4B\u524D\uFF1A\u90A3\u4E0D\u662F\u5931\u8D25\uFF0C\u7EE7\u7EED\u7B49\u65B0\u8FDB\u7A0B\u3002\n }\n await awaitNewBoot(previousBoot, logHint)\n })()\n }\n\n const cancel = (): void => {\n setStage('idle')\n setDetail('')\n }\n\n return { stage, detail, blocked, ask, confirm, cancel }\n}\n\n/** \u62AC\u5934\u53F3\u7AEF\u90A3\u679A\u6309\u94AE\uFF08\u5728 GitHub \u94FE\u63A5\u5DE6\u8FB9\uFF09\u3002 */\nfunction RestartButton({ restart }: { readonly restart: RestartController }) {\n const busy = restart.stage === 'restarting' || restart.stage === 'asking'\n const blocked = restart.blocked\n return (\n <button\n type=\"button\"\n className=\"dsh-ux-restartButton\"\n disabled={busy || blocked !== null}\n title={blocked === null\n ? '\u91CD\u542F DSH\uFF1A\u8BA9\u5BBF\u4E3B\u534A\u7684\u65B0\u4EE3\u7801\uFF08\u9ED8\u8BA4\u7EC8\u7AEF\u3001\u952E\u4F4D schema\uFF09\u751F\u6548\u3002\u70B9\u4E00\u4E0B\u4F1A\u5148\u8BA9\u4F60\u786E\u8BA4\u4E00\u6B21\u3002'\n : blockedText(blocked)}\n onClick={() => { restart.ask() }}\n >\n {restart.stage === 'restarting' ? '\u91CD\u542F\u4E2D\u2026' : '\u91CD\u542F DSH'}\n </button>\n )\n}\n\n/**\n * \u62AC\u5934\u53F3\u7AEF\u90A3\u679A\u300C\u5237\u65B0\u300D\u6309\u94AE\uFF08\u5728\u300C\u91CD\u542F DSH\u300D\u5DE6\u8FB9\uFF09\u3002\n *\n * \u4E3A\u4EC0\u4E48\u503C\u5F97\u6709\u4E00\u679A\uFF1A\u63D2\u4EF6\u7684**\u5BA2\u6237\u7AEF\u534A**\uFF08\u8BBE\u7F6E\u9875 / \u53F3\u952E\u83DC\u5355 / \u952E\u4F4D\u62E6\u622A / \u5FEB\u6377\u6307\u4EE4\u9762\u677F\uFF09\n * \u662F\u968F\u9875\u9762 bundle \u8D70\u7684\uFF0C\u6539\u5B8C\u53EA\u8981\u91CD\u65B0\u52A0\u8F7D\u9875\u9762\u5C31\u751F\u6548\uFF0C**\u6839\u672C\u4E0D\u9700\u8981\u91CD\u542F\u5BBF\u4E3B**\u3002\n * \u800C\u300C\u91CD\u542F DSH\u300D\u5728\u5B98\u65B9\u5B89\u88C5\u7684\u684C\u9762\u7248\u91CC\u4E0D\u53EF\u80FD\u751F\u6548 \u2014\u2014 \u5BBF\u4E3B\u662F Electron \u5E94\u7528\uFF0C\n * \u91CD\u653E\u4E0D\u51FA\u53EF\u7528\u7684\u542F\u52A8\u547D\u4EE4\uFF082026-09-25 \u5B9E\u6D4B\uFF1A`_boot.log` \u53CD\u590D\u62A5\u300C\u65E0\u6CD5\u5B9A\u4F4D dsh CLI\u300D\uFF0C\n * \u91CD\u542Fhelper \u7684\u65E5\u5FD7\u81EA 09-23 \u8D77\u4E00\u6761\u6CA1\u6709\uFF09\u3002\u4E8E\u662F\"\u60F3\u8BA9\u6539\u52A8\u751F\u6548\"\u8FD9\u4EF6\u4E8B\u5728\u684C\u9762\u7248\u91CC\n * \u5C31\u6CA1\u4E86\u4E0B\u624B\u5904\uFF0C\u8FD9\u679A\u6309\u94AE\u8865\u7684\u6B63\u662F\u8FD9\u4E2A\u7F3A\u53E3\u3002\n *\n * \u5B83\u53EA\u505A\u4E00\u4EF6\u4E8B\uFF1A`location.reload()`\u3002\u4E0D\u53D1\u8BF7\u6C42\u3001\u4E0D\u78B0\u5BBF\u4E3B\u3001**\u4E0D\u6253\u65AD\u6B63\u5728\u8DD1\u7684\u4F1A\u8BDD**\n * \uFF08\u4F1A\u8BDD\u5728\u5BBF\u4E3B\u4FA7\u6D3B\u7740\uFF0C\u5237\u65B0\u53EA\u91CD\u5EFA\u754C\u9762\uFF09\u3002\n *\n * \u590D\u7528 `.dsh-ux-restartButton` \u7684\u89C2\u611F\uFF1A\u90A3\u662F\"\u62AC\u5934\u5C0F\u80F6\u56CA\"\u8FD9\u4E00\u5957\u6837\u5F0F\uFF0C\u7C7B\u540D\u88AB\n * `test/client-registration.mjs` \u9489\u7740\uFF08\u6539\u540D\u4F1A\u649E\u62A4\u680F\uFF09\uFF0C\u800C\u4E14\u4E24\u679A\u5E76\u6392\u5FC5\u987B\u957F\u5F97\u4E00\u6837\u3002\n */\nfunction RefreshButton({ busy }: { readonly busy: boolean }) {\n return (\n <button\n type=\"button\"\n className=\"dsh-ux-restartButton\"\n disabled={busy}\n title=\"\u5237\u65B0\u9875\u9762\uFF1A\u8BA9\u63D2\u4EF6\u5BA2\u6237\u7AEF\u534A\u7684\u65B0\u4EE3\u7801\uFF08\u8BBE\u7F6E\u9875 / \u53F3\u952E\u83DC\u5355 / \u952E\u4F4D / \u5FEB\u6377\u6307\u4EE4\u9762\u677F\uFF09\u751F\u6548\u3002\u4E0D\u91CD\u542F DSH\u3001\u4E0D\u6253\u65AD\u6B63\u5728\u8DD1\u7684\u4F1A\u8BDD\u3002\"\n onClick={() => { window.location.reload() }}\n >\n \u5237\u65B0\n </button>\n )\n}\n\n/** \u62AC\u5934\u6B63\u4E0B\u65B9\u7684\u786E\u8BA4\u6761\uFF08\u5E02\u573A\u90A3\u4E2A\u300CN \u9879\u53D8\u66F4\u9700\u91CD\u542F\u300D\u6A2A\u5E45\u7684\u4F4D\u7F6E\uFF09\u3002 */\nfunction RestartBanner({ restart }: { readonly restart: RestartController }) {\n if (restart.stage === 'idle') return null\n const failed = restart.stage === 'failed'\n return (\n <div className={failed ? 'dsh-ux-restartBanner dsh-ux-restartBannerFailed' : 'dsh-ux-restartBanner'}>\n <span className=\"dsh-ux-restartBannerText\">{restart.detail}</span>\n {restart.stage === 'asking' && (\n <span className=\"dsh-ux-restartBannerActions\">\n <button type=\"button\" className=\"dsh-ux-restartGo\" onClick={() => { restart.confirm() }}>\u786E\u8BA4\u91CD\u542F</button>\n <button type=\"button\" className=\"dsh-ux-restartCancel\" onClick={() => { restart.cancel() }}>\u53D6\u6D88</button>\n </span>\n )}\n {failed && (\n <span className=\"dsh-ux-restartBannerActions\">\n <button type=\"button\" className=\"dsh-ux-restartCancel\" onClick={() => { restart.cancel() }}>\u77E5\u9053\u4E86</button>\n </span>\n )}\n </div>\n )\n}\n\n/** \u8BBE\u7F6E\u9875\u4E3B\u4F53\u3002 */\nexport function SettingsSection({ useLive, useBook, useBookStatus, useWriteNotice, actions }: SettingsSectionProps) {\n const settings = useLive(item => item)\n const book = useBook(item => item)\n const bookStatus = useBookStatus(item => item)\n /** '' = \u5199\u5165\u6B63\u5E38\uFF1B\u5176\u4F59\u662F\"\u88AB\u62D2 / \u5199\u4E86\u4F46\u8FD0\u884C\u65F6\u6CA1\u53D8\"\u7684\u8BF4\u660E\uFF08\u89C1 client.tsx \u7684 setField\uFF09\u3002 */\n const writeNotice = useWriteNotice(item => item)\n const [conflict, setConflict] = useState<string | null>(null)\n // \u91CD\u542F\u6309\u94AE\u5728\u62AC\u5934\u3001\u786E\u8BA4\u6761\u5728\u62AC\u5934\u6B63\u4E0B\u65B9 \u2014\u2014 \u4E24\u5904\u8981\u8BFB\u540C\u4E00\u4EFD\u72B6\u6001\uFF0C\u6240\u4EE5\u72B6\u6001\u63D0\u5230\u8FD9\u4E00\u5C42\u3002\n const restart = useRestart()\n /**\n * \u516D\u680F\u5404\u81EA\u7684\u5F00\u5173\u72B6\u6001\uFF08\u603B\u5F00\u5173 + \u680F\u5F00\u5173\uFF09\uFF0C\u516D\u5F20\u5361\u7684\u6807\u9898\u884C\u4E0E\u5185\u5BB9\u90FD\u8BFB\u5B83\u3002\n *\n * \u5355\u9879\u90FD\u8D70 `activeSections` \u800C\u4E0D\u662F\u5728\u8FD9\u91CC\u5404\u5199\u4E00\u904D `settings.enabled && \u2026`\uFF1A\n * \u6F0F\u6389\u603B\u95F8\u662F\u8FD9\u5957\u4E24\u5C42\u7EA7\u5F00\u5173\u6700\u5BB9\u6613\u72AF\u7684\u9519\uFF0C\u5224\u636E\u53EA\u80FD\u6709\u4E00\u5904\u3002\n */\n const sections = activeSections(settings)\n\n const setKey = (side: 'send' | 'newline', chord: string): void => {\n const other = side === 'send' ? settings.newlineKey : settings.sendKey\n if (chord !== '' && chord === other) {\n setConflict(chord)\n return\n }\n setConflict(null)\n actions.setField(side === 'send' ? 'sendKey' : 'newlineKey', chord)\n }\n\n const conflictHint = conflict !== null\n ? `\u300C${displayChord(conflict)}\u300D\u5DF2\u88AB\u53E6\u4E00\u4FA7\u5360\u7528\uFF0C\u8BF7\u5148\u4E3A\u53E6\u4E00\u4FA7\u9009\u62E9\u5176\u5B83\u6309\u952E\u3002`\n : null\n\n const menuEnabled = MENU_ITEMS.filter(item => settings[item.field]).length\n const keySummary = `\u53D1\u9001 ${displayChord(settings.sendKey)} \u00B7 \u6362\u884C ${displayChord(settings.newlineKey)}`\n // \u4E09\u6863\u5404\u81EA\u7684\u6458\u8981\uFF1A\u4E00\u773C\u770B\u51FA\u53F3\u952E\u4F1A\u5F39\u54EA\u4E00\u79CD\u83DC\u5355\uFF0C\u4EE5\u53CA\u81EA\u5B9A\u4E49\u6863\u5F53\u524D\u5F00\u4E86\u51E0\u9879\u3002\n const menuSummary = settings.menuMode === 'official'\n ? '\u5F53\u524D\uFF1A\u5B98\u65B9\u4E0D\u4ECB\u5165'\n : settings.menuMode === 'browser'\n ? '\u5F53\u524D\uFF1A\u6D4F\u89C8\u5668\u83DC\u5355\uFF08\u7C98\u8D34\u514D\u6388\u6743\uFF09'\n : `\u5F53\u524D\uFF1A\u81EA\u5B9A\u4E49\u83DC\u5355 \u00B7 ${menuEnabled} / ${MENU_ITEMS.length} \u9879\u5F00\u542F`\n const panelSummary = `\u8FB9\u7F18\u7F29\u653E ${settings.panelResize ? '\u5F00' : '\u5173'}`\n + ` \u00B7 ${settings.panelWidth}\u00D7${settings.panelHeight}`\n // \u8BF7\u6C42\u5934\u680F\u76EE\u7684\u6982\u89C8\u76F4\u63A5\u590D\u7528\u5BBF\u4E3B\u534A\u5199\u56DE\u6765\u7684\u6267\u884C\u7ED3\u679C\uFF08'\u5DF2\u5199\u5165 opencode-go' \u8FD9\u7C7B\uFF09\u3002\n const headerSummary = settings.headerEnabled\n ? (settings.headerStatus === '' ? '\u5DF2\u542F\u7528' : settings.headerStatus)\n : '\u672A\u542F\u7528'\n const quickCounts = bookCounts(book)\n const quickSummary = `${quickCounts.categories} \u4E2A\u5206\u7C7B \u00B7 ${quickCounts.prompts} \u6761`\n + ` \u00B7 \u6BCF\u6B21 ${quickCounts.always} \u00B7 \u4EC5\u9996\u6B21 ${quickCounts.first}`\n + ` \u00B7 \u4F18\u5316\u6863\u4F4D ${OPTIMIZER_TIERS.find(item => item.id === settings.optimizerTier)?.label ?? '\u9AD8\u7EA7'}`\n const headerStatusText = settings.headerEnabled\n ? (settings.headerStatus === '' ? '\u7B49\u5F85\u9996\u6B21\u5199\u5165\u2026' : settings.headerStatus)\n : '\u672A\u542F\u7528\uFF08\u6253\u5F00\u4E0A\u65B9\u5F00\u5173\u5373\u5199\u5165\uFF09'\n // \u7EC8\u7AEF\u5361\u7247\u7684\u6982\u89C8\uFF1A\u76F4\u63A5\u590D\u7528\u5BBF\u4E3B\u534A\u5199\u56DE\u6765\u7684\u72B6\u6001\uFF08'\u5DF2\u751F\u6548\uFF1A\u2026' / '\u6CA1\u627E\u5230\u53EF\u7528\u7684 bash' \u8FD9\u7C7B\uFF09\u3002\n // \u300C\u8FD9\u4E00\u680F\u6CA1\u542F\u7528\u300D\u4F18\u5148\u4E8E\u5BBF\u4E3B\u534A\u7684\u72B6\u6001 \u2014\u2014 \u6CA1\u5F00\u7684\u65F6\u5019\u72B6\u6001\u884C\u5199\u7684\u662F\"\u672A\u542F\u7528\"\uFF0C\u4F46\u90A3\u53E5\u8BDD\u5728\u6982\u89C8\u91CC\n // \u4E0D\u5982\u300C\u672A\u542F\u7528\u300D\u56DB\u4E2A\u5B57\u76F4\u767D\uFF08FoldCard \u4F1A\u518D\u52A0\u4E00\u6B21\u524D\u7F00\uFF0C\u6240\u4EE5\u8FD9\u91CC\u53EA\u7ED9\u88AB\u5173\u6389\u65F6\u7684\u6863\u4F4D\u63CF\u8FF0\uFF09\u3002\n const terminalSummary = sections.terminal === false\n ? (settings.terminalMode === 'pwsh' ? '\u4FDD\u6301 PowerShell' : '\u6253\u5F00\u540E\u63A5\u7BA1\u7EC8\u7AEF')\n : settings.terminalEffective === 'unsupported'\n ? '\u975E Windows\uFF1A\u4E0D\u9700\u8981'\n : settings.terminalMode === 'pwsh'\n ? '\u5F53\u524D\uFF1A\u4FDD\u6301 PowerShell'\n : (settings.terminalEffective === 'bash' ? '\u5F53\u524D\uFF1AGit Bash' : '\u5F53\u524D\uFF1APowerShell\uFF08\u672A\u63A5\u7BA1\uFF09')\n\n return (\n <div style={{ padding: '4px 2px' }}>\n {/* \u9876\u90E8\u5E38\u663E\u533A\uFF1A\u4E2D\u6587\u540D + \u5185\u5D4C\u82F1\u6587\u5305\u540D\u7684\u4E00\u884C\u63CF\u8FF0 + \u603B\u5F00\u5173\u3002 */}\n <section className=\"dsh-ux-card\">\n <div className=\"dsh-ux-cardHeaderStatic\">\n <span className=\"dsh-ux-cardHeadText\">\n <h2 className=\"dsh-ux-cardName\">\u8F93\u5165\u4F53\u9A8C</h2>\n <p className=\"dsh-ux-cardDescription\">\n dsh-composer-ux \u00B7 \u4E3B\u804A\u5929\u8F93\u5165\u6846\u7684\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u4E0E\u8BBE\u7F6E\u9762\u677F\uFF1B\u8BBE\u7F6E\u5373\u65F6\u751F\u6548\u5E76\u6301\u4E45\u4FDD\u5B58\u3002\n </p>\n </span>\n {/*\n \u300C\u91CD\u542F DSH\u300D\u653E\u5728\u62AC\u5934\u53F3\u7AEF\u3001GitHub \u94FE\u63A5\u5DE6\u8FB9\uFF1A\u8FD9\u662F\u8BBE\u7F6E\u9875\u7B2C\u4E00\u773C\u5C31\u626B\u5230\u7684\u4F4D\u7F6E\uFF0C\n \u800C\u5B83\u8981\u89E3\u51B3\u7684\u95EE\u9898\uFF08\u5BBF\u4E3B\u534A\u6539\u4E86\u8981\u91CD\u542F\u624D\u751F\u6548\uFF09\u6070\u597D\u662F\u7528\u6237\u70B9\u8FDB\u8BBE\u7F6E\u9875\u65F6\u6700\u60F3\u505A\u7684\u4E8B\u3002\n \u786E\u8BA4\u6761\u5728\u62AC\u5934\u6B63\u4E0B\u65B9\uFF08\u89C1\u4E0B\u9762\u7684 RestartBanner\uFF09\uFF0C\u8DDF\u5E02\u573A\u7684\u300C\u5F85\u91CD\u542F\u300D\u6A2A\u5E45\u540C\u4E00\u4E2A\u4F4D\u7F6E\u3002\n */}\n <span className=\"dsh-ux-cardActions\">\n {/*\n \u987A\u5E8F\uFF1A\u5237\u65B0 \u2192 \u91CD\u542F \u2192 GitHub\u3002\u8F7B\u7684\u5728\u524D\u3001\u91CD\u7684\u5728\u540E\uFF08\u5237\u65B0\u53EA\u9700\u91CD\u65B0\u52A0\u8F7D\u9875\u9762\uFF0C\n \u91CD\u542F\u4F1A\u771F\u7684\u6362\u6389\u5BBF\u4E3B\u8FDB\u7A0B\uFF09\uFF0C\u4E0E\u4E24\u679A\u6309\u94AE\u5404\u81EA\u7684\u98CE\u9669\u4E00\u81F4\u3002\n \u91CD\u542F\u5728\u786E\u8BA4\u4E2D / \u91CD\u542F\u4E2D\u65F6\u5237\u65B0\u4E00\u8D77\u7981\u7528\uFF1A\u90A3\u65F6\u7528\u6237\u624B\u4E0A\u6709\u4E00\u4EF6\u672A\u51B3\u7684\u4E8B\uFF0C\n \u5237\u65B0\u4F1A\u628A\u5B83\u8FDE\u540C\u786E\u8BA4\u6761\u4E00\u8D77\u51B2\u6389\u3002\n */}\n <RefreshButton busy={restart.stage === 'restarting' || restart.stage === 'asking'} />\n <RestartButton restart={restart} />\n {/*\n \u4ED3\u5E93\u5165\u53E3\uFF1A\u7528\u771F\u5B9E\u7684 <a>\uFF08\u65B0\u6807\u7B7E\u6253\u5F00\u3001\u4E0D\u5E26 referrer\uFF09\uFF0C\u5730\u5740\u6765\u81EA\u5951\u7EA6\u91CC\u7684 REPO_URL \u2014\u2014\n \u5BA2\u6237\u7AEF\u4E0D\u8BB8\u786C\u7F16\u7801\u7B2C\u4E8C\u4EFD\u5730\u5740\uFF0C\u5426\u5219\u6539\u4E86\u4ED3\u5E93\u4E24\u5904\u4F1A\u5206\u53C9\uFF08\u6709\u6D4B\u8BD5\u76EF\u7740\uFF09\u3002\n */}\n <a\n className=\"dsh-ux-cardLink\"\n href={REPO_URL}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n title=\"\u5728 GitHub \u4E0A\u67E5\u770B\u8FD9\u4E2A\u63D2\u4EF6\uFF08\u65B0\u6807\u7B7E\u6253\u5F00\uFF09\"\n >\n GitHub <span aria-hidden=\"true\">\u2197</span>\n </a>\n </span>\n </div>\n <RestartBanner restart={restart} />\n {/*\n \u5199\u5165\u5931\u8D25 / \u5199\u4E86\u4F46\u6CA1\u751F\u6548\u7684\u8BF4\u660E\u6761\uFF1A\u4E0E\u300C\u91CD\u542F DSH\u300D\u6A2A\u5E45\u540C\u4E00\u4E2A\u4F4D\u7F6E\u3001\u540C\u4E00\u5957\u6837\u5F0F\u3002\n \u4E3A\u4EC0\u4E48\u503C\u5F97\u5360\u8FD9\u4E2A\u4F4D\u7F6E\uFF1A2026-09-23 \u7684\u771F\u673A\u4E8B\u6545\u91CC\uFF0C\u8BBE\u7F6E\u5199\u5165\u88AB\u4E00\u628A\u5B64\u513F\u5199\u5165\u9501\u6321\u4F4F\uFF0C\n \u7528\u6237\u770B\u5230\u7684\u53EA\u6709\"\u5F00\u5173\u4E0D\u52A8\"\uFF0C**\u4E00\u53E5\u63D0\u793A\u90FD\u6CA1\u6709**\uFF0C\u6392\u67E5\u53EA\u80FD\u9760\u7FFB\u5BBF\u4E3B\u65E5\u5FD7\u3002\n \u6240\u4EE5\u8FD9\u6761\u6A2A\u5E45\u7684\u4F5C\u7528\u662F\u8BA9\u4E0B\u4E00\u6B21\u540C\u7C7B\u6545\u969C\u5F53\u573A\u8BF4\u5F97\u51FA\u8BDD\uFF08\u5224\u636E\u89C1 client.tsx \u7684 setField\uFF09\u3002\n */}\n {writeNotice !== '' && (\n <div className=\"dsh-ux-restartBanner dsh-ux-restartBannerFailed\" role=\"status\">\n <span className=\"dsh-ux-restartBannerText\">\u8BBE\u7F6E\u672A\u751F\u6548\uFF1A{writeNotice}</span>\n <span className=\"dsh-ux-restartBannerActions\">\n <button type=\"button\" className=\"dsh-ux-restartCancel\" onClick={() => { actions.dismissNotice() }}>\n \u77E5\u9053\u4E86\n </button>\n </span>\n </div>\n )}\n <div className=\"dsh-ux-cardBody\">\n <ToggleRow\n first\n label=\"\u542F\u7528\u8F93\u5165\u589E\u5F3A\"\n desc=\"\u5173\u95ED\u540E\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u4E0E\u8BBE\u7F6E\u9762\u677F\u6EDA\u52A8/\u7F29\u653E\u5168\u90E8\u505C\u7528\uFF08\u672C\u9875\u4FDD\u7559\u7528\u4E8E\u91CD\u65B0\u5F00\u542F\uFF09\"\n checked={settings.enabled}\n onChange={next => { actions.setField(ENABLED_FIELD, next) }}\n />\n {!settings.enabled && (\n <p style={hintInfo}>\n \u5DF2\u505C\u7528\uFF1A\u53D1\u9001/\u6362\u884C\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u3001\u8BBE\u7F6E\u9762\u677F\u6EDA\u52A8\u4E0E\u8FB9\u7F18\u7F29\u653E\u5747\u4E0D\u518D\u751F\u6548\uFF0C\u8F93\u5165\u6846\u6062\u590D DSH \u539F\u751F\u884C\u4E3A\u3002\n \u6253\u5F00\u4E0A\u65B9\u5F00\u5173\u5373\u53EF\u4E00\u952E\u6062\u590D\uFF1B\u6240\u6709\u8BBE\u7F6E\u503C\u4ECD\u4FDD\u7559\u3002\n </p>\n )}\n </div>\n </section>\n\n {settings.enabled && (<>\n <FoldCard\n name=\"\u952E\u4F4D\"\n summary={keySummary}\n toggle={{\n checked: sections.keys,\n onChange: next => { actions.setField(KEYS_ENABLED_FIELD, next) },\n }}\n >\n <p style={bodyLead}>\n \u652F\u6301\u5E38\u7528\u9884\u8BBE\uFF0C\u4E5F\u53EF\u4EE5\u70B9\u51FB\u300C\u81EA\u5B9A\u4E49\u2026\u300D\u540E\u76F4\u63A5\u6309\u4E0B\u4EFB\u610F\u7EC4\u5408\u952E\u5F55\u5236\uFF08Esc \u53D6\u6D88\uFF0CBackspace \u6E05\u9664\uFF09\u3002\n \u672A\u7ED1\u5B9A\u7684 Enter \u7CFB\u6309\u952E\u4E0D\u4F1A\u89E6\u53D1\u53D1\u9001\u6216\u6362\u884C\uFF1BCtrl+Enter / \u2318+Enter \u672A\u88AB\u7ED1\u5B9A\u65F6\u4FDD\u7559\u539F\u300C\u52A0\u901F\u63D0\u4EA4\u300D\u884C\u4E3A\uFF1B\n \u4E2D\u6587\u8F93\u5165\u6CD5\u7EC4\u5408\u671F\u95F4\u4E0D\u53D7\u5F71\u54CD\u3002\n </p>\n <KeyRow\n first\n title=\"\u53D1\u9001\u952E\"\n desc=\"\u6309\u4E0B\u540E\u53D1\u9001\u5F53\u524D\u8F93\u5165\"\n value={settings.sendKey}\n presets={SEND_PRESETS}\n conflict={chord => chord !== '' && chord === settings.newlineKey}\n onChange={chord => { setKey('send', chord) }}\n />\n <KeyRow\n title=\"\u6362\u884C\u952E\"\n desc=\"\u6309\u4E0B\u540E\u5728\u8F93\u5165\u5185\u6362\u884C\"\n value={settings.newlineKey}\n presets={NEWLINE_PRESETS}\n conflict={chord => chord !== '' && chord === settings.sendKey}\n onChange={chord => { setKey('newline', chord) }}\n />\n {conflictHint !== null && <p style={hintError}>{conflictHint}</p>}\n <div style={{ marginTop: 10 }}>\n <button\n type=\"button\"\n style={pill}\n onClick={() => { setConflict(null); actions.resetAll() }}\n >\n \u6062\u590D\u9ED8\u8BA4\n </button>\n </div>\n </FoldCard>\n\n {/*\n \u4E09\u6863\u8BF4\u660E\u4E0E\u90A3 7 \u4E2A\u6761\u76EE\u5F00\u5173**\u90FD\u5728\u5361\u5185**\uFF0C\u4E14\u6309\u5F53\u524D\u6863\u4F4D\u53EA\u663E\u793A\u76F8\u5173\u7684\u90A3\u90E8\u5206\n \uFF08\u7528\u6237\u8981\u6C42\uFF1A\u70B9\u5B98\u65B9\u770B\u5B98\u65B9\u7684\u3001\u70B9\u6D4F\u89C8\u5668\u770B\u6D4F\u89C8\u5668\u7684\u3001\u70B9\u81EA\u5B9A\u4E49\u770B\u81EA\u5B9A\u4E49\u7684\uFF09\u3002\n 0.5.0 \u5148\u505A\u7684\u662F\u300C7 \u9879\u5F00\u5173\u642C\u5230\u6807\u9898\u884C\u7684\u300E7 \u9879 \u25BC\u300F\u6761\u300D\uFF0C\u7528\u6237\u770B\u8FC7\u771F\u5B9E\u754C\u9762\u540E\u6539\u56DE\u5361\u5185\uFF1A\n \u90A3 7 \u9879\u672C\u6765\u5C31\u53EA\u5BF9\u300C\u81EA\u5B9A\u4E49\u300D\u6863\u6709\u610F\u4E49\uFF0C\u6446\u5728\u6807\u9898\u884C\u7B49\u4E8E\u5728\u4EFB\u4F55\u6863\u4F4D\u90FD\u80FD\u6539\u4E00\u5806\u5F53\u65F6\u4E0D\u751F\u6548\u7684\u4E1C\u897F\u3002\n */}\n <FoldCard\n name=\"\u53F3\u952E\u83DC\u5355\"\n summary={menuSummary}\n toggle={{\n checked: sections.menu,\n onChange: next => { actions.setField(MENU_ENABLED_FIELD, next) },\n }}\n >\n <p style={bodyLead}>\n \u53F3\u952E\u70B9\u51FB\u8F93\u5165\u6846\u65F6\u5F39\u51FA\u54EA\u4E00\u79CD\u83DC\u5355\u3002\u53EA\u5F71\u54CD\u53F3\u952E\uFF0C\u4E0D\u5F71\u54CD\u952E\u4F4D\u4E0E\u5176\u5B83\u529F\u80FD\u3002\n </p>\n <div style={{ ...row, borderTop: 'none', flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>\u83DC\u5355\u6765\u6E90</div>\n </div>\n <PillChoice\n items={MENU_MODES}\n value={settings.menuMode}\n onChange={mode => { actions.setField(MENU_MODE_FIELD, mode) }}\n ariaLabel=\"\u53F3\u952E\u83DC\u5355\u6765\u6E90\"\n />\n </div>\n {settings.menuMode === 'official' && (\n <p style={hintInfo}>\n <strong>\u5B98\u65B9</strong>\uFF1A\u672C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u4ECB\u5165\uFF0CDSH \u4E0E\u5176\u5B83\u63D2\u4EF6\u81EA\u5DF1\u7684\u53F3\u952E\u5904\u7406\u539F\u6837\u751F\u6548\n \uFF08DSH \u5B98\u65B9\u8F93\u5165\u6846\u672C\u8EAB\u6CA1\u6709\u53F3\u952E\u83DC\u5355\uFF0C\u6240\u4EE5\u901A\u5E38\u770B\u5230\u7684\u5C31\u662F\u6D4F\u89C8\u5668\u7684\u83DC\u5355\uFF09\u3002\n </p>\n )}\n {settings.menuMode === 'browser' && (\n <p style={hintInfo}>\n <strong>\u6D4F\u89C8\u5668</strong>\uFF1A\u56FA\u5B9A\u7528\u6D4F\u89C8\u5668\u81EA\u5E26\u7684\u83DC\u5355\uFF08\u6837\u5B50\u968F\u6D4F\u89C8\u5668\u800C\u53D8\uFF09\uFF0C\u5E76\u5728\u672C\u63D2\u4EF6\u8FD9\u4E00\u5C42\n \u6321\u4F4F\u5176\u5B83\u63D2\u4EF6\u7684\u83DC\u5355\uFF1B\u597D\u5904\u662F\u7C98\u8D34\u514D\u6388\u6743\u3001\u96F6\u914D\u7F6E\u3002\n </p>\n )}\n {settings.menuMode === 'custom' && (\n <>\n <p style={hintInfo}>\n <strong>\u81EA\u5B9A\u4E49</strong>\uFF1A\u7528\u672C\u63D2\u4EF6\u56FA\u5B9A\u6837\u5F0F\u7684\u83DC\u5355\uFF08\u672A\u9009\u4E2D\u6587\u672C\u65F6\u300C\u526A\u5207 / \u590D\u5236 / \u5220\u9664\u300D\u7F6E\u7070\uFF09\u3002\n \u8FD9\u4E00\u6863\u7684\u300C\u7C98\u8D34\u300D\u8981\u8BFB\u526A\u8D34\u677F\uFF0C\u6D4F\u89C8\u5668\u4F1A\u5148\u8981\u4E00\u6B21\u6388\u6743\u2014\u2014\u4E09\u5BB6\u6D4F\u89C8\u5668\u7684\u5904\u7406\u4E0D\u4E00\u6837\uFF1A\n </p>\n <p style={hintInfo}>\n \u00B7 Chrome / Edge\uFF08\u8C37\u6B4C / \u5FAE\u8F6F\u6D4F\u89C8\u5668\uFF09\uFF1A\u5F39\u51FA\u540E\u70B9\u300C\u5141\u8BB8\u300D\u5373\u53EF\uFF0C\u4E4B\u540E\u4F1A\u8BB0\u4F4F\u8FD9\u4E2A\u7AD9\u70B9\u3001\u4E0D\u518D\u95EE\u3002\n \u8981\u6539\u6216\u64A4\u9500\u6388\u6743\uFF1A\u70B9\u5730\u5740\u680F\u6700\u5DE6\u8FB9\u7684\u7F51\u7AD9\u56FE\u6807 \u2192 \u7F51\u7AD9\u8BBE\u7F6E\uFF08Edge \u53EB\u300C\u6B64\u7AD9\u70B9\u7684\u6743\u9650\u300D\uFF09\u2192 \u526A\u8D34\u677F\uFF1B\n \u4E5F\u53EF\u4EE5\u76F4\u63A5\u5728\u5730\u5740\u680F\u8F93\u5165 chrome://settings/content/clipboard\uFF08Edge \u8F93\u5165\n edge://settings/content/clipboard\uFF09\u3002\n </p>\n <p style={hintInfo}>\n \u00B7 Firefox\uFF1A\u4E0D\u5141\u8BB8\u7F51\u9875\u9759\u9ED8\u8BFB\u526A\u8D34\u677F\u2014\u2014\u4F60\u70B9\u672C\u63D2\u4EF6\u7684\u300C\u7C98\u8D34\u300D\u540E\uFF0C\u5B83\u4F1A\u5148\u5F39\u4E00\u4E2A\u53EA\u6709\u300C\u7C98\u8D34(P)\u300D\n \u4E00\u9879\u7684\u5C0F\u7A97\uFF08\u7EA6 1 \u79D2\u540E\u624D\u53EF\u70B9\uFF09\uFF0C\u70B9\u5B83\u624D\u5B8C\u6210\u8FD9\u6B21\u7C98\u8D34\u3002\u8FD9\u662F Firefox \u7684\u5B89\u5168\u673A\u5236\uFF0C\u63D2\u4EF6\u5173\u4E0D\u6389\n \uFF08\u5B9E\u6D4B\uFF1Aabout:config \u91CC\u7684\u526A\u8D34\u677F\u9996\u9009\u9879\u5BF9\u5B83\u65E0\u6548\uFF09\u3002\u4E0D\u60F3\u591A\u8FD9\u4E00\u6B65\u5C31\u76F4\u63A5\u6309 Ctrl+V\uFF0C\n \u6216\u628A\u4E0A\u9762\u7684\u300C\u83DC\u5355\u6765\u6E90\u300D\u6362\u6210\u300C\u6D4F\u89C8\u5668 / \u5B98\u65B9\u300D\u6863\u2014\u2014\u90A3\u4E24\u6863\u7528\u7684\u662F\u6D4F\u89C8\u5668\u81EA\u5DF1\u7684\u7C98\u8D34\u3002\n </p>\n <p style={hintInfo}>\n \u6CE8\u610F\uFF1Achrome://\u3001edge:// \u8FD9\u4E9B\u5730\u5740\u6D4F\u89C8\u5668\u4E0D\u5141\u8BB8\u505A\u6210\u7F51\u9875\u91CC\u7684\u94FE\u63A5\uFF0C\u53EA\u80FD\u624B\u8F93\uFF0C\n \u6216\u590D\u5236\u4E0A\u9762\u90A3\u4E32\u7C98\u8D34\u5230\u5730\u5740\u680F\u3002\n </p>\n <div style={{ ...row, flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>\u83DC\u5355\u6761\u76EE</div>\n <div style={rowDesc}>\u8FD9 7 \u4E2A\u5F00\u5173\u51B3\u5B9A\u81EA\u5B9A\u4E49\u83DC\u5355\u91CC\u51FA\u73B0\u54EA\u4E9B\u6761\u76EE\uFF0C\u5173\u6389\u7684\u4E0D\u663E\u793A\u3002</div>\n </div>\n </div>\n {MENU_ITEMS.map((item, index) => (\n <ToggleRow\n key={item.field}\n first={index === 0}\n label={item.label}\n desc={item.shortcut !== '' ? `\u5FEB\u6377\u952E ${item.shortcut}` : ''}\n checked={settings[item.field]}\n onChange={next => { actions.setField(item.field as MenuField, next) }}\n />\n ))}\n <div style={{ padding: '8px 0 2px' }}>\n <button\n type=\"button\"\n style={pill}\n onClick={() => { for (const item of MENU_ITEMS) actions.setField(item.field as MenuField, true) }}\n >\n \u5168\u90E8\u5F00\u542F\n </button>\n </div>\n </>\n )}\n </FoldCard>\n\n <FoldCard\n name=\"\u5FEB\u6377\u6307\u4EE4\"\n summary={quickSummary}\n toggle={{\n checked: sections.quick,\n onChange: next => { actions.setField(QUICK_ENABLED_FIELD, next) },\n }}\n >\n <p style={bodyLead}>\n \u8F93\u5165\u6846\u5DE5\u5177\u884C\u91CC\u90A3\u4E2A\u300C\u5FEB\u6377\u6307\u4EE4\u300D\u6309\u94AE\u70B9\u5F00\u5C31\u662F\u8FD9\u5F20\u6E05\u5355\uFF1A\u70B9\u6761\u76EE\u628A\u5185\u5BB9\u63D2\u5165\u8F93\u5165\u6846\u3002\n \u6BCF\u6761\u53F3\u4FA7\u7684\u4E09\u9009\u4E00\u51B3\u5B9A<strong>\u53D1\u9001\u65F6\u600E\u4E48\u9644\u52A0</strong>\uFF1A\n \u300C\u5173\u300D= \u53EA\u63D2\u5165\u4E0D\u9644\u52A0\uFF1B\u300C\u6BCF\u6B21\u300D= \u6BCF\u6B21\u53D1\u9001\u90FD\u9644\u52A0\u5230\u6D88\u606F<strong>\u672B\u5C3E</strong>\uFF1B\n \u300C\u4EC5\u9996\u6B21\u300D= \u53EA\u5728<strong>\u8FD9\u4E2A\u4F1A\u8BDD\u7684\u7B2C\u4E00\u6761\u6D88\u606F</strong>\u4E0A\u9644\u52A0\uFF08\u4E4B\u540E\u4E0D\u518D\u9644\u52A0\uFF0C\u5237\u65B0\u9875\u9762\u4E5F\u4E0D\u4F1A\u91CD\u590D\uFF09\u3002\n \u591A\u6761\u6309\u5217\u8868\u987A\u5E8F\u62FC\u63A5\uFF0C\u8F93\u5165\u6846\u91CC\u4E0D\u63D0\u524D\u663E\u793A\u3002\n \u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\u4F1A\u7528\u53E6\u4E00\u4E2A AI \u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u6574\u7406\u6210\u4E00\u6761\u80FD\u76F4\u63A5\u53D1\u51FA\u53BB\u7684\u6E05\u6670\u6307\u4EE4\uFF0C\n \u7ED3\u679C\u76F4\u63A5\u5199\u56DE\u8F93\u5165\u6846\uFF08Ctrl+Z \u53EF\u8FD8\u539F\uFF09\u2014\u2014\u4E0D\u4F1A\u6C61\u67D3\u5F53\u524D\u5BF9\u8BDD\uFF0C\u4E5F\u4E0D\u5360\u4F60\u7684\u5BF9\u8BDD\u8F6E\u6B21\u3002\n 0.6.0 \u8D77\u5B83\u4E0D\u518D\"\u81EA\u7531\u6539\u5199\"\uFF1A\u5B83\u53EA\u80FD\u4EA7\u51FA<strong>\u80FD\u6307\u56DE\u4F60\u539F\u8BDD\u67D0\u4E00\u53E5\u8BDD</strong>\u7684\u6761\u76EE\uFF0C\n \u5BBF\u4E3B\u9010\u6761\u505A\u5B57\u9762\u6BD4\u5BF9\uFF0C\u5BF9\u4E0D\u4E0A\u5C31\u4E22\u6389\u90A3\u4E00\u6761\u5E76\u5728\u72B6\u6001\u884C\u91CC\u8BB0\u8D26 \u2014\u2014\n \u6240\u4EE5\"\u66FF\u4F60\u53D1\u660E\u4E00\u6761\u4F60\u6CA1\u8BF4\u8FC7\u7684\u9700\u6C42\"\u5728\u7ED3\u6784\u4E0A\u505A\u4E0D\u5230\u3002\u4E0B\u9762\u53EF\u4EE5\u6539\u6BCF\u4E00\u6863\u7528\u7684\u63D0\u793A\u8BCD\u3002\n </p>\n <div style={{ ...row, borderTop: 'none', flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>\u4F18\u5316\u5F3A\u5EA6</div>\n <div style={rowDesc}>\n {OPTIMIZER_TIERS.find(item => item.id === settings.optimizerTier)?.hint ?? ''}\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>\n {OPTIMIZER_TIERS.map(item => (\n <button\n key={item.id}\n type=\"button\"\n title={item.hint}\n style={settings.optimizerTier === item.id ? pillActive : pill}\n onClick={() => { actions.setField(OPTIMIZER_TIER_FIELD, item.id as OptimizerTier) }}\n >\n {item.label}\n </button>\n ))}\n </div>\n </div>\n <OptimizerPromptEditor\n tier={settings.optimizerTier}\n value={settings[optimizerPromptFieldOf(settings.optimizerTier) as keyof ComposerUxSettings] as string}\n onChange={next => { actions.setField(optimizerPromptFieldOf(settings.optimizerTier) as SettingsField, next) }}\n />\n <div style={{ ...row, borderTop: 'none', flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>\u5FEB\u6377\u6307\u4EE4\u6E05\u5355</div>\n <div style={rowDesc}>\n \u5206\u7C7B\u5728\u8FD9\u91CC\u7BA1\u7406\uFF08\u9762\u677F\u91CC\u53EA\u505A\u5207\u6362\uFF09\uFF1B\u5185\u7F6E 9 \u6761\u53EF\u4EE5\u76F4\u63A5\u7528\uFF0C\u6539\u5B8C\u8BB0\u5F97\u70B9\u300C\u4FDD\u5B58\u4FEE\u6539\u300D\u3002\n </div>\n </div>\n <QuickPromptsEditor\n book={book}\n status={bookStatus}\n onSave={next => { actions.saveBook(next) }}\n onReload={() => { actions.reloadBook() }}\n onReset={() => { actions.resetBook() }}\n />\n </div>\n </FoldCard>\n\n <FoldCard\n name=\"\u8BBE\u7F6E\u9762\u677F\"\n summary={panelSummary}\n toggle={{\n checked: sections.panel,\n onChange: next => { actions.setField(PANEL_ENABLED_FIELD, next) },\n }}\n // \u53EA\u7559\u300C\u8FB9\u7F18\u7F29\u653E\u300D\uFF1A\u5BFC\u822A\u6EDA\u52A8\u5DF2\u7531 DSH 0.1.7 \u5B98\u65B9\u8BBE\u7F6E\u9875\u81EA\u5E26\uFF0C\u672C\u63D2\u4EF6\u4E0D\u518D\u63D0\u4F9B\u90A3\u4E2A\u5F00\u5173\u3002\n controls={(\n <MiniToggle\n label=\"\u8FB9\u7F18\u7F29\u653E\"\n checked={settings.panelResize}\n onChange={next => { actions.setField(PANEL_RESIZE_FIELD, next) }}\n />\n )}\n >\n <p style={bodyLead}>\n \u5BFC\u822A\u5217\u7684\u6EDA\u52A8\u7531 DSH \u5B98\u65B9\u7684\u8BBE\u7F6E\u9875\u81EA\u5DF1\u8D1F\u8D23\uFF0C\u672C\u63D2\u4EF6\u4E0D\u518D\u4ECB\u5165\u3002\n \u5F00\u542F\u300C\u8FB9\u7F18\u8C03\u6574\u5927\u5C0F\u300D\u540E\uFF0C\u628A\u9F20\u6807\u79FB\u5230\u8BBE\u7F6E\u9762\u677F\u7684\u8FB9\u6216\u89D2\u4E0A\uFF08\u51FA\u73B0\u9AD8\u4EAE\u6216\u5149\u6807\u53D8\u5316\uFF09\u62D6\u52A8\u5373\u53EF\u6539\u53D8\u9762\u677F\u5927\u5C0F\uFF0C\n \u5C3A\u5BF8\u4F1A\u8BB0\u4F4F\uFF0C\u4E0B\u6B21\u6253\u5F00\u4FDD\u6301\u3002\uFF08\u8FD9\u4E2A\u5F00\u5173\u5728\u6807\u9898\u884C\u4E0A\u3002\uFF09\n </p>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', marginTop: 10 }}>\n <span style={rowDesc}>\u5C3A\u5BF8\u9884\u8BBE\uFF1A</span>\n <button\n type=\"button\"\n style={pill}\n onClick={() => { actions.clearField(PANEL_WIDTH_FIELD); actions.clearField(PANEL_HEIGHT_FIELD) }}\n >\n \u9ED8\u8BA4\uFF08800\uFF09\n </button>\n <button\n type=\"button\"\n style={settings.panelWidth === 640 && settings.panelHeight === 600 ? pillActive : pill}\n onClick={() => {\n actions.setField(PANEL_WIDTH_FIELD, 640)\n actions.setField(PANEL_HEIGHT_FIELD, 600)\n }}\n >\n \u7D27\u51D1\uFF08640\u00D7600\uFF09\n </button>\n <button\n type=\"button\"\n style={settings.panelWidth === 1040 && settings.panelHeight === 760 ? pillActive : pill}\n onClick={() => {\n actions.setField(PANEL_WIDTH_FIELD, 1040)\n actions.setField(PANEL_HEIGHT_FIELD, 760)\n }}\n >\n \u5BBD\u655E\uFF081040\u00D7760\uFF09\n </button>\n </div>\n </FoldCard>\n\n <FoldCard\n name=\"OpenCode \u8BF7\u6C42\u5934\"\n summary={headerSummary}\n // \u8FD9\u4E00\u680F\u6CA1\u6709\u65B0\u952E\uFF1A\u539F\u6765\u7684\u300C\u9644\u52A0\u8BF7\u6C42\u5934\u300D\u672C\u6765\u5C31\u662F\"\u8FD9\u4E00\u680F\u8981\u4E0D\u8981\u751F\u6548\"\uFF0C\u76F4\u63A5\u5F53\u5361\u7EA7\u5F00\u5173\u3002\n toggle={{\n checked: sections.header,\n onChange: next => { actions.setField(HEADER_ENABLED_FIELD, next) },\n }}\n >\n {/* \u7528\u6237\u5B9E\u6D4B\u8E29\u8FC7\u7684\u5751\uFF0C\u653E\u533A\u5757\u6700\u524D\u9762\uFF1A\u8FD9\u4E00\u680F\u662F\u4E3A\u4E86 OpenCode \u7684 API \u5730\u5740\u670D\u52A1\u7684\uFF0C\n \u7528 DSH \u81EA\u5E26\u7684\u5730\u5740\u914D\u7F6E\u53D1\u56FE\u7247\u4F1A\u62A5\u9519\u3002 */}\n <p style={hintError}>\n \u26A0\uFE0F \u8BF7\u4F7F\u7528\u81EA\u5B9A\u4E49\u7684 OpenCode API \u5730\u5740\uFF0C\u4E0D\u8981\u7528 DSH \u81EA\u5E26\u7684 API \u5730\u5740\u914D\u7F6E\uFF1A\n \u7528\u81EA\u5E26\u7684\u914D\u7F6E\u65E0\u6CD5\u4E0A\u4F20\u56FE\u7247\uFF0C\u4E00\u65E6\u53D1\u9001\u56FE\u7247\u5C31\u4F1A\u62A5\u9519\u3002\n </p>\n <p style={bodyLead}>\n OpenCode \u7684\u63A5\u53E3\u8981\u6C42\u5BA2\u6237\u7AEF\u6BCF\u6B21\u8BF7\u6C42\u90FD\u5E26\u4E0A\u4E00\u4E2A\u7A33\u5B9A\u7684\u4F1A\u8BDD ID \u8BF7\u6C42\u5934\uFF08\u5B98\u65B9 Go \u6587\u6863\n \u300C\u53EF\u4EE5\u5728\u54EA\u91CC\u4F7F\u7528\uFF1F\u300D\u7B2C 3 \u6761\uFF1A\u4E3A\u6BCF\u6BB5\u5BF9\u8BDD\u5728 x-opencode-session \u4E2D\u53D1\u9001\u4F1A\u8BDD ID\uFF0C\n \u4EE5\u4FBF\u5176\u4F18\u5316\u8DEF\u7531\u4E0E\u63D0\u793A\u8BCD\u7F13\u5B58\uFF09\u3002DSH \u7684\u8BBE\u7F6E\u9875\u4E0D\u63D0\u4F9B\u8BF7\u6C42\u5934\u7F16\u8F91\u5668\uFF0C\u6240\u4EE5\u8FD9\u91CC\u76F4\u63A5\u628A\u5B83\u5199\u8FDB\n llm-pi-ai \u7684 provider \u914D\u7F6E\u2014\u2014\u4E0B\u4E00\u6B21\u6A21\u578B\u8BF7\u6C42\u5C31\u751F\u6548\uFF0C\u4E0D\u7528\u91CD\u542F\uFF0C\u4E5F\u4E0D\u7528\u624B\u5DE5\u6539 settings.yaml\u3002\n \u53EA\u5BF9 llm-pi-ai \u91CC\u300C\u5DF2\u5B58\u5728\u300D\u7684 opencode \u7CFB\u8DEF\u7531\u751F\u6548\uFF0C\u4E0D\u4F1A\u51ED\u7A7A\u65B0\u5EFA provider\uFF1B\n \u603B\u5F00\u5173\u5173\u95ED\u6216\u672C\u680F\u76EE\u505C\u7528\u65F6\uFF0C\u5199\u5165\u7684\u5934\u4F1A\u81EA\u52A8\u64A4\u9500\u3002\n </p>\n <TextFieldRow\n title=\"\u5934\u540D\"\n desc={`\u9ED8\u8BA4 ${DEFAULT_HEADER_NAME}\uFF08OpenCode \u5B98\u65B9\u8981\u6C42\u7684\u90A3\u4E00\u4E2A\uFF09`}\n value={settings.headerName}\n placeholder={DEFAULT_HEADER_NAME}\n maxLength={HEADER_NAME_MAX}\n onChange={next => { actions.setField(HEADER_NAME_FIELD, next) }}\n />\n <TextFieldRow\n title=\"\u503C\"\n desc=\"\u6240\u6709\u5BF9\u8BDD\u5171\u7528\u8FD9\u4E00\u4E2A\u503C\uFF1B\u7559\u7A7A\u65F6\u9996\u6B21\u542F\u7528\u4F1A\u81EA\u52A8\u751F\u6210\u4E00\u4E2A UUID \u5E76\u4FDD\u5B58\u6CBF\u7528\"\n value={settings.headerValue}\n placeholder=\"\u7559\u7A7A = \u81EA\u52A8\u751F\u6210\"\n maxLength={HEADER_VALUE_MAX}\n onChange={next => { actions.setField(HEADER_VALUE_FIELD, next) }}\n action={{\n label: '\u91CD\u65B0\u751F\u6210',\n onClick: () => { actions.setField(HEADER_VALUE_FIELD, newSessionId()) },\n }}\n />\n <TextFieldRow\n title=\"\u4F5C\u7528\u8DEF\u7531\"\n desc=\"\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u7559\u7A7A = \u81EA\u52A8\u5339\u914D OpenCode \u8DEF\u7531\uFF08\u540D\u5B57\u4EE5 opencode \u5F00\u5934\uFF0C\u6216 baseURL \u6307\u5411 opencode.ai\uFF09\"\n value={settings.headerRoutes}\n placeholder=\"\u7559\u7A7A = \u81EA\u52A8\uFF08opencode* \u6216 opencode.ai \u7AEF\u70B9\uFF09\"\n maxLength={HEADER_VALUE_MAX}\n onChange={next => { actions.setField(HEADER_ROUTES_FIELD, next) }}\n />\n <p style={hintInfo}>\u72B6\u6001\uFF1A{headerStatusText}</p>\n </FoldCard>\n\n <FoldCard\n name=\"\u9ED8\u8BA4\u7EC8\u7AEF\"\n summary={terminalSummary}\n toggle={{\n checked: sections.terminal,\n onChange: next => { actions.setField(TERMINAL_ENABLED_FIELD, next) },\n }}\n // \u4E09\u6863\u4ECE\u5185\u5BB9\u533A\u642C\u5230\u6807\u9898\u884C\uFF08\u5B83\u6BD4\u5F00\u5173\u66F4\u9002\u5408\u5F53\"\u8FD9\u4E00\u680F\u5F53\u524D\u662F\u4EC0\u4E48\u72B6\u6001\"\u7684\u5C55\u793A\uFF09\u3002\n controls={(\n <PillChoice\n compact\n items={TERMINAL_MODES}\n value={settings.terminalMode}\n onChange={mode => { actions.setField(TERMINAL_MODE_FIELD, mode) }}\n ariaLabel=\"\u7EC8\u7AEF\u5DE5\u5177\"\n />\n )}\n >\n <p style={bodyLead}>\n Windows \u4E0A DSH \u7ED9\u6A21\u578B\u7684\u7EC8\u7AEF\u5DE5\u5177\u662F PowerShell\uFF0C\u800C\u6A21\u578B\u5BF9 bash \u8BED\u6CD5\u7684\u628A\u63E1\u660E\u663E\u66F4\u597D\u3002\u8FD9\u4E00\u680F\u628A\u7EC8\u7AEF\n \u6362\u6210 Git Bash\uFF1A\u6A21\u578B\u770B\u5230\u7684\u5DE5\u5177\u5C31\u53EB bash\u3001PowerShell \u90A3\u4E2A\u5DE5\u5177\u4F1A\u4ECE\u5B83\u7684\u5DE5\u5177\u5217\u8868\u91CC\u6D88\u5931\uFF0C\n \u547D\u4EE4\u91CC\u7684\u8DEF\u5F84\u4E0E\u5F15\u53F7\u6309 bash \u89C4\u5219\u5199\u3002\u672C\u673A\u4E0D\u9700\u8981\u88C5 Git for Windows \u5230\u9ED8\u8BA4\u76EE\u5F55\u2014\u2014\u63A2\u6D4B\u4F1A\u5148\u627E\n git\uFF0C\u518D\u7531\u540C\u4E00\u4E2A\u5B89\u88C5\u53CD\u63A8 bash\u3002\uFF08\u6863\u4F4D\u5728\u6807\u9898\u884C\u4E0A\uFF1A\u81EA\u52A8 / Git Bash / PowerShell\u3002\uFF09\n </p>\n <DefaultTerminalBody settings={settings} setField={actions.setField} hideMode />\n </FoldCard>\n </>)}\n </div>\n )\n}\n", "/**\n * \u6761\u76EE\u5217\u8868**\u6700\u4E0B\u8FB9**\u90A3\u4E00\u884C\u300C\uFF0B\u300D\uFF1A\u70B9\u5F00\u5206\u300C\u65B0\u5EFA / \u79FB\u52A8\u300D\u3002\n *\n * \u300C\u79FB\u52A8\u300D\u5217\u51FA**\u5176\u5B83\u5206\u7C7B**\u91CC\u7684\u5168\u90E8\u6761\u76EE\uFF08`\u5206\u7C7B\u540D \u00B7 \u6761\u76EE\u540D`\uFF09\uFF0C\u70B9\u5B83\u5C31\u628A\u90A3\u6761\u79FB\u8FDB\n * \u5F53\u524D\u5206\u7C7B\uFF08\u8FFD\u52A0\u5230\u672B\u5C3E\uFF0C\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u6807\u8BB0\u8DDF\u7740\u8D70\uFF09\u3002\u83DC\u5355\u5185\u5BB9\u662F\u8DDF\u7740\u5206\u7C7B\u53D8\u7684\uFF0C\u6240\u4EE5\n * \u5207\u6362\u5206\u7C7B\u65F6\u4F1A\u81EA\u52A8\u6536\u8D77\uFF1B\u70B9\u5916\u9762\u6216\u6309 Escape \u4E5F\u6536\u8D77\u3002\n *\n * \u9762\u677F\u4E0E\u8BBE\u7F6E\u9875\u5171\u7528\u540C\u4E00\u4E2A\u7EC4\u4EF6\uFF1A\u9762\u677F\u7A7A\u95F4\u7D27\u5F20\uFF08variant='panel' \u66F4\u7D27\u51D1\uFF09\uFF0C\u8BBE\u7F6E\u9875\u7528\n * \u5361\u7247\u98CE\u683C\uFF08variant='settings'\uFF09\u3002\u4E24\u8FB9\u884C\u4E3A\u5FC5\u987B\u4E00\u81F4\uFF0C\u6240\u4EE5\u4E0D\u8BA9\u5B83\u4EEC\u5404\u5199\u4E00\u5957\u3002\n */\nimport React, { useEffect, useRef, useState } from 'react'\nimport type { CSSProperties } from 'react'\nimport type { QuickPromptBook } from '../settings-contract.ts'\nimport { promptsElsewhere } from './prompt-book.ts'\n\n/** \u7EC4\u4EF6\u7684\u6CE8\u5165\u9762\uFF08\u653E\u5728\u4E24\u8FB9\u5404\u81EA\u7684\u6570\u636E\u6E90\u4E4B\u4E0A\uFF1A\u8BBE\u7F6E\u9875\u4F20\u8349\u7A3F\uFF0C\u9762\u677F\u4F20\u7EBF\u4E0A\u672C\uFF09\u3002 */\nexport interface AddPromptRowProps {\n /** \u5F53\u524D\u8FD9\u672C\uFF1B\u300C\u79FB\u52A8\u300D\u83DC\u5355\u8981\u4ECE\u4E2D\u5217\u51FA\u5176\u5B83\u5206\u7C7B\u7684\u6761\u76EE\u3002 */\n book: QuickPromptBook\n /** \u6761\u76EE\u5C06\u843D\u5230\u8FD9\u4E2A\u5206\u7C7B\u3002 */\n categoryId: string\n /** \u65B0\u5EFA\u4E00\u6761\uFF08\u7531\u8C03\u7528\u65B9\u51B3\u5B9A\u600E\u4E48\u843D\u76D8\uFF1A\u8BBE\u7F6E\u9875\u8FDB\u8349\u7A3F\uFF0C\u9762\u677F\u76F4\u63A5\u5199\uFF09\u3002 */\n onAdd: () => void\n /** \u628A\u8FD9\u6761\u4ECE\u5B83\u6240\u5728\u5206\u7C7B\u79FB\u5230\u8FD9\u91CC\u3002 */\n onMove: (promptId: string) => void\n /** \u89C6\u89C9\u53D8\u4F53\uFF1A\u9762\u677F\u66F4\u7D27\u51D1\u3002 */\n variant?: 'panel' | 'settings'\n}\n\nconst rowBase: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n width: '100%',\n borderRadius: 8,\n border: '0.5px dashed var(--dsw-alias-border-l2)',\n background: 'transparent',\n color: 'var(--dsw-alias-label-tertiary)',\n cursor: 'pointer',\n textAlign: 'left',\n}\n\nconst choiceBase: CSSProperties = {\n padding: '4px 9px',\n borderRadius: 999,\n border: '0.5px solid var(--dsw-alias-border-l2)',\n background: 'transparent',\n color: 'var(--dsw-alias-label-primary)',\n fontSize: 11,\n lineHeight: 1.2,\n cursor: 'pointer',\n}\n\nconst candidateBase: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n width: '100%',\n padding: '4px 6px',\n borderRadius: 6,\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n textAlign: 'left',\n}\n\n/** \u300C\uFF0B \u65B0\u5EFA / \u79FB\u52A8\u300D\u90A3\u4E00\u884C\u3002 */\nexport function AddPromptRow({\n book, categoryId, onAdd, onMove, variant = 'settings',\n}: AddPromptRowProps) {\n const [mode, setMode] = useState<'closed' | 'choose' | 'move'>('closed')\n const ref = useRef<HTMLDivElement | null>(null)\n\n // \u6362\u5206\u7C7B\u5C31\u6536\u8D77\uFF1A\u83DC\u5355\u91CC\u7684\u5019\u9009\u662F\u300C\u5176\u5B83\u5206\u7C7B\u300D\uFF0C\u7559\u7740\u4F1A\u663E\u793A\u4E0A\u4E00\u4E2A\u5206\u7C7B\u5224\u65AD\u51FA\u6765\u7684\u5217\u8868\u3002\n useEffect(() => { setMode('closed') }, [categoryId])\n\n useEffect(() => {\n if (mode === 'closed') return\n const onPointerDown = (event: PointerEvent): void => {\n if (ref.current !== null && event.target instanceof Node && ref.current.contains(event.target)) return\n setMode('closed')\n }\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') setMode('closed')\n }\n document.addEventListener('pointerdown', onPointerDown, true)\n document.addEventListener('keydown', onKeyDown, true)\n return () => {\n document.removeEventListener('pointerdown', onPointerDown, true)\n document.removeEventListener('keydown', onKeyDown, true)\n }\n }, [mode])\n\n const compact = variant === 'panel'\n const candidates = mode === 'move' ? promptsElsewhere(book, categoryId) : []\n\n return (\n <div ref={ref} style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>\n <button\n type=\"button\"\n aria-expanded={mode !== 'closed'}\n title=\"\u65B0\u5EFA\u4E00\u6761\uFF0C\u6216\u628A\u522B\u7684\u5206\u7C7B\u91CC\u7684\u6761\u76EE\u79FB\u52A8\u5230\u8FD9\u91CC\"\n style={{\n ...rowBase,\n padding: compact ? '4px 8px' : '7px 9px',\n fontSize: compact ? 11 : 12,\n }}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { setMode(mode === 'closed' ? 'choose' : 'closed') }}\n >\n <span aria-hidden>\uFF0B</span>\n <span>{mode === 'closed' ? '\u65B0\u5EFA / \u79FB\u52A8' : '\u6536\u8D77'}</span>\n </button>\n\n {mode !== 'closed' && (\n <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>\n <button\n type=\"button\"\n style={choiceBase}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { setMode('closed'); onAdd() }}\n >\n \uFF0B \u65B0\u5EFA\u4E00\u6761\n </button>\n <button\n type=\"button\"\n style={mode === 'move' ? { ...choiceBase, borderColor: 'var(--dsw-alias-brand-primary)' } : choiceBase}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { setMode(mode === 'move' ? 'choose' : 'move') }}\n >\n \u2192 \u628A\u522B\u7684\u5206\u7C7B\u7684\u6761\u76EE\u79FB\u52A8\u5230\u8FD9\u91CC\n </button>\n </div>\n )}\n\n {mode === 'move' && (\n <div\n style={{\n display: 'flex', flexDirection: 'column', gap: 2,\n maxHeight: 190, overflowY: 'auto',\n border: '0.5px solid var(--dsw-alias-border-l2)',\n borderRadius: 8, padding: 4,\n }}\n >\n {candidates.length === 0 && (\n <span style={{ color: 'var(--dsw-alias-label-tertiary)', fontSize: 11, padding: '4px 6px' }}>\n \u522B\u7684\u5206\u7C7B\u91CC\u8FD8\u6CA1\u6709\u6761\u76EE\u53EF\u4EE5\u79FB\u52A8\u3002\n </span>\n )}\n {candidates.map(candidate => (\n <button\n key={candidate.prompt.id}\n type=\"button\"\n title={`${candidate.categoryName} \u00B7 ${candidate.prompt.prompt}`}\n style={candidateBase}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => {\n setMode('closed')\n onMove(candidate.prompt.id)\n }}\n >\n <span style={{ color: 'var(--dsw-alias-label-tertiary)', fontSize: 11, flex: '0 0 auto' }}>\n {candidate.categoryName}\n </span>\n <span style={{ color: 'var(--dsw-alias-label-tertiary)', flex: '0 0 auto' }}>\u00B7</span>\n <span\n style={{\n color: 'var(--dsw-alias-label-primary)', fontSize: 12,\n minWidth: 0, flex: '1 1 auto', overflow: 'hidden',\n textOverflow: 'ellipsis', whiteSpace: 'nowrap',\n }}\n >\n {candidate.prompt.label}\n </span>\n {candidate.prompt.always && (\n <span style={{ color: 'var(--dsw-alias-label-tertiary)', fontSize: 10, flex: '0 0 auto' }}>\n \u9ED8\u8BA4\u63D2\u5165\n </span>\n )}\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n", "/**\n * \u63D0\u793A\u8BCD\u4F18\u5316\u5668\u7684\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF08\u4E09\u6863\uFF09+ \u7528\u6237\u6D88\u606F\u6784\u9020\u3002\n *\n * \u6765\u6E90\u4E0E\u6388\u6743\uFF1A\u521D\u7248\u90A3\u4E09\u6863\u6587\u672C\u9010\u5B57\u53D6\u81EA WestFox-AwA/dsh-prompt-optimizer \u7684 `lib/index.js` \u91CC\n * **`LEGACY_V011`** \u8FD9\u4E2A\u5E38\u91CF\uFF08BSD-3-Clause\uFF0C\u4F5C\u8005\u300C\u5543\u8F6E\u80CE\u7684\u897F\u72D0\u300D\uFF09\u2014\u2014 \u5B83\u81EA\u5DF1\u7684\u6CE8\u91CA\u5199\u7740\n * \"\u9010\u5B57\u8282\u53D6\u81EA 0.1.1 \u7684 system \u63D0\u793A\u8BCD\"\uFF0C\u53EA\u5728\u56DE\u9000\u7B56\u7565 `v011-ptc` \u4E0B\u4F7F\u7528\uFF0C\u5BF9\u65B9\u9ED8\u8BA4\u7B56\u7565\n * \uFF08`STRATEGY_DEFAULT = 'v6'`\uFF09\u8D70\u7684\u662F `buildSystem()` \u53E6\u4E00\u5957\u3002\n * 0.6.0 \u8D77\u6309\u5BF9\u65B9 **0.6 \u7EBF**\uFF08`po06/lib/interpreter.js` \u7684 `SYSTEM_PROMPT` +\n * `validateProvenance`\uFF09\u7684\u673A\u5236\u91CD\u5199\uFF0C\u672C\u63D2\u4EF6\u81EA\u8EAB\u4ECD\u6309 MIT \u53D1\u5E03\u3002\n *\n * \u2500\u2500 \u4E3A\u4EC0\u4E48\u6362\u6210\u8FD9\u5957\uFF08\u5BF9\u65B9\u7684\u771F\u95EE\u9898\uFF0C\u4E5F\u662F\u6211\u4EEC\u7684\uFF09\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * \u65E7\u7248\u662F**\u81EA\u7531\u6539\u5199\u5668**\uFF1A\u6A21\u578B\u76F4\u63A5\u5410\u4E00\u6761\u6210\u54C1\u547D\u4EE4\uFF0C\u5BBF\u4E3B\u53EA\u80FD\u6574\u6BB5\u7167\u6536\u3002\u4E8E\u662F\"\u6A21\u578B\u66FF\u7528\u6237\u53D1\u660E\n * \u4E86\u4E00\u6761\u8981\u6C42\"\u8FD9\u4EF6\u4E8B\u5728\u7ED3\u6784\u4E0A\u65E0\u6CD5\u88AB\u53D1\u73B0 \u2014\u2014 \u63D0\u793A\u8BCD\u91CC\u5199\u5341\u904D\"\u4E0D\u8BB8\u65B0\u589E\u9700\u6C42\"\u4E5F\u6CA1\u7528\uFF0C\u56E0\u4E3A\n * \u6CA1\u6709\u4EFB\u4F55**\u53EF\u673A\u68B0\u6838\u5BF9**\u7684\u5224\u636E\u3002\n *\n * 0.6 \u7684\u529E\u6CD5\uFF1A\u628A\"\u4FE1\u4EFB\u95EE\u9898\"\u53D8\u6210\"\u5B57\u7B26\u4E32\u6BD4\u5BF9\u95EE\u9898\"\u3002\n * \u00B7 \u6A21\u578B\u4E0D\u518D\u81EA\u7531\u5199\uFF0C\u53EA\u4EA7\u51FA**\u6761\u76EE**\uFF1B\n * \u00B7 \u6BCF\u6761 `rewrite` / `requirement` / `quality` \u5FC5\u987B\u9644 `quote` \u2014\u2014 \u4E00\u6BB5**\u5728\u7528\u6237\u539F\u8BDD\u91CC\n * \u9010\u5B57\u5B58\u5728**\u7684\u5B50\u4E32\uFF08\u7167\u6284\uFF0C\u4E0D\u8BB8\u6539\u5199\u3001\u4E0D\u8BB8\u8865\u6807\u70B9\uFF09\uFF1B\n * \u00B7 \u5BBF\u4E3B\u5728 `optimizer-assemble.ts` \u91CC\u505A\u5B57\u9762\u5B50\u4E32\u6BD4\u5BF9\uFF0C**\u5BF9\u4E0D\u4E0A\u5C31\u4E22\u90A3\u4E00\u6761\u5E76\u8BB0\u8D26**\uFF1B\n * \u00B7 `rewrite` \u6309\u5F15\u6587\u5728\u539F\u8BDD\u91CC\u7684**\u4F4D\u7F6E**\u56DE\u586B\uFF0C\u6CA1\u88AB\u8986\u76D6\u7684\u90E8\u5206\u539F\u6837\u4FDD\u7559\u3002\n * \u8FD9\u6837\"\u51ED\u7A7A\u52A0\u9700\u6C42\"\u4E0D\u518D\u662F\u4FE1\u4EFB\u95EE\u9898\uFF1A\u5B83\u62FF\u4E0D\u51FA\u9010\u5B57\u4F9D\u636E\u3002\n *\n * \u6863\u4F4D\u8BED\u4E49\u4E5F\u7167\u642C\u5BF9\u65B9\u7684\u8BF4\u6CD5\uFF1A**\u6863\u4F4D = \u4F9D\u636E\u9884\u7B97**\uFF08\u5141\u8BB8\u8865\u5230\u4EC0\u4E48\u7A0B\u5EA6\u3001\u6210\u54C1\u5141\u8BB8\u591A\u957F\uFF09\uFF0C\n * \u800C\u4E0D\u662F\"\u6362\u4E00\u79CD\u6587\u98CE\"\u3002\u6E29\u5EA6\u4ECD\u6CBF\u7528\u521D\u7248\u5B9E\u6D4B\u503C\uFF080.2 / 0.3 / 0.3\uFF09\u3002\n *\n * \u672C\u6A21\u5757\u96F6 import\uFF0Chost \u534A\u4E0E\u6D4B\u8BD5\u5171\u7528\u3002\n */\n\n/** \u4F20\u8BDD\u8005\u4EBA\u8BBE\uFF1A\u4E3A\u4EC0\u4E48\u5FC5\u987B\u5355\u72EC\u6210\u6BB5\u2014\u2014\u88F8\u6587\u672C\u4F1A\u88AB\u6A21\u578B\u5F53\u6210\u300C\u5BF9\u5B83\u8BF4\u7684\u8BDD\u300D\u800C\u5F00\u59CB\u5BF9\u8BDD\u3002 */\nconst RELAY_ROLE = [\n '\u3010\u4F60\u662F\u8C01\u3011\u4F60\u662F\u4E00\u4E2A**\u4F20\u8BDD\u5668/\u610F\u56FE\u8865\u5168\u5668**\uFF0C\u7AD9\u5728\u7528\u6237\u4E0E\"\u5DE5\u4F5C AI\"\u4E4B\u95F4\uFF1A',\n ' \u7528\u6237 \u2192\uFF08\u4F60\uFF1A\u628A\u7528\u6237\u7684\u610F\u601D\u6574\u7406\u6210\u6761\u76EE\u5E76\u7ED9\u51FA\u9010\u5B57\u4F9D\u636E\uFF09\u2192 \u5BBF\u4E3B\uFF08\u88C5\u914D\u6210\u4E00\u6761\u547D\u4EE4\uFF09\u2192 \u5DE5\u4F5C AI\u3002',\n '\u4F60\u7684\u4EA7\u51FA**\u4E0D\u4F1A**\u88AB\u76F4\u63A5\u5C55\u793A\u7ED9\u7528\u6237\uFF0C\u4E5F\u4E0D\u4F1A\u88AB\u539F\u6837\u53D1\u51FA\uFF1A\u5BBF\u4E3B\u4F1A\u7528\u4F60\u7ED9\u7684**\u9010\u5B57\u5F15\u6587**',\n '\u5728\u539F\u8BDD\u91CC\u5B9A\u4F4D\u3001\u53EA\u91C7\u7EB3\u80FD\u6838\u5BF9\u7684\u6761\u76EE\uFF0C\u518D\u88C5\u914D\u6210\u4E00\u6761\u547D\u4EE4\u4EA4\u7ED9\u5DE5\u4F5C AI\u3002',\n '\u3010\u4F60\u4E0D\u662F\u8C01\u3011\u4F60\u4E0D\u662F\u5728\u548C\u7528\u6237\u804A\u5929\uFF0C\u4E5F\u4E0D\u662F\u5728\u56DE\u7B54\u7528\u6237\uFF1A',\n '- \u4E0D\u8981\u56DE\u5E94\u3001\u4E0D\u8981\u56DE\u7B54\u7528\u6237\u7684\u8981\u6C42\uFF0C\u4E5F\u4E0D\u8981\u66FF\u7528\u6237\u5B8C\u6210\u4EFB\u52A1\uFF08\u4E0D\u8981\u76F4\u63A5\u7ED9\u51FA\u4EE3\u7801/\u7B54\u6848/\u7ED3\u679C\uFF09\u3002',\n '- \u4E0D\u8981\u4EE5\u52A9\u624B\u53E3\u543B\u5BF9\u7528\u6237\u8BF4\u8BDD\uFF08\"\u597D\u7684\"\"\u6536\u5230\"\"\u6211\u53EF\u4EE5\u5E2E\u4F60\"\"\u5EFA\u8BAE\u4F60\u2026\"\"\u9700\u8981\u6211\u2026\u5417\"\uFF09\u3002',\n '- \u4E0D\u8981\u628A\u7528\u6237\u53D1\u6765\u7684\u6587\u5B57\u5F53\u6210\"\u5BF9\u4F60\u8BF4\u7684\u8BDD\"\u6765\u56DE\u5E94\uFF1B\u5B83\u53EA\u662F\u4F60\u8981\u8F6C\u8FBE\u7684\u5185\u5BB9\u3002',\n '- \u4E0D\u8981\u5411\u7528\u6237\u63D0\u95EE\u3002\u8981\u6F84\u6E05\u65F6\uFF0C\u5199\u6210**\u7ED9\u5DE5\u4F5C AI \u7684\u6307\u4EE4**\uFF1A',\n ' \"\u82E5 X \u4E0D\u660E\u786E\uFF0C\u5148\u8BFB Y \u6216\u5148\u5411\u6211\u786E\u8BA4\uFF0C\u4E0D\u8981\u81EA\u884C\u5047\u8BBE\"\u3002',\n].join('\\n')\n\n/**\n * \u4F9D\u636E\u7EAA\u5F8B \u2014\u2014 \u8FD9\u5957\u673A\u5236\u7684\u5168\u90E8\u4EF7\u503C\u6240\u5728\u3002\n *\n * \u6BCF\u6761\u90FD\u5BF9\u5E94\u4E00\u4E2A**\u5BBF\u4E3B\u771F\u7684\u4F1A\u6267\u884C**\u7684\u68C0\u67E5\uFF08\u89C1 optimizer-assemble.ts\uFF09\uFF1A\n * \u6CA1\u6709\u5F15\u6587 \u2192 \u4E22\u8FD9\u4E00\u6761\uFF1B\u5F15\u6587\u4E0D\u662F\u5B57\u9762\u5B50\u4E32 \u2192 \u4E22\u8FD9\u4E00\u6761\uFF1B\u6761\u6570\u8D85\u4E0A\u9650 \u2192 \u622A\u65AD\u540E\u9762\u5E76\u8BB0\u8D26\u3002\n * \u63D0\u793A\u8BCD\u91CC\u5199\"\u5FC5\u987B\"\u800C\u5BBF\u4E3B\u4E0D\u67E5\uFF0C\u5C31\u662F\u7A7A\u8BDD\uFF1B\u8FD9\u91CC\u4E24\u8FB9\u662F\u914D\u5957\u7684\u3002\n */\nconst EVIDENCE_RULES = [\n '\u3010\u4F9D\u636E\u7EAA\u5F8B\uFF08\u5BBF\u4E3B\u4F1A\u9010\u6761\u673A\u68B0\u6838\u5BF9\uFF0C\u5199\u9519\u5C31\u4E22\u8FD9\u4E00\u6761\uFF09\u3011',\n '1. `rewrite` / `requirement` / `quality` **\u5FC5\u987B**\u5E26 `quote`\uFF1A\u4E00\u6BB5\u5728\u3010\u7528\u6237\u539F\u8BDD\u3011\u91CC',\n ' **\u9010\u5B57\u5B58\u5728**\u7684\u5B50\u4E32 \u2014\u2014 \u7167\u6284\uFF0C\u4E0D\u8981\u6539\u5199\u3001\u4E0D\u8981\u8865\u6807\u70B9\u3001\u4E0D\u8981\u7FFB\u8BD1\u3002\u5BBF\u4E3B\u505A\u5B57\u9762\u5B50\u4E32\u6BD4\u5BF9\uFF0C',\n ' \u5BF9\u4E0D\u4E0A\u5C31\u4E22\u6389\u90A3\u4E00\u6761\uFF08\u4E0D\u4F1A\u62A5\u9519\u7ED9\u4F60\uFF0C\u4E5F\u4E0D\u4F1A\u6709\u4EBA\u63D0\u9192\u4F60\uFF09\u3002',\n '2. **\u4E0D\u8BB8\u51ED\u7A7A\u65B0\u589E**\uFF1A\u4EA7\u54C1\u76EE\u6807\u3001\u529F\u80FD\u3001\u786C\u7EA6\u675F\uFF08\"\u5FC5\u987B\u79BB\u7EBF\"\"\u7981\u6B62\u8054\u7F51\"\"\u53EA\u80FD\u7528\u67D0\u4E2A\u5E93\"',\n ' \"\u5FC5\u987B\u652F\u6301\u79FB\u52A8\u7AEF\"\uFF09\u4E00\u5F8B\u4E0D\u8BB8\u7531\u4F60\u51B3\u5B9A\u3002\u4F60\u53EA\u80FD\u8865**\u80FD\u4ECE\u539F\u8BDD\u67D0\u4E00\u53E5\u76F4\u63A5\u63A8\u51FA**\u7684\u6700\u4F4E\u8981\u6C42\uFF0C',\n ' \u5E76\u4E14\u5FC5\u987B\u5F15\u7528\u90A3\u4E00\u53E5\u3002',\n '3. \u4E0D\u786E\u5B9A\u3001\u4F1A\u5F71\u54CD\u7ED3\u679C\u3001\u4E14\u53EA\u6709\u7528\u6237\u80FD\u5B9A\u7684\u53D6\u820D \u2192 \u5199 `unknown`\uFF08`unknownClass` =',\n ' \"user_preference\"\uFF09\uFF0C**\u4E0D\u8981\u66FF\u7528\u6237\u731C**\uFF0C\u4E5F\u4E0D\u8981\u5199\"\u6309\u6700\u4FDD\u5B88\u7406\u89E3\u6267\u884C\"\u3002',\n ' \u5728\u8BB8\u53EF\u8303\u56F4\u5185\u8BFB\u4EE3\u7801\u5C31\u80FD\u786E\u5B9A\u7684\u4E8B\u5B9E\u5199 \"lookupable_fact\"\uFF1B\u53EF\u9006\u7684\u5B9E\u73B0\u7EC6\u8282',\n ' \uFF08\u95F4\u8DDD\u3001\u547D\u540D\u3001\u5E93\u7684\u5185\u90E8\u7528\u6CD5\uFF09\u5199 \"implementation_detail\"\u3002',\n '4. \u4E0D\u5F97\u865A\u6784\u9879\u76EE\u4E8B\u5B9E\uFF08\u6587\u4EF6\u5185\u5BB9\u3001\u76EE\u5F55\u7ED3\u6784\u3001\u4F9D\u8D56\u7248\u672C\uFF09\u3002\u4F60\u6CA1\u8BFB\u5230\u7684\u4E1C\u897F\u4E0D\u5B58\u5728\u3002',\n].join('\\n')\n\n/** \u5199\u6B63\u6587\u65F6\u7684\u6587\u98CE\u7EAA\u5F8B\uFF1A\u8FD9\u4E9B `text` \u4F1A\u88AB\u62FC\u8FDB\u6700\u7EC8\u547D\u4EE4\uFF0C\u8BFB\u8005\u53EA\u6709\u5DE5\u4F5C AI \u4E00\u4E2A\u3002 */\nconst STYLE_RULES = [\n '\u3010\u5199 text \u7684\u7EAA\u5F8B\u3011\u4F60\u7684 text \u4F1A\u88AB\u5BBF\u4E3B\u62FC\u8FDB\u6700\u7EC8\u547D\u4EE4\uFF0C\u8BFB\u8005\u53EA\u6709\"\u5DE5\u4F5C AI\"\u4E00\u4E2A\uFF1A',\n '- \u7948\u4F7F\u53E5\u3001\u76F4\u7ED9\u8981\u6C42\u3001\u53EF\u6267\u884C\uFF1B\u4E2D\u6587\u8FDB\u4E2D\u6587\u51FA\u3002',\n '- \u4E0D\u8981\u5143\u8BDD\u8BED\u4E0E\u5143\u6807\u9898\uFF08\"\u4F18\u5316\u540E\u7684\u63D0\u793A\u8BCD\"\"\u6539\u5199\u540E\"\"\u8BF4\u660E\"\"\u4EE5\u4E0B\u662F\u2026\"\uFF09\u3002',\n '- \u4E0D\u8981\u63D0\u5230\"\u7528\u6237/\u539F\u6587/\u4E0A\u9762\u7684\u8BDD\"\uFF0C\u4E5F\u4E0D\u8981\u5199\"\u6211\u6765\u5E2E\u4F60\u2026\"\u3002',\n '- \u4E0D\u8981\u5199\u6D41\u7A0B\u4EEA\u5F0F\u3001\u901A\u7528\u6559\u5B66\u3001\u9A8C\u6536\u5957\u8BDD\uFF08\"\u8BF7\u786E\u4FDD\u4EE3\u7801\u8D28\u91CF\"\u8FD9\u79CD\u6CA1\u6709\u6307\u5411\u7684\u8BDD\uFF09\u3002',\n '- `rewrite` \u7684 text \u662F**\u66FF\u6362\u6389\u90A3\u6BB5\u5F15\u6587**\u7684\u6B63\u6587\uFF0C\u6240\u4EE5\u53EA\u5199\u90A3\u6BB5\u8BDD\u672C\u8EAB\uFF0C\u4E0D\u8981\u5E26\u524D\u7F00\u540E\u7F00\u3002',\n].join('\\n')\n\n/**\n * \u8F93\u51FA\u5951\u7EA6\uFF1A**\u6C38\u8FDC\u8FFD\u52A0\u5728\u6700\u540E\u4E00\u6BB5**\uFF0C\u4E14\u4E0D\u968F\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u6539\u53D8\u3002\n *\n * \u4E3A\u4EC0\u4E48\u4E0D\u8BA9\u5B83\u88AB\u6539\uFF1A\u5BBF\u4E3B\u6309\u8FD9\u4EFD\u5951\u7EA6\u89E3\u6790\uFF1B\u5951\u7EA6\u4E00\u6539\uFF0C\"\u9010\u5B57\u4F9D\u636E\"\u5C31\u6CA1\u4EBA\u6821\u9A8C\u4E86\uFF0C\n * \u6574\u5957\u673A\u5236\u9000\u5316\u6210\"\u4FE1\u4EFB\u6A21\u578B\"\u3002\u8BBE\u7F6E\u9875\u7684\u8BF4\u660E\u91CC\u5BF9\u6B64\u6709\u660E\u793A\u3002\n * \u653E\u6700\u540E\u662F\u56E0\u4E3A\u6A21\u578B\u5BF9**\u6700\u540E\u4E00\u6761\u6307\u4EE4**\u7684\u670D\u4ECE\u5EA6\u6700\u9AD8\uFF08\u5BF9\u65B9 0.6 \u7684 `askTail` \u540C\u7406\uFF09\u3002\n */\nexport const OPTIMIZER_OUTPUT_CONTRACT = [\n '\u3010\u8F93\u51FA\u5951\u7EA6\uFF08\u56FA\u5B9A\uFF0C\u4E0D\u53EF\u66F4\u6539\uFF09\u3011',\n '\u53EA\u8F93\u51FA\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u4E0D\u8981 Markdown \u4EE3\u7801\u5757\u3001\u4E0D\u8981\u5728 JSON \u524D\u540E\u5199\u4EFB\u4F55\u5B57\uFF1A',\n '{\"items\":[{\"kind\":\"rewrite\",\"quote\":\"\u539F\u8BDD\u91CC\u9010\u5B57\u5B58\u5728\u7684\u7247\u6BB5\",\"text\":\"\u66FF\u6362\u6389\u8BE5\u7247\u6BB5\u7684\u6B63\u6587\"}]}',\n '\u5B57\u6BB5\u4E0E\u53D6\u503C\uFF08`kind` \u53EA\u80FD\u662F\u8FD9\u516D\u79CD\uFF09\uFF1A',\n '- rewrite\uFF1A\u8BED\u8A00\u5C42\u4FEE\u590D\u3002`quote` \u5FC5\u586B\uFF1B\u540C\u4E00\u6BB5\u539F\u8BDD\u6700\u591A\u4E00\u6761 rewrite\uFF0C\u4E0D\u8981\u91CD\u53E0\u3002',\n '- requirement\uFF1A\u4ECE `quote` \u76F4\u63A5\u63A8\u51FA\u7684\u8865\u5168\u8981\u6C42\uFF08\u9A8C\u6536\u6807\u51C6/\u786C\u7EA6\u675F\uFF09\u3002`quote` \u5FC5\u586B\u3002',\n '- quality\uFF1A\u5BF9\u539F\u8BDD\u91CC\u8D28\u91CF\u8BCD\u7684\u89E3\u91CA\u3002`quote` \u5FC5\u586B\uFF08\u5C31\u586B\u90A3\u51E0\u4E2A\u8D28\u91CF\u5B57\uFF09\u3002',\n '- unknown\uFF1A\u672A\u51B3\u9879\u3002\u5FC5\u987B\u5E26 `unknownClass`\uFF08user_preference / lookupable_fact /',\n ' implementation_detail\uFF09\uFF0C\u53EF\u9009 `blocking`\uFF08true/false\uFF0C\u662F\u5426\u6321\u4F4F\u4E0B\u4E00\u6B65\uFF09\u3002',\n '- plan\uFF1A\u5206\u9636\u6BB5\u6267\u884C\u8BA1\u5212\uFF08\u4EC5\"\u6781\u7AEF\"\u6863\u7528\uFF09\u3002',\n '- risk\uFF1A\u591A\u60C5\u51B5\u9884\u6848\uFF08\u4EC5\"\u6781\u7AEF\"\u6863\u7528\uFF09\uFF0C\u6BCF\u6761\u6309\"\u89E6\u53D1\u4FE1\u53F7 \u2192 \u5E94\u5BF9 \u2192 \u7981\u6B62\u52A8\u4F5C\"\u5199\u3002',\n '\u9650\u5236\uFF1A`text` \u6BCF\u6761\u4E0D\u8D85\u8FC7 300 \u5B57\uFF1B`items` \u603B\u5171\u4E0D\u8D85\u8FC7 12 \u6761\uFF1Bid \u4E0D\u9700\u8981\u7ED9\u3002',\n '\u6CA1\u6709\u53EF\u8865\u7684\u5185\u5BB9\u65F6\uFF0C\u8F93\u51FA {\"items\":[]} \u2014\u2014 \u4F46**\u5148\u60F3\u6E05\u695A**\uFF1A\u7528\u6237\u8FD9\u4E00\u8F6E\u7684\u539F\u8BDD\u91CC',\n '\u771F\u7684\u6CA1\u6709\u4EFB\u4F55\u53EF\u6838\u5BF9\u7684\u8865\u5168\u5417\uFF1F',\n].join('\\n')\n\n/** \u6A21\u578B\u53EF\u4EE5\u4EA7\u51FA\u7684\u6761\u76EE\u79CD\u7C7B\uFF08\u5BBF\u4E3B\u53EA\u8BA4\u8FD9\u4E9B\uFF0C\u5176\u4F59\u6574\u6761\u4E22\u5F03\u5E76\u8BB0\u8D26\uFF09\u3002 */\nexport const OPTIMIZE_ITEM_KINDS = ['rewrite', 'requirement', 'quality', 'unknown', 'plan', 'risk'] as const\n\n/** \u6A21\u578B\u53EF\u4EE5\u4EA7\u51FA\u7684\u672A\u51B3\u9879\u5206\u7C7B\uFF08\u7F3A\u7701\u6309\"\u53EA\u6709\u7528\u6237\u80FD\u5B9A\"\u5904\u7406\uFF0C\u4E0E\u5BF9\u65B9 0.6 \u540C\u53E3\u5F84\uFF09\u3002 */\nexport const OPTIMIZE_UNKNOWN_CLASSES = ['user_preference', 'lookupable_fact', 'implementation_detail'] as const\n\n/** \u5355\u6B21\u4EA7\u51FA\u5141\u8BB8\u7684\u6700\u5927\u6761\u76EE\u6570\uFF08\u8D85\u51FA\u90E8\u5206\u622A\u65AD\u5E76\u8BB0\u8D26\uFF0C\u800C\u4E0D\u662F\u6574\u8F6E\u4F5C\u5E9F\uFF09\u3002 */\nexport const OPTIMIZE_MAX_ITEMS = 12\n\n/** \u5355\u6761 `text` \u7684\u5B57\u7B26\u4E0A\u9650\uFF08\u8D85\u51FA\u5C31\u5730\u622A\u65AD\u5E76\u8BB0\u8D26\uFF09\u3002 */\nexport const OPTIMIZE_ITEM_MAX_CHARS = 300\n\n/**\n * \u5404\u6863\u7684\u4EFB\u52A1\u6BB5\uFF08**\u53EF\u88AB\u8BBE\u7F6E\u9875\u91CC\u7684\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u6574\u4F53\u66FF\u6362**\u7684\u90A3\u90E8\u5206\uFF09\u3002\n *\n * \u4E09\u6863\u7684\u5DEE\u522B\u662F\"\u5141\u8BB8\u8865\u5230\u54EA\u4E00\u5C42\"\uFF0C\u4E0D\u662F\"\u6362\u4E00\u79CD\u8BED\u6C14\"\uFF1A\n * \u00B7 basic \u2014\u2014 \u53EA\u78B0\u8BED\u8A00\uFF1B\u4E0D\u4EA7\u51FA requirement / plan / risk\u3002\n * \u00B7 advanced \u2014\u2014 \u5141\u8BB8\u8865\"\u80FD\u6307\u56DE\u539F\u8BDD\u67D0\u53E5\"\u7684\u5FC5\u8981\u8981\u6C42\uFF0C\u5E76\u5BF9\u8D28\u91CF\u8BCD\u4F5C\u89E3\u91CA\u3002\n * \u00B7 extreme \u2014\u2014 \u518D\u52A0\u5206\u9636\u6BB5\u8BA1\u5212\u4E0E\u9884\u6848\u3002\n */\nconst TIER_TASKS: Record<string, readonly string[]> = {\n basic: [\n '\u3010\u672C\u8F6E\u4EFB\u52A1\uFF1A\u53EA\u505A\u8BED\u8A00\u5C42\u4FEE\u590D\u3011',\n '\u7528\u6237\u539F\u8BDD\u53EF\u80FD\u6709\u75C5\u53E5\u3001\u6307\u4EE3\u4E0D\u660E\u3001\u7528\u8BCD\u542B\u7CCA\u3002\u628A\u5B83\u6539\u5199\u6210\u901A\u987A\u3001\u7CBE\u786E\u3001\u65E0\u6B67\u4E49\u7684**\u540C\u4E00\u6BB5\u8BDD**\u3002',\n '\u53EA\u4EA7\u51FA `rewrite`\uFF08\u53EF\u4EE5\u6309\u53E5\u5B50\u62C6\u6210\u591A\u6761\uFF0C\u6BCF\u6761\u5F15\u7528\u539F\u8BDD\u91CC\u5BF9\u5E94\u90A3\u4E00\u53E5\uFF09\u3002',\n '\u4E25\u7981\u4EA7\u51FA requirement / plan / risk\uFF1A\u8FD9\u4E00\u6863**\u4E0D\u65B0\u589E\u4EFB\u4F55\u8981\u6C42**\uFF0C\u53EA\u628A\u8BDD\u8BF4\u660E\u767D\u3002',\n '\u539F\u8BDD\u786E\u6709\u6B67\u4E49\u3001\u4E14\u6B67\u4E49\u4F1A\u5BFC\u81F4\u505A\u9519\u65F6\uFF0C\u624D\u8865\u4E00\u6761 `unknown`\uFF08unknownClass \u53D6',\n 'user_preference \u6216 lookupable_fact\uFF09\uFF1B\u786E\u5B9E\u6CA1\u6709\u53EF\u8865\u7684\u5C31\u8F93\u51FA\u7A7A\u6570\u7EC4\u3002',\n '\u957F\u5EA6\u7EAA\u5F8B\uFF1A\u6210\u54C1\u4E0D\u8D85\u8FC7\u539F\u8BDD\u7684 1.4 \u500D\uFF1B\u539F\u8BDD 30 \u5B57\u4EE5\u5185\u65F6\u4E0D\u8D85\u8FC7 60 \u5B57\u3002',\n ],\n advanced: [\n '\u3010\u672C\u8F6E\u4EFB\u52A1\uFF1A\u5728\u4E0D\u52A8\u76EE\u6807\u7684\u524D\u63D0\u4E0B\u628A\u547D\u4EE4\u8BF4\u6E05\u695A\u3011',\n '\u7528\u6237\u539F\u8BDD\u542B\u7CCA\u3001\u7F3A\u5173\u952E\u7EA6\u675F\u3002\u4F60\u8981\u8865\u7684\u662F\"\u7528\u6237\u663E\u7136\u60F3\u8981\u3001\u4F46\u6CA1\u8BF4\u51FA\u53E3\"\u7684\u5FC5\u8981\u4FE1\u606F\uFF0C',\n '\u8BA9\u5B83\u4E00\u6B21\u505A\u5BF9 \u2014\u2014 \u4F46\u6BCF\u4E00\u6761\u90FD\u5FC5\u987B\u662F**\u4ECE\u539F\u8BDD\u67D0\u4E00\u53E5\u76F4\u63A5\u63A8\u51FA**\u7684\uFF0C\u5E76\u5F15\u7528\u90A3\u4E00\u53E5\u3002',\n '\u5141\u8BB8\u4EA7\u51FA\uFF1A',\n '- `rewrite`\uFF1A\u628A\u542B\u7CCA\u3001\u6709\u75C5\u53E5\u7684\u5730\u65B9\u8BF4\u6E05\u695A\uFF08\u540C\u4E00\u6BB5\u539F\u8BDD\u6700\u591A\u4E00\u6761\uFF09\u3002',\n '- `requirement`\uFF1A\u4ECE\u539F\u8BDD\u76F4\u63A5\u63A8\u51FA\u7684\u6700\u4F4E\u4EA4\u4ED8\u8981\u6C42\u4E0E\u9A8C\u6536\u6807\u51C6\uFF08\"\u6539\u5B8C\u80FD\u8DD1\u8D77\u6765\"\"\u9875\u9762\u80FD\u6253\u5F00\"',\n ' \u8FD9\u7C7B\u53EF\u89C2\u6D4B\u7684\u8BDD\uFF09\uFF0C\u5199\u6210\u5BF9\u5DE5\u4F5C AI \u7684\u8981\u6C42\u800C\u4E0D\u662F\u8BC4\u8BBA\u3002\u6BCF\u6761\u90FD\u8981\u80FD\u6307\u56DE\u539F\u8BDD\u91CC\u7684\u67D0\u4E00\u53E5\u3002',\n '- `quality`\uFF1A\u7528\u6237\u8BF4\u7684\u8D28\u91CF\u8BCD\uFF08\"\u597D\u770B\u70B9\"\"\u9AD8\u7EA7\u611F\"\"\u6D41\u7545\"\uFF09\u2192 \u89E3\u91CA\u6210\u53EF\u89C2\u5BDF\u7684\u8981\u6C42\u3002',\n ' \u5B83\u662F**\u89E3\u91CA**\uFF0C\u4E0D\u662F\u65B0\u589E\u76EE\u6807\uFF1A\u4E00\u6761\u8D28\u91CF\u8BCD\u6700\u591A\u4E00\u6761 quality\u3002',\n '- `unknown`\uFF1A\u53EA\u6709\u7528\u6237\u80FD\u5B9A\u7684\u53D6\u820D\uFF08user_preference\uFF09/ \u8BE5\u53BB\u67E5\u8BC1\u7684\u4E8B\u5B9E\uFF08lookupable_fact\uFF09\u3002',\n '\u7981\u6B62\uFF1A\u65B0\u589E\u529F\u80FD\u3001\u65B0\u76EE\u6807\u3001\u65B0\u4F9D\u8D56\uFF1B\u865A\u6784\u9879\u76EE\u4E8B\u5B9E\uFF1B\u5199\u7528\u6237\u6CA1\u6388\u6743\u7684\u6280\u672F\u9009\u578B\u3002',\n '\u6570\u91CF\u7EAA\u5F8B\uFF1Arequirement \u6700\u591A 3 \u6761\uFF0Cquality \u6700\u591A 2 \u6761\uFF0Cunknown \u6700\u591A 2 \u6761\u3002',\n ],\n extreme: [\n '\u3010\u672C\u8F6E\u4EFB\u52A1\uFF1A\u628A\u8BC9\u6C42\u56FA\u5316\u6210\u4E00\u6761\u53EF\u76F4\u63A5\u6267\u884C\u7684\u547D\u4EE4\u3011',\n '\u8FD9\u6B21\u662F\u591A\u6B65\u6267\u884C\u7684\u590D\u6742\u4EFB\u52A1\uFF0C\u5DE5\u4F5C AI \u4F1A\u7167\u8FD9\u6761\u547D\u4EE4\u5E72\uFF0C\u7528\u6237\u4E0D\u4F1A\u518D\u8865\u5145\u3002',\n '\u5728\"\u9AD8\u7EA7\"\u6863\u5141\u8BB8\u7684\u5168\u90E8\u6761\u76EE\u7684\u57FA\u7840\u4E0A\uFF0C\u518D\u52A0\u4E24\u7C7B\uFF08\u90FD\u8981\u4EE5\u7528\u6237\u5728\u7ED9\u5DE5\u4F5C AI \u4E0B\u547D\u4EE4\u7684\u53E3\u543B\u5199\uFF09\uFF1A',\n '- `plan`\uFF1A\u5206\u9636\u6BB5\u6267\u884C\u8BA1\u5212\u3002\u6BCF\u9636\u6BB5\u5199\u6E05\u52A8\u4F5C\u4E0E\u4EA7\u51FA\uFF0C\u5E76\u5199\u660E\u7EAA\u5F8B\uFF08\u5148\u9A8C\u8BC1\u518D\u6539\u3001\u5931\u8D25\u5373\u56DE\u9000\u3001',\n ' \u4E0D\u64C5\u81EA\u6269\u5927\u8303\u56F4\u3001\u6539\u5B8C\u7ED9\u51FA\u8BC1\u636E\uFF09\u3002',\n '- `risk`\uFF1A\u591A\u60C5\u51B5\u9884\u6848 2~4 \u6761\uFF0C\u6BCF\u6761\u5199\u6210\"\u5982\u679C\u51FA\u73B0 <\u89E6\u53D1\u4FE1\u53F7>\uFF0C\u5C31\u5148 <\u5E94\u5BF9\u52A8\u4F5C>\uFF0C',\n ' \u4E0D\u8981 <\u7981\u6B62\u52A8\u4F5C>\"\u3002',\n '\u8FD8\u8981\u5224\u65AD\u8FD9\u6B21\u4EFB\u52A1\u662F\u5426\u503C\u5F97\u8BA9\u5DE5\u4F5C AI \u7528 goal / todo / \u8BA1\u5212\u6A21\u5F0F\u8DDF\u8E2A\uFF0C\u5E76\u628A\u7ED3\u8BBA\u5199\u6210',\n '`requirement` \u7684\u4E00\u90E8\u5206\uFF08\u4F8B\u5982\"\u8BF7\u5148\u5EFA\u7ACB goal\uFF1A\u2026\uFF0C\u518D\u6309\u4E0B\u5217\u9636\u6BB5\u63A8\u8FDB\"\uFF09\uFF1B\u4E0D\u9700\u8981\u5C31\u5B8C\u5168\u4E0D\u63D0\u3002',\n '\u94C1\u5F8B\uFF1A\u4E0D\u5F97\u865A\u6784\u9879\u76EE\u4E8B\u5B9E\u3002\u9700\u8981\u9879\u76EE\u4E8B\u5B9E\u65F6\u5199\u6210\"\u5148\u8BFB\u53D6/\u786E\u8BA4 X\"\u7684\u67E5\u8BC1\u52A8\u4F5C\u3002',\n '\u6570\u91CF\u7EAA\u5F8B\uFF1Aplan \u6700\u591A 1 \u6761\uFF0Crisk \u6700\u591A 4 \u6761\uFF0Crequirement \u6700\u591A 3 \u6761\u3002',\n ],\n}\n\n/** \u6863\u4F4D id \u4E0E\u7CFB\u7EDF\u63D0\u793A / \u6E29\u5EA6\u7684\u5BF9\u5E94\u8868\u3002 */\nexport const OPTIMIZER_SPECS = {\n basic: {\n temperature: 0.2,\n system: [RELAY_ROLE, TIER_TASKS.basic!.join('\\n'), EVIDENCE_RULES, STYLE_RULES].join('\\n\\n'),\n },\n advanced: {\n temperature: 0.3,\n system: [RELAY_ROLE, TIER_TASKS.advanced!.join('\\n'), EVIDENCE_RULES, STYLE_RULES].join('\\n\\n'),\n },\n extreme: {\n temperature: 0.3,\n system: [RELAY_ROLE, TIER_TASKS.extreme!.join('\\n'), EVIDENCE_RULES, STYLE_RULES].join('\\n\\n'),\n },\n} as const\n\n/** \u6863\u4F4D id \u8054\u5408\uFF08\u4E0E settings-contract \u7684 OptimizerTier \u4E00\u81F4\uFF0C\u6B64\u5904\u4E0D import \u4EE5\u514D\u5FAA\u73AF\uFF09\u3002 */\nexport type OptimizerSpecTier = keyof typeof OPTIMIZER_SPECS\n\n/** \u672A\u77E5\u6863\u4F4D\u56DE\u843D\u5230\u9ED8\u8BA4\u6863\uFF08\u4E0E `DEFAULT_OPTIMIZER_TIER` \u540C\u503C\uFF1B\u6B64\u5904\u4E0D import \u4EE5\u514D\u5FAA\u73AF\uFF09\u3002 */\nconst FALLBACK_TIER = 'advanced'\n\n/** \u53D6\u4E00\u4E2A\u6863\u4F4D\u7684\u8BF4\u660E\uFF08\u672A\u77E5\u6863\u8D70\u9ED8\u8BA4\u6863\uFF09\u3002 */\nfunction specOf(tier: string): { temperature: number; system: string } {\n return OPTIMIZER_SPECS[tier as OptimizerSpecTier] ?? OPTIMIZER_SPECS[FALLBACK_TIER as OptimizerSpecTier]\n}\n\n/**\n * \u7EC4\u88C5\u4E00\u6B21\u4F18\u5316\u7684 system \u63D0\u793A\u8BCD\u3002\n *\n * \u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\uFF08\u8BBE\u7F6E\u9875\u53EF\u7F16\u8F91\uFF09**\u6574\u4F53\u66FF\u6362**\u4EFB\u52A1\u6BB5\uFF0C\u4F46\u8F93\u51FA\u5951\u7EA6\u6C38\u8FDC\u8FFD\u52A0\u5728\u672B\u5C3E \u2014\u2014\n * \u5951\u7EA6\u662F\u5BBF\u4E3B\u89E3\u6790\u7684\u4F9D\u636E\uFF0C\u88AB\u6539\u6389\u6574\u5957\u673A\u5236\u5C31\u5931\u6548\uFF08\u8BBE\u7F6E\u9875\u5BF9\u6B64\u6709\u8BF4\u660E\uFF09\u3002\n * @param tier - \u5F3A\u5EA6\u6863\u4F4D\uFF1B\u672A\u77E5\u503C\u8D70 advanced\uFF08\u9ED8\u8BA4\u6863\uFF09\u3002\n * @param custom - \u8BBE\u7F6E\u9875\u91CC\u7684\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\uFF1B\u7A7A\u4E32 = \u7528\u5185\u7F6E\u90A3\u4EFD\u3002\n * @returns \u8BE5\u6863\u4F4D\u7684\u5B8C\u6574\u7CFB\u7EDF\u63D0\u793A\u8BCD\u3002\n */\nexport function buildOptimizeSystem(tier: string, custom = ''): string {\n const body = custom.trim() === '' ? specOf(tier).system : custom.trim()\n return `${body}\\n\\n${OPTIMIZER_OUTPUT_CONTRACT}`\n}\n\n/**\n * \u7EC4\u88C5\u4E00\u6B21\u4F18\u5316\u7684 temperature\u3002\n * @param tier - \u5F3A\u5EA6\u6863\u4F4D\uFF1B\u672A\u77E5\u503C\u8D70 advanced\u3002\n * @returns \u8BE5\u6863\u4F4D\u7684\u91C7\u6837\u6E29\u5EA6\u3002\n */\nexport function buildOptimizeTemperature(tier: string): number {\n return specOf(tier).temperature\n}\n\n/**\n * \u8FD9\u6B21\u7528\u7684\u662F\u81EA\u5B9A\u4E49\u8FD8\u662F\u5185\u7F6E\u63D0\u793A\u8BCD\uFF08\u56DE\u4F20\u7ED9\u9762\u677F\uFF0C\u65B9\u4FBF\u7528\u6237\u786E\u8BA4\u81EA\u5DF1\u90A3\u4EFD\u771F\u7684\u751F\u6548\u4E86\uFF09\u3002\n * @param custom - \u8BBE\u7F6E\u9875\u91CC\u7684\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u3002\n * @returns 'custom' = \u7528\u4E86\u7528\u6237\u90A3\u4EFD\uFF1B'builtin' = \u7528\u4E86\u5185\u7F6E\u90A3\u4EFD\u3002\n */\nexport function optimizePromptSource(custom: string): 'custom' | 'builtin' {\n return String(custom ?? '').trim() === '' ? 'builtin' : 'custom'\n}\n\n/**\n * \u4F20\u8BDD\u6846\u67B6\uFF1A\u628A\u7528\u6237\u539F\u8BDD\u5305\u6210\u300C\u5F85\u8F6C\u8FBE\u5185\u5BB9\u300D\u800C\u4E0D\u662F\u300C\u5BF9\u4F60\u8BF4\u7684\u8BDD\u300D\u3002\n *\n * \u8FD9\u662F\u539F\u4F5C\u8005\u4FEE\u300C\u4F18\u5316 AI \u4EE5\u4E3A\u81EA\u5DF1\u5728\u548C\u7528\u6237\u5BF9\u8BDD\u300D\u7684\u5173\u952E\u4E00\u62DB \u2014\u2014 \u88F8\u6587\u672C\u4F1A\u88AB\u5F53\u6210\n * \u5BF9\u8BDD\u8F93\u5165\uFF0C\u4E8E\u662F\u6A21\u578B\u5F00\u59CB\u56DE\u5E94\u4F60\u800C\u4E0D\u662F\u66FF\u4F60\u8F6C\u8FBE\u3002\n * @param original - \u8F93\u5165\u6846\u91CC\u7684\u539F\u8BDD\u3002\n * @param options - `retry`\uFF1A\u4E0A\u4E00\u6B21\u4EA7\u51FA\u4E3A\u7A7A\uFF0C\u6309\u5BF9\u65B9 0.6 \u7684 `retryEmpty` \u518D\u70B9\u4E00\u904D\u89C4\u5219\n * \uFF08\u5BF9\u65B9\u7684\u771F\u673A\u6559\u8BAD\uFF1A\u77ED\u6D88\u606F/\u8001\u4F1A\u8BDD\u4F1A\u53CD\u590D\"\u601D\u8003\u5B8C\u6210\u5374\u6CA1\u6709\u4EA7\u51FA\"\uFF09\u3002\n * @returns \u76F4\u63A5\u4F5C\u4E3A user \u6D88\u606F\u53D1\u9001\u7684\u6587\u672C\u3002\n */\nexport function buildOptimizeUser(\n original: string,\n options: { readonly retry?: boolean; readonly reason?: string } = {},\n): string {\n const parts = [\n '\u3010\u5F85\u8F6C\u8FBE\u5185\u5BB9\u3011\u4E0B\u9762\u662F\"\u7528\u6237\"\u53D1\u7ED9\u6211\u7684\u539F\u8BDD\u3002**\u5B83\u4E0D\u662F\u8BF4\u7ED9\u4F60\u542C\u7684**\uFF0C\u4F60\u4E0D\u9700\u8981\u56DE\u5E94\u5B83\u3001\u4E5F\u4E0D\u9700\u8981\u66FF\u7528\u6237\u53BB\u505A\u8FD9\u4EF6\u4E8B\u3002',\n '<\u539F\u6587>',\n String(original ?? ''),\n '</\u539F\u6587>',\n '',\n '\u3010\u4F60\u7684\u4EFB\u52A1\u3011\u6309\u7CFB\u7EDF\u63D0\u793A\u8BCD\u7684\u89C4\u5219\uFF0C\u628A\u4E0A\u9762\u7684\u539F\u8BDD\u62C6\u6210**\u6761\u76EE**\u5E76\u7ED9\u6BCF\u6761\u9644\u4E0A**\u9010\u5B57\u5F15\u6587**\u3002',\n '- \u53EA\u8F93\u51FA\u90A3\u4EFD JSON \u5951\u7EA6\u8981\u6C42\u7684\u4E1C\u897F\uFF1B\u4E0D\u8981\u56DE\u5E94\u6211\u3001\u4E0D\u8981\u56DE\u7B54\u95EE\u9898\u3001\u4E0D\u8981\u8C22\u5E55\u3001\u4E0D\u8981\u89E3\u91CA\u4F60\u505A\u4E86\u4EC0\u4E48\u3002',\n '- \u8BFB\u8005\u53EA\u6709\"\u5DE5\u4F5C AI\"\u4E00\u4E2A\uFF0C\u800C\u4F60\u7684\u4EA7\u51FA\u4F1A\u5148\u7ECF\u5BBF\u4E3B\u9010\u6761\u6838\u5BF9\u5F15\u6587\u3002',\n ]\n if (options.retry === true) {\n parts.push(\n '',\n `\u3010\u91CD\u8981\uFF1A\u4F60\u4E0A\u4E00\u6B21\u7684\u8F93\u51FA\u662F\u7A7A\u7684${options.reason ? `\uFF08${options.reason}\uFF09` : ''}\u3011`,\n '\u4E0A\u4E00\u6B21\u4F60\u6CA1\u6709\u7ED9\u51FA\u4EFB\u4F55\u6761\u76EE\uFF0C\u8FD9\u4E00\u8F6E\u56E0\u6B64**\u6CA1\u6709\u4EFB\u4F55\u8865\u5168**\u53EF\u4EE5\u4EA4\u7ED9\u5DE5\u4F5C AI\u3002',\n '\u8BF7\u6309\u7CFB\u7EDF\u63D0\u793A\u8BCD\u7684\u786C\u89C4\u5219\u91CD\u505A\uFF1A**\u54EA\u6015\u7528\u6237\u53EA\u5199\u4E86\u4E00\u4E24\u4E2A\u5B57\uFF0C\u4E5F\u8981\u5C3D\u91CF\u628A\u5B83\u62C6\u6210\u53EF\u5F15\u7528\u7684\u6761\u76EE**',\n '\uFF08\u81F3\u5C11\u4E00\u6761 `rewrite`\uFF0C\u6216\u4E00\u6761 `quality` / `unknown`\uFF09\uFF1B\u786E\u5B9E\u6CA1\u6709\u53EF\u8865\u7684\u5185\u5BB9\u65F6\u624D\u8F93\u51FA {\"items\":[]}\u3002',\n '\u53EA\u8F93\u51FA JSON\u3002',\n )\n }\n return parts.join('\\n')\n}\n", "/**\n * \u8BBE\u7F6E\u9875\u91CC\u7684\u300C\u672C\u6863\u63D0\u793A\u8BCD\u300D\u7F16\u8F91\u5668\uFF080.6.0 \u8D77\uFF09\u3002\n *\n * \u4E3A\u4EC0\u4E48\u9700\u8981\u5B83\uFF1A0.6.0 \u628A\u63D0\u793A\u8BCD\u4F18\u5316\u6539\u6210\u4E86\u300C\u6A21\u578B\u53EA\u4EA7\u6761\u76EE\u3001\u5BBF\u4E3B\u6309\u9010\u5B57\u4F9D\u636E\u6838\u5BF9\u540E\u88C5\u914D\u300D\n * \uFF08\u505A\u6CD5\u53D6\u81EA WestFox-AwA/dsh-prompt-optimizer \u7684 0.6 \u7EBF\uFF09\u3002\u6A21\u578B\u884C\u4E3A\u4E0D\u5408\u53E3\u5473\u65F6\uFF0C\n * \u7528\u6237\u552F\u4E00\u80FD\u8C03\u7684\u5C31\u662F\u90A3\u4EFD\u4EFB\u52A1\u63D0\u793A\u8BCD \u2014\u2014 \u6240\u4EE5\u5FC5\u987B\u53EF\u7F16\u8F91\u3001\u53EF\u6062\u590D\u3001\u4E14\u80FD\u770B\u89C1\u5185\u7F6E\u90A3\u4EFD\u957F\u4EC0\u4E48\u6837\u3002\n *\n * \u4E24\u6761\u523B\u610F\u7684\u8BBE\u8BA1\uFF1A\n * \u00B7 **\u7559\u7A7A = \u7528\u5185\u7F6E**\uFF1A\u7A7A\u4E32\u65E2\u662F\"\u6CA1\u81EA\u5B9A\u4E49\"\u7684\u8868\u793A\uFF0C\u4E5F\u662F\u300C\u6062\u590D\u5185\u7F6E\u300D\u8981\u5199\u56DE\u7684\u503C\uFF0C\n * \u4E0D\u5FC5\u518D\u591A\u4E00\u4E2A\"\u662F\u5426\u81EA\u5B9A\u4E49\"\u7684\u5F00\u5173\uFF08\u591A\u4E00\u4E2A\u5F00\u5173\u5C31\u591A\u4E00\u79CD\u81EA\u76F8\u77DB\u76FE\u7684\u72B6\u6001\uFF09\u3002\n * \u00B7 **JSON \u8F93\u51FA\u5951\u7EA6\u4E0D\u7ED9\u6539**\uFF1A\u5BBF\u4E3B\u6309\u5B83\u89E3\u6790\u6761\u76EE\u3001\u505A\u9010\u5B57\u4F9D\u636E\u6BD4\u5BF9\uFF1B\u5951\u7EA6\u88AB\u6539\u6389\uFF0C\n * \"\u4E0D\u8BB8\u51ED\u7A7A\u65B0\u589E\u9700\u6C42\"\u5C31\u9000\u5316\u6210\u4E00\u53E5\u7A7A\u8BDD\u3002\u6240\u4EE5\u8FD9\u91CC\u660E\u8BF4\uFF0C\u5E76\u628A\u5951\u7EA6\u7559\u5728\u63D2\u4EF6\u91CC\u8FFD\u52A0\u3002\n */\nimport {\n OPTIMIZER_PROMPT_MAX, OPTIMIZER_TIERS,\n type OptimizerTier,\n} from '../settings-contract.ts'\nimport { OPTIMIZER_SPECS, OPTIMIZER_OUTPUT_CONTRACT } from '../optimizer-prompt.ts'\nimport { pill, row, rowDesc, rowText, rowTitle, textInput } from './styles.ts'\n\n/** \u7EC4\u4EF6\u5165\u53C2\u3002 */\nexport interface OptimizerPromptEditorProps {\n /** \u5F53\u524D\u6863\u4F4D\uFF08\u51B3\u5B9A\u7F16\u8F91\u54EA\u4E00\u4EFD\u3001\u4EE5\u53CA\"\u8F7D\u5165\u5185\u7F6E\u7248\"\u8F7D\u5165\u54EA\u4E00\u4EFD\uFF09\u3002 */\n readonly tier: OptimizerTier\n /** \u8BE5\u6863\u4F4D\u5F53\u524D\u7684\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\uFF08'' = \u7528\u5185\u7F6E\uFF09\u3002 */\n readonly value: string\n /** \u5199\u56DE\u8BE5\u6863\u4F4D\u7684\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u3002 */\n readonly onChange: (next: string) => void\n}\n\n/** \u5185\u7F6E\u7684\u4EFB\u52A1\u63D0\u793A\u8BCD\u6B63\u6587\uFF08**\u4E0D\u542B**\u8F93\u51FA\u5951\u7EA6\u2014\u2014\u5951\u7EA6\u7531\u5BBF\u4E3B\u8FFD\u52A0\uFF0C\u89C1\u6587\u4EF6\u5934\u6CE8\u91CA\uFF09\u3002 */\nexport function builtinTaskPrompt(tier: string): string {\n return OPTIMIZER_SPECS[tier as OptimizerTier]?.system ?? OPTIMIZER_SPECS.advanced.system\n}\n\n/**\n * \u5F53\u524D\u6863\u4F4D\u7684\u63D0\u793A\u8BCD\u7F16\u8F91\u5757\u3002\n * @param props - \u6863\u4F4D\u3001\u5F53\u524D\u503C\u3001\u5199\u56DE\u56DE\u8C03\u3002\n */\nexport function OptimizerPromptEditor({ tier, value, onChange }: OptimizerPromptEditorProps) {\n const label = OPTIMIZER_TIERS.find(item => item.id === tier)?.label ?? tier\n const custom = value.trim() !== ''\n return (\n <div style={{ ...row, borderTop: 'none', flexDirection: 'column', alignItems: 'stretch', gap: 8 }}>\n <div style={rowText}>\n <div style={rowTitle}>\n {`\u672C\u6863\u63D0\u793A\u8BCD\uFF08${label}\uFF09`}\n <span style={{ marginLeft: 8, opacity: 0.75 }}>{custom ? '\u81EA\u5B9A\u4E49' : '\u5185\u7F6E'}</span>\n </div>\n <div style={rowDesc}>\n \u7559\u7A7A = \u7528\u63D2\u4EF6\u5185\u7F6E\u90A3\u4EFD\u3002\u6539\u7684\u662F\u300C\u4EFB\u52A1\u4E0E\u98CE\u683C\u300D\u8FD9\u6BB5\uFF1B\n {' '}<strong>JSON \u8F93\u51FA\u5951\u7EA6</strong>\u7531\u63D2\u4EF6\u5728\u672B\u5C3E\u8FFD\u52A0\u3001\u4E0D\u5728\u8FD9\u91CC\u6539 \u2014\u2014\n \u5BBF\u4E3B\u9760\u5B83\u9010\u6761\u6838\u5BF9\u300C\u6BCF\u6761\u8865\u5168\u90FD\u6307\u56DE\u4F60\u539F\u8BDD\u91CC\u7684\u67D0\u53E5\u300D\uFF0C\u5951\u7EA6\u88AB\u6539\u6389\u8FD9\u5957\u6821\u9A8C\u5C31\u6CA1\u4E86\u3002\n </div>\n </div>\n <textarea\n value={value}\n placeholder={'\u7559\u7A7A = \u7528\u5185\u7F6E\u63D0\u793A\u8BCD\u3002\u70B9\u4E0B\u9762\u7684\u300C\u8F7D\u5165\u5185\u7F6E\u7248\u300D\u53EF\u4EE5\u5148\u628A\u5185\u7F6E\u90A3\u4EFD\u6284\u8FDB\u6765\u518D\u6539\u3002'}\n maxLength={OPTIMIZER_PROMPT_MAX}\n spellCheck={false}\n rows={value.trim() === '' ? 3 : Math.min(16, Math.max(6, Math.ceil(value.length / 60)))}\n onChange={event => { onChange(event.target.value) }}\n style={{ ...textInput, resize: 'vertical', fontFamily: 'inherit', lineHeight: 1.5 }}\n />\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>\n <button\n type=\"button\"\n style={pill}\n title=\"\u628A\u5185\u7F6E\u90A3\u4EFD\u4EFB\u52A1\u63D0\u793A\u8BCD\u6284\u8FDB\u8F93\u5165\u6846\uFF0C\u65B9\u4FBF\u5728\u6B64\u57FA\u7840\u4E0A\u6539\"\n onClick={() => { onChange(builtinTaskPrompt(tier)) }}\n >\n \u8F7D\u5165\u5185\u7F6E\u7248\n </button>\n <button\n type=\"button\"\n style={pill}\n disabled={!custom}\n title=\"\u6E05\u7A7A\u81EA\u5B9A\u4E49\uFF0C\u6539\u7528\u5185\u7F6E\u63D0\u793A\u8BCD\"\n onClick={() => { onChange('') }}\n >\n \u6062\u590D\u5185\u7F6E\n </button>\n <span style={{ ...rowDesc, flex: '1 1 auto' }}>\n {`\u5F53\u524D\u5B57\u6570 ${String(value.length)} / ${String(OPTIMIZER_PROMPT_MAX)}`}\n </span>\n </div>\n <details>\n <summary style={{ ...rowDesc, cursor: 'pointer' }}>\u770B\u63D2\u4EF6\u56FA\u5B9A\u8FFD\u52A0\u7684\u90A3\u6BB5\u8F93\u51FA\u5951\u7EA6</summary>\n <pre style={{ ...rowDesc, whiteSpace: 'pre-wrap', margin: '6px 0 0' }}>{OPTIMIZER_OUTPUT_CONTRACT}</pre>\n </details>\n </div>\n )\n}\n", "/**\n * \u901A\u7528\u300CN \u9009\u4E00\u300D\u80F6\u56CA\u63A7\u4EF6\uFF1A\u4E00\u884C\u4E92\u65A5\u5C0F\u80F6\u56CA\uFF0C\u9009\u4E2D\u6001\u53EA\u6539\u8FB9\u6846\u4E0E\u6587\u5B57\u8272\u3002\n *\n * \u4E3A\u4EC0\u4E48\u62BD\u51FA\u6765\u5171\u7528\uFF1A\u63D2\u5165\u6A21\u5F0F\uFF08\u5173 / \u6BCF\u6B21 / \u4EC5\u9996\u6B21\uFF09\u4E0E\u53F3\u952E\u83DC\u5355\u6A21\u5F0F\uFF08\u5B98\u65B9 / \u6D4F\u89C8\u5668 / \u81EA\u5B9A\u4E49\uFF09\n * \u662F\u540C\u4E00\u79CD\u4EA4\u4E92\u2014\u2014\u4E00\u7EC4\u4E92\u65A5\u9009\u9879\u3001\u5F53\u524D\u9879\u9AD8\u4EAE\u3001\u6BCF\u9879\u7528\u60AC\u505C\u63D0\u793A\u8BF4\u6E05\u5B83\u505A\u4EC0\u4E48\u3002\u8BA9\u4E24\u5904\u6E32\u67D3\u540C\u4E00\u4E2A\n * \u7EC4\u4EF6\uFF0C\u6837\u5F0F\u4E0E\u65E0\u969C\u788D\u884C\u4E3A\u5C31\u4E0D\u4F1A\u5404\u5199\u4E00\u904D\u7136\u540E\u6162\u6162\u5206\u53C9\u3002\n *\n * \u9009\u4E2D\u6001\u4E3A\u4EC0\u4E48\u4E0D\u7528\u5B9E\u8272\u586B\u5145\uFF1A\u5B9E\u8272\u8981\u914D\u300C\u586B\u5145 + \u524D\u666F\u300D\u4E24\u4E2A\u4EE4\u724C\uFF0C0.2.0 \u5C31\u56E0\u4E3A\u53EA\u5199\u4E86\u4E00\u534A\u800C\u5728\n * \u6DF1\u8272\u4E3B\u9898\u4E0B\u53D8\u6210\u767D\u5E95\u767D\u5B57\u3002\u53EA\u6539\u8FB9\u6846\u548C\u6587\u5B57\u8272\u5C31\u4E0D\u5FC5\u914D\u5BF9\uFF0C\u4E5F\u5C31\u4E0D\u4F1A\u91CD\u6F14\u3002\n */\nimport React from 'react'\nimport type { CSSProperties } from 'react'\n\n/** \u4E00\u4E2A\u9009\u9879\u3002 */\nexport interface PillChoiceItem<T extends string> {\n readonly id: T\n readonly label: string\n /** \u60AC\u505C\u63D0\u793A\uFF1A\u8FD9\u4E00\u6863\u5230\u5E95\u505A\u4EC0\u4E48\u3002 */\n readonly hint: string\n}\n\n/** \u7EC4\u4EF6\u6CE8\u5165\u9762\u3002 */\nexport interface PillChoiceProps<T extends string> {\n /** \u9009\u9879\uFF08\u6570\u7EC4\u987A\u5E8F\u5373\u754C\u9762\u987A\u5E8F\uFF09\u3002 */\n readonly items: readonly PillChoiceItem<T>[]\n /** \u5F53\u524D\u9009\u4E2D\u7684\u90A3\u4E2A\u3002 */\n readonly value: T\n /** \u7528\u6237\u9009\u4E86\u53E6\u4E00\u4E2A\u3002 */\n readonly onChange: (value: T) => void\n /** \u65E0\u969C\u788D\u7EC4\u540D\uFF08\u540C\u4E00\u5C4F\u53EF\u80FD\u6709\u591A\u4E2A\u8FD9\u6837\u7684\u63A7\u4EF6\uFF0C\u8981\u80FD\u5206\u8FA8\uFF09\u3002 */\n readonly ariaLabel: string\n /** \u9762\u677F\u91CC\u66F4\u7D27\u51D1\uFF08\u7A7A\u95F4\u7D27\u5F20\uFF09\u3002 */\n readonly compact?: boolean\n}\n\nconst base: CSSProperties = {\n border: '0.5px solid var(--dsw-alias-border-l2)',\n background: 'transparent',\n color: 'var(--dsw-alias-label-tertiary)',\n borderRadius: 999,\n cursor: 'pointer',\n lineHeight: 1,\n whiteSpace: 'nowrap',\n}\n\n/** \u9009\u4E2D\u6001\u53EA\u6539\u8FB9\u6846\u4E0E\u6587\u5B57\u8272\uFF0C\u4E0D\u7528\u5B9E\u8272\u586B\u5145\uFF08\u89C1\u6587\u4EF6\u5934\u8BF4\u660E\uFF09\u3002 */\nconst active: CSSProperties = {\n ...base,\n border: '0.5px solid var(--dsw-alias-brand-primary)',\n color: 'var(--dsw-alias-label-primary)',\n fontWeight: 600,\n}\n\n/** \u6E32\u67D3\u4E00\u7EC4\u4E92\u65A5\u80F6\u56CA\u3002 */\nexport function PillChoice<T extends string>({\n items, value, onChange, ariaLabel, compact = false,\n}: PillChoiceProps<T>) {\n return (\n <div\n role=\"group\"\n aria-label={ariaLabel}\n style={{ display: 'inline-flex', alignItems: 'center', gap: 2, flex: '0 0 auto' }}\n >\n {items.map(item => (\n <button\n key={item.id}\n type=\"button\"\n title={item.hint}\n aria-pressed={value === item.id}\n style={{\n ...(value === item.id ? active : base),\n fontSize: compact ? 10 : 11,\n padding: compact ? '3px 5px' : '4px 7px',\n }}\n // \u4E0D\u8BA9\u6309\u94AE\u62A2\u8D70\u8F93\u5165\u6846\u91CC\u53EF\u80FD\u5B58\u5728\u7684\u9009\u533A\uFF08\u4E0E\u5DE5\u5177\u884C\u5176\u5B83\u6309\u94AE\u4E00\u81F4\uFF09\u3002\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { onChange(item.id) }}\n >\n {item.label}\n </button>\n ))}\n </div>\n )\n}\n", "/**\n * \u63D2\u5165\u6A21\u5F0F\u7684\u4E09\u9009\u4E00\u63A7\u4EF6\uFF08\u5173 / \u6BCF\u6B21 / \u4EC5\u9996\u6B21\uFF09\uFF1A\u9762\u677F\u4E0E\u8BBE\u7F6E\u9875\u5171\u7528\u3002\n *\n * \u4E3A\u4EC0\u4E48\u662F**\u4E00\u4E2A**\u63A7\u4EF6\u800C\u4E0D\u662F\u4E24\u4E2A\u52FE\u9009\u6846\uFF1A\u300C\u6BCF\u6B21\u300D\u4E0E\u300C\u4EC5\u9996\u6B21\u300D\u4E92\u76F8\u6392\u65A5\uFF0C\u4E24\u4E2A\u72EC\u7ACB\u52FE\u9009\u6846\n * \u5C31\u80FD\u9020\u51FA\u300C\u540C\u65F6\u53C8\u6BCF\u6B21\u53C8\u4EC5\u9996\u6B21\u300D\u7684\u77DB\u76FE\u72B6\u6001\u3002\u8FD9\u91CC\u53EA\u53D1\u51FA\u4E00\u4E2A mode\uFF0C\u7531\n * `withInsertMode` \u4E00\u6B21\u628A\u4E24\u4E2A\u6807\u5FD7\u5199\u5BF9\u3002\n *\n * \u6E32\u67D3\u4EA4\u7ED9\u901A\u7528\u7684 `PillChoice`\uFF08\u53F3\u952E\u83DC\u5355\u6A21\u5F0F\u4E5F\u7528\u540C\u4E00\u4E2A\uFF0C\u89C1\u8BE5\u6587\u4EF6\uFF09\u3002\n */\nimport React from 'react'\nimport { INSERT_MODES, type InsertMode } from '../settings-contract.ts'\nimport { PillChoice } from './PillChoice.tsx'\n\n/** \u7EC4\u4EF6\u6CE8\u5165\u9762\u3002 */\nexport interface InsertModeControlProps {\n /** \u5F53\u524D\u6A21\u5F0F\u3002 */\n readonly mode: InsertMode\n /** \u7528\u6237\u9009\u4E86\u53E6\u4E00\u4E2A\u6A21\u5F0F\u3002 */\n readonly onChange: (mode: InsertMode) => void\n /** \u9762\u677F\u91CC\u66F4\u7D27\u51D1\uFF08\u7A7A\u95F4\u7D27\u5F20\uFF09\u3002 */\n readonly compact?: boolean\n /** \u65E0\u969C\u788D\u6807\u7B7E\uFF1A\u5217\u8868\u91CC\u533A\u5206\u662F\u54EA\u4E00\u6761\uFF08\u540C\u4E00\u5C4F\u4F1A\u6709\u5F88\u591A\u4E2A\uFF09\u3002 */\n readonly label?: string\n}\n\n/** \u300C\u5173 / \u6BCF\u6B21 / \u4EC5\u9996\u6B21\u300D\u3002 */\nexport function InsertModeControl({ mode, onChange, compact = false, label }: InsertModeControlProps) {\n return (\n <PillChoice\n items={INSERT_MODES}\n value={mode}\n onChange={onChange}\n compact={compact}\n ariaLabel={label === undefined ? '\u53D1\u9001\u65F6\u63D2\u5165' : `\u53D1\u9001\u65F6\u63D2\u5165\uFF08${label}\uFF09`}\n />\n )\n}\n", "/**\n * \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u6309\u94AE\uFF1A\u5750\u5728\u5B98\u65B9\u8F93\u5165\u5361\u7247\u5DE5\u5177\u884C\u91CC\u300C\u5C55\u5F00\u300D\u6309\u94AE\u7684\u65C1\u8FB9\n * \uFF08\u69FD\u4F4D `conversation.input.right`\uFF0Corder 89 < \u5C55\u5F00\u7684 90\uFF09\uFF0C\u5F62\u72B6\u4E0E\u5B83\u540C\u6B3E\u80F6\u56CA\u3002\n *\n * \u672C\u7EC4\u4EF6\u53EA\u505A\u4E09\u4EF6\u4E8B\uFF1A\n * 1. \u628A\u5B98\u65B9\u7684 `inputActions` \u4E0E\u5F53\u524D\u8349\u7A3F\u6295\u9012\u7ED9 quick-commands \u6865\u63A5\n * \uFF08\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u7684\u53D1\u9001\u62E6\u622A\u5FC5\u987B\u62FF\u5230\u5B83\u4EEC\uFF0C\u62E6\u622A\u5668\u6D3B\u5728 React \u4E4B\u5916\uFF09\uFF1B\n * 2. \u6E32\u67D3\u6309\u94AE\u3001\u70B9\u51FB\u540E\u628A\u81EA\u8EAB\u77E9\u5F62\u4EA4\u7ED9\u9762\u677F\u505A\u951A\u70B9\uFF1B\n * 3. \u628A\u9762\u677F\u7684\u5F00\u5408\u72B6\u6001\u53CD\u5C04\u5230 `aria-expanded`\u3002\n */\nimport React, { useEffect, useRef } from 'react'\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport { activeSections, type ComposerUxSettings } from '../settings-contract.ts'\nimport { publishInputBridge, releaseInputBridge, type InputActionsLike } from './quick-commands.ts'\nimport { QUICK_BUTTON_CLASS } from './quick-style.ts'\n\n/** \u9762\u677F\u951A\u70B9\uFF1A\u6309\u94AE\u7684\u89C6\u53E3\u77E9\u5F62\uFF08\u9762\u677F\u636E\u6B64\u8D34\u5728\u4E0A\u65B9\uFF09\u3002 */\nexport interface QuickPanelAnchor {\n readonly left: number\n readonly bottom: number\n readonly width: number\n}\n\n/** \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u6CE8\u5165\u9762\u3002 */\nexport interface QuickCommandsInjected {\n hooks: {\n /** \u5F53\u524D\u8BBE\u7F6E\uFF08\u603B\u5F00\u5173\u4E0E\u5FEB\u6377\u6307\u4EE4\u5217\u8868\uFF09\u3002 */\n live: SnapshotStore<ComposerUxSettings>\n /** \u9762\u677F\u951A\u70B9\uFF1Bnull = \u9762\u677F\u5173\u95ED\u3002 */\n panel: SnapshotStore<QuickPanelAnchor | null>\n }\n actions: {\n /** \u4EE5\u7ED9\u5B9A\u951A\u70B9\u6253\u5F00\u9762\u677F\uFF1B\u5DF2\u5F00\u5219\u5173\u95ED\uFF08\u70B9\u6309\u94AE\u5373\u5F00\u5408\uFF09\u3002 */\n toggle: (anchor: QuickPanelAnchor) => void\n }\n}\n\nexport type QuickCommandsButtonProps =\n PropsRuntime<'conversation.input.right'>\n & InjectFace<QuickCommandsInjected>\n\n/** \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u5165\u53E3\u6309\u94AE\u3002 */\nexport function QuickCommandsButton({\n useInput, inputActions, sessionId, useSession, useLive, usePanel, actions,\n}: QuickCommandsButtonProps) {\n const settings = useLive(item => item)\n const anchor = usePanel(item => item)\n const draft = useInput(state => state.draft)\n /**\n * \u4F1A\u8BDD\u662F\u4E0D\u662F\u8FD8\u6CA1\u6709\u4EFB\u4F55\u6D88\u606F \u2014\u2014 \u300C\u4EC5\u9996\u6B21\u63D2\u5165\u300D\u7684\u5224\u636E\u3002\n *\n * `useSession` \u662F `conversation.input.right`\uFF08scope: session\uFF09\u7684\u6807\u51C6 props\uFF0C\u4E0E\u672C\u7EC4\u4EF6\n * \u5DF2\u7ECF\u5728\u7528\u7684 `useInput` \u6765\u81EA\u540C\u4E00\u4EFD\u5951\u7EA6\uFF0C\u6240\u4EE5\u65E0\u6761\u4EF6\u8C03\u7528\u5B83\uFF1B\u9009\u62E9\u5668\u91CC\u518D\u6321\u4E00\u5C42 undefined\n * \uFF08\u9009\u62E9\u5668\u629B\u9519\u4F1A\u76F4\u63A5\u628A React \u6E32\u67D3\u6253\u65AD\uFF0C\u8FD9\u91CC\u4E0D\u503C\u5F97\u5192\u9669\uFF09\u3002\n */\n const blank = useSession(state => state?.blank === true)\n const ref = useRef<HTMLButtonElement | null>(null)\n\n // \u6BCF\u6B21\u6E32\u67D3\u628A\u5B98\u65B9\u8F93\u5165\u52A8\u4F5C\u3001\u8349\u7A3F\u4E0E\u300C\u4F1A\u8BDD\u8FD8\u662F\u7A7A\u7684\u300D\u6295\u9012\u7ED9\u6865\u63A5\uFF1A\n // \u62E6\u622A\u5668\u8981\u5728 React \u4E4B\u5916\u8BFB\u5B83\u4EEC\uFF0C\u800C\u8FD9\u4E9B\u53EA\u6709\u69FD\u4F4D\u80FD\u62FF\u5230\u3002\n useEffect(() => {\n const sid = typeof sessionId === 'string' ? sessionId : ''\n publishInputBridge({\n actions: (inputActions ?? null) as InputActionsLike | null,\n draft: typeof draft === 'string' ? draft : '',\n sessionId: sid,\n blank: blank === true,\n })\n return () => { releaseInputBridge(sid) }\n }, [inputActions, draft, sessionId, blank])\n\n // \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u680F\uFF08\u6216\u603B\u5F00\u5173\uFF09\u5173\u7740\u65F6\u8FD9\u679A\u6309\u94AE\u6574\u4E2A\u4E0D\u51FA\u73B0\u3002\n if (!activeSections(settings).quick) return null\n\n const open = anchor !== null\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={QUICK_BUTTON_CLASS}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n title=\"\u5FEB\u6377\u6307\u4EE4\uFF1A\u4E00\u952E\u63D2\u5165\u5E38\u7528\u63D0\u793A\u8BCD\uFF0C\u6216\u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u4F18\u5316\u6210\u4E00\u6761\u6E05\u6670\u7684\u6307\u4EE4\"\n // \u6837\u5F0F\u5168\u90E8\u6765\u81EA\u6CE8\u5165\u7684\u6837\u5F0F\u8868\uFF08\u89C1 quick-style.ts\uFF09\uFF1A\u4E0E\u65C1\u8FB9\u5B98\u65B9\u300C\u5C55\u5F00\u300D\u6309\u94AE\n // \u9010\u9879\u5BF9\u9F50\uFF0C\u4E14 hover / \u5C55\u5F00\u6001\u53EA\u6709\u6837\u5F0F\u8868\u80FD\u8868\u8FBE\u3002\n // \u4E0D\u8BA9\u6309\u94AE\u62A2\u8D70\u62D6\u52A8\u65F6\u53EF\u80FD\u5B58\u5728\u7684\u8F93\u5165\u6846\u9009\u533A\uFF08\u4E0E\u5B98\u65B9\u5DE5\u5177\u884C\u4E00\u81F4\uFF09\u3002\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => {\n const rect = ref.current?.getBoundingClientRect()\n actions.toggle({\n left: rect?.left ?? 0,\n bottom: rect?.bottom ?? 0,\n width: rect?.width ?? 0,\n })\n }}\n >\n <svg\n viewBox=\"0 0 16 16\"\n width=\"12\"\n height=\"12\"\n aria-hidden\n >\n <path\n d=\"M9.2 1.2 3.4 9.1h3.5l-0.9 5.7 6-8.1H8.4l0.8-5.5Z\"\n fill=\"currentColor\"\n />\n </svg>\n <span>\u5FEB\u6377\u6307\u4EE4</span>\n </button>\n )\n}\n", "/**\n * \u300C\u5FEB\u6377\u6307\u4EE4\u300D\u5C55\u5F00\u9762\u677F\uFF1A\u6CE8\u518C\u8FDB shell.overlay\uFF08root \u7EA7\u6D6E\u5C42\uFF0C\u4E0D\u53D7\u8F93\u5165\u5361\u7247\u88C1\u526A\uFF09\u3002\n *\n * \u9762\u677F\u5F62\u6001\uFF080.3.0 \u8D77\u662F**\u5206\u7C7B\u4E24\u7EA7**\u7ED3\u6784\uFF09\uFF1A\n * - \u9876\u90E8\uFF1A\u300C\u2728 \u4F18\u5316\u63D0\u793A\u8BCD\u300D\u4E3B\u6309\u94AE + \u4E09\u6863\u5F3A\u5EA6\u5206\u6BB5\u63A7\u4EF6\uFF1B\n * - \u5206\u7C7B\u884C\uFF1A\u4E00\u4E2A\u5206\u7C7B\u4E00\u4E2A\u6807\u7B7E\uFF0C\u70B9\u5B83\u5207\u6362\uFF1B\u300C\uFF0B \u65B0\u5206\u7C7B\u300D\u76F4\u63A5\u52A0\u4E00\u4E2A\uFF08\u6539\u540D/\u5220\u9664\u5728\u8BBE\u7F6E\u9875\uFF0C\n * \u9762\u677F\u4FDD\u6301\u8F7B\u91CF\uFF0C\u907F\u514D\u5728\u8FD9\u91CC\u585E\u4E00\u5957\u91CD\u547D\u540D UI\uFF09\uFF1B\n * - \u4E2D\u90E8\uFF1A\u5F53\u524D\u5206\u7C7B\u7684\u6761\u76EE \u2014\u2014 \u70B9\u6761\u76EE\u628A\u5185\u5BB9\u63D2\u5165\u8F93\u5165\u6846\uFF0C\u53F3\u4FA7\u4E09\u9009\u4E00\u662F\u63D2\u5165\u6A21\u5F0F\n * \uFF08\u5173 / \u6BCF\u6B21 / \u4EC5\u9996\u6B21\uFF09\uFF1B\u5217\u8868\u6700\u4E0B\u8FB9\u90A3\u4E00\u884C\u300C\uFF0B\u300D\u8D1F\u8D23\u65B0\u5EFA\u4E0E\u8DE8\u5206\u7C7B\u79FB\u52A8\u3002\n * \uFF08\u52FE\u4E0A\u540E\u70B9\u53D1\u9001\u65F6\u81EA\u52A8\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E\uFF0C**\u8DE8\u5206\u7C7B\u751F\u6548**\uFF09\uFF1B\n * - \u5E95\u90E8\uFF1A\u72B6\u6001\u63D0\u793A + \u6307\u8DEF\u8BBE\u7F6E\u9875\u3002\n */\nimport React, { useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport {\n DEFAULT_CATEGORY_NAME, OPTIMIZER_TIERS, QUICK_CATEGORY_MAX, insertModeOf,\n type ComposerUxSettings, type InsertMode, type OptimizerTier, type QuickPromptBook,\n} from '../settings-contract.ts'\nimport { bookCounts } from './prompt-book.ts'\nimport { AddPromptRow } from './AddPromptRow.tsx'\nimport { InsertModeControl } from './InsertModeControl.tsx'\nimport type { QuickPanelAnchor } from './QuickCommandsButton.tsx'\nimport {\n quickAlwaysBox, quickAlwaysLabel, quickCategoryAdd, quickCategoryRow, quickCategoryTab,\n quickCategoryTabActive, quickEmpty, quickFootHint, quickItem, quickItemLabel,\n quickItemPreview, quickList, quickNotice, quickPanel, quickPanelFoot, quickPanelHead,\n quickPanelTitle, quickPanelTitleRow, quickPrimaryButton, quickPrimaryButtonDisabled,\n quickTierButton, quickTierButtonActive, quickTierRow,\n} from './styles.ts'\n\n/** \u9762\u677F\u6CE8\u5165\u9762\u3002 */\nexport interface QuickPanelInjected {\n hooks: {\n /** \u5F53\u524D\u8BBE\u7F6E\uFF08\u6863\u4F4D + \u603B\u5F00\u5173\uFF09\u3002 */\n live: SnapshotStore<ComposerUxSettings>\n /** \u9762\u677F\u951A\u70B9\uFF1Bnull = \u9762\u677F\u5173\u95ED\u3002 */\n panel: SnapshotStore<QuickPanelAnchor | null>\n /** \u662F\u5426\u6709\u4E00\u6B21\u4F18\u5316\u5728\u98DE\u3002 */\n busy: SnapshotStore<boolean>\n /** \u9762\u677F\u72B6\u6001\u63D0\u793A\uFF08\u7A7A\u4E32 = \u65E0\uFF09\u3002 */\n notice: SnapshotStore<string>\n /** \u5FEB\u6377\u6307\u4EE4\u672C\uFF08\u771F\u76F8\u5728\u78C1\u76D8\u90A3\u4EFD quick-prompts.json\uFF09\u3002 */\n book: SnapshotStore<QuickPromptBook>\n /** '' = \u6B63\u5E38\uFF1B'saving' = \u6B63\u5728\u5199\uFF1B\u5176\u4F59 = \u4E0A\u4E00\u6B21\u7684\u9519\u8BEF\u6587\u6848\u3002 */\n bookStatus: SnapshotStore<string>\n }\n actions: {\n /** \u5173\u95ED\u9762\u677F\u3002 */\n close: () => void\n /** \u628A\u4E00\u6BB5\u6587\u672C\u63D2\u8FDB\u8F93\u5165\u6846\u3002 */\n insert: (text: string) => void\n /** \u7528\u5F53\u524D\u8F93\u5165\u6846\u5185\u5BB9\u8DD1\u4E00\u6B21\u4F18\u5316\uFF0C\u7ED3\u679C\u5199\u56DE\u8F93\u5165\u6846\u3002 */\n optimize: () => void\n /** \u5207\u6362\u4F18\u5316\u6863\u4F4D\u3002 */\n setTier: (tier: OptimizerTier) => void\n /** \u8BBE\u7F6E\u67D0\u6761\u7684\u63D2\u5165\u6A21\u5F0F\uFF08\u5173 / \u6BCF\u6B21 / \u4EC5\u9996\u6B21\uFF1B\u6309 id \u8DE8\u5206\u7C7B\u627E\uFF09\u3002 */\n setInsertMode: (promptId: string, mode: InsertMode) => void\n /** \u65B0\u589E\u4E00\u4E2A\u5206\u7C7B\uFF08\u540D\u5B57\u7531\u8BBE\u7F6E\u9875\u518D\u6539\uFF09\u3002 */\n addCategory: (name: string) => void\n /** \u5728\u5F53\u524D\u5206\u7C7B\u91CC\u65B0\u5EFA\u4E00\u6761\uFF08\u5360\u4F4D\u6B63\u6587\uFF0C\u5177\u4F53\u5185\u5BB9\u5230\u8BBE\u7F6E\u9875\u6539\uFF09\u3002 */\n addPrompt: (categoryId: string) => void\n /** \u628A\u67D0\u6761\u4ECE\u5B83\u6240\u5728\u5206\u7C7B\u79FB\u5230\u76EE\u6807\u5206\u7C7B\uFF08\u300C\u79FB\u52A8\u5230\u8FD9\u91CC\u300D\uFF09\u3002 */\n movePrompt: (promptId: string, toCategoryId: string) => void\n /** \u4ECE\u78C1\u76D8\u91CD\u8BFB\uFF08\u6587\u4EF6\u88AB\u624B\u5DE5\u6539\u8FC7\u65F6\u7684\u515C\u5E95\uFF09\u3002 */\n reloadBook: () => void\n }\n}\n\nexport type QuickCommandsPanelProps =\n PropsRuntime<'shell.overlay'>\n & InjectFace<QuickPanelInjected>\n\n/** \u4E0E\u89C6\u53E3\u8FB9\u754C\u4FDD\u6301\u7684\u95F4\u8DDD\u3002 */\nconst MARGIN = 8\n/** \u9762\u677F\u4E0E\u951A\u70B9\u6309\u94AE\u4E4B\u95F4\u7684\u95F4\u8DDD\u3002 */\nconst GAP = 8\n\n/** \u5C55\u5F00\u9762\u677F\u3002 */\nexport function QuickCommandsPanel({\n useLive, usePanel, useBusy, useNotice, useBook, useBookStatus, actions,\n}: QuickCommandsPanelProps) {\n const settings = useLive(item => item)\n const anchor = usePanel(item => item)\n const busy = useBusy(item => item)\n const notice = useNotice(item => item)\n const book = useBook(item => item)\n const status = useBookStatus(item => item)\n const ref = useRef<HTMLDivElement | null>(null)\n const [position, setPosition] = useState<{ left: number; top: number } | null>(null)\n const [activeId, setActiveId] = useState('')\n\n const counts = bookCounts(book)\n const categories = book.categories\n const active = categories.find(category => category.id === activeId) ?? categories[0]\n\n // \u8D34\u951A\u70B9\u6309\u94AE\u4E0A\u65B9\uFF1B\u653E\u4E0D\u4E0B\u5C31\u7FFB\u5230\u4E0B\u65B9\uFF1B\u5DE6\u53F3\u94B3\u5236\u5728\u89C6\u53E3\u5185\u3002\n useLayoutEffect(() => {\n if (anchor === null) {\n setPosition(null)\n return\n }\n const el = ref.current\n const height = el === null ? 320 : el.getBoundingClientRect().height\n const width = el === null ? 420 : el.getBoundingClientRect().width\n const left = Math.max(MARGIN, Math.min(anchor.left, window.innerWidth - width - MARGIN))\n const above = anchor.bottom - height - GAP\n const top = above >= MARGIN ? above : Math.min(anchor.bottom + GAP, window.innerHeight - height - MARGIN)\n setPosition({ left, top: Math.max(MARGIN, top) })\n }, [anchor?.left, anchor?.bottom, counts.prompts, categories.length, busy])\n\n // \u5916\u90E8\u70B9\u51FB / Escape / \u6EDA\u52A8 / \u7F29\u653E\u65F6\u5173\u95ED\uFF08\u4E0E\u53F3\u952E\u83DC\u5355\u540C\u4E00\u5957\u89C4\u5219\uFF09\u3002\n useEffect(() => {\n if (anchor === null) return\n const onPointerDown = (event: PointerEvent): void => {\n if (ref.current !== null && event.target instanceof Node && ref.current.contains(event.target)) return\n // \u70B9\u5165\u53E3\u6309\u94AE\u672C\u8EAB\u7531\u5B83\u81EA\u5DF1 toggle\uFF0C\u8FD9\u91CC\u8BA9\u8DEF\uFF0C\u514D\u5F97\u300C\u5173\u4E86\u53C8\u5F00\u300D\u3002\n if (event.target instanceof Element && event.target.closest('.composer-ux-quick-button') !== null) return\n actions.close()\n }\n const onEscape = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape') return\n event.preventDefault()\n event.stopPropagation()\n actions.close()\n }\n window.addEventListener('pointerdown', onPointerDown, true)\n window.addEventListener('keydown', onEscape, true)\n window.addEventListener('resize', actions.close)\n return () => {\n window.removeEventListener('pointerdown', onPointerDown, true)\n window.removeEventListener('keydown', onEscape, true)\n window.removeEventListener('resize', actions.close)\n }\n }, [anchor === null, actions])\n\n if (anchor === null) return null\n\n const tier = settings.optimizerTier\n const items = active?.prompts ?? []\n const failure = status !== '' && status !== 'saving' ? status : ''\n\n return (\n <div\n ref={ref}\n role=\"dialog\"\n aria-label=\"\u5FEB\u6377\u6307\u4EE4\"\n style={{ ...quickPanel, left: position?.left ?? anchor.left, top: position?.top ?? anchor.bottom }}\n >\n <div style={quickPanelHead}>\n <div style={quickPanelTitleRow}>\n <span style={quickPanelTitle}>\u5FEB\u6377\u6307\u4EE4</span>\n <div style={quickTierRow} role=\"group\" aria-label=\"\u4F18\u5316\u5F3A\u5EA6\">\n {OPTIMIZER_TIERS.map(item => (\n <button\n key={item.id}\n type=\"button\"\n title={item.hint}\n aria-pressed={tier === item.id}\n style={tier === item.id ? quickTierButtonActive : quickTierButton}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { actions.setTier(item.id) }}\n >\n {item.label}\n </button>\n ))}\n </div>\n </div>\n <button\n type=\"button\"\n disabled={busy}\n title=\"\u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u4EA4\u7ED9\u53E6\u4E00\u4E2A AI \u6574\u7406\u6210\u4E00\u6761\u53EF\u4EE5\u76F4\u63A5\u53D1\u51FA\u53BB\u7684\u6E05\u6670\u6307\u4EE4\uFF0C\u7ED3\u679C\u76F4\u63A5\u5199\u56DE\u8F93\u5165\u6846\u3002\u5B83\u53EA\u80FD\u4EA7\u51FA\u80FD\u6307\u56DE\u4F60\u539F\u8BDD\u67D0\u4E00\u53E5\u7684\u8865\u5168\uFF0C\u6307\u4E0D\u56DE\u53BB\u7684\u4F1A\u88AB\u4E22\u6389\u5E76\u8BB0\u8D26\"\n style={busy ? quickPrimaryButtonDisabled : quickPrimaryButton}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { actions.optimize() }}\n >\n <span aria-hidden>\u2728</span>\n <span>{busy ? '\u4F18\u5316\u4E2D\u2026' : '\u4F18\u5316\u63D0\u793A\u8BCD'}</span>\n </button>\n <div style={quickCategoryRow}>\n {categories.map(category => (\n <button\n key={category.id}\n type=\"button\"\n title={`${category.name}\uFF08${String(category.prompts.length)} \u6761\uFF09`}\n aria-pressed={category.id === active?.id}\n style={category.id === active?.id ? quickCategoryTabActive : quickCategoryTab}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { setActiveId(category.id) }}\n >\n {category.name}\n </button>\n ))}\n <button\n type=\"button\"\n style={quickCategoryAdd}\n disabled={categories.length >= QUICK_CATEGORY_MAX}\n title=\"\u65B0\u589E\u4E00\u4E2A\u5206\u7C7B\uFF08\u540D\u5B57\u5230\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C\u300D\u91CC\u6539\uFF09\"\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => {\n actions.addCategory(DEFAULT_CATEGORY_NAME)\n }}\n >\n \uFF0B\n </button>\n </div>\n </div>\n\n <div style={quickList}>\n {items.length === 0 && (\n <div style={quickEmpty}>\n \u8FD9\u4E2A\u5206\u7C7B\u91CC\u8FD8\u6CA1\u6709\u6761\u76EE\u3002<br />\n \u5728\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C \u2192 \u5FEB\u6377\u6307\u4EE4\u6E05\u5355\u300D\u91CC\u6DFB\u52A0\u3002\n </div>\n )}\n {items.map(item => (\n <div key={item.id} style={{ display: 'flex', alignItems: 'center', gap: 4 }}>\n <button\n type=\"button\"\n title={item.prompt}\n style={quickItem}\n onMouseDown={event => { event.preventDefault() }}\n onClick={() => { actions.insert(item.prompt) }}\n >\n <span style={quickItemLabel}>{item.label}</span>\n <span style={quickItemPreview}>{item.prompt.replace(/\\s+/g, ' ')}</span>\n </button>\n <InsertModeControl\n compact\n label={item.label}\n mode={insertModeOf(item)}\n onChange={mode => { actions.setInsertMode(item.id, mode) }}\n />\n </div>\n ))}\n {active !== undefined && (\n <AddPromptRow\n variant=\"panel\"\n book={book}\n categoryId={active.id}\n onAdd={() => { actions.addPrompt(active.id) }}\n onMove={promptId => { actions.movePrompt(promptId, active.id) }}\n />\n )}\n </div>\n\n <div style={quickPanelFoot}>\n <span style={quickNotice} role=\"status\">{notice !== '' ? notice : failure}</span>\n <span\n style={quickFootHint}\n title=\"\u6570\u636E\u5728 ~/.dsh/quick-prompts.json\"\n >\n {counts.categories} \u5206\u7C7B \u00B7 {counts.prompts} \u6761\n </span>\n </div>\n </div>\n )\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,8BAAoC;;;ACqF7B,SAAS,cAAc,OAAuB;AACnD,QAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,UAAU,EAAE;AACjD,QAAM,UAAU,QAAQ,QAAQ,OAAO,GAAG,EAAE,QAAQ,WAAW,GAAG;AAClE,SAAO,QAAQ,SAAS,IAAI,QAAQ,QAAQ,QAAQ,EAAE,IAAI;AAC5D;;;AC/EO,IAAM,sBAAsB;AAG5B,IAAM,2BAA2B;AAGjC,IAAM,4BAA4B;AAGlC,IAAM,wBAAwB;AAG9B,IAAM,2BAA2B;AAGjC,IAAM,oBAAoB;AAM1B,IAAM,iBAIP;AAAA,EACJ;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AACF;AAGO,IAAM,wBAAsC;AAW5C,SAAS,iBAAiB,OAA8B;AAC7D,SAAO,UAAU,UAAU,UAAU,aAAa,UAAU,SAAS,QAAQ;AAC/E;AAaO,SAAS,2BAA2B,OAA8C;AACvF,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,QAAM,MAA2B,CAAC;AAClC,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,QAAQ,OAAO;AACxB,QAAI,IAAI,UAAU,GAAI;AACtB,QAAI,OAAO,SAAS,YAAY,SAAS,KAAM;AAC/C,UAAMA,OAAM;AACZ,UAAM,OAAO,OAAOA,KAAI,SAAS,WAAW,cAAcA,KAAI,IAAI,EAAE,MAAM,GAAG,GAAG,IAAI;AACpF,QAAI,SAAS,GAAI;AACjB,UAAM,MAAM,KAAK,YAAY;AAC7B,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AACZ,UAAM,QAAQ,OAAOA,KAAI,UAAU,WAAWA,KAAI,MAAM,MAAM,GAAG,EAAE,IAAI;AACvE,UAAM,OAAOA,KAAI,SAAS,SAASA,KAAI,SAAS,WAAWA,KAAI,SAAS,YACnEA,KAAI,SAAS,aAAaA,KAAI,SAAS,SAASA,KAAI,OAAO;AAChE,QAAI,KAAK,EAAE,MAAM,OAAO,UAAU,KAAK,SAAS,OAAO,MAAM,UAAUA,KAAI,aAAa,KAAK,CAAC;AAAA,EAChG;AACA,SAAO;AACT;;;ACzFO,IAAM,YAAY;AAQlB,IAAM,WAAW;AAUjB,IAAM,mBAAmB;AAGzB,IAAM,gBAAgB;AAiBtB,IAAM,qBAAqB;AAE3B,IAAM,qBAAqB;AAE3B,IAAM,sBAAsB;AAE5B,IAAM,sBAAsB;AAE5B,IAAM,yBAAyB;AAG/B,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAS1B,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB;AAC1B,IAAM,qBAAqB;AAG3B,IAAM,cAAc;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAWO,IAAM,kBAAkB;AAGxB,IAAM,oBAAoB;AAM1B,IAAM,aAIP;AAAA,EACJ;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AACF;AAYO,SAAS,aAAa,YAAqB,cAAiC;AACjF,MAAI,eAAe,cAAc,eAAe,aAAa,eAAe,SAAU,QAAO;AAC7F,MAAI,iBAAiB,KAAM,QAAO;AAClC,MAAI,iBAAiB,MAAO,QAAO;AACnC,SAAO,iBAAiB;AAC1B;AAKO,IAAM,sBAAsB;AAG5B,IAAM,uBAAuB;AAG7B,IAAM,mBAAmB;AAGzB,IAAM,qBAAqB;AAG3B,IAAM,0BAA0B;AAGhC,IAAM,kBAAkB;AAQxB,IAAM,iBAAiB;AAgBvB,IAAM,yBAAyB;AAG/B,IAAM,qBAAqB;AAG3B,IAAM,wBAAwB;AAY9B,IAAM,qBAAqB;AAgC3B,IAAM,eAIP;AAAA,EACJ,EAAE,IAAI,SAAS,OAAO,UAAK,MAAM,mGAAmB;AAAA,EACpD,EAAE,IAAI,UAAU,OAAO,gBAAM,MAAM,6FAAkB;AAAA,EACrD,EAAE,IAAI,SAAS,OAAO,sBAAO,MAAM,6FAAkB;AACvD;AAQO,SAAS,aAAa,QAA+D;AAC1F,MAAI,OAAO,OAAQ,QAAO;AAC1B,MAAI,OAAO,UAAW,QAAO;AAC7B,SAAO;AACT;AAaO,IAAM,kBAIP;AAAA,EACJ,EAAE,IAAI,SAAS,OAAO,gBAAM,MAAM,4OAA8C;AAAA,EAChF,EAAE,IAAI,YAAY,OAAO,gBAAM,MAAM,yTAA0D;AAAA,EAC/F,EAAE,IAAI,WAAW,OAAO,gBAAM,MAAM,kMAAuC;AAC7E;AAGO,IAAM,yBAAwC;AAS9C,IAAM,0BAA0B;AAAA,EACrC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS;AACX;AAGO,IAAM,8BACX,gBAAgB,IAAI,UAAQ,wBAAwB,KAAK,EAAE,CAAC;AAQvD,IAAM,uBAAuB;AAO7B,SAAS,uBAAuB,MAAsB;AAC3D,SAAO,wBAAwB,IAAqB,KAAK,wBAAwB,sBAAsB;AACzG;AASO,IAAM,wBAAgD;AAAA,EAC3D,EAAE,IAAI,aAAa,OAAO,4BAAQ,QAAQ,oSAAoD,QAAQ,OAAO,WAAW,MAAM;AAAA,EAC9H,EAAE,IAAI,aAAa,OAAO,4BAAQ,QAAQ,kRAAiD,QAAQ,OAAO,WAAW,MAAM;AAAA,EAC3H,EAAE,IAAI,aAAa,OAAO,kCAAS,QAAQ,wFAAkB,QAAQ,OAAO,WAAW,MAAM;AAAA,EAC7F,EAAE,IAAI,aAAa,OAAO,wCAAU,QAAQ,kIAAyB,QAAQ,OAAO,WAAW,MAAM;AAAA,EACrG,EAAE,IAAI,aAAa,OAAO,4BAAQ,QAAQ,qLAAmD,QAAQ,OAAO,WAAW,MAAM;AAAA,EAC7H,EAAE,IAAI,aAAa,OAAO,sBAAO,QAAQ,0MAAqC,QAAQ,OAAO,WAAW,MAAM;AAAA,EAC9G,EAAE,IAAI,aAAa,OAAO,4BAAQ,QAAQ,oGAAoB,QAAQ,OAAO,WAAW,MAAM;AAAA,EAC9F,EAAE,IAAI,aAAa,OAAO,sBAAO,QAAQ,wFAAkB,QAAQ,OAAO,WAAW,MAAM;AAAA,EAC3F,EAAE,IAAI,aAAa,OAAO,4BAAQ,QAAQ,gKAA8B,QAAQ,OAAO,WAAW,MAAM;AAC1G;AAGO,SAAS,mBAA2B;AACzC,SAAO,MAAM,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAChF;AAcO,SAAS,qBAA6B;AAC3C,SAAO,MAAM,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAChF;AAgBO,SAAS,mBAAoC;AAClD,SAAO;AAAA,IACL,SAAS;AAAA,IACT,YAAY,CAAC,EAAE,IAAI,eAAe,MAAM,uBAAuB,SAAS,sBAAsB,CAAC;AAAA,EACjG;AACF;AAkBA,SAAS,YAAY,OAAuF;AAC1G,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAMC,OAAM;AACZ,QAAM,SAAS,CAAC,OAAgB,WAA4B;AAC1D,UAAM,SAAS,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;AACnE,WAAO,OAAO,WAAW,WAAW,SAAS;AAAA,EAC/C;AACA,QAAM,SAAS,OAAOA,KAAI,QAAQA,KAAI,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,KAAK;AAC1E,MAAI,WAAW,GAAI,QAAO;AAC1B,QAAM,QAAQ,OAAOA,KAAI,OAAOA,KAAI,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE,KAAK;AAC1E,QAAM,KAAK,OAAOA,KAAI,OAAO,YAAYA,KAAI,OAAO,KAAKA,KAAI,GAAG,MAAM,GAAG,EAAE,IAAI,iBAAiB;AAChG,QAAM,QAAQ,OAAOA,KAAI,UAAU,YAAY,OAAO,SAASA,KAAI,KAAK,IACpE,KAAK,IAAI,GAAG,KAAK,MAAMA,KAAI,KAAK,CAAC,IACjC;AACJ,SAAO;AAAA,IACL,QAAQ;AAAA,MACN;AAAA,MACA,OAAO,UAAU,KAAK,OAAO,MAAM,GAAG,EAAE,IAAI;AAAA,MAC5C;AAAA,MACA,QAAQA,KAAI,WAAW,QAAQA,KAAI,aAAa;AAAA,MAChD,WAAWA,KAAI,cAAc,QAAQA,KAAI,kBAAkB;AAAA,IAC7D;AAAA,IACA;AAAA,EACF;AACF;AAGA,SAAS,aAAa,QAAoD;AACxE,QAAM,OAAiE,CAAC;AACxE,aAAW,SAAS,QAAQ;AAC1B,UAAMA,OAAM,YAAY,KAAK;AAC7B,QAAIA,SAAQ,OAAW,MAAK,KAAK,EAAE,GAAGA,MAAK,OAAO,KAAK,OAAO,CAAC;AAAA,EACjE;AACA,OAAK,KAAK,CAAC,GAAG,MAAM;AAClB,UAAM,OAAO,EAAE,SAAS,OAAO;AAC/B,UAAM,QAAQ,EAAE,SAAS,OAAO;AAChC,WAAO,SAAS,QAAQ,EAAE,QAAQ,EAAE,QAAQ,OAAO;AAAA,EACrD,CAAC;AACD,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAqB,CAAC;AAC5B,aAAWA,QAAO,MAAM;AACtB,QAAI,IAAI,UAAU,iBAAkB;AACpC,QAAI,KAAK,IAAIA,KAAI,OAAO,EAAE,EAAG;AAC7B,SAAK,IAAIA,KAAI,OAAO,EAAE;AACtB,QAAI,KAAKA,KAAI,MAAM;AAAA,EACrB;AACA,SAAO;AACT;AAQO,SAAS,aAAa,OAA6C;AACxE,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,SAAS;AAGf,QAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAS,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,UAAU;AAC9F,MAAI,SAAS,QAAW;AACtB,UAAM,UAAU,aAAa,IAAI;AACjC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,YAAY,QAAQ,WAAW,IAC3B,CAAC,IACD,CAAC,EAAE,IAAI,eAAe,MAAM,uBAAuB,QAAQ,CAAC;AAAA,IAClE;AAAA,EACF;AAEA,MAAI,CAAC,MAAM,QAAQ,OAAO,UAAU,EAAG,QAAO;AAC9C,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,aAAoC,CAAC;AAC3C,aAAW,OAAO,OAAO,YAAY;AACnC,QAAI,WAAW,UAAU,mBAAoB;AAC7C,QAAI,OAAO,QAAQ,YAAY,QAAQ,KAAM;AAC7C,UAAMA,OAAM;AACZ,UAAM,UAAU,aAAa,MAAM,QAAQA,KAAI,OAAO,IAAIA,KAAI,UAAU,CAAC,CAAC;AAI1E,UAAM,SAAS,OAAOA,KAAI,OAAO,YAAYA,KAAI,OAAO,KAAKA,KAAI,GAAG,MAAM,GAAG,EAAE,IAAI,mBAAmB;AACtG,UAAM,KAAK,KAAK,IAAI,MAAM,IAAI,mBAAmB,IAAI;AACrD,SAAK,IAAI,EAAE;AACX,UAAMC,SAAQ,OAAOD,KAAI,SAAS,WAAWA,KAAI,OAAO,IAAI,MAAM,GAAG,uBAAuB,EAAE,KAAK;AACnG,eAAW,KAAK,EAAE,IAAI,MAAMC,UAAS,KAAK,wBAAwBA,OAAM,QAAQ,CAAC;AAAA,EACnF;AACA,SAAO,EAAE,SAAS,oBAAoB,WAAW;AACnD;AAuBO,SAAS,oBAAoB,MAA+C;AACjF,SAAO,KAAK,WAAW,QAAQ,cAAY,SAAS,OAAO;AAC7D;AAGO,SAAS,mBAAmB,MAA+C;AAChF,SAAO,oBAAoB,IAAI,EAAE,OAAO,YAAU,aAAa,MAAM,MAAM,QAAQ;AACrF;AAGO,SAAS,sBAAsB,MAA+C;AACnF,SAAO,oBAAoB,IAAI,EAAE,OAAO,YAAU,aAAa,MAAM,MAAM,OAAO;AACpF;AASO,SAAS,mBAAmB,MAAuB,OAAwC;AAChG,QAAM,QAAQ,mBAAmB,IAAI;AACrC,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,CAAC,GAAG,OAAO,GAAG,sBAAsB,IAAI,CAAC;AAClD;AAUO,IAAM,uBAAuB;AAC7B,IAAM,oBAAoB;AAC1B,IAAM,qBAAqB;AAE3B,IAAM,sBAAsB;AAG5B,IAAM,4BAA4B;AAClC,IAAM,6BAA6B;AAGnC,IAAM,sBAAsB;AAmC5B,IAAM,sBAAsB;AAG5B,IAAM,mBAAmB;AAGzB,IAAM,kBAAkB;AAsHxB,IAAM,mBAAuC;AAAA;AAAA,EAElD,SAAS;AAAA;AAAA,EAET,aAAa;AAAA,EACb,aAAa;AAAA,EACb,cAAc;AAAA,EACd,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,UAAU;AAAA,EACV,aAAa;AAAA,EACb,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,cAAc;AAAA,EACd,eAAe;AAAA;AAAA,EAEf,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,oBAAoB,CAAC;AAAA,EACrB,gBAAgB;AAAA,EAChB,mBAAmB;AACrB;AAOO,SAAS,eAAe,UAO7B;AACA,QAAM,KAAK,SAAS;AACpB,SAAO;AAAA,IACL,MAAM,MAAM,SAAS;AAAA,IACrB,MAAM,MAAM,SAAS;AAAA,IACrB,OAAO,MAAM,SAAS;AAAA,IACtB,OAAO,MAAM,SAAS;AAAA,IACtB,QAAQ,MAAM,SAAS;AAAA,IACvB,UAAU,MAAM,SAAS;AAAA,EAC3B;AACF;AAGO,IAAM,eAAkC,CAAC,SAAS,cAAc,aAAa,aAAa;AAC1F,IAAM,kBAAqC,CAAC,eAAe,SAAS,cAAc,WAAW;AAG7F,IAAM,aAIP;AAAA,EACJ,EAAE,OAAO,YAAY,OAAO,gBAAM,UAAU,SAAS;AAAA,EACrD,EAAE,OAAO,YAAY,OAAO,gBAAM,UAAU,SAAS;AAAA,EACrD,EAAE,OAAO,WAAW,OAAO,gBAAM,UAAU,SAAS;AAAA,EACpD,EAAE,OAAO,YAAY,OAAO,gBAAM,UAAU,SAAS;AAAA,EACrD,EAAE,OAAO,aAAa,OAAO,gBAAM,UAAU,SAAS;AAAA,EACtD,EAAE,OAAO,cAAc,OAAO,gBAAM,UAAU,GAAG;AAAA,EACjD,EAAE,OAAO,iBAAiB,OAAO,gBAAM,UAAU,SAAS;AAC5D;AAOO,SAAS,eAAuB;AACrC,QAAM,MAAM;AACZ,MAAI,OAAO,IAAI,QAAQ,eAAe,WAAY,QAAO,IAAI,OAAO,WAAW;AAC/E,QAAM,MAAM,CAAC,UAA0B,MAAM;AAAA,IAC3C,EAAE,QAAQ,MAAM;AAAA,IAChB,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE,EAAE,SAAS,EAAE;AAAA,EAClD,EAAE,KAAK,EAAE;AACT,SAAO,GAAG,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;AAC7D;AAwBA,IAAM,kBAA0F;AAAA,EAC9F,CAAC,kBAAkB,GAAG,YACpB,QAAQ,QAAQ,gBAAgB,iBAAiB,OAAO,KACrD,QAAQ,QAAQ,mBAAmB,iBAAiB,UAAU;AAAA;AAAA;AAAA,EAGnE,CAAC,kBAAkB,GAAG,YACpB,aAAa,OAAO,eAAe,GAAG,OAAO,iBAAiB,CAAC,MAAM;AAAA,EACvE,CAAC,mBAAmB,GAAG,YACpB,MAAM,QAAQ,OAAO,mBAAmB,CAAC,KACrC,OAAO,mBAAmB,EAAE,WAAW,sBAAsB,UAC/D,QAAQ,QAAQ,sBAAsB,sBAAsB;AAAA,EACjE,CAAC,mBAAmB,GAAG,YACrB,QAAQ,QAAQ,oBAAoB,IAAI,KACrC,OAAO,iBAAiB,MAAM,UAC9B,OAAO,kBAAkB,MAAM;AAAA,EACpC,CAAC,sBAAsB,GAAG,YACxB,QAAQ,QAAQ,qBAAqB,qBAAqB,KACvD,QAAQ,QAAQ,0BAA0B,EAAE;AACnD;AASA,SAAS,QAAQ,QAAiC,OAAe,WAA6B;AAC5F,QAAM,QAAQ,OAAO,KAAK;AAC1B,SAAO,UAAU,UAAa,UAAU;AAC1C;AAQO,SAAS,iBAAiB,OAAe,QAA0C;AACxF,QAAM,WAAW,OAAO,KAAK;AAC7B,MAAI,OAAO,aAAa,UAAW,QAAO;AAC1C,QAAM,SAAS,gBAAgB,KAAK;AACpC,SAAO,WAAW,SAAY,QAAQ,OAAO,MAAM;AACrD;AAGO,SAAS,iBAAiB,OAAoC;AACnE,QAAM,SAAU,OAAO,UAAU,YAAY,UAAU,OAAO,QAAQ,CAAC;AACvE,QAAM,WAAW,CAAC,UAA0B;AAC1C,UAAM,IAAI,OAAO,KAAK;AACtB,WAAO,OAAO,MAAM,YAAY,EAAE,SAAS,KAAK,EAAE,UAAU,KAAK,IAAI;AAAA,EACvE;AACA,QAAM,SAAS,CAAC,OAAe,QAAwB;AACrD,UAAM,IAAI,OAAO,KAAK;AACtB,WAAO,OAAO,MAAM,YAAY,EAAE,UAAU,MAAM,IAAI;AAAA,EACxD;AASA,QAAM,WAAW,CAAC,OAAe,QAAwB;AACvD,UAAM,IAAI,OAAO,KAAK;AACtB,WAAO,OAAO,MAAM,WAAW,EAAE,MAAM,GAAG,GAAG,IAAI;AAAA,EACnD;AACA,QAAM,SAAS,CAAC,UAA2B;AACzC,UAAM,IAAI,OAAO,KAAK;AACtB,WAAO,OAAO,MAAM,YAAY,IAAK,iBAAwD,KAAK;AAAA,EACpG;AACA,QAAM,SAAS,CAAC,UAAsC;AACpD,UAAM,IAAI,OAAO,KAAK;AACtB,WAAO,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,KAAK,KAAK,OAAO,KAAK,MAAO,KAAK,MAAM,CAAC,IAAI;AAAA,EAChG;AAMA,QAAM,iBAAiB,MAA8B;AACnD,UAAM,MAAM,OAAO,mBAAmB;AACtC,QAAI,CAAC,MAAM,QAAQ,GAAG,EAAG,QAAO;AAChC,UAAM,OAAO,oBAAI,IAAY;AAC7B,UAAM,MAAqB,CAAC;AAC5B,eAAW,QAAQ,KAAK;AACtB,UAAI,IAAI,UAAU,iBAAkB;AACpC,UAAI,OAAO,SAAS,YAAY,SAAS,KAAM;AAC/C,YAAMC,OAAM;AACZ,YAAM,SAAS,OAAOA,KAAI,WAAW,WAAWA,KAAI,OAAO,MAAM,GAAG,cAAc,EAAE,KAAK,IAAI;AAC7F,UAAI,WAAW,GAAI;AACnB,YAAM,QAAQ,OAAOA,KAAI,UAAU,WAAWA,KAAI,MAAM,MAAM,GAAG,eAAe,EAAE,KAAK,IAAI;AAC3F,YAAM,KAAK,OAAOA,KAAI,OAAO,YAAYA,KAAI,OAAO,KAAKA,KAAI,GAAG,MAAM,GAAG,EAAE,IAAI,iBAAiB;AAChG,UAAI,KAAK,IAAI,EAAE,EAAG;AAClB,WAAK,IAAI,EAAE;AACX,UAAI,KAAK;AAAA,QACP;AAAA,QACA,OAAO,UAAU,KAAK,OAAO,MAAM,GAAG,EAAE,IAAI;AAAA,QAC5C;AAAA,QACA,QAAQA,KAAI,WAAW;AAAA,QACvB,WAAWA,KAAI,cAAc;AAAA,MAC/B,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AACA,QAAM,SAAS,MAAqB;AAClC,UAAM,IAAI,OAAO,oBAAoB;AACrC,WAAO,MAAM,WAAW,MAAM,cAAc,MAAM,YAAY,IAAI;AAAA,EACpE;AACA,SAAO;AAAA,IACL,SAAS,OAAO,aAAa;AAAA;AAAA,IAE7B,aAAa,iBAAiB,oBAAoB,MAAM;AAAA,IACxD,aAAa,iBAAiB,oBAAoB,MAAM;AAAA,IACxD,cAAc,iBAAiB,qBAAqB,MAAM;AAAA,IAC1D,cAAc,iBAAiB,qBAAqB,MAAM;AAAA,IAC1D,iBAAiB,iBAAiB,wBAAwB,MAAM;AAAA,IAChE,SAAS,SAAS,cAAc;AAAA,IAChC,YAAY,SAAS,iBAAiB;AAAA,IACtC,UAAU,OAAO,UAAU;AAAA,IAC3B,UAAU,OAAO,UAAU;AAAA,IAC3B,SAAS,OAAO,SAAS;AAAA,IACzB,UAAU,OAAO,UAAU;AAAA,IAC3B,WAAW,OAAO,WAAW;AAAA,IAC7B,YAAY,OAAO,YAAY;AAAA,IAC/B,eAAe,OAAO,eAAe;AAAA,IACrC,UAAU,aAAa,OAAO,eAAe,GAAG,OAAO,iBAAiB,CAAC;AAAA,IACzE,aAAa,OAAO,kBAAkB;AAAA,IACtC,YAAY,OAAO,iBAAiB;AAAA,IACpC,aAAa,OAAO,kBAAkB;AAAA,IACtC,eAAe,OAAO,oBAAoB;AAAA;AAAA;AAAA,IAG1C,YAAY,OAAO,mBAAmB,eAAe;AAAA,IACrD,aAAa,OAAO,oBAAoB,gBAAgB;AAAA,IACxD,cAAc,OAAO,qBAAqB,gBAAgB;AAAA,IAC1D,mBAAmB,OAAO,2BAA2B,eAAe;AAAA,IACpE,oBAAoB,OAAO,4BAA4B,gBAAgB;AAAA,IACvE,cAAc,OAAO,qBAAqB,gBAAgB;AAAA,IAC1D,cAAc,eAAe;AAAA,IAC7B,eAAe,OAAO;AAAA,IACtB,sBAAsB,SAAS,wBAAwB,OAAO,oBAAoB;AAAA,IAClF,yBAAyB,SAAS,wBAAwB,UAAU,oBAAoB;AAAA,IACxF,wBAAwB,SAAS,wBAAwB,SAAS,oBAAoB;AAAA,IACtF,cAAc,iBAAiB,OAAO,mBAAmB,CAAC;AAAA;AAAA;AAAA,IAG1D,kBAAkB,OAAO,0BAA0B,GAAG;AAAA,IACtD,oBAAoB,2BAA2B,OAAO,yBAAyB,CAAC;AAAA,IAChF,gBAAgB,OAAO,uBAAuB,GAAG;AAAA,IACjD,mBAAmB,OAAO,0BAA0B,EAAE;AAAA,EACxD;AACF;;;AC77BA,eAAe,YAAY,QAAwB,MAA0C;AAC3F,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,wBAAwB;AAAA,MACnD;AAAA,MACA,SAAS,SAAS,SAAY,SAAY,EAAE,gBAAgB,mBAAmB;AAAA,MAC/E,MAAM,SAAS,SAAY,SAAY,KAAK,UAAU,IAAI;AAAA,IAC5D,CAAC;AACD,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,IAAI;AAAA,IAC1B,QAAQ;AACN,aAAO,EAAE,IAAI,OAAO,OAAO,mEAAsB,OAAO,SAAS,MAAM,CAAC,SAAI;AAAA,IAC9E;AACA,UAAMC,OAAO,OAAO,WAAW,YAAY,WAAW,OAAO,SAAS,CAAC;AACvE,UAAM,OAAO,aAAaA,KAAI,IAAI;AAClC,UAAM,SAAS,CAAC,UAAwC,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;AAC5G,WAAO;AAAA,MACL,IAAIA,KAAI,OAAO;AAAA,MACf,GAAI,SAAS,SAAY,CAAC,IAAI,EAAE,KAAK;AAAA,MACrC,GAAI,OAAOA,KAAI,KAAK,MAAM,SAAY,CAAC,IAAI,EAAE,OAAO,OAAOA,KAAI,KAAK,EAAE;AAAA,MACtE,GAAI,OAAOA,KAAI,IAAI,MAAM,SAAY,CAAC,IAAI,EAAE,MAAM,OAAOA,KAAI,IAAI,EAAE;AAAA,MACnE,GAAI,OAAOA,KAAI,WAAW,MAAM,SAAY,CAAC,IAAI,EAAE,aAAa,OAAOA,KAAI,WAAW,EAAE;AAAA,IAC1F;AAAA,EACF,SAAS,OAAgB;AACvB,WAAO,EAAE,IAAI,OAAO,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,EACpF;AACF;AAGO,SAAS,iBAA2C;AACzD,SAAO,YAAY,KAAK;AAC1B;AAGO,SAAS,eAAe,MAAiD;AAC9E,SAAO,YAAY,QAAQ,EAAE,KAAK,CAAC;AACrC;AAKO,SAAS,WAAW,MAAuB,YAAqD;AACrG,SAAO,KAAK,WAAW,KAAK,cAAY,SAAS,OAAO,UAAU;AACpE;AAGO,SAAS,WACd,MACA,UACsF;AACtF,aAAW,YAAY,KAAK,YAAY;AACtC,UAAM,SAAS,SAAS,QAAQ,KAAK,UAAQ,KAAK,OAAO,QAAQ;AACjE,QAAI,WAAW,OAAW,QAAO,EAAE,UAAU,OAAO;AAAA,EACtD;AACA,SAAO;AACT;AAGO,SAAS,WAAW,MAKzB;AACA,QAAM,UAAU,KAAK,WAAW,QAAQ,cAAY,SAAS,OAAO;AACpE,SAAO;AAAA,IACL,YAAY,KAAK,WAAW;AAAA,IAC5B,SAAS,QAAQ;AAAA,IACjB,QAAQ,QAAQ,OAAO,YAAU,aAAa,MAAM,MAAM,QAAQ,EAAE;AAAA,IACpE,OAAO,QAAQ,OAAO,YAAU,aAAa,MAAM,MAAM,OAAO,EAAE;AAAA,EACpE;AACF;AAEA,SAAS,YACP,MACA,YACA,MACiB;AACjB,SAAO;AAAA,IACL,SAAS,KAAK;AAAA,IACd,YAAY,KAAK,WAAW,IAAI,cAAa,SAAS,OAAO,aAAa,KAAK,QAAQ,IAAI,QAAS;AAAA,EACtG;AACF;AAGO,SAAS,kBAAkB,MAAuBC,OAA+B;AACtF,MAAI,KAAK,WAAW,UAAU,mBAAoB,QAAO;AACzD,QAAM,QAAQA,MAAK,KAAK,EAAE,MAAM,GAAG,uBAAuB;AAC1D,SAAO;AAAA,IACL,SAAS,KAAK;AAAA,IACd,YAAY,CAAC,GAAG,KAAK,YAAY,EAAE,IAAI,mBAAmB,GAAG,MAAM,UAAU,KAAK,wBAAwB,OAAO,SAAS,CAAC,EAAE,CAAC;AAAA,EAChI;AACF;AAGO,SAAS,oBAAoB,MAAuB,YAAoBA,OAA+B;AAC5G,QAAM,QAAQA,MAAK,KAAK,EAAE,MAAM,GAAG,uBAAuB;AAC1D,SAAO,YAAY,MAAM,YAAY,eAAa,EAAE,GAAG,UAAU,MAAM,UAAU,KAAK,wBAAwB,MAAM,EAAE;AACxH;AAGO,SAAS,oBAAoB,MAAuB,YAAqC;AAC9F,SAAO,EAAE,SAAS,KAAK,SAAS,YAAY,KAAK,WAAW,OAAO,cAAY,SAAS,OAAO,UAAU,EAAE;AAC7G;AAGO,SAAS,kBAAkB,MAAuB,YAAoB,OAAgC;AAC3G,QAAM,QAAQ,KAAK,WAAW,UAAU,cAAY,SAAS,OAAO,UAAU;AAC9E,QAAM,OAAO,QAAQ;AACrB,MAAI,QAAQ,KAAK,OAAO,KAAK,QAAQ,KAAK,WAAW,OAAQ,QAAO;AACpE,QAAM,aAAa,CAAC,GAAG,KAAK,UAAU;AACtC,QAAM,CAAC,KAAK,IAAI,WAAW,OAAO,OAAO,CAAC;AAC1C,aAAW,OAAO,MAAM,GAAG,KAAK;AAChC,SAAO,EAAE,SAAS,KAAK,SAAS,WAAW;AAC7C;AAUO,SAAS,gBAAgB,MAAuB,YAAqC;AAC1F,SAAO,YAAY,MAAM,YAAY,CAAC,aAAa;AACjD,QAAI,SAAS,QAAQ,UAAU,iBAAkB,QAAO;AACxD,WAAO;AAAA,MACL,GAAG;AAAA,MACH,SAAS,CAAC,GAAG,SAAS,SAAS;AAAA,QAC7B,IAAI,iBAAiB;AAAA,QAAG,OAAO;AAAA,QAAO,QAAQ;AAAA,QAAS,QAAQ;AAAA,QAAO,WAAW;AAAA,MACnF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AASO,SAAS,kBACd,MACA,YACA,UACA,OACiB;AACjB,SAAO,YAAY,MAAM,YAAY,CAAC,cAAc;AAAA,IAClD,GAAG;AAAA,IACH,SAAS,SAAS,QAAQ,IAAI,CAAC,WAAW;AACxC,UAAI,OAAO,OAAO,SAAU,QAAO;AACnC,YAAM,QAAQ,MAAM,UAAU,SAAY,OAAO,QAAQ,MAAM,MAAM,MAAM,GAAG,eAAe;AAC7F,YAAM,OAAO,MAAM,WAAW,SAAY,OAAO,SAAS,MAAM,OAAO,MAAM,GAAG,cAAc;AAC9F,YAAM,SAAS,MAAM,WAAW,SAAY,OAAO,SAAS,MAAM;AAClE,YAAM,YAAY,MAAM,cAAc,SAAY,OAAO,YAAY,MAAM;AAC3E,aAAO,EAAE,IAAI,OAAO,IAAI,OAAO,QAAQ,MAAM,QAAQ,UAAU;AAAA,IACjE,CAAC;AAAA,EACH,EAAE;AACJ;AAUO,SAAS,eAAe,MAAuB,UAAkB,MAAmC;AACzG,QAAM,MAAM,WAAW,MAAM,QAAQ;AACrC,MAAI,QAAQ,OAAW,QAAO;AAC9B,MAAI,aAAa,IAAI,MAAM,MAAM,KAAM,QAAO;AAC9C,SAAO,kBAAkB,MAAM,IAAI,SAAS,IAAI,UAAU;AAAA,IACxD,QAAQ,SAAS;AAAA,IACjB,WAAW,SAAS;AAAA,EACtB,CAAC;AACH;AAGO,SAAS,kBAAkB,MAAuB,YAAoB,UAAmC;AAC9G,SAAO,YAAY,MAAM,YAAY,eAAa;AAAA,IAChD,GAAG;AAAA,IACH,SAAS,SAAS,QAAQ,OAAO,YAAU,OAAO,OAAO,QAAQ;AAAA,EACnE,EAAE;AACJ;AAGO,SAAS,gBAAgB,MAAuB,YAAoB,UAAkB,OAAgC;AAC3H,QAAM,WAAW,WAAW,MAAM,UAAU;AAC5C,MAAI,aAAa,OAAW,QAAO;AACnC,QAAM,QAAQ,SAAS,QAAQ,UAAU,YAAU,OAAO,OAAO,QAAQ;AACzE,QAAM,OAAO,QAAQ;AACrB,MAAI,QAAQ,KAAK,OAAO,KAAK,QAAQ,SAAS,QAAQ,OAAQ,QAAO;AACrE,QAAM,UAAU,CAAC,GAAG,SAAS,OAAO;AACpC,QAAM,CAAC,KAAK,IAAI,QAAQ,OAAO,OAAO,CAAC;AACvC,UAAQ,OAAO,MAAM,GAAG,KAAK;AAC7B,SAAO,YAAY,MAAM,YAAY,aAAW,EAAE,GAAG,QAAQ,QAAQ,EAAE;AACzE;AAUO,SAAS,iBACd,MACA,YACyG;AACzG,SAAO,KAAK,WACT,OAAO,cAAY,SAAS,OAAO,UAAU,EAC7C,QAAQ,cAAY,SAAS,QAAQ,IAAI,aAAW;AAAA,IACnD,YAAY,SAAS;AAAA,IACrB,cAAc,SAAS;AAAA,IACvB;AAAA,EACF,EAAE,CAAC;AACP;AAWO,SAAS,0BACd,MACA,UACA,cACiB;AACjB,QAAM,MAAM,WAAW,MAAM,QAAQ;AACrC,MAAI,QAAQ,UAAa,IAAI,SAAS,OAAO,aAAc,QAAO;AAClE,QAAM,SAAS,WAAW,MAAM,YAAY;AAC5C,MAAI,WAAW,UAAa,OAAO,QAAQ,UAAU,iBAAkB,QAAO;AAC9E,SAAO;AAAA,IACL,SAAS,KAAK;AAAA,IACd,YAAY,KAAK,WAAW,IAAI,CAAC,aAAa;AAC5C,UAAI,SAAS,OAAO,IAAI,SAAS,IAAI;AACnC,eAAO,EAAE,GAAG,UAAU,SAAS,SAAS,QAAQ,OAAO,YAAU,OAAO,OAAO,QAAQ,EAAE;AAAA,MAC3F;AACA,UAAI,SAAS,OAAO,cAAc;AAEhC,eAAO,EAAE,GAAG,UAAU,SAAS,CAAC,GAAG,SAAS,SAAS,IAAI,MAAM,EAAE;AAAA,MACnE;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;;;AC3QA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,WAAW,OAAO,SAAS,QAAQ,UAAU,CAAC;AAG7E,IAAM,cAAgD;AAAA,EACpD,OAAO;AAAA,EACP,WAAW;AAAA,EACX,aAAa;AAAA,EACb,cAAc;AAAA,EACd,WAAW;AAAA,EACX,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACT;AAGO,SAAS,YAAY,OAA2B;AACrD,QAAM,QAAkB,CAAC;AACzB,MAAI,MAAM,QAAS,OAAM,KAAK,MAAM;AACpC,MAAI,MAAM,OAAQ,OAAM,KAAK,KAAK;AAClC,MAAI,MAAM,SAAU,OAAM,KAAK,OAAO;AACtC,MAAI,MAAM,QAAS,OAAM,KAAK,MAAM;AACpC,QAAM,UAAU,iBAAiB,KAAK;AACtC,MAAI,YAAY,GAAI,QAAO;AAC3B,QAAM,KAAK,OAAO;AAClB,SAAO,MAAM,KAAK,GAAG;AACvB;AAGA,SAAS,iBAAiB,OAA2B;AACnD,QAAM,OAAO,MAAM;AACnB,MAAI,KAAK,WAAW,KAAK,EAAG,QAAO,KAAK,MAAM,CAAC;AAC/C,MAAI,KAAK,WAAW,OAAO,EAAG,QAAO,KAAK,MAAM,CAAC;AACjD,MAAI,YAAY,IAAI,MAAM,OAAW,QAAO,YAAY,IAAI;AAE5D,SAAO,SAAS,KAAK,OAAO,MAAM;AACpC;AAGO,SAAS,eAAe,OAA4B;AACzD,SAAO,cAAc,IAAI,MAAM,GAAG;AACpC;AAGA,IAAM,eAAe,oBAAI,IAAI;AAAA,EAC3B;AAAA,EAAS;AAAA,EAAS;AAAA,EAAO;AAAA,EAAa;AAAA,EAAU;AAAA,EAAU;AAAA,EAAQ;AAAA,EAClE;AAAA,EAAU;AAAA,EAAY;AAAA,EAAW;AAAA,EAAa;AAAA,EAAa;AAC7D,CAAC;AAGM,SAAS,iBAAiB,OAAwB;AACvD,MAAI,MAAM,SAAS,GAAG,EAAG,QAAO;AAChC,MAAI,aAAa,IAAI,KAAK,EAAG,QAAO;AACpC,SAAO,aAAa,KAAK,KAAK;AAChC;AAGO,SAAS,YAAY,OAAkC;AAC5D,QAAM,QAAQ,MAAM,MAAM,GAAG,EAAE,OAAO,OAAO;AAC7C,QAAM,OAA0B;AAAA,IAC9B,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,SAAS;AAAA,IACT,YAAY;AAAA,EACd;AACA,QAAM,MAAM,MAAM,IAAI,KAAK;AAC3B,OAAK,MAAM;AAEX,OAAK,OAAO,IAAI,WAAW,IAAK,UAAU,KAAK,GAAG,IAAI,MAAM,GAAG,KAAK,MAAO;AAC3E,aAAW,QAAQ,OAAO;AACxB,QAAI,SAAS,OAAQ,MAAK,UAAU;AAAA,aAC3B,SAAS,MAAO,MAAK,SAAS;AAAA,aAC9B,SAAS,QAAS,MAAK,WAAW;AAAA,aAClC,SAAS,OAAQ,MAAK,UAAU;AAAA,EAC3C;AACA,SAAO;AACT;AAGO,SAAS,cAAc,OAAwB;AACpD,SAAO,UAAU,WAAW,MAAM,SAAS,QAAQ;AACrD;AAWO,SAAS,oBAAoB,OAAiC;AACnE,MAAI,eAAe,KAAK,EAAG,QAAO,EAAE,MAAM,SAAS;AACnD,MAAI,MAAM,SAAS,YAAY,MAAM,QAAQ,SAAU,QAAO,EAAE,MAAM,SAAS;AAE/E,MAAI,MAAM,SAAS,eAAe,MAAM,SAAS,SAAU,QAAO,EAAE,MAAM,QAAQ;AAClF,QAAM,QAAQ,YAAY,KAAK;AAC/B,MAAI,UAAU,GAAI,QAAO,EAAE,MAAM,SAAS;AAC1C,MAAI,CAAC,iBAAiB,KAAK,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AACA,SAAO,EAAE,MAAM,MAAM,MAAM;AAC7B;AAGO,SAAS,aAAa,OAAuB;AAClD,SAAO,UAAU,KAAK,WAAM;AAC9B;;;AC5FA,IAAM,oBAAoB;AAG1B,IAAM,gBAAgB;AAEtB,IAAM,QAAqB,EAAE,SAAS,MAAM,OAAO,IAAI,WAAW,IAAI,OAAO,MAAM;AAM5E,SAAS,mBAAmB,MAK1B;AACP,QAAM,UAAU,KAAK;AACrB,QAAM,QAAQ,KAAK;AACnB,QAAM,YAAY,KAAK;AACvB,QAAM,QAAQ,KAAK;AACrB;AAOO,SAAS,mBAAmB,WAAyB;AAC1D,MAAI,MAAM,cAAc,UAAW;AACnC,QAAM,UAAU;AAChB,QAAM,QAAQ;AACd,QAAM,YAAY;AAClB,QAAM,QAAQ;AAChB;AAGO,SAAS,sBAA+B;AAC7C,SAAO,MAAM,UAAU;AACzB;AAGA,SAAS,eAAuB;AAC9B,QAAM,KAAK,SAAS,cAAc,iBAAiB;AACnD,MAAI,EAAE,cAAc,aAAc,QAAO;AACzC,SAAO,GAAG,UAAU,QAAQ,QAAQ,EAAE;AACxC;AAGO,SAAS,eAAuB;AACrC,SAAO,MAAM,YAAY,OAAO,aAAa,IAAI,MAAM;AACzD;AA6BO,SAAS,oBAAoB,OAAe,SAAgD;AACjG,QAAM,SAAS,QAAQ,OAAO,UAAQ,KAAK,OAAO,KAAK,MAAM,EAAE;AAC/D,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAMC,QAAO,MAAM,QAAQ,QAAQ,EAAE;AACrC,MAAIA,UAAS,GAAI,QAAO;AACxB,QAAM,SAAS,OAAO,IAAI,UAAQ,KAAK,OAAO,KAAK,CAAC,EAAE,KAAK,MAAM;AACjE,MAAIA,MAAK,SAAS,MAAM,EAAG,QAAO;AAClC,SAAO,GAAGA,KAAI;AAAA;AAAA,EAAO,MAAM;AAC7B;AAUO,SAAS,oBAAoB,SAA0C;AAC5E,QAAM,UAAU,MAAM;AACtB,MAAI,YAAY,KAAM,QAAO;AAC7B,QAAM,OAAO,oBAAoB,aAAa,GAAG,OAAO;AACxD,MAAI,SAAS,KAAM,QAAO;AAC1B,UAAQ,SAAS,IAAI;AACrB,SAAO;AACT;AAGO,SAAS,gBAAgB,MAAuB;AACrD,QAAM,UAAU,MAAM;AACtB,QAAM,OAAO,KAAK,KAAK;AACvB,MAAI,YAAY,QAAQ,SAAS,GAAI,QAAO;AAC5C,QAAM,QAAQ,aAAa;AAC3B,QAAM,OAAO,MAAM,KAAK,MAAM,KAAK,OAAO,GAAG,MAAM,QAAQ,QAAQ,EAAE,CAAC;AAAA,EAAK,IAAI;AAC/E,UAAQ,SAAS,IAAI;AACrB,SAAO;AACT;AAGO,SAAS,aAAa,MAAuB;AAClD,QAAM,UAAU,MAAM;AACtB,MAAI,YAAY,KAAM,QAAO;AAC7B,UAAQ,SAAS,IAAI;AACrB,SAAO;AACT;AAGO,SAAS,gBAAsB;AACpC,QAAM,KAAK,SAAS,cAAc,iBAAiB;AACnD,MAAI,cAAc,YAAa,IAAG,MAAM,EAAE,eAAe,KAAK,CAAC;AACjE;AAiBO,SAAS,aAAa,QAAsD;AACjF,MAAI,EAAE,kBAAkB,SAAU,QAAO;AACzC,QAAM,OAAO,OAAO,QAAQ,aAAa;AACzC,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,UAAU,KAAK,iBAAiB,QAAQ;AAC9C,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,QAAM,OAAO,QAAQ,QAAQ,SAAS,CAAC;AAEvC,MAAI,EAAE,gBAAgB,mBAAoB,QAAO;AACjD,MAAI,SAAS,UAAU,CAAC,KAAK,SAAS,MAAM,EAAG,QAAO;AACtD,MAAI,KAAK,SAAU,QAAO;AAE1B,MAAI,KAAK,cAAc,UAAU,MAAM,KAAM,QAAO;AACpD,MAAI,KAAK,cAAc,UAAU,MAAM,KAAM,QAAO;AACpD,SAAO;AACT;AAmCA,SAAS,UAAU,OAA4C;AAC7D,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,QAAM,MAAyB,CAAC;AAChC,aAAW,SAAS,OAAO;AACzB,QAAI,OAAO,UAAU,YAAY,UAAU,KAAM;AACjD,UAAMC,OAAM;AACZ,QAAI,KAAK;AAAA,MACP,IAAI,OAAOA,KAAI,OAAO,WAAWA,KAAI,KAAK;AAAA,MAC1C,MAAM,OAAOA,KAAI,SAAS,WAAWA,KAAI,OAAO;AAAA,MAChD,QAAQ,OAAOA,KAAI,WAAW,WAAWA,KAAI,SAAS;AAAA,IACxD,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAGA,SAAS,WAAW,OAAmC;AACrD,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,SAAO,MAAM,OAAO,CAAC,UAA2B,OAAO,UAAU,QAAQ;AAC3E;AAWA,eAAsB,cAAc,MAAc,MAAwC;AACxF,QAAM,OAAO,KAAK,KAAK;AACvB,MAAI,SAAS,GAAI,QAAO,EAAE,IAAI,OAAO,OAAO,6FAAkB;AAC9D,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,MAAM,oBAAoB;AAAA,MACzC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,MAAM,MAAM,KAAK,CAAC;AAAA,IAC3C,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,EAAE,IAAI,OAAO,OAAO,2EAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,GAAG;AAAA,EACrG;AACA,MAAI,CAAC,SAAS,IAAI;AAChB,WAAO,EAAE,IAAI,OAAO,OAAO,uCAAc,SAAS,MAAM,2EAAe;AAAA,EACzE;AACA,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,SAAS,KAAK;AAAA,EAChC,QAAQ;AACN,WAAO,EAAE,IAAI,OAAO,OAAO,wDAAgB;AAAA,EAC7C;AACA,QAAM,SAAU,OAAO,YAAY,YAAY,YAAY,OAAO,UAAU,CAAC;AAC7E,QAAM,UAAU,OAAO,YAAY;AACnC,MAAI,OAAO,OAAO,MAAM;AACtB,UAAM,UAAU,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,OAAO,QAAQ;AACzF,WAAO,EAAE,IAAI,OAAO,OAAO,SAAS,QAAQ;AAAA,EAC9C;AACA,QAAM,YAAY,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK,KAAK,IAAI;AACzE,MAAI,cAAc,GAAI,QAAO,EAAE,IAAI,OAAO,OAAO,gEAAc,QAAQ;AACvE,QAAM,QAAQ,GAAG,OAAO,OAAO,YAAY,EAAE,CAAC,IAAI,OAAO,OAAO,SAAS,EAAE,CAAC;AAC5E,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM;AAAA,IACN;AAAA,IACA,WAAW,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY;AAAA,IACrE,SAAS,UAAU,OAAO,OAAO;AAAA,IACjC,UAAU,WAAW,OAAO,QAAQ;AAAA,IACpC,UAAU,OAAO,aAAa;AAAA,IAC9B;AAAA,IACA,cAAc,OAAO,OAAO,iBAAiB,WAAW,OAAO,eAAe;AAAA,IAC9E,gBAAgB,OAAO,OAAO,mBAAmB,WAAW,OAAO,iBAAiB;AAAA,EACtF;AACF;;;AC/QA,IAAM,iBAAiB;AACvB,IAAM,mBAAmB;AAGzB,SAAS,iBAAiB,QAAgD;AACxE,MAAI,EAAE,kBAAkB,SAAU,QAAO;AACzC,SAAO,OAAO,QAAqB,cAAc;AACnD;AAGA,SAAS,cAAuB;AAC9B,SAAO,SAAS,cAAc,gBAAgB,MAAM;AACtD;AAGA,IAAI,YAAY;AAGhB,IAAI,qBAAqB;AAGzB,IAAI,aAA4B;AAGhC,SAAS,oBAA0B;AACjC,eAAa;AACb,QAAM,WAAY,UAA+E,WAAW;AAC5G,MAAI,OAAO,aAAa,WAAY;AACpC,WAAS,KAAK,UAAU,SAAS,EAAE;AAAA,IACjC,CAAC,SAAiB;AAAE,mBAAa;AAAA,IAAK;AAAA,IACtC,MAAM;AAAE,mBAAa;AAAA,IAAK;AAAA,EAC5B;AACF;AAGA,SAAS,YAAY,MAAmB,MAA+B;AACrE,cAAY;AACZ,MAAI;AACF,SAAK,cAAc,IAAI,cAAc,WAAW,IAAI,CAAC;AAAA,EACvD,UAAE;AACA,gBAAY;AAAA,EACd;AACF;AAGA,SAAS,UAAU,OAA+B;AAEhD,SAAO,MAAM,eAAe,MAAM,YAAY;AAChD;AAGO,SAAS,oBAAoB,MAAmC;AACrE,QAAM,YAAY,CAAC,UAA+B;AAChD,QAAI,UAAW;AAEf,QAAI,CAAC,eAAe,KAAK,SAAS,CAAC,EAAE,KAAM;AAC3C,UAAM,OAAO,iBAAiB,MAAM,MAAM;AAC1C,QAAI,SAAS,KAAM;AACnB,QAAI,UAAU,KAAK,EAAG;AACtB,UAAM,QAAQ,YAAY,KAA8B;AACxD,QAAI,CAAC,cAAc,KAAK,EAAG;AAE3B,QAAI,YAAY,EAAG;AAEnB,UAAM,WAAW,KAAK,SAAS;AAC/B,UAAM,UAAU,UAAU,SAAS,UAC/B,SACA,UAAU,SAAS,aACjB,YACC,UAAU,gBAAgB,UAAU,eAAgB,gBACnD;AAER,UAAM,eAAe;AACrB,UAAM,gBAAgB;AAEtB,QAAI,MAAM,OAAQ;AAElB,QAAI,YAAY,QAAQ;AAMtB,0BAAoB,KAAK,eAAe,CAAC;AACzC,kBAAY,MAAM,YAAY,OAAO,CAAC;AAAA,IACxC,WAAW,YAAY,WAAW;AAChC,kBAAY,MAAM,YAAY,aAAa,CAAC;AAAA,IAC9C,WAAW,YAAY,eAAe;AACpC,kBAAY,MAAM,YAAY,YAAY,CAAC;AAAA,IAC7C;AAAA,EAEF;AAEA,QAAM,gBAAgB,CAAC,UAA4B;AACjD,UAAM,OAAO,iBAAiB,MAAM,MAAM;AAC1C,QAAI,SAAS,KAAM;AACnB,UAAM,WAAW,KAAK,SAAS;AAE/B,QAAI,CAAC,eAAe,QAAQ,EAAE,KAAM;AACpC,UAAM,OAAO,SAAS;AAItB,QAAI,SAAS,WAAY;AAIzB,QAAI,SAAS,WAAW;AACtB,UAAI,KAAK,SAAS,EAAG,MAAK,QAAQ,IAAI;AACtC,YAAM,yBAAyB;AAC/B,YAAM,gBAAgB;AACtB;AAAA,IACF;AAKA,UAAM,eAAe;AACrB,UAAM,yBAAyB;AAC/B,UAAM,gBAAgB;AACtB,UAAM,YAAY,OAAO,aAAa;AACtC,UAAM,eAAe,cAAc,QAC9B,CAAC,UAAU,eACX,UAAU,eAAe,QACzB,KAAK,SAAS,UAAU,UAAU;AACvC,SAAK,QAAQ,EAAE,GAAG,MAAM,SAAS,GAAG,MAAM,SAAS,aAAa,CAAC;AAEjE,sBAAkB;AAAA,EACpB;AAiBA,QAAM,cAAc,CAAC,UAA4B;AAC/C,QAAI,mBAAoB;AACxB,UAAM,SAAS,aAAa,MAAM,MAAM;AACxC,QAAI,WAAW,KAAM;AACrB,QAAI,CAAC,oBAAoB,KAAK,eAAe,CAAC,EAAG;AACjD,UAAM,eAAe;AACrB,UAAM,gBAAgB;AACtB,yBAAqB;AACrB,QAAI;AACF,aAAO,MAAM;AAAA,IACf,UAAE;AACA,2BAAqB;AAAA,IACvB;AAAA,EACF;AAEA,SAAO,iBAAiB,WAAW,WAAW,IAAI;AAClD,SAAO,iBAAiB,eAAe,eAAe,IAAI;AAC1D,SAAO,iBAAiB,SAAS,aAAa,IAAI;AAClD,SAAO,MAAM;AACX,WAAO,oBAAoB,WAAW,WAAW,IAAI;AACrD,WAAO,oBAAoB,eAAe,eAAe,IAAI;AAC7D,WAAO,oBAAoB,SAAS,aAAa,IAAI;AAAA,EACvD;AACF;AAWA,eAAsB,cAAc,IAA6C;AAC/E,QAAM,OAAO,SAAS,cAA2B,cAAc;AAC/D,MAAI,SAAS,KAAM,QAAO,EAAE,IAAI,OAAO,SAAS,uCAAS;AACzD,MAAI,CAAC,SAAS,iBAAiB,CAAC,KAAK,SAAS,SAAS,aAAa,GAAG;AACrE,QAAI,KAAK,aAAa;AACpB,WAAK,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,IACpC;AAAA,EACF;AACA,UAAQ,IAAI;AAAA,IACV,KAAK;AACH,kBAAY,MAAM,YAAY,QAAQ,CAAC;AACvC,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB,KAAK;AACH,kBAAY,MAAM,YAAY,QAAQ,CAAC;AACvC,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB,KAAK;AACH,aAAO,EAAE,IAAI,SAAS,YAAY,MAAM,EAAE;AAAA,IAC5C,KAAK;AACH,aAAO,EAAE,IAAI,SAAS,YAAY,KAAK,EAAE;AAAA,IAC3C,KAAK;AACH,aAAO,EAAE,IAAI,SAAS,YAAY,QAAQ,EAAE;AAAA,IAC9C,KAAK;AACH,aAAO,EAAE,IAAI,SAAS,YAAY,WAAW,EAAE;AAAA,IACjD,KAAK;AACH,aAAO,UAAU,IAAI;AAAA,EACzB;AACF;AAGA,SAAS,YAAe,SAAqB,IAAwB;AACnE,SAAO,IAAI,QAAW,CAAC,SAAS,WAAW;AACzC,UAAM,QAAQ,WAAW,MAAM;AAAE,aAAO,IAAI,MAAM,wBAAwB,CAAC;AAAA,IAAE,GAAG,EAAE;AAClF,YAAQ;AAAA,MACN,CAAC,UAAU;AAAE,qBAAa,KAAK;AAAG,gBAAQ,KAAK;AAAA,MAAE;AAAA,MACjD,CAAC,UAAmB;AAAE,qBAAa,KAAK;AAAG,eAAO,KAAK;AAAA,MAAE;AAAA,IAC3D;AAAA,EACF,CAAC;AACH;AAEA,SAAS,mBAAmB,OAAyB;AACnD,SAAO,iBAAiB,SAAS,MAAM,YAAY;AACrD;AAGA,SAAS,YAAqB;AAC5B,SAAO,OAAO,cAAc,eAAe,YAAY,KAAK,UAAU,SAAS;AACjF;AAYA,IAAM,cAAc;AAQpB,eAAe,UAAU,MAA8C;AACrE,QAAM,aAAa,CAACC,UAAmC;AACrD,QAAI,CAAC,SAAS,iBAAiB,CAAC,KAAK,SAAS,SAAS,aAAa,GAAG;AACrE,WAAK,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,IACpC;AACA,QAAIA,UAAS,GAAI,QAAO,EAAE,IAAI,KAAK;AACnC,WAAO,EAAE,IAAI,SAAS,YAAY,cAAc,OAAOA,KAAI,EAAE;AAAA,EAC/D;AAEA,MAAI,eAAe,QAAQ,eAAe,IAAI;AAC5C,UAAMA,QAAO;AACb,iBAAa;AACb,WAAO,WAAWA,KAAI;AAAA,EACxB;AACA,MAAI,OAAO,cAAc,eAAe,UAAU,cAAc,UAC3D,OAAO,UAAU,UAAU,aAAa,YAAY;AACvD,WAAO,EAAE,IAAI,OAAO,SAAS,uHAA6B;AAAA,EAC5D;AAEA,QAAM,cAAe,UAElB;AACH,MAAI,aAAa,OAAO;AACtB,QAAI;AACF,YAAM,SAAS,MAAM,YAAY,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACjE,UAAI,OAAO,UAAU,UAAU;AAC7B,YAAI,UAAU,EAAG,QAAO,EAAE,IAAI,OAAO,SAAS,YAAY;AAC1D,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACA,MAAI;AACJ,MAAI;AAGF,WAAO,MAAM,YAAY,UAAU,UAAU,SAAS,GAAG,IAAK;AAAA,EAChE,SAAS,OAAO;AACd,QAAI,UAAU,GAAG;AACf,aAAO,EAAE,IAAI,OAAO,SAAS,YAAY;AAAA,IAC3C;AACA,QAAI,mBAAmB,KAAK,GAAG;AAC7B,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,SAAS;AAAA,MACX;AAAA,IACF;AACA,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS;AAAA,IACX;AAAA,EACF;AACA,MAAI,CAAC,SAAS,iBAAiB,CAAC,KAAK,SAAS,SAAS,aAAa,GAAG;AACrE,SAAK,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,EACpC;AACA,MAAI,SAAS,GAAI,QAAO,EAAE,IAAI,KAAK;AACnC,SAAO,EAAE,IAAI,SAAS,YAAY,cAAc,OAAO,IAAI,EAAE;AAC/D;;;ACnUO,IAAM,iBAAiB;AAIvB,IAAM,qBAAqB;AAE3B,IAAM,uBAAuB;AAE7B,IAAM,oBAAoB;AAE1B,IAAM,oBAAoB;AAMjC,IAAM,OAAO;AAEb,IAAM,QAAQ;AAEd,IAAM,OAAO;AAUN,SAAS,UAAU,MAAiC;AACzD,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAQ,aAAO,EAAE,MAAM,GAAG,KAAK,OAAO,QAAQ,OAAO,OAAO,MAAM,QAAQ,YAAY;AAAA,IAC3F,KAAK;AAAS,aAAO,EAAE,OAAO,GAAG,KAAK,OAAO,QAAQ,OAAO,OAAO,MAAM,QAAQ,YAAY;AAAA,IAC7F,KAAK;AAAO,aAAO,EAAE,KAAK,GAAG,MAAM,OAAO,OAAO,OAAO,QAAQ,MAAM,QAAQ,YAAY;AAAA,IAC1F,KAAK;AAAU,aAAO,EAAE,QAAQ,GAAG,MAAM,OAAO,OAAO,OAAO,QAAQ,MAAM,QAAQ,YAAY;AAAA,IAChG,KAAK;AAAM,aAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,MAAM,QAAQ,MAAM,QAAQ,cAAc;AAAA,EAC5F;AACF;AAGO,IAAM,uBAAsC;AAAA,EACjD,UAAU;AAAA,EACV,OAAO;AAAA;AAAA;AAAA,EAGP,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,eAAe;AACjB;AAaA,IAAM,aAAa;AAAA,GAChB,kBAAkB;AAAA,GAClB,iBAAiB,MAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAQxC,iBAAiB;AAAA,GACjB,iBAAiB;AAAA,GACjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAOjB,iBAAiB;AAAA;AAIb,SAAS,0BAAsC;AACpD,QAAM,MAAM,SAAS,cAAc,OAAO;AAC1C,MAAI,QAAQ,SAAS;AACrB,MAAI,cAAc;AAClB,WAAS,KAAK,YAAY,GAAG;AAC7B,SAAO,MAAM;AACX,QAAI,OAAO;AAAA,EACb;AACF;AAGO,SAAS,oBAAwC;AACtD,SAAO,SAAS,cAA2B,cAAc;AAC3D;AAGO,SAAS,gBAAgB,OAAuB;AACrD,SAAO,KAAK,IAAI,KAAK,KAAK,IAAI,OAAO,KAAK,IAAI,KAAK,OAAO,aAAa,EAAE,CAAC,CAAC;AAC7E;AAEO,SAAS,iBAAiB,QAAwB;AACvD,SAAO,KAAK,IAAI,KAAK,KAAK,IAAI,QAAQ,KAAK,IAAI,KAAK,OAAO,cAAc,EAAE,CAAC,CAAC;AAC/E;;;ACzHA,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA+MV,SAAS,2BAAuC;AACrD,QAAM,MAAM,SAAS,cAAc,OAAO;AAC1C,MAAI,QAAQ,SAAS;AACrB,MAAI,cAAc;AAClB,WAAS,KAAK,YAAY,GAAG;AAC7B,SAAO,MAAM;AAAE,QAAI,OAAO;AAAA,EAAE;AAC9B;;;AC/MO,IAAM,qBAAqB;AAGlC,IAAM,mBAAmB;AAAA,GACtB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAkBlB,kBAAkB;AAAA,GAClB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,GAKlB,kBAAkB;AAAA;AAId,SAAS,0BAAsC;AACpD,QAAM,MAAM,SAAS,cAAc,OAAO;AAC1C,MAAI,QAAQ,SAAS;AACrB,MAAI,cAAc;AAClB,WAAS,KAAK,YAAY,GAAG;AAC7B,SAAO,MAAM;AAAE,QAAI,OAAO;AAAA,EAAE;AAC9B;;;AChDA,mBAAoE;;;ACmB7D,IAAM,cAA6B;AAAA,EACxC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AACV;AAGO,IAAM,MAAqB;AAAA,EAChC,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,KAAK;AAAA,EACL,WAAW;AAAA,EACX,SAAS;AAAA,EACT,WAAW;AACb;AAGO,IAAM,UAAyB;AAAA,EACpC,UAAU;AAAA,EACV,MAAM;AACR;AAGO,IAAM,WAA0B;AAAA,EACrC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AACd;AAGO,IAAM,UAAyB;AAAA,EACpC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AACb;AAGO,IAAM,MAAqB;AAAA,EAChC,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,YAAY;AACd;AAGO,IAAM,OAAsB;AAAA,EACjC,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,YAAY;AACd;AAGO,IAAM,aAA4B;AAAA,EACvC,GAAG;AAAA,EACH,OAAO;AAAA,EACP,aAAa;AACf;AAGO,IAAM,YAA2B;AAAA,EACtC,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM;AACR;AAGO,IAAM,YAA2B;AAAA,EACtC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AACV;AAGO,IAAM,WAA0B;AAAA,EACrC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AACV;AAcO,IAAM,OAAsB;AAAA,EACjC,UAAU;AAAA;AAAA;AAAA,EAGV,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,WAAW;AAAA,EACX,gCAAgC;AAAA,EAChC,SAAS;AAAA,EACT,eAAe;AAAA,EACf,YAAY;AACd;AAGO,IAAM,WAA0B;AAAA,EACrC,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,KAAK;AAAA,EACL,SAAS;AAAA,EACT,cAAc;AAAA,EACd,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,WAAW;AACb;AAEO,IAAM,cAA6B;AAAA,EACxC,GAAG;AAAA,EACH,OAAO;AAAA,EACP,QAAQ;AACV;AAGO,IAAM,eAA8B;AAAA,EACzC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AACd;AAGO,IAAM,gBAA+B;AAAA,EAC1C,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,QAAQ;AACV;AAGO,IAAM,WAA0B;AAAA,EACrC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,SAAS;AACX;AAiBO,IAAM,aAA4B;AAAA,EACvC,UAAU;AAAA;AAAA,EAEV,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS;AAAA,EACT,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,WAAW;AAAA,EACX,gCAAgC;AAAA,EAChC,eAAe;AAAA,EACf,UAAU;AACZ;AAGO,IAAM,iBAAgC;AAAA,EAC3C,SAAS;AAAA,EACT,cAAc;AAAA,EACd,SAAS;AAAA,EACT,eAAe;AAAA,EACf,KAAK;AACP;AAGO,IAAM,qBAAoC;AAAA,EAC/C,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,KAAK;AACP;AAGO,IAAM,kBAAiC;AAAA,EAC5C,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AACd;AAGO,IAAM,eAA8B;AAAA,EACzC,SAAS;AAAA,EACT,KAAK;AAAA,EACL,SAAS;AAAA,EACT,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,QAAQ;AACV;AAGO,IAAM,kBAAiC;AAAA,EAC5C,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AACd;AAOO,IAAM,wBAAuC;AAAA,EAClD,GAAG;AAAA,EACH,YAAY;AAAA,EACZ,OAAO;AACT;AAGO,IAAM,qBAAoC;AAAA,EAC/C,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,KAAK;AAAA,EACL,OAAO;AAAA,EACP,SAAS;AAAA,EACT,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,UAAU;AAAA,EACV,QAAQ;AACV;AAGO,IAAM,6BAA4C;AAAA,EACvD,GAAG;AAAA,EACH,SAAS;AAAA,EACT,QAAQ;AACV;AAGO,IAAM,YAA2B;AAAA,EACtC,WAAW;AAAA,EACX,SAAS;AAAA,EACT,SAAS;AAAA,EACT,eAAe;AAAA,EACf,KAAK;AACP;AAMO,IAAM,YAA2B;AAAA,EACtC,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,SAAS;AAAA,EACT,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,UAAU;AAAA,EACV,WAAW;AACb;AAGO,IAAM,iBAAgC;AAAA,EAC3C,OAAO;AAAA,EACP,UAAU;AAAA,EACV,MAAM;AAAA,EACN,YAAY;AACd;AAGO,IAAM,mBAAkC;AAAA,EAC7C,OAAO;AAAA,EACP,UAAU;AAAA,EACV,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cAAc;AAAA,EACd,YAAY;AACd;AAqBO,IAAM,iBAAgC;AAAA,EAC3C,SAAS;AAAA,EACT,WAAW;AAAA,EACX,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,KAAK;AACP;AAGO,IAAM,cAA6B;AAAA,EACxC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cAAc;AAChB;AAGO,IAAM,gBAA+B;AAAA,EAC1C,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,MAAM;AACR;AAGO,IAAM,aAA4B;AAAA,EACvC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,WAAW;AACb;AAKO,IAAM,mBAAkC;AAAA,EAC7C,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,UAAU;AACZ;AAGO,IAAM,mBAAkC;AAAA,EAC7C,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cAAc;AAChB;AAKO,IAAM,yBAAwC;AAAA,EACnD,GAAG;AAAA,EACH,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,YAAY;AACd;AAGO,IAAM,mBAAkC;AAAA,EAC7C,GAAG;AAAA,EACH,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AACV;;;ADnT6B;AAjH7B,IAAM,SAAoJ;AAAA,EACxJ;AAAA,IACE,EAAE,OAAO,gBAAM,UAAU,UAAU,OAAO,YAAY,IAAI,OAAO;AAAA,IACjE,EAAE,OAAO,gBAAM,UAAU,UAAU,OAAO,YAAY,IAAI,OAAO;AAAA,EACnE;AAAA,EACA;AAAA,IACE,EAAE,OAAO,gBAAM,UAAU,UAAU,OAAO,WAAW,IAAI,MAAM;AAAA,IAC/D,EAAE,OAAO,gBAAM,UAAU,UAAU,OAAO,YAAY,IAAI,OAAO;AAAA,IACjE,EAAE,OAAO,gBAAM,UAAU,UAAU,OAAO,aAAa,IAAI,QAAQ;AAAA,IACnE,EAAE,OAAO,gBAAM,UAAU,IAAI,OAAO,cAAc,IAAI,SAAS;AAAA,EACjE;AAAA,EACA;AAAA,IACE,EAAE,OAAO,gBAAM,UAAU,UAAU,OAAO,iBAAiB,IAAI,YAAY;AAAA,EAC7E;AACF;AAEA,IAAM,cAA4D;AAAA,EAChE,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,WAAW;AACb;AAGA,SAAS,MAAM,OAAe,MAAc,UAA0B;AACpE,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,WAAW,OAAO,CAAC,CAAC;AACzD;AAGO,SAAS,gBAAgB,EAAE,SAAS,SAAS,QAAQ,GAAyB;AACnF,QAAM,YAAY,QAAQ,UAAQ,IAAI;AACtC,QAAM,WAAW,QAAQ,UAAQ,IAAI;AACrC,QAAM,UAAM,qBAA8B,IAAI;AAC9C,QAAM,CAAC,UAAU,WAAW,QAAI,uBAA0C,IAAI;AAG9E,oCAAgB,MAAM;AACpB,QAAI,cAAc,MAAM;AACtB,kBAAY,IAAI;AAChB;AAAA,IACF;AACA,UAAM,KAAK,IAAI;AACf,QAAI,OAAO,KAAM;AACjB,UAAM,OAAO,GAAG,sBAAsB;AACtC,gBAAY;AAAA,MACV,GAAG,MAAM,UAAU,GAAG,KAAK,OAAO,OAAO,UAAU;AAAA,MACnD,GAAG,MAAM,UAAU,GAAG,KAAK,QAAQ,OAAO,WAAW;AAAA,IACvD,CAAC;AAAA,EACH,GAAG,CAAC,WAAW,GAAG,WAAW,CAAC,CAAC;AAG/B,8BAAU,MAAM;AACd,QAAI,cAAc,KAAM;AACxB,UAAM,gBAAgB,CAAC,UAA8B;AACnD,UAAI,IAAI,YAAY,QAAQ,MAAM,kBAAkB,QAAQ,IAAI,QAAQ,SAAS,MAAM,MAAM,EAAG;AAChG,cAAQ,MAAM;AAAA,IAChB;AACA,UAAM,WAAW,CAAC,UAA+B;AAC/C,UAAI,MAAM,QAAQ,SAAU;AAC5B,YAAM,eAAe;AACrB,YAAM,gBAAgB;AACtB,cAAQ,MAAM;AAAA,IAChB;AACA,WAAO,iBAAiB,eAAe,eAAe,IAAI;AAC1D,WAAO,iBAAiB,WAAW,UAAU,IAAI;AACjD,WAAO,iBAAiB,UAAU,QAAQ,OAAO,IAAI;AACrD,WAAO,iBAAiB,UAAU,QAAQ,KAAK;AAC/C,WAAO,MAAM;AACX,aAAO,oBAAoB,eAAe,eAAe,IAAI;AAC7D,aAAO,oBAAoB,WAAW,UAAU,IAAI;AACpD,aAAO,oBAAoB,UAAU,QAAQ,OAAO,IAAI;AACxD,aAAO,oBAAoB,UAAU,QAAQ,KAAK;AAAA,IACpD;AAAA,EACF,GAAG,CAAC,cAAc,MAAM,OAAO,CAAC;AAGhC,8BAAU,MAAM;AACd,QAAI,WAAW,SAAS,OAAW;AACnC,UAAM,QAAQ,WAAW,MAAM;AAAE,cAAQ,KAAK,MAAS;AAAA,IAAE,GAAG,GAAI;AAChE,WAAO,MAAM;AAAE,mBAAa,KAAK;AAAA,IAAE;AAAA,EACrC,GAAG,CAAC,WAAW,IAAI,CAAC;AAEpB,MAAI,cAAc,KAAM,QAAO;AAE/B,QAAM,cAAc,CAAC,OAA2B;AAE9C,QAAI,OAAO,QAAS,SAAQ,KAAK,kDAAU;AAE3C,SAAK,QAAQ,IAAI,EAAE,EAAE,KAAK,CAAC,WAAW;AACpC,UAAI,OAAO,GAAI,SAAQ,MAAM;AAAA,UACxB,SAAQ,KAAK,OAAO,WAAW,0BAAM;AAAA,IAC5C,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,OACZ,IAAI,WAAS,MAAM,OAAO,UAAQ,SAAS,KAAK,KAAK,MAAM,IAAI,CAAC,EAChE,OAAO,WAAS,MAAM,SAAS,CAAC;AAEnC,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,MAAK;AAAA,MACL,OAAO;AAAA,QACL,GAAG;AAAA,QACH,MAAM,UAAU,KAAK,UAAU;AAAA,QAC/B,KAAK,UAAU,KAAK,UAAU;AAAA,MAChC;AAAA,MAEC;AAAA,eAAO,IAAI,CAAC,OAAO,eAClB,6CAAC,aAAAC,QAAM,UAAN,EACE;AAAA,uBAAa,KAAK,4CAAC,SAAI,MAAK,aAAY,OAAO,eAAe;AAAA,UAC9D,MAAM,IAAI,UAAQ;AACjB,kBAAM,iBAAiB,YAAY,KAAK,EAAE,MAAM;AAChD,kBAAM,WAAW,kBAAkB,CAAC,UAAU;AAC9C,kBAAM,QAAQ,WAAW,cAAc;AACvC,mBACE;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAK;AAAA,gBACL,MAAK;AAAA,gBACL;AAAA,gBACA;AAAA,gBACA,aAAa,CAAC,UAAU;AAAE,wBAAM,eAAe;AAAA,gBAAE;AAAA,gBACjD,SAAS,MAAM;AAAE,8BAAY,KAAK,EAAE;AAAA,gBAAE;AAAA,gBAEtC;AAAA,8DAAC,UAAM,eAAK,OAAM;AAAA,kBACjB,KAAK,aAAa,MAAM,4CAAC,UAAK,OAAO,cAAe,eAAK,UAAS;AAAA;AAAA;AAAA,cAT9D,KAAK;AAAA,YAUZ;AAAA,UAEJ,CAAC;AAAA,aApBkB,MAAM,CAAC,EAAG,KAqB/B,CACD;AAAA,QACA,UAAU,SAAS,UAAa,4CAAC,SAAI,OAAO,UAAW,oBAAU,MAAK;AAAA;AAAA;AAAA,EACzE;AAEJ;;;AE5JA,IAAAC,gBAAmD;AACnD,uBAA6B;AA8IzB,IAAAC,sBAAA;AA9GJ,IAAM,QAA+B,CAAC,QAAQ,SAAS,OAAO,UAAU,IAAI;AAGrE,SAAS,mBAAmB,EAAE,SAAS,QAAQ,GAAqB;AACzE,QAAM,WAAW,QAAQ,YAAU;AAAA;AAAA,IAEjC,WAAW,eAAe,KAAK,EAAE;AAAA,IACjC,aAAa,MAAM;AAAA,IACnB,YAAY,MAAM;AAAA,IAClB,aAAa,MAAM;AAAA,EACrB,EAAE;AACF,QAAM,UAAU,SAAS,cAAc,QAAQ,SAAS,gBAAgB;AACxE,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAA6B,IAAI;AAC3D,QAAM,CAACC,SAAQ,SAAS,QAAI,wBAA4B,IAAI;AAC5D,QAAM,cAAU,sBAAyB,IAAI;AAI7C,+BAAU,MAAM;AACd,QAAI,CAAC,SAAS;AACZ,eAAS,IAAI;AACb;AAAA,IACF;AACA,QAAI,UAA8B;AAClC,UAAM,QAAQ,MAAY;AACxB,YAAM,QAAQ,kBAAkB;AAChC,UAAI,UAAU,QAAS;AACvB,gBAAU;AACV,eAAS,KAAK;AAAA,IAChB;AACA,UAAM;AACN,UAAM,QAAQ,YAAY,OAAO,GAAG;AACpC,WAAO,MAAM;AAAE,oBAAc,KAAK;AAAA,IAAE;AAAA,EACtC,GAAG,CAAC,OAAO,CAAC;AAKZ,+BAAU,MAAM;AACd,QAAI,UAAU,KAAM;AACpB,UAAM,QAAQ,SAAS;AACvB,UAAM,SAAS,SAAS;AACxB,QAAI,UAAU,OAAW,OAAM,MAAM,eAAe,OAAO;AAAA,QACtD,OAAM,MAAM,QAAQ,GAAG,gBAAgB,KAAK,CAAC;AAClD,QAAI,WAAW,OAAW,OAAM,MAAM,eAAe,QAAQ;AAAA,QACxD,OAAM,MAAM,SAAS,GAAG,iBAAiB,MAAM,CAAC;AAAA,EACvD,GAAG,CAAC,OAAO,SAAS,YAAY,SAAS,WAAW,CAAC;AAErD,MAAI,CAAC,WAAW,UAAU,KAAM,QAAO;AAEvC,QAAM,gBAAgB,CAAC,MAAkB,UAAoC;AAC3E,UAAM,eAAe;AACrB,UAAM,gBAAgB;AACtB,UAAM,KAAK;AACX,UAAM,OAAO,GAAG,sBAAsB;AAGtC,OAAG,MAAM,WAAW;AACpB,OAAG,MAAM,SAAS;AAClB,OAAG,MAAM,OAAO,GAAG,KAAK,IAAI;AAC5B,OAAG,MAAM,MAAM,GAAG,KAAK,GAAG;AAC1B,OAAG,MAAM,QAAQ,GAAG,KAAK,KAAK;AAC9B,OAAG,MAAM,SAAS,GAAG,KAAK,MAAM;AAEhC,UAAM,QAAmB;AAAA,MACvB;AAAA,MAAM,GAAG,MAAM;AAAA,MAAS,GAAG,MAAM;AAAA,MACjC,MAAM,KAAK;AAAA,MAAM,KAAK,KAAK;AAAA,MAAK,OAAO,KAAK;AAAA,MAAO,QAAQ,KAAK;AAAA,IAClE;AACA,YAAQ,UAAU;AAClB,cAAU,IAAI;AACd,aAAS,KAAK,MAAM,SAAS,OAAO,UAAU,IAAI,EAAE,UAAU,SAAS;AACvE,aAAS,KAAK,MAAM,aAAa;AAEjC,UAAM,SAAS,CAAC,SAA6B;AAC3C,UAAI,QAAQ,YAAY,MAAO;AAC/B,WAAK,eAAe;AACpB,YAAM,KAAK,KAAK,UAAU,MAAM;AAChC,YAAM,KAAK,KAAK,UAAU,MAAM;AAChC,UAAI,EAAE,MAAM,KAAK,OAAO,OAAO,IAAI;AACnC,UAAI,SAAS,WAAW,SAAS,KAAM,SAAQ,gBAAgB,MAAM,QAAQ,EAAE;AAC/E,UAAI,SAAS,YAAY,SAAS,KAAM,UAAS,iBAAiB,MAAM,SAAS,EAAE;AACnF,UAAI,SAAS,QAAQ;AACnB,gBAAQ,gBAAgB,MAAM,QAAQ,EAAE;AACxC,eAAO,MAAM,QAAQ,MAAM,QAAQ;AAAA,MACrC;AACA,UAAI,SAAS,OAAO;AAClB,iBAAS,iBAAiB,MAAM,SAAS,EAAE;AAC3C,cAAM,MAAM,OAAO,MAAM,SAAS;AAAA,MACpC;AACA,SAAG,MAAM,OAAO,GAAG,KAAK,MAAM,IAAI,CAAC;AACnC,SAAG,MAAM,MAAM,GAAG,KAAK,MAAM,GAAG,CAAC;AACjC,SAAG,MAAM,QAAQ,GAAG,KAAK,MAAM,KAAK,CAAC;AACrC,SAAG,MAAM,SAAS,GAAG,KAAK,MAAM,MAAM,CAAC;AAAA,IACzC;AACA,UAAM,OAAO,MAAY;AACvB,aAAO,oBAAoB,eAAe,MAAM;AAChD,aAAO,oBAAoB,aAAa,IAAI;AAC5C,cAAQ,UAAU;AAClB,gBAAU,IAAI;AACd,YAAM,MAAM,GAAG,sBAAsB;AACrC,cAAQ,SAAS,mBAAmB,KAAK,MAAM,gBAAgB,IAAI,KAAK,CAAC,CAAC;AAC1E,cAAQ,SAAS,oBAAoB,KAAK,MAAM,iBAAiB,IAAI,MAAM,CAAC,CAAC;AAC7E,eAAS,KAAK,MAAM,eAAe,QAAQ;AAC3C,eAAS,KAAK,MAAM,eAAe,aAAa;AAAA,IAClD;AACA,WAAO,iBAAiB,eAAe,MAAM;AAC7C,WAAO,iBAAiB,aAAa,IAAI;AAAA,EAC3C;AAEA,aAAO;AAAA,IACL,8CAAC,SAAI,WAAW,oBAAoB,2BAAuB,MACzD;AAAA,mDAAC,SAAI,WAAW,sBAAsB,OAAO,sBAAsB;AAAA,MAClE,MAAM,IAAI,UACT;AAAA,QAAC;AAAA;AAAA,UAEC,WAAW,SAAS,OAAO,oBAAoB;AAAA,UAC/C,eAAaA,YAAW,OAAO,SAAS;AAAA,UACxC,OAAO,SAAS,OAAO,+CAAY;AAAA,UACnC,OAAO,UAAU,IAAI;AAAA,UACrB,eAAe,WAAS;AAAE,0BAAc,MAAM,KAAK;AAAA,UAAE;AAAA,UAEpD,mBAAS,QACR,6CAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,eAAW,MACzD;AAAA,YAAC;AAAA;AAAA,cACC,GAAE;AAAA,cACF,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,eAAc;AAAA;AAAA,UAChB,GACF;AAAA;AAAA,QAfG;AAAA,MAiBP,CACD;AAAA,OACH;AAAA,IACA;AAAA,EACF;AACF;;;ACnLA,IAAAC,gBAAuE;;;ACEvE,IAAAC,gBAAmD;AAwF7C,IAAAC,sBAAA;AArEN,IAAM,UAAyB;AAAA,EAC7B,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,OAAO;AAAA,EACP,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,WAAW;AACb;AAEA,IAAM,aAA4B;AAAA,EAChC,SAAS;AAAA,EACT,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AACV;AAEA,IAAM,gBAA+B;AAAA,EACnC,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,OAAO;AAAA,EACP,SAAS;AAAA,EACT,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,WAAW;AACb;AAGO,SAAS,aAAa;AAAA,EAC3B;AAAA,EAAM;AAAA,EAAY;AAAA,EAAO;AAAA,EAAQ,UAAU;AAC7C,GAAsB;AACpB,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAuC,QAAQ;AACvE,QAAM,UAAM,sBAA8B,IAAI;AAG9C,+BAAU,MAAM;AAAE,YAAQ,QAAQ;AAAA,EAAE,GAAG,CAAC,UAAU,CAAC;AAEnD,+BAAU,MAAM;AACd,QAAI,SAAS,SAAU;AACvB,UAAM,gBAAgB,CAAC,UAA8B;AACnD,UAAI,IAAI,YAAY,QAAQ,MAAM,kBAAkB,QAAQ,IAAI,QAAQ,SAAS,MAAM,MAAM,EAAG;AAChG,cAAQ,QAAQ;AAAA,IAClB;AACA,UAAM,YAAY,CAAC,UAA+B;AAChD,UAAI,MAAM,QAAQ,SAAU,SAAQ,QAAQ;AAAA,IAC9C;AACA,aAAS,iBAAiB,eAAe,eAAe,IAAI;AAC5D,aAAS,iBAAiB,WAAW,WAAW,IAAI;AACpD,WAAO,MAAM;AACX,eAAS,oBAAoB,eAAe,eAAe,IAAI;AAC/D,eAAS,oBAAoB,WAAW,WAAW,IAAI;AAAA,IACzD;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,UAAU,YAAY;AAC5B,QAAM,aAAa,SAAS,SAAS,iBAAiB,MAAM,UAAU,IAAI,CAAC;AAE3E,SACE,8CAAC,SAAI,KAAU,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,EAAE,GACvE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,iBAAe,SAAS;AAAA,QACxB,OAAM;AAAA,QACN,OAAO;AAAA,UACL,GAAG;AAAA,UACH,SAAS,UAAU,YAAY;AAAA,UAC/B,UAAU,UAAU,KAAK;AAAA,QAC3B;AAAA,QACA,aAAa,WAAS;AAAE,gBAAM,eAAe;AAAA,QAAE;AAAA,QAC/C,SAAS,MAAM;AAAE,kBAAQ,SAAS,WAAW,WAAW,QAAQ;AAAA,QAAE;AAAA,QAElE;AAAA,uDAAC,UAAK,eAAW,MAAC,oBAAC;AAAA,UACnB,6CAAC,UAAM,mBAAS,WAAW,gCAAY,gBAAK;AAAA;AAAA;AAAA,IAC9C;AAAA,IAEC,SAAS,YACR,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,GAAG,UAAU,OAAO,GACtD;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO;AAAA,UACP,aAAa,WAAS;AAAE,kBAAM,eAAe;AAAA,UAAE;AAAA,UAC/C,SAAS,MAAM;AAAE,oBAAQ,QAAQ;AAAG,kBAAM;AAAA,UAAE;AAAA,UAC7C;AAAA;AAAA,MAED;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO,SAAS,SAAS,EAAE,GAAG,YAAY,aAAa,iCAAiC,IAAI;AAAA,UAC5F,aAAa,WAAS;AAAE,kBAAM,eAAe;AAAA,UAAE;AAAA,UAC/C,SAAS,MAAM;AAAE,oBAAQ,SAAS,SAAS,WAAW,MAAM;AAAA,UAAE;AAAA,UAC/D;AAAA;AAAA,MAED;AAAA,OACF;AAAA,IAGD,SAAS,UACR;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UAAQ,eAAe;AAAA,UAAU,KAAK;AAAA,UAC/C,WAAW;AAAA,UAAK,WAAW;AAAA,UAC3B,QAAQ;AAAA,UACR,cAAc;AAAA,UAAG,SAAS;AAAA,QAC5B;AAAA,QAEC;AAAA,qBAAW,WAAW,KACrB,6CAAC,UAAK,OAAO,EAAE,OAAO,mCAAmC,UAAU,IAAI,SAAS,UAAU,GAAG,wGAE7F;AAAA,UAED,WAAW,IAAI,eACd;AAAA,YAAC;AAAA;AAAA,cAEC,MAAK;AAAA,cACL,OAAO,GAAG,UAAU,YAAY,SAAM,UAAU,OAAO,MAAM;AAAA,cAC7D,OAAO;AAAA,cACP,aAAa,WAAS;AAAE,sBAAM,eAAe;AAAA,cAAE;AAAA,cAC/C,SAAS,MAAM;AACb,wBAAQ,QAAQ;AAChB,uBAAO,UAAU,OAAO,EAAE;AAAA,cAC5B;AAAA,cAEA;AAAA,6DAAC,UAAK,OAAO,EAAE,OAAO,mCAAmC,UAAU,IAAI,MAAM,WAAW,GACrF,oBAAU,cACb;AAAA,gBACA,6CAAC,UAAK,OAAO,EAAE,OAAO,mCAAmC,MAAM,WAAW,GAAG,kBAAC;AAAA,gBAC9E;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,sBACL,OAAO;AAAA,sBAAkC,UAAU;AAAA,sBACnD,UAAU;AAAA,sBAAG,MAAM;AAAA,sBAAY,UAAU;AAAA,sBACzC,cAAc;AAAA,sBAAY,YAAY;AAAA,oBACxC;AAAA,oBAEC,oBAAU,OAAO;AAAA;AAAA,gBACpB;AAAA,gBACC,UAAU,OAAO,UAChB,6CAAC,UAAK,OAAO,EAAE,OAAO,mCAAmC,UAAU,IAAI,MAAM,WAAW,GAAG,sCAE3F;AAAA;AAAA;AAAA,YA1BG,UAAU,OAAO;AAAA,UA4BxB,CACD;AAAA;AAAA;AAAA,IACH;AAAA,KAEJ;AAEJ;;;AC3JA,IAAM,aAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AASX,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AAGX,IAAM,cAAc;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AASJ,IAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AAsBX,IAAM,aAAgD;AAAA,EACpD,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,UAAU;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGO,IAAM,kBAAkB;AAAA,EAC7B,OAAO;AAAA,IACL,aAAa;AAAA,IACb,QAAQ,CAAC,YAAY,WAAW,MAAO,KAAK,IAAI,GAAG,gBAAgB,WAAW,EAAE,KAAK,MAAM;AAAA,EAC7F;AAAA,EACA,UAAU;AAAA,IACR,aAAa;AAAA,IACb,QAAQ,CAAC,YAAY,WAAW,SAAU,KAAK,IAAI,GAAG,gBAAgB,WAAW,EAAE,KAAK,MAAM;AAAA,EAChG;AAAA,EACA,SAAS;AAAA,IACP,aAAa;AAAA,IACb,QAAQ,CAAC,YAAY,WAAW,QAAS,KAAK,IAAI,GAAG,gBAAgB,WAAW,EAAE,KAAK,MAAM;AAAA,EAC/F;AACF;;;AC/HQ,IAAAC,sBAAA;AAdD,SAAS,kBAAkB,MAAsB;AACtD,SAAO,gBAAgB,IAAqB,GAAG,UAAU,gBAAgB,SAAS;AACpF;AAMO,SAAS,sBAAsB,EAAE,MAAM,OAAO,SAAS,GAA+B;AAC3F,QAAM,QAAQ,gBAAgB,KAAK,UAAQ,KAAK,OAAO,IAAI,GAAG,SAAS;AACvE,QAAM,SAAS,MAAM,KAAK,MAAM;AAChC,SACE,8CAAC,SAAI,OAAO,EAAE,GAAG,KAAK,WAAW,QAAQ,eAAe,UAAU,YAAY,WAAW,KAAK,EAAE,GAC9F;AAAA,kDAAC,SAAI,OAAO,SACV;AAAA,oDAAC,SAAI,OAAO,UACT;AAAA,+CAAS,KAAK;AAAA,QACf,6CAAC,UAAK,OAAO,EAAE,YAAY,GAAG,SAAS,KAAK,GAAI,mBAAS,uBAAQ,gBAAK;AAAA,SACxE;AAAA,MACA,8CAAC,SAAI,OAAO,SAAS;AAAA;AAAA,QAElB;AAAA,QAAI,6CAAC,YAAO,2CAAS;AAAA,QAAS;AAAA,SAEjC;AAAA,OACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,aAAa;AAAA,QACb,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,MAAM,MAAM,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,KAAK,MAAM,SAAS,EAAE,CAAC,CAAC;AAAA,QACtF,UAAU,WAAS;AAAE,mBAAS,MAAM,OAAO,KAAK;AAAA,QAAE;AAAA,QAClD,OAAO,EAAE,GAAG,WAAW,QAAQ,YAAY,YAAY,WAAW,YAAY,IAAI;AAAA;AAAA,IACpF;AAAA,IACA,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,UAAU,OAAO,GAC5E;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO;AAAA,UACP,OAAM;AAAA,UACN,SAAS,MAAM;AAAE,qBAAS,kBAAkB,IAAI,CAAC;AAAA,UAAE;AAAA,UACpD;AAAA;AAAA,MAED;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO;AAAA,UACP,UAAU,CAAC;AAAA,UACX,OAAM;AAAA,UACN,SAAS,MAAM;AAAE,qBAAS,EAAE;AAAA,UAAE;AAAA,UAC/B;AAAA;AAAA,MAED;AAAA,MACA,6CAAC,UAAK,OAAO,EAAE,GAAG,SAAS,MAAM,WAAW,GACzC,sCAAQ,OAAO,MAAM,MAAM,CAAC,MAAM,OAAO,oBAAoB,CAAC,IACjE;AAAA,OACF;AAAA,IACA,8CAAC,aACC;AAAA,mDAAC,aAAQ,OAAO,EAAE,GAAG,SAAS,QAAQ,UAAU,GAAG,kGAAc;AAAA,MACjE,6CAAC,SAAI,OAAO,EAAE,GAAG,SAAS,YAAY,YAAY,QAAQ,UAAU,GAAI,qCAA0B;AAAA,OACpG;AAAA,KACF;AAEJ;;;AC5BQ,IAAAC,sBAAA;AA7BR,IAAM,OAAsB;AAAA,EAC1B,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,YAAY;AACd;AAGA,IAAM,SAAwB;AAAA,EAC5B,GAAG;AAAA,EACH,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,YAAY;AACd;AAGO,SAAS,WAA6B;AAAA,EAC3C;AAAA,EAAO;AAAA,EAAO;AAAA,EAAU;AAAA,EAAW,UAAU;AAC/C,GAAuB;AACrB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,OAAO,EAAE,SAAS,eAAe,YAAY,UAAU,KAAK,GAAG,MAAM,WAAW;AAAA,MAE/E,gBAAM,IAAI,UACT;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,OAAO,KAAK;AAAA,UACZ,gBAAc,UAAU,KAAK;AAAA,UAC7B,OAAO;AAAA,YACL,GAAI,UAAU,KAAK,KAAK,SAAS;AAAA,YACjC,UAAU,UAAU,KAAK;AAAA,YACzB,SAAS,UAAU,YAAY;AAAA,UACjC;AAAA,UAEA,aAAa,WAAS;AAAE,kBAAM,eAAe;AAAA,UAAE;AAAA,UAC/C,SAAS,MAAM;AAAE,qBAAS,KAAK,EAAE;AAAA,UAAE;AAAA,UAElC,eAAK;AAAA;AAAA,QAbD,KAAK;AAAA,MAcZ,CACD;AAAA;AAAA,EACH;AAEJ;;;ACvDI,IAAAC,sBAAA;AAFG,SAAS,kBAAkB,EAAE,MAAM,UAAU,UAAU,OAAO,MAAM,GAA2B;AACpG,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,WAAW,UAAU,SAAY,mCAAU,uCAAS,KAAK;AAAA;AAAA,EAC3D;AAEJ;;;ALwDM,IAAAC,sBAAA;AANN,IAAM,WAA0B,EAAE,GAAG,aAAa,QAAQ,SAAS;AAGnE,SAAS,UAAU;AACjB,SACE,6CAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,eAAY,QACtE;AAAA,IAAC;AAAA;AAAA,MACC,GAAE;AAAA,MACF,QAAO;AAAA,MACP,aAAY;AAAA,MACZ,eAAc;AAAA,MACd,gBAAe;AAAA;AAAA,EACjB,GACF;AAEJ;AAMA,SAAS,SAAS,OAQf;AACD,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAS,KAAK;AACtC,QAAM,MAAM,MAAM,WAAW,UAAa,MAAM,OAAO,YAAY;AACnE,SACE,8CAAC,aAAQ,WAAW;AAAA,IAClB;AAAA,IACA,OAAO,oBAAoB;AAAA,IAC3B,MAAM,mBAAmB;AAAA,EAC3B,EAAE,OAAO,UAAQ,SAAS,EAAE,EAAE,KAAK,GAAG,GAKpC;AAAA,kDAAC,SAAI,WAAU,wBACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,iBAAe;AAAA,UACf,SAAS,MAAM;AAAE,oBAAQ,aAAW,CAAC,OAAO;AAAA,UAAE;AAAA,UAE9C;AAAA,0DAAC,UAAK,WAAU,uBACd;AAAA,2DAAC,UAAK,WAAU,mBAAmB,gBAAM,MAAK;AAAA,cAC9C,6CAAC,UAAK,WAAU,0BACb,gBAAM,2BAAS,MAAM,OAAO,KAAK,MAAM,SAC1C;AAAA,eACF;AAAA,YACA,6CAAC,UAAK,WAAW,OAAO,8CAA8C,sBACpE,uDAAC,WAAQ,GACX;AAAA;AAAA;AAAA,MACF;AAAA,MACA,8CAAC,UAAK,WAAU,uBACb;AAAA,cAAM;AAAA,QACN,MAAM,WAAW,UAChB;AAAA,UAAC;AAAA;AAAA,YACC,OAAK;AAAA,YACL,OAAO,GAAG,MAAM,IAAI;AAAA,YACpB,SAAS,MAAM,OAAO;AAAA,YACtB,UAAU,MAAM,OAAO;AAAA;AAAA,QACzB;AAAA,SAEJ;AAAA,OACF;AAAA,IACC,QAAQ,6CAAC,SAAI,WAAU,mBAAmB,gBAAM,UAAS;AAAA,KAC5D;AAEJ;AAGA,SAAS,OAAO,OASb;AACD,QAAM,EAAE,OAAO,MAAM,OAAO,SAAS,UAAU,UAAU,MAAM,IAAI;AACnE,QAAM,CAAC,WAAW,YAAY,QAAI,wBAAS,KAAK;AAChD,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAwB,IAAI;AAEtD,+BAAU,MAAM;AACd,QAAI,CAAC,UAAW;AAChB,UAAM,YAAY,CAAC,UAA+B;AAEhD,YAAM,eAAe;AACrB,YAAM,gBAAgB;AACtB,UAAI,MAAM,YAAa;AACvB,YAAM,SAAS,oBAAoB,KAA8B;AACjE,UAAI,OAAO,SAAS,SAAU;AAC9B,UAAI,OAAO,SAAS,UAAU;AAC5B,qBAAa,KAAK;AAClB,iBAAS,IAAI;AACb;AAAA,MACF;AACA,UAAI,OAAO,SAAS,SAAS;AAC3B,qBAAa,KAAK;AAClB,iBAAS,IAAI;AACb,iBAAS,EAAE;AACX;AAAA,MACF;AACA,UAAI,OAAO,SAAS,UAAU;AAC5B,iBAAS,OAAO,OAAO;AACvB;AAAA,MACF;AACA,UAAI,SAAS,OAAO,KAAK,GAAG;AAC1B,qBAAa,KAAK;AAClB,iBAAS,sLAAgC;AACzC;AAAA,MACF;AACA,mBAAa,KAAK;AAClB,eAAS,IAAI;AACb,eAAS,OAAO,KAAK;AAAA,IACvB;AACA,WAAO,iBAAiB,WAAW,WAAW,IAAI;AAClD,WAAO,MAAM;AAAE,aAAO,oBAAoB,WAAW,WAAW,IAAI;AAAA,IAAE;AAAA,EACxE,GAAG,CAAC,WAAW,UAAU,QAAQ,CAAC;AAElC,QAAMC,QAAO,UAAU,OAAO,EAAE,GAAG,KAAK,WAAW,OAAO,IAAI;AAE9D,SACE,8CAAC,SAAI,OAAO,EAAE,GAAGA,OAAM,eAAe,UAAU,YAAY,WAAW,KAAK,EAAE,GAC5E;AAAA,kDAAC,SAAI,OAAO,SACV;AAAA,mDAAC,SAAI,OAAO,UAAW,iBAAM;AAAA,MAC7B,6CAAC,SAAI,OAAO,SAAU,gBAAK;AAAA,OAC7B;AAAA,IACA,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,UAAU,OAAO,GAC5E;AAAA,mDAAC,UAAK,OAAO,KAAM,uBAAa,KAAK,GAAE;AAAA,MACtC,CAAC,aAAa,QAAQ,IAAI,YACzB;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,OAAO,UAAU,SAAS,aAAa;AAAA,UACvC,SAAS,MAAM;AAAE,qBAAS,IAAI;AAAG,qBAAS,MAAM;AAAA,UAAE;AAAA,UAEjD,uBAAa,MAAM;AAAA;AAAA,QALf;AAAA,MAMP,CACD;AAAA,MACA,CAAC,aAAa,UAAU,MACvB,6CAAC,YAAO,MAAK,UAAS,OAAO,MAAM,SAAS,MAAM;AAAE,iBAAS,IAAI;AAAG,iBAAS,EAAE;AAAA,MAAE,GAAG,0BAEpF;AAAA,MAEF;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO,YAAY,aAAa;AAAA,UAChC,SAAS,MAAM;AAAE,yBAAa,IAAI;AAAG,qBAAS,IAAI;AAAA,UAAE;AAAA,UAEnD,sBAAY,qDAAa;AAAA;AAAA,MAC5B;AAAA,MACC,aACC,6CAAC,YAAO,MAAK,UAAS,OAAO,MAAM,SAAS,MAAM;AAAE,qBAAa,KAAK;AAAG,iBAAS,IAAI;AAAA,MAAE,GAAG,8BAE3F;AAAA,MAED,UAAU,QACT,6CAAC,UAAK,OAAO,EAAE,OAAO,wCAAwC,UAAU,GAAG,GAAI,iBAAM;AAAA,OAEzF;AAAA,KACF;AAEJ;AAQA,SAAS,OAAO,OAMb;AACD,QAAM,EAAE,SAAS,UAAU,OAAO,QAAQ,MAAM,IAAI;AACpD,QAAM,QAAQ,QAAQ,KAAK;AAC3B,QAAM,SAAS,QAAQ,KAAK;AAC5B,QAAM,OAAO,QAAQ,KAAK;AAC1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,MAAK;AAAA,MACL,gBAAc;AAAA,MACd,cAAY;AAAA,MACZ,OAAO;AAAA,MACP,SAAS,MAAM;AAAE,iBAAS,CAAC,OAAO;AAAA,MAAE;AAAA,MACpC,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,YAAY,UACR,yCACA;AAAA,QACJ,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU;AAAA,YACV,KAAK,QAAQ,IAAI;AAAA,YACjB,MAAM,UAAU,QAAQ,QAAQ,QAAQ,IAAI,KAAM,QAAQ,IAAI;AAAA,YAC9D,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,YAAY,UACR,8CACA;AAAA,YACJ,YAAY;AAAA,UACd;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;AAGA,SAAS,WAAW,OAIjB;AACD,SACE,8CAAC,UAAK,WAAU,qBACd;AAAA,iDAAC,UAAK,WAAU,0BAA0B,gBAAM,OAAM;AAAA,IACtD,6CAAC,UAAO,OAAK,MAAC,OAAO,MAAM,OAAO,SAAS,MAAM,SAAS,UAAU,MAAM,UAAU;AAAA,KACtF;AAEJ;AAGA,SAAS,UAAU,OAOhB;AACD,QAAM,EAAE,OAAO,MAAM,SAAS,UAAU,MAAM,IAAI;AAClD,SACE,8CAAC,SAAI,OAAO,UAAU,OAAO,EAAE,GAAG,KAAK,WAAW,OAAO,IAAI,KAC3D;AAAA,kDAAC,SAAI,OAAO,SACV;AAAA,mDAAC,SAAI,OAAO,UAAW,iBAAM;AAAA,MAC5B,SAAS,UAAa,SAAS,MAAM,6CAAC,SAAI,OAAO,SAAU,gBAAK;AAAA,OACnE;AAAA,IACA,6CAAC,UAAO,OAAc,SAAkB,UAAoB;AAAA,KAC9D;AAEJ;AAIA,SAAS,aAAa,OAUnB;AACD,QAAM,EAAE,OAAO,MAAM,OAAO,aAAa,WAAW,UAAU,QAAQ,MAAM,IAAI;AAChF,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAS,KAAK;AACxC,QAAM,cAAU,sBAAO,KAAK;AAG5B,+BAAU,MAAM;AACd,QAAI,CAAC,QAAQ,QAAS,UAAS,KAAK;AAAA,EACtC,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,SAAS,MAAY;AACzB,QAAI,UAAU,MAAO;AACrB,aAAS,MAAM,KAAK,CAAC;AAAA,EACvB;AAEA,QAAMA,QAAO,UAAU,OAAO,EAAE,GAAG,KAAK,WAAW,OAAO,IAAI;AAE9D,SACE,8CAAC,SAAI,OAAO,EAAE,GAAGA,OAAM,eAAe,UAAU,YAAY,WAAW,KAAK,EAAE,GAC5E;AAAA,kDAAC,SAAI,OAAO,SACV;AAAA,mDAAC,SAAI,OAAO,UAAW,iBAAM;AAAA,MAC7B,6CAAC,SAAI,OAAO,SAAU,gBAAK;AAAA,OAC7B;AAAA,IACA,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAE,GAC1D;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO;AAAA,UACP,aAAa,eAAe;AAAA,UAC5B;AAAA,UACA,YAAY;AAAA,UACZ,aAAY;AAAA,UACZ,gBAAe;AAAA,UACf,SAAS,MAAM;AAAE,oBAAQ,UAAU;AAAA,UAAK;AAAA,UACxC,UAAU,WAAS;AAAE,qBAAS,MAAM,OAAO,KAAK;AAAA,UAAE;AAAA,UAClD,QAAQ,MAAM;AAAE,oBAAQ,UAAU;AAAO,mBAAO;AAAA,UAAE;AAAA,UAClD,WAAW,WAAS;AAClB,gBAAI,MAAM,QAAQ,QAAS;AAC3B,kBAAM,eAAe;AACrB,mBAAO;AACP,kBAAM,cAAc,KAAK;AAAA,UAC3B;AAAA,UACA,OAAO;AAAA;AAAA,MACT;AAAA,MACC,WAAW,UACV,6CAAC,YAAO,MAAK,UAAS,OAAO,MAAM,SAAS,OAAO,SAAU,iBAAO,OAAM;AAAA,OAE9E;AAAA,KACF;AAEJ;AAYA,SAAS,mBAAmB,OAMzB;AACD,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAA0B,MAAM,MAAM,IAAI;AACpE,QAAM,CAAC,UAAU,WAAW,QAAI,wBAAS,MAAM,MAAM,KAAK,WAAW,CAAC,GAAG,MAAM,EAAE;AACjF,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAS,KAAK;AACxC,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,EAAE;AAEzC,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAS,EAAE;AAGnC,+BAAU,MAAM;AACd,QAAI,MAAO;AACX,aAAS,MAAM,IAAI;AACnB,QAAI,CAAC,MAAM,KAAK,WAAW,KAAK,cAAY,SAAS,OAAO,QAAQ,GAAG;AACrE,kBAAY,MAAM,KAAK,WAAW,CAAC,GAAG,MAAM,EAAE;AAAA,IAChD;AAAA,EACF,GAAG,CAAC,MAAM,MAAM,OAAO,QAAQ,CAAC;AAEhC,QAAM,OAAO,CAAC,SAAgC;AAC5C,aAAS,IAAI;AACb,aAAS,IAAI;AAAA,EACf;AACA,QAAM,UAAU,MAAM,WAAW,KAAK,cAAY,SAAS,OAAO,QAAQ,KAAK,MAAM,WAAW,CAAC;AACjG,QAAM,SAAS,WAAW,KAAK;AAC/B,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,SAAS,MAAM,WAAW,MAAM,MAAM,WAAW;AAEvD,QAAM,SAAwB;AAAA,IAC5B,SAAS;AAAA,IAAQ,eAAe;AAAA,IAAU,KAAK;AAAA,IAC/C,SAAS;AAAA,IAAG,cAAc;AAAA,IAC1B,QAAQ;AAAA,IACR,YAAY;AAAA,EACd;AAEA,SACE,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,EAAE,GAE7D;AAAA,kDAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,UAAU,OAAO,GAC3E;AAAA,YAAM,WAAW,IAAI,cACpB;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,OAAO,SAAS,OAAO,SAAS,KAAK,aAAa;AAAA,UAClD,SAAS,MAAM;AAAE,wBAAY,SAAS,EAAE;AAAA,UAAE;AAAA,UAEzC;AAAA,qBAAS;AAAA,YAAK;AAAA,YAAE,SAAS,QAAQ;AAAA,YAAO;AAAA;AAAA;AAAA,QALpC,SAAS;AAAA,MAMhB,CACD;AAAA,MACD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO;AAAA,UACP,aAAY;AAAA,UACZ,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,UAAU,WAAS;AAAE,uBAAW,MAAM,OAAO,KAAK;AAAA,UAAE;AAAA,UACpD,OAAO,EAAE,GAAG,WAAW,MAAM,YAAY;AAAA;AAAA,MAC3C;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO;AAAA,UACP,UAAU,MAAM,WAAW,UAAU;AAAA,UACrC,SAAS,MAAM;AACb,iBAAK,kBAAkB,OAAO,YAAY,KAAK,wBAAwB,OAAO,CAAC;AAC/E,uBAAW,EAAE;AAAA,UACf;AAAA,UACD;AAAA;AAAA,MAED;AAAA,OACF;AAAA,IAEC,YAAY,UACX,6CAAC,OAAE,OAAO,SAAS,sIAAoB;AAAA,IAGxC,YAAY,UACX,8EAEE;AAAA,oDAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,UAAU,OAAO,GAC5E;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,OAAO,QAAQ;AAAA,YACf,cAAW;AAAA,YACX,WAAW;AAAA,YACX,YAAY;AAAA,YACZ,UAAU,WAAS;AAAE,mBAAK,oBAAoB,OAAO,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,YAAE;AAAA,YACtF,OAAO,EAAE,GAAG,WAAW,MAAM,YAAY;AAAA;AAAA,QAC3C;AAAA,QACA,6CAAC,YAAO,MAAK,UAAS,OAAO,MAAM,OAAM,4BAAO,SAAS,MAAM;AAAE,eAAK,kBAAkB,OAAO,QAAQ,IAAI,EAAE,CAAC;AAAA,QAAE,GAAG,oBAAC;AAAA,QACpH,6CAAC,YAAO,MAAK,UAAS,OAAO,MAAM,OAAM,4BAAO,SAAS,MAAM;AAAE,eAAK,kBAAkB,OAAO,QAAQ,IAAI,CAAC,CAAC;AAAA,QAAE,GAAG,oBAAC;AAAA,QACnH;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,OAAO;AAAA,YACP,OAAM;AAAA,YACN,SAAS,MAAM;AAAE,mBAAK,oBAAoB,OAAO,QAAQ,EAAE,CAAC;AAAA,YAAE;AAAA,YAC/D;AAAA;AAAA,QAED;AAAA,QACA,8CAAC,UAAK,OAAO,SAAU;AAAA,kBAAQ,QAAQ;AAAA,UAAO;AAAA,UAAI;AAAA,UAAiB;AAAA,WAAE;AAAA,SACvE;AAAA,MAEC,QAAQ,QAAQ,IAAI,YACnB,8CAAC,SAAoB,OAAO,QAC1B;AAAA,sDAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,UAAU,OAAO,GAC5E;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAO,OAAO;AAAA,cACd,aAAY;AAAA,cACZ,WAAW;AAAA,cACX,YAAY;AAAA,cACZ,UAAU,WAAS;AAAE,qBAAK,kBAAkB,OAAO,QAAQ,IAAI,OAAO,IAAI,EAAE,OAAO,MAAM,OAAO,MAAM,CAAC,CAAC;AAAA,cAAE;AAAA,cAC1G,OAAO,EAAE,GAAG,WAAW,MAAM,YAAY;AAAA;AAAA,UAC3C;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,OAAO;AAAA,cACd,MAAM,aAAa,MAAM;AAAA,cACzB,UAAU,UAAQ;AAAE,qBAAK,eAAe,OAAO,OAAO,IAAI,IAAI,CAAC;AAAA,cAAE;AAAA;AAAA,UACnE;AAAA,UACA,6CAAC,UAAK,OAAO,EAAE,MAAM,EAAE,GAAG;AAAA,UAC1B,6CAAC,YAAO,MAAK,UAAS,OAAO,MAAM,OAAM,gBAAK,SAAS,MAAM;AAAE,iBAAK,gBAAgB,OAAO,QAAQ,IAAI,OAAO,IAAI,EAAE,CAAC;AAAA,UAAE,GAAG,oBAAC;AAAA,UAC3H,6CAAC,YAAO,MAAK,UAAS,OAAO,MAAM,OAAM,gBAAK,SAAS,MAAM;AAAE,iBAAK,gBAAgB,OAAO,QAAQ,IAAI,OAAO,IAAI,CAAC,CAAC;AAAA,UAAE,GAAG,oBAAC;AAAA,UAC1H,6CAAC,YAAO,MAAK,UAAS,OAAO,MAAM,OAAM,4BAAO,SAAS,MAAM;AAAE,iBAAK,kBAAkB,OAAO,QAAQ,IAAI,OAAO,EAAE,CAAC;AAAA,UAAE,GAAG,oBAAC;AAAA,WAC7H;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,OAAO;AAAA,YACd,aAAY;AAAA,YACZ,WAAW;AAAA,YACX,YAAY;AAAA,YACZ,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,KAAK,OAAO,OAAO,SAAS,EAAE,CAAC,CAAC;AAAA,YACnE,UAAU,WAAS;AAAE,mBAAK,kBAAkB,OAAO,QAAQ,IAAI,OAAO,IAAI,EAAE,QAAQ,MAAM,OAAO,MAAM,CAAC,CAAC;AAAA,YAAE;AAAA,YAC3G,OAAO,EAAE,GAAG,WAAW,QAAQ,YAAY,YAAY,WAAW,YAAY,IAAI;AAAA;AAAA,QACpF;AAAA,WA7BQ,OAAO,EA8BjB,CACD;AAAA,MAGD;AAAA,QAAC;AAAA;AAAA,UACC,MAAM;AAAA,UACN,YAAY,QAAQ;AAAA,UACpB,OAAO,MAAM;AAAE,iBAAK,gBAAgB,OAAO,QAAQ,EAAE,CAAC;AAAA,UAAE;AAAA,UACxD,QAAQ,cAAY;AAAE,iBAAK,0BAA0B,OAAO,UAAU,QAAQ,EAAE,CAAC;AAAA,UAAE;AAAA;AAAA,MACrF;AAAA,OACF;AAAA,IAGF,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,UAAU,OAAO,GAC5E;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO,QAAQ,aAAa;AAAA,UAC5B,UAAU,CAAC,SAAS;AAAA,UACpB,SAAS,MAAM;AAGb,kBAAM,OAAwB;AAAA,cAC5B,SAAS,MAAM;AAAA,cACf,YAAY,MAAM,WAAW,IAAI,eAAa;AAAA,gBAC5C,GAAG;AAAA,gBACH,SAAS,SAAS,QAAQ,OAAO,YAAU,OAAO,OAAO,KAAK,MAAM,EAAE;AAAA,cACxE,EAAE;AAAA,YACJ;AACA,kBAAM,UAAU,OAAO,UAAU,WAAW,IAAI,EAAE;AAClD,oBAAQ,UAAU,IAAI,sBAAO,OAAO,OAAO,CAAC,sDAAc,EAAE;AAC5D,kBAAM,OAAO,IAAI;AACjB,qBAAS,KAAK;AAAA,UAChB;AAAA,UAEC,mBAAS,6BAAU,QAAQ,6BAAS;AAAA;AAAA,MACvC;AAAA,MACA,6CAAC,YAAO,MAAK,UAAS,OAAO,MAAM,SAAS,MAAM;AAAE,cAAM,SAAS;AAAA,MAAE,GAAG,sCAAI;AAAA,MAC5E,6CAAC,YAAO,MAAK,UAAS,OAAO,MAAM,SAAS,MAAM;AAAE,cAAM,QAAQ;AAAA,MAAE,GAAG,+CAAQ;AAAA,MAC/E,8CAAC,UAAK,OAAO,SAAS;AAAA;AAAA,QACjB,OAAO;AAAA,QAAW;AAAA,QAAQ,OAAO;AAAA,QAAQ;AAAA,QAAS,OAAO;AAAA,QAAO;AAAA,QAAU,OAAO;AAAA,QAAM;AAAA,QACzF,SAAS,KAAK,KAAK,SAAM,IAAI;AAAA,QAC7B,SAAS,SAAM,MAAM,MAAM,KAAK;AAAA,SACnC;AAAA,OACF;AAAA,IACA,8CAAC,OAAE,OAAO,SAAS;AAAA;AAAA,MACZ,6CAAC,UAAK,uCAAyB;AAAA,MAAO;AAAA,OAE7C;AAAA,KACF;AAEJ;AAGA,IAAM,gBAA+B;AAAA,EACnC,GAAG;AAAA,EACH,WAAW;AAAA,EACX,UAAU;AAAA,EACV,cAAc;AAAA,EACd,YAAY;AACd;AASA,SAAS,oBAAoB,OAK1B;AACD,QAAM,EAAE,UAAU,UAAU,WAAW,MAAM,IAAI;AACjD,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAS,EAAE;AACnC,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAS,KAAK;AACtC,QAAM,aAAa,SAAS;AAE5B,MAAI,SAAS,sBAAsB,eAAe;AAChD,WACE,6CAAC,OAAE,OAAO,UAAU,gSAGpB;AAAA,EAEJ;AAGA,QAAM,WAAW,YAA2B;AAC1C,YAAQ,IAAI;AACZ,YAAQ,EAAE;AACV,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,mBAAmB,EAAE,QAAQ,OAAO,CAAC;AAClE,YAAM,SAAS,MAAM,SAAS,KAAK;AACnC,YAAM,QAAQ,2BAA2B,OAAO,UAAU;AAC1D,cAAQ,MAAM,WAAW,IACrB,yKACA,gBAAM,OAAO,MAAM,MAAM,CAAC,yDAAY;AAAA,IAC5C,SAAS,OAAgB;AACvB,cAAQ,6CAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAAA,IAC5E,UAAE;AACA,cAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAEA,SACE,8EACG;AAAA,KAAC,YACF,8CAAC,SAAI,OAAO,EAAE,GAAG,KAAK,WAAW,QAAQ,eAAe,UAAU,YAAY,WAAW,KAAK,EAAE,GAC9F;AAAA,oDAAC,SAAI,OAAO,SACV;AAAA,qDAAC,SAAI,OAAO,UAAU,sCAAI;AAAA,QAC1B,6CAAC,SAAI,OAAO,SACT,yBAAe,KAAK,UAAQ,KAAK,OAAO,SAAS,YAAY,GAAG,QAAQ,IAC3E;AAAA,SACF;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,OAAO,SAAS;AAAA,UAChB,UAAU,UAAQ;AAAE,qBAAS,qBAAqB,IAAI;AAAA,UAAE;AAAA,UACxD,WAAU;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IAGC,SAAS,iBAAiB,UAAW,8EACpC;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAM;AAAA,UACN,MAAK;AAAA,UACL,OAAO,SAAS;AAAA,UAChB,aAAY;AAAA,UACZ,WAAW;AAAA,UACX,UAAU,UAAQ;AAAE,qBAAS,0BAA0B,IAAI;AAAA,UAAE;AAAA,UAC7D,QAAQ,EAAE,OAAO,OAAO,6BAAS,4BAAQ,SAAS,MAAM;AAAE,iBAAK,SAAS;AAAA,UAAE,EAAE;AAAA;AAAA,MAC9E;AAAA,MACC,WAAW,SAAS,KACnB,6CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,GAAG,WAAW,EAAE,GAC1E,qBAAW,IAAI,eACd;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,OAAO,UAAU;AAAA,UACjB,OAAO,UAAU,SAAS,SAAS,mBAAmB,EAAE,GAAG,eAAe,GAAG,WAAW,IAAI;AAAA,UAC5F,SAAS,MAAM;AAAE,qBAAS,0BAA0B,UAAU,IAAI;AAAA,UAAE;AAAA,UAEnE;AAAA,sBAAU;AAAA,YAAM;AAAA,YAAE,UAAU;AAAA,YAAM,UAAU,WAAW,mCAAU;AAAA;AAAA;AAAA,QAN7D,UAAU;AAAA,MAOjB,CACD,GACH;AAAA,MAED,SAAS,MAAM,6CAAC,OAAE,OAAO,UAAW,gBAAK;AAAA,OAC5C;AAAA,IAEA,8CAAC,OAAE,OAAO,UAAU;AAAA;AAAA,MACd,SAAS,mBAAmB,KAAK,qDAAa,SAAS;AAAA,OAC7D;AAAA,IACA,6CAAC,OAAE,OAAO,UAAU,0XAGpB;AAAA,IACA,6CAAC,OAAE,OAAO,UAAU,iaAGpB;AAAA,IACA,6CAAC,OAAE,OAAO,UAAU,ybAGpB;AAAA,KACF;AAEJ;AAwCA,IAAM,kBAAkB;AAExB,IAAM,kBAAkB;AAGxB,SAAS,YAAY,SAAyB;AAC5C,MAAI,YAAY,YAAY;AAC1B,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,WAAW,aAAa,GAAG;AACrC,WAAO,kCAAS,QAAQ,MAAM,cAAc,MAAM,CAAC;AAAA,EAErD;AACA,SAAO,6FAAkB,OAAO;AAClC;AAGA,SAAS,aAAgC;AACvC,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAuB,MAAM;AACvD,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAAS,EAAE;AACvC,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAwB,IAAI;AAG1D,QAAM,YAAY,YAAuD;AACvE,UAAM,WAAW,MAAM,MAAM,kBAAkB,EAAE,OAAO,WAAW,CAAC;AACpE,QAAI,CAAC,SAAS,GAAI,QAAO,EAAE,OAAO,QAAQ,OAAO,SAAS,MAAM,CAAC,GAAG;AACpE,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,WAAO;AAAA,MACL,SAAS,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;AAAA,MAC/D,SAAS,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;AAAA,MAC/D,SAAS,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;AAAA,MAC/D,SAAS,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;AAAA,MAC/D,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO;AAAA,IACxD;AAAA,EACF;AAGA,QAAM,eAAe,OAAO,cAA6B,YAAmC;AAC1F,UAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,WAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,YAAM,IAAI,QAAc,UAAQ;AAAE,mBAAW,MAAM,eAAe;AAAA,MAAE,CAAC;AACrE,UAAI;AACF,cAAM,QAAQ,MAAM,UAAU;AAC9B,YAAI,WAAW,MAAO;AAEtB,YAAI,MAAM,SAAS,QAAQ,MAAM,SAAS,cAAc;AACtD,mBAAS,OAAO;AAChB;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AACA,aAAS,QAAQ;AACjB,cAAU,2JACL,YAAY,KAAK,KAAK,0DAAa,OAAO,SAAI;AAAA,EACrD;AAGA,QAAM,MAAM,MAAY;AACtB,aAAS,QAAQ;AACjB,cAAU,wDAAW;AACrB,UAAM,YAAY;AAChB,UAAI;AACF,cAAM,QAAQ,MAAM,UAAU;AAC9B,YAAI,WAAW,OAAO;AACpB,mBAAS,QAAQ;AACjB,oBAAU,mDAAW,MAAM,KAAK,yMACC;AACjC;AAAA,QACF;AACA,mBAAW,MAAM,OAAO;AACxB,YAAI,MAAM,YAAY,MAAM;AAC1B,mBAAS,QAAQ;AACjB,oBAAU,YAAY,MAAM,OAAO,CAAC;AACpC;AAAA,QACF;AACA,iBAAS,QAAQ;AAGjB,mBAAW,MAAM,SAAS,OACtB,wPACA,iCAAQ,MAAM,OAAO,YACrB,sBAAO,OAAO,MAAM,OAAO,CAAC,uKAAgC;AAAA,MAClE,SAAS,OAAgB;AACvB,iBAAS,QAAQ;AACjB,kBAAU,mDAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAAA,MAC/E;AAAA,IACF,GAAG;AAAA,EACL;AAGA,QAAM,UAAU,MAAY;AAC1B,aAAS,YAAY;AACrB,cAAU,kLAAiC;AAC3C,UAAM,YAAY;AAChB,UAAI,eAA8B;AAClC,UAAI,UAAU;AACd,UAAI;AACF,cAAM,SAAS,MAAM,UAAU;AAC/B,YAAI,EAAE,WAAW,SAAS;AACxB,yBAAe,OAAO;AACtB,oBAAU,OAAO;AAAA,QACnB;AAAA,MACF,QAAQ;AAAA,MAER;AACA,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,kBAAkB;AAAA,UAC7C,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM;AAAA,QACR,CAAC;AACD,cAAM,SAAS,MAAM,SAAS,KAAK;AACnC,YAAI,SAAS,WAAW,OAAO,OAAO,OAAO,MAAM;AACjD,mBAAS,QAAQ;AACjB,oBAAU,uCAAS,OAAO,SAAS,QAAQ,OAAO,SAAS,MAAM,CAAC,EAAE,sEAClC;AAClC;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AACA,YAAM,aAAa,cAAc,OAAO;AAAA,IAC1C,GAAG;AAAA,EACL;AAEA,QAAM,SAAS,MAAY;AACzB,aAAS,MAAM;AACf,cAAU,EAAE;AAAA,EACd;AAEA,SAAO,EAAE,OAAO,QAAQ,SAAS,KAAK,SAAS,OAAO;AACxD;AAGA,SAAS,cAAc,EAAE,QAAQ,GAA4C;AAC3E,QAAM,OAAO,QAAQ,UAAU,gBAAgB,QAAQ,UAAU;AACjE,QAAM,UAAU,QAAQ;AACxB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAU;AAAA,MACV,UAAU,QAAQ,YAAY;AAAA,MAC9B,OAAO,YAAY,OACf,kOACA,YAAY,OAAO;AAAA,MACvB,SAAS,MAAM;AAAE,gBAAQ,IAAI;AAAA,MAAE;AAAA,MAE9B,kBAAQ,UAAU,eAAe,6BAAS;AAAA;AAAA,EAC7C;AAEJ;AAkBA,SAAS,cAAc,EAAE,KAAK,GAA+B;AAC3D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAU;AAAA,MACV,UAAU;AAAA,MACV,OAAM;AAAA,MACN,SAAS,MAAM;AAAE,eAAO,SAAS,OAAO;AAAA,MAAE;AAAA,MAC3C;AAAA;AAAA,EAED;AAEJ;AAGA,SAAS,cAAc,EAAE,QAAQ,GAA4C;AAC3E,MAAI,QAAQ,UAAU,OAAQ,QAAO;AACrC,QAAM,SAAS,QAAQ,UAAU;AACjC,SACE,8CAAC,SAAI,WAAW,SAAS,oDAAoD,wBAC3E;AAAA,iDAAC,UAAK,WAAU,4BAA4B,kBAAQ,QAAO;AAAA,IAC1D,QAAQ,UAAU,YACjB,8CAAC,UAAK,WAAU,+BACd;AAAA,mDAAC,YAAO,MAAK,UAAS,WAAU,oBAAmB,SAAS,MAAM;AAAE,gBAAQ,QAAQ;AAAA,MAAE,GAAG,sCAAI;AAAA,MAC7F,6CAAC,YAAO,MAAK,UAAS,WAAU,wBAAuB,SAAS,MAAM;AAAE,gBAAQ,OAAO;AAAA,MAAE,GAAG,0BAAE;AAAA,OAChG;AAAA,IAED,UACC,6CAAC,UAAK,WAAU,+BACd,uDAAC,YAAO,MAAK,UAAS,WAAU,wBAAuB,SAAS,MAAM;AAAE,cAAQ,OAAO;AAAA,IAAE,GAAG,gCAAG,GACjG;AAAA,KAEJ;AAEJ;AAGO,SAAS,gBAAgB,EAAE,SAAS,SAAS,eAAe,gBAAgB,QAAQ,GAAyB;AAClH,QAAM,WAAW,QAAQ,UAAQ,IAAI;AACrC,QAAM,OAAO,QAAQ,UAAQ,IAAI;AACjC,QAAM,aAAa,cAAc,UAAQ,IAAI;AAE7C,QAAM,cAAc,eAAe,UAAQ,IAAI;AAC/C,QAAM,CAAC,UAAU,WAAW,QAAI,wBAAwB,IAAI;AAE5D,QAAM,UAAU,WAAW;AAO3B,QAAM,WAAW,eAAe,QAAQ;AAExC,QAAM,SAAS,CAAC,MAA0B,UAAwB;AAChE,UAAM,QAAQ,SAAS,SAAS,SAAS,aAAa,SAAS;AAC/D,QAAI,UAAU,MAAM,UAAU,OAAO;AACnC,kBAAY,KAAK;AACjB;AAAA,IACF;AACA,gBAAY,IAAI;AAChB,YAAQ,SAAS,SAAS,SAAS,YAAY,cAAc,KAAK;AAAA,EACpE;AAEA,QAAM,eAAe,aAAa,OAC9B,SAAI,aAAa,QAAQ,CAAC,yIAC1B;AAEJ,QAAM,cAAc,WAAW,OAAO,UAAQ,SAAS,KAAK,KAAK,CAAC,EAAE;AACpE,QAAM,aAAa,gBAAM,aAAa,SAAS,OAAO,CAAC,sBAAS,aAAa,SAAS,UAAU,CAAC;AAEjG,QAAM,cAAc,SAAS,aAAa,aACtC,qDACA,SAAS,aAAa,YACpB,+FACA,yDAAc,WAAW,MAAM,WAAW,MAAM;AACtD,QAAM,eAAe,4BAAQ,SAAS,cAAc,WAAM,QAAG,SACnD,SAAS,UAAU,OAAI,SAAS,WAAW;AAErD,QAAM,gBAAgB,SAAS,gBAC1B,SAAS,iBAAiB,KAAK,uBAAQ,SAAS,eACjD;AACJ,QAAM,cAAc,WAAW,IAAI;AACnC,QAAM,eAAe,GAAG,YAAY,UAAU,4BAAU,YAAY,OAAO,6BAC9D,YAAY,MAAM,4BAAU,YAAY,KAAK,kCAC3C,gBAAgB,KAAK,UAAQ,KAAK,OAAO,SAAS,aAAa,GAAG,SAAS,cAAI;AAC9F,QAAM,mBAAmB,SAAS,gBAC7B,SAAS,iBAAiB,KAAK,+CAAY,SAAS,eACrD;AAIJ,QAAM,kBAAkB,SAAS,aAAa,QACzC,SAAS,iBAAiB,SAAS,4BAAkB,+CACtD,SAAS,sBAAsB,gBAC7B,2CACA,SAAS,iBAAiB,SACxB,8CACC,SAAS,sBAAsB,SAAS,+BAAgB;AAEjE,SACE,8CAAC,SAAI,OAAO,EAAE,SAAS,UAAU,GAE/B;AAAA,kDAAC,aAAQ,WAAU,eACjB;AAAA,oDAAC,SAAI,WAAU,2BACb;AAAA,sDAAC,UAAK,WAAU,uBACd;AAAA,uDAAC,QAAG,WAAU,mBAAkB,sCAAI;AAAA,UACpC,6CAAC,OAAE,WAAU,0BAAyB,mOAEtC;AAAA,WACF;AAAA,QAMA,8CAAC,UAAK,WAAU,sBAOd;AAAA,uDAAC,iBAAc,MAAM,QAAQ,UAAU,gBAAgB,QAAQ,UAAU,UAAU;AAAA,UACnF,6CAAC,iBAAc,SAAkB;AAAA,UAKjC;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,MAAM;AAAA,cACN,QAAO;AAAA,cACP,KAAI;AAAA,cACJ,OAAM;AAAA,cACP;AAAA;AAAA,gBACQ,6CAAC,UAAK,eAAY,QAAO,oBAAC;AAAA;AAAA;AAAA,UACnC;AAAA,WACF;AAAA,SACF;AAAA,MACA,6CAAC,iBAAc,SAAkB;AAAA,MAOhC,gBAAgB,MACf,8CAAC,SAAI,WAAU,mDAAkD,MAAK,UACpE;AAAA,sDAAC,UAAK,WAAU,4BAA2B;AAAA;AAAA,UAAO;AAAA,WAAY;AAAA,QAC9D,6CAAC,UAAK,WAAU,+BACd,uDAAC,YAAO,MAAK,UAAS,WAAU,wBAAuB,SAAS,MAAM;AAAE,kBAAQ,cAAc;AAAA,QAAE,GAAG,gCAEnG,GACF;AAAA,SACF;AAAA,MAEF,8CAAC,SAAI,WAAU,mBACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAK;AAAA,YACL,OAAM;AAAA,YACN,MAAK;AAAA,YACL,SAAS,SAAS;AAAA,YAClB,UAAU,UAAQ;AAAE,sBAAQ,SAAS,eAAe,IAAI;AAAA,YAAE;AAAA;AAAA,QAC5D;AAAA,QACC,CAAC,SAAS,WACT,6CAAC,OAAE,OAAO,UAAU,2ZAGpB;AAAA,SAEJ;AAAA,OACF;AAAA,IAEC,SAAS,WAAY,8EACtB;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,QAAQ;AAAA,YACN,SAAS,SAAS;AAAA,YAClB,UAAU,UAAQ;AAAE,sBAAQ,SAAS,oBAAoB,IAAI;AAAA,YAAE;AAAA,UACjE;AAAA,UAEA;AAAA,yDAAC,OAAE,OAAO,UAAU,mkBAIpB;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAK;AAAA,gBACL,OAAM;AAAA,gBACN,MAAK;AAAA,gBACL,OAAO,SAAS;AAAA,gBAChB,SAAS;AAAA,gBACT,UAAU,WAAS,UAAU,MAAM,UAAU,SAAS;AAAA,gBACtD,UAAU,WAAS;AAAE,yBAAO,QAAQ,KAAK;AAAA,gBAAE;AAAA;AAAA,YAC7C;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAK;AAAA,gBACL,OAAO,SAAS;AAAA,gBAChB,SAAS;AAAA,gBACT,UAAU,WAAS,UAAU,MAAM,UAAU,SAAS;AAAA,gBACtD,UAAU,WAAS;AAAE,yBAAO,WAAW,KAAK;AAAA,gBAAE;AAAA;AAAA,YAChD;AAAA,YACC,iBAAiB,QAAQ,6CAAC,OAAE,OAAO,WAAY,wBAAa;AAAA,YAC7D,6CAAC,SAAI,OAAO,EAAE,WAAW,GAAG,GAC1B;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO;AAAA,gBACP,SAAS,MAAM;AAAE,8BAAY,IAAI;AAAG,0BAAQ,SAAS;AAAA,gBAAE;AAAA,gBACxD;AAAA;AAAA,YAED,GACF;AAAA;AAAA;AAAA,MACF;AAAA,MAQA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,QAAQ;AAAA,YACN,SAAS,SAAS;AAAA,YAClB,UAAU,UAAQ;AAAE,sBAAQ,SAAS,oBAAoB,IAAI;AAAA,YAAE;AAAA,UACjE;AAAA,UAEA;AAAA,yDAAC,OAAE,OAAO,UAAU,oNAEpB;AAAA,YACA,8CAAC,SAAI,OAAO,EAAE,GAAG,KAAK,WAAW,QAAQ,eAAe,UAAU,YAAY,WAAW,KAAK,EAAE,GAC9F;AAAA,2DAAC,SAAI,OAAO,SACV,uDAAC,SAAI,OAAO,UAAU,sCAAI,GAC5B;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,kBACP,OAAO,SAAS;AAAA,kBAChB,UAAU,UAAQ;AAAE,4BAAQ,SAAS,iBAAiB,IAAI;AAAA,kBAAE;AAAA,kBAC5D,WAAU;AAAA;AAAA,cACZ;AAAA,eACF;AAAA,YACC,SAAS,aAAa,cACrB,8CAAC,OAAE,OAAO,UACR;AAAA,2DAAC,YAAO,0BAAE;AAAA,cAAS;AAAA,eAErB;AAAA,YAED,SAAS,aAAa,aACrB,8CAAC,OAAE,OAAO,UACR;AAAA,2DAAC,YAAO,gCAAG;AAAA,cAAS;AAAA,eAEtB;AAAA,YAED,SAAS,aAAa,YACrB,8EACE;AAAA,4DAAC,OAAE,OAAO,UACR;AAAA,6DAAC,YAAO,gCAAG;AAAA,gBAAS;AAAA,iBAEtB;AAAA,cACA,6CAAC,OAAE,OAAO,UAAU,gqBAKpB;AAAA,cACA,6CAAC,OAAE,OAAO,UAAU,u5BAKpB;AAAA,cACA,6CAAC,OAAE,OAAO,UAAU,4RAGpB;AAAA,cACA,6CAAC,SAAI,OAAO,EAAE,GAAG,KAAK,eAAe,UAAU,YAAY,WAAW,KAAK,EAAE,GAC3E,wDAAC,SAAI,OAAO,SACV;AAAA,6DAAC,SAAI,OAAO,UAAU,sCAAI;AAAA,gBAC1B,6CAAC,SAAI,OAAO,SAAS,6KAA6B;AAAA,iBACpD,GACF;AAAA,cACC,WAAW,IAAI,CAAC,MAAM,UACrB;AAAA,gBAAC;AAAA;AAAA,kBAEC,OAAO,UAAU;AAAA,kBACjB,OAAO,KAAK;AAAA,kBACZ,MAAM,KAAK,aAAa,KAAK,sBAAO,KAAK,QAAQ,KAAK;AAAA,kBACtD,SAAS,SAAS,KAAK,KAAK;AAAA,kBAC5B,UAAU,UAAQ;AAAE,4BAAQ,SAAS,KAAK,OAAoB,IAAI;AAAA,kBAAE;AAAA;AAAA,gBAL/D,KAAK;AAAA,cAMZ,CACD;AAAA,cACD,6CAAC,SAAI,OAAO,EAAE,SAAS,YAAY,GACjC;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,OAAO;AAAA,kBACP,SAAS,MAAM;AAAE,+BAAW,QAAQ,WAAY,SAAQ,SAAS,KAAK,OAAoB,IAAI;AAAA,kBAAE;AAAA,kBACjG;AAAA;AAAA,cAED,GACF;AAAA,eACF;AAAA;AAAA;AAAA,MAEJ;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,QAAQ;AAAA,YACN,SAAS,SAAS;AAAA,YAClB,UAAU,UAAQ;AAAE,sBAAQ,SAAS,qBAAqB,IAAI;AAAA,YAAE;AAAA,UAClE;AAAA,UAEA;AAAA,0DAAC,OAAE,OAAO,UAAU;AAAA;AAAA,cAER,6CAAC,YAAO,wDAAO;AAAA,cAAS;AAAA,cACN,6CAAC,YAAO,0BAAE;AAAA,cAAS;AAAA,cACtC,6CAAC,YAAO,0EAAU;AAAA,cAAS;AAAA,cAId,6CAAC,YAAO,0EAAU;AAAA,cAAS;AAAA,eAGnD;AAAA,YACA,8CAAC,SAAI,OAAO,EAAE,GAAG,KAAK,WAAW,QAAQ,eAAe,UAAU,YAAY,WAAW,KAAK,EAAE,GAC9F;AAAA,4DAAC,SAAI,OAAO,SACV;AAAA,6DAAC,SAAI,OAAO,UAAU,sCAAI;AAAA,gBAC1B,6CAAC,SAAI,OAAO,SACT,0BAAgB,KAAK,UAAQ,KAAK,OAAO,SAAS,aAAa,GAAG,QAAQ,IAC7E;AAAA,iBACF;AAAA,cACA,6CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,UAAU,OAAO,GAC3E,0BAAgB,IAAI,UACnB;AAAA,gBAAC;AAAA;AAAA,kBAEC,MAAK;AAAA,kBACL,OAAO,KAAK;AAAA,kBACZ,OAAO,SAAS,kBAAkB,KAAK,KAAK,aAAa;AAAA,kBACzD,SAAS,MAAM;AAAE,4BAAQ,SAAS,sBAAsB,KAAK,EAAmB;AAAA,kBAAE;AAAA,kBAEjF,eAAK;AAAA;AAAA,gBAND,KAAK;AAAA,cAOZ,CACD,GACH;AAAA,eACF;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAM,SAAS;AAAA,gBACf,OAAO,SAAS,uBAAuB,SAAS,aAAa,CAA6B;AAAA,gBAC1F,UAAU,UAAQ;AAAE,0BAAQ,SAAS,uBAAuB,SAAS,aAAa,GAAoB,IAAI;AAAA,gBAAE;AAAA;AAAA,YAC9G;AAAA,YACA,8CAAC,SAAI,OAAO,EAAE,GAAG,KAAK,WAAW,QAAQ,eAAe,UAAU,YAAY,WAAW,KAAK,EAAE,GAC9F;AAAA,4DAAC,SAAI,OAAO,SACV;AAAA,6DAAC,SAAI,OAAO,UAAU,kDAAM;AAAA,gBAC5B,6CAAC,SAAI,OAAO,SAAS,qPAErB;AAAA,iBACF;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC;AAAA,kBACA,QAAQ;AAAA,kBACR,QAAQ,UAAQ;AAAE,4BAAQ,SAAS,IAAI;AAAA,kBAAE;AAAA,kBACzC,UAAU,MAAM;AAAE,4BAAQ,WAAW;AAAA,kBAAE;AAAA,kBACvC,SAAS,MAAM;AAAE,4BAAQ,UAAU;AAAA,kBAAE;AAAA;AAAA,cACvC;AAAA,eACF;AAAA;AAAA;AAAA,MACF;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,QAAQ;AAAA,YACN,SAAS,SAAS;AAAA,YAClB,UAAU,UAAQ;AAAE,sBAAQ,SAAS,qBAAqB,IAAI;AAAA,YAAE;AAAA,UAClE;AAAA,UAEA,UACE;AAAA,YAAC;AAAA;AAAA,cACC,OAAM;AAAA,cACN,SAAS,SAAS;AAAA,cAClB,UAAU,UAAQ;AAAE,wBAAQ,SAAS,oBAAoB,IAAI;AAAA,cAAE;AAAA;AAAA,UACjE;AAAA,UAGF;AAAA,yDAAC,OAAE,OAAO,UAAU,umBAIpB;AAAA,YACA,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,UAAU,QAAQ,WAAW,GAAG,GAC3F;AAAA,2DAAC,UAAK,OAAO,SAAS,4CAAK;AAAA,cAC3B;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,OAAO;AAAA,kBACP,SAAS,MAAM;AAAE,4BAAQ,WAAW,iBAAiB;AAAG,4BAAQ,WAAW,kBAAkB;AAAA,kBAAE;AAAA,kBAChG;AAAA;AAAA,cAED;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,OAAO,SAAS,eAAe,OAAO,SAAS,gBAAgB,MAAM,aAAa;AAAA,kBAClF,SAAS,MAAM;AACb,4BAAQ,SAAS,mBAAmB,GAAG;AACvC,4BAAQ,SAAS,oBAAoB,GAAG;AAAA,kBAC1C;AAAA,kBACD;AAAA;AAAA,cAED;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,OAAO,SAAS,eAAe,QAAQ,SAAS,gBAAgB,MAAM,aAAa;AAAA,kBACnF,SAAS,MAAM;AACb,4BAAQ,SAAS,mBAAmB,IAAI;AACxC,4BAAQ,SAAS,oBAAoB,GAAG;AAAA,kBAC1C;AAAA,kBACD;AAAA;AAAA,cAED;AAAA,eACF;AAAA;AAAA;AAAA,MACF;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UAET,QAAQ;AAAA,YACN,SAAS,SAAS;AAAA,YAClB,UAAU,UAAQ;AAAE,sBAAQ,SAAS,sBAAsB,IAAI;AAAA,YAAE;AAAA,UACnE;AAAA,UAIA;AAAA,yDAAC,OAAE,OAAO,WAAW,kUAGrB;AAAA,YACA,6CAAC,OAAE,OAAO,UAAU,4mCAOpB;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAM,gBAAM,mBAAmB;AAAA,gBAC/B,OAAO,SAAS;AAAA,gBAChB,aAAa;AAAA,gBACb,WAAW;AAAA,gBACX,UAAU,UAAQ;AAAE,0BAAQ,SAAS,mBAAmB,IAAI;AAAA,gBAAE;AAAA;AAAA,YAChE;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAK;AAAA,gBACL,OAAO,SAAS;AAAA,gBAChB,aAAY;AAAA,gBACZ,WAAW;AAAA,gBACX,UAAU,UAAQ;AAAE,0BAAQ,SAAS,oBAAoB,IAAI;AAAA,gBAAE;AAAA,gBAC/D,QAAQ;AAAA,kBACN,OAAO;AAAA,kBACP,SAAS,MAAM;AAAE,4BAAQ,SAAS,oBAAoB,aAAa,CAAC;AAAA,kBAAE;AAAA,gBACxE;AAAA;AAAA,YACF;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAK;AAAA,gBACL,OAAO,SAAS;AAAA,gBAChB,aAAY;AAAA,gBACZ,WAAW;AAAA,gBACX,UAAU,UAAQ;AAAE,0BAAQ,SAAS,qBAAqB,IAAI;AAAA,gBAAE;AAAA;AAAA,YAClE;AAAA,YACA,8CAAC,OAAE,OAAO,UAAU;AAAA;AAAA,cAAI;AAAA,eAAiB;AAAA;AAAA;AAAA,MAC3C;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,QAAQ;AAAA,YACN,SAAS,SAAS;AAAA,YAClB,UAAU,UAAQ;AAAE,sBAAQ,SAAS,wBAAwB,IAAI;AAAA,YAAE;AAAA,UACrE;AAAA,UAEA,UACE;AAAA,YAAC;AAAA;AAAA,cACC,SAAO;AAAA,cACP,OAAO;AAAA,cACP,OAAO,SAAS;AAAA,cAChB,UAAU,UAAQ;AAAE,wBAAQ,SAAS,qBAAqB,IAAI;AAAA,cAAE;AAAA,cAChE,WAAU;AAAA;AAAA,UACZ;AAAA,UAGF;AAAA,yDAAC,OAAE,OAAO,UAAU,uzBAKpB;AAAA,YACA,6CAAC,uBAAoB,UAAoB,UAAU,QAAQ,UAAU,UAAQ,MAAC;AAAA;AAAA;AAAA,MAChF;AAAA,OACA;AAAA,KACF;AAEJ;;;AM75CA,IAAAC,gBAAyC;AAoErC,IAAAC,sBAAA;AAnCG,SAAS,oBAAoB;AAAA,EAClC;AAAA,EAAU;AAAA,EAAc;AAAA,EAAW;AAAA,EAAY;AAAA,EAAS;AAAA,EAAU;AACpE,GAA6B;AAC3B,QAAM,WAAW,QAAQ,UAAQ,IAAI;AACrC,QAAM,SAAS,SAAS,UAAQ,IAAI;AACpC,QAAM,QAAQ,SAAS,CAAAC,WAASA,OAAM,KAAK;AAQ3C,QAAM,QAAQ,WAAW,CAAAA,WAASA,QAAO,UAAU,IAAI;AACvD,QAAM,UAAM,sBAAiC,IAAI;AAIjD,+BAAU,MAAM;AACd,UAAM,MAAM,OAAO,cAAc,WAAW,YAAY;AACxD,uBAAmB;AAAA,MACjB,SAAU,gBAAgB;AAAA,MAC1B,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,MAC3C,WAAW;AAAA,MACX,OAAO,UAAU;AAAA,IACnB,CAAC;AACD,WAAO,MAAM;AAAE,yBAAmB,GAAG;AAAA,IAAE;AAAA,EACzC,GAAG,CAAC,cAAc,OAAO,WAAW,KAAK,CAAC;AAG1C,MAAI,CAAC,eAAe,QAAQ,EAAE,MAAO,QAAO;AAE5C,QAAM,OAAO,WAAW;AAExB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,MAAK;AAAA,MACL,WAAW;AAAA,MACX,iBAAc;AAAA,MACd,iBAAe;AAAA,MACf,OAAM;AAAA,MAIN,aAAa,WAAS;AAAE,cAAM,eAAe;AAAA,MAAE;AAAA,MAC/C,SAAS,MAAM;AACb,cAAM,OAAO,IAAI,SAAS,sBAAsB;AAChD,gBAAQ,OAAO;AAAA,UACb,MAAM,MAAM,QAAQ;AAAA,UACpB,QAAQ,MAAM,UAAU;AAAA,UACxB,OAAO,MAAM,SAAS;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,OAAM;AAAA,YACN,QAAO;AAAA,YACP,eAAW;AAAA,YAEX;AAAA,cAAC;AAAA;AAAA,gBACC,GAAE;AAAA,gBACF,MAAK;AAAA;AAAA,YACP;AAAA;AAAA,QACF;AAAA,QACA,6CAAC,UAAK,sCAAI;AAAA;AAAA;AAAA,EACZ;AAEJ;;;ACpGA,IAAAC,gBAAoE;AA0I5D,IAAAC,sBAAA;AA5ER,IAAM,SAAS;AAEf,IAAM,MAAM;AAGL,SAAS,mBAAmB;AAAA,EACjC;AAAA,EAAS;AAAA,EAAU;AAAA,EAAS;AAAA,EAAW;AAAA,EAAS;AAAA,EAAe;AACjE,GAA4B;AAC1B,QAAM,WAAW,QAAQ,UAAQ,IAAI;AACrC,QAAM,SAAS,SAAS,UAAQ,IAAI;AACpC,QAAM,OAAO,QAAQ,UAAQ,IAAI;AACjC,QAAM,SAAS,UAAU,UAAQ,IAAI;AACrC,QAAM,OAAO,QAAQ,UAAQ,IAAI;AACjC,QAAM,SAAS,cAAc,UAAQ,IAAI;AACzC,QAAM,UAAM,sBAA8B,IAAI;AAC9C,QAAM,CAAC,UAAU,WAAW,QAAI,wBAA+C,IAAI;AACnF,QAAM,CAAC,UAAU,WAAW,QAAI,wBAAS,EAAE;AAE3C,QAAM,SAAS,WAAW,IAAI;AAC9B,QAAM,aAAa,KAAK;AACxB,QAAMC,UAAS,WAAW,KAAK,cAAY,SAAS,OAAO,QAAQ,KAAK,WAAW,CAAC;AAGpF,qCAAgB,MAAM;AACpB,QAAI,WAAW,MAAM;AACnB,kBAAY,IAAI;AAChB;AAAA,IACF;AACA,UAAM,KAAK,IAAI;AACf,UAAM,SAAS,OAAO,OAAO,MAAM,GAAG,sBAAsB,EAAE;AAC9D,UAAM,QAAQ,OAAO,OAAO,MAAM,GAAG,sBAAsB,EAAE;AAC7D,UAAM,OAAO,KAAK,IAAI,QAAQ,KAAK,IAAI,OAAO,MAAM,OAAO,aAAa,QAAQ,MAAM,CAAC;AACvF,UAAM,QAAQ,OAAO,SAAS,SAAS;AACvC,UAAM,MAAM,SAAS,SAAS,QAAQ,KAAK,IAAI,OAAO,SAAS,KAAK,OAAO,cAAc,SAAS,MAAM;AACxG,gBAAY,EAAE,MAAM,KAAK,KAAK,IAAI,QAAQ,GAAG,EAAE,CAAC;AAAA,EAClD,GAAG,CAAC,QAAQ,MAAM,QAAQ,QAAQ,OAAO,SAAS,WAAW,QAAQ,IAAI,CAAC;AAG1E,+BAAU,MAAM;AACd,QAAI,WAAW,KAAM;AACrB,UAAM,gBAAgB,CAAC,UAA8B;AACnD,UAAI,IAAI,YAAY,QAAQ,MAAM,kBAAkB,QAAQ,IAAI,QAAQ,SAAS,MAAM,MAAM,EAAG;AAEhG,UAAI,MAAM,kBAAkB,WAAW,MAAM,OAAO,QAAQ,2BAA2B,MAAM,KAAM;AACnG,cAAQ,MAAM;AAAA,IAChB;AACA,UAAM,WAAW,CAAC,UAA+B;AAC/C,UAAI,MAAM,QAAQ,SAAU;AAC5B,YAAM,eAAe;AACrB,YAAM,gBAAgB;AACtB,cAAQ,MAAM;AAAA,IAChB;AACA,WAAO,iBAAiB,eAAe,eAAe,IAAI;AAC1D,WAAO,iBAAiB,WAAW,UAAU,IAAI;AACjD,WAAO,iBAAiB,UAAU,QAAQ,KAAK;AAC/C,WAAO,MAAM;AACX,aAAO,oBAAoB,eAAe,eAAe,IAAI;AAC7D,aAAO,oBAAoB,WAAW,UAAU,IAAI;AACpD,aAAO,oBAAoB,UAAU,QAAQ,KAAK;AAAA,IACpD;AAAA,EACF,GAAG,CAAC,WAAW,MAAM,OAAO,CAAC;AAE7B,MAAI,WAAW,KAAM,QAAO;AAE5B,QAAM,OAAO,SAAS;AACtB,QAAM,QAAQA,SAAQ,WAAW,CAAC;AAClC,QAAM,UAAU,WAAW,MAAM,WAAW,WAAW,SAAS;AAEhE,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,MAAK;AAAA,MACL,cAAW;AAAA,MACX,OAAO,EAAE,GAAG,YAAY,MAAM,UAAU,QAAQ,OAAO,MAAM,KAAK,UAAU,OAAO,OAAO,OAAO;AAAA,MAEjG;AAAA,sDAAC,SAAI,OAAO,gBACV;AAAA,wDAAC,SAAI,OAAO,oBACV;AAAA,yDAAC,UAAK,OAAO,iBAAiB,sCAAI;AAAA,YAClC,6CAAC,SAAI,OAAO,cAAc,MAAK,SAAQ,cAAW,4BAC/C,0BAAgB,IAAI,UACnB;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAK;AAAA,gBACL,OAAO,KAAK;AAAA,gBACZ,gBAAc,SAAS,KAAK;AAAA,gBAC5B,OAAO,SAAS,KAAK,KAAK,wBAAwB;AAAA,gBAClD,aAAa,WAAS;AAAE,wBAAM,eAAe;AAAA,gBAAE;AAAA,gBAC/C,SAAS,MAAM;AAAE,0BAAQ,QAAQ,KAAK,EAAE;AAAA,gBAAE;AAAA,gBAEzC,eAAK;AAAA;AAAA,cARD,KAAK;AAAA,YASZ,CACD,GACH;AAAA,aACF;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,UAAU;AAAA,cACV,OAAM;AAAA,cACN,OAAO,OAAO,6BAA6B;AAAA,cAC3C,aAAa,WAAS;AAAE,sBAAM,eAAe;AAAA,cAAE;AAAA,cAC/C,SAAS,MAAM;AAAE,wBAAQ,SAAS;AAAA,cAAE;AAAA,cAEpC;AAAA,6DAAC,UAAK,eAAW,MAAC,oBAAC;AAAA,gBACnB,6CAAC,UAAM,iBAAO,6BAAS,kCAAQ;AAAA;AAAA;AAAA,UACjC;AAAA,UACA,8CAAC,SAAI,OAAO,kBACT;AAAA,uBAAW,IAAI,cACd;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAK;AAAA,gBACL,OAAO,GAAG,SAAS,IAAI,SAAI,OAAO,SAAS,QAAQ,MAAM,CAAC;AAAA,gBAC1D,gBAAc,SAAS,OAAOA,SAAQ;AAAA,gBACtC,OAAO,SAAS,OAAOA,SAAQ,KAAK,yBAAyB;AAAA,gBAC7D,aAAa,WAAS;AAAE,wBAAM,eAAe;AAAA,gBAAE;AAAA,gBAC/C,SAAS,MAAM;AAAE,8BAAY,SAAS,EAAE;AAAA,gBAAE;AAAA,gBAEzC,mBAAS;AAAA;AAAA,cARL,SAAS;AAAA,YAShB,CACD;AAAA,YACD;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO;AAAA,gBACP,UAAU,WAAW,UAAU;AAAA,gBAC/B,OAAM;AAAA,gBACN,aAAa,WAAS;AAAE,wBAAM,eAAe;AAAA,gBAAE;AAAA,gBAC/C,SAAS,MAAM;AACb,0BAAQ,YAAY,qBAAqB;AAAA,gBAC3C;AAAA,gBACD;AAAA;AAAA,YAED;AAAA,aACF;AAAA,WACF;AAAA,QAEA,8CAAC,SAAI,OAAO,WACT;AAAA,gBAAM,WAAW,KAChB,8CAAC,SAAI,OAAO,YAAY;AAAA;AAAA,YACX,6CAAC,QAAG;AAAA,YAAE;AAAA,aAEnB;AAAA,UAED,MAAM,IAAI,UACT,8CAAC,SAAkB,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAE,GACxE;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO,KAAK;AAAA,gBACZ,OAAO;AAAA,gBACP,aAAa,WAAS;AAAE,wBAAM,eAAe;AAAA,gBAAE;AAAA,gBAC/C,SAAS,MAAM;AAAE,0BAAQ,OAAO,KAAK,MAAM;AAAA,gBAAE;AAAA,gBAE7C;AAAA,+DAAC,UAAK,OAAO,gBAAiB,eAAK,OAAM;AAAA,kBACzC,6CAAC,UAAK,OAAO,kBAAmB,eAAK,OAAO,QAAQ,QAAQ,GAAG,GAAE;AAAA;AAAA;AAAA,YACnE;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAO;AAAA,gBACP,OAAO,KAAK;AAAA,gBACZ,MAAM,aAAa,IAAI;AAAA,gBACvB,UAAU,UAAQ;AAAE,0BAAQ,cAAc,KAAK,IAAI,IAAI;AAAA,gBAAE;AAAA;AAAA,YAC3D;AAAA,eAhBQ,KAAK,EAiBf,CACD;AAAA,UACAA,YAAW,UACV;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR;AAAA,cACA,YAAYA,QAAO;AAAA,cACnB,OAAO,MAAM;AAAE,wBAAQ,UAAUA,QAAO,EAAE;AAAA,cAAE;AAAA,cAC5C,QAAQ,cAAY;AAAE,wBAAQ,WAAW,UAAUA,QAAO,EAAE;AAAA,cAAE;AAAA;AAAA,UAChE;AAAA,WAEJ;AAAA,QAEA,8CAAC,SAAI,OAAO,gBACV;AAAA,uDAAC,UAAK,OAAO,aAAa,MAAK,UAAU,qBAAW,KAAK,SAAS,SAAQ;AAAA,UAC1E;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,cACP,OAAM;AAAA,cAEL;AAAA,uBAAO;AAAA,gBAAW;AAAA,gBAAO,OAAO;AAAA,gBAAQ;AAAA;AAAA;AAAA,UAC3C;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;ArB5NO,IAAM,OAAO;AAWb,IAAM,SAAS,CAAC,OAAO;AAiB9B,IAAM,aAAgC;AAAA,EACpC,aAAa,OAAO,EAAE,QAAQ,eAAe,OAAO,OAAU;AAAA,EAC9D,WAAW,MAAM,MAAM;AAAA,EAAC;AAAA,EACxB,KAAK,YAAY;AAAA,EACjB,OAAO,YAAY;AAAA,EACnB,QAAQ,YAAY;AACtB;AAGO,SAAS,MAAM,KAAgB;AACpC,QAAM,QAAQ,IAAI;AAElB,QAAM,WAAO,6CAAwC,EAAE,GAAG,iBAAiB,CAAC;AAC5E,QAAMC,YAAO,6CAAsC,IAAI;AACvD,QAAM,YAAQ,6CAA6C,IAAI;AAC/D,QAAM,iBAAa,6CAA6B,KAAK;AACrD,QAAM,kBAAc,6CAA4B,EAAE;AAQlD,QAAM,kBAAc,6CAA4B,EAAE;AAGlD,MAAI,QAA2B;AAE/B,QAAM,OAAO,MAAY;AACvB,UAAM,WAAW,MAAM,YAAY;AACnC,SAAK,IAAI,SAAS,WAAW,WAAW,SAAS,UAAU,SACvD,EAAE,GAAG,kBAAkB,GAAG,iBAAiB,SAAS,KAAK,EAAE,IAC3D,EAAE,GAAG,iBAAiB,CAAC;AAAA,EAC7B;AACA,OAAK;AASL,MAAI,UAAU;AACd,QAAM,gBAAgB,CAAC,SAAkB,UAAgC;AACvE,QAAI,WAAW,YAAY,QAAQ,YAAY,OAAW;AAC1D,UAAM,MAAM;AAIZ,UAAM,OAAO,UAAU,QAAQ,IAAI,MAAM,SAAS,IAAI,IAAI,OAAO,EAAE,WAAW,UAAU,CAAC;AACzF,QAAI,SAAS,QAAQ,SAAS,OAAW;AACzC,QAAI,OAAQ,KAA2B,gBAAgB,WAAY;AACnE,cAAU;AACV,YAAQ;AACR,SAAK;AACL,QAAI,OAAO,MAAM,MAAM,UAAU,IAAI,GAAG,4BAA4B;AAAA,EACtE;AAOA,QAAM,cAAc,CAAC,MAAgB,aAA4D;AAC/F,QAAI,OAAO,IAAI,WAAW,WAAY;AACtC,QAAI;AACF,UAAI,OAAO,MAAM,QAAQ;AAAA,IAC3B,SAAS,OAAgB;AACvB,cAAQ,KAAK,gDAAgD,KAAK;AAAA,IACpE;AAAA,EACF;AACA,cAAY,CAAC,aAAa,GAAG,UAAQ;AAAE,kBAAc,KAAK,aAAa,KAAK;AAAA,EAAE,CAAC;AAC/E,cAAY,CAAC,eAAe,GAAG,UAAQ;AAAE,kBAAc,KAAK,eAAe,MAAM;AAAA,EAAE,CAAC;AAUpF,QAAM,cAAc,CAACC,UAA0B;AAC7C,QAAI;AACF,aAAQ,IAAgCA,KAAI;AAAA,IAC9C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,gBAAc,YAAY,aAAa,GAAG,KAAK;AAC/C,gBAAc,YAAY,eAAe,GAAG,MAAM;AAelD,QAAM,oBAAoB;AAC1B,QAAM,WAAW,CAAC,OAAsB,UAAyB;AAC/D,gBAAY,IAAI,EAAE;AAClB,UAAM,SAAS,OAAO,UAAU;AAChC,SAAK,MAAM,IAAI,OAAO,KAAc,EAAE,KAAK,CAAC,aAAsB;AAChE,UAAI,aAAa,OAAO;AACtB,gBAAQ,KAAK,wCAAwC,KAAK;AAC1D,oBAAY;AAAA,UACV,qBAAM,KAAK;AAAA,QAGb;AACA;AAAA,MACF;AACA,UAAI,CAAC,OAAQ;AACb,iBAAW,MAAM;AACf,cAAM,MAAO,KAAK,YAAY,EAAyC,KAAK;AAC5E,YAAI,QAAQ,MAAO;AACnB,gBAAQ,KAAK,sDAAsD,OAAO,KAAK,KAAK;AACpF,oBAAY;AAAA,UACV,qBAAM,KAAK,kIAAyB,OAAO,GAAG,CAAC;AAAA,QAEjD;AAAA,MACF,GAAG,iBAAiB;AAAA,IACtB,GAAG,CAAC,UAAmB;AACrB,cAAQ,MAAM,uCAAuC,KAAK;AAC1D,kBAAY,IAAI,qBAAM,KAAK,2BAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAAA,IAC5F,CAAC;AAAA,EACH;AACA,QAAM,aAAa,CAAC,UAA+B;AACjD,SAAK,MAAM,MAAM,KAAK,EAAE,KAAK,CAAC,aAAsB;AAClD,UAAI,aAAa,MAAO,SAAQ,KAAK,wCAAwC,KAAK;AAAA,IACpF,GAAG,CAAC,UAAmB;AACrB,cAAQ,MAAM,uCAAuC,KAAK;AAAA,IAC5D,CAAC;AAAA,EACH;AAMA,QAAM,WAAO,6CAAqC,iBAAiB,CAAC;AAEpE,QAAM,iBAAa,6CAA4B,EAAE;AAEjD,QAAM,aAAa,YAA2B;AAC5C,UAAM,QAAQ,MAAM,eAAe;AACnC,QAAI,MAAM,MAAM,MAAM,SAAS,QAAW;AACxC,WAAK,IAAI,MAAM,IAAI;AACnB,iBAAW,IAAI,EAAE;AACjB;AAAA,IACF;AACA,eAAW,IAAI,MAAM,SAAS,kDAAU;AAAA,EAC1C;AAEA,QAAM,aAAa,CAAC,SAAgC;AAClD,SAAK,IAAI,IAAI;AACb,eAAW,IAAI,QAAQ;AACvB,SAAK,eAAe,IAAI,EAAE;AAAA,MACxB,CAAC,UAAU;AACT,YAAI,MAAM,MAAM,MAAM,SAAS,QAAW;AAExC,eAAK,IAAI,MAAM,IAAI;AACnB,qBAAW,IAAI,EAAE;AACjB;AAAA,QACF;AACA,mBAAW,IAAI,MAAM,SAAS,0BAAM;AACpC,aAAK,WAAW;AAAA,MAClB;AAAA,MACA,CAAC,UAAmB;AAClB,mBAAW,IAAI,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AACrE,aAAK,WAAW;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAEA,OAAK,WAAW;AAEhB,QAAM,cAAc;AAAA,IAClB,QAAQ,MAAY;AAAE,WAAK,WAAW;AAAA,IAAE;AAAA,IACxC,aAAa,CAACA,UAAuB;AAAE,iBAAW,kBAAkB,KAAK,YAAY,GAAGA,KAAI,CAAC;AAAA,IAAE;AAAA,IAC/F,gBAAgB,CAAC,IAAYA,UAAuB;AAClD,iBAAW,oBAAoB,KAAK,YAAY,GAAG,IAAIA,KAAI,CAAC;AAAA,IAC9D;AAAA,IACA,gBAAgB,CAAC,OAAqB;AAAE,iBAAW,oBAAoB,KAAK,YAAY,GAAG,EAAE,CAAC;AAAA,IAAE;AAAA,IAChG,cAAc,CAAC,IAAY,UAAwB;AACjD,iBAAW,kBAAkB,KAAK,YAAY,GAAG,IAAI,KAAK,CAAC;AAAA,IAC7D;AAAA,IACA,WAAW,CAAC,eAA6B;AAAE,iBAAW,gBAAgB,KAAK,YAAY,GAAG,UAAU,CAAC;AAAA,IAAE;AAAA,IACvG,aAAa,CAAC,YAAoB,IAAY,UAAqD;AACjG,iBAAW,kBAAkB,KAAK,YAAY,GAAG,YAAY,IAAI,KAAK,CAAC;AAAA,IACzE;AAAA,IACA,cAAc,CAAC,YAAoB,OAAqB;AACtD,iBAAW,kBAAkB,KAAK,YAAY,GAAG,YAAY,EAAE,CAAC;AAAA,IAClE;AAAA,IACA,YAAY,CAAC,YAAoB,IAAY,UAAwB;AACnE,iBAAW,gBAAgB,KAAK,YAAY,GAAG,YAAY,IAAI,KAAK,CAAC;AAAA,IACvE;AAAA,IACA,WAAW,MAAY;AAAE,iBAAW,iBAAiB,CAAC;AAAA,IAAE;AAAA;AAAA,IAExD,sBAAsB,CAAC,UAAkB,iBAA+B;AACtE,iBAAW,0BAA0B,KAAK,YAAY,GAAG,UAAU,YAAY,CAAC;AAAA,IAClF;AAAA;AAAA,IAEA,UAAU,CAAC,SAAgC;AAAE,iBAAW,IAAI;AAAA,IAAE;AAAA,EAChE;AAEA,QAAM,WAAW,MAAY;AAK3B,SAAK,MAAM;AAAA,MACT;AAAA,QACE;AAAA,QAAe;AAAA,QAAgB;AAAA,QAAmB,GAAG;AAAA,QACrD;AAAA;AAAA,QAEA;AAAA,QACA;AAAA,QAAoB;AAAA,QAAmB;AAAA,QACvC;AAAA,QAAsB;AAAA,QAAmB;AAAA,QAAoB;AAAA,QAC7D;AAAA;AAAA,QAEA;AAAA,QAAqB;AAAA;AAAA;AAAA,QAGrB;AAAA,QAAoB;AAAA,QAAoB;AAAA,QACxC;AAAA,QAAqB;AAAA;AAAA;AAAA,QAGrB;AAAA,MACF,EAAE,IAAI,YAAU,EAAE,IAAI,SAAS,MAAM,CAAC,KAAK,EAAE,EAAE;AAAA,IACjD,EAAE,MAAM,CAAC,UAAmB;AAC1B,cAAQ,MAAM,uCAAuC,KAAK;AAAA,IAC5D,CAAC;AACD,gBAAY,UAAU;AAAA,EACxB;AAKA,MAAI;AACJ,QAAM,OAAO,CAAC,SAAiB,KAAK,SAAe;AACjD,gBAAY,IAAI,OAAO;AACvB,QAAI,gBAAgB,OAAW,cAAa,WAAW;AACvD,QAAI,YAAY,GAAI;AACpB,kBAAc,WAAW,MAAM;AAAE,kBAAY,IAAI,EAAE;AAAA,IAAE,GAAG,EAAE;AAAA,EAC5D;AACA,MAAI,OAAO,MAAM,MAAM;AACrB,QAAI,gBAAgB,OAAW,cAAa,WAAW;AAAA,EACzD,GAAG,iCAAiC;AAEpC,QAAM,eAAe;AAAA,IACnB,QAAQ,CAAC,WAAkE;AACzE,UAAI,MAAM,YAAY,MAAM,MAAM;AAChC,cAAM,IAAI,IAAI;AACd,oBAAY,IAAI,EAAE;AAClB;AAAA,MACF;AACA,kBAAY,IAAI,EAAE;AAClB,YAAM,IAAI,MAAM;AAAA,IAClB;AAAA,IACA,OAAO,MAAY;AACjB,YAAM,IAAI,IAAI;AACd,kBAAY,IAAI,EAAE;AAAA,IACpB;AAAA,IACA,QAAQ,CAAC,SAAuB;AAC9B,UAAI,gBAAgB,IAAI,EAAG,eAAc;AAAA,IAC3C;AAAA,IACA,UAAU,MAAY;AACpB,UAAI,WAAW,YAAY,EAAG;AAC9B,YAAM,QAAQ,aAAa;AAC3B,UAAI,MAAM,KAAK,MAAM,IAAI;AACvB,aAAK,wGAAmB;AACxB;AAAA,MACF;AACA,iBAAW,IAAI,IAAI;AACnB,WAAK,gCAAO;AACZ,WAAK,cAAc,OAAO,KAAK,YAAY,EAAE,aAAa,EAAE;AAAA,QAC1D,CAAC,WAAW;AACV,qBAAW,IAAI,KAAK;AACpB,cAAI,CAAC,OAAO,IAAI;AACd,iBAAK,iCAAQ,OAAO,SAAS,0BAAM,EAAE;AACrC;AAAA,UACF;AACA,uBAAa,OAAO,QAAQ,EAAE;AAC9B,wBAAc;AAGd,gBAAM,OAAiB,CAAC;AACxB,cAAI,OAAO,aAAa,KAAM,MAAK,KAAK,4IAAyB;AAAA,cAC5D,MAAK,KAAK,GAAG,OAAO,OAAO,aAAa,CAAC,CAAC,qBAAM;AACrD,gBAAM,OAAO,OAAO,SAAS,UAAU;AACvC,cAAI,OAAO,EAAG,MAAK,KAAK,gBAAM,OAAO,IAAI,CAAC,SAAI;AAC9C,cAAI,OAAO,iBAAiB,SAAU,MAAK,KAAK,sCAAQ;AACxD,cAAI,OAAO,YAAY,KAAM,MAAK,KAAK,gCAAO;AAC9C,eAAK,6CAAU,OAAO,KAAK,cAAM,KAAK,KAAK,QAAK,CAAC,iCAAe;AAAA,QAClE;AAAA,QACA,CAAC,UAAmB;AAClB,qBAAW,IAAI,KAAK;AACpB,eAAK,iCAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAAA,QACvE;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS,CAAC,SAA8B;AAAE,eAAS,sBAAsB,IAAI;AAAA,IAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAO/E,eAAe,CAAC,UAAkB,SAA2B;AAC3D,iBAAW,eAAe,KAAK,YAAY,GAAG,UAAU,IAAI,CAAC;AAAA,IAC/D;AAAA,EACF;AAGA,QAAM,OAAO,oBAAoB,MAAM,MAAM,SAAS;AAAA,IACpD,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,OAAO;AAAA,IACP,QAAQ,OAAO;AAAA,MACb,OAAO,EAAE,MAAM,MAAM,YAAY,YAAY;AAAA,MAC7C,SAAS;AAAA,QACP;AAAA,QAAU;AAAA,QAAY;AAAA,QACtB,UAAU,YAAY;AAAA,QACtB,YAAY,YAAY;AAAA,QACxB,WAAW,YAAY;AAAA,QACvB,eAAe,MAAM;AAAE,sBAAY,IAAI,EAAE;AAAA,QAAE;AAAA,MAC7C;AAAA,IACF;AAAA,EACF,GAAG,eAAe,CAAC;AAGnB,QAAM,OAAO,iBAAiB,MAAM,MAAM,SAAS;AAAA,IACjD,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,QAAQ,OAAO;AAAA,MACb,OAAO,EAAE,MAAAD,OAAM,KAAK;AAAA,MACpB,SAAS;AAAA,QACP,KAAK;AAAA,QACL,OAAO,MAAM;AAAE,UAAAA,MAAK,IAAI,IAAI;AAAA,QAAE;AAAA,QAC9B,MAAM,CAAC,YAAgC;AACrC,gBAAM,UAAUA,MAAK,YAAY;AACjC,cAAI,YAAY,KAAM;AACtB,UAAAA,MAAK,IAAI,EAAE,GAAG,SAAS,MAAM,QAAQ,CAAC;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,eAAe,CAAC;AAGnB,QAAM,OAAO,iBAAiB,MAAM,MAAM,SAAS;AAAA,IACjD,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,QAAQ,OAAO,EAAE,OAAO,EAAE,KAAK,GAAG,SAAS,EAAE,SAAS,EAAE;AAAA,EAC1D,GAAG,kBAAkB,CAAC;AAGtB,QAAM,OAAO,4BAA4B,MAAM,MAAM,SAAS;AAAA,IAC5D,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,OAAO;AAAA,IACP,QAAQ,OAAO;AAAA,MACb,OAAO,EAAE,MAAM,MAAM;AAAA,MACrB,SAAS,EAAE,QAAQ,aAAa,OAAO;AAAA,IACzC;AAAA,EACF,GAAG,mBAAmB,CAAC;AAGvB,QAAM,OAAO,iBAAiB,MAAM,MAAM,SAAS;AAAA,IACjD,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,QAAQ,OAAO;AAAA,MACb,OAAO,EAAE,MAAM,OAAO,MAAM,YAAY,QAAQ,aAAa,MAAM,WAAW;AAAA,MAC9E,SAAS;AAAA,QACP,QAAQ,aAAa;AAAA,QACrB,OAAO,aAAa;AAAA,QACpB,QAAQ,aAAa;AAAA,QACrB,UAAU,aAAa;AAAA,QACvB,SAAS,aAAa;AAAA,QACtB,eAAe,aAAa;AAAA,QAC5B,aAAa,YAAY;AAAA,QACzB,gBAAgB,YAAY;AAAA,QAC5B,gBAAgB,YAAY;AAAA,QAC5B,cAAc,YAAY;AAAA,QAC1B,WAAW,YAAY;AAAA,QACvB,YAAY,YAAY;AAAA,QACxB,YAAY,YAAY;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,GAAG,kBAAkB,CAAC;AAGtB,MAAI,OAAO,MAAM,yBAAyB,GAAG,kCAAkC;AAG/E,MAAI,OAAO,MAAM,wBAAwB,GAAG,iCAAiC;AAI7E,MAAI,OAAO,MAAM,wBAAwB,GAAG,iCAAiC;AAK7E,MAAI,OAAO,MAAM;AACf,QAAI,UAA+B;AACnC,UAAM,mBAAmB,MAAY;AACnC,YAAM,WAAW,KAAK,YAAY;AAClC,YAAM,WAAW,eAAe,QAAQ;AACxC,YAAM,SAAS,SAAS,QAAQ,SAAS,QAAQ,SAAS;AAC1D,UAAI,UAAU,YAAY,MAAM;AAC9B,kBAAU,oBAAoB;AAAA,UAC5B,UAAU,MAAM,KAAK,YAAY;AAAA;AAAA;AAAA;AAAA,UAIjC,gBAAgB,MAAO,eAAe,KAAK,YAAY,CAAC,EAAE,QACtD,mBAAmB,KAAK,YAAY,GAAG,oBAAoB,CAAC,IAC5D,CAAC;AAAA,UACL,SAAS,CAAAE,WAAS;AAAE,YAAAF,MAAK,IAAIE,MAAK;AAAA,UAAE;AAAA,UACpC,UAAU,MAAMF,MAAK,YAAY,MAAM;AAAA,QACzC,CAAC;AAAA,MACH,WAAW,CAAC,QAAQ;AAClB,kBAAU;AACV,kBAAU;AAAA,MACZ;AAEA,UAAI,SAAS,aAAa,YAAY,CAAC,SAAS,KAAM,CAAAA,MAAK,IAAI,IAAI;AAGnE,UAAI,CAAC,SAAS,MAAO,OAAM,IAAI,IAAI;AAAA,IACrC;AACA,qBAAiB;AACjB,UAAM,cAAc,KAAK,UAAU,gBAAgB;AACnD,WAAO,MAAM;AACX,kBAAY;AACZ,gBAAU;AACV,gBAAU;AAAA,IACZ;AAAA,EACF,GAAG,iCAAiC;AACtC;",
6
6
  "names": ["row", "row", "name", "row", "row", "name", "base", "row", "text", "React", "import_react", "import_jsx_runtime", "active", "import_react", "import_react", "import_jsx_runtime", "import_jsx_runtime", "import_jsx_runtime", "import_jsx_runtime", "import_jsx_runtime", "base", "import_react", "import_jsx_runtime", "state", "import_react", "import_jsx_runtime", "active", "menu", "name", "state"]
7
7
  }