@goodandready/dsh-tts 0.4.20 → 0.4.22
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 +10 -0
- package/lib/client-src/50-settings.js +3 -3
- package/lib/client-src/60-card-dock.js +1 -1
- package/lib/client.js +4 -4
- package/lib/routes.js +3 -0
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes to `@goodandready/dsh-tts`.
|
|
4
4
|
|
|
5
|
+
## 0.4.22
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- Enforce fail-closed `isTrustedSettingsRequest(req)` validation on `/stream`, `/pending`, and `/speak` HTTP handlers to reject untrusted cross-site requests with 403 Forbidden (#136).
|
|
9
|
+
|
|
10
|
+
## 0.4.21
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Settings no longer wait on the removed settingsScope service. The client uses configForms (#137).
|
|
14
|
+
|
|
5
15
|
## 0.4.19
|
|
6
16
|
|
|
7
17
|
### Fixed
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
|
|
16
16
|
const ctx = props && props.ctx
|
|
17
17
|
const scope = React.useMemo(() => {
|
|
18
|
-
const s = (ctx && ctx.get && ctx.get('lanSettings')) || (ctx && ctx.
|
|
19
|
-
if (!s || !s.
|
|
18
|
+
const s = (ctx && ctx.get && ctx.get('lanSettings')) || (ctx && ctx.configForms)
|
|
19
|
+
if (!s || !s.get) return null
|
|
20
20
|
try {
|
|
21
|
-
return s.
|
|
21
|
+
return s.get(NS)
|
|
22
22
|
} catch (_) { /* settings scope binding failed */
|
|
23
23
|
return null
|
|
24
24
|
}
|
package/lib/client.js
CHANGED
|
@@ -1379,10 +1379,10 @@ async function pollPending() {
|
|
|
1379
1379
|
|
|
1380
1380
|
const ctx = props && props.ctx
|
|
1381
1381
|
const scope = React.useMemo(() => {
|
|
1382
|
-
const s = (ctx && ctx.get && ctx.get('lanSettings')) || (ctx && ctx.
|
|
1383
|
-
if (!s || !s.
|
|
1382
|
+
const s = (ctx && ctx.get && ctx.get('lanSettings')) || (ctx && ctx.configForms)
|
|
1383
|
+
if (!s || !s.get) return null
|
|
1384
1384
|
try {
|
|
1385
|
-
return s.
|
|
1385
|
+
return s.get(NS)
|
|
1386
1386
|
} catch (_) { /* settings scope binding failed */
|
|
1387
1387
|
return null
|
|
1388
1388
|
}
|
|
@@ -1969,7 +1969,7 @@ async function pollPending() {
|
|
|
1969
1969
|
))
|
|
1970
1970
|
}
|
|
1971
1971
|
|
|
1972
|
-
exports.inject = ['slots', '
|
|
1972
|
+
exports.inject = ['slots', 'configForms', 'locale']
|
|
1973
1973
|
exports.apply = function apply(ctx) {
|
|
1974
1974
|
registerSettings(ctx)
|
|
1975
1975
|
registerSpeaker(ctx)
|
package/lib/routes.js
CHANGED
|
@@ -58,6 +58,7 @@ export function registerHttpRoutes(ctx, api) {
|
|
|
58
58
|
path: '/dsh-tts/stream',
|
|
59
59
|
handler: async (req, res) => {
|
|
60
60
|
if (req.method !== 'GET') { writeJson(res, 405, { ok: false, error: { code: 'method', message: 'GET only' } }); return }
|
|
61
|
+
if (!isTrustedSettingsRequest(req)) { writeJson(res, 403, { ok: false, error: { code: 'forbidden', message: 'same-origin only' } }); return }
|
|
61
62
|
try {
|
|
62
63
|
res.writeHead(200, {
|
|
63
64
|
'Content-Type': 'text/event-stream',
|
|
@@ -376,6 +377,7 @@ export function registerHttpRoutes(ctx, api) {
|
|
|
376
377
|
path: '/dsh-tts/pending',
|
|
377
378
|
handler: async (req, res) => {
|
|
378
379
|
if (req.method !== 'GET') { writeJson(res, 405, { ok: false, error: { code: 'method', message: 'GET only' } }); return }
|
|
380
|
+
if (!isTrustedSettingsRequest(req)) { writeJson(res, 403, { ok: false, error: { code: 'forbidden', message: 'same-origin only' } }); return }
|
|
379
381
|
const url = new URL(req.url || '/', 'http://127.0.0.1')
|
|
380
382
|
const after = url.searchParams.get('after') || ''
|
|
381
383
|
let items = pending.slice()
|
|
@@ -392,6 +394,7 @@ export function registerHttpRoutes(ctx, api) {
|
|
|
392
394
|
path: '/dsh-tts/speak',
|
|
393
395
|
handler: async (req, res) => {
|
|
394
396
|
if (req.method !== 'POST') { writeJson(res, 405, { ok: false, error: { code: 'method', message: 'POST only' } }); return }
|
|
397
|
+
if (!isTrustedSettingsRequest(req)) { writeJson(res, 403, { ok: false, error: { code: 'forbidden', message: 'same-origin only' } }); return }
|
|
395
398
|
let raw
|
|
396
399
|
try { raw = await readBody(req, 256 * 1024) } catch (e) {
|
|
397
400
|
writeJson(res, 400, { ok: false, error: { code: 'body', message: e.message } }); return
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-tts",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.22",
|
|
4
4
|
"description": "Text-to-speech for DeepSeek Harness: speak agent replies in the Web UI with a provider fallback chain (OpenAI, ElevenLabs, Google, Azure, Groq, Deepgram, OpenRouter, Edge, Piper, eSpeak).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -54,7 +54,9 @@
|
|
|
54
54
|
"platform": "web",
|
|
55
55
|
"inject": [
|
|
56
56
|
"@deepseek-ai/dsh-client-locale",
|
|
57
|
-
"@deepseek-ai/dsh-client-connection"
|
|
57
|
+
"@deepseek-ai/dsh-client-connection",
|
|
58
|
+
"@deepseek-ai/dsh-client-ui-slots",
|
|
59
|
+
"@deepseek-ai/dsh-client-ui-settings"
|
|
58
60
|
]
|
|
59
61
|
}
|
|
60
62
|
},
|