50 lines
3.1 KiB
JavaScript
50 lines
3.1 KiB
JavaScript
import test from 'node:test'
|
||
import assert from 'node:assert/strict'
|
||
import { VoiceDispatchGate } from '../src/behavior.mjs'
|
||
import { VoiceSession } from '../src/voice.mjs'
|
||
|
||
test('IDE result cannot resurrect pending audio consent', async () => {
|
||
const voice = new VoiceSession({ onText() {} }); voice.ready = true; voice.send = () => {}
|
||
voice.audioTranscript = 'Bunu yap'; voice.dispatchGate.input('Bunu yap')
|
||
voice.result({ taskId: 'done', status: 'complete', text: 'Bunu yap' })
|
||
assert.equal(voice.audioTranscript, '')
|
||
assert.throws(() => voice.dispatchGate.claim('Bunu yap', 'execute'))
|
||
})
|
||
|
||
for (const phrase of ['Tamam, bunu yap.', 'Bu görevi gönder', 'Lütfen araştır', 'Şimdi başlat', 'Evet uygula']) {
|
||
test(`direct current instruction: ${phrase}`, () => {
|
||
const gate = new VoiceDispatchGate(); gate.input(phrase)
|
||
assert.equal(gate.claim(phrase, 'research'), 1)
|
||
assert.throws(() => gate.claim(phrase, 'research'))
|
||
})
|
||
}
|
||
for (const phrase of ['Bunu yapma', 'Bunu yap mı', 'Bunu yapabilir miyiz?', '“Bunu yap” dedi', 'Yapsak nasıl olur', 'Hayır, bekle', 'Tamam']) {
|
||
test(`discussion is not dispatch permission: ${phrase}`, () => {
|
||
const gate = new VoiceDispatchGate(); gate.input(phrase)
|
||
assert.throws(() => gate.claim(phrase, 'execute'))
|
||
})
|
||
}
|
||
test('old consent, unfinished speech, research escalation and stopped session fail closed', () => {
|
||
const gate = new VoiceDispatchGate(); gate.input('Bunu yap'); gate.input('Hayır bekle')
|
||
assert.throws(() => gate.claim('Bunu yap', 'execute'))
|
||
gate.input('Araştır'); assert.throws(() => gate.claim('Araştır', 'execute'))
|
||
gate.input('Bunu ', false); assert.throws(() => gate.claim('Araştır', 'research'))
|
||
gate.input('yap', true); assert.equal(gate.claim('Bunu yap', 'execute'), 4)
|
||
gate.invalidate(); assert.throws(() => gate.claim('Bunu yap', 'execute'))
|
||
})
|
||
test('voice dispatch uses actual user text once; no model-generated permission or success', async () => {
|
||
const sends = [], responses = []
|
||
const voice = new VoiceSession({ onText() {}, onDraft() {}, onSubmit: async (...args) => { sends.push(args); return { accepted: true, completed: false } } })
|
||
voice.send = frame => responses.push(frame)
|
||
const args = { intent: 'research', objective: 'İncele', scope: 'Android', context: 'Yeşil seçildi', constraints: 'Değiştirme', output: 'Rapor', completion: 'Kanıt', userInstruction: 'Araştır' }
|
||
const frame = { data: JSON.stringify({ toolCall: { functionCalls: [{ id: '1', name: 'submit_task', args }] } }) }
|
||
await voice.receive(frame); assert.equal(sends.length, 0)
|
||
await voice.receive({ data: JSON.stringify({ toolCall: { functionCalls: [{ id: 'draft', name: 'prepare_task', args }] } }) })
|
||
responses.length = 0
|
||
await voice.receive({ data: JSON.stringify({ serverContent: { inputTranscription: { text: 'Araştır' } } }) })
|
||
await voice.receive(frame); await voice.receive(frame)
|
||
assert.equal(sends.length, 1)
|
||
assert.deepEqual(responses[0].toolResponse.functionResponses[0].response, { accepted: true, completed: false })
|
||
assert.ok(responses[1].toolResponse.functionResponses[0].response.error)
|
||
})
|