phonic 0.26.1 → 0.28.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 CHANGED
@@ -190,16 +190,25 @@ const toolsResult = await phonic.tools.list();
190
190
 
191
191
  ### Get tool
192
192
 
193
+ Gets a tool by its ID or name.
194
+
193
195
  ```ts
194
196
  const toolResult = await phonic.tools.get("next_invoice");
197
+ const toolByIdResult = await phonic.tools.get("tool_12cf6e88-c254-4d3e-a149-ddf1bdd2254c");
195
198
  ```
196
199
 
197
200
  ### Create tool
198
201
 
202
+ Tools can be either webhook-based (HTTP endpoints) or WebSocket-based.
203
+
204
+ #### Create webhook tool
205
+
199
206
  ```ts
200
- const createToolResult = await phonic.tools.create({
207
+ const createWebhookToolResult = await phonic.tools.create({
201
208
  name: "next_invoice",
202
209
  description: "Returns the next invoice of the given user",
210
+ type: "custom_webhook",
211
+ executionMode: "sync",
203
212
  endpointMethod: "POST",
204
213
  endpointUrl: "https://myapp.com/webhooks/next-invoice",
205
214
  endpointHeaders: {
@@ -230,12 +239,75 @@ const createToolResult = await phonic.tools.create({
230
239
  });
231
240
  ```
232
241
 
242
+ #### Create WebSocket tool
243
+
244
+ WebSocket tools allow you to handle tool execution through the WebSocket connection. When the agent calls a WebSocket tool, you'll receive a `tool_call` message and must respond with a `tool_call_output` message that contains the tool result.
245
+
246
+ ```ts
247
+ const createWebSocketToolResult = await phonic.tools.create({
248
+ name: "get_product_recommendations",
249
+ description: "Gets personalized product recommendations",
250
+ type: "custom_websocket",
251
+ executionMode: "async",
252
+ toolCallOutputTimeoutMs: 5000, // Optional, defaults to 15000
253
+ parameters: [
254
+ {
255
+ type: "string",
256
+ name: "category",
257
+ description: "Product category (e.g., 'handbags', 'shoes', 'electronics')",
258
+ isRequired: true
259
+ }
260
+ ]
261
+ });
262
+ ```
263
+
264
+ To use this tool in a conversation, add it to your agent or config:
265
+
266
+ ```ts
267
+ // When creating an agent
268
+ const agent = await phonic.agents.create({
269
+ name: "shopping-assistant",
270
+ tools: ["get_product_recommendations"],
271
+ // ... other config
272
+ });
273
+
274
+ // Or, override agent settings when starting a WebSocket conversation
275
+ const phonicWebSocket = phonic.sts.websocket({
276
+ name: "shopping-assistant",
277
+ tools: ["get_product_recommendations"],
278
+ // ... other config
279
+ });
280
+
281
+ // Handle the tool call when it's invoked
282
+ phonicWebSocket.onMessage(async (message) => {
283
+ if (message.type === "tool_call" && message.name === "get_product_recommendations") {
284
+ const category = message.parameters.category;
285
+
286
+ // Execute your business logic
287
+ const recommendations = fetchRecommendations(category);
288
+
289
+ // Send the result back
290
+ phonicWebSocket.[sendToolCallOutput](#send-tool-output-to-phonic)({
291
+ toolCallId: message.tool_call_id,
292
+ output: {
293
+ products: recommendations,
294
+ total: recommendations.length
295
+ }
296
+ });
297
+ }
298
+ });
299
+ ```
300
+
233
301
  ### Update tool
234
302
 
303
+ Updates a tool by ID or name. All fields are optional - only provided fields will be updated.
304
+
235
305
  ```ts
236
- const updateToolResult = await phonic.tools.update("next_invoice", {
306
+ const updateWebhookToolResult = await phonic.tools.update("next_invoice", {
237
307
  name: "next_invoice_updated",
238
308
  description: "Updated description.",
309
+ type: "custom_webhook",
310
+ executionMode: "sync",
239
311
  endpointMethod: "POST",
240
312
  endpointUrl: "https://myapp.com/webhooks/next-invoice-updated",
241
313
  endpointHeaders: {
@@ -266,8 +338,19 @@ const updateToolResult = await phonic.tools.update("next_invoice", {
266
338
  });
267
339
  ```
268
340
 
341
+ For WebSocket tools, you would use `toolCallOutputTimeoutMs` instead of the endpoint fields:
342
+
343
+ ```ts
344
+ const updateWebSocketToolResult = await phonic.tools.update("get_product_recommendations", {
345
+ description: "Updated product recommendation tool",
346
+ toolCallOutputTimeoutMs: 7000
347
+ });
348
+ ```
349
+
269
350
  ### Delete tool
270
351
 
352
+ Deletes a tool by ID or name.
353
+
271
354
  ```ts
272
355
  const deleteToolResult = await phonic.tools.delete("next_invoice");
273
356
  ```
@@ -412,6 +495,26 @@ phonicWebSocket.onMessage((message) => {
412
495
  );
413
496
  break;
414
497
  }
498
+
499
+ case "tool_call": {
500
+ // Handle WebSocket tool calls
501
+ console.log(`Tool ${message.tool_name} called with parameters:`, message.parameters);
502
+
503
+ // Example: Process a product recommendations tool call
504
+ if (message.tool_name === "get_product_recommendations") {
505
+ const category = message.parameters.category;
506
+ const recommendations = fetchRecommendations(category);
507
+
508
+ phonicWebSocket.[sendToolCallOutput](#send-tool-output-to-phonic)({
509
+ toolCallId: message.tool_call_id,
510
+ output: {
511
+ products: recommendations,
512
+ total: recommendations.length
513
+ }
514
+ });
515
+ }
516
+ break;
517
+ }
415
518
  }
416
519
  });
