phonic 0.32.12 → 0.32.14
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/dist/cjs/BaseClient.js +2 -2
- package/dist/cjs/api/resources/agents/client/requests/AgentsCreateRequest.d.ts +1 -1
- package/dist/cjs/api/resources/agents/client/requests/UpdateAgentRequest.d.ts +1 -1
- package/dist/cjs/api/resources/tools/client/Client.d.ts +65 -0
- package/dist/cjs/api/resources/tools/client/Client.js +65 -0
- package/dist/cjs/api/resources/tools/client/requests/CreateToolRequest.d.ts +99 -5
- package/dist/cjs/api/resources/tools/client/requests/CreateToolRequest.js +7 -0
- package/dist/cjs/api/resources/tools/client/requests/UpdateToolRequest.d.ts +26 -6
- package/dist/cjs/api/resources/tools/client/requests/UpdateToolRequest.js +8 -1
- package/dist/cjs/api/types/Agent.d.ts +1 -1
- package/dist/cjs/api/types/ConfigOptions.d.ts +1 -1
- package/dist/cjs/api/types/CreateAgentRequest.d.ts +1 -1
- package/dist/cjs/api/types/InlineWebSocketTool.d.ts +2 -0
- package/dist/cjs/api/types/OutboundCallConfig.d.ts +1 -1
- package/dist/cjs/api/types/Tool.d.ts +26 -2
- package/dist/cjs/api/types/Tool.js +7 -0
- package/dist/cjs/api/types/ToolParameter.d.ts +5 -2
- package/dist/cjs/api/types/ToolParameter.js +2 -1
- package/dist/cjs/api/types/ToolParametersJsonSchema.d.ts +15 -0
- package/dist/cjs/api/types/ToolParametersJsonSchema.js +3 -0
- package/dist/cjs/api/types/index.d.ts +1 -0
- package/dist/cjs/api/types/index.js +1 -0
- package/dist/cjs/custom/ReconnectableConversationsSocket.d.ts +16 -0
- package/dist/cjs/custom/ReconnectableConversationsSocket.js +127 -11
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/BaseClient.mjs +2 -2
- package/dist/esm/api/resources/agents/client/requests/AgentsCreateRequest.d.mts +1 -1
- package/dist/esm/api/resources/agents/client/requests/UpdateAgentRequest.d.mts +1 -1
- package/dist/esm/api/resources/tools/client/Client.d.mts +65 -0
- package/dist/esm/api/resources/tools/client/Client.mjs +65 -0
- package/dist/esm/api/resources/tools/client/requests/CreateToolRequest.d.mts +99 -5
- package/dist/esm/api/resources/tools/client/requests/CreateToolRequest.mjs +7 -0
- package/dist/esm/api/resources/tools/client/requests/UpdateToolRequest.d.mts +26 -6
- package/dist/esm/api/resources/tools/client/requests/UpdateToolRequest.mjs +8 -1
- package/dist/esm/api/types/Agent.d.mts +1 -1
- package/dist/esm/api/types/ConfigOptions.d.mts +1 -1
- package/dist/esm/api/types/CreateAgentRequest.d.mts +1 -1
- package/dist/esm/api/types/InlineWebSocketTool.d.mts +2 -0
- package/dist/esm/api/types/OutboundCallConfig.d.mts +1 -1
- package/dist/esm/api/types/Tool.d.mts +26 -2
- package/dist/esm/api/types/Tool.mjs +7 -0
- package/dist/esm/api/types/ToolParameter.d.mts +5 -2
- package/dist/esm/api/types/ToolParameter.mjs +2 -1
- package/dist/esm/api/types/ToolParametersJsonSchema.d.mts +15 -0
- package/dist/esm/api/types/ToolParametersJsonSchema.mjs +2 -0
- package/dist/esm/api/types/index.d.mts +1 -0
- package/dist/esm/api/types/index.mjs +1 -0
- package/dist/esm/custom/ReconnectableConversationsSocket.d.mts +16 -0
- package/dist/esm/custom/ReconnectableConversationsSocket.mjs +127 -11
- package/dist/esm/version.d.mts +1 -1
- package/dist/esm/version.mjs +1 -1
- package/package.json +1 -1
|
@@ -27,6 +27,11 @@ type EventHandlers = {
|
|
|
27
27
|
* with a terminal close code (4800 session expired, 4801 invalid state),
|
|
28
28
|
* the safety cap is reached, or the user calls close().
|
|
29
29
|
*
|
|
30
|
+
* A reconnectable close is not surfaced to the user's close handler while the
|
|
31
|
+
* reconnect is in flight. The close is emitted only when reconnection has
|
|
32
|
+
* failed, meaning the conversation is closing. Closes that are not
|
|
33
|
+
* reconnectable (1000, 4000, etc) are not affected and will pass through.
|
|
34
|
+
*
|
|
30
35
|
* Uses composition rather than inheritance to avoid coupling to the parent's
|
|
31
36
|
* private event handler registration or ReconnectingWebSocket internals.
|
|
32
37
|
*/
|
|
@@ -41,6 +46,8 @@ export declare class ReconnectableConversationsSocket {
|
|
|
41
46
|
private _cleanupWireListeners;
|
|
42
47
|
private _pendingReconnect;
|
|
43
48
|
private _pendingReplacement;
|
|
49
|
+
private _lastSuppressedClose;
|
|
50
|
+
private _gaveUp;
|
|
44
51
|
constructor(args: ReconnectableConversationsSocketArgs);
|
|
45
52
|
/** The conversation ID captured from the server's conversation_created message. */
|
|
46
53
|
get conversationId(): string | null;
|
|
@@ -67,9 +74,18 @@ export declare class ReconnectableConversationsSocket {
|
|
|
67
74
|
connect(): never;
|
|
68
75
|
close(): void;
|
|
69
76
|
waitForOpen(): Promise<core.ReconnectingWebSocket>;
|
|
77
|
+
private _willReconnectAfter;
|
|
78
|
+
private _giveUp;
|
|
70
79
|
private _getReconnectDelay;
|
|
71
80
|
/** Schedule a reconnection attempt after backoff delay. */
|
|
72
81
|
private _scheduleReconnect;
|
|
82
|
+
/** Settle as soon as the abort signal fires rather than waiting on the
|
|
83
|
+
* factory, whose promise is caller-supplied (it awaits fresh auth) and
|
|
84
|
+
* may never settle — the suppressed close would stay hidden forever.
|
|
85
|
+
* Resolves null when aborted; a socket arriving afterwards is closed
|
|
86
|
+
* rather than leaked. The listener is removed once the factory settles,
|
|
87
|
+
* so a long-lived conversation does not accumulate them on the signal. */
|
|
88
|
+
private _createSocketOrAbort;
|
|
73
89
|
/** Perform the actual reconnection attempt. */
|
|
74
90
|
private _doReconnect;
|
|
75
91
|
private _wireInner;
|
|
@@ -80,6 +80,11 @@ const MAX_RECONNECT_ATTEMPTS = 10;
|
|
|
80
80
|
* with a terminal close code (4800 session expired, 4801 invalid state),
|
|
81
81
|
* the safety cap is reached, or the user calls close().
|
|
82
82
|
*
|
|
83
|
+
* A reconnectable close is not surfaced to the user's close handler while the
|
|
84
|
+
* reconnect is in flight. The close is emitted only when reconnection has
|
|
85
|
+
* failed, meaning the conversation is closing. Closes that are not
|
|
86
|
+
* reconnectable (1000, 4000, etc) are not affected and will pass through.
|
|
87
|
+
*
|
|
83
88
|
* Uses composition rather than inheritance to avoid coupling to the parent's
|
|
84
89
|
* private event handler registration or ReconnectingWebSocket internals.
|
|
85
90
|
*/
|
|
@@ -92,6 +97,8 @@ class ReconnectableConversationsSocket {
|
|
|
92
97
|
this._cleanupWireListeners = null;
|
|
93
98
|
this._pendingReconnect = null;
|
|
94
99
|
this._pendingReplacement = false;
|
|
100
|
+
this._lastSuppressedClose = null;
|
|
101
|
+
this._gaveUp = false;
|
|
95
102
|
this._createReconnectSocket = args.createReconnectSocket;
|
|
96
103
|
this._abortSignal = args.abortSignal != undefined ? args.abortSignal : null;
|
|
97
104
|
this._inner = new Socket_js_1.ConversationsSocket({ socket: args.socket });
|
|
@@ -170,15 +177,36 @@ class ReconnectableConversationsSocket {
|
|
|
170
177
|
clearTimeout(this._pendingReconnect);
|
|
171
178
|
this._pendingReconnect = null;
|
|
172
179
|
}
|
|
180
|
+
// Close before detaching: ConversationsSocket.close() synthesizes a
|
|
181
|
+
// 1000 close event, and a user-initiated close should still surface one.
|
|
182
|
+
this._inner.close();
|
|
173
183
|
(_a = this._cleanupWireListeners) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
174
184
|
this._cleanupWireListeners = null;
|
|
175
|
-
this._inner.close();
|
|
176
185
|
}
|
|
177
186
|
waitForOpen() {
|
|
178
187
|
return __awaiter(this, void 0, void 0, function* () {
|
|
179
188
|
return this._inner.waitForOpen();
|
|
180
189
|
});
|
|
181
190
|
}
|
|
191
|
+
_willReconnectAfter(event) {
|
|
192
|
+
return (!this._isClosed
|
|
193
|
+
&& !this._gaveUp
|
|
194
|
+
&& this._conversationId !== null
|
|
195
|
+
&& isReconnectableClose(event.code, event.reason));
|
|
196
|
+
}
|
|
197
|
+
_giveUp() {
|
|
198
|
+
var _a, _b;
|
|
199
|
+
this._pendingReplacement = false;
|
|
200
|
+
if (this._gaveUp || this._isClosed) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
this._gaveUp = true;
|
|
204
|
+
const suppressed = this._lastSuppressedClose;
|
|
205
|
+
this._lastSuppressedClose = null;
|
|
206
|
+
if (suppressed !== null) {
|
|
207
|
+
(_b = (_a = this._handlers).close) === null || _b === void 0 ? void 0 : _b.call(_a, suppressed);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
182
210
|
_getReconnectDelay() {
|
|
183
211
|
// Exponential backoff: 500ms, 1s, 2s, 4s, capped at 5s
|
|
184
212
|
const delay = BASE_RECONNECT_DELAY_MS * Math.pow(2, this._reconnectAttempts - 1);
|
|
@@ -187,12 +215,18 @@ class ReconnectableConversationsSocket {
|
|
|
187
215
|
/** Schedule a reconnection attempt after backoff delay. */
|
|
188
216
|
_scheduleReconnect() {
|
|
189
217
|
var _a, _b, _c;
|
|
190
|
-
|
|
218
|
+
// With no conversation the close was never suppressed, so unlike the
|
|
219
|
+
// branches below there is nothing to emit.
|
|
220
|
+
if (this._isClosed || this._conversationId === null) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if ((_a = this._abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) {
|
|
224
|
+
this._giveUp();
|
|
191
225
|
return;
|
|
192
226
|
}
|
|
193
227
|
if (this._reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
|
194
|
-
this._pendingReplacement = false;
|
|
195
228
|
(_c = (_b = this._handlers).error) === null || _c === void 0 ? void 0 : _c.call(_b, new Error("Max reconnect attempts reached"));
|
|
229
|
+
this._giveUp();
|
|
196
230
|
return;
|
|
197
231
|
}
|
|
198
232
|
// Clear any existing timer to prevent orphaned timeouts
|
|
@@ -203,24 +237,70 @@ class ReconnectableConversationsSocket {
|
|
|
203
237
|
const delay = this._getReconnectDelay();
|
|
204
238
|
this._pendingReplacement = true;
|
|
205
239
|
this._pendingReconnect = setTimeout(() => {
|
|
240
|
+
var _a;
|
|
206
241
|
this._pendingReconnect = null;
|
|
207
242
|
if (this._isClosed) {
|
|
208
243
|
this._pendingReplacement = false;
|
|
209
244
|
return;
|
|
210
245
|
}
|
|
246
|
+
if ((_a = this._abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) {
|
|
247
|
+
this._giveUp();
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
211
250
|
void this._doReconnect();
|
|
212
251
|
}, delay);
|
|
213
252
|
}
|
|
253
|
+
/** Settle as soon as the abort signal fires rather than waiting on the
|
|
254
|
+
* factory, whose promise is caller-supplied (it awaits fresh auth) and
|
|
255
|
+
* may never settle — the suppressed close would stay hidden forever.
|
|
256
|
+
* Resolves null when aborted; a socket arriving afterwards is closed
|
|
257
|
+
* rather than leaked. The listener is removed once the factory settles,
|
|
258
|
+
* so a long-lived conversation does not accumulate them on the signal. */
|
|
259
|
+
_createSocketOrAbort(created) {
|
|
260
|
+
const signal = this._abortSignal;
|
|
261
|
+
if (signal === null) {
|
|
262
|
+
return created;
|
|
263
|
+
}
|
|
264
|
+
const discardLate = () => {
|
|
265
|
+
void created.then((socket) => socket.close()).catch(() => undefined);
|
|
266
|
+
};
|
|
267
|
+
if (signal.aborted) {
|
|
268
|
+
discardLate();
|
|
269
|
+
return Promise.resolve(null);
|
|
270
|
+
}
|
|
271
|
+
return new Promise((resolve, reject) => {
|
|
272
|
+
const onAbort = () => {
|
|
273
|
+
discardLate();
|
|
274
|
+
resolve(null);
|
|
275
|
+
};
|
|
276
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
277
|
+
created.then((socket) => {
|
|
278
|
+
signal.removeEventListener("abort", onAbort);
|
|
279
|
+
resolve(socket);
|
|
280
|
+
}, (error) => {
|
|
281
|
+
signal.removeEventListener("abort", onAbort);
|
|
282
|
+
reject(error);
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
}
|
|
214
286
|
/** Perform the actual reconnection attempt. */
|
|
215
287
|
_doReconnect() {
|
|
216
288
|
return __awaiter(this, void 0, void 0, function* () {
|
|
217
289
|
var _a, _b;
|
|
218
290
|
try {
|
|
219
291
|
const created = this._createReconnectSocket(this._conversationId);
|
|
220
|
-
const newRawSocket = created instanceof Promise ? yield created : created;
|
|
292
|
+
const newRawSocket = created instanceof Promise ? yield this._createSocketOrAbort(created) : created;
|
|
293
|
+
if (newRawSocket === null) {
|
|
294
|
+
// Aborted while the factory was still in flight.
|
|
295
|
+
this._giveUp();
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
221
298
|
if (this._isClosed || ((_a = this._abortSignal) === null || _a === void 0 ? void 0 : _a.aborted)) {
|
|
222
299
|
this._pendingReplacement = false;
|
|
223
300
|
newRawSocket.close();
|
|
301
|
+
if (!this._isClosed) {
|
|
302
|
+
this._giveUp();
|
|
303
|
+
}
|
|
224
304
|
return;
|
|
225
305
|
}
|
|
226
306
|
// Clean up the old socket: remove our custom listeners and close
|
|
@@ -233,7 +313,7 @@ class ReconnectableConversationsSocket {
|
|
|
233
313
|
catch ( /* already closed from 1006 */_c) { /* already closed from 1006 */ }
|
|
234
314
|
const newInner = new Socket_js_1.ConversationsSocket({ socket: newRawSocket });
|
|
235
315
|
this._inner = newInner;
|
|
236
|
-
this._wireInner(newInner, newRawSocket);
|
|
316
|
+
this._wireInner(newInner, newRawSocket, true);
|
|
237
317
|
}
|
|
238
318
|
catch (_d) {
|
|
239
319
|
this._pendingReplacement = false;
|
|
@@ -244,17 +324,41 @@ class ReconnectableConversationsSocket {
|
|
|
244
324
|
}
|
|
245
325
|
});
|
|
246
326
|
}
|
|
247
|
-
_wireInner(inner, rawSocket) {
|
|
248
|
-
//
|
|
249
|
-
//
|
|
250
|
-
//
|
|
327
|
+
_wireInner(inner, rawSocket, isReplacement = false) {
|
|
328
|
+
// A replacement that closes before ever opening failed at the transport
|
|
329
|
+
// level, and its code says nothing about why: ReconnectingWebSocket
|
|
330
|
+
// synthesizes 1000 for connect errors and timeouts (_handleError ->
|
|
331
|
+
// _disconnect). Read it as a failed attempt rather than as a close.
|
|
332
|
+
// _isClosed excluded: close() also reaches this via the synthesized
|
|
333
|
+
// 1000, and a user-initiated close is a close, not a failed attempt.
|
|
334
|
+
let opened = false;
|
|
335
|
+
const isFailedAttempt = () => isReplacement && !opened && !this._isClosed;
|
|
336
|
+
// Clearing _pendingReplacement before the user's open handler keeps
|
|
337
|
+
// sends made inside that handler from being dropped.
|
|
251
338
|
inner.on("open", () => {
|
|
252
339
|
var _a, _b;
|
|
340
|
+
opened = true;
|
|
253
341
|
this._pendingReplacement = false;
|
|
342
|
+
this._lastSuppressedClose = null;
|
|
254
343
|
(_b = (_a = this._handlers).open) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
255
344
|
});
|
|
256
345
|
inner.on("message", (msg) => { var _a, _b; return (_b = (_a = this._handlers).message) === null || _b === void 0 ? void 0 : _b.call(_a, msg); });
|
|
257
|
-
|
|
346
|
+
// ConversationsSocket registers this in its constructor, so it runs
|
|
347
|
+
// before the rawSocket close listener below that schedules the
|
|
348
|
+
// reconnect — the decision cannot be read off reconnect state here.
|
|
349
|
+
inner.on("close", (ev) => {
|
|
350
|
+
var _a, _b;
|
|
351
|
+
// Leave _lastSuppressedClose holding the original drop, so _giveUp
|
|
352
|
+
// reports what went wrong rather than this attempt's code.
|
|
353
|
+
if (isFailedAttempt()) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
if (this._willReconnectAfter(ev)) {
|
|
357
|
+
this._lastSuppressedClose = ev;
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
(_b = (_a = this._handlers).close) === null || _b === void 0 ? void 0 : _b.call(_a, ev);
|
|
361
|
+
});
|
|
258
362
|
inner.on("error", (err) => { var _a, _b; return (_b = (_a = this._handlers).error) === null || _b === void 0 ? void 0 : _b.call(_a, err); });
|
|
259
363
|
// Intercept raw messages to capture conversation_id and reset reconnect counter
|
|
260
364
|
const onMessage = (event) => {
|
|
@@ -274,8 +378,15 @@ class ReconnectableConversationsSocket {
|
|
|
274
378
|
// ignore — inner socket handles parse errors
|
|
275
379
|
}
|
|
276
380
|
};
|
|
381
|
+
// After giving up this is a plain pass-through: the close was already
|
|
382
|
+
// forwarded above, and retrying would repeat the give-up error.
|
|
277
383
|
const onClose = (event) => {
|
|
278
|
-
if (this._isClosed) {
|
|
384
|
+
if (this._isClosed || this._gaveUp) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (isFailedAttempt()) {
|
|
388
|
+
rawSocket.close();
|
|
389
|
+
this._scheduleReconnect();
|
|
279
390
|
return;
|
|
280
391
|
}
|
|
281
392
|
if (isReconnectableClose(event.code, event.reason) && this._conversationId !== null) {
|
|
@@ -294,6 +405,11 @@ class ReconnectableConversationsSocket {
|
|
|
294
405
|
rawSocket.addEventListener("message", onMessage);
|
|
295
406
|
rawSocket.addEventListener("close", onClose);
|
|
296
407
|
this._cleanupWireListeners = () => {
|
|
408
|
+
// ConversationsSocket.close() synthesizes a 1000 close event, so a
|
|
409
|
+
// discarded socket would otherwise report a spurious normal closure.
|
|
410
|
+
for (const event of ["open", "message", "close", "error"]) {
|
|
411
|
+
inner.on(event, undefined);
|
|
412
|
+
}
|
|
297
413
|
rawSocket.removeEventListener("message", onMessage);
|
|
298
414
|
rawSocket.removeEventListener("close", onClose);
|
|
299
415
|
};
|
package/dist/cjs/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.32.
|
|
1
|
+
export declare const SDK_VERSION = "0.32.14";
|
package/dist/cjs/version.js
CHANGED
package/dist/esm/BaseClient.mjs
CHANGED
|
@@ -6,8 +6,8 @@ export function normalizeClientOptions(options) {
|
|
|
6
6
|
const headers = mergeHeaders({
|
|
7
7
|
"X-Fern-Language": "JavaScript",
|
|
8
8
|
"X-Fern-SDK-Name": "phonic",
|
|
9
|
-
"X-Fern-SDK-Version": "0.32.
|
|
10
|
-
"User-Agent": "phonic/0.32.
|
|
9
|
+
"X-Fern-SDK-Version": "0.32.13",
|
|
10
|
+
"User-Agent": "phonic/0.32.13",
|
|
11
11
|
"X-Fern-Runtime": core.RUNTIME.type,
|
|
12
12
|
"X-Fern-Runtime-Version": core.RUNTIME.version,
|
|
13
13
|
}, options === null || options === void 0 ? void 0 : options.headers);
|
|
@@ -133,7 +133,7 @@ export interface AgentsCreateRequest {
|
|
|
133
133
|
vad_min_silence_duration_ms?: number;
|
|
134
134
|
/** Voice activity detection threshold. */
|
|
135
135
|
vad_threshold?: number;
|
|
136
|
-
/** When `true`, PII and PHI are redacted from text transcripts (e.g. replaced with tags like `[PHONE
|
|
136
|
+
/** When `true`, PII and PHI are redacted from text transcripts (e.g. replaced with tags like `[PHONE]`) and bleeped from audio recordings after the conversation ends. */
|
|
137
137
|
enable_redaction?: boolean;
|
|
138
138
|
/** Array of MCP server IDs to make available to the agent. */
|
|
139
139
|
mcp_server_ids?: string[];
|
|
@@ -139,7 +139,7 @@ export interface UpdateAgentRequest {
|
|
|
139
139
|
vad_min_silence_duration_ms?: number;
|
|
140
140
|
/** Voice activity detection threshold. */
|
|
141
141
|
vad_threshold?: number;
|
|
142
|
-
/** When `true`, PII and PHI are redacted from text transcripts (e.g. replaced with tags like `[PHONE
|
|
142
|
+
/** When `true`, PII and PHI are redacted from text transcripts (e.g. replaced with tags like `[PHONE]`) and bleeped from audio recordings after the conversation ends. */
|
|
143
143
|
enable_redaction?: boolean;
|
|
144
144
|
/** Array of MCP server IDs to make available to the agent. */
|
|
145
145
|
mcp_server_ids?: string[];
|
|
@@ -90,6 +90,71 @@ export declare class ToolsClient {
|
|
|
90
90
|
* @example
|
|
91
91
|
* await client.tools.create({
|
|
92
92
|
* project: "main",
|
|
93
|
+
* name: "create_order",
|
|
94
|
+
* description: "Creates an order in the fulfillment system",
|
|
95
|
+
* type: "custom_webhook",
|
|
96
|
+
* execution_mode: "sync",
|
|
97
|
+
* parameters: {
|
|
98
|
+
* type: "object",
|
|
99
|
+
* properties: {
|
|
100
|
+
* "customer": {
|
|
101
|
+
* "type": "object",
|
|
102
|
+
* "description": "The customer placing the order",
|
|
103
|
+
* "properties": {
|
|
104
|
+
* "name": {
|
|
105
|
+
* "type": "string",
|
|
106
|
+
* "description": "The customer's full name"
|
|
107
|
+
* },
|
|
108
|
+
* "tier": {
|
|
109
|
+
* "type": "string",
|
|
110
|
+
* "enum": [
|
|
111
|
+
* "free",
|
|
112
|
+
* "pro"
|
|
113
|
+
* ],
|
|
114
|
+
* "description": "The customer's subscription tier"
|
|
115
|
+
* }
|
|
116
|
+
* },
|
|
117
|
+
* "required": [
|
|
118
|
+
* "name"
|
|
119
|
+
* ]
|
|
120
|
+
* },
|
|
121
|
+
* "items": {
|
|
122
|
+
* "type": "array",
|
|
123
|
+
* "description": "The items being ordered",
|
|
124
|
+
* "items": {
|
|
125
|
+
* "type": "object",
|
|
126
|
+
* "properties": {
|
|
127
|
+
* "sku": {
|
|
128
|
+
* "type": "string",
|
|
129
|
+
* "description": "The item's SKU"
|
|
130
|
+
* },
|
|
131
|
+
* "quantity": {
|
|
132
|
+
* "type": "integer",
|
|
133
|
+
* "description": "How many of the item to order"
|
|
134
|
+
* }
|
|
135
|
+
* },
|
|
136
|
+
* "required": [
|
|
137
|
+
* "sku",
|
|
138
|
+
* "quantity"
|
|
139
|
+
* ]
|
|
140
|
+
* }
|
|
141
|
+
* }
|
|
142
|
+
* },
|
|
143
|
+
* required: ["customer", "items"],
|
|
144
|
+
* additionalProperties: false
|
|
145
|
+
* },
|
|
146
|
+
* parameter_locations: {
|
|
147
|
+
* "customer": "request_body",
|
|
148
|
+
* "items": "request_body"
|
|
149
|
+
* },
|
|
150
|
+
* endpoint_method: "POST",
|
|
151
|
+
* endpoint_url: "https://api.example.com/orders",
|
|
152
|
+
* endpoint_timeout_ms: 5000
|
|
153
|
+
* })
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* await client.tools.create({
|
|
157
|
+
* project: "main",
|
|
93
158
|
* name: "check_inventory",
|
|
94
159
|
* description: "Checks product inventory levels",
|
|
95
160
|
* type: "custom_websocket",
|
|
@@ -150,6 +150,71 @@ export class ToolsClient {
|
|
|
150
150
|
* @example
|
|
151
151
|
* await client.tools.create({
|
|
152
152
|
* project: "main",
|
|
153
|
+
* name: "create_order",
|
|
154
|
+
* description: "Creates an order in the fulfillment system",
|
|
155
|
+
* type: "custom_webhook",
|
|
156
|
+
* execution_mode: "sync",
|
|
157
|
+
* parameters: {
|
|
158
|
+
* type: "object",
|
|
159
|
+
* properties: {
|
|
160
|
+
* "customer": {
|
|
161
|
+
* "type": "object",
|
|
162
|
+
* "description": "The customer placing the order",
|
|
163
|
+
* "properties": {
|
|
164
|
+
* "name": {
|
|
165
|
+
* "type": "string",
|
|
166
|
+
* "description": "The customer's full name"
|
|
167
|
+
* },
|
|
168
|
+
* "tier": {
|
|
169
|
+
* "type": "string",
|
|
170
|
+
* "enum": [
|
|
171
|
+
* "free",
|
|
172
|
+
* "pro"
|
|
173
|
+
* ],
|
|
174
|
+
* "description": "The customer's subscription tier"
|
|
175
|
+
* }
|
|
176
|
+
* },
|
|
177
|
+
* "required": [
|
|
178
|
+
* "name"
|
|
179
|
+
* ]
|
|
180
|
+
* },
|
|
181
|
+
* "items": {
|
|
182
|
+
* "type": "array",
|
|
183
|
+
* "description": "The items being ordered",
|
|
184
|
+
* "items": {
|
|
185
|
+
* "type": "object",
|
|
186
|
+
* "properties": {
|
|
187
|
+
* "sku": {
|
|
188
|
+
* "type": "string",
|
|
189
|
+
* "description": "The item's SKU"
|
|
190
|
+
* },
|
|
191
|
+
* "quantity": {
|
|
192
|
+
* "type": "integer",
|
|
193
|
+
* "description": "How many of the item to order"
|
|
194
|
+
* }
|
|
195
|
+
* },
|
|
196
|
+
* "required": [
|
|
197
|
+
* "sku",
|
|
198
|
+
* "quantity"
|
|
199
|
+
* ]
|
|
200
|
+
* }
|
|
201
|
+
* }
|
|
202
|
+
* },
|
|
203
|
+
* required: ["customer", "items"],
|
|
204
|
+
* additionalProperties: false
|
|
205
|
+
* },
|
|
206
|
+
* parameter_locations: {
|
|
207
|
+
* "customer": "request_body",
|
|
208
|
+
* "items": "request_body"
|
|
209
|
+
* },
|
|
210
|
+
* endpoint_method: "POST",
|
|
211
|
+
* endpoint_url: "https://api.example.com/orders",
|
|
212
|
+
* endpoint_timeout_ms: 5000
|
|
213
|
+
* })
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* await client.tools.create({
|
|
217
|
+
* project: "main",
|
|
153
218
|
* name: "check_inventory",
|
|
154
219
|
* description: "Checks product inventory levels",
|
|
155
220
|
* type: "custom_websocket",
|
|
@@ -55,6 +55,71 @@ import type * as Phonic from "../../../../index.mjs";
|
|
|
55
55
|
* @example
|
|
56
56
|
* {
|
|
57
57
|
* project: "main",
|
|
58
|
+
* name: "create_order",
|
|
59
|
+
* description: "Creates an order in the fulfillment system",
|
|
60
|
+
* type: "custom_webhook",
|
|
61
|
+
* execution_mode: "sync",
|
|
62
|
+
* parameters: {
|
|
63
|
+
* type: "object",
|
|
64
|
+
* properties: {
|
|
65
|
+
* "customer": {
|
|
66
|
+
* "type": "object",
|
|
67
|
+
* "description": "The customer placing the order",
|
|
68
|
+
* "properties": {
|
|
69
|
+
* "name": {
|
|
70
|
+
* "type": "string",
|
|
71
|
+
* "description": "The customer's full name"
|
|
72
|
+
* },
|
|
73
|
+
* "tier": {
|
|
74
|
+
* "type": "string",
|
|
75
|
+
* "enum": [
|
|
76
|
+
* "free",
|
|
77
|
+
* "pro"
|
|
78
|
+
* ],
|
|
79
|
+
* "description": "The customer's subscription tier"
|
|
80
|
+
* }
|
|
81
|
+
* },
|
|
82
|
+
* "required": [
|
|
83
|
+
* "name"
|
|
84
|
+
* ]
|
|
85
|
+
* },
|
|
86
|
+
* "items": {
|
|
87
|
+
* "type": "array",
|
|
88
|
+
* "description": "The items being ordered",
|
|
89
|
+
* "items": {
|
|
90
|
+
* "type": "object",
|
|
91
|
+
* "properties": {
|
|
92
|
+
* "sku": {
|
|
93
|
+
* "type": "string",
|
|
94
|
+
* "description": "The item's SKU"
|
|
95
|
+
* },
|
|
96
|
+
* "quantity": {
|
|
97
|
+
* "type": "integer",
|
|
98
|
+
* "description": "How many of the item to order"
|
|
99
|
+
* }
|
|
100
|
+
* },
|
|
101
|
+
* "required": [
|
|
102
|
+
* "sku",
|
|
103
|
+
* "quantity"
|
|
104
|
+
* ]
|
|
105
|
+
* }
|
|
106
|
+
* }
|
|
107
|
+
* },
|
|
108
|
+
* required: ["customer", "items"],
|
|
109
|
+
* additionalProperties: false
|
|
110
|
+
* },
|
|
111
|
+
* parameter_locations: {
|
|
112
|
+
* "customer": "request_body",
|
|
113
|
+
* "items": "request_body"
|
|
114
|
+
* },
|
|
115
|
+
* endpoint_method: "POST",
|
|
116
|
+
* endpoint_url: "https://api.example.com/orders",
|
|
117
|
+
* endpoint_timeout_ms: 5000
|
|
118
|
+
* }
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* {
|
|
122
|
+
* project: "main",
|
|
58
123
|
* name: "check_inventory",
|
|
59
124
|
* description: "Checks product inventory levels",
|
|
60
125
|
* type: "custom_websocket",
|
|
@@ -111,12 +176,21 @@ export interface CreateToolRequest {
|
|
|
111
176
|
/** Mode of operation. */
|
|
112
177
|
execution_mode: CreateToolRequest.ExecutionMode;
|
|
113
178
|
/**
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* For `custom_webhook` tools with
|
|
117
|
-
* For `
|
|
179
|
+
* The tool's parameters, either as a flat array of parameter definitions or as a raw JSON Schema object (use the object form for nested parameters).
|
|
180
|
+
* When sending an array:
|
|
181
|
+
* - For `custom_webhook` tools with POST method, each parameter must include a `location` field.
|
|
182
|
+
* - For `custom_webhook` tools with GET method, `location` defaults to `"query_string"` if not specified.
|
|
183
|
+
* - For `custom_websocket`, `built_in_transfer_to_phone_number`, and `built_in_transfer_to_agent` tools, `location` must not be specified.
|
|
184
|
+
* - `parameter_locations` must not be sent, since placement is carried inline on each parameter.
|
|
185
|
+
* When sending a JSON Schema object, `custom_webhook` tools supply parameter placement in `parameter_locations` instead.
|
|
186
|
+
* Tools that cannot have parameters (`custom_context` and the `built_in_*` types) must send an empty array or omit the field.
|
|
118
187
|
*/
|
|
119
|
-
parameters?:
|
|
188
|
+
parameters?: CreateToolRequest.Parameters;
|
|
189
|
+
/**
|
|
190
|
+
* Where each top-level parameter is sent in the webhook request, as a map from parameter name to location. Only for `custom_webhook` tools whose `parameters` are a raw JSON Schema object.
|
|
191
|
+
* Every key must name a top-level parameter. For POST webhooks, every parameter needs an entry. For GET webhooks, entries default to `"query_string"` and `"request_body"` is not allowed.
|
|
192
|
+
*/
|
|
193
|
+
parameter_locations?: Record<string, CreateToolRequest.ParameterLocations.Value>;
|
|
120
194
|
/** Required for webhook tools. HTTP method for the webhook endpoint. */
|
|
121
195
|
endpoint_method?: CreateToolRequest.EndpointMethod;
|
|
122
196
|
/** Required for webhook tools. Must be a publicly routable HTTPS URL without embedded credentials. */
|
|
@@ -147,6 +221,8 @@ export interface CreateToolRequest {
|
|
|
147
221
|
wait_for_speech_before_tool_call?: boolean;
|
|
148
222
|
/** When true, forbids the agent from speaking after executing the tool. Available for custom_context, custom_webhook and custom_websocket tools. */
|
|
149
223
|
forbid_speech_after_tool_call?: boolean;
|
|
224
|
+
/** When true, forbids the agent from calling the tool right after it has spoken. Available for custom_webhook and custom_websocket tools. */
|
|
225
|
+
forbid_tool_call_after_speech?: boolean;
|
|
150
226
|
/** When true, allows the agent to chain and execute other tools after executing the tool. Available for custom_context, custom_webhook and custom_websocket tools. */
|
|
151
227
|
allow_tool_chaining?: boolean;
|
|
152
228
|
/** The agent doesn't typically wait for the response of async custom_websocket tools. When true, makes the agent wait for a response, not call other tools and inform the user of the result. Only available for async custom_websocket tools. */
|
|
@@ -173,6 +249,24 @@ export declare namespace CreateToolRequest {
|
|
|
173
249
|
readonly Async: "async";
|
|
174
250
|
};
|
|
175
251
|
type ExecutionMode = (typeof ExecutionMode)[keyof typeof ExecutionMode];
|
|
252
|
+
/**
|
|
253
|
+
* The tool's parameters, either as a flat array of parameter definitions or as a raw JSON Schema object (use the object form for nested parameters).
|
|
254
|
+
* When sending an array:
|
|
255
|
+
* - For `custom_webhook` tools with POST method, each parameter must include a `location` field.
|
|
256
|
+
* - For `custom_webhook` tools with GET method, `location` defaults to `"query_string"` if not specified.
|
|
257
|
+
* - For `custom_websocket`, `built_in_transfer_to_phone_number`, and `built_in_transfer_to_agent` tools, `location` must not be specified.
|
|
258
|
+
* - `parameter_locations` must not be sent, since placement is carried inline on each parameter.
|
|
259
|
+
* When sending a JSON Schema object, `custom_webhook` tools supply parameter placement in `parameter_locations` instead.
|
|
260
|
+
* Tools that cannot have parameters (`custom_context` and the `built_in_*` types) must send an empty array or omit the field.
|
|
261
|
+
*/
|
|
262
|
+
type Parameters = Phonic.ToolParameter[] | Phonic.ToolParametersJsonSchema;
|
|
263
|
+
namespace ParameterLocations {
|
|
264
|
+
const Value: {
|
|
265
|
+
readonly RequestBody: "request_body";
|
|
266
|
+
readonly QueryString: "query_string";
|
|
267
|
+
};
|
|
268
|
+
type Value = (typeof Value)[keyof typeof Value];
|
|
269
|
+
}
|
|
176
270
|
/** Required for webhook tools. HTTP method for the webhook endpoint. */
|
|
177
271
|
const EndpointMethod: {
|
|
178
272
|
readonly Get: "GET";
|
|
@@ -17,6 +17,13 @@ export var CreateToolRequest;
|
|
|
17
17
|
Sync: "sync",
|
|
18
18
|
Async: "async",
|
|
19
19
|
};
|
|
20
|
+
let ParameterLocations;
|
|
21
|
+
(function (ParameterLocations) {
|
|
22
|
+
ParameterLocations.Value = {
|
|
23
|
+
RequestBody: "request_body",
|
|
24
|
+
QueryString: "query_string",
|
|
25
|
+
};
|
|
26
|
+
})(ParameterLocations = CreateToolRequest.ParameterLocations || (CreateToolRequest.ParameterLocations = {}));
|
|
20
27
|
/** Required for webhook tools. HTTP method for the webhook endpoint. */
|
|
21
28
|
CreateToolRequest.EndpointMethod = {
|
|
22
29
|
Get: "GET",
|