chore: prepare GoodBuddy 0.8.2
Cross-platform packages / Validate source (push) Waiting to run
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, macos, macos-15) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, windows, windows-2025) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, linux, ubuntu-24.04) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, macos, macos-15-intel) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, windows, windows-2025) (push) Blocked by required conditions
Cross-platform packages / Publish GitHub Release (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, linux, ubuntu-24.04-arm) (push) Blocked by required conditions

This commit is contained in:
lofyer
2026-08-06 22:47:13 +08:00
parent 8d00e6371d
commit b8fc7bc86e
114 changed files with 22916 additions and 1560 deletions
@@ -0,0 +1,144 @@
import { describe, expect, it, vi } from 'vitest'
import {
SPEECH_TRANSCRIPTION_SAMPLE_RATE,
type SpeechTranscriptionInput
} from '../../shared/speech-model-contracts'
import {
SpeechTranscriptionService,
createSherpaRecognizerConfig
} from './speech-transcription-service'
import type { SelectedSpeechRuntimeModel } from './speech-model-manager'
const requestId = '00000000-0000-4000-8000-000000000001'
function whisperModel(): SelectedSpeechRuntimeModel {
return {
id: 'whisper-tiny-multilingual',
family: 'whisper',
directory: 'C:\\models\\whisper',
files: [
{
name: 'tiny-encoder.int8.onnx',
role: 'encoder',
size: 1,
sha256: 'a'.repeat(64)
},
{
name: 'tiny-decoder.int8.onnx',
role: 'decoder',
size: 1,
sha256: 'b'.repeat(64)
},
{
name: 'tiny-tokens.txt',
role: 'tokens',
size: 1,
sha256: 'c'.repeat(64)
}
]
}
}
function input(): SpeechTranscriptionInput {
return {
requestId,
sampleRate: SPEECH_TRANSCRIPTION_SAMPLE_RATE,
audio: new Float32Array([0, 0.25, -0.25]).buffer
}
}
describe('SpeechTranscriptionService', () => {
it('wires the selected Whisper files to bounded local inference', async () => {
const runner = vi.fn(async () => ' 本地识别结果 ')
const service = new SpeechTranscriptionService(
{
getSelectedRuntimeModel: vi.fn(async () => whisperModel())
},
runner
)
await expect(service.transcribe(input())).resolves.toEqual({
text: '本地识别结果'
})
expect(runner).toHaveBeenCalledWith(
createSherpaRecognizerConfig(whisperModel()),
expect.any(Float32Array),
SPEECH_TRANSCRIPTION_SAMPLE_RATE,
expect.any(AbortSignal)
)
expect(
createSherpaRecognizerConfig(whisperModel()).modelConfig.whisper
?.language
).toBe('')
})
it('requires an installed selected model and rejects oversized audio', async () => {
const service = new SpeechTranscriptionService(
{
getSelectedRuntimeModel: vi.fn(async () => undefined)
},
vi.fn()
)
await expect(service.transcribe(input())).rejects.toThrow(
'安装并选择本地语音模型'
)
await expect(
service.transcribe({
...input(),
audio: new ArrayBuffer(
SPEECH_TRANSCRIPTION_SAMPLE_RATE * 20 * 4 + 4
)
})
).rejects.toThrow('录音数据')
})
it('aborts active inference and cleans up cancellation state', async () => {
const runner = vi.fn(
(
_config: unknown,
_samples: Float32Array,
_sampleRate: number,
signal: AbortSignal
) =>
new Promise<string>((_resolve, reject) => {
signal.addEventListener(
'abort',
() => reject(new Error('cancelled by test')),
{ once: true }
)
})
)
const service = new SpeechTranscriptionService(
{
getSelectedRuntimeModel: vi.fn(async () => whisperModel())
},
runner
)
const transcription = service.transcribe(input())
await vi.waitFor(() => expect(runner).toHaveBeenCalledOnce())
expect(service.cancel(requestId)).toBe(true)
await expect(transcription).rejects.toThrow('cancelled by test')
expect(service.cancel(requestId)).toBe(false)
})
it('surfaces inference failures and frees the request for retry', async () => {
const runner = vi.fn(async () => {
throw new Error('Runtime failed')
})
const service = new SpeechTranscriptionService(
{
getSelectedRuntimeModel: vi.fn(async () => whisperModel())
},
runner
)
await expect(service.transcribe(input())).rejects.toThrow(
'Runtime failed'
)
await expect(service.transcribe(input())).rejects.toThrow(
'Runtime failed'
)
})
})