sqs-dsh-better-input 0.1.0
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/LICENSE +27 -0
- package/README.md +218 -0
- package/assets/banner.png +0 -0
- package/cordis.patch.yml +6 -0
- package/lib/about.d.ts +65 -0
- package/lib/client/MicrophoneButton.d.ts +64 -0
- package/lib/client/OptimizeButton.d.ts +33 -0
- package/lib/client/VoiceRecognitionBar.d.ts +14 -0
- package/lib/client/index.d.ts +14 -0
- package/lib/client/settings-controller.d.ts +80 -0
- package/lib/client/settings.d.ts +15 -0
- package/lib/client/strings.d.ts +113 -0
- package/lib/client/templates-controller.d.ts +45 -0
- package/lib/client/templates-section.d.ts +17 -0
- package/lib/client/templates-source.d.ts +16 -0
- package/lib/client/voice-session.d.ts +35 -0
- package/lib/client/web-speech.d.ts +35 -0
- package/lib/client.d.ts +1 -0
- package/lib/client.js +2925 -0
- package/lib/client.js.map +1 -0
- package/lib/config.d.ts +100 -0
- package/lib/identity-CzaR1Taa.js +18 -0
- package/lib/identity-CzaR1Taa.js.map +1 -0
- package/lib/identity.d.ts +24 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.js +920 -0
- package/lib/index.js.map +1 -0
- package/lib/polish/prompts.d.ts +37 -0
- package/lib/polish/service.d.ts +45 -0
- package/lib/remote-contract.d.ts +166 -0
- package/lib/remote.d.ts +56 -0
- package/lib/remote.js +226 -0
- package/lib/remote.js.map +1 -0
- package/lib/settings/store.d.ts +41 -0
- package/lib/templates/model.d.ts +30 -0
- package/lib/templates/store.d.ts +27 -0
- package/lib/typert.d.ts +107 -0
- package/lib/typert.js +468 -0
- package/lib/typert.js.map +1 -0
- package/package.json +116 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","names":["useSyncExternalStore","useRef","buttonStyle","useState","useRef","buttonStyle","createPortal","useSyncExternalStore","inputStyle","useState","useRef","SectionFrame","hintStyle","errorStyle","useSyncExternalStore","useState"],"sources":["../src/identity.ts","../src/remote.ts","../src/client/strings.ts","../src/config.ts","../src/client/web-speech.ts","../src/client/voice-session.ts","../src/client/MicrophoneButton.tsx","../src/client/OptimizeButton.tsx","../src/client/VoiceRecognitionBar.tsx","../src/client/settings-controller.ts","../src/client/settings.tsx","../src/client/templates-source.ts","../src/client/templates-controller.ts","../src/templates/model.ts","../src/client/templates-section.tsx","../src/client/index.ts"],"sourcesContent":["/**\n * Single source of truth for this package's identity.\n *\n * Every externally visible name (the Typert package key, the npm package name\n * used by the update check, the settings namespace) derives from here so a\n * rename never leaves a stale literal behind.\n */\n\n/** Stable identifier for this fork. Used as the Typert package key. */\nexport const PACKAGE_NAME = 'sqs-dsh-better-input'\n\n/** Author of this secondary development. */\nexport const AUTHOR = 'sanqianshuang'\n\n/** Repository for this fork. */\nexport const REPOSITORY_URL = 'https://github.com/sanqianshuang/sqs-dsh-better-input'\n\n/** npm scope owner; only used to build the fallback slug when a URL is unparseable. */\nexport const NPM_SCOPE = 'sanqianshuang'\n\n/** License inherited from the upstream MIT project. */\nexport const LICENSE = 'MIT'\n\n/**\n * Upstream attribution. This is a secondary development of the MIT-licensed\n * `dsh-better-input` project; the original copyright notice and license text\n * are retained in LICENSE as the MIT terms require.\n */\nexport const UPSTREAM_NAME = 'dsh-better-input'\nexport const UPSTREAM_URL = 'https://github.com/DIAG5/dsh-better-input'\n","import type { RemoteResult, TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol'\nimport type { ClientRemote } from '@deepseek-ai/dsh-api-remotes/client'\nimport type { AboutInfoWire, BetterInputSettingsPatch, BetterInputSettingsView, PolishRoute, ReasoningEffortInfo, TemplateInputWire, TemplateWire, UpdateCheckResultWire } from './remote-contract.js'\nimport { PACKAGE_NAME } from './identity.js'\n\nexport type BetterInputRemote = ClientRemote['betterInput']\n\ndeclare module '@deepseek-ai/dsh-typert-protocol' {\n interface TypertRemoteNamespace$betterInput {\n getSettings: () => Promise<RemoteResult<BetterInputSettingsView>>\n updateSettings: (patch: BetterInputSettingsPatch, signal?: AbortSignal) => Promise<RemoteResult<BetterInputSettingsView>>\n listRoutes: () => Promise<RemoteResult<PolishRoute[]>>\n resolveModelEfforts: (provider: string, model: string) => Promise<RemoteResult<{ efforts: readonly ReasoningEffortInfo[]; defaultEffort?: string }>>\n getAbout: () => Promise<RemoteResult<AboutInfoWire>>\n checkForUpdate: (signal?: AbortSignal) => Promise<RemoteResult<UpdateCheckResultWire>>\n polish: (transcript: string, provider: string, model: string, signal?: AbortSignal) => Promise<RemoteResult<string>>\n optimize: (text: string, provider: string, model: string, context: string, signal?: AbortSignal) => Promise<RemoteResult<string>>\n templatesList: () => Promise<RemoteResult<{ templates: TemplateWire[] }>>\n templatesSave: (template: TemplateInputWire, signal?: AbortSignal) => Promise<RemoteResult<{ template: TemplateWire }>>\n templatesRemove: (id: string, signal?: AbortSignal) => Promise<RemoteResult<{ removed: boolean }>>\n }\n\n interface TypertRemoteMap {\n 'betterInput/getSettings': () => Promise<RemoteResult<BetterInputSettingsView>>\n 'betterInput/updateSettings': (patch: BetterInputSettingsPatch, signal?: AbortSignal) => Promise<RemoteResult<BetterInputSettingsView>>\n 'betterInput/listRoutes': () => Promise<RemoteResult<PolishRoute[]>>\n 'betterInput/resolveModelEfforts': (provider: string, model: string) => Promise<RemoteResult<{ efforts: readonly ReasoningEffortInfo[]; defaultEffort?: string }>>\n 'betterInput/getAbout': () => Promise<RemoteResult<AboutInfoWire>>\n 'betterInput/checkForUpdate': (signal?: AbortSignal) => Promise<RemoteResult<UpdateCheckResultWire>>\n 'betterInput/polish': (transcript: string, provider: string, model: string, signal?: AbortSignal) => Promise<RemoteResult<string>>\n 'betterInput/optimize': (text: string, provider: string, model: string, context: string, signal?: AbortSignal) => Promise<RemoteResult<string>>\n 'betterInput/templatesList': () => Promise<RemoteResult<{ templates: TemplateWire[] }>>\n 'betterInput/templatesSave': (template: TemplateInputWire, signal?: AbortSignal) => Promise<RemoteResult<{ template: TemplateWire }>>\n 'betterInput/templatesRemove': (id: string, signal?: AbortSignal) => Promise<RemoteResult<{ removed: boolean }>>\n }\n\n interface TypertRemoteNamespaceMap {\n betterInput: TypertRemoteNamespace$betterInput\n }\n}\n\n/**\n * Build one strict codec for the CLIENT face.\n *\n * The client face exists only to describe the wire shape to\n * `ctx.remote.$mount`; the actual byte validation happens on the Host. This is\n * not an assumption — it is how dsh 0.1.7 is wired:\n *\n * - `@deepseek-ai/dsh-api-gateway/lib/index.js` (Host) is the ONLY place that\n * runs `codec.create().parse(value)`. Validation lives in `decode()`.\n * - `…/lib/client.js` contains ZERO `.create()` calls. Its `$mount` path only\n * calls `requireStrictCodecs`, which inspects `codec.mode === 'strict'` and\n * never reads `typeSymbol` or invokes the factory. `prepareInvocation()`\n * forwards raw argument values straight to the RPC carrier.\n *\n * So materializing a real schema in the browser is pure dead weight: it pulls\n * all of zod (~280 KB) into `lib/client.js` for a factory that is never called.\n * The `create()` here is therefore lazy AND schema-free — it never imports zod.\n *\n * The eager `import { …Schema } from './remote-contract.js'` that used to sit\n * at the top of this file was the single value-reachability edge that dragged\n * zod into the browser bundle, because `src/client/index.ts` needs\n * `TYPERT_REMOTE` as a value.\n *\n * The placeholder satisfies `TypertSchema` ({ parse(value) }) structurally, so\n * the client face still typechecks. It is unreachable at runtime; if a future\n * dsh ever validates on the client, `parse` throws loudly instead of silently\n * accepting bad bytes. The Host manifest in `typert.ts` keeps the real zod\n * schemas.\n */\nfunction codec(typeSymbol: string) {\n return {\n mode: 'strict' as const,\n typeSymbol,\n create: () => ({\n parse(value: unknown): unknown {\n throw new Error(\n `sqs-dsh-better-input: client-face codec ${typeSymbol} was materialized. ` +\n 'The client must never validate wire bytes (the Host does). ' +\n 'If this fires, the client-face descriptor is being used for validation it should not own.'\n )\n }\n })\n }\n}\n\n/** Type symbol for one of this plugin's own wire types. */\nconst symbol = (name: string): string => `${PACKAGE_NAME}#${name}`\n\n/** The client-face Typert manifest; mirrors the Host face in `typert.ts`. */\nexport const TYPERT_REMOTE: TypertRemoteContribution = {\n package: PACKAGE_NAME,\n descriptors: [\n {\n id: `${PACKAGE_NAME}#betterInput/getSettings`,\n service: 'BetterInputPolish',\n namespace: 'betterInput',\n method: 'getSettings',\n invocation: { kind: 'direct' },\n parameters: [],\n result: codec(symbol('BetterInputSettingsView'))\n },\n {\n id: `${PACKAGE_NAME}#betterInput/updateSettings`,\n service: 'BetterInputPolish',\n namespace: 'betterInput',\n method: 'updateSettings',\n invocation: { kind: 'direct' },\n parameters: [{\n name: 'patch',\n wire: 'patch',\n source: 'json',\n codec: codec(symbol('BetterInputSettingsPatch'))\n }],\n cancellation: { parameter: 'signal' },\n result: codec(symbol('BetterInputSettingsView'))\n },\n {\n id: `${PACKAGE_NAME}#betterInput/listRoutes`,\n service: 'BetterInputPolish',\n namespace: 'betterInput',\n method: 'listRoutes',\n invocation: { kind: 'direct' },\n parameters: [],\n result: codec(symbol('PolishRoute[]'))\n },\n {\n id: `${PACKAGE_NAME}#betterInput/resolveModelEfforts`,\n service: 'BetterInputPolish',\n namespace: 'betterInput',\n method: 'resolveModelEfforts',\n invocation: { kind: 'direct' },\n parameters: [\n { name: 'provider', wire: 'provider', source: 'json', codec: codec('string') },\n { name: 'model', wire: 'model', source: 'json', codec: codec('string') }\n ],\n result: codec(symbol('ResolveModelEffortsResult'))\n },\n {\n id: `${PACKAGE_NAME}#betterInput/getAbout`,\n service: 'BetterInputPolish',\n namespace: 'betterInput',\n method: 'getAbout',\n invocation: { kind: 'direct' },\n parameters: [],\n result: codec(symbol('AboutInfo'))\n },\n {\n id: `${PACKAGE_NAME}#betterInput/checkForUpdate`,\n service: 'BetterInputPolish',\n namespace: 'betterInput',\n method: 'checkForUpdate',\n invocation: { kind: 'direct' },\n parameters: [],\n cancellation: { parameter: 'signal' },\n result: codec(symbol('UpdateCheckResult'))\n },\n {\n id: `${PACKAGE_NAME}#betterInput/polish`,\n service: 'BetterInputPolish',\n namespace: 'betterInput',\n method: 'polish',\n invocation: { kind: 'direct' },\n parameters: [\n { name: 'transcript', wire: 'transcript', source: 'json', codec: codec('string') },\n { name: 'provider', wire: 'provider', source: 'json', codec: codec('string') },\n { name: 'model', wire: 'model', source: 'json', codec: codec('string') }\n ],\n cancellation: { parameter: 'signal' },\n result: codec('string')\n },\n {\n id: `${PACKAGE_NAME}#betterInput/optimize`,\n service: 'BetterInputPolish',\n namespace: 'betterInput',\n method: 'optimize',\n invocation: { kind: 'direct' },\n parameters: [\n { name: 'text', wire: 'text', source: 'json', codec: codec('string') },\n { name: 'provider', wire: 'provider', source: 'json', codec: codec('string') },\n { name: 'model', wire: 'model', source: 'json', codec: codec('string') },\n { name: 'context', wire: 'context', source: 'json', codec: codec('string') }\n ],\n cancellation: { parameter: 'signal' },\n result: codec('string')\n },\n {\n id: `${PACKAGE_NAME}#betterInput/templatesList`,\n service: 'BetterInputPolish',\n namespace: 'betterInput',\n method: 'templatesList',\n invocation: { kind: 'direct' },\n parameters: [],\n result: codec(symbol('TemplateListResult'))\n },\n {\n id: `${PACKAGE_NAME}#betterInput/templatesSave`,\n service: 'BetterInputPolish',\n namespace: 'betterInput',\n method: 'templatesSave',\n invocation: { kind: 'direct' },\n parameters: [{\n name: 'template',\n wire: 'template',\n source: 'json',\n codec: codec(symbol('TemplateInput'))\n }],\n cancellation: { parameter: 'signal' },\n result: codec(symbol('TemplateSaveResult'))\n },\n {\n id: `${PACKAGE_NAME}#betterInput/templatesRemove`,\n service: 'BetterInputPolish',\n namespace: 'betterInput',\n method: 'templatesRemove',\n invocation: { kind: 'direct' },\n parameters: [{ name: 'id', wire: 'id', source: 'json', codec: codec('string') }],\n cancellation: { parameter: 'signal' },\n result: codec(symbol('TemplateRemoveResult'))\n }\n ]\n}\n\nexport default TYPERT_REMOTE\n","/**\n * Bilingual UI strings for sqs-dsh-better-input (zh/en). Registered as one\n * namespace into the DSH locale runtime; every slot component declares that\n * namespace and reads copy through the framework-injected `t` seat, so the\n * UI follows the DSH settings language switch automatically.\n */\nexport type BetterInputStrings = {\n voiceStart: string\n voiceStop: string\n voiceBusy: string\n voiceUnavailable: string\n listening: string\n transcribing: string\n polishing: string\n voiceFailed: string\n polishNotConfigured: string\n polishFailedKeepOriginal: string\n settingsTitle: string\n settingsDescription: string\n loading: string\n saveFailed: string\n languageLabel: string\n languageHint: string\n languagePlaceholder: string\n recordingLimitLabel: string\n recordingLimitHint: string\n polishLabel: string\n polishHint: string\n on: string\n off: string\n polishModelLabel: string\n polishModelHint: string\n polishModelNone: string\n polishEffortLabel: string\n polishEffortHint: string\n polishPromptLabel: string\n polishPromptHint: string\n polishPromptPlaceholder: string\n showDefaultPrompt: string\n hideDefaultPrompt: string\n defaultPromptLabel: string\n effortDefaultLabel: string\n effortLoadingLabel: string\n routesStatus: string\n routesUnavailable: string\n optimizeButton: string\n optimizeBusy: string\n optimizeFailed: string\n optimizeEmpty: string\n optimizePanelTitle: string\n optimizeOriginalLabel: string\n optimizeOptimizedLabel: string\n optimizeAdopt: string\n optimizeCancel: string\n optimizeNotConfigured: string\n optimizeSectionLabel: string\n optimizeModelLabel: string\n optimizeModelHint: string\n optimizeEffortLabel: string\n optimizeEffortHint: string\n optimizePromptLabel: string\n optimizePromptHint: string\n optimizePromptPlaceholder: string\n contextTurnsLabel: string\n contextTurnsHint: string\n aboutTitle: string\n aboutVersionLabel: string\n aboutRepositoryLabel: string\n aboutChangelogLabel: string\n aboutLicenseLabel: string\n checkUpdateButton: string\n checkingUpdate: string\n updateUpToDate: string\n updateAvailable: string\n updateUnpublished: string\n updateCheckFailed: string\n updateCommandLabel: string\n updateCommandNpxLabel: string\n updateCommandPick: string\n voiceSectionLabel: string\n polishSectionLabel: string\n templatesTitle: string\n templatesDescription: string\n templatesNew: string\n templatesEdit: string\n templatesSave: string\n templatesCancel: string\n templatesDelete: string\n templatesDeleteConfirm: string\n templatesEmpty: string\n templatesLoadFailed: string\n templatesRetry: string\n templatesActionFailed: string\n templatesNameLabel: string\n templatesNamePlaceholder: string\n templatesDescriptionLabel: string\n templatesDescriptionPlaceholder: string\n templatesContentLabel: string\n templatesContentPlaceholder: string\n templatesTagsLabel: string\n templatesTagsHint: string\n}\n\nexport const zh: BetterInputStrings = {\n voiceStart: '语音输入',\n voiceStop: '停止语音输入',\n voiceBusy: '正在处理…',\n voiceUnavailable: '此浏览器不支持语音识别',\n listening: '正在聆听…',\n transcribing: '正在转写…',\n polishing: '正在润色…',\n voiceFailed: '语音输入失败',\n polishNotConfigured: '未配置润色模型,请在设置页选择',\n polishFailedKeepOriginal: '润色失败,已保留原文',\n settingsTitle: 'BetterInput 设置',\n settingsDescription: '配置语音识别与 AI 润色。润色复用你在 dsh 设置里已配置的模型,无需额外 API key。',\n loading: '加载中…',\n saveFailed: '保存失败,请重试',\n languageLabel: '识别语言',\n languageHint: '留空时跟随浏览器语言。',\n languagePlaceholder: '例如 zh-CN 或 en-US',\n recordingLimitLabel: '单次录音上限(秒)',\n recordingLimitHint: '1–600 秒。',\n polishLabel: 'AI 润色',\n polishHint: '识别完成后用大模型清理转写文本(去口头禅、修正同音错字、加标点)。',\n on: '开',\n off: '关',\n polishModelLabel: '润色模型',\n polishModelHint: '选择 dsh 中已配置的模型路由。',\n polishModelNone: '(未选择)',\n polishEffortLabel: '润色思考强度',\n polishEffortHint: '控制大模型的推理深度。默认即适配器最低档,适合大多数场景。',\n polishPromptLabel: '自定义润色提示词',\n polishPromptHint: '留空使用内置提示词。自定义提示词总是追加输出契约保护。',\n polishPromptPlaceholder: '可选:粘贴自定义提示词…',\n showDefaultPrompt: '查看内置提示词',\n hideDefaultPrompt: '收起内置提示词',\n defaultPromptLabel: '内置提示词',\n effortDefaultLabel: '默认(关闭思考)',\n effortLoadingLabel: '加载思考强度选项…',\n routesStatus: '可用模型路由',\n routesUnavailable: '不可用',\n optimizeButton: '优化提示词',\n optimizeBusy: '优化中…',\n optimizeFailed: '优化失败,请重试',\n optimizeEmpty: '输入框为空,无需优化',\n optimizePanelTitle: '提示词优化结果',\n optimizeOriginalLabel: '原文',\n optimizeOptimizedLabel: '优化后',\n optimizeAdopt: '采纳',\n optimizeCancel: '取消',\n optimizeNotConfigured: '未配置优化模型,请在设置页开启',\n optimizeSectionLabel: '提示词优化',\n optimizeModelLabel: '优化模型',\n optimizeModelHint: '选择 dsh 中已配置的模型路由。',\n optimizeEffortLabel: '优化思考强度',\n optimizeEffortHint: '控制大模型的推理深度。默认即适配器最低档,适合大多数场景。',\n optimizePromptLabel: '自定义优化提示词',\n optimizePromptHint: '留空使用内置提示词。自定义提示词总是追加输出契约保护。',\n optimizePromptPlaceholder: '可选:粘贴自定义提示词…',\n contextTurnsLabel: '上下文引用轮数',\n contextTurnsHint: '优化时引用最近 N 轮对话作为上下文,0 为禁用。默认 3 轮。',\n aboutTitle: '关于与更新',\n aboutVersionLabel: '当前版本',\n aboutRepositoryLabel: '项目地址',\n aboutChangelogLabel: '更新日志',\n aboutLicenseLabel: '许可证',\n checkUpdateButton: '检查更新',\n checkingUpdate: '检查中…',\n updateUpToDate: '当前已是最新版本。',\n updateAvailable: '发现新版本',\n updateUnpublished: '该版本未在 npm 上公开发布。',\n updateCheckFailed: '检查更新失败',\n updateCommandLabel: '已全局安装 dsh CLI,执行',\n updateCommandNpxLabel: '未全局安装,改用 npx 执行',\n updateCommandPick: '按你的安装方式二选一即可',\n voiceSectionLabel: '语音识别',\n polishSectionLabel: '提示词润色',\n templatesTitle: '提示词模板',\n templatesDescription: '把常用提示词存成模板,在输入框键入 / 即可搜索并插入。',\n templatesNew: '新建模板',\n templatesEdit: '编辑',\n templatesSave: '保存',\n templatesCancel: '取消',\n templatesDelete: '删除',\n templatesDeleteConfirm: '再次点击确认删除',\n templatesEmpty: '还没有模板,点击「新建模板」创建第一个。',\n templatesLoadFailed: '模板加载失败',\n templatesRetry: '重试',\n templatesActionFailed: '操作失败,请重试',\n templatesNameLabel: '名称',\n templatesNamePlaceholder: '例如:代码评审助手',\n templatesDescriptionLabel: '描述',\n templatesDescriptionPlaceholder: '可选:这个模板用来做什么',\n templatesContentLabel: '内容',\n templatesContentPlaceholder: '插入输入框的提示词正文…',\n templatesTagsLabel: '标签',\n templatesTagsHint: '逗号分隔,最多 8 个,用于菜单搜索。'\n}\n\nexport const en: BetterInputStrings = {\n voiceStart: 'Voice input',\n voiceStop: 'Stop voice input',\n voiceBusy: 'Processing…',\n voiceUnavailable: 'Speech recognition is not supported in this browser',\n listening: 'Listening…',\n transcribing: 'Transcribing…',\n polishing: 'Polishing…',\n voiceFailed: 'Voice input failed',\n polishNotConfigured: 'No polish model configured, please choose one in Settings',\n polishFailedKeepOriginal: 'Polishing failed, original kept',\n settingsTitle: 'BetterInput Settings',\n settingsDescription: 'Configure voice recognition and AI polishing. Polishing reuses the models already configured in dsh — no extra API key needed.',\n loading: 'Loading…',\n saveFailed: 'Failed to save, please retry',\n languageLabel: 'Recognition language',\n languageHint: 'Empty follows the browser language.',\n languagePlaceholder: 'e.g. zh-CN or en-US',\n recordingLimitLabel: 'Recording limit (seconds)',\n recordingLimitHint: '1–600 seconds.',\n polishLabel: 'AI polishing',\n polishHint: 'Clean the transcript with an LLM after recognition (fillers, homophone fixes, punctuation).',\n on: 'On',\n off: 'Off',\n polishModelLabel: 'Polish model',\n polishModelHint: 'Pick a model route already configured in dsh.',\n polishModelNone: '(none)',\n polishEffortLabel: 'Polishing thinking effort',\n polishEffortHint: 'Controls the model inference depth. Default uses the adapter baseline (lightest tier).',\n polishPromptLabel: 'Custom polish prompt',\n polishPromptHint: 'Empty uses the built-in prompt. A custom prompt always keeps the output-contract guard.',\n polishPromptPlaceholder: 'Optional: paste a custom prompt…',\n showDefaultPrompt: 'Show the built-in prompt',\n hideDefaultPrompt: 'Hide the built-in prompt',\n defaultPromptLabel: 'Built-in prompt',\n effortDefaultLabel: 'Default (thinking off)',\n effortLoadingLabel: 'Loading reasoning effort options…',\n routesStatus: 'Available model routes',\n routesUnavailable: 'unavailable',\n optimizeButton: 'Optimize prompt',\n optimizeBusy: 'Optimizing…',\n optimizeFailed: 'Optimization failed, please retry',\n optimizeEmpty: 'Input is empty, nothing to optimize',\n optimizePanelTitle: 'Prompt optimization result',\n optimizeOriginalLabel: 'Original',\n optimizeOptimizedLabel: 'Optimized',\n optimizeAdopt: 'Adopt',\n optimizeCancel: 'Cancel',\n optimizeNotConfigured: 'No optimize model configured, enable it in Settings',\n optimizeSectionLabel: 'Prompt optimization',\n optimizeModelLabel: 'Optimize model',\n optimizeModelHint: 'Pick a model route already configured in dsh.',\n optimizeEffortLabel: 'Optimize thinking effort',\n optimizeEffortHint: 'Controls the model inference depth. Default uses the adapter baseline (lightest tier).',\n optimizePromptLabel: 'Custom optimize prompt',\n optimizePromptHint: 'Empty uses the built-in prompt. A custom prompt always keeps the output-contract guard.',\n optimizePromptPlaceholder: 'Optional: paste a custom prompt…',\n contextTurnsLabel: 'Context turns',\n contextTurnsHint: 'Include recent N turns as context for optimization. 0 = disabled. Default 3.',\n aboutTitle: 'About & Updates',\n aboutVersionLabel: 'Installed version',\n aboutRepositoryLabel: 'Repository',\n aboutChangelogLabel: 'Changelog',\n aboutLicenseLabel: 'License',\n checkUpdateButton: 'Check for updates',\n checkingUpdate: 'Checking…',\n updateUpToDate: 'You are up to date.',\n updateAvailable: 'A new version is available',\n updateUnpublished: 'This version is not published on npm.',\n updateCheckFailed: 'Update check failed',\n updateCommandLabel: 'With a global dsh CLI, run',\n updateCommandNpxLabel: 'Without a global dsh CLI, run via npx',\n updateCommandPick: 'Use either one depending on how you installed DSH',\n voiceSectionLabel: 'Voice Recognition',\n polishSectionLabel: 'Prompt Polishing',\n templatesTitle: 'Prompt Templates',\n templatesDescription: 'Save frequently used prompts as templates, then type / in the input box to search and insert.',\n templatesNew: 'New template',\n templatesEdit: 'Edit',\n templatesSave: 'Save',\n templatesCancel: 'Cancel',\n templatesDelete: 'Delete',\n templatesDeleteConfirm: 'Click again to confirm',\n templatesEmpty: 'No templates yet. Create your first one with \"New template\".',\n templatesLoadFailed: 'Failed to load templates',\n templatesRetry: 'Retry',\n templatesActionFailed: 'Action failed, please retry',\n templatesNameLabel: 'Name',\n templatesNamePlaceholder: 'e.g. Code review assistant',\n templatesDescriptionLabel: 'Description',\n templatesDescriptionPlaceholder: 'Optional: what this template is for',\n templatesContentLabel: 'Content',\n templatesContentPlaceholder: 'Prompt body inserted into the input box…',\n templatesTagsLabel: 'Tags',\n templatesTagsHint: 'Comma separated, up to 8, used for menu search.'\n}\n\n/** Namespace owning every BetterInput surface string. Registered into the DSH\n * locale runtime; slots declaring this namespace receive the typed `t`. */\nexport const BETTER_INPUT_NS = 'better-input'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n /** BetterInput dictionary keys (one shared key set, zh/en bilingual). */\n interface LocaleNamespaceMap {\n 'better-input': keyof BetterInputStrings\n }\n}\n","/**\n * Shared constants and browser-side helpers for sqs-dsh-better-input.\n * Voice input through the browser Web Speech API, plus Host-side\n * AI polishing of transcripts and prompt optimization.\n */\n\nexport const SETTINGS_NAMESPACE = 'sqs-dsh-better-input'\n\n/** Recording is capped to avoid an abandoned session holding the mic forever. */\nexport const DEFAULT_MAX_RECORDING_SECONDS = 120\n\nexport const MAX_POLISH_PROMPT_LENGTH = 4000\nexport const MAX_OPTIMIZE_PROMPT_LENGTH = 4000\nexport const MAX_TRANSCRIPT_CHARACTERS = 12_000\nexport const MAX_OPTIMIZE_CHARACTERS = 12_000\nexport const MAX_POLISHED_CHARACTERS = 24_000\nexport const MAX_OPTIMIZED_CHARACTERS = 24_000\nexport const POLISH_TIMEOUT_MS = 20_000\nexport const OPTIMIZE_TIMEOUT_MS = 20_000\n\nexport interface BetterInputSettings {\n /** Recognition language, empty follows the dsh UI locale. */\n language: string\n /** Recording limit in seconds. */\n maxRecordingSeconds: number\n /** Enable Host LLM polishing after the transcript lands in the draft. */\n polishingEnabled: boolean\n /** dsh polish provider id (a route already registered in dsh). */\n polishProvider: string\n /** dsh polish model id. */\n polishModel: string\n /** Selected reasoning effort id for polish, empty uses the adapter's default (usually the lightest). */\n polishReasoningEffort: string\n /** Custom polish system prompt, empty for the built-in one. */\n polishPrompt: string\n /** Enable prompt optimization through the Host LLM. */\n optimizeEnabled: boolean\n /** dsh optimize provider id (reuses the same route pool as polish). */\n optimizeProvider: string\n /** dsh optimize model id. */\n optimizeModel: string\n /** Selected reasoning effort id for optimize, empty uses the adapter's default (usually the lightest). */\n optimizeReasoningEffort: string\n /** Custom optimize system prompt, empty for the built-in one. */\n optimizePrompt: string\n /** Number of recent conversation turns to include as context for optimization. 0 disables context. */\n contextTurns: number\n}\n\n/**\n * Out-of-the-box defaults: every toggle ON so new users get the full\n * experience immediately; reasoning effort left empty, which the Host\n * translates to \"thinking off\" (the model's `off` tier when it exposes\n * one, otherwise the adapter's own default).\n * Provider/model stay empty and get auto-filled on first settings page\n * load via SettingsController (first route returned by listRoutes).\n */\nexport const DEFAULT_SETTINGS: BetterInputSettings = Object.freeze({\n language: '',\n maxRecordingSeconds: DEFAULT_MAX_RECORDING_SECONDS,\n polishingEnabled: true,\n polishProvider: '',\n polishModel: '',\n polishReasoningEffort: '',\n polishPrompt: '',\n optimizeEnabled: true,\n optimizeProvider: '',\n optimizeModel: '',\n optimizeReasoningEffort: '',\n optimizePrompt: '',\n contextTurns: 3,\n})\n\nexport type BetterInputSettingsPatch = Partial<BetterInputSettings>\n\n/** One selectable reasoning effort tier for a specific model route. */\nexport interface ReasoningEffortInfo {\n /** Stable id passed to `LlmCallConfig.reasoningEffort`. */\n readonly id: string\n /** Display name shown in the settings dropdown. */\n readonly name: string\n /** Optional longer description shown in a tooltip. */\n readonly description?: string\n}\n\n/** A usable (provider, model) pair returned by dsh's LLM runtime, plus any\n * reasoning-effort tiers the model reports as selectable. The efforts\n * list is empty when the adapter / model does not expose thinking\n * controls — in that case the settings dropdown is hidden entirely.\n * `defaultEffort` is the adapter-configured baseline (generally the\n * lightest tier); we use it as the placeholder label in the UI and as\n * the fallback when the stored effort string is empty.\n */\nexport interface PolishRoute {\n readonly provider: string\n readonly providerName: string\n readonly model: string\n readonly modelName: string\n readonly reasoningEfforts: readonly ReasoningEffortInfo[]\n readonly defaultReasoningEffort?: string\n}\n\nexport interface BetterInputSettingsView {\n available: boolean\n writable: boolean\n settings: BetterInputSettings\n overridden: string[]\n /** The built-in polish system prompt, shown in the settings page. */\n defaultPolishPrompt: string\n /** The built-in optimize system prompt, shown in the settings page. */\n defaultOptimizePrompt: string\n}\n\n/**\n * Recognition language derived from the browser locale. An empty stored\n * language follows the UI.\n */\nexport function recognitionLanguageFromBrowser(): string {\n if (typeof navigator === 'undefined') return 'en-US'\n const lang = (navigator.language ?? '').toLowerCase()\n return lang.startsWith('zh') ? 'zh-CN' : 'en-US'\n}\n\nexport function effectiveRecognitionLanguage(stored: string): string {\n const value = stored.trim()\n return value === '' ? recognitionLanguageFromBrowser() : value\n}\n\nexport function isValidRecordingLimit(value: number): boolean {\n return Number.isSafeInteger(value) && value >= 1 && value <= 600\n}\n\nexport function isValidContextTurns(value: number): boolean {\n return Number.isSafeInteger(value) && value >= 0 && value <= 20\n}\n\nexport function validateSettings(settings: BetterInputSettings): void {\n if (!isValidRecordingLimit(settings.maxRecordingSeconds)) {\n throw new Error('sqs-dsh-better-input recording limit must be between 1 and 600 seconds')\n }\n if (!isValidContextTurns(settings.contextTurns)) {\n throw new Error('sqs-dsh-better-input context turns must be between 0 and 20')\n }\n if (settings.polishPrompt.trim().length > MAX_POLISH_PROMPT_LENGTH) {\n throw new Error('sqs-dsh-better-input polish prompt is too long')\n }\n if (settings.optimizePrompt.trim().length > MAX_OPTIMIZE_PROMPT_LENGTH) {\n throw new Error('sqs-dsh-better-input optimize prompt is too long')\n }\n}\n\n/** Resolve the effective recording cap from stored settings. */\nexport function effectiveRecordingSeconds(settings: Pick<BetterInputSettings, 'maxRecordingSeconds'>): number {\n return isValidRecordingLimit(settings.maxRecordingSeconds) ? settings.maxRecordingSeconds : DEFAULT_MAX_RECORDING_SECONDS\n}\n","/**\n * Browser Web Speech recognition session, written from scratch for\n * sqs-dsh-better-input. Wraps SpeechRecognition / webkitSpeechRecognition with a\n * small structural interface so no DOM lib augmentation is required.\n */\n\nexport type WebSpeechState = 'starting' | 'recording' | 'stopped' | 'error'\n\ntype SpeechRecognitionAlternativeLike = {\n readonly transcript: string\n}\n\ntype SpeechRecognitionResultLike = {\n readonly isFinal: boolean\n readonly length: number\n [index: number]: SpeechRecognitionAlternativeLike\n}\n\ntype SpeechRecognitionResultListLike = {\n readonly length: number\n [index: number]: SpeechRecognitionResultLike\n}\n\ntype SpeechRecognitionEventLike = Event & {\n readonly resultIndex: number\n readonly results: SpeechRecognitionResultListLike\n}\n\ntype SpeechRecognitionErrorEventLike = Event & {\n readonly error?: string\n readonly message?: string\n}\n\ntype SpeechRecognitionLike = {\n lang: string\n continuous: boolean\n interimResults: boolean\n maxAlternatives: number\n onstart: (() => void) | null\n onresult: ((event: SpeechRecognitionEventLike) => void) | null\n onerror: ((event: SpeechRecognitionErrorEventLike) => void) | null\n onend: (() => void) | null\n start(): void\n stop(): void\n abort(): void\n}\n\ntype SpeechRecognitionConstructor = new () => SpeechRecognitionLike\n\ntype SpeechRecognitionWindow = Window & {\n SpeechRecognition?: SpeechRecognitionConstructor\n webkitSpeechRecognition?: SpeechRecognitionConstructor\n}\n\nexport type WebSpeechSessionOptions = {\n language: string\n onStart?: () => void\n onInterim: (text: string) => void\n onFinal: (text: string) => void\n onError: (error: Error) => void\n onEnd: (text: string) => void\n}\n\nexport function isWebSpeechAvailable(): boolean {\n return getSpeechRecognitionConstructor() !== undefined\n}\n\nexport class WebSpeechSession {\n private readonly recognition: SpeechRecognitionLike\n private readonly options: WebSpeechSessionOptions\n private active = false\n private stopping = false\n private finalText = ''\n private lastHeard = ''\n private ended = false\n private silent = false\n\n constructor(options: WebSpeechSessionOptions) {\n const Recognition = getSpeechRecognitionConstructor()\n if (Recognition === undefined) {\n throw new Error('Speech recognition is unavailable in this browser')\n }\n\n this.options = options\n this.recognition = new Recognition()\n this.recognition.lang = options.language\n this.recognition.continuous = true\n this.recognition.interimResults = true\n this.recognition.maxAlternatives = 1\n this.recognition.onstart = () => options.onStart?.()\n this.recognition.onresult = (event) => this.handleResult(event)\n this.recognition.onerror = (event) => this.handleError(event)\n this.recognition.onend = () => this.handleEnd()\n }\n\n start(): void {\n if (this.active || this.ended || this.silent) return\n this.active = true\n this.stopping = false\n try {\n this.recognition.start()\n } catch (error) {\n this.fail(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n stop(): void {\n if (!this.active || this.ended || this.silent) return\n this.stopping = true\n this.active = false\n try {\n this.recognition.stop()\n } catch {\n this.endOnce()\n }\n }\n\n abort(): void {\n if (this.ended || this.silent) return\n this.silent = true\n this.stopping = true\n this.active = false\n this.recognition.onstart = null\n this.recognition.onresult = null\n this.recognition.onerror = null\n this.recognition.onend = null\n try {\n this.recognition.abort()\n } catch {\n // The browser may report an invalid state when recognition already ended.\n }\n this.ended = true\n }\n\n private handleResult(event: SpeechRecognitionEventLike): void {\n if (this.silent || this.ended) return\n let finalChunk = ''\n let interimChunk = ''\n\n for (let index = event.resultIndex; index < event.results.length; index += 1) {\n const result = event.results[index]\n const transcript = result?.[0]?.transcript ?? ''\n if (result?.isFinal === true) {\n finalChunk = appendSpeech(finalChunk, transcript)\n } else {\n interimChunk = appendSpeech(interimChunk, transcript)\n }\n }\n\n if (finalChunk !== '') {\n this.finalText = appendSpeech(this.finalText, finalChunk)\n this.lastHeard = this.finalText\n this.options.onFinal(this.finalText)\n }\n\n const heard = appendSpeech(this.finalText, interimChunk)\n if (heard !== '') this.lastHeard = heard\n this.options.onInterim(heard)\n }\n\n private handleError(event: SpeechRecognitionErrorEventLike): void {\n if (this.stopping || this.silent || this.ended) return\n const code = event.error ?? 'unknown'\n const detail = event.message === undefined ? '' : `: ${event.message}`\n this.fail(new Error(`Speech recognition failed (${code})${detail}`))\n }\n\n private handleEnd(): void {\n if (this.silent || this.ended) return\n if (this.active && !this.stopping) {\n // Continuous recognition ended on its own (e.g. silence); restart it.\n try {\n this.recognition.start()\n return\n } catch (error) {\n this.fail(error instanceof Error ? error : new Error(String(error)))\n return\n }\n }\n this.endOnce()\n }\n\n private fail(error: Error): void {\n if (this.stopping || this.silent || this.ended) return\n this.active = false\n this.stopping = true\n this.options.onError(error)\n try {\n this.recognition.abort()\n } catch {\n // Error already surfaced; finish below.\n }\n this.endOnce()\n }\n\n private endOnce(): void {\n if (this.ended || this.silent) return\n this.ended = true\n this.options.onEnd(this.finalText !== '' ? this.finalText : this.lastHeard)\n }\n}\n\nexport function appendSpeech(current: string, next: string): string {\n if (next === '') return current\n if (current === '') return next\n if (/\\s$/.test(current) || /^\\s/.test(next)) return current + next\n return `${current} ${next}`\n}\n\nfunction getSpeechRecognitionConstructor(): SpeechRecognitionConstructor | undefined {\n if (typeof window === 'undefined') return undefined\n const speechWindow = window as SpeechRecognitionWindow\n return speechWindow.SpeechRecognition ?? speechWindow.webkitSpeechRecognition\n}\n","import { useSyncExternalStore } from 'react'\n\nexport type VoiceInputState = 'idle' | 'starting' | 'recording' | 'transcribing' | 'polishing' | 'error' | 'polish-error'\n\nexport type VoiceInputSessionSnapshot = {\n readonly state: VoiceInputState\n readonly detail: string\n}\n\ntype Listener = () => void\ntype StopListener = () => void\n\nconst NOTICE_STATES = new Set<VoiceInputState>(['error', 'polish-error'])\nexport const VOICE_ERROR_DISMISS_MS = 2600\n\n/**\n * Shared voice-input state for one session, written from scratch for\n * sqs-dsh-better-input. The microphone button and the recognition bar both\n * subscribe; the bar can request stop/cancel through the same instance.\n */\nexport class VoiceInputSession {\n private snapshot: VoiceInputSessionSnapshot = { state: 'idle', detail: '' }\n private readonly listeners = new Set<Listener>()\n private readonly stopListeners = new Set<StopListener>()\n private readonly cancelListeners = new Set<StopListener>()\n private epoch = 0\n private errorTimer: ReturnType<typeof setTimeout> | undefined\n\n captureEpoch(): number {\n return this.epoch\n }\n\n isCurrentEpoch(epoch: number): boolean {\n return this.epoch === epoch\n }\n\n readonly getSnapshot = (): VoiceInputSessionSnapshot => this.snapshot\n\n readonly subscribe = (listener: Listener): (() => void) => {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n readonly onStopRequested = (listener: StopListener): (() => void) => {\n this.stopListeners.add(listener)\n return () => this.stopListeners.delete(listener)\n }\n\n readonly onCancelRequested = (listener: StopListener): (() => void) => {\n this.cancelListeners.add(listener)\n return () => this.cancelListeners.delete(listener)\n }\n\n setState(state: VoiceInputState, detail = ''): void {\n const nextDetail = NOTICE_STATES.has(state) ? detail : ''\n if (this.snapshot.state === state && this.snapshot.detail === nextDetail) return\n this.clearErrorTimer()\n this.snapshot = { state, detail: nextDetail }\n this.emit()\n if (NOTICE_STATES.has(state)) {\n this.errorTimer = setTimeout(() => {\n this.errorTimer = undefined\n if (NOTICE_STATES.has(this.snapshot.state)) this.setState('idle')\n }, VOICE_ERROR_DISMISS_MS)\n }\n }\n\n requestStop(): void {\n for (const listener of this.stopListeners) listener()\n }\n\n requestCancel(): void {\n if (this.snapshot.state !== 'transcribing' && this.snapshot.state !== 'polishing') return\n this.epoch += 1\n for (const listener of this.cancelListeners) listener()\n this.setState('idle')\n }\n\n dispose(): void {\n this.clearErrorTimer()\n this.listeners.clear()\n this.stopListeners.clear()\n this.cancelListeners.clear()\n }\n\n private clearErrorTimer(): void {\n if (this.errorTimer === undefined) return\n clearTimeout(this.errorTimer)\n this.errorTimer = undefined\n }\n\n private emit(): void {\n for (const listener of this.listeners) listener()\n }\n}\n\nexport function useVoiceInputSession(session: VoiceInputSession): VoiceInputSessionSnapshot {\n return useSyncExternalStore(session.subscribe, session.getSnapshot, session.getSnapshot)\n}\n","import { useEffect, useRef } from 'react'\nimport type { SnapshotSelectorHook, TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { InputState } from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport { effectiveRecognitionLanguage, effectiveRecordingSeconds, type BetterInputSettings, type BetterInputSettingsPatch } from '../config.js'\nimport type { BetterInputRemote } from '../remote.js'\nimport { WebSpeechSession, isWebSpeechAvailable } from './web-speech.js'\nimport { useVoiceInputSession, type VoiceInputSession } from './voice-session.js'\n\n/** The framework-injected `t` seat for the BetterInput namespace. */\ntype Translate = TranslateNS<'better-input'>\n\n/**\n * Standard props the conversation input zone hands to every\n * `conversation.input.right` entry, plus the injected voice session and\n * settings controller face.\n */\nexport type InputZoneLikeProps = {\n readonly useInput: SnapshotSelectorHook<InputState>\n readonly inputActions: {\n setDraft(text: string): void\n }\n readonly voiceSession: VoiceInputSession\n readonly remote: BetterInputRemote\n readonly useSettings: () => SettingsFace\n readonly t: Translate\n}\n\nexport type SettingsFace = {\n readonly status: 'loading' | 'ready' | 'error'\n readonly settings: BetterInputSettings\n}\n\n/**\n * The microphone button in the composer tool row. Click to start listening,\n * click again to stop. Transcripts stream into the draft in real time; when\n * polishing is enabled, the committed transcript is polished through the Host\n * LLM route and replaces the draft (unless the user edited it meanwhile).\n */\nexport function MicrophoneButton({ useInput, inputActions, voiceSession, remote, useSettings, t }: InputZoneLikeProps) {\n const snapshot = useVoiceInputSession(voiceSession)\n const state = snapshot.state\n const setState = (next: typeof state, detail = '') => voiceSession.setState(next, detail)\n // The current composer draft, read through the framework's standard `useInput`\n // hook. `InputState` keeps exposing `.draft` in dsh 0.1.2.\n const input = useInput((state) => state)\n\n const speechRef = useRef<WebSpeechSession | null>(null)\n const baseDraftRef = useRef('')\n const mountedRef = useRef(true)\n const stopRef = useRef<(() => void) | null>(null)\n const polishAbortRef = useRef<AbortController | null>(null)\n const recordingTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const settingsRef = useRef<BetterInputSettings | null>(null)\n const settingsFace = useSettings()\n if (settingsFace.status === 'ready') settingsRef.current = settingsFace.settings\n\n // The latest committed draft. Updated on every input prop change so the\n // polish race check can tell whether the user edited the draft meanwhile.\n const latestDraftRef = useRef(input.draft)\n useEffect(() => {\n latestDraftRef.current = input.draft\n }, [input.draft])\n\n useEffect(() => {\n mountedRef.current = true\n const stop = voiceSession.onStopRequested(() => stopRef.current?.())\n const cancel = voiceSession.onCancelRequested(() => {\n speechRef.current?.abort()\n polishAbortRef.current?.abort()\n })\n return () => {\n mountedRef.current = false\n stop()\n cancel()\n speechRef.current?.abort()\n speechRef.current = null\n polishAbortRef.current?.abort()\n polishAbortRef.current = null\n clearRecordingTimer(recordingTimerRef)\n voiceSession.setState('idle')\n }\n }, [voiceSession])\n\n const active = state === 'starting' || state === 'recording'\n const busy = state === 'transcribing' || state === 'polishing'\n\n const settings = settingsFace.status === 'ready' ? settingsFace.settings : settingsRef.current\n const polishingEnabled = settings?.polishingEnabled ?? false\n const polishProvider = (settings?.polishProvider ?? '').trim()\n const polishModel = (settings?.polishModel ?? '').trim()\n const polishConfigured = polishingEnabled && polishProvider !== '' && polishModel !== ''\n\n const startListening = () => {\n if (active || busy) return\n const baseDraft = input.draft\n baseDraftRef.current = baseDraft\n let sessionDraft = baseDraft\n let failed = false\n setState('starting')\n\n let session: WebSpeechSession\n try {\n session = new WebSpeechSession({\n language: effectiveRecognitionLanguage(settingsRef.current?.language ?? ''),\n onInterim: (text) => {\n sessionDraft = updateDraft(baseDraft, text)\n inputActions.setDraft(sessionDraft)\n },\n onFinal: (text) => {\n sessionDraft = updateDraft(baseDraft, text)\n inputActions.setDraft(sessionDraft)\n },\n onError: (error) => {\n failed = true\n setState('error', error.message)\n },\n onEnd: (text) => {\n speechRef.current = null\n clearRecordingTimer(recordingTimerRef)\n if (!mountedRef.current) return\n const transcript = text.trim()\n if (failed) return\n if (transcript === '') {\n setState('idle')\n return\n }\n const draftAtStop = updateDraft(baseDraft, transcript)\n inputActions.setDraft(draftAtStop)\n latestDraftRef.current = draftAtStop\n const settings = settingsRef.current\n if (settings !== null && settings.polishingEnabled && settings.polishProvider.trim() !== '' && settings.polishModel.trim() !== '') {\n void polishDraft({\n transcript,\n baseDraft,\n draftAtStop,\n provider: settings.polishProvider,\n model: settings.polishModel,\n remote,\n setState,\n latestDraftRef,\n actionsRef: { current: inputActions },\n polishAbortRef\n })\n } else {\n setState('idle')\n }\n }\n })\n } catch (error) {\n if (mountedRef.current) {\n setState('error', error instanceof Error ? error.message : 'Speech recognition is unavailable in this browser')\n }\n return\n }\n\n speechRef.current = session\n session.start()\n if (failed) return\n setState('recording')\n // Auto-stop at the configured recording limit so an abandoned session\n // never holds the microphone forever.\n armRecordingTimer(recordingTimerRef, effectiveRecordingSeconds(settingsRef.current ?? { maxRecordingSeconds: 120 }), () => {\n speechRef.current?.stop()\n })\n }\n\n const stopListening = () => {\n clearRecordingTimer(recordingTimerRef)\n if (!active) return\n speechRef.current?.stop()\n }\n\n stopRef.current = stopListening\n\n const tooltip = busy\n ? t('voiceBusy')\n : active\n ? t('voiceStop')\n : state === 'polish-error'\n ? t('polishFailedKeepOriginal')\n : state === 'error'\n ? t('voiceFailed')\n : !polishConfigured\n ? `${t('voiceStart')} — ${t('polishNotConfigured')}`\n : t('voiceStart')\n const label = busy ? '…' : active ? t('voiceStop') : t('voiceStart')\n\n return (\n <button\n type=\"button\"\n aria-label={label}\n aria-pressed={active}\n disabled={busy}\n title={tooltip}\n onClick={active ? stopListening : startListening}\n data-better-input-state={state}\n data-better-input-polish-configured={polishConfigured ? 'yes' : 'no'}\n style={buttonStyle(active, busy, !polishConfigured)}\n >\n <MicrophoneIcon />\n </button>\n )\n}\n\nexport interface PolishDraftOptions {\n transcript: string\n baseDraft: string\n draftAtStop: string\n provider: string\n model: string\n remote: BetterInputRemote\n setState: (state: 'idle' | 'error' | 'polish-error' | 'polishing', detail?: string) => void\n latestDraftRef: { current: string }\n actionsRef: { current: { setDraft(text: string): void } }\n polishAbortRef: { current: AbortController | null }\n}\n\nexport async function polishDraft(options: PolishDraftOptions): Promise<void> {\n if (options.provider.trim() === '' || options.model.trim() === '') return\n const controller = new AbortController()\n options.polishAbortRef.current = controller\n options.setState('polishing')\n\n try {\n const result = await options.remote.polish(options.transcript, options.provider, options.model, controller.signal)\n if (controller.signal.aborted) return\n if (!shouldApplyPolishResult(options.latestDraftRef.current, options.draftAtStop, options.baseDraft)) {\n options.setState('idle')\n return\n }\n if (!result.ok) {\n options.setState('polish-error', result.error.message)\n return\n }\n const text = result.value.trim() !== '' ? result.value.trim() : options.transcript\n const nextDraft = updateDraft(options.baseDraft, text)\n options.latestDraftRef.current = nextDraft\n options.actionsRef.current.setDraft(nextDraft)\n options.setState('idle')\n } catch (error) {\n if (controller.signal.aborted) return\n options.setState('polish-error', error instanceof Error ? error.message : 'Polishing failed')\n } finally {\n if (options.polishAbortRef.current === controller) options.polishAbortRef.current = null\n }\n}\n\n/**\n * Only replace the draft when the user has not edited it since the transcript\n * landed. Both the transcript-at-stop and the base draft count as unchanged\n * (the user may have reverted the interim edits).\n */\nexport function shouldApplyPolishResult(currentDraft: string, draftAtStop: string, baseDraft: string): boolean {\n const current = collapseDraft(currentDraft)\n return current === collapseDraft(draftAtStop) || current === collapseDraft(baseDraft)\n}\n\nfunction collapseDraft(text: string): string {\n return text.replace(/\\s+/g, ' ').trim()\n}\n\nfunction buttonStyle(active: boolean, busy: boolean, polishUnconfigured: boolean): React.CSSProperties {\n return {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 28,\n height: 28,\n padding: 0,\n border: 'none',\n borderRadius: 6,\n background: active ? 'var(--dsw-alias-state-business-primary, #4f8cff)' : 'transparent',\n color: active ? '#fff' : 'var(--dsw-alias-label-primary, inherit)',\n cursor: busy ? 'default' : 'pointer',\n opacity: busy ? 0.5 : polishUnconfigured ? 0.75 : 1,\n flex: 'none'\n }\n}\n\nfunction MicrophoneIcon() {\n return (\n <svg aria-hidden=\"true\" fill=\"none\" height=\"16\" viewBox=\"0 0 16 16\" width=\"16\">\n <path\n d=\"M8 1.75a2.25 2.25 0 0 0-2.25 2.25v3.5a2.25 2.25 0 0 0 4.5 0V4A2.25 2.25 0 0 0 8 1.75Z\"\n stroke=\"currentColor\"\n strokeLinejoin=\"round\"\n strokeWidth=\"1.4\"\n />\n <path\n d=\"M3.5 7.5a4.5 4.5 0 0 0 9 0M8 12.25V14M5.5 14h5\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"1.4\"\n />\n </svg>\n )\n}\n\n/** Append transcript to a base draft with one space separator. */\nexport function updateDraft(baseDraft: string, transcript: string): string {\n const text = transcript.trim()\n if (text === '') return baseDraft\n if (baseDraft === '') return text\n if (/\\s$/.test(baseDraft) || /^\\s/.test(text)) return baseDraft + text\n return `${baseDraft} ${text}`\n}\n\nfunction armRecordingTimer(timerRef: { current: ReturnType<typeof setTimeout> | null }, seconds: number, stop: () => void): void {\n clearRecordingTimer(timerRef)\n timerRef.current = setTimeout(stop, Math.max(1, seconds) * 1000)\n}\n\nfunction clearRecordingTimer(timerRef: { current: ReturnType<typeof setTimeout> | null }): void {\n if (timerRef.current === null) return\n clearTimeout(timerRef.current)\n timerRef.current = null\n}\n\nexport function isSupported(): boolean {\n return isWebSpeechAvailable()\n}\n\nexport type { BetterInputSettingsPatch }\n","import { useEffect, useRef, useState, type KeyboardEvent } from 'react'\nimport { createPortal } from 'react-dom'\nimport type { SnapshotSelectorHook, TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { InputState } from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type { ChatSnapshot } from '@deepseek-ai/dsh-client-ui-chat/client'\nimport type { BetterInputRemote } from '../remote.js'\nimport type { SettingsFace } from './MicrophoneButton.js'\n\n/** The framework-injected `t` seat for the BetterInput namespace. */\ntype Translate = TranslateNS<'better-input'>\n\n/**\n * Props handed to a `conversation.input.right` entry, plus the injected\n * remote and settings face. In dsh 0.1.2 the slot standard kit supplies\n * `useChat` (Chat target snapshot, whose `legacy.nodes` carries the message\n * array) and `useInput` (draft); message history is no longer exposed through\n * a top-level `session` owner.\n */\nexport type OptimizeButtonProps = {\n readonly useChat: SnapshotSelectorHook<ChatSnapshot>\n readonly useInput: SnapshotSelectorHook<InputState>\n readonly inputActions: {\n setDraft(text: string): void\n }\n readonly remote: BetterInputRemote\n readonly useSettings: () => SettingsFace\n readonly t: Translate\n}\n\ntype OptimizeState =\n | { kind: 'idle' }\n | { kind: 'optimizing' }\n | { kind: 'result'; original: string; optimized: string }\n | { kind: 'error'; message: string }\n\n/**\n * The ✨ optimize button rendered above the composer card (in\n * `conversation.input.dock`), right-aligned. Click reads the current draft,\n * calls the Host LLM to optimize it, then shows a confirmation panel with\n * the original and optimized text. The draft is replaced only when the user\n * clicks \"Adopt\".\n */\nexport function OptimizeButton({ useChat, useInput, inputActions, remote, useSettings, t }: OptimizeButtonProps) {\n const [state, setState] = useState<OptimizeState>({ kind: 'idle' })\n const settingsFace = useSettings()\n const abortRef = useRef<AbortController | null>(null)\n // Draft comes from `useInput`; message history comes from the `useChat`\n // target snapshot (its `legacy.nodes` carries the ordered message array).\n const input = useInput((state) => state)\n const chat = useChat((area) => area)\n\n // Keep the latest draft in a ref so the click handler can read it without\n // re-subscribing on every keystroke.\n const draftRef = useRef(input.draft)\n useEffect(() => {\n draftRef.current = input.draft\n }, [input.draft])\n\n useEffect(() => {\n return () => {\n abortRef.current?.abort()\n }\n }, [])\n\n const settings = settingsFace.status === 'ready' ? settingsFace.settings : null\n // The prompt-optimize feature is a core capability: an on/off toggle works\n // against the \"everything is a plugin\" philosophy, so it stays always-on\n // and users just configure its provider/model/prompt in settings.\n\n const provider = settings?.optimizeProvider.trim() ?? ''\n const model = settings?.optimizeModel.trim() ?? ''\n const modelConfigured = provider !== '' && model !== ''\n\n const handleClick = async () => {\n if (state.kind === 'optimizing') return\n const draft = draftRef.current.trim()\n if (draft === '') {\n setState({ kind: 'error', message: t('optimizeEmpty') })\n return\n }\n\n if (!modelConfigured) {\n setState({ kind: 'error', message: t('optimizeNotConfigured') })\n return\n }\n\n abortRef.current?.abort()\n const controller = new AbortController()\n abortRef.current = controller\n setState({ kind: 'optimizing' })\n\n try {\n // Extract conversation context based on user settings\n const contextTurns = settings?.contextTurns ?? 3\n const context = contextTurns > 0 ? extractConversationContext(chat.legacy.nodes, contextTurns) : ''\n const result = await remote.optimize(draft, provider, model, context, controller.signal)\n if (controller.signal.aborted) return\n if (!result.ok) {\n setState({ kind: 'error', message: result.error.message })\n return\n }\n const optimized = result.value.trim()\n if (optimized === '') {\n setState({ kind: 'error', message: t('optimizeFailed') })\n return\n }\n // Always show the comparison panel, even when the model returned the\n // text unchanged — silently closing after a visible loading state\n // reads as \"the button did nothing\".\n setState({ kind: 'result', original: draft, optimized })\n } catch (error) {\n if (controller.signal.aborted) return\n setState({ kind: 'error', message: error instanceof Error ? error.message : t('optimizeFailed') })\n } finally {\n if (abortRef.current === controller) abortRef.current = null\n }\n }\n\n const handleAdopt = () => {\n if (state.kind !== 'result') return\n inputActions.setDraft(state.optimized)\n setState({ kind: 'idle' })\n }\n\n const handleCancel = () => {\n setState({ kind: 'idle' })\n }\n\n const busy = state.kind === 'optimizing'\n const disabled = busy || !modelConfigured\n const buttonTitle = modelConfigured ? t('optimizeButton') : t('optimizeNotConfigured')\n\n const errorToast = state.kind === 'error' ? (\n <ErrorToastPortal\n message={state.message}\n onDismiss={handleCancel}\n />\n ) : null\n\n const confirmModal = state.kind === 'result' ? (\n <ConfirmModalPortal\n title={t('optimizePanelTitle')}\n originalLabel={t('optimizeOriginalLabel')}\n optimizedLabel={t('optimizeOptimizedLabel')}\n original={state.original}\n optimized={state.optimized}\n adoptLabel={t('optimizeAdopt')}\n cancelLabel={t('optimizeCancel')}\n onAdopt={handleAdopt}\n onCancel={handleCancel}\n />\n ) : null\n\n return (\n <>\n <div style={containerStyle}>\n <button\n type=\"button\"\n aria-label={buttonTitle}\n title={buttonTitle}\n disabled={disabled}\n onClick={handleClick}\n style={buttonStyle(disabled)}\n >\n <SparkleIcon />\n {busy ? t('optimizeBusy') : ''}\n </button>\n </div>\n {errorToast}\n {confirmModal}\n </>\n )\n}\n\n/** Ctrl/Cmd+A inside a `<pre>` selects only that block's text. */\nfunction selectAllInPre(e: KeyboardEvent<HTMLPreElement>) {\n if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'a') {\n e.preventDefault()\n const range = document.createRange()\n range.selectNodeContents(e.currentTarget)\n const selection = window.getSelection()\n if (selection) {\n selection.removeAllRanges()\n selection.addRange(range)\n }\n }\n}\n\nfunction OptimizeConfirmPanel(props: {\n title: string\n originalLabel: string\n optimizedLabel: string\n original: string\n optimized: string\n adoptLabel: string\n cancelLabel: string\n onAdopt: () => void\n onCancel: () => void\n}) {\n return (\n <div style={modalContentStyle}>\n <div style={panelTitleStyle}>{props.title}</div>\n <div style={compareRowStyle}>\n <div style={compareColStyle}>\n <div style={compareLabelStyle}>{props.originalLabel}</div>\n <pre style={preStyle} tabIndex={0} onKeyDown={selectAllInPre}>{props.original}</pre>\n </div>\n <div style={compareColStyle}>\n <div style={compareLabelStyle}>{props.optimizedLabel}</div>\n <pre style={{ ...preStyle, borderColor: 'var(--dsw-alias-state-business-primary, #4f8cff)' }} tabIndex={0} onKeyDown={selectAllInPre}>{props.optimized}</pre>\n </div>\n </div>\n <div style={panelActionsStyle}>\n <button type=\"button\" style={cancelBtnStyle} onClick={props.onCancel}>{props.cancelLabel}</button>\n <button type=\"button\" style={adoptBtnStyle} onClick={props.onAdopt}>{props.adoptLabel}</button>\n </div>\n </div>\n )\n}\n\n/**\n * Comparison modal portalled to `document.body`. DSH renders slot content\n * inside shadow roots whose ancestors may clip or contain fixed-position\n * children, so the overlay must escape the component tree entirely.\n */\nfunction ConfirmModalPortal(props: {\n title: string\n originalLabel: string\n optimizedLabel: string\n original: string\n optimized: string\n adoptLabel: string\n cancelLabel: string\n onAdopt: () => void\n onCancel: () => void\n}) {\n return createPortal(\n <div\n style={modalOverlayStyle}\n onClick={(e) => {\n // Ignore clicks that finish a text drag-select (selection not\n // collapsed), so releasing the mouse outside the modal neither\n // closes it nor loses the selection.\n const selection = window.getSelection()\n if (selection && !selection.isCollapsed) return\n props.onCancel()\n }}\n >\n <div onClick={(e) => e.stopPropagation()}>\n <OptimizeConfirmPanel {...props} />\n </div>\n </div>,\n document.body\n )\n}\n\n/**\n * Small error modal, also portalled to `document.body` for the same\n * stacking/escaping reasons as the comparison modal.\n */\nfunction ErrorToastPortal({ message, onDismiss }: { message: string; onDismiss: () => void }) {\n return createPortal(\n <div\n style={modalOverlayStyle}\n onClick={(e) => {\n const selection = window.getSelection()\n if (selection && !selection.isCollapsed) return\n onDismiss()\n }}\n >\n <div style={errorModalStyle} onClick={(e) => e.stopPropagation()}>\n <div style={{ flex: 1 }}>{message}</div>\n <button type=\"button\" style={errorDismissStyle} onClick={onDismiss}>×</button>\n </div>\n </div>,\n document.body\n )\n}\n\nfunction SparkleIcon() {\n return (\n <svg aria-hidden=\"true\" fill=\"none\" height=\"14\" viewBox=\"0 0 16 16\" width=\"14\">\n <path\n d=\"M8 1.5l1.3 3.7L13 6.5l-3.7 1.3L8 11.5 6.7 7.8 3 6.5l3.7-1.3L8 1.5z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M12.5 10.5l.6 1.7 1.7.6-1.7.6-.6 1.7-.6-1.7-1.7-.6 1.7-.6.6-1.7z\"\n fill=\"currentColor\"\n opacity=\"0.6\"\n />\n </svg>\n )\n}\n\n/**\n * Minimal structural view of a ConversationNode, read purely for its message\n * text. Declared locally (rather than importing `ConversationNode`) so the\n * extractor does not depend on third-party type resolution of the conversation\n * records package. Matches the fields emitted by `ChatSnapshot.legacy.nodes`.\n */\ntype ConversationNodeView =\n | { readonly kind: 'user'; readonly content: readonly { readonly type: 'text'; readonly text: string }[] }\n | { readonly kind: 'assistant'; readonly blocks: readonly { readonly kind: 'text'; readonly text: string }[] }\n\n/**\n * Extract recent conversation context from the message array. Returns a\n * plain-text summary of the last N user/assistant turns, formatted as:\n *\n * User: <message text>\n * Assistant: <response text (truncated at 500 chars)>\n *\n * Returns an empty string when there are no user/assistant nodes.\n */\nfunction extractConversationContext(nodes: readonly ConversationNodeView[], maxTurns: number): string {\n // chat.legacy.nodes is the ordered message array from the Chat target.\n const relevant: Array<{ role: 'user' | 'assistant'; text: string }> = []\n for (const node of nodes) {\n if (node.kind === 'user') {\n // Extract text from user content blocks.\n const text = node.content\n .filter((c) => c.type === 'text')\n .map((c) => c.text)\n .join('')\n if (text.trim()) relevant.push({ role: 'user', text: text.trim() })\n } else if (node.kind === 'assistant') {\n // Extract text from assistant blocks.\n const text = node.blocks\n .filter((b) => b.kind === 'text')\n .map((b) => b.text)\n .join('')\n if (text.trim()) relevant.push({ role: 'assistant', text: text.trim().slice(0, 500) })\n }\n }\n\n // Take only the last `maxTurns` turns (a turn = user + assistant pair).\n const recent = relevant.slice(-maxTurns * 2)\n if (recent.length === 0) return ''\n\n return recent\n .map((entry) => (entry.role === 'user' ? `User: ${entry.text}` : `Assistant: ${entry.text}`))\n .join('\\n')\n}\n\n// --- Styles ---\n// Now rendered inline as a regular item in the `conversation.input.right`\n// flex row (left of the microphone button). No more position hacks — order\n// in `index.ts` places it on the microphone's immediate left.\n\nconst containerStyle: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n height: 26,\n flex: 'none'\n}\n\nconst buttonStyle = (disabled: boolean): React.CSSProperties => ({\n display: 'inline-flex',\n alignItems: 'center',\n gap: 4,\n height: 26,\n padding: '0 8px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--dsw-alias-label-secondary, inherit)',\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n fontSize: 12,\n flex: 'none'\n})\n\n// \"Full-screen\" overlay with position:fixed anchored to the viewport so it\n// escapes any overflow clipping inside the composer card.\nconst modalOverlayStyle: React.CSSProperties = {\n position: 'fixed',\n inset: 0,\n background: 'rgba(0,0,0,0.35)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 99998\n}\n\nconst modalContentStyle: React.CSSProperties = {\n padding: 14,\n borderRadius: 10,\n background: 'var(--dsw-alias-bg-layer-2, #fff)',\n border: '1px solid var(--dsw-alias-border-l2, #e0e0e0)',\n boxShadow: '0 8px 32px rgba(0,0,0,0.2)',\n width: 'min(640px, 92vw)',\n zIndex: 99999\n}\n\nconst panelTitleStyle: React.CSSProperties = {\n fontSize: 14,\n fontWeight: 600,\n marginBottom: 10,\n color: 'var(--dsw-alias-label-primary, inherit)'\n}\n\nconst compareRowStyle: React.CSSProperties = {\n display: 'flex',\n gap: 10,\n maxHeight: 300\n}\n\nconst compareColStyle: React.CSSProperties = {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n minWidth: 0\n}\n\nconst compareLabelStyle: React.CSSProperties = {\n fontSize: 11,\n color: 'var(--dsw-alias-label-secondary, #888)',\n marginBottom: 4\n}\n\nconst preStyle: React.CSSProperties = {\n margin: 0,\n padding: 10,\n fontSize: 12,\n lineHeight: 1.6,\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n overflow: 'auto',\n maxHeight: 240,\n borderRadius: 6,\n border: '1px solid var(--dsw-alias-border-l2, #e8e8e8)',\n background: 'var(--dsw-alias-bg-layer-1, #f9f9f9)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n fontFamily: 'inherit'\n}\n\nconst panelActionsStyle: React.CSSProperties = {\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 8,\n marginTop: 12\n}\n\nconst adoptBtnStyle: React.CSSProperties = {\n padding: '6px 16px',\n border: 'none',\n borderRadius: 6,\n background: 'var(--dsw-alias-state-business-primary, #4f8cff)',\n color: '#fff',\n cursor: 'pointer',\n fontSize: 13\n}\n\nconst cancelBtnStyle: React.CSSProperties = {\n padding: '6px 16px',\n border: '1px solid var(--dsw-alias-border-l2, #ddd)',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--dsw-alias-label-primary, inherit)',\n cursor: 'pointer',\n fontSize: 13\n}\n\n// Error toast, also portal-rendered on top of everything.\nconst errorModalStyle: React.CSSProperties = {\n padding: '10px 14px',\n borderRadius: 8,\n background: 'var(--dsw-alias-bg-layer-2, #fff)',\n border: '1px solid var(--dsw-alias-state-error-secondary, #f5c2c7)',\n boxShadow: '0 4px 16px rgba(0,0,0,0.15)',\n color: 'var(--dsw-alias-state-error-primary, #c33)',\n fontSize: 13,\n display: 'flex',\n alignItems: 'center',\n gap: 10,\n zIndex: 99999,\n maxWidth: 420,\n width: 'min(420px, 90vw)'\n}\n\nconst errorDismissStyle: React.CSSProperties = {\n border: 'none',\n background: 'transparent',\n color: 'inherit',\n cursor: 'pointer',\n fontSize: 18,\n padding: 0,\n lineHeight: 1,\n flex: 'none'\n}\n","import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'\nimport { useVoiceInputSession, type VoiceInputSession } from './voice-session.js'\n\n/** The framework-injected `t` seat for the BetterInput namespace. */\ntype Translate = TranslateNS<'better-input'>\n\nexport type RecognitionBarProps = {\n readonly voiceSession: VoiceInputSession\n readonly t: Translate\n}\n\n/**\n * The recognition status bar above the composer. Shows live state and a stop\n * button while recording; the bar renders nothing when idle.\n */\nexport function VoiceRecognitionBar({ voiceSession, t }: RecognitionBarProps) {\n const snapshot = useVoiceInputSession(voiceSession)\n\n const active = snapshot.state === 'starting' || snapshot.state === 'recording'\n const label = active\n ? t('listening')\n : snapshot.state === 'transcribing'\n ? t('transcribing')\n : snapshot.state === 'polishing'\n ? t('polishing')\n : snapshot.state === 'polish-error'\n ? t('polishFailedKeepOriginal')\n : snapshot.state === 'error'\n ? t('voiceFailed')\n : ''\n\n if (label === '') return null\n\n return (\n <div\n data-better-input-bar=\"true\"\n role=\"status\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '4px 10px',\n borderRadius: 8,\n fontSize: 12,\n lineHeight: '18px',\n background: 'var(--dsw-alias-bg-layer-3, rgba(0,0,0,0.04))',\n color: 'var(--dsw-alias-label-primary, inherit)'\n }}\n >\n {active ? <PulsingDot /> : null}\n <span>{label}</span>\n {(snapshot.state === 'error' || snapshot.state === 'polish-error') && snapshot.detail !== '' ? (\n <span style={{ opacity: 0.7 }}>{snapshot.detail}</span>\n ) : null}\n {active ? (\n <button\n type=\"button\"\n onClick={() => voiceSession.requestStop()}\n style={{\n marginLeft: 'auto',\n padding: '2px 8px',\n border: 'none',\n borderRadius: 6,\n fontSize: 12,\n background: 'var(--dsw-alias-state-error-secondary, #e5484d)',\n color: '#fff',\n cursor: 'pointer'\n }}\n >\n {t('voiceStop')}\n </button>\n ) : null}\n </div>\n )\n}\n\nfunction PulsingDot() {\n return (\n <span\n aria-hidden=\"true\"\n style={{\n width: 8,\n height: 8,\n borderRadius: '50%',\n background: 'var(--dsw-alias-state-error-secondary, #e5484d)',\n animation: 'sqs-dsh-better-input-pulse 1.2s ease-in-out infinite'\n }}\n />\n )\n}\n","import { useSyncExternalStore } from 'react'\nimport { DEFAULT_SETTINGS, type BetterInputSettings, type BetterInputSettingsPatch, type BetterInputSettingsView, type PolishRoute, type ReasoningEffortInfo } from '../config.js'\nimport type { AboutInfoWire, UpdateCheckResultWire } from '../remote-contract.js'\nimport type { BetterInputRemote } from '../remote.js'\n\nexport type SettingsStatus = 'loading' | 'ready' | 'error'\n\nexport type SettingsSnapshot = {\n readonly status: SettingsStatus\n readonly view: BetterInputSettingsView\n readonly detail: string\n}\n\nexport type RoutesSnapshot = {\n readonly status: 'loading' | 'ready' | 'error'\n readonly routes: readonly PolishRoute[]\n readonly detail: string\n}\n\n/** Keyed by `${provider}\\u0000${model}` — undefined effort = loading requested,\n * null effort = load failed, object = resolved efforts. */\nexport type EffortsSnapshot = Readonly<Record<string, EffortsEntry>>\nexport type EffortsEntry = {\n readonly status: 'loading' | 'ready' | 'error'\n readonly efforts: readonly ReasoningEffortInfo[]\n readonly defaultEffort?: string\n readonly detail: string\n}\n\nexport type AboutSnapshot = {\n readonly status: 'loading' | 'ready' | 'error'\n readonly about: AboutInfoWire\n readonly detail: string\n}\n\nexport type UpdateSnapshot = {\n readonly status: 'idle' | 'loading' | 'ready' | 'error'\n readonly update: UpdateCheckResultWire | null\n readonly detail: string\n}\n\nconst EMPTY_ABOUT: AboutInfoWire = {\n repository: '',\n repositorySlug: '',\n version: '',\n license: '',\n updateCommand: '',\n updateCommandNpx: ''\n}\n\nconst EMPTY_VIEW: BetterInputSettingsView = {\n available: false,\n writable: false,\n settings: { ...DEFAULT_SETTINGS },\n overridden: [],\n defaultPolishPrompt: '',\n defaultOptimizePrompt: ''\n}\n\ntype Listener = () => void\n\n/**\n * Settings read/write controller for the settings page and the microphone\n * flow. Owns the remote calls and a simple external store so both the page\n * and the voice button observe the same values. Also caches per-model\n * reasoning-effort metadata loaded lazily through resolveModelEfforts so\n * opening the effort dropdown never double-fetches across renders.\n */\nexport class SettingsController {\n private settingsSnapshot: SettingsSnapshot = { status: 'loading', view: EMPTY_VIEW, detail: '' }\n private routesSnapshot: RoutesSnapshot = { status: 'loading', routes: [], detail: '' }\n private effortsSnapshot: EffortsSnapshot = {}\n private aboutSnapshot: AboutSnapshot = { status: 'loading', about: EMPTY_ABOUT, detail: '' }\n private updateSnapshot: UpdateSnapshot = { status: 'idle', update: null, detail: '' }\n private readonly listeners = new Set<Listener>()\n private disposed = false\n\n constructor(private readonly remote: BetterInputRemote) {}\n\n readonly getSettingsSnapshot = (): SettingsSnapshot => this.settingsSnapshot\n\n readonly getRoutesSnapshot = (): RoutesSnapshot => this.routesSnapshot\n\n readonly getEffortsSnapshot = (): EffortsSnapshot => this.effortsSnapshot\n\n readonly getAboutSnapshot = (): AboutSnapshot => this.aboutSnapshot\n\n readonly getUpdateSnapshot = (): UpdateSnapshot => this.updateSnapshot\n\n readonly subscribe = (listener: Listener): (() => void) => {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n async refreshSettings(): Promise<void> {\n const result = await this.remote.getSettings()\n if (this.disposed) return\n if (!result.ok) {\n this.settingsSnapshot = { status: 'error', view: EMPTY_VIEW, detail: result.error.message }\n } else {\n this.settingsSnapshot = { status: 'ready', view: result.value, detail: '' }\n // Best-effort \"first launch\" default model pick: if the profile store\n // still carries the empty-string defaults (no model ever chosen in\n // BetterInput), wait a tick for routes and auto-pick the first one\n // available in the dsh registry as the default for polish + optimize.\n // This roughly matches \"use the user's primary configured model\"\n // because dsh's listRoutes() keeps user-favorite providers first.\n void this.autoPopulateDefaultRoutesIfNeeded(result.value.settings)\n }\n this.emit()\n }\n\n async refreshRoutes(): Promise<void> {\n const result = await this.remote.listRoutes()\n if (this.disposed) return\n if (!result.ok) {\n this.routesSnapshot = { status: 'error', routes: [], detail: result.error.message }\n } else {\n this.routesSnapshot = { status: 'ready', routes: result.value, detail: '' }\n // Settings may have arrived before routes; re-check autopopulate now.\n if (this.settingsSnapshot.status === 'ready') {\n void this.autoPopulateDefaultRoutesIfNeeded(this.settingsSnapshot.view.settings)\n }\n }\n this.emit()\n }\n\n private readonly autoPopulateDefaultRoutesIfNeeded = async (settings: BetterInputSettings): Promise<void> => {\n const polishEmpty = settings.polishProvider === '' || settings.polishModel === ''\n const optimizeEmpty = settings.optimizeProvider === '' || settings.optimizeModel === ''\n if (!polishEmpty && !optimizeEmpty) return\n\n const routes = this.routesSnapshot.status === 'ready' && this.routesSnapshot.routes.length > 0\n ? this.routesSnapshot.routes\n : await (async (): Promise<readonly PolishRoute[]> => {\n if (this.disposed) return []\n const rs = await this.remote.listRoutes()\n if (this.disposed || !rs.ok) return []\n this.routesSnapshot = { status: 'ready', routes: rs.value, detail: '' }\n this.emit()\n return rs.value\n })()\n\n const first = routes[0]\n if (first === undefined) return\n\n const patch: BetterInputSettingsPatch = {}\n if (polishEmpty) {\n patch.polishProvider = first.provider\n patch.polishModel = first.model\n }\n if (optimizeEmpty) {\n patch.optimizeProvider = first.provider\n patch.optimizeModel = first.model\n }\n await this.update(patch)\n }\n\n async update(patch: BetterInputSettingsPatch): Promise<boolean> {\n const result = await this.remote.updateSettings(patch)\n if (this.disposed) return false\n if (!result.ok) return false\n this.settingsSnapshot = { status: 'ready', view: result.value, detail: '' }\n this.emit()\n return true\n }\n\n /**\n * Lazily fetch reasoning efforts for a route. Results are cached in the\n * controller so changing the effort dropdown back and forth doesn't\n * re-trigger remote calls. Returns a snapshot entry immediately — the\n * caller subscribes via `useEffortsSnapshot` to re-render when the data\n * lands.\n */\n async ensureEffortsFor(provider: string, model: string): Promise<void> {\n if (provider === '' || model === '' || this.disposed) return\n const key = `${provider}\\u0000${model}`\n const existing = this.effortsSnapshot[key]\n // Never refetch; keep whatever previous result (success / error / loading) we had.\n if (existing !== undefined) return\n this.effortsSnapshot = {\n ...this.effortsSnapshot,\n [key]: { status: 'loading', efforts: [], detail: '' }\n }\n this.emit()\n try {\n const result = await this.remote.resolveModelEfforts(provider, model)\n if (this.disposed) return\n if (result.ok) {\n this.effortsSnapshot = {\n ...this.effortsSnapshot,\n [key]: { status: 'ready', efforts: result.value.efforts, defaultEffort: result.value.defaultEffort, detail: '' }\n }\n } else {\n this.effortsSnapshot = {\n ...this.effortsSnapshot,\n [key]: { status: 'error', efforts: [], detail: result.error.message }\n }\n }\n } catch (error) {\n if (this.disposed) return\n this.effortsSnapshot = {\n ...this.effortsSnapshot,\n [key]: { status: 'error', efforts: [], detail: error instanceof Error ? error.message : String(error) }\n }\n }\n this.emit()\n }\n\n async refreshAbout(): Promise<void> {\n const result = await this.remote.getAbout()\n if (this.disposed) return\n if (!result.ok) {\n this.aboutSnapshot = { status: 'error', about: EMPTY_ABOUT, detail: result.error.message }\n } else {\n this.aboutSnapshot = { status: 'ready', about: result.value, detail: '' }\n }\n this.emit()\n }\n\n async checkForUpdate(): Promise<void> {\n if (this.disposed) return\n if (this.updateSnapshot.status === 'loading') return\n this.updateSnapshot = { status: 'loading', update: null, detail: '' }\n this.emit()\n try {\n const result = await this.remote.checkForUpdate()\n if (this.disposed) return\n if (result.ok) {\n this.updateSnapshot = { status: 'ready', update: result.value, detail: '' }\n } else {\n this.updateSnapshot = { status: 'error', update: null, detail: result.error.message }\n }\n } catch (error) {\n if (this.disposed) return\n this.updateSnapshot = { status: 'error', update: null, detail: error instanceof Error ? error.message : String(error) }\n }\n this.emit()\n }\n\n dispose(): void {\n this.disposed = true\n this.listeners.clear()\n }\n\n private emit(): void {\n for (const listener of this.listeners) listener()\n }\n}\n\nexport function useSettingsSnapshot(controller: SettingsController): SettingsSnapshot {\n return useSyncExternalStore(controller.subscribe, controller.getSettingsSnapshot, controller.getSettingsSnapshot)\n}\n\nexport function useRoutesSnapshot(controller: SettingsController): RoutesSnapshot {\n return useSyncExternalStore(controller.subscribe, controller.getRoutesSnapshot, controller.getRoutesSnapshot)\n}\n\nexport function useEffortsSnapshot(controller: SettingsController): EffortsSnapshot {\n return useSyncExternalStore(controller.subscribe, controller.getEffortsSnapshot, controller.getEffortsSnapshot)\n}\n\nexport function useAboutSnapshot(controller: SettingsController): AboutSnapshot {\n return useSyncExternalStore(controller.subscribe, controller.getAboutSnapshot, controller.getAboutSnapshot)\n}\n\nexport function useUpdateSnapshot(controller: SettingsController): UpdateSnapshot {\n return useSyncExternalStore(controller.subscribe, controller.getUpdateSnapshot, controller.getUpdateSnapshot)\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { BetterInputSettings, BetterInputSettingsPatch, ReasoningEffortInfo } from '../config.js'\nimport type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SettingsController, UpdateSnapshot } from './settings-controller.js'\nimport { useAboutSnapshot, useEffortsSnapshot, useSettingsSnapshot, useRoutesSnapshot, useUpdateSnapshot } from './settings-controller.js'\n\n/** The framework-injected `t` seat for the BetterInput namespace. */\ntype Translate = TranslateNS<'better-input'>\n\nfunction ReasoningEffortSelect(props: {\n settingsController: SettingsController\n provider: string\n model: string\n storedEffort: string\n onChange: (effortId: string) => void\n t: Translate\n}) {\n const { settingsController, provider, model, storedEffort, onChange, t } = props\n const efforts = useEffortsSnapshot(settingsController)\n\n // Kick off the lazy fetch whenever the selected model changes.\n useEffect(() => {\n if (provider === '' || model === '') return\n void settingsController.ensureEffortsFor(provider, model)\n }, [settingsController, provider, model])\n\n if (provider === '' || model === '') return null\n const key = `${provider}\\u0000${model}`\n const entry = efforts[key]\n\n // Not yet requested / loading → show a disabled placeholder so the user\n // knows the field exists but is warming up.\n if (entry === undefined || entry.status === 'loading') {\n return (\n <select value=\"\" disabled={true} style={inputStyle}>\n <option value=\"\">{t('effortLoadingLabel')}</option>\n </select>\n )\n }\n if (entry.status === 'error' || entry.efforts.length === 0) {\n // Nothing to show; silently hide like the \"no efforts\" case so the UI\n // doesn't constantly surface adapter metadata misses for regular models.\n return null\n }\n // The default option means \"let the Host decide\" — it prefers the model's\n // `off` tier, so we no longer surface the adapter's defaultEffort here.\n const items: readonly ReasoningEffortInfo[] = entry.efforts\n return (\n <select\n value={storedEffort}\n onChange={(event) => onChange(event.target.value)}\n style={inputStyle}\n >\n <option value=\"\">{t('effortDefaultLabel')}</option>\n {items.map((effort) => (\n <option key={effort.id} value={effort.id} title={effort.description}>\n {effort.name}\n </option>\n ))}\n </select>\n )\n}\n\nexport type SettingsSectionProps = {\n readonly close: () => void\n readonly t: Translate\n readonly settingsController: SettingsController\n}\n\ntype FieldState = {\n text: string\n invalid: boolean\n}\n\n/**\n * The BetterInput settings page. Renders the recognition and polishing\n * configuration; every field edits a local draft and saves on blur/change.\n */\nexport function BetterInputSettingsSection({ close, settingsController, t }: SettingsSectionProps) {\n const settings = useSettingsSnapshot(settingsController)\n const routes = useRoutesSnapshot(settingsController)\n const about = useAboutSnapshot(settingsController)\n const update = useUpdateSnapshot(settingsController)\n const [drafts, setDrafts] = useState<Record<string, string>>({})\n const [saveFailed, setSaveFailed] = useState(false)\n const [showDefaultPrompt, setShowDefaultPrompt] = useState(false)\n const [showDefaultOptimizePrompt, setShowDefaultOptimizePrompt] = useState(false)\n const draftsRef = useRef(drafts)\n draftsRef.current = drafts\n\n useEffect(() => {\n void settingsController.refreshSettings()\n void settingsController.refreshRoutes()\n void settingsController.refreshAbout()\n }, [settingsController])\n\n if (settings.status === 'loading' || routes.status === 'loading') {\n return <SectionFrame title={t('settingsTitle')}>{t('loading')}</SectionFrame>\n }\n\n const field = (name: string, current: string): FieldState => ({\n text: drafts[name] ?? current,\n invalid: false\n })\n\n const setField = (name: string, value: string) => {\n setDrafts((prev) => ({ ...prev, [name]: value }))\n }\n\n const save = async (patch: BetterInputSettingsPatch) => {\n setSaveFailed(false)\n const ok = await settingsController.update(patch)\n if (ok) {\n setDrafts((prev) => {\n const next = { ...prev }\n for (const key of Object.keys(patch)) delete next[key]\n return next\n })\n } else {\n setSaveFailed(true)\n }\n }\n\n const s = settings.view.settings\n const languageField = field('language', s.language)\n const secondsField = field('maxRecordingSeconds', String(s.maxRecordingSeconds))\n const polishPromptField = field('polishPrompt', s.polishPrompt)\n const optimizePromptField = field('optimizePrompt', s.optimizePrompt)\n const contextTurnsField = field('contextTurns', String(s.contextTurns))\n\n return (\n <SectionFrame title={t('settingsTitle')}>\n <p style={hintStyle}>{t('settingsDescription')}</p>\n\n {saveFailed ? <p style={errorStyle}>{t('saveFailed')}</p> : null}\n\n <h3 style={sectionTitleStyle}>{t('voiceSectionLabel')}</h3>\n\n <Field label={t('languageLabel')} hint={t('languageHint')}>\n <input\n type=\"text\"\n value={languageField.text}\n placeholder={t('languagePlaceholder')}\n onChange={(event) => setField('language', event.target.value)}\n onBlur={() => void save({ language: languageField.text.trim() })}\n style={inputStyle}\n />\n </Field>\n\n <Field label={t('recordingLimitLabel')} hint={t('recordingLimitHint')}>\n <input\n type=\"number\"\n min={1}\n max={600}\n value={secondsField.text}\n onChange={(event) => setField('maxRecordingSeconds', event.target.value)}\n onBlur={() => {\n const parsed = Number(secondsField.text)\n if (!Number.isSafeInteger(parsed) || parsed < 1 || parsed > 600) return\n void save({ maxRecordingSeconds: parsed })\n }}\n style={inputStyle}\n />\n </Field>\n\n <h3 style={sectionTitleStyle}>{t('polishSectionLabel')}</h3>\n\n <Field label={t('polishLabel')} hint={t('polishHint')}>\n <label style={switchStyle}>\n <input\n type=\"checkbox\"\n checked={s.polishingEnabled}\n onChange={(event) => void save({ polishingEnabled: event.target.checked })}\n />\n <span>{s.polishingEnabled ? t('on') : t('off')}</span>\n </label>\n </Field>\n\n {s.polishingEnabled ? (\n <>\n <Field label={t('polishModelLabel')} hint={t('polishModelHint')}>\n <select\n value={drafts.polishProvider !== undefined || drafts.polishModel !== undefined\n ? `${drafts.polishProvider ?? s.polishProvider}\\u0000${drafts.polishModel ?? s.polishModel}`\n : `${s.polishProvider}\\u0000${s.polishModel}`}\n onChange={(event) => {\n const [provider, model] = event.target.value.split('\\u0000')\n void save({ polishProvider: provider ?? '', polishModel: model ?? '' })\n }}\n style={inputStyle}\n disabled={routes.status !== 'ready' || routes.routes.length === 0}\n >\n <option value={'\\u0000'}>{t('polishModelNone')}</option>\n {routes.status === 'ready' && routes.routes.map((route) => (\n <option key={`${route.provider}\\u0000${route.model}`} value={`${route.provider}\\u0000${route.model}`}>\n {route.providerName} / {route.modelName}\n </option>\n ))}\n </select>\n </Field>\n\n <Field label={t('polishEffortLabel')} hint={t('polishEffortHint')}>\n <ReasoningEffortSelect\n settingsController={settingsController}\n provider={s.polishProvider}\n model={s.polishModel}\n storedEffort={s.polishReasoningEffort}\n onChange={(effortId) => void save({ polishReasoningEffort: effortId })}\n t={t}\n />\n </Field>\n\n <Field label={t('polishPromptLabel')} hint={t('polishPromptHint')}>\n <textarea\n value={polishPromptField.text}\n rows={5}\n placeholder={t('polishPromptPlaceholder')}\n onChange={(event) => setField('polishPrompt', event.target.value)}\n onBlur={() => void save({ polishPrompt: polishPromptField.text })}\n style={{ ...inputStyle, resize: 'vertical', fontFamily: 'monospace' }}\n />\n {settings.view.defaultPolishPrompt !== '' ? (\n <div>\n <button\n type=\"button\"\n onClick={() => setShowDefaultPrompt((prev) => !prev)}\n style={toggleLinkStyle}\n >\n {showDefaultPrompt ? t('hideDefaultPrompt') : t('showDefaultPrompt')}\n </button>\n {showDefaultPrompt ? (\n <pre\n style={{\n margin: '6px 0 0',\n padding: 8,\n maxHeight: 220,\n overflow: 'auto',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n fontSize: 11,\n lineHeight: 1.5,\n background: 'var(--dsw-alias-bg-layer-1, rgba(0,0,0,0.03))',\n border: '1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.3))',\n borderRadius: 6,\n fontFamily: 'monospace'\n }}\n >\n {settings.view.defaultPolishPrompt}\n </pre>\n ) : null}\n </div>\n ) : null}\n </Field>\n </>\n ) : null}\n\n <h3 style={{ margin: '16px 0 0', fontSize: 14 }}>{t('optimizeSectionLabel')}</h3>\n\n <Field label={t('optimizeModelLabel')} hint={t('optimizeModelHint')}>\n <select\n value={drafts.optimizeProvider !== undefined || drafts.optimizeModel !== undefined\n ? `${drafts.optimizeProvider ?? s.optimizeProvider}\\u0000${drafts.optimizeModel ?? s.optimizeModel}`\n : `${s.optimizeProvider}\\u0000${s.optimizeModel}`}\n onChange={(event) => {\n const [provider, model] = event.target.value.split('\\u0000')\n void save({ optimizeProvider: provider ?? '', optimizeModel: model ?? '' })\n }}\n style={inputStyle}\n disabled={routes.status !== 'ready' || routes.routes.length === 0}\n >\n <option value={'\\u0000'}>{t('polishModelNone')}</option>\n {routes.status === 'ready' && routes.routes.map((route) => (\n <option key={`${route.provider}\\u0000${route.model}`} value={`${route.provider}\\u0000${route.model}`}>\n {route.providerName} / {route.modelName}\n </option>\n ))}\n </select>\n </Field>\n\n <Field label={t('optimizeEffortLabel')} hint={t('optimizeEffortHint')}>\n <ReasoningEffortSelect\n settingsController={settingsController}\n provider={s.optimizeProvider}\n model={s.optimizeModel}\n storedEffort={s.optimizeReasoningEffort}\n onChange={(effortId) => void save({ optimizeReasoningEffort: effortId })}\n t={t}\n />\n </Field>\n\n <Field label={t('optimizePromptLabel')} hint={t('optimizePromptHint')}>\n <textarea\n value={optimizePromptField.text}\n rows={5}\n placeholder={t('optimizePromptPlaceholder')}\n onChange={(event) => setField('optimizePrompt', event.target.value)}\n onBlur={() => void save({ optimizePrompt: optimizePromptField.text })}\n style={{ ...inputStyle, resize: 'vertical', fontFamily: 'monospace' }}\n />\n {settings.view.defaultOptimizePrompt !== '' ? (\n <div>\n <button\n type=\"button\"\n onClick={() => setShowDefaultOptimizePrompt((prev) => !prev)}\n style={toggleLinkStyle}\n >\n {showDefaultOptimizePrompt ? t('hideDefaultPrompt') : t('showDefaultPrompt')}\n </button>\n {showDefaultOptimizePrompt ? (\n <pre\n style={{\n margin: '6px 0 0',\n padding: 8,\n maxHeight: 220,\n overflow: 'auto',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n fontSize: 11,\n lineHeight: 1.5,\n background: 'var(--dsw-alias-bg-layer-1, rgba(0,0,0,0.03))',\n border: '1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.3))',\n borderRadius: 6,\n fontFamily: 'monospace'\n }}\n >\n {settings.view.defaultOptimizePrompt}\n </pre>\n ) : null}\n </div>\n ) : null}\n </Field>\n\n <Field label={t('contextTurnsLabel')} hint={t('contextTurnsHint')}>\n <input\n type=\"number\"\n min={0}\n max={20}\n value={contextTurnsField.text}\n onChange={(event) => setField('contextTurns', event.target.value)}\n onBlur={() => {\n const parsed = Number(contextTurnsField.text)\n if (!Number.isSafeInteger(parsed) || parsed < 0 || parsed > 20) return\n void save({ contextTurns: parsed })\n }}\n style={inputStyle}\n />\n </Field>\n\n <p style={hintStyle}>\n {t('routesStatus')}: {routes.status === 'ready' ? `${routes.routes.length}` : routes.detail || t('routesUnavailable')}\n </p>\n\n <hr style={dividerStyle} />\n\n <AboutUpdateSection\n aboutStatus={about.status}\n version={about.about.version}\n repository={about.about.repository}\n license={about.about.license}\n update={update}\n t={t}\n onCheckUpdate={() => void settingsController.checkForUpdate()}\n />\n </SectionFrame>\n )\n}\n\nfunction AboutUpdateSection(props: {\n aboutStatus: string\n version: string\n repository: string\n license: string\n update: UpdateSnapshot\n t: Translate\n onCheckUpdate: () => void\n}) {\n const { aboutStatus, version, repository, license, update, t, onCheckUpdate } = props\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>\n <h3 style={{ margin: 0, fontSize: 14 }}>{t('aboutTitle')}</h3>\n {aboutStatus === 'ready' ? (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 2, fontSize: 13, opacity: 0.85 }}>\n <span>{t('aboutVersionLabel')}: {version || '—'}</span>\n <span>{t('aboutLicenseLabel')}: {license || '—'}</span>\n {repository !== '' ? (\n <a\n href={repository}\n target=\"_blank\"\n rel=\"noreferrer\"\n style={{ color: 'var(--dsw-alias-state-business-primary, #4f8cff)' }}\n >\n {t('aboutRepositoryLabel')}: {repository}\n </a>\n ) : null}\n {repository !== '' ? (\n <a\n href={`${repository.replace(/\\/+$/, '')}/blob/main/CHANGELOG.md`}\n target=\"_blank\"\n rel=\"noreferrer\"\n style={{ color: 'var(--dsw-alias-state-business-primary, #4f8cff)' }}\n >\n {t('aboutChangelogLabel')}\n </a>\n ) : null}\n </div>\n ) : null}\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <button\n type=\"button\"\n onClick={onCheckUpdate}\n disabled={update.status === 'loading'}\n style={{\n width: 'fit-content',\n padding: '6px 12px',\n borderRadius: 6,\n border: '1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.4))',\n background: 'var(--dsh-color-surface, transparent)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n fontSize: 13,\n cursor: update.status === 'loading' ? 'default' : 'pointer'\n }}\n >\n {update.status === 'loading' ? t('checkingUpdate') : t('checkUpdateButton')}\n </button>\n {update.status === 'ready' && update.update !== null ? (\n (() => {\n const status = update.update.status\n if (status === 'up-to-date') {\n return <p style={hintStyle}>{t('updateUpToDate')}</p>\n }\n if (status === 'unpublished') {\n return <p style={hintStyle}>{t('updateUnpublished')}</p>\n }\n if (status === 'update-available') {\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>\n <p style={{ ...hintStyle, color: 'var(--dsw-alias-state-error-primary, #e5484d)' }}>\n {t('updateAvailable')}: {update.update.installed} → {update.update.latest}\n </p>\n <span style={hintStyle}>{t('updateCommandLabel')}:</span>\n <code style={codeStyle}>{update.update.updateCommand}</code>\n <span style={hintStyle}>{t('updateCommandNpxLabel')}:</span>\n <code style={codeStyle}>{update.update.updateCommandNpx}</code>\n <span style={hintStyle}>{t('updateCommandPick')}:</span>\n </div>\n )\n }\n return <p style={errorStyle}>{t('updateCheckFailed')}</p>\n })()\n ) : null}\n {update.status === 'error' ? (\n <p style={errorStyle}>{t('updateCheckFailed')}: {update.detail}</p>\n ) : null}\n </div>\n </div>\n )\n}\n\nfunction SectionFrame({ title, children }: { title: string; children: React.ReactNode }) {\n return (\n <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 12 }}>\n <h2 style={{ margin: 0, fontSize: 16 }}>{title}</h2>\n {children}\n </div>\n )\n}\n\nfunction Field({ label, hint, children }: { label: string; hint: string; children: React.ReactNode }) {\n return (\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>\n <span style={{ fontSize: 13, fontWeight: 600 }}>{label}</span>\n {children}\n <span style={hintStyle}>{hint}</span>\n </label>\n )\n}\n\nconst inputStyle: React.CSSProperties = {\n padding: '6px 8px',\n borderRadius: 6,\n border: '1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.4))',\n background: 'var(--dsw-alias-bg-layer-1, #f9f9f9)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n fontSize: 13\n}\n\nconst hintStyle: React.CSSProperties = {\n margin: 0,\n fontSize: 12,\n opacity: 0.7\n}\n\nconst errorStyle: React.CSSProperties = {\n margin: 0,\n fontSize: 12,\n color: 'var(--dsw-alias-state-error-primary, #e5484d)'\n}\n\nconst switchStyle: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n fontSize: 13\n}\n\nconst toggleLinkStyle: React.CSSProperties = {\n marginTop: 6,\n padding: 0,\n border: 'none',\n background: 'none',\n color: 'var(--dsw-alias-state-business-primary, #4f8cff)',\n fontSize: 12,\n cursor: 'pointer',\n textDecoration: 'underline'\n}\n\nconst dividerStyle: React.CSSProperties = {\n margin: '8px 0',\n border: 'none',\n borderTop: '1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.3))'\n}\n\nconst sectionTitleStyle: React.CSSProperties = {\n margin: '16px 0 0',\n fontSize: 14\n}\n\nconst codeStyle: React.CSSProperties = {\n padding: '6px 8px',\n overflow: 'auto',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-all',\n fontSize: 12,\n fontFamily: 'monospace',\n background: 'var(--dsw-alias-bg-layer-1, rgba(0,0,0,0.03))',\n border: '1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.3))',\n borderRadius: 6\n}","import type {\n ClientSessionContext,\n InputTriggerCandidate,\n InputTriggerPick,\n InputTriggerSource\n} from '@deepseek-ai/dsh-client-ui-input-trigger/client'\nimport type { TemplatesController } from './templates-controller.js'\n\n/** Unique source name on the `/` trigger (the menu group title). */\nexport const TEMPLATES_SOURCE_NAME = 'better-input-templates'\n\nconst MAX_CANDIDATES = 50\n\n/**\n * The input-trigger source that inserts stored prompt templates as literal\n * text on the `/` trigger.\n *\n * - `warm()` prefetches the template list when the input box mounts, so the\n * first `/` keystroke already shows entries.\n * - `candidates()` filters by name / description / tag substring.\n * - `onPick()` returns `{ text: content }` — the trigger token span is\n * replaced by the template body, so `/name` never persists in the draft\n * and no lexicon/codec registration is needed.\n */\nexport function createTemplatesSource(controller: TemplatesController): InputTriggerSource {\n const source: InputTriggerSource = {\n trigger: '/',\n name: TEMPLATES_SOURCE_NAME,\n order: 300,\n showGroupTitle: true,\n\n async candidates(_session, req): Promise<readonly InputTriggerCandidate[]> {\n const query = req.query.trim().toLowerCase()\n const templates = controller.getSnapshot().templates\n const matched = query === ''\n ? templates\n : templates.filter((template) =>\n template.name.toLowerCase().includes(query) ||\n (template.description !== '' && template.description.toLowerCase().includes(query)) ||\n template.tags.some((tag) => tag.toLowerCase().includes(query))\n )\n return matched.slice(0, MAX_CANDIDATES).map((template) => ({\n name: template.name,\n ...(template.description === '' ? {} : { description: template.description }),\n ...(template.tags.length === 0 ? {} : { hint: template.tags.join(' / ') }),\n value: template.id\n }))\n },\n\n onPick(pick: InputTriggerPick) {\n const id = pick.candidate.value ?? ''\n const template = controller.byId(id)\n if (template === undefined) {\n return undefined\n }\n return { text: template.content }\n },\n\n warm(_session: ClientSessionContext): void {\n controller.ensureLoaded()\n }\n }\n return source\n}\n","/**\n * Client-side store for the prompt template library. Mirrors the settings\n * controller: an external-store class consumed via useSyncExternalStore,\n * one sticky initial fetch (also kicked off by the `/` trigger warm hook),\n * and optimistic list updates after save/remove so the menu and the settings\n * section stay in sync without refetching.\n */\n\nimport { useSyncExternalStore } from 'react'\nimport type { TemplateInputWire, TemplateWire } from '../remote-contract.js'\nimport type { BetterInputRemote } from '../remote.js'\n\nexport type TemplatesSnapshot = {\n readonly status: 'loading' | 'ready' | 'error'\n readonly templates: readonly TemplateWire[]\n readonly detail: string\n}\n\n/** Form state: tags stay a raw comma-separated string until save. */\nexport type TemplateDraft = {\n readonly id?: string\n readonly name: string\n readonly description: string\n readonly tags: string\n readonly content: string\n}\n\ntype Listener = () => void\n\nconst EMPTY_SNAPSHOT: TemplatesSnapshot = { status: 'loading', templates: [], detail: '' }\n\nfunction sortByRecency(templates: readonly TemplateWire[]): TemplateWire[] {\n return [...templates].sort((left, right) => right.updatedAt - left.updatedAt)\n}\n\n/** Split on ASCII and full-width commas, trim, drop empties. */\nfunction parseTags(raw: string): string[] {\n return raw\n .split(/[,,]/)\n .map((tag) => tag.trim())\n .filter((tag) => tag !== '')\n}\n\nexport class TemplatesController {\n private snapshot: TemplatesSnapshot = EMPTY_SNAPSHOT\n private readonly listeners = new Set<Listener>()\n private disposed = false\n private loadPromise: Promise<void> | undefined\n\n constructor(private readonly remote: BetterInputRemote) {}\n\n readonly getSnapshot = (): TemplatesSnapshot => this.snapshot\n\n readonly subscribe = (listener: Listener): (() => void) => {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n readonly byId = (id: string): TemplateWire | undefined =>\n this.snapshot.templates.find((template) => template.id === id)\n\n /** Kick off the one-time initial fetch; safe to call repeatedly. */\n readonly ensureLoaded = (): void => {\n if (this.loadPromise !== undefined || this.disposed) {\n return\n }\n this.loadPromise = this.refresh()\n }\n\n async refresh(): Promise<void> {\n try {\n const result = await this.remote.templatesList()\n if (this.disposed) return\n if (result.ok) {\n this.snapshot = { status: 'ready', templates: sortByRecency(result.value.templates), detail: '' }\n } else {\n this.snapshot = { status: 'error', templates: [], detail: result.error.message }\n }\n } catch (error) {\n if (this.disposed) return\n this.snapshot = { status: 'error', templates: [], detail: error instanceof Error ? error.message : String(error) }\n }\n this.emit()\n }\n\n /** Create or update one template; resolves false when the call failed. */\n async save(draft: TemplateDraft): Promise<boolean> {\n const tags = parseTags(draft.tags)\n const input: TemplateInputWire = {\n name: draft.name,\n content: draft.content,\n ...(draft.id === undefined ? {} : { id: draft.id }),\n ...(draft.description === '' ? {} : { description: draft.description }),\n ...(tags.length === 0 ? {} : { tags })\n }\n try {\n const result = await this.remote.templatesSave(input)\n if (this.disposed || !result.ok) {\n return false\n }\n const saved = result.value.template\n const rest = this.snapshot.templates.filter((template) => template.id !== saved.id)\n this.snapshot = { ...this.snapshot, status: 'ready', templates: sortByRecency([...rest, saved]) }\n this.emit()\n return true\n } catch {\n return false\n }\n }\n\n /** Remove one template; resolves false when the call failed. */\n async remove(id: string): Promise<boolean> {\n try {\n const result = await this.remote.templatesRemove(id)\n if (this.disposed || !result.ok || !result.value.removed) {\n return false\n }\n this.snapshot = { ...this.snapshot, templates: this.snapshot.templates.filter((template) => template.id !== id) }\n this.emit()\n return true\n } catch {\n return false\n }\n }\n\n dispose(): void {\n this.disposed = true\n this.listeners.clear()\n }\n\n private emit(): void {\n for (const listener of this.listeners) listener()\n }\n}\n\nexport function useTemplatesSnapshot(controller: TemplatesController): TemplatesSnapshot {\n return useSyncExternalStore(controller.subscribe, controller.getSnapshot, controller.getSnapshot)\n}\n","/**\n * Prompt template data model shared by the host store and the Typert layer.\n * A template is a plain text snippet the user stores once and later inserts\n * from the input box via the `/` trigger source.\n */\n\nexport type BetterInputTemplate = {\n readonly id: string\n readonly name: string\n readonly description: string\n readonly content: string\n readonly tags: readonly string[]\n readonly createdAt: number\n readonly updatedAt: number\n}\n\nexport type TemplateInput = {\n readonly id?: string\n readonly name: string\n readonly description?: string\n readonly content: string\n readonly tags?: readonly string[]\n}\n\nexport const MAX_TEMPLATE_COUNT = 200\nexport const MAX_TEMPLATE_NAME_LENGTH = 60\nexport const MAX_TEMPLATE_DESCRIPTION_LENGTH = 200\nexport const MAX_TEMPLATE_CONTENT_LENGTH = 8000\nexport const MAX_TEMPLATE_TAGS = 8\nexport const MAX_TEMPLATE_TAG_LENGTH = 20\n\n/** Trim, drop empties, dedupe case-insensitively, cap count and length. */\nexport function normalizeTags(tags: readonly string[]): string[] {\n const seen = new Set<string>()\n const result: string[] = []\n for (const raw of tags) {\n const tag = raw.trim()\n if (tag === '') {\n continue\n }\n const key = tag.toLowerCase()\n if (seen.has(key)) {\n continue\n }\n seen.add(key)\n result.push(tag.slice(0, MAX_TEMPLATE_TAG_LENGTH))\n if (result.length >= MAX_TEMPLATE_TAGS) {\n break\n }\n }\n return result\n}\n\nexport function validateTemplateInput(input: TemplateInput): void {\n const name = input.name.trim()\n if (name === '') {\n throw new Error('sqs-dsh-better-input template name must not be empty')\n }\n if (name.length > MAX_TEMPLATE_NAME_LENGTH) {\n throw new Error(`sqs-dsh-better-input template name must not exceed ${MAX_TEMPLATE_NAME_LENGTH} characters`)\n }\n if (input.content.trim() === '') {\n throw new Error('sqs-dsh-better-input template content must not be empty')\n }\n if (input.content.length > MAX_TEMPLATE_CONTENT_LENGTH) {\n throw new Error(`sqs-dsh-better-input template content must not exceed ${MAX_TEMPLATE_CONTENT_LENGTH} characters`)\n }\n if (input.description !== undefined && input.description.length > MAX_TEMPLATE_DESCRIPTION_LENGTH) {\n throw new Error(`sqs-dsh-better-input template description must not exceed ${MAX_TEMPLATE_DESCRIPTION_LENGTH} characters`)\n }\n}\n","/**\n * Settings section for the prompt template library: list saved templates,\n * create/edit through an inline form, and delete with a two-step confirm.\n * Mirrors the settings section conventions (framework-injected `t` + local\n * frame/field components + dsw CSS variables).\n */\n\nimport { useEffect, useState } from 'react'\nimport type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { TemplateWire } from '../remote-contract.js'\nimport { MAX_TEMPLATE_CONTENT_LENGTH, MAX_TEMPLATE_DESCRIPTION_LENGTH, MAX_TEMPLATE_NAME_LENGTH } from '../templates/model.js'\nimport { useTemplatesSnapshot } from './templates-controller.js'\nimport type { TemplateDraft, TemplatesController } from './templates-controller.js'\n\n/** The framework-injected `t` seat for the BetterInput namespace. */\ntype Translate = TranslateNS<'better-input'>\n\nexport type TemplatesSectionProps = {\n readonly close: () => void\n readonly t: Translate\n readonly templatesController: TemplatesController\n}\n\ntype EditorState = { readonly kind: 'closed' } | { readonly kind: 'open'; readonly draft: TemplateDraft }\n\nconst EMPTY_DRAFT: TemplateDraft = { name: '', description: '', tags: '', content: '' }\n\nfunction draftFromTemplate(template: TemplateWire): TemplateDraft {\n return {\n id: template.id,\n name: template.name,\n description: template.description,\n tags: [...template.tags].join(', '),\n content: template.content\n }\n}\n\nexport function TemplatesSection({ t, templatesController }: TemplatesSectionProps) {\n const snapshot = useTemplatesSnapshot(templatesController)\n const [editor, setEditor] = useState<EditorState>({ kind: 'closed' })\n const [busy, setBusy] = useState(false)\n const [actionFailed, setActionFailed] = useState(false)\n const [armedDeleteId, setArmedDeleteId] = useState<string | null>(null)\n\n // Re-fetch on mount so the section always reflects the on-disk file (the\n // `/` trigger may have warmed the same controller earlier in the session).\n useEffect(() => {\n void templatesController.refresh()\n }, [templatesController])\n\n if (snapshot.status === 'loading') {\n return (\n <SectionFrame title={t('templatesTitle')}>\n <p style={hintStyle}>{t('loading')}</p>\n </SectionFrame>\n )\n }\n if (snapshot.status === 'error') {\n return (\n <SectionFrame title={t('templatesTitle')}>\n <p style={errorStyle}>{t('templatesLoadFailed')}: {snapshot.detail}</p>\n <button type=\"button\" style={buttonStyle} onClick={() => void templatesController.refresh()}>\n {t('templatesRetry')}\n </button>\n </SectionFrame>\n )\n }\n\n const editing = editor.kind === 'open' ? editor.draft : null\n\n const saveDraft = async (): Promise<void> => {\n if (editing === null || busy) return\n if (editing.name.trim() === '' || editing.content.trim() === '') return\n setBusy(true)\n setActionFailed(false)\n const ok = await templatesController.save(editing)\n setBusy(false)\n if (ok) {\n setEditor({ kind: 'closed' })\n } else {\n setActionFailed(true)\n }\n }\n\n return (\n <SectionFrame title={t('templatesTitle')}>\n <p style={hintStyle}>{t('templatesDescription')}</p>\n {actionFailed ? <p style={errorStyle}>{t('templatesActionFailed')}</p> : null}\n {editing === null ? (\n <button\n type=\"button\"\n style={buttonStyle}\n onClick={() => {\n setActionFailed(false)\n setArmedDeleteId(null)\n setEditor({ kind: 'open', draft: EMPTY_DRAFT })\n }}\n >\n {t('templatesNew')}\n </button>\n ) : (\n <div style={editorStyle}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>\n <span style={labelStyle}>{t('templatesNameLabel')}</span>\n <input\n value={editing.name}\n maxLength={MAX_TEMPLATE_NAME_LENGTH}\n placeholder={t('templatesNamePlaceholder')}\n onChange={(event) => setEditor({ kind: 'open', draft: { ...editing, name: event.target.value } })}\n style={inputStyle}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>\n <span style={labelStyle}>{t('templatesDescriptionLabel')}</span>\n <input\n value={editing.description}\n maxLength={MAX_TEMPLATE_DESCRIPTION_LENGTH}\n placeholder={t('templatesDescriptionPlaceholder')}\n onChange={(event) => setEditor({ kind: 'open', draft: { ...editing, description: event.target.value } })}\n style={inputStyle}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>\n <span style={labelStyle}>{t('templatesTagsLabel')}</span>\n <input\n value={editing.tags}\n placeholder={t('templatesTagsHint')}\n onChange={(event) => setEditor({ kind: 'open', draft: { ...editing, tags: event.target.value } })}\n style={inputStyle}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>\n <span style={labelStyle}>{t('templatesContentLabel')}</span>\n <textarea\n value={editing.content}\n rows={6}\n maxLength={MAX_TEMPLATE_CONTENT_LENGTH}\n placeholder={t('templatesContentPlaceholder')}\n onChange={(event) => setEditor({ kind: 'open', draft: { ...editing, content: event.target.value } })}\n style={{ ...inputStyle, resize: 'vertical', fontFamily: 'monospace' }}\n />\n <span style={hintStyle}>{editing.content.length} / {MAX_TEMPLATE_CONTENT_LENGTH}</span>\n </label>\n <div style={{ display: 'flex', gap: 8 }}>\n <button\n type=\"button\"\n style={buttonStyle}\n disabled={busy || editing.name.trim() === '' || editing.content.trim() === ''}\n onClick={() => void saveDraft()}\n >\n {t('templatesSave')}\n </button>\n <button\n type=\"button\"\n style={buttonStyle}\n disabled={busy}\n onClick={() => {\n setEditor({ kind: 'closed' })\n setActionFailed(false)\n }}\n >\n {t('templatesCancel')}\n </button>\n </div>\n </div>\n )}\n {snapshot.templates.length === 0 ? <p style={hintStyle}>{t('templatesEmpty')}</p> : null}\n {snapshot.templates.map((template) => (\n <div key={template.id} style={cardStyle}>\n <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 8 }}>\n <strong style={{ fontSize: 13 }}>{template.name}</strong>\n <span style={hintStyle}>{new Date(template.updatedAt).toLocaleDateString()}</span>\n </div>\n {template.description !== '' ? <p style={hintStyle}>{template.description}</p> : null}\n <p style={previewStyle}>\n {template.content.length > 120 ? `${template.content.slice(0, 120)}…` : template.content}\n </p>\n {template.tags.length > 0 ? (\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>\n {template.tags.map((tag) => (\n <span key={tag} style={tagStyle}>{tag}</span>\n ))}\n </div>\n ) : null}\n <div style={{ display: 'flex', gap: 8 }}>\n <button\n type=\"button\"\n style={buttonStyle}\n onClick={() => {\n setActionFailed(false)\n setArmedDeleteId(null)\n setEditor({ kind: 'open', draft: draftFromTemplate(template) })\n }}\n >\n {t('templatesEdit')}\n </button>\n <button\n type=\"button\"\n style={armedDeleteId === template.id ? deleteArmedStyle : buttonStyle}\n onClick={() => {\n if (armedDeleteId !== template.id) {\n setArmedDeleteId(template.id)\n return\n }\n setArmedDeleteId(null)\n void templatesController.remove(template.id).then((ok) => {\n if (!ok) setActionFailed(true)\n })\n }}\n >\n {armedDeleteId === template.id ? t('templatesDeleteConfirm') : t('templatesDelete')}\n </button>\n </div>\n </div>\n ))}\n </SectionFrame>\n )\n}\n\nfunction SectionFrame({ title, children }: { title: string; children: React.ReactNode }) {\n return (\n <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 12 }}>\n <h2 style={{ margin: 0, fontSize: 16 }}>{title}</h2>\n {children}\n </div>\n )\n}\n\nconst editorStyle: React.CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: 8,\n padding: 12,\n border: '1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.4))',\n borderRadius: 6,\n background: 'var(--dsw-alias-bg-layer-1, rgba(0,0,0,0.03))'\n}\n\nconst cardStyle: React.CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: 6,\n padding: 12,\n border: '1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.3))',\n borderRadius: 6\n}\n\nconst previewStyle: React.CSSProperties = {\n margin: 0,\n fontSize: 12,\n fontFamily: 'monospace',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-all',\n opacity: 0.8\n}\n\nconst tagStyle: React.CSSProperties = {\n padding: '1px 6px',\n fontSize: 11,\n borderRadius: 4,\n border: '1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.3))',\n opacity: 0.85\n}\n\nconst labelStyle: React.CSSProperties = {\n fontSize: 13,\n fontWeight: 600\n}\n\nconst buttonStyle: React.CSSProperties = {\n width: 'fit-content',\n padding: '6px 12px',\n borderRadius: 6,\n border: '1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.4))',\n background: 'var(--dsh-color-surface, transparent)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n fontSize: 13,\n cursor: 'pointer'\n}\n\nconst deleteArmedStyle: React.CSSProperties = {\n ...buttonStyle,\n borderColor: 'var(--dsw-alias-state-error-primary, #e5484d)',\n color: 'var(--dsw-alias-state-error-primary, #e5484d)'\n}\n\nconst inputStyle: React.CSSProperties = {\n padding: '6px 8px',\n borderRadius: 6,\n border: '1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.4))',\n background: 'var(--dsw-alias-bg-layer-1, #f9f9f9)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n fontSize: 13\n}\n\nconst hintStyle: React.CSSProperties = {\n margin: 0,\n fontSize: 12,\n opacity: 0.7\n}\n\nconst errorStyle: React.CSSProperties = {\n margin: 0,\n fontSize: 12,\n color: 'var(--dsw-alias-state-error-primary, #e5484d)'\n}\n","import type { Context as ClientContext } from '@deepseek-ai/cordis'\n// Loads the conversation SlotMap augmentation (registers\n// 'conversation.input.right' / 'conversation.input.dock' slot keys).\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\n// Loads the settings SlotMap augmentation ('settings.section').\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\n// Activates the `ctx.inputTriggers` service augmentation (module-level side effect).\nimport type {} from '@deepseek-ai/dsh-client-ui-input-trigger/client'\nimport { TYPERT_REMOTE } from '../remote.js'\nimport type { BetterInputRemote } from '../remote.js'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport { BETTER_INPUT_NS, en, zh } from './strings.js'\nimport { MicrophoneButton, type SettingsFace } from './MicrophoneButton.js'\nimport { OptimizeButton } from './OptimizeButton.js'\nimport { VoiceRecognitionBar } from './VoiceRecognitionBar.js'\nimport { BetterInputSettingsSection } from './settings.jsx'\nimport { SettingsController, useSettingsSnapshot } from './settings-controller.js'\nimport { createTemplatesSource } from './templates-source.js'\nimport { TemplatesController } from './templates-controller.js'\nimport { TemplatesSection } from './templates-section.jsx'\nimport { VoiceInputSession } from './voice-session.js'\n\nconst PULSE_KEYFRAMES = `@keyframes sqs-dsh-better-input-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.3; }\n}`\n\n/**\n * Required Client services: the slot registry, the Typert remote hub, and\n * the DSH locale runtime. `remote.betterInput` is mounted by this plugin's\n * own apply() via `ctx.remote.$mount`, so it MUST NOT appear here — the\n * outer inject gates plugin activation and would deadlock waiting for\n * itself. It is declared only on the inner ctx.inject() below, which runs\n * after the mount. Settings reach the browser through `SettingsScopeBinder`\n * (provided by `@deepseek-ai/dsh-client-ui-settings`) and are read inside\n * the settings section slot itself, not via a top-level `settings` service\n * here.\n */\nexport const inject = ['slots', 'remote', 'locale', 'inputTriggers', 'conversation']\n\nexport async function apply(ctx: ClientContext): Promise<() => Promise<void>> {\n const disposeRemote = await ctx.remote.$mount(TYPERT_REMOTE)\n // Register our bilingual dictionary with the DSH locale runtime BEFORE any\n // slot renders, so the injected `t` seat never hits a missing namespace.\n const disposeLocaleDicts = ctx.locale.register(BETTER_INPUT_NS, { zh, en })\n await ctx.inject(['slots', 'remote', 'remote.betterInput', 'inputTriggers', 'conversation'], async (remoteCtx) => {\n const remote = remoteCtx.remote.betterInput as BetterInputRemote\n const controller = new SettingsController(remote)\n const templatesController = new TemplatesController(remote)\n\n const voiceSessions = new Map<string, VoiceInputSession>()\n const voiceSessionFor = (sessionId: string): VoiceInputSession => {\n let session = voiceSessions.get(sessionId)\n if (session === undefined) {\n session = new VoiceInputSession()\n voiceSessions.set(sessionId, session)\n }\n return session\n }\n\n // Prompt template library: the `/` trigger source and the settings section\n // share one controller so both see the same optimistic updates.\n const disposeTemplatesSource = remoteCtx.inputTriggers.registerSource(createTemplatesSource(templatesController))\n\n remoteCtx.effect(() => () => {\n for (const session of voiceSessions.values()) session.dispose()\n voiceSessions.clear()\n disposeTemplatesSource()\n controller.dispose()\n templatesController.dispose()\n }, 'sqs-dsh-better-input sessions lifecycle')\n\n // Inject the keyframes used by the recognition bar pulse.\n remoteCtx.effect(() => {\n const styleTag = document.createElement('style')\n styleTag.dataset.plugin = 'sqs-dsh-better-input'\n styleTag.textContent = PULSE_KEYFRAMES\n document.head.appendChild(styleTag)\n return () => {\n styleTag.remove()\n }\n }, 'sqs-dsh-better-input styles')\n\n void controller.refreshSettings()\n void controller.refreshRoutes()\n void templatesController.ensureLoaded()\n\n const useSettings = (): SettingsFace => {\n const snapshot = useSettingsSnapshot(controller)\n if (snapshot.status !== 'ready') return { status: 'loading', settings: snapshot.view.settings }\n return { status: 'ready', settings: snapshot.view.settings }\n }\n\n // Recognition bar stays in `dock` (above the composer card, the\n // horizontal status strip) — unchanged placement.\n remoteCtx.slots.inject('conversation.input.dock', () =>\n remoteCtx.slots.register(\n {\n name: 'conversation.input.dock',\n id: 'better-input-recognition-bar',\n order: 15,\n locale: BETTER_INPUT_NS,\n inject: (sessionId) => ({ voiceSession: voiceSessionFor(sessionId) })\n },\n VoiceRecognitionBar\n )\n )\n\n // The sparkle (prompt-optimize) button sits inline inside the\n // `conversation.input.right` toolbar, immediately to the left of the\n // microphone. order = 9998 places it one slot before the mic (9999),\n // which is the rightmost edge of the public right slot — the model\n // picker and send button follow in their own, non-slot seats.\n remoteCtx.slots.inject('conversation.input.right', () =>\n remoteCtx.slots.register(\n {\n name: 'conversation.input.right',\n id: 'better-input-optimize',\n order: 9998,\n locale: BETTER_INPUT_NS,\n inject: () => ({\n remote,\n useSettings\n })\n },\n OptimizeButton\n )\n )\n\n // Microphone is the LAST registered entry in the public\n // `conversation.input.right` list, so it sits immediately right of the\n // sparkle and immediately left of DSH's built-in model-select seat.\n remoteCtx.slots.inject('conversation.input.right', () =>\n remoteCtx.slots.register(\n {\n name: 'conversation.input.right',\n id: 'better-input-voice',\n order: 9999,\n locale: BETTER_INPUT_NS,\n inject: (sessionId) => ({\n remote,\n voiceSession: voiceSessionFor(sessionId),\n useSettings\n })\n },\n MicrophoneButton\n )\n )\n\n remoteCtx.slots.inject('settings.section', () =>\n remoteCtx.slots.register(\n {\n name: 'settings.section',\n id: 'sqs-dsh-better-input',\n order: 16,\n // Thunk so the sidebar row follows the active locale on switches.\n label: () => ctx.locale.bind(BETTER_INPUT_NS)('settingsTitle'),\n locale: BETTER_INPUT_NS,\n inject: () => ({ settingsController: controller })\n },\n BetterInputSettingsSection\n )\n )\n\n // Prompt template library management (list/create/edit/delete), right\n // under the main BetterInput settings section.\n remoteCtx.slots.inject('settings.section', () =>\n remoteCtx.slots.register(\n {\n name: 'settings.section',\n id: 'sqs-dsh-better-input-templates',\n order: 17,\n label: () => ctx.locale.bind(BETTER_INPUT_NS)('templatesTitle'),\n locale: BETTER_INPUT_NS,\n inject: () => ({ templatesController })\n },\n TemplatesSection\n )\n )\n\n return () => {\n // Slots and effects are disposed through their own fiber.\n }\n })\n\n return async () => {\n disposeLocaleDicts()\n await disposeRemote()\n }\n}\n"],"mappings":"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"}
|
package/lib/config.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared constants and browser-side helpers for sqs-dsh-better-input.
|
|
3
|
+
* Voice input through the browser Web Speech API, plus Host-side
|
|
4
|
+
* AI polishing of transcripts and prompt optimization.
|
|
5
|
+
*/
|
|
6
|
+
export declare const SETTINGS_NAMESPACE = "sqs-dsh-better-input";
|
|
7
|
+
/** Recording is capped to avoid an abandoned session holding the mic forever. */
|
|
8
|
+
export declare const DEFAULT_MAX_RECORDING_SECONDS = 120;
|
|
9
|
+
export declare const MAX_POLISH_PROMPT_LENGTH = 4000;
|
|
10
|
+
export declare const MAX_OPTIMIZE_PROMPT_LENGTH = 4000;
|
|
11
|
+
export declare const MAX_TRANSCRIPT_CHARACTERS = 12000;
|
|
12
|
+
export declare const MAX_OPTIMIZE_CHARACTERS = 12000;
|
|
13
|
+
export declare const MAX_POLISHED_CHARACTERS = 24000;
|
|
14
|
+
export declare const MAX_OPTIMIZED_CHARACTERS = 24000;
|
|
15
|
+
export declare const POLISH_TIMEOUT_MS = 20000;
|
|
16
|
+
export declare const OPTIMIZE_TIMEOUT_MS = 20000;
|
|
17
|
+
export interface BetterInputSettings {
|
|
18
|
+
/** Recognition language, empty follows the dsh UI locale. */
|
|
19
|
+
language: string;
|
|
20
|
+
/** Recording limit in seconds. */
|
|
21
|
+
maxRecordingSeconds: number;
|
|
22
|
+
/** Enable Host LLM polishing after the transcript lands in the draft. */
|
|
23
|
+
polishingEnabled: boolean;
|
|
24
|
+
/** dsh polish provider id (a route already registered in dsh). */
|
|
25
|
+
polishProvider: string;
|
|
26
|
+
/** dsh polish model id. */
|
|
27
|
+
polishModel: string;
|
|
28
|
+
/** Selected reasoning effort id for polish, empty uses the adapter's default (usually the lightest). */
|
|
29
|
+
polishReasoningEffort: string;
|
|
30
|
+
/** Custom polish system prompt, empty for the built-in one. */
|
|
31
|
+
polishPrompt: string;
|
|
32
|
+
/** Enable prompt optimization through the Host LLM. */
|
|
33
|
+
optimizeEnabled: boolean;
|
|
34
|
+
/** dsh optimize provider id (reuses the same route pool as polish). */
|
|
35
|
+
optimizeProvider: string;
|
|
36
|
+
/** dsh optimize model id. */
|
|
37
|
+
optimizeModel: string;
|
|
38
|
+
/** Selected reasoning effort id for optimize, empty uses the adapter's default (usually the lightest). */
|
|
39
|
+
optimizeReasoningEffort: string;
|
|
40
|
+
/** Custom optimize system prompt, empty for the built-in one. */
|
|
41
|
+
optimizePrompt: string;
|
|
42
|
+
/** Number of recent conversation turns to include as context for optimization. 0 disables context. */
|
|
43
|
+
contextTurns: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Out-of-the-box defaults: every toggle ON so new users get the full
|
|
47
|
+
* experience immediately; reasoning effort left empty, which the Host
|
|
48
|
+
* translates to "thinking off" (the model's `off` tier when it exposes
|
|
49
|
+
* one, otherwise the adapter's own default).
|
|
50
|
+
* Provider/model stay empty and get auto-filled on first settings page
|
|
51
|
+
* load via SettingsController (first route returned by listRoutes).
|
|
52
|
+
*/
|
|
53
|
+
export declare const DEFAULT_SETTINGS: BetterInputSettings;
|
|
54
|
+
export type BetterInputSettingsPatch = Partial<BetterInputSettings>;
|
|
55
|
+
/** One selectable reasoning effort tier for a specific model route. */
|
|
56
|
+
export interface ReasoningEffortInfo {
|
|
57
|
+
/** Stable id passed to `LlmCallConfig.reasoningEffort`. */
|
|
58
|
+
readonly id: string;
|
|
59
|
+
/** Display name shown in the settings dropdown. */
|
|
60
|
+
readonly name: string;
|
|
61
|
+
/** Optional longer description shown in a tooltip. */
|
|
62
|
+
readonly description?: string;
|
|
63
|
+
}
|
|
64
|
+
/** A usable (provider, model) pair returned by dsh's LLM runtime, plus any
|
|
65
|
+
* reasoning-effort tiers the model reports as selectable. The efforts
|
|
66
|
+
* list is empty when the adapter / model does not expose thinking
|
|
67
|
+
* controls — in that case the settings dropdown is hidden entirely.
|
|
68
|
+
* `defaultEffort` is the adapter-configured baseline (generally the
|
|
69
|
+
* lightest tier); we use it as the placeholder label in the UI and as
|
|
70
|
+
* the fallback when the stored effort string is empty.
|
|
71
|
+
*/
|
|
72
|
+
export interface PolishRoute {
|
|
73
|
+
readonly provider: string;
|
|
74
|
+
readonly providerName: string;
|
|
75
|
+
readonly model: string;
|
|
76
|
+
readonly modelName: string;
|
|
77
|
+
readonly reasoningEfforts: readonly ReasoningEffortInfo[];
|
|
78
|
+
readonly defaultReasoningEffort?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface BetterInputSettingsView {
|
|
81
|
+
available: boolean;
|
|
82
|
+
writable: boolean;
|
|
83
|
+
settings: BetterInputSettings;
|
|
84
|
+
overridden: string[];
|
|
85
|
+
/** The built-in polish system prompt, shown in the settings page. */
|
|
86
|
+
defaultPolishPrompt: string;
|
|
87
|
+
/** The built-in optimize system prompt, shown in the settings page. */
|
|
88
|
+
defaultOptimizePrompt: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Recognition language derived from the browser locale. An empty stored
|
|
92
|
+
* language follows the UI.
|
|
93
|
+
*/
|
|
94
|
+
export declare function recognitionLanguageFromBrowser(): string;
|
|
95
|
+
export declare function effectiveRecognitionLanguage(stored: string): string;
|
|
96
|
+
export declare function isValidRecordingLimit(value: number): boolean;
|
|
97
|
+
export declare function isValidContextTurns(value: number): boolean;
|
|
98
|
+
export declare function validateSettings(settings: BetterInputSettings): void;
|
|
99
|
+
/** Resolve the effective recording cap from stored settings. */
|
|
100
|
+
export declare function effectiveRecordingSeconds(settings: Pick<BetterInputSettings, 'maxRecordingSeconds'>): number;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/identity.ts
|
|
2
|
+
/**
|
|
3
|
+
* Single source of truth for this package's identity.
|
|
4
|
+
*
|
|
5
|
+
* Every externally visible name (the Typert package key, the npm package name
|
|
6
|
+
* used by the update check, the settings namespace) derives from here so a
|
|
7
|
+
* rename never leaves a stale literal behind.
|
|
8
|
+
*/
|
|
9
|
+
/** Stable identifier for this fork. Used as the Typert package key. */
|
|
10
|
+
const PACKAGE_NAME = "sqs-dsh-better-input";
|
|
11
|
+
/** Repository for this fork. */
|
|
12
|
+
const REPOSITORY_URL = "https://github.com/sanqianshuang/sqs-dsh-better-input";
|
|
13
|
+
/** npm scope owner; only used to build the fallback slug when a URL is unparseable. */
|
|
14
|
+
const NPM_SCOPE = "sanqianshuang";
|
|
15
|
+
//#endregion
|
|
16
|
+
export { PACKAGE_NAME as n, REPOSITORY_URL as r, NPM_SCOPE as t };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=identity-CzaR1Taa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-CzaR1Taa.js","names":[],"sources":["../src/identity.ts"],"sourcesContent":["/**\n * Single source of truth for this package's identity.\n *\n * Every externally visible name (the Typert package key, the npm package name\n * used by the update check, the settings namespace) derives from here so a\n * rename never leaves a stale literal behind.\n */\n\n/** Stable identifier for this fork. Used as the Typert package key. */\nexport const PACKAGE_NAME = 'sqs-dsh-better-input'\n\n/** Author of this secondary development. */\nexport const AUTHOR = 'sanqianshuang'\n\n/** Repository for this fork. */\nexport const REPOSITORY_URL = 'https://github.com/sanqianshuang/sqs-dsh-better-input'\n\n/** npm scope owner; only used to build the fallback slug when a URL is unparseable. */\nexport const NPM_SCOPE = 'sanqianshuang'\n\n/** License inherited from the upstream MIT project. */\nexport const LICENSE = 'MIT'\n\n/**\n * Upstream attribution. This is a secondary development of the MIT-licensed\n * `dsh-better-input` project; the original copyright notice and license text\n * are retained in LICENSE as the MIT terms require.\n */\nexport const UPSTREAM_NAME = 'dsh-better-input'\nexport const UPSTREAM_URL = 'https://github.com/DIAG5/dsh-better-input'\n"],"mappings":";;;;;;;;;AASA,MAAa,eAAe;;AAM5B,MAAa,iBAAiB;;AAG9B,MAAa,YAAY"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for this package's identity.
|
|
3
|
+
*
|
|
4
|
+
* Every externally visible name (the Typert package key, the npm package name
|
|
5
|
+
* used by the update check, the settings namespace) derives from here so a
|
|
6
|
+
* rename never leaves a stale literal behind.
|
|
7
|
+
*/
|
|
8
|
+
/** Stable identifier for this fork. Used as the Typert package key. */
|
|
9
|
+
export declare const PACKAGE_NAME = "sqs-dsh-better-input";
|
|
10
|
+
/** Author of this secondary development. */
|
|
11
|
+
export declare const AUTHOR = "sanqianshuang";
|
|
12
|
+
/** Repository for this fork. */
|
|
13
|
+
export declare const REPOSITORY_URL = "https://github.com/sanqianshuang/sqs-dsh-better-input";
|
|
14
|
+
/** npm scope owner; only used to build the fallback slug when a URL is unparseable. */
|
|
15
|
+
export declare const NPM_SCOPE = "sanqianshuang";
|
|
16
|
+
/** License inherited from the upstream MIT project. */
|
|
17
|
+
export declare const LICENSE = "MIT";
|
|
18
|
+
/**
|
|
19
|
+
* Upstream attribution. This is a secondary development of the MIT-licensed
|
|
20
|
+
* `dsh-better-input` project; the original copyright notice and license text
|
|
21
|
+
* are retained in LICENSE as the MIT terms require.
|
|
22
|
+
*/
|
|
23
|
+
export declare const UPSTREAM_NAME = "dsh-better-input";
|
|
24
|
+
export declare const UPSTREAM_URL = "https://github.com/DIAG5/dsh-better-input";
|