speechflow 2.3.1 → 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 (79) hide show
  1. package/.ase/service.log +10357 -0
  2. package/.ase/service.yaml +1 -0
  3. package/.claude/CLAUDE.md +1 -0
  4. package/AGENTS.md +1 -1
  5. package/CHANGELOG.md +25 -1
  6. package/README.md +10 -37
  7. package/package.json +8 -8
  8. package/speechflow-cli/dst/speechflow-main-api.js +8 -1
  9. package/speechflow-cli/dst/speechflow-main-api.js.map +1 -1
  10. package/speechflow-cli/dst/speechflow-main-graph.js +14 -5
  11. package/speechflow-cli/dst/speechflow-main-graph.js.map +1 -1
  12. package/speechflow-cli/dst/speechflow-node-a2a-mute.js +5 -1
  13. package/speechflow-cli/dst/speechflow-node-a2a-mute.js.map +1 -1
  14. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.d.ts +7 -0
  15. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js +145 -62
  16. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js.map +1 -1
  17. package/speechflow-cli/dst/speechflow-node-a2t-google.js +10 -4
  18. package/speechflow-cli/dst/speechflow-node-a2t-google.js.map +1 -1
  19. package/speechflow-cli/dst/speechflow-node-a2t-openai.js +10 -4
  20. package/speechflow-cli/dst/speechflow-node-a2t-openai.js.map +1 -1
  21. package/speechflow-cli/dst/speechflow-node-t2t-google.js +3 -0
  22. package/speechflow-cli/dst/speechflow-node-t2t-google.js.map +1 -1
  23. package/speechflow-cli/dst/{speechflow-node-t2t-spellcheck.d.ts → speechflow-node-t2t-proofread.d.ts} +1 -1
  24. package/speechflow-cli/dst/{speechflow-node-t2t-spellcheck.js → speechflow-node-t2t-proofread.js} +53 -61
  25. package/speechflow-cli/dst/speechflow-node-t2t-proofread.js.map +1 -0
  26. package/speechflow-cli/dst/speechflow-node-t2t-sentence.js +64 -14
  27. package/speechflow-cli/dst/speechflow-node-t2t-sentence.js.map +1 -1
  28. package/speechflow-cli/dst/speechflow-node-t2t-summary.js +1 -1
  29. package/speechflow-cli/dst/speechflow-node-t2t-summary.js.map +1 -1
  30. package/speechflow-cli/dst/speechflow-node-t2t-translate.js +1 -1
  31. package/speechflow-cli/dst/speechflow-node-t2t-translate.js.map +1 -1
  32. package/speechflow-cli/dst/speechflow-node-xio-device.js +4 -1
  33. package/speechflow-cli/dst/speechflow-node-xio-device.js.map +1 -1
  34. package/speechflow-cli/dst/speechflow-node-xio-exec.js +4 -1
  35. package/speechflow-cli/dst/speechflow-node-xio-exec.js.map +1 -1
  36. package/speechflow-cli/dst/speechflow-util-llm.d.ts +1 -0
  37. package/speechflow-cli/dst/speechflow-util-llm.js +7 -3
  38. package/speechflow-cli/dst/speechflow-util-llm.js.map +1 -1
  39. package/speechflow-cli/dst/speechflow-util-misc.js +28 -14
  40. package/speechflow-cli/dst/speechflow-util-misc.js.map +1 -1
  41. package/speechflow-cli/dst/speechflow.js.map +1 -1
  42. package/speechflow-cli/etc/oxlint.jsonc +10 -2
  43. package/speechflow-cli/etc/stx.conf +2 -2
  44. package/speechflow-cli/package.d/{@typescript-eslint+typescript-estree+8.57.2.patch → @typescript-eslint+typescript-estree+8.60.0.patch} +1 -1
  45. package/speechflow-cli/package.json +34 -31
  46. package/speechflow-cli/src/speechflow-main-api.ts +8 -1
  47. package/speechflow-cli/src/speechflow-main-graph.ts +14 -5
  48. package/speechflow-cli/src/speechflow-node-a2a-mute.ts +6 -1
  49. package/speechflow-cli/src/speechflow-node-a2t-deepgram.ts +156 -66
  50. package/speechflow-cli/src/speechflow-node-a2t-google.ts +10 -4
  51. package/speechflow-cli/src/speechflow-node-a2t-openai.ts +10 -4
  52. package/speechflow-cli/src/speechflow-node-t2t-google.ts +3 -0
  53. package/speechflow-cli/src/{speechflow-node-t2t-spellcheck.ts → speechflow-node-t2t-proofread.ts} +61 -66
  54. package/speechflow-cli/src/speechflow-node-t2t-sentence.ts +21 -3
  55. package/speechflow-cli/src/speechflow-node-t2t-summary.ts +1 -1
  56. package/speechflow-cli/src/speechflow-node-t2t-translate.ts +1 -1
  57. package/speechflow-cli/src/speechflow-node-xio-device.ts +4 -1
  58. package/speechflow-cli/src/speechflow-node-xio-exec.ts +4 -1
  59. package/speechflow-cli/src/speechflow-util-llm.ts +8 -3
  60. package/speechflow-cli/src/speechflow-util-misc.ts +33 -16
  61. package/speechflow-cli/src/speechflow.ts +1 -0
  62. package/speechflow-ui-db/dst/index.js +19 -16
  63. package/speechflow-ui-db/etc/oxlint.jsonc +0 -1
  64. package/speechflow-ui-db/etc/stx.conf +2 -2
  65. package/speechflow-ui-db/package.d/{@typescript-eslint+typescript-estree+8.57.2.patch → @typescript-eslint+typescript-estree+8.60.0.patch} +1 -1
  66. package/speechflow-ui-db/package.json +16 -16
  67. package/speechflow-ui-st/dst/index.css +1 -1
  68. package/speechflow-ui-st/dst/index.js +33 -33
  69. package/speechflow-ui-st/etc/oxlint.jsonc +2 -2
  70. package/speechflow-ui-st/etc/stx.conf +2 -2
  71. package/speechflow-ui-st/package.d/{@typescript-eslint+typescript-estree+8.57.2.patch → @typescript-eslint+typescript-estree+8.60.0.patch} +1 -1
  72. package/speechflow-ui-st/package.json +16 -16
  73. package/speechflow-ui-st/src/app.vue +3 -3
  74. package/.claude/settings.local.json +0 -3
  75. package/speechflow-cli/dst/speechflow-node-t2t-punctuation.d.ts +0 -13
  76. package/speechflow-cli/dst/speechflow-node-t2t-punctuation.js +0 -219
  77. package/speechflow-cli/dst/speechflow-node-t2t-punctuation.js.map +0 -1
  78. package/speechflow-cli/dst/speechflow-node-t2t-spellcheck.js.map +0 -1
  79. package/speechflow-cli/src/speechflow-node-t2t-punctuation.ts +0 -200
