Archived
feat: harden voice API conversations and progress
This commit is contained in:
+19
-3
@@ -23,7 +23,9 @@ Use `Authorization: Bearer pwv1_...` on every HTTP and WebSocket connection. The
|
||||
|
||||
## HTTP
|
||||
|
||||
`GET /api/v1/voice/targets` returns only the caller's authorized registered workspaces plus effective scopes.
|
||||
`GET /api/v1/voice/targets` returns only the caller's authorized registered workspaces plus effective scopes. Use its `workspaces[].id` to choose a workspace; paths are returned for display but are never accepted as an API input.
|
||||
|
||||
`GET /api/v1/voice/conversations?workspaceId=<workspace-id>` lists prior Pi sessions rooted at that authorized workspace. This lets a device show a conversation picker without learning about sessions outside its workspace scope.
|
||||
|
||||
`POST /api/v1/voice/conversations`
|
||||
|
||||
@@ -36,7 +38,21 @@ Use `Authorization: Bearer pwv1_...` on every HTTP and WebSocket connection. The
|
||||
}
|
||||
```
|
||||
|
||||
The response is `201` and includes the opaque conversation id, session id, selected workspace, and `input-ready` status. `GET` and `DELETE /api/v1/voice/conversations/:id` inspect and close the API conversation handle.
|
||||
For an existing directory beneath the device-safe root `/home/hope/workspaces` that is not yet registered as a PI WEB workspace, use `POST /api/v1/voice/conversations/path` with `path` instead of `workspaceId`. The path must already exist, resolve beneath that root, and is validated before a session starts.
|
||||
|
||||
The response is `201` and includes the opaque conversation id, session id, selected workspace, and `input-ready` status. `GET /api/v1/voice/conversations/:id/models` lists the models currently available to that conversation's Pi session, filtered by the device token's model scope. `GET` and `DELETE /api/v1/voice/conversations/:id` inspect and close the API conversation handle.
|
||||
|
||||
To resume a listed session, create a new token-owned voice handle:
|
||||
|
||||
```json
|
||||
POST /api/v1/voice/conversations/resume
|
||||
{
|
||||
"workspaceId": "registered-workspace-id",
|
||||
"sessionId": "previous-pi-session-id"
|
||||
}
|
||||
```
|
||||
|
||||
The session must be in the selected workspace and within the caller's token scope.
|
||||
|
||||
## WebSocket wire protocol
|
||||
|
||||
@@ -77,7 +93,7 @@ Azure push-stream recognition emits `transcript.partial` and `transcript.final`
|
||||
|
||||
### Turn output and lifecycle
|
||||
|
||||
For either input form, the server emits `agent.working`, then `agent.accepted` after Pi accepted the prompt. It subscribes to the session event stream before submission and waits for Pi's native `agent.settled` event (not merely `agent.end`), with a two-minute turn timeout. `assistant.delta` is streamed while Pi answers; `assistant.final` contains only assistant text, never STT transcript.
|
||||
For either input form, the server emits `agent.working`, then `agent.accepted` after Pi accepted the prompt. While it waits for Pi's native `agent.settled` event (not merely `agent.end`), it repeats the existing `agent.working` frame every 15 seconds; those progress frames stop before `assistant.final` and never overlap synthesized audio. The wait has a two-minute turn timeout. `assistant.delta` is streamed while Pi answers; `assistant.final` contains only assistant text, never STT transcript.
|
||||
|
||||
Azure synthesis output is signed little-endian 16-bit, 24 kHz, mono PCM. Every binary server frame has this eight-byte header followed by PCM:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user