dsh-dafeiyu-emotion 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.2
4
+
5
+ - Added `ttsOnlyAfterVoice` (default `true`): spoken replies are limited to assistant messages within two minutes of a voice input, so normal coding chats do not read every answer aloud.
6
+ - Added the matching settings toggle.
7
+
3
8
  ## 0.3.1
4
9
 
5
10
  - Added spoken assistant replies. The host now forwards `assistant/message` text over `/plugins/dsh-dafeiyu-emotion/events`; the client plays it with TTS.
package/README.md CHANGED
@@ -116,9 +116,9 @@ dsh plugin --profile desktop add github:LiDu-china/dsh-dafeiyu-emotion
116
116
  ### 通过 Release tarball
117
117
 
118
118
  ```bash
119
- curl -L -o dsh-dafeiyu-emotion-0.3.1.tgz \
120
- https://github.com/LiDu-china/dsh-dafeiyu-emotion/releases/download/v0.3.1/dsh-dafeiyu-emotion-0.3.1.tgz
121
- dsh plugin --profile desktop add "D:/path/to/dsh-dafeiyu-emotion-0.3.1.tgz"
119
+ curl -L -o dsh-dafeiyu-emotion-0.3.2.tgz \
120
+ https://github.com/LiDu-china/dsh-dafeiyu-emotion/releases/download/v0.3.2/dsh-dafeiyu-emotion-0.3.2.tgz
121
+ dsh plugin --profile desktop add "D:/path/to/dsh-dafeiyu-emotion-0.3.2.tgz"
122
122
  ```
123
123
 
124
124
  > DSH Desktop 的 profile 由 Electron 应用管理;命令行安装请使用桌面应用自带的 `dsh` 命令。
@@ -213,6 +213,7 @@ python -m pip install piper-tts
213
213
  | `language` | `zh` | 识别语言:`zh` / `en` / `auto` |
214
214
  | `empathyStyle` | `gentle` | 共情策略:`gentle` / `direct` / `humorous` / `concise` |
215
215
  | `ttsEnabled` | `true` | 是否朗读大肥鱼回复 |
216
+ | `ttsOnlyAfterVoice` | `true` | 只朗读录音后两分钟内的回复 |
216
217
  | `ttsEngine` | `piper` | `piper` 本地 / `edge` 在线 / `browser` 系统语音 |
217
218
  | `ttsVoice` | `zh-CN-XiaoyiNeural` | Edge TTS 音色 |
218
219
  | `ttsRate` | `+6%` | Piper/Edge 语速 |
package/cordis.patch.yml CHANGED
@@ -30,6 +30,7 @@
30
30
  language: zh
31
31
  empathyStyle: gentle
32
32
  ttsEnabled: true
33
+ ttsOnlyAfterVoice: true
33
34
  ttsEngine: piper
34
35
  ttsVoice: zh-CN-XiaoyiNeural
35
36
  ttsRate: "+6%"
@@ -72,7 +72,7 @@ https://github.com/LiDu-china/dsh-dafeiyu-emotion/releases/download/v0.2.3/dsh-d
72
72
  dsh plugin --profile desktop add dsh-dafeiyu-emotion
