speechflow 2.4.0 → 2.4.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 (34) hide show
  1. package/.ase/service.log +85 -0
  2. package/.ase/service.yaml +1 -0
  3. package/CHANGELOG.md +16 -2
  4. package/package.json +3 -3
  5. package/speechflow-cli/dst/speechflow-main-api.js +8 -1
  6. package/speechflow-cli/dst/speechflow-main-api.js.map +1 -1
  7. package/speechflow-cli/dst/speechflow-node-a2a-mute.js +5 -1
  8. package/speechflow-cli/dst/speechflow-node-a2a-mute.js.map +1 -1
  9. package/speechflow-cli/dst/speechflow-node-t2t-google.js +3 -0
  10. package/speechflow-cli/dst/speechflow-node-t2t-google.js.map +1 -1
  11. package/speechflow-cli/dst/speechflow-node-t2t-proofread.js +17 -9
  12. package/speechflow-cli/dst/speechflow-node-t2t-proofread.js.map +1 -1
  13. package/speechflow-cli/dst/speechflow-node-t2t-sentence.js +20 -3
  14. package/speechflow-cli/dst/speechflow-node-t2t-sentence.js.map +1 -1
  15. package/speechflow-cli/dst/speechflow-util-llm.js +1 -1
  16. package/speechflow-cli/dst/speechflow-util-llm.js.map +1 -1
  17. package/speechflow-cli/etc/oxlint.jsonc +1 -0
  18. package/speechflow-cli/etc/stx.conf +2 -2
  19. package/speechflow-cli/package.json +11 -8
  20. package/speechflow-cli/src/speechflow-main-api.ts +8 -1
  21. package/speechflow-cli/src/speechflow-node-a2a-mute.ts +6 -1
  22. package/speechflow-cli/src/speechflow-node-t2t-google.ts +3 -0
  23. package/speechflow-cli/src/speechflow-node-t2t-proofread.ts +17 -9
  24. package/speechflow-cli/src/speechflow-node-t2t-sentence.ts +21 -3
  25. package/speechflow-cli/src/speechflow-util-llm.ts +1 -1
  26. package/speechflow-ui-db/etc/stx.conf +2 -2
  27. package/speechflow-ui-db/package.json +5 -5
  28. package/speechflow-ui-st/dst/index.css +1 -1
  29. package/speechflow-ui-st/etc/stx.conf +2 -2
  30. package/speechflow-ui-st/package.json +5 -5
  31. package/speechflow-ui-st/src/app.vue +3 -3
  32. /package/speechflow-cli/package.d/{@typescript-eslint+typescript-estree+8.59.3.patch → @typescript-eslint+typescript-estree+8.60.0.patch} +0 -0
  33. /package/speechflow-ui-db/package.d/{@typescript-eslint+typescript-estree+8.59.3.patch → @typescript-eslint+typescript-estree+8.60.0.patch} +0 -0
  34. /package/speechflow-ui-st/package.d/{@typescript-eslint+typescript-estree+8.59.3.patch → @typescript-eslint+typescript-estree+8.60.0.patch} +0 -0
@@ -26,15 +26,15 @@
26
26
  "deepl-node": "1.27.0",
27
27
  "@elevenlabs/elevenlabs-js": "2.49.1",
28
28
  "get-stream": "9.0.1",
29
- "@dotenvx/dotenvx": "1.69.1",
29
+ "@dotenvx/dotenvx": "1.69.2",
30
30
  "speex-resampler": "3.0.1",
31
31
  "@sapphi-red/speex-preprocess-wasm": "0.4.0",
32
32
  "@shiguredo/rnnoise-wasm": "2025.1.5",
33
33
  "sherpa-onnx": "1.12.25",
34
34
  "axios": "1.16.1",
35
- "@aws-sdk/client-transcribe-streaming": "3.1056.0",
36
- "@aws-sdk/client-translate": "3.1056.0",
37
- "@aws-sdk/client-polly": "3.1056.0",
35
+ "@aws-sdk/client-transcribe-streaming": "3.1057.0",
36
+ "@aws-sdk/client-translate": "3.1057.0",
37
+ "@aws-sdk/client-polly": "3.1057.0",
38
38
  "@google-cloud/translate": "9.4.1",
39
39
  "@google-cloud/speech": "7.3.1",
40
40
  "@google-cloud/text-to-speech": "6.4.1",
@@ -91,9 +91,9 @@
91
91
  "eslint-plugin-promise": "7.3.0",
92
92
  "eslint-plugin-import": "2.32.0",
93
93
  "eslint-plugin-node": "11.1.0",
