fix: reconcile uncertain voice admission with bounded cancellation
This commit is contained in:
1 parent
0cb00e6095
commit
0c57217ad9
3 files changed
+40
-4
No files matched your search
@@ -65,6 +65,7 @@ class ConversationStream(llm.LLMStream):
|
||||
if not text.strip(): raise HermesLLMError('empty_voice_turn')
|
||||
timer = None
|
||||
admission = None
|
||||
admission_rejected = False
|
||||
try:
|
||||
# Do not abandon uncertain admission on barge-in. A successfully
|
||||
# admitted remote action must be identified and cancelled, not left
|
||||
@@ -72,7 +73,9 @@ class ConversationStream(llm.LLMStream):
|
||||
admission = asyncio.create_task(self.bridge.client.post(self.bridge.root + '/messages', headers=self.bridge.headers,
|
||||
json={'content': text, 'idempotency_key': self.operation_id, 'modality': 'voice'}, timeout=httpx.Timeout(20, connect=5)))
|
||||
response = await asyncio.shield(admission)
|
||||
if response.status_code != 202: raise HermesLLMError('voice_admission_failed')
|
||||
if response.status_code != 202:
|
||||
admission_rejected = 400 <= response.status_code < 500
|
||||
raise HermesLLMError('voice_admission_failed')
|
||||
self.run_id = response.json()['run']['id']
|
||||
await self.progress('working', 'Working on your request.')
|
||||
timer = asyncio.create_task(self.notice())
|
||||
@@ -117,17 +120,25 @@ class ConversationStream(llm.LLMStream):
|
||||
# admission, then return the run identity for cancellation.
|
||||
try:
|
||||
admitted = await self.bridge.client.post(self.bridge.root + '/messages', headers=self.bridge.headers,
|
||||
json={'content': text, 'idempotency_key': self.operation_id, 'modality': 'voice'})
|
||||
json={'content': text, 'idempotency_key': self.operation_id, 'modality': 'voice'}, timeout=httpx.Timeout(20, connect=5))
|
||||
if admitted.status_code == 202:
|
||||
self.run_id = admitted.json()['run']['id']
|
||||
except Exception: pass
|
||||
if self.run_id:
|
||||
try:
|
||||
await asyncio.shield(self.bridge.client.post(self.bridge.root + '/runs/' + self.run_id + '/cancel', headers=self.bridge.headers))
|
||||
await asyncio.shield(self.bridge.client.post(self.bridge.root + '/runs/' + self.run_id + '/cancel', headers=self.bridge.headers, timeout=httpx.Timeout(10, connect=5)))
|
||||
except Exception: pass
|
||||
await self.progress('failed', 'Request cancelled.')
|
||||
raise
|
||||
except Exception:
|
||||
# A failed HTTP receipt is not proof admission failed. Fail safely
|
||||
# by tombstoning the stable operation key, including when JSON/SSE
|
||||
# decoding failed after the coordinator already accepted the turn.
|
||||
if not admission_rejected:
|
||||
try:
|
||||
await self.bridge.client.post(self.bridge.root + '/operations/' + self.operation_id + '/cancel',
|
||||
headers=self.bridge.headers, timeout=httpx.Timeout(10, connect=5))
|
||||
except Exception: pass
|
||||
await self.progress('failed', 'Hope could not complete this response.')
|
||||
raise HermesLLMError('voice_coordinator_failed') from None
|
||||
finally:
|
||||
|
||||
Reference in new issue
Block a user