phonic 0.15.0 → 0.16.0
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.
- package/README.md +1 -7
- package/dist/index.d.mts +8 -5
- package/dist/index.d.ts +8 -5
- package/dist/index.js +49 -99
- package/dist/index.mjs +49 -99
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -96,7 +96,7 @@ if (error === null) {
|
|
|
96
96
|
To start a conversation, open a WebSocket connection:
|
|
97
97
|
|
|
98
98
|
```ts
|
|
99
|
-
const
|
|
99
|
+
const phonicWebSocket = phonic.sts.websocket({
|
|
100
100
|
input_format: "mulaw_8000",
|
|
101
101
|
|
|
102
102
|
// Optional fields
|
|
@@ -106,12 +106,6 @@ const { data, error } = await phonic.sts.websocket({
|
|
|
106
106
|
voice_id: "meredith",
|
|
107
107
|
output_format: "mulaw_8000"
|
|
108
108
|
});
|
|
109
|
-
|
|
110
|
-
if (error !== null) {
|
|
111
|
-
throw new Error(`Failed to start conversation: ${error.message}`);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const { phonicWebSocket } = data;
|
|
115
109
|
```
|
|
116
110
|
|
|
117
111
|
Stream input (user) audio chunks:
|
package/dist/index.d.mts
CHANGED
|
@@ -96,6 +96,9 @@ type PhonicSTSWebSocketResponseMessage = {
|
|
|
96
96
|
} | {
|
|
97
97
|
type: "is_user_speaking";
|
|
98
98
|
isUserSpeaking: boolean;
|
|
99
|
+
} | {
|
|
100
|
+
type: "interrupted_response";
|
|
101
|
+
interruptedResponse: string;
|
|
99
102
|
} | {
|
|
100
103
|
type: "error";
|
|
101
104
|
error: {
|
|
@@ -116,10 +119,13 @@ type OnErrorCallback = (event: WebSocket.ErrorEvent) => void;
|
|
|
116
119
|
|
|
117
120
|
declare class PhonicSTSWebSocket {
|
|
118
121
|
private readonly ws;
|
|
122
|
+
private readonly config;
|
|
119
123
|
private onMessageCallback;
|
|
120
124
|
private onCloseCallback;
|
|
121
125
|
private onErrorCallback;
|
|
122
|
-
|
|
126
|
+
private buffer;
|
|
127
|
+
private isOpen;
|
|
128
|
+
constructor(ws: WebSocket, config: PhonicSTSConfig);
|
|
123
129
|
onMessage(callback: OnMessageCallback): void;
|
|
124
130
|
onClose(callback: OnCloseCallback): void;
|
|
125
131
|
onError(callback: OnErrorCallback): void;
|
|
@@ -138,10 +144,7 @@ declare class PhonicSTSWebSocket {
|
|
|
138
144
|
declare class SpeechToSpeech {
|
|
139
145
|
private readonly phonic;
|
|
140
146
|
constructor(phonic: Phonic);
|
|
141
|
-
|
|
142
|
-
websocket(config: PhonicSTSConfig): DataOrError<{
|
|
143
|
-
phonicWebSocket: PhonicSTSWebSocket;
|
|
144
|
-
}>;
|
|
147
|
+
websocket(config: PhonicSTSConfig): PhonicSTSWebSocket;
|
|
145
148
|
}
|
|
146
149
|
|
|
147
150
|
type Voice = {
|
package/dist/index.d.ts
CHANGED
|
@@ -96,6 +96,9 @@ type PhonicSTSWebSocketResponseMessage = {
|
|
|
96
96
|
} | {
|
|
97
97
|
type: "is_user_speaking";
|
|
98
98
|
isUserSpeaking: boolean;
|
|
99
|
+
} | {
|
|
100
|
+
type: "interrupted_response";
|
|
101
|
+
interruptedResponse: string;
|
|
99
102
|
} | {
|
|
100
103
|
type: "error";
|
|
101
104
|
error: {
|
|
@@ -116,10 +119,13 @@ type OnErrorCallback = (event: WebSocket.ErrorEvent) => void;
|
|
|
116
119
|
|
|
117
120
|
declare class PhonicSTSWebSocket {
|
|
118
121
|
private readonly ws;
|
|
122
|
+
private readonly config;
|
|
119
123
|
private onMessageCallback;
|
|
120
124
|
private onCloseCallback;
|
|
121
125
|
private onErrorCallback;
|
|
122
|
-
|
|
126
|
+
private buffer;
|
|
127
|
+
private isOpen;
|
|
128
|
+
constructor(ws: WebSocket, config: PhonicSTSConfig);
|
|
123
129
|
onMessage(callback: OnMessageCallback): void;
|
|
124
130
|
onClose(callback: OnCloseCallback): void;
|
|
125
131
|
onError(callback: OnErrorCallback): void;
|
|
@@ -138,10 +144,7 @@ declare class PhonicSTSWebSocket {
|
|
|
138
144
|
declare class SpeechToSpeech {
|
|
139
145
|
private readonly phonic;
|
|
140
146
|
constructor(phonic: Phonic);
|
|
141
|
-
|
|
142
|
-
websocket(config: PhonicSTSConfig): DataOrError<{
|
|
143
|
-
phonicWebSocket: PhonicSTSWebSocket;
|
|
144
|
-
}>;
|
|
147
|
+
websocket(config: PhonicSTSConfig): PhonicSTSWebSocket;
|
|
145
148
|
}
|
|
146
149
|
|
|
147
150
|
type Voice = {
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
37
|
// package.json
|
|
38
|
-
var version = "0.
|
|
38
|
+
var version = "0.16.0";
|
|
39
39
|
|
|
40
40
|
// src/conversations/index.ts
|
|
41
41
|
var Conversations = class {
|
|
@@ -87,8 +87,21 @@ var import_ws = __toESM(require("ws"));
|
|
|
87
87
|
|
|
88
88
|
// src/sts/websocket.ts
|
|
89
89
|
var PhonicSTSWebSocket = class {
|
|
90
|
-
constructor(ws) {
|
|
90
|
+
constructor(ws, config) {
|
|
91
91
|
this.ws = ws;
|
|
92
|
+
this.config = config;
|
|
93
|
+
this.buffer.push(
|
|
94
|
+
JSON.stringify({
|
|
95
|
+
type: "config",
|
|
96
|
+
...this.config
|
|
97
|
+
})
|
|
98
|
+
);
|
|
99
|
+
this.ws.onopen = () => {
|
|
100
|
+
for (const message of this.buffer) {
|
|
101
|
+
this.ws.send(message);
|
|
102
|
+
}
|
|
103
|
+
this.isOpen = true;
|
|
104
|
+
};
|
|
92
105
|
this.ws.onmessage = (event) => {
|
|
93
106
|
if (this.onMessageCallback === null) {
|
|
94
107
|
return;
|
|
@@ -122,6 +135,8 @@ var PhonicSTSWebSocket = class {
|
|
|
122
135
|
onMessageCallback = null;
|
|
123
136
|
onCloseCallback = null;
|
|
124
137
|
onErrorCallback = null;
|
|
138
|
+
buffer = [];
|
|
139
|
+
isOpen = false;
|
|
125
140
|
onMessage(callback) {
|
|
126
141
|
this.onMessageCallback = callback;
|
|
127
142
|
}
|
|
@@ -132,28 +147,37 @@ var PhonicSTSWebSocket = class {
|
|
|
132
147
|
this.onErrorCallback = callback;
|
|
133
148
|
}
|
|
134
149
|
audioChunk({ audio }) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
150
|
+
const audiochunkMessage = JSON.stringify({
|
|
151
|
+
type: "audio_chunk",
|
|
152
|
+
audio
|
|
153
|
+
});
|
|
154
|
+
if (this.isOpen) {
|
|
155
|
+
this.ws.send(audiochunkMessage);
|
|
156
|
+
} else {
|
|
157
|
+
this.buffer.push(audiochunkMessage);
|
|
158
|
+
}
|
|
141
159
|
}
|
|
142
160
|
updateSystemPrompt({ systemPrompt }) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
161
|
+
const updateSystemPromptMessage = JSON.stringify({
|
|
162
|
+
type: "update_system_prompt",
|
|
163
|
+
system_prompt: systemPrompt
|
|
164
|
+
});
|
|
165
|
+
if (this.isOpen) {
|
|
166
|
+
this.ws.send(updateSystemPromptMessage);
|
|
167
|
+
} else {
|
|
168
|
+
this.buffer.push(updateSystemPromptMessage);
|
|
169
|
+
}
|
|
149
170
|
}
|
|
150
171
|
setExternalId({ externalId }) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
172
|
+
const setExternalIdMessage = JSON.stringify({
|
|
173
|
+
type: "set_external_id",
|
|
174
|
+
external_id: externalId
|
|
175
|
+
});
|
|
176
|
+
if (this.isOpen) {
|
|
177
|
+
this.ws.send(setExternalIdMessage);
|
|
178
|
+
} else {
|
|
179
|
+
this.buffer.push(setExternalIdMessage);
|
|
180
|
+
}
|
|
157
181
|
}
|
|
158
182
|
close(code) {
|
|
159
183
|
this.ws.close(code ?? 1e3);
|
|
@@ -161,64 +185,11 @@ var PhonicSTSWebSocket = class {
|
|
|
161
185
|
};
|
|
162
186
|
|
|
163
187
|
// src/sts/index.ts
|
|
164
|
-
var phonicApiCloseCodes = {
|
|
165
|
-
insuffucientCapacityAvailable: 4004
|
|
166
|
-
};
|
|
167
188
|
var SpeechToSpeech = class {
|
|
168
189
|
constructor(phonic) {
|
|
169
190
|
this.phonic = phonic;
|
|
170
191
|
}
|
|
171
|
-
|
|
172
|
-
return new Promise((resolve) => {
|
|
173
|
-
const ws = new import_ws.default(phonicApiWsUrl, {
|
|
174
|
-
headers: this.phonic.headers
|
|
175
|
-
});
|
|
176
|
-
ws.onopen = () => {
|
|
177
|
-
ws.send(
|
|
178
|
-
JSON.stringify({
|
|
179
|
-
type: "config",
|
|
180
|
-
...config
|
|
181
|
-
})
|
|
182
|
-
);
|
|
183
|
-
};
|
|
184
|
-
ws.onmessage = (event) => {
|
|
185
|
-
if (typeof event.data !== "string") {
|
|
186
|
-
throw new Error("Received non-string message");
|
|
187
|
-
}
|
|
188
|
-
const dataObj = JSON.parse(
|
|
189
|
-
event.data
|
|
190
|
-
);
|
|
191
|
-
if (dataObj.type === "ready_to_start_conversation") {
|
|
192
|
-
resolve({
|
|
193
|
-
data: {
|
|
194
|
-
phonicWebSocket: new PhonicSTSWebSocket(ws)
|
|
195
|
-
},
|
|
196
|
-
error: null
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
ws.onerror = (error) => {
|
|
201
|
-
resolve({
|
|
202
|
-
data: null,
|
|
203
|
-
error: {
|
|
204
|
-
message: error.message
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
};
|
|
208
|
-
ws.onclose = (event) => {
|
|
209
|
-
if (event.code === phonicApiCloseCodes.insuffucientCapacityAvailable) {
|
|
210
|
-
resolve({
|
|
211
|
-
data: null,
|
|
212
|
-
error: {
|
|
213
|
-
message: event.reason,
|
|
214
|
-
code: "insuffucient_capacity_available"
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
async websocket(config) {
|
|
192
|
+
websocket(config) {
|
|
222
193
|
const wsBaseUrl = this.phonic.baseUrl.replace(/^http/, "ws");
|
|
223
194
|
const queryString = new URLSearchParams({
|
|
224
195
|
...this.phonic.__downstreamWebSocketUrl !== null && {
|
|
@@ -226,31 +197,10 @@ var SpeechToSpeech = class {
|
|
|
226
197
|
}
|
|
227
198
|
}).toString();
|
|
228
199
|
const phonicApiWsUrl = `${wsBaseUrl}/v1/sts/ws?${queryString}`;
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const connectResult = await this.connectToPhonicAPI(
|
|
234
|
-
phonicApiWsUrl,
|
|
235
|
-
config
|
|
236
|
-
);
|
|
237
|
-
if (connectResult.data !== null) {
|
|
238
|
-
return connectResult;
|
|
239
|
-
}
|
|
240
|
-
if (connectResult.error.code === "insuffucient_capacity_available") {
|
|
241
|
-
if (retryNumber >= maxRetries) {
|
|
242
|
-
return connectResult;
|
|
243
|
-
}
|
|
244
|
-
console.info(
|
|
245
|
-
`${connectResult.error.message}, will retry in ${retryDelay / 1e3}sec`
|
|
246
|
-
);
|
|
247
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
248
|
-
retryNumber += 1;
|
|
249
|
-
console.info(`Retrying... ${retryNumber}/${maxRetries}`);
|
|
250
|
-
continue;
|
|
251
|
-
}
|
|
252
|
-
return connectResult;
|
|
253
|
-
}
|
|
200
|
+
const ws = new import_ws.default(phonicApiWsUrl, {
|
|
201
|
+
headers: this.phonic.headers
|
|
202
|
+
});
|
|
203
|
+
return new PhonicSTSWebSocket(ws, config);
|
|
254
204
|
}
|
|
255
205
|
};
|
|
256
206
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// package.json
|
|
2
|
-
var version = "0.
|
|
2
|
+
var version = "0.16.0";
|
|
3
3
|
|
|
4
4
|
// src/conversations/index.ts
|
|
5
5
|
var Conversations = class {
|
|
@@ -51,8 +51,21 @@ import WebSocket from "ws";
|
|
|
51
51
|
|
|
52
52
|
// src/sts/websocket.ts
|
|
53
53
|
var PhonicSTSWebSocket = class {
|
|
54
|
-
constructor(ws) {
|
|
54
|
+
constructor(ws, config) {
|
|
55
55
|
this.ws = ws;
|
|
56
|
+
this.config = config;
|
|
57
|
+
this.buffer.push(
|
|
58
|
+
JSON.stringify({
|
|
59
|
+
type: "config",
|
|
60
|
+
...this.config
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
this.ws.onopen = () => {
|
|
64
|
+
for (const message of this.buffer) {
|
|
65
|
+
this.ws.send(message);
|
|
66
|
+
}
|
|
67
|
+
this.isOpen = true;
|
|
68
|
+
};
|
|
56
69
|
this.ws.onmessage = (event) => {
|
|
57
70
|
if (this.onMessageCallback === null) {
|
|
58
71
|
return;
|
|
@@ -86,6 +99,8 @@ var PhonicSTSWebSocket = class {
|
|
|
86
99
|
onMessageCallback = null;
|
|
87
100
|
onCloseCallback = null;
|
|
88
101
|
onErrorCallback = null;
|
|
102
|
+
buffer = [];
|
|
103
|
+
isOpen = false;
|
|
89
104
|
onMessage(callback) {
|
|
90
105
|
this.onMessageCallback = callback;
|
|
91
106
|
}
|
|
@@ -96,28 +111,37 @@ var PhonicSTSWebSocket = class {
|
|
|
96
111
|
this.onErrorCallback = callback;
|
|
97
112
|
}
|
|
98
113
|
audioChunk({ audio }) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
114
|
+
const audiochunkMessage = JSON.stringify({
|
|
115
|
+
type: "audio_chunk",
|
|
116
|
+
audio
|
|
117
|
+
});
|
|
118
|
+
if (this.isOpen) {
|
|
119
|
+
this.ws.send(audiochunkMessage);
|
|
120
|
+
} else {
|
|
121
|
+
this.buffer.push(audiochunkMessage);
|
|
122
|
+
}
|
|
105
123
|
}
|
|
106
124
|
updateSystemPrompt({ systemPrompt }) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
125
|
+
const updateSystemPromptMessage = JSON.stringify({
|
|
126
|
+
type: "update_system_prompt",
|
|
127
|
+
system_prompt: systemPrompt
|
|
128
|
+
});
|
|
129
|
+
if (this.isOpen) {
|
|
130
|
+
this.ws.send(updateSystemPromptMessage);
|
|
131
|
+
} else {
|
|
132
|
+
this.buffer.push(updateSystemPromptMessage);
|
|
133
|
+
}
|
|
113
134
|
}
|
|
114
135
|
setExternalId({ externalId }) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
136
|
+
const setExternalIdMessage = JSON.stringify({
|
|
137
|
+
type: "set_external_id",
|
|
138
|
+
external_id: externalId
|
|
139
|
+
});
|
|
140
|
+
if (this.isOpen) {
|
|
141
|
+
this.ws.send(setExternalIdMessage);
|
|
142
|
+
} else {
|
|
143
|
+
this.buffer.push(setExternalIdMessage);
|
|
144
|
+
}
|
|
121
145
|
}
|
|
122
146
|
close(code) {
|
|
123
147
|
this.ws.close(code ?? 1e3);
|
|
@@ -125,64 +149,11 @@ var PhonicSTSWebSocket = class {
|
|
|
125
149
|
};
|
|
126
150
|
|
|
127
151
|
// src/sts/index.ts
|
|
128
|
-
var phonicApiCloseCodes = {
|
|
129
|
-
insuffucientCapacityAvailable: 4004
|
|
130
|
-
};
|
|
131
152
|
var SpeechToSpeech = class {
|
|
132
153
|
constructor(phonic) {
|
|
133
154
|
this.phonic = phonic;
|
|
134
155
|
}
|
|
135
|
-
|
|
136
|
-
return new Promise((resolve) => {
|
|
137
|
-
const ws = new WebSocket(phonicApiWsUrl, {
|
|
138
|
-
headers: this.phonic.headers
|
|
139
|
-
});
|
|
140
|
-
ws.onopen = () => {
|
|
141
|
-
ws.send(
|
|
142
|
-
JSON.stringify({
|
|
143
|
-
type: "config",
|
|
144
|
-
...config
|
|
145
|
-
})
|
|
146
|
-
);
|
|
147
|
-
};
|
|
148
|
-
ws.onmessage = (event) => {
|
|
149
|
-
if (typeof event.data !== "string") {
|
|
150
|
-
throw new Error("Received non-string message");
|
|
151
|
-
}
|
|
152
|
-
const dataObj = JSON.parse(
|
|
153
|
-
event.data
|
|
154
|
-
);
|
|
155
|
-
if (dataObj.type === "ready_to_start_conversation") {
|
|
156
|
-
resolve({
|
|
157
|
-
data: {
|
|
158
|
-
phonicWebSocket: new PhonicSTSWebSocket(ws)
|
|
159
|
-
},
|
|
160
|
-
error: null
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
ws.onerror = (error) => {
|
|
165
|
-
resolve({
|
|
166
|
-
data: null,
|
|
167
|
-
error: {
|
|
168
|
-
message: error.message
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
};
|
|
172
|
-
ws.onclose = (event) => {
|
|
173
|
-
if (event.code === phonicApiCloseCodes.insuffucientCapacityAvailable) {
|
|
174
|
-
resolve({
|
|
175
|
-
data: null,
|
|
176
|
-
error: {
|
|
177
|
-
message: event.reason,
|
|
178
|
-
code: "insuffucient_capacity_available"
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
async websocket(config) {
|
|
156
|
+
websocket(config) {
|
|
186
157
|
const wsBaseUrl = this.phonic.baseUrl.replace(/^http/, "ws");
|
|
187
158
|
const queryString = new URLSearchParams({
|
|
188
159
|
...this.phonic.__downstreamWebSocketUrl !== null && {
|
|
@@ -190,31 +161,10 @@ var SpeechToSpeech = class {
|
|
|
190
161
|
}
|
|
191
162
|
}).toString();
|
|
192
163
|
const phonicApiWsUrl = `${wsBaseUrl}/v1/sts/ws?${queryString}`;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const connectResult = await this.connectToPhonicAPI(
|
|
198
|
-
phonicApiWsUrl,
|
|
199
|
-
config
|
|
200
|
-
);
|
|
201
|
-
if (connectResult.data !== null) {
|
|
202
|
-
return connectResult;
|
|
203
|
-
}
|
|
204
|
-
if (connectResult.error.code === "insuffucient_capacity_available") {
|
|
205
|
-
if (retryNumber >= maxRetries) {
|
|
206
|
-
return connectResult;
|
|
207
|
-
}
|
|
208
|
-
console.info(
|
|
209
|
-
`${connectResult.error.message}, will retry in ${retryDelay / 1e3}sec`
|
|
210
|
-
);
|
|
211
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
212
|
-
retryNumber += 1;
|
|
213
|
-
console.info(`Retrying... ${retryNumber}/${maxRetries}`);
|
|
214
|
-
continue;
|
|
215
|
-
}
|
|
216
|
-
return connectResult;
|
|
217
|
-
}
|
|
164
|
+
const ws = new WebSocket(phonicApiWsUrl, {
|
|
165
|
+
headers: this.phonic.headers
|
|
166
|
+
});
|
|
167
|
+
return new PhonicSTSWebSocket(ws, config);
|
|
218
168
|
}
|
|
219
169
|
};
|
|
220
170
|
|