73
73
  ```
74
74
 
75
- Published as `dsh-dafeiyu-emotion@0.3.1` on npm. The 1024Store entry refreshes its one-click install automatically. GitHub-source and Release-tarball installs remain available as fallbacks.
75
+ Published as `dsh-dafeiyu-emotion@0.3.2` on npm. The 1024Store entry refreshes its one-click install automatically. GitHub-source and Release-tarball installs remain available as fallbacks.
76
76
 
77
77
  ## Privacy
78
78
 
@@ -0,0 +1,15 @@
1
+ ## 0.3.2
2
+
3
+ 语音回复的体验收口。
4
+
5
+ - 新增 `ttsOnlyAfterVoice`,默认开启:只在录音后两分钟内的助手回复朗读。
6
+ - 普通代码对话、没有录音触发的回复不再自动朗读。
7
+ - 设置页新增「只朗读语音触发的回复」开关。
8
+
9
+ ## 安装
10
+
11
+ ```bash
12
+ dsh plugin --profile desktop add dsh-dafeiyu-emotion
13
+ ```
14
+
15
+ 升级后请完全退出并重新启动 the agent harness。
package/lib/client.js CHANGED
@@ -826,6 +826,7 @@ window.__ModuleLoader__.load({
826
826
  || draft.language !== config.language
827
827
  || draft.empathyStyle !== config.empathyStyle
828
828
  || draft.ttsEnabled !== config.ttsEnabled
829
+ || draft.ttsOnlyAfterVoice !== config.ttsOnlyAfterVoice
829
830
  || draft.ttsEngine !== config.ttsEngine
830
831
  || draft.ttsVoice !== config.ttsVoice
831
832
  || draft.ttsRate !== config.ttsRate
@@ -839,7 +840,7 @@ window.__ModuleLoader__.load({
839
840
  const save = async () => {
840
841
  if (!config || !draft || saving) return
841
842
  const patch = {}
842
- for (const key of ['enabled', 'backendRoot', 'pythonPath', 'language', 'empathyStyle', 'ttsEnabled', 'ttsEngine', 'ttsVoice', 'ttsRate', 'ttsPitch', 'ttsPiperModel', 'maxAudioBytes', 'startupTimeoutMs', 'requestTimeoutMs']) {
843
+ for (const key of ['enabled', 'backendRoot', 'pythonPath', 'language', 'empathyStyle', 'ttsEnabled', 'ttsOnlyAfterVoice', 'ttsEngine', 'ttsVoice', 'ttsRate', 'ttsPitch', 'ttsPiperModel', 'maxAudioBytes', 'startupTimeoutMs', 'requestTimeoutMs']) {
843
844
  if (draft[key] !== config[key]) patch[key] = draft[key]
844
845
  }
845
846
  if (Object.keys(patch).length === 0) return
@@ -1264,6 +1265,16 @@ window.__ModuleLoader__.load({
1264
1265
  label: '朗读大肥鱼回复',
1265
1266
  onChange: (value) => update('ttsEnabled', value),
1266
1267
  })),
1268
+ h(SettingsField, {
1269
+ icon: 'spark',
1270
+ label: '只朗读语音触发的回复',
1271
+ hint: '开启后只朗读录音后两分钟内的回复;关闭后所有助手回复都会朗读。',
1272
+ }, h(SettingsSwitch, {
1273
+ checked: draft.ttsOnlyAfterVoice !== false,
1274
+ disabled: disabled || draft.ttsEnabled !== true,
1275
+ label: '只朗读语音触发的回复',
1276
+ onChange: (value) => update('ttsOnlyAfterVoice', value),
1277
+ })),
1267
1278
  h(SettingsField, {
1268
1279
  icon: 'spark',
1269
1280
  label: '合成引擎',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-dafeiyu-emotion",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "大肥鱼语音情绪耳朵:听语气、识别情绪,并让 DSH 按对方当下的状态自然回复。 · Voice + emotion-aware companion for DeepSeek Harness.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/index.js CHANGED
@@ -31,6 +31,7 @@ const DEFAULTS = Object.freeze({
31
31
  requestTimeoutMs: 180000,
32
32
  empathyStyle: 'gentle',
33
33
  ttsEnabled: true,
34
+ ttsOnlyAfterVoice: true,
34
35
  ttsEngine: 'piper',
35
36
  ttsVoice: 'zh-CN-XiaoyiNeural',
36
37
  ttsRate: '+6%',
@@ -80,6 +81,7 @@ export const Config = Schema.object({
80
81
  Schema.const('concise').description('简洁'),
81
82
  ]).default('gentle').description('共情策略').volatile(),
82
83
  ttsEnabled: Schema.boolean().default(true).description('朗读大肥鱼回复').volatile(),
84
+ ttsOnlyAfterVoice: Schema.boolean().default(true).description('只朗读语音触发的回复').volatile(),
83
85
  ttsEngine: Schema.union([
84
86
  Schema.const('piper').description('Piper 本地模型(推荐)'),
85
87
  Schema.const('edge').description('Edge TTS(更好听,需要网络)'),
@@ -464,6 +466,7 @@ function resolveOptions(raw = {}) {
464
466
  ? value.empathyStyle
465
467
  : DEFAULTS.empathyStyle,
466
468
  ttsEnabled: value.ttsEnabled === true,
469
+ ttsOnlyAfterVoice: value.ttsOnlyAfterVoice !== false,
467
470
  ttsEngine: ['piper', 'edge', 'browser'].includes(value.ttsEngine) ? value.ttsEngine : DEFAULTS.ttsEngine,
468
471
  ttsVoice: String(value.ttsVoice || DEFAULTS.ttsVoice).trim(),
469
472
  ttsRate: String(value.ttsRate || DEFAULTS.ttsRate).trim(),
@@ -485,6 +488,7 @@ function publicConfig(options, writable = false) {
485
488
  language: options.language || DEFAULTS.language,
486
489
  empathyStyle: options.empathyStyle || DEFAULTS.empathyStyle,
487
490
  ttsEnabled: options.ttsEnabled === true,
491
+ ttsOnlyAfterVoice: options.ttsOnlyAfterVoice !== false,
488
492
  ttsEngine: options.ttsEngine || DEFAULTS.ttsEngine,
489
493
  ttsVoice: options.ttsVoice || DEFAULTS.ttsVoice,
490
494
  ttsRate: options.ttsRate || DEFAULTS.ttsRate,
@@ -530,6 +534,11 @@ function normalizeConfigPatch(value) {
530
534
  patch.ttsEnabled = next
531
535
  continue
532
536
  }
537
+ if (key === 'ttsOnlyAfterVoice') {
538
+ if (typeof next !== 'boolean') throw new HttpError(400, 'ttsOnlyAfterVoice 必须是布尔值')
539
+ patch.ttsOnlyAfterVoice = next
540
+ continue
541
+ }
533
542
  if (key === 'ttsEngine') {
534
543
  const engine = String(next || '').trim().toLowerCase()
535
544
  if (!['piper', 'edge', 'browser'].includes(engine)) {
@@ -1358,6 +1367,7 @@ function createAnalyzeHandler(runtime, backend, getSpeechToText) {
1358
1367
  }
1359
1368
  runtime.lastAudioBytes = buffer.length
1360
1369
  runtime.lastAnalysisAt = runtime.lastAnalysis.at
1370
+ runtime.lastVoiceAt = Date.now()
1361
1371
  jsonResponse(res, 200, analysis)
1362
1372
  } catch (error) {
1363
1373
  if (controller?.signal.aborted || res.writableEnded) return
@@ -1390,6 +1400,7 @@ export function apply(ctx, rawConfig = {}) {
1390
1400
  // shared runtime object and settings.update persists it for the next boot.
1391
1401
  options: resolveOptions(rawConfig),
1392
1402
  lastAnalysis: null,
1403
+ lastVoiceAt: null,
1393
1404
  lastAudioBytes: 0,
1394
1405
  lastAnalysisAt: null,
1395
1406
  lastCleanupAt: null,
@@ -1413,6 +1424,8 @@ export function apply(ctx, rawConfig = {}) {
1413
1424
  try {
1414
1425
  const off = sessionCtx.on?.('session/event', (session, event) => {
1415
1426
  if (event?.type !== 'assistant/message' || !runtime.options.ttsEnabled) return
1427
+ if (runtime.options.ttsOnlyAfterVoice
1428
+ && (!runtime.lastVoiceAt || Date.now() - runtime.lastVoiceAt > 120000)) return
1416
1429
  const text = cleanForSpeech(assistantTextFromEvent(event))
1417
1430
  if (!text) return
1418
1431
  speechStream.broadcast({
@@ -1453,6 +1466,7 @@ export function apply(ctx, rawConfig = {}) {
1453
1466
  language: options.language,
1454
1467
  empathyStyle: options.empathyStyle,
1455
1468
  ttsEnabled: options.ttsEnabled,
1469
+ ttsOnlyAfterVoice: options.ttsOnlyAfterVoice,
1456
1470
  ttsEngine: options.ttsEngine,
1457
1471
  ttsVoice: options.ttsVoice,
1458
1472
  ttsReady: ttsReady(options),
@@ -1471,6 +1485,7 @@ export function apply(ctx, rawConfig = {}) {
1471
1485
  privacy: {
1472
1486
  lastAudioBytes: runtime.lastAudioBytes,
1473
1487
  lastAnalysisAt: runtime.lastAnalysisAt,
1488
+ lastVoiceAt: runtime.lastVoiceAt,
1474
1489
  lastCleanupAt: runtime.lastCleanupAt,
1475
1490
  workerPid: backendStatus.pid,
1476
1491
  modelLoadMs: backendStatus.modelLoadMs,