417
520
  ```
@@ -432,6 +535,34 @@ phonicWebSocket.setExternalId({
432
535
  })
433
536
  ```
434
537
 
538
+ ### Send tool output to Phonic
539
+
540
+ When you receive a `tool_call` message for a WebSocket tool, you must respond with the tool's output using `sendToolCallOutput()`. This method sends the execution result back to Phonic so the conversation can continue.
541
+
542
+ ```ts
543
+ phonicWebSocket.sendToolCallOutput({
544
+ toolCallId: "tool_call_123...", // The tool_call_id from the tool_call message
545
+ output: "Success! Found 2 items" // Can be any JSON-serializable value (string, number, object, array, etc.)
546
+ });
547
+
548
+ // Or with an object:
549
+ phonicWebSocket.sendToolCallOutput({
550
+ toolCallId: message.tool_call_id,
551
+ output: {
552
+ result: "success",
553
+ data: {
554
+ items: ["item1", "item2"],
555
+ total: 2
556
+ }
557
+ }
558
+ });
559
+ ```
560
+
561
+ **Important notes:**
562
+ - You must use the exact `tool_call_id` received in the `tool_call` message
563
+ - The `output` can be any JSON-serializable value (string, number, boolean, object, array, etc.)
564
+ - If you don't send a response within `toolCallOutputTimeoutMs`, the tool call will be marked as failed.
565
+
435
566
  To end the conversation, close the WebSocket:
436
567
 
437
568
  ```ts
@@ -564,7 +695,24 @@ Sent when the assistant decides to end the conversation.
564
695
  ```ts