94
- "typescript-eslint": "8.59.3",
95
- "@typescript-eslint/eslint-plugin": "8.59.3",
96
- "@typescript-eslint/parser": "8.59.3",
94
+ "typescript-eslint": "8.60.0",
95
+ "@typescript-eslint/eslint-plugin": "8.60.0",
96
+ "@typescript-eslint/parser": "8.60.0",
97
97
  "oxlint": "1.67.0",
98
98
  "oxlint-plugin-complexity": "2.1.3",
99
99
  "eslint-plugin-oxlint": "1.67.0",
@@ -136,7 +136,10 @@
136
136
  "!@deepgram/sdk",
137
137
  "!sherpa-onnx",
138
138
  "!eslint",
139
- "!@eslint/js"
139
+ "!@eslint/js",
140
+ "!@google/genai",
141
+ "!@huggingface/transformers",
142
+ "!@soundtouchjs/audio-worklet"
140
143
  ],
141
144
  "engines": {
142
145
  "node": ">=22.0.0"
@@ -64,7 +64,14 @@ export class APIServer {
64
64
  if (req.request !== "COMMAND")
65
65
  throw new Error("invalid external request (command expected)")
66
66
  const name = req.node as string
67
- const argList = req.args as any[]
67
+ const argList = (req.args as any[]).map((arg) => {
68
+ if (arg === "true" || arg === "false")
69
+ return (arg === "true")
70
+ else if (arg.match(/^\d+$/))
71
+ return Number.parseInt(arg, 10)
72
+ else
73
+ return arg
74
+ })
68
75
  const foundNode = graph.findGraphNode(name)
69
76
  if (foundNode === undefined) {
70
77
  this.cli.log("warning", `external request failed: no such node <${name}>`)
@@ -31,7 +31,9 @@ export default class SpeechFlowNodeA2AMute extends SpeechFlowNode {
31
31
  super(id, cfg, opts, args)
32
32
 
33
33
  /* declare node configuration parameters */
34
- this.configure({})
34
+ this.configure({
35
+ muteMode: { type: "string", val: "none", pos: 0, match: /^(?:none|silenced|unplugged)$/ }
36
+ })
35
37
 
36
38
  /* declare node input/output format */
37
39
  this.input = "audio"
@@ -75,6 +77,9 @@ export default class SpeechFlowNodeA2AMute extends SpeechFlowNode {
75
77
  /* clear destruction flag */
76
78
  this.closing = false
77
79
 
80
+ /* determine initial mute mode */
81
+ this.muteMode = this.params.muteMode as MuteMode
82
+
78
83
  /* establish a transform stream */
79
84
  const self = this
80
85
  this.stream = new Stream.Transform({
@@ -86,6 +86,7 @@ export default class SpeechFlowNodeT2TGoogle extends SpeechFlowNode {
86
86
  })
87
87
 
88
88
  /* establish a transform stream and connect it to Google Translate */
89
+ const self = this
89
90
  this.stream = new Stream.Transform({
90
91
  readableObjectMode: true,
91
92
  writableObjectMode: true,
@@ -99,7 +100,9 @@ export default class SpeechFlowNodeT2TGoogle extends SpeechFlowNode {
99
100
  callback()
100
101
  }
101
102
  else {
103
+ self.log("info", `receive text (${chunk.kind}): "${chunk.payload}"`)
102
104
  translate(chunk.payload).then((payload) => {
105
+ self.log("info", `send text (${chunk.kind}): "${payload}"`)
103
106
  const chunkNew = chunk.clone()
104
107
  chunkNew.payload = payload
105
108
  this.push(chunkNew)
@@ -119,12 +119,14 @@ export default class SpeechFlowNodeT2TProofread extends SpeechFlowNode {
119
119
  const cfg = this.setup[this.params.lang]
120
120
  if (!cfg)
121
121
  throw new Error(`unsupported language: ${this.params.lang}`)
122
- this.log("info", `PROMPT "${cfg.systemPrompt}", chat: ${JSON.stringify(cfg.chat)}`)
123
- return llm.complete({
122
+ this.log("info", `input: "${text}"`)
123
+ const output = await llm.complete({
124
124
  system: cfg.systemPrompt,
125
125
  messages: cfg.chat,
126
126
  prompt: text
127
127
  })
128
+ this.log("info", `output: "${output}"`)
129
+ return output
128
130
  }
129
131
 
130
132
  /* establish a transform stream and connect it to LLM */
@@ -141,14 +143,20 @@ export default class SpeechFlowNodeT2TProofread extends SpeechFlowNode {
141
143
  callback()
142
144
  }
143
145
  else {
144
- proofread(chunk.payload).then((payload) => {
145
- const chunkNew = chunk.clone()
146
- chunkNew.payload = payload
147
- this.push(chunkNew)
146
+ if (chunk.kind === "final") {
147
+ proofread(chunk.payload).then((payload) => {
148
+ const chunkNew = chunk.clone()
149
+ chunkNew.payload = payload
150
+ this.push(chunkNew)
151
+ callback()
152
+ }).catch((error: unknown) => {
153
+ callback(util.ensureError(error))
154
+ })
155
+ }
156
+ else {
157
+ this.push(chunk)
148
158
  callback()
149
- }).catch((error: unknown) => {
150
- callback(util.ensureError(error))
151
- })
159
+ }
152
160
  }
153
161
  },
154
162
  final (callback) {
@@ -324,12 +324,30 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
324
324
  return
325
325
  }
326
326
  if (element.chunk.kind === "intermediate") {
327
- self.queueRecv.walk(-1)
328
- self.queueRecv.delete()
327
+ /* the trailing element is a (speculative) intermediate chunk:
328
+ if the newly arrived chunk carries the very same intermediate
329
+ payload (Deepgram re-sends identical intermediates), treat it
330
+ as a no-op to avoid churning the queue (delete+append) and
331
+ re-emitting an unchanged preview */
332
+ if (chunk.kind === "intermediate"
333
+ && (element.chunk.payload as string) === (chunk.payload as string)) {
334
+ self.lastChunkTime = Date.now()
335
+ callback()
336
+ return
337
+ }
338
+
339
+ /* remove the trailing intermediate silently, so the
340
+ transient half-mutated queue (intermediate deleted, but
341
+ replacement not yet appended) does NOT emit a "write"
342
+ event and trigger a premature flush that would emit a
343
+ truncated preview and oscillate the dashboard preview */
344
+ self.queue.silently(() => {
345
+ self.queueRecv.walk(-1)
346
+ self.queueRecv.delete()
347
+ })
329
348
  }
330
349
  }
331
350
  }
332
- previewedPayload = ""
333
351
  self.queueRecv.append({ type: "text-frame", chunk, complete: false })
334
352
  self.lastChunkTime = Date.now()
335
353
  callback()
@@ -61,7 +61,7 @@ export class LLM extends EventEmitter {
61
61
  api: "",
62
62
  model: "",
63
63
  key: "",
64
- timeout: 30 * 1000,
64
+ timeout: 240 * 1000,
65
65
  temperature: 0.7,
66
66
  maxTokens: 1024,
67
67
  cacheDir: "",
@@ -24,8 +24,8 @@ lint-watch
24
24
  lint
25
25
  check-dependencies && \
26
26
  vue-tsc --project etc/tsc-client.json --noEmit && \
27
- oxlint --config etc/oxlint.jsonc src/*.vue src/*.ts && \
28
- eslint --config etc/eslint.mjs src/*.vue src/*.ts && \
27
+ oxlint --config etc/oxlint.jsonc src && \
28
+ eslint --config etc/eslint.mjs src && \
29
29
  stylelint --config etc/stylelint.yaml src/*.styl src/*.vue && \
30
30
  htmllint --rc etc/htmllint.json src/*.html
31
31
 
@@ -26,11 +26,11 @@
26
26
  },
27
27
  "devDependencies": {
28
28
  "vite": "7.3.1",
29
- "typescript-eslint": "8.59.3",
30
- "@typescript-eslint/eslint-plugin": "8.59.3",
31
- "@typescript-eslint/parser": "8.59.3",
29
+ "typescript-eslint": "8.60.0",
30
+ "@typescript-eslint/eslint-plugin": "8.60.0",
31
+ "@typescript-eslint/parser": "8.60.0",
32
32
  "@vitejs/plugin-vue": "6.0.7",
33
- "@rollup/plugin-yaml": "4.1.2",
33
+ "@rollup/plugin-yaml": "5.0.0",
34
34
  "vite-plugin-node-polyfills": "0.28.0",
35
35
  "vite-svg-loader": "5.1.1",
36
36
  "@liuli-util/vite-plugin-node": "0.10.0",
@@ -62,7 +62,7 @@
62
62
  "postcss-html": "1.8.1",
63
63
  "stylus": "0.64.0",
64
64
  "typescript": "6.0.3",
65
- "vue-tsc": "3.3.2",
65
+ "vue-tsc": "3.3.3",
66
66
  "delay-cli": "3.0.0",
67
67
  "cross-env": "10.1.0",
68
68
  "serve": "14.2.6",