dsh-speak 1.7.0 → 1.7.1

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.
Files changed (2) hide show
  1. package/client/client.js +25 -0
  2. package/package.json +1 -1
package/client/client.js CHANGED
@@ -45,6 +45,8 @@ window.__ModuleLoader__.load({
45
45
  replayFullReadHint: '手动重播时跳过超长文本的标题截断,完整朗读。',
46
46
  queueAllMessages: '入队所有消息',
47
47
  queueAllMessagesHint: '每一条 assistant 消息到达即入队朗读(中间消息也读,FIFO),而不只读最终回复。',
48
+ throttleMs: '合并延迟(毫秒)',
49
+ throttleMsHint: '回复文本等待多久才播报(合并同一回复的多步消息)。',
48
50
  cleanMarkdown: '清理 Markdown',
49
51
  cleanMarkdownHint: '把 Markdown 转成自然的语音文本。',
50
52
  markdownCleaning: 'Markdown 清理',
@@ -61,6 +63,12 @@ window.__ModuleLoader__.load({
61
63
  codeBlockReplacementTextHint: '代码块被替换时朗读的文本。',
62
64
  maxChars: '最大朗读字数',
63
65
  maxCharsHint: 'macOS 上 0 = 不限;Windows 保留安全默认值。',
66
+ volume: '音量',
67
+ volumeHint: '仅 Windows(0-100);macOS 音量跟随系统。',
68
+ rate: '语速',
69
+ rateHint: '0 = 引擎默认(Windows SAPI 刻度 / macOS words-per-minute)。',
70
+ engine: '引擎路径',
71
+ engineHint: '自定义引擎脚本路径;留空自动解析(包内引擎 → ~/.dsh/hooks)。',
64
72
  longTextBehavior: '超长文本行为',
65
73
  longTextBehaviorHint: '超过正数上限时如何处理。',
66
74
  longTextMessageOption: '朗读替换提示语',
@@ -69,6 +77,8 @@ window.__ModuleLoader__.load({
69
77
  fixedPromptHint: '超长文本(message 模式)时朗读的提示语。',
70
78
  announceApprovals: '播报审批',
71
79
  announceApprovalsHint: '朗读审批请求。',
80
+ stripApprovalPrefix: '剥离审批前缀',
81
+ stripApprovalPrefixHint: '剥离审批原因里的固定英文模板前缀(escalate sandbox to …: )。',
72
82
  announceQuestions: '播报提问',
73
83
  announceQuestionsHint: '朗读 ask_user_question 问题。',
74
84
  questionGap: '问题间隔(毫秒)',
@@ -102,6 +112,8 @@ window.__ModuleLoader__.load({
102
112
  replayFullReadHint: 'When replaying, read the full text instead of the heading fallback.',
103
113
  queueAllMessages: 'Queue All Messages',
104
114
  queueAllMessagesHint: 'Also speaks intermediate assistant messages in a FIFO queue, not only the final reply.',
115
+ throttleMs: 'Merge Delay (ms)',
116
+ throttleMsHint: 'How long a reply waits before being announced (merges multi-step messages).',
105
117
  cleanMarkdown: 'Clean Markdown Formatting',
106
118
  cleanMarkdownHint: 'Converts Markdown into natural speech text.',
107
119
  markdownCleaning: 'Markdown cleaning',
@@ -118,6 +130,12 @@ window.__ModuleLoader__.load({
118
130
  codeBlockReplacementTextHint: 'Used when a code block is replaced.',
119
131
  maxChars: 'Max Speech Characters',
120
132
  maxCharsHint: '0 is unlimited on macOS; Windows keeps its safe default.',
133
+ volume: 'Volume',
134
+ volumeHint: 'Windows only (0-100); macOS volume follows the system.',
135
+ rate: 'Speech Rate',
136
+ rateHint: '0 = engine default (Windows SAPI scale / macOS words-per-minute).',
137
+ engine: 'Engine Path',
138
+ engineHint: 'Custom engine script path; empty = auto-resolve (package engine → ~/.dsh/hooks).',
121
139
  longTextBehavior: 'Long Text Behavior',
122
140
  longTextBehaviorHint: 'When a positive maximum is exceeded.',
123
141
  longTextMessageOption: 'Read replacement message',
@@ -126,6 +144,8 @@ window.__ModuleLoader__.load({
126
144
  fixedPromptHint: 'The prompt spoken when the text is too long (message mode).',
127
145
  announceApprovals: 'Announce Approvals',
128
146
  announceApprovalsHint: 'Announces approval requests.',
147
+ stripApprovalPrefix: 'Strip Approval Prefix',
148
+ stripApprovalPrefixHint: 'Strip the fixed English template prefix (escalate sandbox to …:) from approval reasons.',
129
149
  announceQuestions: 'Announce Questions',
130
150
  announceQuestionsHint: 'Announces ask-user questions.',
131
151
  questionGap: 'Question Gap (ms)',
@@ -275,11 +295,16 @@ window.__ModuleLoader__.load({
275
295
  e(Toggle, { label: t('automaticSpeech'), value: value.automaticSpeech !== false, disabled, onChange: next => set('automaticSpeech', next), hint: t('automaticSpeechHint') }),
276
296
  e(Toggle, { label: t('replayFullRead'), value: value.replayFullRead === true, disabled, onChange: next => set('replayFullRead', next), hint: t('replayFullReadHint') }),
277
297
  e(Toggle, { label: t('queueAllMessages'), value: value.queueAllMessages === true, disabled: disabled || value.automaticSpeech === false, onChange: next => set('queueAllMessages', next), hint: t('queueAllMessagesHint') }),
298
+ e(SettingInput, { label: t('throttleMs'), value: value.throttleMs == null ? 1500 : value.throttleMs, numeric: true, disabled, onChange: next => { if (/^\d+$/.test(next)) set('throttleMs', Number(next)) }, hint: t('throttleMsHint') }),
278
299
  e(Toggle, { label: t('cleanMarkdown'), value: clean, disabled, onChange: next => set('cleanMarkdownFormatting', next), hint: t('cleanMarkdownHint') }), e(MarkdownCleaning, { value, clean, disabled, set }),
279
300
  e(SettingInput, { label: t('maxChars'), value: value.maxChars == null ? 0 : value.maxChars, numeric: true, disabled, onChange: next => { if (/^\d+$/.test(next)) set('maxChars', Number(next)) }, hint: t('maxCharsHint') }),
301
+ e(SettingInput, { label: t('volume'), value: value.volume == null ? 50 : value.volume, numeric: true, disabled, onChange: next => { if (/^\d+$/.test(next)) set('volume', Number(next)) }, hint: t('volumeHint') }),
302
+ e(SettingInput, { label: t('rate'), value: value.rate == null ? 0 : value.rate, numeric: true, disabled, onChange: next => { if (/^-?\d*\.?\d*$/.test(next)) set('rate', Number(next)) }, hint: t('rateHint') }),
303
+ e(SettingInput, { label: t('engine'), value: value.engine || '', disabled, onChange: next => set('engine', next), hint: t('engineHint') }),
280
304
  e(Options, { label: t('longTextBehavior'), value: value.longTextMode || 'message', disabled, onChange: next => set('longTextMode', next), hint: t('longTextBehaviorHint'), options: [{ value: 'message', label: t('longTextMessageOption') }, { value: 'heading', label: t('longTextHeadingOption') }] }),
281
305
  e(SettingInput, { label: t('fixedPrompt'), value: value.longTextMessage || '本次播报内容较长,请自行阅读。', disabled: disabled || value.longTextMode !== 'message', onChange: next => set('longTextMessage', next), hint: t('fixedPromptHint') }),
282
306
  e(Toggle, { label: t('announceApprovals'), value: value.announceApprovals !== false, disabled, onChange: next => set('announceApprovals', next), hint: t('announceApprovalsHint') }),
307
+ e(Toggle, { label: t('stripApprovalPrefix'), value: value.stripApprovalPrefix !== false, disabled: disabled || value.announceApprovals === false, onChange: next => set('stripApprovalPrefix', next), hint: t('stripApprovalPrefixHint') }),
283
308
  e(Toggle, { label: t('announceQuestions'), value: value.announceQuestions !== false, disabled, onChange: next => set('announceQuestions', next), hint: t('announceQuestionsHint') }),
284
309
  e(SettingInput, { label: t('questionGap'), value: value.questionGapMs == null ? 2000 : value.questionGapMs, numeric: true, disabled: disabled || value.announceQuestions === false, onChange: next => { if (/^\d+$/.test(next)) set('questionGapMs', Number(next)) }, hint: t('questionGapHint') }),
285
310
  e(DisclosureRow, { icon: null, title: t('optionalEvents'), open: eventsOpen, expandable: true, onToggle: () => setEventsOpen(!eventsOpen), expandOnRowClick: true }, e('div', { style: { paddingLeft: '22px' } },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-speak",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "Make your AI harness speak — voice announcements for DSH and other AI coding harnesses (Windows SAPI5 + macOS system voices)",
5
5
  "main": "adapters/dsh/speech-hook.js",
6
6
  "exports": {