565
696
  {
566
697
  type: "tool_call";
567
- id: string;
698
+ tool_call_id: string;
699
+ tool_name: string;
700
+ parameters: Record<string, unknown>;
701
+ }
702
+ ```
703
+
704
+ Sent when a WebSocket tool is called during the conversation. When you receive this message, you should:
705
+ 1. Process the tool call using the provided `tool_name` and `parameters`
706
+ 2. Send back the result using [`phonicWebSocket.sendToolCallOutput`](#send-tool-output-to-phonic)
707
+
708
+ This is only sent for tools created with `type: "custom_websocket"`. Webhook tools are executed server-side and only send `tool_call_output_processed` messages.
709
+
710
+ #### `tool_call_output_processed`
711
+
712
+ ```ts
713
+ {
714
+ type: "tool_call_output_processed";
715
+ tool_call_id: string;
568
716
  tool: {
569
717
  id: string;
570
718
  name: string;
package/dist/index.d.mts CHANGED
@@ -93,8 +93,8 @@ type PhonicSTSWebSocketResponseMessage = {
93
93
  type: "dtmf";
94
94
  digits: string;
95
95
  } | {
96
- type: "tool_call";
97
- id: string;
96
+ type: "tool_call_output_processed";
97
+ tool_call_id: string;
98
98
  tool: {
99
99
  id: string;
100
100
  name: string;
@@ -109,10 +109,17 @@ type PhonicSTSWebSocketResponseMessage = {
109
109
  } | null;
110
110
  [key: string]: unknown;
111
111
  } | null;
112
- response_body: Record<string, unknown> | null;
112
+ parameters: Record<string, unknown> | null;
113
+ output: unknown | null;
114
+ response_body: unknown | null;
113
115
  response_status_code: number | null;
114
116
  timed_out: boolean | null;
115
117
  error_message: string | null;
118
+ } | {
119
+ type: "tool_call";
120
+ tool_call_id: string;
121
+ tool_name: string;
122
+ parameters: Record<string, unknown>;
116
123
  } | {
117
124
  type: "error";
118
125
  error: {
@@ -277,11 +284,11 @@ declare class Agents {
277
284
  private getTemplateVariablesForBody;
278
285
  private getConfigurationEndpointForBody;
279
286
  list(params?: ListAgentsParams): DataOrError<ListAgentsSuccessResponse>;
280
- get(name: string, params?: GetAgentParams): DataOrError<GetAgentSuccessResponse>;
287
+ get(nameOrId: string, params?: GetAgentParams): DataOrError<GetAgentSuccessResponse>;
281
288
  create(params: CreateAgentParams): DataOrError<CreateAgentSuccessResponse>;
282
- update(name: string, params: UpdateAgentParams): DataOrError<UpdateAgentSuccessResponse>;
289
+ update(nameOrId: string, params: UpdateAgentParams): DataOrError<UpdateAgentSuccessResponse>;
283
290
  upsert(params: UpsertAgentParams): DataOrError<UpsertAgentSuccessResponse>;
284
- delete(name: string, params?: DeleteAgentParams): DataOrError<DeleteAgentSuccessResponse>;
291
+ delete(nameOrId: string, params?: DeleteAgentParams): DataOrError<DeleteAgentSuccessResponse>;
285
292
  }
286
293
 
287
294
  type ISODateTime = `${string}Z`;
@@ -362,6 +369,48 @@ declare class Conversations {
362
369
  outboundCall(toPhoneNumber: string, config: OutboundCallConfig): DataOrError<OutboundCallSuccessResponse>;
363
370
  }
364
371
 
372
+ type Project = {
373
+ id: string;
374
+ name: string;
375
+ default_agent: {
376
+ id: string;
377
+ name: string;
378
+ } | null;
379
+ };
380
+ type ListProjectsSuccessResponse = {
381
+ projects: Array<Project>;
382
+ };
383
+ type GetProjectSuccessResponse = {
384
+ project: Project;
385
+ };
386
+ type CreateProjectParams = {
387
+ name: string;
388
+ };
389
+ type CreateProjectSuccessResponse = {
390
+ id: string;
391
+ name: string;
392
+ };
393
+ type UpdateProjectParams = {
394
+ name?: string;
395
+ defaultAgent?: string;
396
+ };
397
+ type UpdateProjectSuccessResponse = {
398
+ success: true;
399
+ };
400
+ type DeleteProjectSuccessResponse = {
401
+ success: true;
402
+ };
403
+
404
+ declare class Projects {
405
+ private readonly phonic;
406
+ constructor(phonic: Phonic);
407
+ list(): DataOrError<ListProjectsSuccessResponse>;
408
+ get(nameOrId: string): DataOrError<GetProjectSuccessResponse>;
409
+ create(params: CreateProjectParams): DataOrError<CreateProjectSuccessResponse>;
410
+ update(nameOrId: string, params: UpdateProjectParams): DataOrError<UpdateProjectSuccessResponse>;
411
+ delete(nameOrId: string): DataOrError<DeleteProjectSuccessResponse>;
412
+ }
413
+
365
414
  declare class PhonicSTSWebSocket {
366
415
  private readonly ws;
367
416
  private readonly config;
@@ -371,12 +420,17 @@ declare class PhonicSTSWebSocket {
371
420
  private buffer;
372
421
  private isOpen;
373
422
  constructor(ws: WebSocket, config: PhonicSTSConfig);
423
+ private processUserMessage;
374
424
  onMessage(callback: OnMessageCallback): void;
375
425
  onClose(callback: OnCloseCallback): void;
376
426
  onError(callback: OnErrorCallback): void;
377
427
  audioChunk({ audio }: {
378
428
  audio: string;
379
429
  }): void;
430
+ sendToolCallOutput({ toolCallId, output, }: {
431
+ toolCallId: string;
432
+ output: unknown;
433
+ }): void;
380
434
  updateSystemPrompt({ systemPrompt }: {
381
435
  systemPrompt: string;
382
436
  }): void;
@@ -405,31 +459,50 @@ interface ArrayParameter extends ParameterBase {
405
459
  itemType: "string" | "integer" | "number" | "boolean";
406
460
  }
407
461
  type ToolParameters = Array<PrimitiveParameter | ArrayParameter>;
408
- type Tool = {
462
+ type ExecutionMode = "sync" | "async";
463
+ interface ToolBase {
409
464
  id: string;
410
465
  name: string;
411
466
  description: string;
467
+ execution_mode: ExecutionMode;
468
+ parameters: ToolParameters;
469
+ }
470
+ interface WebhookTool extends ToolBase {
471
+ type: "custom_webhook";
412
472
  endpoint_method: "POST";
413
473
  endpoint_url: string;
414
474
  endpoint_headers: Record<string, string>;
415
475
  endpoint_timeout_ms: number;
416
- parameters: ToolParameters;
417
- };
476
+ }
477
+ interface WebSocketTool extends ToolBase {
478
+ type: "custom_websocket";
479
+ tool_call_output_timeout_ms: number;
480
+ }
481
+ type Tool = WebhookTool | WebSocketTool;
418
482
  type ListToolsSuccessResponse = DataOrError<{
419
483
  tools: Array<Tool>;
420
484
  }>;
421
485
  type GetToolSuccessResponse = DataOrError<{
422
486
  tool: Tool;
423
487
  }>;
424
- type CreateToolParams = {
488
+ interface CreateToolParamsBase {
425
489
  name: string;
426
490
  description: string;
491
+ executionMode: ExecutionMode;
492
+ parameters?: ToolParameters;
493
+ }
494
+ interface CreateWebhookToolParams extends CreateToolParamsBase {
495
+ type: "custom_webhook";
427
496
  endpointMethod: "POST";
428
497
  endpointUrl: string;
429
498
  endpointHeaders?: Record<string, string>;
430
499
  endpointTimeoutMs?: number;
431
- parameters?: ToolParameters;
432
- };
500
+ }
501
+ interface CreateWebSocketToolParams extends CreateToolParamsBase {
502
+ type: "custom_websocket";
503
+ toolCallOutputTimeoutMs?: number;
504
+ }
505
+ type CreateToolParams = CreateWebhookToolParams | CreateWebSocketToolParams;
433
506
  type CreateToolSuccessResponse = {
434
507
  id: string;
435
508
  name: string;
@@ -437,11 +510,14 @@ type CreateToolSuccessResponse = {
437
510
  type UpdateToolParams = {
438
511
  name?: string;
439
512
  description?: string;
513
+ type?: "custom_webhook" | "custom_websocket";
514
+ executionMode?: ExecutionMode;
440
515
  endpointMethod?: "POST";
441
516
  endpointUrl?: string;
442
517
  endpointHeaders?: Record<string, string>;
443
518
  endpointTimeoutMs?: number;
444
- parameters?: Array<PrimitiveParameter | ArrayParameter>;
519
+ toolCallOutputTimeoutMs?: number;
520
+ parameters?: ToolParameters;
445
521
  };
446
522
  type UpdateToolSuccessResponse = {
447
523
  success: true;
@@ -455,10 +531,10 @@ declare class Tools {
455
531
  constructor(phonic: Phonic);
456
532
  private getParametersForBody;
457
533
  list(): DataOrError<ListToolsSuccessResponse>;
458
- get(name: string): DataOrError<GetToolSuccessResponse>;
534
+ get(nameOrId: string): DataOrError<GetToolSuccessResponse>;
459
535
  create(params: CreateToolParams): DataOrError<CreateToolSuccessResponse>;
460
- update(name: string, params: UpdateToolParams): DataOrError<UpdateToolSuccessResponse>;
461
- delete(name: string): DataOrError<DeleteToolSuccessResponse>;
536
+ update(nameOrId: string, params: UpdateToolParams): DataOrError<UpdateToolSuccessResponse>;
537
+ delete(nameOrId: string): DataOrError<DeleteToolSuccessResponse>;
462
538
  }
463
539
 
464
540
  type Voice = {
@@ -488,6 +564,7 @@ declare class Phonic {
488
564
  readonly headers: Record<string, string>;
489
565
  readonly agents: Agents;
490
566
  readonly conversations: Conversations;
567
+ readonly projects: Projects;
491
568
  readonly tools: Tools;
492
569
  readonly voices: Voices;
493
570
  readonly sts: SpeechToSpeech;
@@ -550,4 +627,4 @@ declare class Phonic {
550
627
  }>;
551
628
  }
552
629
 
553
- export { Phonic, type PhonicConfigurationEndpointRequestPayload, type PhonicConfigurationEndpointResponsePayload, type PhonicSTSConfig, PhonicSTSWebSocket };
630
+ export { Phonic, type PhonicConfigurationEndpointRequestPayload, type PhonicConfigurationEndpointResponsePayload, type PhonicSTSConfig, PhonicSTSWebSocket, type PhonicSTSWebSocketResponseMessage };
package/dist/index.d.ts CHANGED
@@ -93,8 +93,8 @@ type PhonicSTSWebSocketResponseMessage = {
93
93
  type: "dtmf";
94
94
  digits: string;
95
95
  } | {
96
- type: "tool_call";
97
- id: string;
96
+ type: "tool_call_output_processed";
97
+ tool_call_id: string;
98
98
  tool: {
99
99
  id: string;
100
100
  name: string;
@@ -109,10 +109,17 @@ type PhonicSTSWebSocketResponseMessage = {
109
109
  } | null;
110
110
  [key: string]: unknown;
111
111
  } | null;
112
- response_body: Record<string, unknown> | null;
112
+ parameters: Record<string, unknown> | null;
113
+ output: unknown | null;
114
+ response_body: unknown | null;
113
115
  response_status_code: number | null;
114
116
  timed_out: boolean | null;
115
117
  error_message: string | null;
118
+ } | {
119
+ type: "tool_call";
120
+ tool_call_id: string;
121
+ tool_name: string;
122
+ parameters: Record<string, unknown>;
116
123
  } | {
117
124
  type: "error";
118
125
  error: {
@@ -277,11 +284,11 @@ declare class Agents {
277
284
  private getTemplateVariablesForBody;
278
285
  private getConfigurationEndpointForBody;
279
286
  list(params?: ListAgentsParams): DataOrError<ListAgentsSuccessResponse>;
280
- get(name: string, params?: GetAgentParams): DataOrError<GetAgentSuccessResponse>;
287
+ get(nameOrId: string, params?: GetAgentParams): DataOrError<GetAgentSuccessResponse>;
281
288
  create(params: CreateAgentParams): DataOrError<CreateAgentSuccessResponse>;
282
- update(name: string, params: UpdateAgentParams): DataOrError<UpdateAgentSuccessResponse>;
289
+ update(nameOrId: string, params: UpdateAgentParams): DataOrError<UpdateAgentSuccessResponse>;
283
290
  upsert(params: UpsertAgentParams): DataOrError<UpsertAgentSuccessResponse>;
284
- delete(name: string, params?: DeleteAgentParams): DataOrError<DeleteAgentSuccessResponse>;
291
+ delete(nameOrId: string, params?: DeleteAgentParams): DataOrError<DeleteAgentSuccessResponse>;
285
292
  }
286
293
 
287
294
  type ISODateTime = `${string}Z`;
@@ -362,6 +369,48 @@ declare class Conversations {
362
369
  outboundCall(toPhoneNumber: string, config: OutboundCallConfig): DataOrError<OutboundCallSuccessResponse>;
363
370
  }
364
371
 
372
+ type Project = {
373
+ id: string;
374
+ name: string;
375
+ default_agent: {
376
+ id: string;
377
+ name: string;
378
+ } | null;
379
+ };
380
+ type ListProjectsSuccessResponse = {
381
+ projects: Array<Project>;
382
+ };
383
+ type GetProjectSuccessResponse = {
384
+ project: Project;
385
+ };
386
+ type CreateProjectParams = {
387
+ name: string;
388
+ };
389
+ type CreateProjectSuccessResponse = {
390
+ id: string;
391
+ name: string;
392
+ };
393
+ type UpdateProjectParams = {
394
+ name?: string;
395
+ defaultAgent?: string;
396
+ };
397
+ type UpdateProjectSuccessResponse = {
398
+ success: true;
399
+ };
400
+ type DeleteProjectSuccessResponse = {
401
+ success: true;
402
+ };
403
+
404
+ declare class Projects {
405
+ private readonly phonic;
406
+ constructor(phonic: Phonic);
407
+ list(): DataOrError<ListProjectsSuccessResponse>;
408
+ get(nameOrId: string): DataOrError<GetProjectSuccessResponse>;
409
+ create(params: CreateProjectParams): DataOrError<CreateProjectSuccessResponse>;
410
+ update(nameOrId: string, params: UpdateProjectParams): DataOrError<UpdateProjectSuccessResponse>;
411
+ delete(nameOrId: string): DataOrError<DeleteProjectSuccessResponse>;
412
+ }
413
+
365
414
  declare class PhonicSTSWebSocket {
366
415
  private readonly ws;
367
416
  private readonly config;
@@ -371,12 +420,17 @@ declare class PhonicSTSWebSocket {
371
420
  private buffer;
372
421
  private isOpen;
373
422
  constructor(ws: WebSocket, config: PhonicSTSConfig);
423
+ private processUserMessage;
374
424
  onMessage(callback: OnMessageCallback): void;
375
425
  onClose(callback: OnCloseCallback): void;
376
426
  onError(callback: OnErrorCallback): void;
377
427
  audioChunk({ audio }: {
378
428
  audio: string;
379
429
  }): void;
430
+ sendToolCallOutput({ toolCallId, output, }: {
431
+ toolCallId: string;
432
+ output: unknown;
433
+ }): void;
380
434
  updateSystemPrompt({ systemPrompt }: {
381
435
  systemPrompt: string;
382
436
  }): void;
@@ -405,31 +459,50 @@ interface ArrayParameter extends ParameterBase {
405
459
  itemType: "string" | "integer" | "number" | "boolean";
406
460
  }
407
461
  type ToolParameters = Array<PrimitiveParameter | ArrayParameter>;
408
- type Tool = {
462
+ type ExecutionMode = "sync" | "async";
463
+ interface ToolBase {
409
464
  id: string;
410
465
  name: string;
411
466
  description: string;
467
+ execution_mode: ExecutionMode;
468
+ parameters: ToolParameters;
469
+ }
470
+ interface WebhookTool extends ToolBase {
471
+ type: "custom_webhook";
412
472
  endpoint_method: "POST";
413
473
  endpoint_url: string;
414
474
  endpoint_headers: Record<string, string>;
415
475
  endpoint_timeout_ms: number;
416
- parameters: ToolParameters;
417
- };
476
+ }
477
+ interface WebSocketTool extends ToolBase {
478
+ type: "custom_websocket";
479
+ tool_call_output_timeout_ms: number;
480
+ }
481
+ type Tool = WebhookTool | WebSocketTool;
418
482
  type ListToolsSuccessResponse = DataOrError<{
419
483
  tools: Array<Tool>;
420
484
  }>;
421
485
  type GetToolSuccessResponse = DataOrError<{
422
486
  tool: Tool;
423
487
  }>;
424
- type CreateToolParams = {
488
+ interface CreateToolParamsBase {
425
489
  name: string;
426
490
  description: string;
491
+ executionMode: ExecutionMode;
492
+ parameters?: ToolParameters;
493
+ }
494
+ interface CreateWebhookToolParams extends CreateToolParamsBase {
495
+ type: "custom_webhook";
427
496
  endpointMethod: "POST";
428
497
  endpointUrl: string;
429
498
  endpointHeaders?: Record<string, string>;
430
499
  endpointTimeoutMs?: number;
431
- parameters?: ToolParameters;
432
- };
500
+ }
501
+ interface CreateWebSocketToolParams extends CreateToolParamsBase {
502
+ type: "custom_websocket";
503
+ toolCallOutputTimeoutMs?: number;
504
+ }
505
+ type CreateToolParams = CreateWebhookToolParams | CreateWebSocketToolParams;
433
506
  type CreateToolSuccessResponse = {
434
507
  id: string;
435
508
  name: string;
@@ -437,11 +510,14 @@ type CreateToolSuccessResponse = {
437
510
  type UpdateToolParams = {
438
511
  name?: string;
439
512
  description?: string;
513
+ type?: "custom_webhook" | "custom_websocket";
514
+ executionMode?: ExecutionMode;
440
515
  endpointMethod?: "POST";
441
516
  endpointUrl?: string;
442
517
  endpointHeaders?: Record<string, string>;
443
518
  endpointTimeoutMs?: number;
444
- parameters?: Array<PrimitiveParameter | ArrayParameter>;
519
+ toolCallOutputTimeoutMs?: number;
520
+ parameters?: ToolParameters;
445
521
  };
446
522
  type UpdateToolSuccessResponse = {
447
523
  success: true;
@@ -455,10 +531,10 @@ declare class Tools {
455
531
  constructor(phonic: Phonic);
456
532
  private getParametersForBody;
457
533
  list(): DataOrError<ListToolsSuccessResponse>;
458
- get(name: string): DataOrError<GetToolSuccessResponse>;
534
+ get(nameOrId: string): DataOrError<GetToolSuccessResponse>;
459
535
  create(params: CreateToolParams): DataOrError<CreateToolSuccessResponse>;
460
- update(name: string, params: UpdateToolParams): DataOrError<UpdateToolSuccessResponse>;
461
- delete(name: string): DataOrError<DeleteToolSuccessResponse>;
536
+ update(nameOrId: string, params: UpdateToolParams): DataOrError<UpdateToolSuccessResponse>;
537
+ delete(nameOrId: string): DataOrError<DeleteToolSuccessResponse>;
462
538
  }
463
539
 
464
540
  type Voice = {
@@ -488,6 +564,7 @@ declare class Phonic {
488
564
  readonly headers: Record<string, string>;
489
565
  readonly agents: Agents;
490
566
  readonly conversations: Conversations;
567
+ readonly projects: Projects;
491
568
  readonly tools: Tools;
492
569
  readonly voices: Voices;
493
570
  readonly sts: SpeechToSpeech;
@@ -550,4 +627,4 @@ declare class Phonic {
550
627
  }>;
551
628
  }
552
629
 
553
- export { Phonic, type PhonicConfigurationEndpointRequestPayload, type PhonicConfigurationEndpointResponsePayload, type PhonicSTSConfig, PhonicSTSWebSocket };
630
+ export { Phonic, type PhonicConfigurationEndpointRequestPayload, type PhonicConfigurationEndpointResponsePayload, type PhonicSTSConfig, PhonicSTSWebSocket, type PhonicSTSWebSocketResponseMessage };
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.26.1";
38
+ var version = "0.28.0";
39
39
 
40
40
  // src/agents/index.ts
41
41
  var Agents = class {
@@ -78,9 +78,9 @@ var Agents = class {
78
78
  );
79
79
  return response;
80
80
  }
81
- async get(name, params) {
81
+ async get(nameOrId, params) {
82
82
  const response = await this.phonic.get(
83
- `/agents/${name}?${this.getQueryString(params)}`
83
+ `/agents/${nameOrId}?${this.getQueryString(params)}`
84
84
  );
85
85
  return response;
86
86
  }
@@ -110,9 +110,9 @@ var Agents = class {
110
110
  );
111
111
  return response;
112
112
  }
113
- async update(name, params) {
113
+ async update(nameOrId, params) {
114
114
  const response = await this.phonic.patch(
115
- `/agents/${name}?${this.getQueryString(params)}`,
115
+ `/agents/${nameOrId}?${this.getQueryString(params)}`,
116
116
  {
117
117
  name: params.name,
118
118
  phone_number: params.phoneNumber,
@@ -162,9 +162,9 @@ var Agents = class {
162
162
  );
163
163
  return response;
164
164
  }
165
- async delete(name, params) {
165
+ async delete(nameOrId, params) {
166
166
  const response = await this.phonic.delete(
167
- `/agents/${name}?${this.getQueryString(params)}`
167
+ `/agents/${nameOrId}?${this.getQueryString(params)}`
168
168
  );
169
169
  return response;
170
170
  }
@@ -250,6 +250,48 @@ var Conversations = class {
250
250
  }
251
251
  };
252
252
 
253
+ // src/projects/index.ts
254
+ var Projects = class {
255
+ constructor(phonic) {
256
+ this.phonic = phonic;
257
+ }
258
+ async list() {
259
+ const response = await this.phonic.get("/projects");
260
+ return response;
261
+ }
262
+ async get(nameOrId) {
263
+ const response = await this.phonic.get(
264
+ `/projects/${nameOrId}`
265
+ );
266
+ return response;
267
+ }
268
+ async create(params) {
269
+ const response = await this.phonic.post(
270
+ "/projects",
271
+ {
272
+ name: params.name
273
+ }
274
+ );
275
+ return response;
276
+ }
277
+ async update(nameOrId, params) {
278
+ const response = await this.phonic.patch(
279
+ `/projects/${nameOrId}`,
280
+ {
281
+ name: params.name,
282
+ default_agent: params.defaultAgent
283
+ }
284
+ );
285
+ return response;
286
+ }
287
+ async delete(nameOrId) {
288
+ const response = await this.phonic.delete(
289
+ `/projects/${nameOrId}`
290
+ );
291
+ return response;
292
+ }
293
+ };
294
+
253
295
  // src/sts/index.ts
254
296
  var import_ws = __toESM(require("ws"));
255
297
 
@@ -298,6 +340,9 @@ var PhonicSTSWebSocket = class {
298
340
  this.onClose = this.onClose.bind(this);
299
341
  this.onError = this.onError.bind(this);
300
342
  this.audioChunk = this.audioChunk.bind(this);
343
+ this.sendToolCallOutput = this.sendToolCallOutput.bind(this);
344
+ this.updateSystemPrompt = this.updateSystemPrompt.bind(this);
345
+ this.setExternalId = this.setExternalId.bind(this);
301
346
  this.close = this.close.bind(this);
302
347
  }
303
348
  onMessageCallback = null;
@@ -305,6 +350,14 @@ var PhonicSTSWebSocket = class {
305
350
  onErrorCallback = null;
306
351
  buffer = [];
307
352
  isOpen = false;
353
+ processUserMessage(message) {
354
+ const messageStr = JSON.stringify(message);
355
+ if (this.isOpen) {
356
+ this.ws.send(messageStr);
357
+ } else {
358
+ this.buffer.push(messageStr);
359
+ }
360
+ }
308
361
  onMessage(callback) {
309
362
  this.onMessageCallback = callback;
310
363
  }
@@ -315,37 +368,32 @@ var PhonicSTSWebSocket = class {
315
368
  this.onErrorCallback = callback;
316
369
  }
317
370
  audioChunk({ audio }) {
318
- const audiochunkMessage = JSON.stringify({
371
+ this.processUserMessage({
319
372
  type: "audio_chunk",
320
373
  audio
321
374
  });
322
- if (this.isOpen) {
323
- this.ws.send(audiochunkMessage);
324
- } else {
325
- this.buffer.push(audiochunkMessage);
326
- }
375
+ }
376
+ sendToolCallOutput({
377
+ toolCallId,
378
+ output
379
+ }) {
380
+ this.processUserMessage({
381
+ type: "tool_call_output",
382
+ tool_call_id: toolCallId,
383
+ output
384
+ });
327
385
  }
328
386
  updateSystemPrompt({ systemPrompt }) {
329
- const updateSystemPromptMessage = JSON.stringify({
387
+ this.processUserMessage({
330
388
  type: "update_system_prompt",
331
389
  system_prompt: systemPrompt
332
390
  });
333
- if (this.isOpen) {
334
- this.ws.send(updateSystemPromptMessage);
335
- } else {
336
- this.buffer.push(updateSystemPromptMessage);
337
- }
338
391
  }
339
392
  setExternalId({ externalId }) {
340
- const setExternalIdMessage = JSON.stringify({
393
+ this.processUserMessage({
341
394
  type: "set_external_id",
342
395
  external_id: externalId
343
396
  });
344
- if (this.isOpen) {
345
- this.ws.send(setExternalIdMessage);
346
- } else {
347
- this.buffer.push(setExternalIdMessage);
348
- }
349
397
  }
350
398
  close(code) {
351
399
  this.ws.close(code ?? 1e3);
@@ -397,45 +445,56 @@ var Tools = class {
397
445
  const response = await this.phonic.get("/tools");
398
446
  return response;
399
447
  }
400
- async get(name) {
448
+ async get(nameOrId) {
401
449
  const response = await this.phonic.get(
402
- `/tools/${name}`
450
+ `/tools/${nameOrId}`
403
451
  );
404
452
  return response;
405
453
  }
406
454
  async create(params) {
455
+ const body = {
456
+ name: params.name,
457
+ description: params.description,
458
+ type: params.type,
459
+ execution_mode: params.executionMode,
460
+ parameters: this.getParametersForBody(params.parameters)
461
+ };
462
+ if (params.type === "custom_webhook") {
463
+ body.endpoint_method = params.endpointMethod;
464
+ body.endpoint_url = params.endpointUrl;
465
+ body.endpoint_headers = params.endpointHeaders;
466
+ body.endpoint_timeout_ms = params.endpointTimeoutMs;
467
+ }
468
+ if (params.type === "custom_websocket") {
469
+ body.tool_call_output_timeout_ms = params.toolCallOutputTimeoutMs;
470
+ }
407
471
  const response = await this.phonic.post(
408
472
  "/tools",
409
- {
410
- name: params.name,
411
- description: params.description,
412
- endpoint_method: params.endpointMethod,
413
- endpoint_url: params.endpointUrl,
414
- endpoint_headers: params.endpointHeaders,
415
- endpoint_timeout_ms: params.endpointTimeoutMs,
416
- parameters: this.getParametersForBody(params.parameters)
417
- }
473
+ body
418
474
  );
419
475
  return response;
420
476
  }
421
- async update(name, params) {
477
+ async update(nameOrId, params) {
422
478
  const response = await this.phonic.patch(
423
- `/tools/${name}`,
479
+ `/tools/${nameOrId}`,
424
480
  {
425
481
  name: params.name,
426
482
  description: params.description,
483
+ type: params.type,
484
+ execution_mode: params.executionMode,
427
485
  endpoint_method: params.endpointMethod,
428
486
  endpoint_url: params.endpointUrl,
429
487
  endpoint_headers: params.endpointHeaders,
430
488
  endpoint_timeout_ms: params.endpointTimeoutMs,
431
- parameters: this.getParametersForBody(params.parameters)
489
+ parameters: this.getParametersForBody(params.parameters),
490
+ tool_call_output_timeout_ms: params.toolCallOutputTimeoutMs
432
491
  }
433
492
  );
434
493
  return response;
435
494
  }
436
- async delete(name) {
495
+ async delete(nameOrId) {
437
496
  const response = await this.phonic.delete(
438
- `/tools/${name}`
497
+ `/tools/${nameOrId}`
439
498
  );
440
499
  return response;
441
500
  }
@@ -490,6 +549,7 @@ var Phonic = class {
490
549
  headers;
491
550
  agents = new Agents(this);
492
551
  conversations = new Conversations(this);
552
+ projects = new Projects(this);
493
553
  tools = new Tools(this);
494
554
  voices = new Voices(this);
495
555
  sts = new SpeechToSpeech(this);
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.26.1";
2
+ var version = "0.28.0";
3
3
 
4
4
  // src/agents/index.ts
5
5
  var Agents = class {
@@ -42,9 +42,9 @@ var Agents = class {
42
42
  );
43
43
  return response;
44
44
  }
45
- async get(name, params) {
45
+ async get(nameOrId, params) {
46
46
  const response = await this.phonic.get(
47
- `/agents/${name}?${this.getQueryString(params)}`
47
+ `/agents/${nameOrId}?${this.getQueryString(params)}`
48
48
  );
49
49
  return response;
50
50
  }
@@ -74,9 +74,9 @@ var Agents = class {
74
74
  );
75
75
  return response;
76
76
  }
77
- async update(name, params) {
77
+ async update(nameOrId, params) {
78
78
  const response = await this.phonic.patch(
79
- `/agents/${name}?${this.getQueryString(params)}`,
79
+ `/agents/${nameOrId}?${this.getQueryString(params)}`,
80
80
  {
81
81
  name: params.name,
82
82
  phone_number: params.phoneNumber,
@@ -126,9 +126,9 @@ var Agents = class {
126
126
  );
127
127
  return response;
128
128
  }
129
- async delete(name, params) {
129
+ async delete(nameOrId, params) {
130
130
  const response = await this.phonic.delete(
131
- `/agents/${name}?${this.getQueryString(params)}`
131
+ `/agents/${nameOrId}?${this.getQueryString(params)}`
132
132
  );
133
133
  return response;
134
134
  }
@@ -214,6 +214,48 @@ var Conversations = class {
214
214
  }
215
215
  };
216
216
 
217
+ // src/projects/index.ts
218
+ var Projects = class {
219
+ constructor(phonic) {
220
+ this.phonic = phonic;
221
+ }
222
+ async list() {
223
+ const response = await this.phonic.get("/projects");
224
+ return response;
225
+ }
226
+ async get(nameOrId) {
227
+ const response = await this.phonic.get(
228
+ `/projects/${nameOrId}`
229
+ );
230
+ return response;
231
+ }
232
+ async create(params) {
233
+ const response = await this.phonic.post(
234
+ "/projects",
235
+ {
236
+ name: params.name
237
+ }
238
+ );
239
+ return response;
240
+ }
241
+ async update(nameOrId, params) {
242
+ const response = await this.phonic.patch(
243
+ `/projects/${nameOrId}`,
244
+ {
245
+ name: params.name,
246
+ default_agent: params.defaultAgent
247
+ }
248
+ );
249
+ return response;
250
+ }
251
+ async delete(nameOrId) {
252
+ const response = await this.phonic.delete(
253
+ `/projects/${nameOrId}`
254
+ );
255
+ return response;
256
+ }
257
+ };
258
+
217
259
  // src/sts/index.ts
218
260
  import WebSocket from "ws";
219
261
 
@@ -262,6 +304,9 @@ var PhonicSTSWebSocket = class {
262
304
  this.onClose = this.onClose.bind(this);
263
305
  this.onError = this.onError.bind(this);
264
306
  this.audioChunk = this.audioChunk.bind(this);
307
+ this.sendToolCallOutput = this.sendToolCallOutput.bind(this);
308
+ this.updateSystemPrompt = this.updateSystemPrompt.bind(this);
309
+ this.setExternalId = this.setExternalId.bind(this);
265
310
  this.close = this.close.bind(this);
266
311
  }
267
312
  onMessageCallback = null;
@@ -269,6 +314,14 @@ var PhonicSTSWebSocket = class {
269
314
  onErrorCallback = null;
270
315
  buffer = [];
271
316
  isOpen = false;
317
+ processUserMessage(message) {
318
+ const messageStr = JSON.stringify(message);
319
+ if (this.isOpen) {
320
+ this.ws.send(messageStr);
321
+ } else {
322
+ this.buffer.push(messageStr);
323
+ }
324
+ }
272
325
  onMessage(callback) {
273
326
  this.onMessageCallback = callback;
274
327
  }
@@ -279,37 +332,32 @@ var PhonicSTSWebSocket = class {
279
332
  this.onErrorCallback = callback;
280
333
  }
281
334
  audioChunk({ audio }) {
282
- const audiochunkMessage = JSON.stringify({
335
+ this.processUserMessage({
283
336
  type: "audio_chunk",
284
337
  audio
285
338
  });
286
- if (this.isOpen) {
287
- this.ws.send(audiochunkMessage);
288
- } else {
289
- this.buffer.push(audiochunkMessage);
290
- }
339
+ }
340
+ sendToolCallOutput({
341
+ toolCallId,
342
+ output
343
+ }) {
344
+ this.processUserMessage({
345
+ type: "tool_call_output",
346
+ tool_call_id: toolCallId,
347
+ output
348
+ });
291
349
  }
292
350
  updateSystemPrompt({ systemPrompt }) {
293
- const updateSystemPromptMessage = JSON.stringify({
351
+ this.processUserMessage({
294
352
  type: "update_system_prompt",
295
353
  system_prompt: systemPrompt
296
354
  });
297
- if (this.isOpen) {
298
- this.ws.send(updateSystemPromptMessage);
299
- } else {
300
- this.buffer.push(updateSystemPromptMessage);
301
- }
302
355
  }
303
356
  setExternalId({ externalId }) {
304
- const setExternalIdMessage = JSON.stringify({
357
+ this.processUserMessage({
305
358
  type: "set_external_id",
306
359
  external_id: externalId
307
360
  });
308
- if (this.isOpen) {
309
- this.ws.send(setExternalIdMessage);
310
- } else {
311
- this.buffer.push(setExternalIdMessage);
312
- }
313
361
  }
314
362
  close(code) {
315
363
  this.ws.close(code ?? 1e3);
@@ -361,45 +409,56 @@ var Tools = class {
361
409
  const response = await this.phonic.get("/tools");
362
410
  return response;
363
411
  }
364
- async get(name) {
412
+ async get(nameOrId) {
365
413
  const response = await this.phonic.get(
366
- `/tools/${name}`
414
+ `/tools/${nameOrId}`
367
415
  );
368
416
  return response;
369
417
  }
370
418
  async create(params) {
419
+ const body = {
420
+ name: params.name,
421
+ description: params.description,
422
+ type: params.type,
423
+ execution_mode: params.executionMode,
424
+ parameters: this.getParametersForBody(params.parameters)
425
+ };
426
+ if (params.type === "custom_webhook") {
427
+ body.endpoint_method = params.endpointMethod;
428
+ body.endpoint_url = params.endpointUrl;
429
+ body.endpoint_headers = params.endpointHeaders;
430
+ body.endpoint_timeout_ms = params.endpointTimeoutMs;
431
+ }
432
+ if (params.type === "custom_websocket") {
433
+ body.tool_call_output_timeout_ms = params.toolCallOutputTimeoutMs;
434
+ }
371
435
  const response = await this.phonic.post(
372
436
  "/tools",
373
- {
374
- name: params.name,
375
- description: params.description,
376
- endpoint_method: params.endpointMethod,
377
- endpoint_url: params.endpointUrl,
378
- endpoint_headers: params.endpointHeaders,
379
- endpoint_timeout_ms: params.endpointTimeoutMs,
380
- parameters: this.getParametersForBody(params.parameters)
381
- }
437
+ body
382
438
  );
383
439
  return response;
384
440
  }
385
- async update(name, params) {
441
+ async update(nameOrId, params) {
386
442
  const response = await this.phonic.patch(
387
- `/tools/${name}`,
443
+ `/tools/${nameOrId}`,
388
444
  {
389
445
  name: params.name,
390
446
  description: params.description,
447
+ type: params.type,
448
+ execution_mode: params.executionMode,
391
449
  endpoint_method: params.endpointMethod,
392
450
  endpoint_url: params.endpointUrl,
393
451
  endpoint_headers: params.endpointHeaders,
394
452
  endpoint_timeout_ms: params.endpointTimeoutMs,
395
- parameters: this.getParametersForBody(params.parameters)
453
+ parameters: this.getParametersForBody(params.parameters),
454
+ tool_call_output_timeout_ms: params.toolCallOutputTimeoutMs
396
455
  }
397
456
  );
398
457
  return response;
399
458
  }
400
- async delete(name) {
459
+ async delete(nameOrId) {
401
460
  const response = await this.phonic.delete(
402
- `/tools/${name}`
461
+ `/tools/${nameOrId}`
403
462
  );
404
463
  return response;
405
464
  }
@@ -454,6 +513,7 @@ var Phonic = class {
454
513
  headers;
455
514
  agents = new Agents(this);
456
515
  conversations = new Conversations(this);
516
+ projects = new Projects(this);
457
517
  tools = new Tools(this);
458
518
  voices = new Voices(this);
459
519
  sts = new SpeechToSpeech(this);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phonic",
3
- "version": "0.26.1",
3
+ "version": "0.28.0",
4
4
  "description": "Phonic Node.js SDK",
5
5
  "scripts": {
6
6
  "build": "tsup",