dsh-voice-say 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.js +1 -0
- package/index.js +16 -1
- package/lib/director.mjs +15 -4
- package/package.json +2 -2
package/client.js
CHANGED
|
@@ -465,6 +465,7 @@ window.__ModuleLoader__.load({
|
|
|
465
465
|
directRes.elapsedMs ? `· ${(directRes.elapsedMs / 1000).toFixed(1)} 秒` : '',
|
|
466
466
|
directRes.cached ? '· 命中缓存' : '',
|
|
467
467
|
directRes.transport === 'dsh' ? '· 在 DeepSeek 窗口里想的' : '',
|
|
468
|
+
directRes.transport === 'api-fallback' ? '· 会话没走通,已退回直连' : '',
|
|
468
469
|
].filter(Boolean).join(' ')),
|
|
469
470
|
directRes.sessionId ? h('div', { 'data-vs-sub': '', 'data-vs-mono': '' }, `会话:${directRes.sessionId}`) : null,
|
|
470
471
|
directRes.notes ? h('div', { 'data-vs-sub': '' }, `导演说明:${directRes.notes}`) : null,
|
package/index.js
CHANGED
|
@@ -32,7 +32,7 @@ import { direct as directText, gatherContext, probeDirector, clearCache as clear
|
|
|
32
32
|
export const name = 'dsh-voice-say'
|
|
33
33
|
export const inject = ['webServer', 'tools']
|
|
34
34
|
|
|
35
|
-
const PLUGIN_VERSION = '0.6.
|
|
35
|
+
const PLUGIN_VERSION = '0.6.2'
|
|
36
36
|
const DEFAULT_INSTRUCTIONS = '说话自然一点,带点傲娇和不耐烦,别太热情。'
|
|
37
37
|
const DEFAULT_PREVIEW_TEXT = '哼,才不是特意来跟你说话的呢,笨蛋。'
|
|
38
38
|
const MAX_BODY = 32 * 1024 * 1024
|
|
@@ -59,6 +59,10 @@ export async function apply(ctx, config = {}) {
|
|
|
59
59
|
const uiConfigFile = path.join(dataRoot, 'config.json')
|
|
60
60
|
const outDir = ensureDir(path.join(dataRoot, 'out'))
|
|
61
61
|
|
|
62
|
+
// 最近一次「网页/桥接是从哪个地址访问到我的」。DSH 的端口每次重启都会变,
|
|
63
|
+
// 记下来就不必依赖外部配置文件去猜——导演台直接用这个地址去连自己的 GUI。
|
|
64
|
+
let lastSeenHost = ''
|
|
65
|
+
|
|
62
66
|
/** 生效配置:patch config + 数据根 config.json 覆盖 */
|
|
63
67
|
function cfg() {
|
|
64
68
|
const base = {
|
|
@@ -106,6 +110,11 @@ export async function apply(ctx, config = {}) {
|
|
|
106
110
|
merged.guidanceScale = Number.isFinite(g) ? Math.min(Math.max(g, 1), 3) : 1
|
|
107
111
|
merged.instructions = String(merged.instructions ?? '').trim()
|
|
108
112
|
merged.styles = pickStyles(merged.styles).map((s) => s.id)
|
|
113
|
+
// 没显式配 DSH 地址时,用「刚刚访问到我的那个地址」——这就是当前 GUI 的真实端口
|
|
114
|
+
if (lastSeenHost) {
|
|
115
|
+
const d = merged.director && typeof merged.director === 'object' ? merged.director : {}
|
|
116
|
+
if (!d.dshBaseUrl) merged.director = { ...d, dshBaseUrl: `http://${lastSeenHost}` }
|
|
117
|
+
}
|
|
109
118
|
return merged
|
|
110
119
|
}
|
|
111
120
|
|
|
@@ -576,6 +585,12 @@ export async function apply(ctx, config = {}) {
|
|
|
576
585
|
path: '/api/voice-say',
|
|
577
586
|
handler: async (req, res) => {
|
|
578
587
|
if (!sameOrigin(req)) { sendJson(res, 403, { ok: false, error: '只接受本机同源请求' }); return }
|
|
588
|
+
// 顺手记下「网页是从哪个地址访问到我的」——DSH 的端口每次重启都会变,
|
|
589
|
+
// 有了这个就能自己去找到同进程的 GUI,不用等 QQ 桥接更新配置。
|
|
590
|
+
try {
|
|
591
|
+
const h = String(req.headers.host || '')
|
|
592
|
+
if (/^(127\.0\.0\.1|localhost|\[::1\]):\d+$/.test(h)) lastSeenHost = h
|
|
593
|
+
} catch { /* 记不下来就算了 */ }
|
|
579
594
|
try {
|
|
580
595
|
const url = new URL(req.url, 'http://127.0.0.1')
|
|
581
596
|
const sub = url.pathname.replace(/^\/api\/voice-say\/?/, '').replace(/\/+$/, '')
|
package/lib/director.mjs
CHANGED
|
@@ -453,10 +453,20 @@ async function askModel(o, key, messages, extraNote, ctx = {}) {
|
|
|
453
453
|
const full = extraNote ? [...messages, { role: 'user', content: extraNote }] : messages
|
|
454
454
|
if (o.transport === 'dsh') {
|
|
455
455
|
const dsh = o.dsh
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
456
|
+
const why = !dsh.baseUrl
|
|
457
|
+
? '找不到 DSH 地址(桥接没记下 baseUrl,可在设置里填 dshBaseUrl)'
|
|
458
|
+
: (!dsh.hasSecret ? '读不到 DSH 会话密钥(~/.dsh/.credentials.yaml)' : '')
|
|
459
|
+
if (!why) {
|
|
460
|
+
const r = await askSession(dsh, { text: messagesToText(full), hooks: ctx.hooks })
|
|
461
|
+
if (r.ok) return { content: r.text, elapsedMs: r.elapsedMs, transport: 'dsh', sessionId: r.sessionId }
|
|
462
|
+
if (!key) throw new Error(r.error || 'DSH 会话没回话')
|
|
463
|
+
// 会话这条走不通、但手里有 key —— 悄悄退到直连,别让人听不到声音
|
|
464
|
+
const out = await callModel(o, key, full)
|
|
465
|
+
return { ...out, transport: 'api-fallback', sessionId: '', fallbackReason: r.error || '' }
|
|
466
|
+
}
|
|
467
|
+
if (!key) throw new Error(why)
|
|
468
|
+
const out = await callModel(o, key, full)
|
|
469
|
+
return { ...out, transport: 'api-fallback', sessionId: '', fallbackReason: why }
|
|
460
470
|
}
|
|
461
471
|
const out = await callModel(o, key, full)
|
|
462
472
|
return { ...out, transport: 'api', sessionId: '' }
|
|
@@ -527,6 +537,7 @@ export async function direct(cfg = {}, input = {}) {
|
|
|
527
537
|
let parsed = parseReply(out.content)
|
|
528
538
|
result.elapsedMs = out.elapsedMs
|
|
529
539
|
if (out.transport) result.transport = out.transport
|
|
540
|
+
if (out.fallbackReason) result.fallbackReason = out.fallbackReason
|
|
530
541
|
if (out.sessionId) {
|
|
531
542
|
result.sessionId = out.sessionId
|
|
532
543
|
o.dsh.sessionId = out.sessionId // 重试沿用同一个窗口,别又开一个
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-voice-say",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "dsh-voice-say:把一句话合成语音。两条通道(本地 Breeze TTS 2 / 云端 apiKey+voiceId)共用 instructions + guidanceScale;18 个风格可叠加;合成前由「读音导演」重排标点——默认在 DeepSeek 窗口里的专用会话里想,按人设、当下情绪与对话情节断句;支持上传本地音色、自定义参考音频与试听片段。QQ 桥接会先问插件,群里发出去的语音与设置页试听同源同风格。",
|
|
5
|
+
"description": "dsh-voice-say:把一句话合成语音。两条通道(本地 Breeze TTS 2 / 云端 apiKey+voiceId)共用 instructions + guidanceScale;18 个风格可叠加;合成前由「读音导演」重排标点——默认在 DeepSeek 窗口里的专用会话里想,按人设、当下情绪与对话情节断句;支持上传本地音色、自定义参考音频与试听片段。QQ 桥接会先问插件,群里发出去的语音与设置页试听同源同风格。 导演台连不上时自动改用「当前访问地址」自愈。",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "dsh-voice-say contributors",
|
|
8
8
|
"keywords": [
|