@@ -192,7 +192,10 @@ export default class SpeechFlowNodeXIODevice extends SpeechFlowNode {
192
192
 
193
193
  /* pass-through PortAudio errors */
194
194
  this.io!.on("error", (err) => {
195
- this.emit("error", err)
195
+ /* NOTICE: do not emit("error") on the node itself, since nothing
196
+ listens for it and it would become an uncaughtException tearing
197
+ down the whole graph. Route via the stream instead, where it is
198
+ handled by the graph supervisor. */
196
199
  this.stream?.emit("error", err)
197
200
  })
198
201
 
@@ -95,7 +95,10 @@ export default class SpeechFlowNodeXIOExec extends SpeechFlowNode {
95
95
  /* handle subprocess errors */
96
96
  this.subprocess.on("error", (err) => {
97
97
  this.log("error", `subprocess error: ${err.message}`)
98
- this.emit("error", err)
98
+ /* NOTICE: do not emit("error") on the node itself, since nothing
99
+ listens for it and it would become an uncaughtException tearing
100
+ down the whole graph. Route via the stream instead, where it is
101
+ handled by the graph supervisor. */
99
102
  if (this.stream !== null && !this.stream.destroyed)
100
103
  this.stream.emit("error", err)
101
104
  })
@@ -31,6 +31,7 @@ export type LLMConfig = {
31
31
  temperature?: number
32
32
  maxTokens?: number
33
33
  cacheDir?: string
34
+ thinking?: boolean
34
35
  }
35
36
  export type LLMCompleteOptions = {
36
37
  system?: string
@@ -60,10 +61,11 @@ export class LLM extends EventEmitter {
60
61
  api: "",
61
62
  model: "",
62
63
  key: "",
63
- timeout: 30 * 1000,
64
+ timeout: 240 * 1000,
64
65
  temperature: 0.7,
65
66
  maxTokens: 1024,
66
67
  cacheDir: "",
68
+ thinking: false,
67
69
  ...config
68
70
  } as Required<LLMConfig>
69
71
 
@@ -255,7 +257,8 @@ export class LLM extends EventEmitter {
255
257
  max_tokens: this.config.maxTokens,
256
258
  temperature: this.config.temperature,
257
259
  system: systemMessage?.content,
258
- messages: chatMessages as Anthropic.MessageParam[]
260
+ messages: chatMessages as Anthropic.MessageParam[],
261
+ ...(!this.config.thinking ? { thinking: { type: "disabled" } } : {})
259
262
  }).catch((err) => {
260
263
  throw new Error(`failed to perform Anthropic chat completion: ${err}`, { cause: err })
261
264
  })
@@ -284,7 +287,8 @@ export class LLM extends EventEmitter {
284
287
  config: {
285
288
  maxOutputTokens: this.config.maxTokens,
286
289
  temperature: this.config.temperature,
287
- ...(systemInstruction ? { systemInstruction } : {})
290
+ ...(systemInstruction ? { systemInstruction } : {}),
291
+ ...(!this.config.thinking ? { thinkingConfig: { thinkingBudget: 0 } } : {})
288
292
  }
289
293
  }).catch((err) => {
290
294
  throw new Error(`failed to perform Google chat completion: ${err}`, { cause: err })
@@ -303,6 +307,7 @@ export class LLM extends EventEmitter {
303
307
  model: this.config.model,
304
308
  messages,
305
309
  keep_alive: "10m",
310
+ think: this.config.thinking,
306
311
  options: {
307
312
  num_predict: this.config.maxTokens,
308
313
  temperature: this.config.temperature
@@ -46,35 +46,52 @@ export const deepClone = (value: any): any => {
46
46
  }
47
47
 
48
48
  /* sleep: wait a duration of time and then resolve */
49
- export function sleep (durationMs: number, signal?: AbortSignal) {
49
+ export function sleep (durationMs: number, signal?: AbortSignal): Promise<void> {
50
50
  return new Promise<void>((resolve) => {
51
- const ac = new AbortController()
52
- const timer = setTimeout(() => {
53
- ac.abort()
51
+ const ac: AbortController | undefined =
52
+ signal !== undefined ? new AbortController() : undefined
53
+ let timer: ReturnType<typeof setTimeout> | null = setTimeout(() => {
54
+ timer = null
55
+ if (signal !== undefined)
56
+ ac!.abort()
54
57
  resolve()
55
58
  }, durationMs)
56
59
  timer.unref()
57
- if (signal !== undefined)
58
- signal.addEventListener("abort", () => {
59
- clearTimeout(timer)
60
+ if (signal !== undefined) {
61
+ if (signal.aborted)
60
62
  resolve()
61
- }, { once: true, signal: ac.signal })
63
+ else
64
+ signal.addEventListener("abort", () => {
65
+ if (timer !== null)
66
+ clearTimeout(timer)
67
+ resolve()
68
+ }, { once: true, signal: ac!.signal })
69
+ }
62
70
  })
63
71
  }
64
72
 
65
73
  /* timeout: wait a duration of time and then reject */
66
- export function timeout (durationMs: number, info = "timeout", signal?: AbortSignal) {
74
+ export function timeout (durationMs: number, info = "timeout", signal?: AbortSignal): Promise<never> {
67
75
  return new Promise<never>((resolve, reject) => {
68
- const ac = new AbortController()
69
- const timer = setTimeout(() => {
70
- ac.abort()
76
+ const ac: AbortController | undefined =
77
+ signal !== undefined ? new AbortController() : undefined
78
+ let timer: ReturnType<typeof setTimeout> | null = setTimeout(() => {
79
+ timer = null
80
+ if (signal !== undefined)
81
+ ac!.abort()
71
82
  reject(new Error(info))
72
83
  }, durationMs)
73
84
  timer.unref()
74
- if (signal !== undefined)
75
- signal.addEventListener("abort", () => {
76
- clearTimeout(timer)
85
+ if (signal !== undefined) {
86
+ if (signal.aborted)
77
87
  resolve(undefined as never)
78
- }, { once: true, signal: ac.signal })
88
+ else
89
+ signal.addEventListener("abort", () => {
90
+ if (timer !== null)
91
+ clearTimeout(timer)
92
+ resolve(undefined as never)
93
+ }, { once: true, signal: ac!.signal })
94
+ }
79
95
  })
80
96
  }
97
+
@@ -7,5 +7,6 @@
7
7
 
8
8
  /* pass-through control to the main module */
9
9
  import Main from "./speechflow-main"
10
+
10
11
  Main.main()
11
12