@goodandready/dsh-voice 0.9.31 → 0.9.32
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/README.md +255 -252
- package/README.ru.md +254 -251
- package/README.zh.md +182 -179
- package/lib/client.js +295 -56
- package/lib/dictation-modes.js +28 -0
- package/lib/host-routes.js +222 -188
- package/lib/macros.js +53 -0
- package/lib/polish.js +14 -6
- package/lib/providers.js +3 -1
- package/lib/schema.js +173 -161
- package/package.json +72 -72
package/lib/schema.js
CHANGED
|
@@ -1,161 +1,173 @@
|
|
|
1
|
-
// lib/schema.js — Schemastery configuration schemas for @goodandready/dsh-voice
|
|
2
|
-
import z from '@deepseek-ai/schemastery'
|
|
3
|
-
import { PROVIDER_KEYS, PRESET_KEYS, CUSTOM_TEMPLATES } from './providers.js'
|
|
4
|
-
|
|
5
|
-
export const ChainEntry = z.object({
|
|
6
|
-
provider: z.string().default('local-whisper')
|
|
7
|
-
.description(`Provider key. Built in: ${PROVIDER_KEYS.join(', ')}. `
|
|
8
|
-
+ `Ready-made, just add the key: ${PRESET_KEYS.join(', ')}. `
|
|
9
|
-
+ 'Or the name of an entry from customProviders. '
|
|
10
|
-
+ '"browser" recognises speech via Web Speech API; '
|
|
11
|
-
+ '"browser-webgpu" runs offline Whisper directly in the page via WebGPU/WASM; '
|
|
12
|
-
+ 'put a normal host provider after them as a fallback.'),
|
|
13
|
-
model: z.string().default('')
|
|
14
|
-
.description('Model override. Empty means the provider default.'),
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
// Custom provider: everything needed to call any OpenAI-compatible API.
|
|
18
|
-
export const CustomProvider = z.object({
|
|
19
|
-
key: z.string().default('')
|
|
20
|
-
.description('Name used in the chains above. Must differ from the built-in keys.'),
|
|
21
|
-
template: z.string().default('openai-transcriptions')
|
|
22
|
-
.description(`API shape: ${CUSTOM_TEMPLATES.join(' or ')}. `
|
|
23
|
-
+ 'OpenRouter has no /audio/transcriptions, use openai-chat-audio there.'),
|
|
24
|
-
baseURL: z.string().default('')
|
|
25
|
-
.description('API root without a trailing slash, e.g. https://openrouter.ai/api/v1'),
|
|
26
|
-
model: z.string().default(''),
|
|
27
|
-
keyEnv: z.string().default('')
|
|
28
|
-
.description('Credential name holding the API key. Empty means no authorization header.'),
|
|
29
|
-
prompt: z.string().default('')
|
|
30
|
-
.description('openai-chat-audio only: instruction sent along with the audio. '
|
|
31
|
-
+ 'Empty means the built-in one.'),
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
.description('
|
|
44
|
-
|
|
45
|
-
.description('
|
|
46
|
-
|
|
47
|
-
.description('
|
|
48
|
-
|
|
49
|
-
.description('
|
|
50
|
-
|
|
51
|
-
.description('
|
|
52
|
-
|
|
53
|
-
.description('
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
.description('
|
|
63
|
-
|
|
64
|
-
.description('
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
.description('
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
.description('
|
|
101
|
-
|
|
102
|
-
.description('
|
|
103
|
-
|
|
104
|
-
.description('
|
|
105
|
-
|
|
106
|
-
.description('
|
|
107
|
-
|
|
108
|
-
.description('
|
|
109
|
-
|
|
110
|
-
.description('
|
|
111
|
-
|
|
112
|
-
.description('
|
|
113
|
-
|
|
114
|
-
.description('
|
|
115
|
-
|
|
116
|
-
.description('
|
|
117
|
-
|
|
118
|
-
.description('
|
|
119
|
-
|
|
120
|
-
.description('
|
|
121
|
-
|
|
122
|
-
.description('
|
|
123
|
-
|
|
124
|
-
.description('Offline polish:
|
|
125
|
-
|
|
126
|
-
.description('
|
|
127
|
-
|
|
128
|
-
.description('
|
|
129
|
-
|
|
130
|
-
.description('
|
|
131
|
-
|
|
132
|
-
.description('
|
|
133
|
-
|
|
134
|
-
.description('SenseVoice /
|
|
135
|
-
|
|
136
|
-
.description('
|
|
137
|
-
|
|
138
|
-
.description('
|
|
139
|
-
|
|
140
|
-
.description('
|
|
141
|
-
|
|
142
|
-
.description('
|
|
143
|
-
|
|
144
|
-
.description('
|
|
145
|
-
|
|
146
|
-
.description('
|
|
147
|
-
|
|
148
|
-
.description('
|
|
149
|
-
|
|
150
|
-
.description('
|
|
151
|
-
|
|
152
|
-
.description('
|
|
153
|
-
|
|
154
|
-
.description('
|
|
155
|
-
|
|
156
|
-
.description('
|
|
157
|
-
|
|
158
|
-
.description('
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
1
|
+
// lib/schema.js — Schemastery configuration schemas for @goodandready/dsh-voice
|
|
2
|
+
import z from '@deepseek-ai/schemastery'
|
|
3
|
+
import { PROVIDER_KEYS, PRESET_KEYS, CUSTOM_TEMPLATES } from './providers.js'
|
|
4
|
+
|
|
5
|
+
export const ChainEntry = z.object({
|
|
6
|
+
provider: z.string().default('local-whisper')
|
|
7
|
+
.description(`Provider key. Built in: ${PROVIDER_KEYS.join(', ')}. `
|
|
8
|
+
+ `Ready-made, just add the key: ${PRESET_KEYS.join(', ')}. `
|
|
9
|
+
+ 'Or the name of an entry from customProviders. '
|
|
10
|
+
+ '"browser" recognises speech via Web Speech API; '
|
|
11
|
+
+ '"browser-webgpu" runs offline Whisper directly in the page via WebGPU/WASM; '
|
|
12
|
+
+ 'put a normal host provider after them as a fallback.'),
|
|
13
|
+
model: z.string().default('')
|
|
14
|
+
.description('Model override. Empty means the provider default.'),
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
// Custom provider: everything needed to call any OpenAI-compatible API.
|
|
18
|
+
export const CustomProvider = z.object({
|
|
19
|
+
key: z.string().default('')
|
|
20
|
+
.description('Name used in the chains above. Must differ from the built-in keys.'),
|
|
21
|
+
template: z.string().default('openai-transcriptions')
|
|
22
|
+
.description(`API shape: ${CUSTOM_TEMPLATES.join(' or ')}. `
|
|
23
|
+
+ 'OpenRouter has no /audio/transcriptions, use openai-chat-audio there.'),
|
|
24
|
+
baseURL: z.string().default('')
|
|
25
|
+
.description('API root without a trailing slash, e.g. https://openrouter.ai/api/v1'),
|
|
26
|
+
model: z.string().default(''),
|
|
27
|
+
keyEnv: z.string().default('')
|
|
28
|
+
.description('Credential name holding the API key. Empty means no authorization header.'),
|
|
29
|
+
prompt: z.string().default('')
|
|
30
|
+
.description('openai-chat-audio only: instruction sent along with the audio. '
|
|
31
|
+
+ 'Empty means the built-in one.'),
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
export const VoiceMacro = z.object({
|
|
35
|
+
trigger: z.string().default(''),
|
|
36
|
+
template: z.string().default(''),
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
export const BaseConfig = z.object({
|
|
40
|
+
dictation: z.object({
|
|
41
|
+
chain: z.array(ChainEntry)
|
|
42
|
+
.default([{ provider: 'deepgram', model: '' }, { provider: 'groq', model: '' }, { provider: 'local-whisper', model: '' }])
|
|
43
|
+
.description('Fallback chain for dictation. Speed matters more than accuracy here.'),
|
|
44
|
+
language: z.string().default('')
|
|
45
|
+
.description('Recognition language code for dictation (e.g. "en", "ru", "zh", or empty string for auto-detection).'),
|
|
46
|
+
vadSilenceMs: z.number().default(700)
|
|
47
|
+
.description('Silence longer than this ends a phrase and sends the chunk.'),
|
|
48
|
+
sendDelayMs: z.number().default(0)
|
|
49
|
+
.description('Dictation: wait this many ms after a phrase before appending it, with a cancel window. 0 disables the delay.'),
|
|
50
|
+
polish: z.boolean().default(false)
|
|
51
|
+
.description('Polish the transcript through the harness model before inserting: punctuation, paragraphs, filler-word removal.'),
|
|
52
|
+
stream: z.boolean().default(false)
|
|
53
|
+
.description('Continuous dictation: cut phrases by a timer instead of waiting for a long silence, so text flows while you speak.'),
|
|
54
|
+
streamChunkMs: z.number().default(1200)
|
|
55
|
+
.description('Continuous dictation: phrase length in ms of uninterrupted speech before the chunk is sent.'),
|
|
56
|
+
vadAdapt: z.number().min(0).max(1).default(0)
|
|
57
|
+
.description('Adaptive silence threshold: 0 = fixed (current behaviour); >0 shrinks the threshold during dense speech and grows it during pauses.'),
|
|
58
|
+
}).default({}),
|
|
59
|
+
message: z.object({
|
|
60
|
+
chain: z.array(ChainEntry)
|
|
61
|
+
.default([{ provider: 'groq', model: '' }, { provider: 'hf', model: '' }, { provider: 'local-whisper', model: '' }])
|
|
62
|
+
.description('Fallback chain for voice messages. Accuracy matters more than speed.'),
|
|
63
|
+
language: z.string().default('')
|
|
64
|
+
.description('Recognition language code for messages (e.g. "en", "ru", "zh", or empty string for auto-detection).'),
|
|
65
|
+
autoSendMs: z.number().default(4000)
|
|
66
|
+
.description('Cancel window before the recognized text is sent to the agent.'),
|
|
67
|
+
sessionCommands: z.boolean().default(false)
|
|
68
|
+
.description('Voice session commands: a clean "send", "cancel", "stop", "continue" does not become text — it drives the composer/session.'),
|
|
69
|
+
polishSend: z.boolean().default(false),
|
|
70
|
+
editablePreview: z.boolean().default(true)
|
|
71
|
+
.description('Polish the whole composed draft through the model right before sending, not just single phrases.'),
|
|
72
|
+
}).default({}),
|
|
73
|
+
hotkey: z.string().default('Control')
|
|
74
|
+
.description('Hold this key anywhere in the page to record a voice message; release to send, '
|
|
75
|
+
+ 'Escape to discard. Modifier names (Control, Alt, Shift) or a KeyboardEvent code. '
|
|
76
|
+
+ 'Empty disables the hotkey.'),
|
|
77
|
+
customProviders: z.array(CustomProvider).default([])
|
|
78
|
+
.description('Own recognition providers, usable in both chains next to the built-in ones.'),
|
|
79
|
+
deepgramKeyEnv: z.string().default('DEEPGRAM_API_KEY'),
|
|
80
|
+
deepgramBaseUrl: z.string().default('https://api.deepgram.com')
|
|
81
|
+
.description('Deepgram-compatible host. Point this at a private/self-hosted Deepgram deployment '
|
|
82
|
+
+ 'instead of the public api.deepgram.com endpoint.'),
|
|
83
|
+
groqKeyEnv: z.string().default('GROQ_API_KEY'),
|
|
84
|
+
hfTokenEnv: z.string().default('HF_TOKEN'),
|
|
85
|
+
whisperUrl: z.string().default('http://127.0.0.1:8001/inference'),
|
|
86
|
+
whisperBin: z.string().default('whisper-server')
|
|
87
|
+
.description('whisper.cpp server binary, looked up in PATH unless an absolute path is given.'),
|
|
88
|
+
whisperModel: z.string().default('')
|
|
89
|
+
.description('Absolute path to the ggml model. Autostart stays off while this is empty; '
|
|
90
|
+
+ 'point it at your own model file to let the plugin launch whisper.cpp itself.'),
|
|
91
|
+
autoStart: z.boolean().default(true)
|
|
92
|
+
.description('Launch the local whisper.cpp server on activation if the port is free. '
|
|
93
|
+
+ 'Requires whisperModel to be set.'),
|
|
94
|
+
ffmpegBin: z.string().default('ffmpeg')
|
|
95
|
+
.description('ffmpeg used to convert browser webm/opus into the WAV that whisper.cpp requires.'),
|
|
96
|
+
timeoutMs: z.number().default(120000),
|
|
97
|
+
allowedAudioDirs: z.array(z.string()).default([]),
|
|
98
|
+
maxFileBytes: z.number().default(25 * 1024 * 1024),
|
|
99
|
+
normalizeTranscript: z.boolean().default(false)
|
|
100
|
+
.description('transcribe_audio: convert spoken numbers to digits and tidy punctuation.'),
|
|
101
|
+
beep: z.boolean().default(false)
|
|
102
|
+
.description('Play a short beep when recording starts and stops.'),
|
|
103
|
+
localOnly: z.boolean().default(false)
|
|
104
|
+
.description('Restrict both chains to local-whisper only: fully offline, no cloud providers.'),
|
|
105
|
+
micDeviceId: z.string().default('')
|
|
106
|
+
.description('Microphone device id for recording. Empty means the system default.'),
|
|
107
|
+
noiseGateDb: z.number().default(-45)
|
|
108
|
+
.description('Audio noise gate threshold in dB for client-side recording (-50 to -25 dB, or <= -90 to disable). Silence below this threshold cuts ambient background noise and prevents false VAD triggers.'),
|
|
109
|
+
historyLimit: z.number().default(20)
|
|
110
|
+
.description('How many recent dictation inserts to keep for undo in the browser. 0 disables history.'),
|
|
111
|
+
vocabulary: z.array(z.string()).default([])
|
|
112
|
+
.description('Custom words (names, terms) hinted to providers so they recognize them correctly.'),
|
|
113
|
+
contextGlossary: z.boolean().default(true)
|
|
114
|
+
.description('Automatically extract code words and terms from context and hint them to STT providers.'),
|
|
115
|
+
noiseSuppression: z.boolean().default(true)
|
|
116
|
+
.description('Enable hardware noise suppression, echo cancellation, and auto gain control.'),
|
|
117
|
+
voiceCommands: z.boolean().default(false)
|
|
118
|
+
.description('During dictation, spoken edit commands ("new line", "paragraph") become real line breaks instead of words.'),
|
|
119
|
+
wakeWord: z.string().default('')
|
|
120
|
+
.description('Heads-free dictation: a phrase that, when recognized by the browser leg, starts a recording. Empty disables.'),
|
|
121
|
+
bargeIn: z.boolean().default(false)
|
|
122
|
+
.description('Ongoing playback or a long turn is interrupted by detected speech (browser leg).'),
|
|
123
|
+
polishBaseUrl: z.string().default('')
|
|
124
|
+
.description('Offline polish: OpenAI-compatible /chat/completions endpoint (e.g. local Ollama). Empty uses the harness model.'),
|
|
125
|
+
polishModel: z.string().default('')
|
|
126
|
+
.description('Offline polish: model id on polishBaseUrl.'),
|
|
127
|
+
polishKeyEnv: z.string().default('')
|
|
128
|
+
.description('Offline polish: credential name for the api key. Empty means no Authorization header.'),
|
|
129
|
+
polishProvider: z.string().default('')
|
|
130
|
+
.description('Harness polish: provider id. Empty uses the agent default model selection.'),
|
|
131
|
+
polishModelId: z.string().default('')
|
|
132
|
+
.description('Harness polish: model id. Empty uses the agent default model selection.'),
|
|
133
|
+
sensevoiceUrl: z.string().default('http://127.0.0.1:6006/api/v1/asr')
|
|
134
|
+
.description('SenseVoice-ONNX / Sherpa-ONNX endpoint: POST /api/v1/asr or OpenAI-compatible /v1/audio/transcriptions.'),
|
|
135
|
+
sensevoiceBin: z.string().default('sherpa-onnx-offline-http-server')
|
|
136
|
+
.description('SenseVoice / sherpa-onnx executable binary used when autostart is enabled.'),
|
|
137
|
+
sensevoiceModel: z.string().default('')
|
|
138
|
+
.description('SenseVoice / sherpa-onnx model path or model identifier.'),
|
|
139
|
+
sensevoiceAutostart: z.boolean().default(false)
|
|
140
|
+
.description('Start the local SenseVoice / sherpa-onnx server process automatically on startup.'),
|
|
141
|
+
sensevoiceProvider: z.string().default('cpu')
|
|
142
|
+
.description('Execution provider for sherpa-onnx: "cpu", "rknn" (Rockchip RK3588/RK3568 NPU on ARM SBC with RKNN models), "openvino", "cuda".'),
|
|
143
|
+
sensevoiceThreads: z.number().default(4)
|
|
144
|
+
.description('Execution thread count for local SenseVoice / sherpa-onnx on CPU/SBC.'),
|
|
145
|
+
webgpuModel: z.string().default('onnx-community/whisper-tiny')
|
|
146
|
+
.description('In-browser offline WebGPU Whisper model identifier (e.g. "onnx-community/whisper-tiny").'),
|
|
147
|
+
visualizerStyle: z.union(['liquid-wave', 'dynamic-orb', 'bars', 'off']).default('liquid-wave')
|
|
148
|
+
.description('Audio visualizer animation style in the recording pill: "liquid-wave", "dynamic-orb", "bars", or "off".'),
|
|
149
|
+
gatedTurnTaking: z.boolean().default(true)
|
|
150
|
+
.description('Gated mode for speakers: pause recording or ignore input while assistant TTS is speaking to prevent acoustic feedback.'),
|
|
151
|
+
autoSendVisualRing: z.boolean().default(true)
|
|
152
|
+
.description('Show animated circular countdown ring on recording pill before auto-sending.'),
|
|
153
|
+
voiceActions: z.boolean().default(true)
|
|
154
|
+
.description('Enable spoken action triggers ("send", "cancel", "clear", "new line" in English/Russian).'),
|
|
155
|
+
techJargonCorrection: z.boolean().default(true)
|
|
156
|
+
.description('Apply developer lexicon and IT jargon normalization (GitHub, Docker, pnpm, Kubernetes, etc.).'),
|
|
157
|
+
jargonDictionary: z.array(z.object({ from: z.string(), to: z.string() })).default([])
|
|
158
|
+
.description('Custom jargon replacement dictionary.'),
|
|
159
|
+
liveInterimPreview: z.boolean().default(true)
|
|
160
|
+
.description('Display real-time interim speech preview (ghost text) in the recording pill.'),
|
|
161
|
+
structuredPromptVoice: z.boolean().default(true)
|
|
162
|
+
.description('Target voice dictation and numeric choices to active DSH structured prompt modals.'),
|
|
163
|
+
dictationMode: z.union(['verbatim', 'clean', 'task', 'note']).default('clean')
|
|
164
|
+
.description('Dictation post-processing mode: "verbatim", "clean", "task", or "note".'),
|
|
165
|
+
dictationPrompts: z.object({
|
|
166
|
+
clean: z.string().default(''),
|
|
167
|
+
task: z.string().default(''),
|
|
168
|
+
note: z.string().default(''),
|
|
169
|
+
}).default({})
|
|
170
|
+
.description('Custom prompt templates for dictation modes.'),
|
|
171
|
+
voiceMacros: z.array(VoiceMacro).default([])
|
|
172
|
+
.description('User voice action macros (spoken trigger phrase -> structured prompt replacement).'),
|
|
173
|
+
})
|
package/package.json
CHANGED
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@goodandready/dsh-voice",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "Voice input for DeepSeek Harness: dictation chunked by pauses and voice messages, each with its own provider fallback chain (Deepgram, Groq, HuggingFace, local whisper.cpp, plus any OpenAI-compatible API of your own).",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"main": "./lib/index.js",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": "./lib/index.js",
|
|
10
|
-
"./client": "./lib/client.js",
|
|
11
|
-
"./package.json": "./package.json",
|
|
12
|
-
"./cordis.patch.yml": "./cordis.patch.yml"
|
|
13
|
-
},
|
|
14
|
-
"files": [
|
|
15
|
-
"lib/*.js",
|
|
16
|
-
"cordis.patch.yml",
|
|
17
|
-
"README.md",
|
|
18
|
-
"README.zh.md",
|
|
19
|
-
"README.ru.md",
|
|
20
|
-
"LICENSE"
|
|
21
|
-
],
|
|
22
|
-
"keywords": [
|
|
23
|
-
"dsh",
|
|
24
|
-
"dsh-plugin",
|
|
25
|
-
"deepseek-harness",
|
|
26
|
-
"voice",
|
|
27
|
-
"stt",
|
|
28
|
-
"dictation",
|
|
29
|
-
"whisper",
|
|
30
|
-
"deepgram",
|
|
31
|
-
"groq",
|
|
32
|
-
"openrouter",
|
|
33
|
-
"openai-compatible"
|
|
34
|
-
],
|
|
35
|
-
"repository": {
|
|
36
|
-
"type": "git",
|
|
37
|
-
"url": "https://github.com/GooDAnDReaDY/dsh-voice.git"
|
|
38
|
-
},
|
|
39
|
-
"homepage": "https://github.com/GooDAnDReaDY/dsh-voice",
|
|
40
|
-
"bugs": {
|
|
41
|
-
"url": "https://github.com/GooDAnDReaDY/dsh-voice/issues"
|
|
42
|
-
},
|
|
43
|
-
"scripts": {
|
|
44
|
-
"test": "node --test test/*.test.mjs",
|
|
45
|
-
"build:client": "node scripts/build-client.mjs",
|
|
46
|
-
"build:check": "node scripts/build-client.mjs --check",
|
|
47
|
-
"pretest": "node scripts/build-client.mjs && node scripts/lint.mjs && node scripts/pack-check.mjs",
|
|
48
|
-
"lint": "node scripts/lint.mjs",
|
|
49
|
-
"pack:check": "node scripts/pack-check.mjs"
|
|
50
|
-
},
|
|
51
|
-
"dsh": {
|
|
52
|
-
"bundle": {
|
|
53
|
-
"patch": "./cordis.patch.yml"
|
|
54
|
-
},
|
|
55
|
-
"client": {
|
|
56
|
-
"platform": "web",
|
|
57
|
-
"inject": [
|
|
58
|
-
"@deepseek-ai/dsh-client-ui-slots",
|
|
59
|
-
"@deepseek-ai/dsh-client-locale",
|
|
60
|
-
"@deepseek-ai/dsh-client-ui-settings"
|
|
61
|
-
]
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
"peerDependencies": {
|
|
65
|
-
"@deepseek-ai/cordis": "^4.0.1",
|
|
66
|
-
"@deepseek-ai/dsh-tools": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
67
|
-
"@deepseek-ai/dsh-credentials": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
68
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
69
|
-
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
70
|
-
"@deepseek-ai/schemastery": "^3.18.1"
|
|
71
|
-
}
|
|
72
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@goodandready/dsh-voice",
|
|
3
|
+
"version": "0.9.32",
|
|
4
|
+
"description": "Voice input for DeepSeek Harness: dictation chunked by pauses and voice messages, each with its own provider fallback chain (Deepgram, Groq, HuggingFace, local whisper.cpp, plus any OpenAI-compatible API of your own).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./lib/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./lib/index.js",
|
|
10
|
+
"./client": "./lib/client.js",
|
|
11
|
+
"./package.json": "./package.json",
|
|
12
|
+
"./cordis.patch.yml": "./cordis.patch.yml"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"lib/*.js",
|
|
16
|
+
"cordis.patch.yml",
|
|
17
|
+
"README.md",
|
|
18
|
+
"README.zh.md",
|
|
19
|
+
"README.ru.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"dsh",
|
|
24
|
+
"dsh-plugin",
|
|
25
|
+
"deepseek-harness",
|
|
26
|
+
"voice",
|
|
27
|
+
"stt",
|
|
28
|
+
"dictation",
|
|
29
|
+
"whisper",
|
|
30
|
+
"deepgram",
|
|
31
|
+
"groq",
|
|
32
|
+
"openrouter",
|
|
33
|
+
"openai-compatible"
|
|
34
|
+
],
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "https://github.com/GooDAnDReaDY/dsh-voice.git"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/GooDAnDReaDY/dsh-voice",
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/GooDAnDReaDY/dsh-voice/issues"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"test": "node --test test/*.test.mjs",
|
|
45
|
+
"build:client": "node scripts/build-client.mjs",
|
|
46
|
+
"build:check": "node scripts/build-client.mjs --check",
|
|
47
|
+
"pretest": "node scripts/build-client.mjs && node scripts/lint.mjs && node scripts/pack-check.mjs",
|
|
48
|
+
"lint": "node scripts/lint.mjs",
|
|
49
|
+
"pack:check": "node scripts/pack-check.mjs"
|
|
50
|
+
},
|
|
51
|
+
"dsh": {
|
|
52
|
+
"bundle": {
|
|
53
|
+
"patch": "./cordis.patch.yml"
|
|
54
|
+
},
|
|
55
|
+
"client": {
|
|
56
|
+
"platform": "web",
|
|
57
|
+
"inject": [
|
|
58
|
+
"@deepseek-ai/dsh-client-ui-slots",
|
|
59
|
+
"@deepseek-ai/dsh-client-locale",
|
|
60
|
+
"@deepseek-ai/dsh-client-ui-settings"
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
66
|
+
"@deepseek-ai/dsh-tools": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
67
|
+
"@deepseek-ai/dsh-credentials": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
68
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
69
|
+
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
70
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
71
|
+
}
|
|
72
|
+
}
|