phonic 0.32.8 → 0.32.10

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.
@@ -43,8 +43,8 @@ function normalizeClientOptions(options) {
43
43
  const headers = (0, headers_js_1.mergeHeaders)({
44
44
  "X-Fern-Language": "JavaScript",
45
45
  "X-Fern-SDK-Name": "phonic",
46
- "X-Fern-SDK-Version": "0.32.8",
47
- "User-Agent": "phonic/0.32.8",
46
+ "X-Fern-SDK-Version": "0.32.10",
47
+ "User-Agent": "phonic/0.32.10",
48
48
  "X-Fern-Runtime": core.RUNTIME.type,
49
49
  "X-Fern-Runtime-Version": core.RUNTIME.version,
50
50
  }, options === null || options === void 0 ? void 0 : options.headers);
@@ -15,8 +15,9 @@ import * as core from "./core/index.js";
15
15
  export declare namespace PhonicClient {
16
16
  type Options = BaseClientOptions & {
17
17
  /**
18
- * When `true`, conversation WebSockets automatically reconnect after an
19
- * abnormal disconnect (WebSocket close code 1006) using `reconnect_conv_id`.
18
+ * **Experimental.** When `true`, conversation WebSockets automatically
19
+ * reconnect and resume after a non-deliberate disconnect (WebSocket close
20
+ * codes 1006, 1012, or 1001/"restarting") using `reconnect_conv_id`.
20
21
  * Defaults to `false` until the behavior is broadly validated in production;
21
22
  * set to `true` to opt in early.
22
23
  */
@@ -6,9 +6,9 @@ import { ConversationsSocket } from "./Socket.js";
6
6
  export declare namespace ConversationsClient {
7
7
  type Options = BaseClientOptions & {
8
8
  /**
9
- * When `true`, `connect()` uses session-aware reconnection on abnormal
10
- * disconnect (1006). Set via `PhonicClient` options as
11
- * `reconnectConversationOnAbnormalDisconnect`.
9
+ * **Experimental.** When `true`, `connect()` uses session-aware reconnection
10
+ * on a non-deliberate disconnect (close codes 1006, 1012, or 1001/"restarting").
11
+ * Set via `PhonicClient` options as `reconnectConversationOnAbnormalDisconnect`.
12
12
  */
13
13
  reconnectConversationOnAbnormalDisconnect?: boolean;
14
14
  };
@@ -85,6 +85,8 @@ export interface ConfigOptions {
85
85
  assistant_backchannel_aggressiveness?: number | undefined;
86
86
  /** When not `null`, the agent will call this endpoint to get configuration options for the conversation. */
87
87
  configuration_endpoint?: (ConfigOptions.ConfigurationEndpoint | null) | undefined;
88
+ /** Additional runtime parameters. */
89
+ additional_params?: Record<string, unknown> | undefined;
88
90
  /**
89
91
  * Policy controlling how long transcripts and audio recordings are retained before being deleted.
90
92
  * When `zero_data_retention` is `true`, nothing is retained and `transcripts`/`audio_recordings` are omitted.
@@ -69,6 +69,8 @@ export interface OutboundCallConfig {
69
69
  assistant_backchannel_aggressiveness?: number | undefined;
70
70
  /** When not `null`, at the beginning of the conversation the agent will make a POST request to this endpoint to get configuration options. */
71
71
  configuration_endpoint?: (OutboundCallConfig.ConfigurationEndpoint | null) | undefined;
72
+ /** Additional runtime parameters. */
73
+ additional_params?: Record<string, unknown> | undefined;
72
74
  /** Controls how long transcripts and audio recordings are retained before deletion. */
73
75
  data_retention_policy?: Phonic.DataRetentionPolicy | undefined;
74
76
  }
@@ -2,7 +2,7 @@ import * as core from "../core/index.js";
2
2
  import type * as Phonic from "../api/index.js";
3
3
  import { ConversationsSocket } from "../api/resources/conversations/client/Socket.js";
4
4
  export interface ReconnectableConversationsSocketArgs {
5
- /** Called on 1006 to create a new socket with reconnect_conv_id. May be async (e.g. fresh auth). */
5
+ /** Called on a reconnectable close to create a new socket with reconnect_conv_id. May be async (e.g. fresh auth). */
6
6
  createReconnectSocket: (conversationId: string) => core.ReconnectingWebSocket | Promise<core.ReconnectingWebSocket>;
7
7
  /** Initial socket for the first connection. */
8
8
  socket: core.ReconnectingWebSocket;
@@ -16,9 +16,10 @@ type EventHandlers = {
16
16
  error?: (error: Error) => void;
17
17
  };
18
18
  /**
19
- * Wraps ConversationsSocket with automatic reconnection on 1006.
19
+ * Wraps ConversationsSocket with automatic reconnection on a reconnectable
20
+ * close (1006, 1012, or 1001/"restarting" — see isReconnectableClose).
20
21
  *
21
- * On abnormal closure, creates a brand new ReconnectingWebSocket (via the
22
+ * On such a close, creates a brand new ReconnectingWebSocket (via the
22
23
  * createReconnectSocket factory) and wraps it in a fresh ConversationsSocket,
23
24
  * forwarding all events to user-registered handlers.
24
25
  *
@@ -60,7 +61,7 @@ export declare class ReconnectableConversationsSocket {
60
61
  sendMute(message: Phonic.MutePayload): void;
61
62
  sendUnmute(message: Phonic.UnmutePayload): void;
62
63
  /**
63
- * Not supported — reconnection after 1006 is handled automatically.
64
+ * Not supported — reconnection after a dropped connection is handled automatically.
64
65
  * To start a new conversation, create a new socket via client.conversations.connect().
65
66
  */
66
67
  connect(): never;
@@ -46,20 +46,33 @@ exports.ReconnectableConversationsSocket = void 0;
46
46
  const core = __importStar(require("../core/index.js"));
47
47
  const Socket_js_1 = require("../api/resources/conversations/client/Socket.js");
48
48
  const json_js_1 = require("../core/json.js");
49
- /** 1006 is the only close code that indicates an unexpected disconnect
50
- * worth reconnecting for. All other codes (1000, 4000, 4800, etc.)
51
- * are intentional server-side closes. */
52
49
  const ABNORMAL_CLOSURE = 1006;
50
+ const SERVICE_RESTART = 1012;
51
+ const GOING_AWAY = 1001;
52
+ /** Whether a close means the disconnect was NOT a deliberate end of the
53
+ * conversation, so the SDK should transparently reconnect and resume it:
54
+ * - 1006 abnormal closure (socket died with no close frame)
55
+ * - 1012 service restart — an edge proxy/load-balancer restart closes the
56
+ * client with 1012/"restarting"; the conversation is still alive
57
+ * server-side within the grace window
58
+ * - 1001 "going away" ONLY when the reason is "restarting" — a proxy drain
59
+ * can surface to the client as 1001/"restarting" instead of 1012. A bare
60
+ * 1001 (empty/other reason) is a deliberate close (the caller ended the
61
+ * conversation, tab closed/suspended) and must NOT reconnect.
62
+ * Matches the server's reconnect policy. All other codes (1000, 4000,
63
+ * 4800, ...) are intentional closes. */
64
+ const isReconnectableClose = (code, reason) => code === ABNORMAL_CLOSURE || code === SERVICE_RESTART || (code === GOING_AWAY && reason === "restarting");
53
65
  const BASE_RECONNECT_DELAY_MS = 500;
54
66
  const MAX_RECONNECT_DELAY_MS = 5000;
55
67
  /** Safety cap: stop retrying if the server is completely unreachable.
56
68
  * In normal operation the server's terminal codes (4800/4801) stop
57
- * retries much sooner (within the 10s grace period). */
69
+ * retries much sooner (within the 30s grace period). */
58
70
  const MAX_RECONNECT_ATTEMPTS = 10;
59
71
  /**
60
- * Wraps ConversationsSocket with automatic reconnection on 1006.
72
+ * Wraps ConversationsSocket with automatic reconnection on a reconnectable
73
+ * close (1006, 1012, or 1001/"restarting" — see isReconnectableClose).
61
74
  *
62
- * On abnormal closure, creates a brand new ReconnectingWebSocket (via the
75
+ * On such a close, creates a brand new ReconnectingWebSocket (via the
63
76
  * createReconnectSocket factory) and wraps it in a fresh ConversationsSocket,
64
77
  * forwarding all events to user-registered handlers.
65
78
  *
@@ -141,12 +154,12 @@ class ReconnectableConversationsSocket {
141
154
  this._safeSend((inner) => inner.sendUnmute(message));
142
155
  }
143
156
  /**
144
- * Not supported — reconnection after 1006 is handled automatically.
157
+ * Not supported — reconnection after a dropped connection is handled automatically.
145
158
  * To start a new conversation, create a new socket via client.conversations.connect().
146
159
  */
147
160
  connect() {
148
161
  throw new Error("connect() is not supported on ReconnectableConversationsSocket. "
149
- + "Reconnection after 1006 is automatic. To start a new conversation, "
162
+ + "Reconnection after an abnormal close is automatic. To start a new conversation, "
150
163
  + "call client.conversations.connect() again.");
151
164
  }
152
165
  close() {
@@ -225,7 +238,7 @@ class ReconnectableConversationsSocket {
225
238
  catch (_d) {
226
239
  this._pendingReplacement = false;
227
240
  // Connection failed — schedule another attempt.
228
- // The server's grace period (10s) is the natural limit;
241
+ // The server's grace period (30s) is the natural limit;
229
242
  // once it expires, the next attempt will get 4800 and stop.
230
243
  this._scheduleReconnect();
231
244
  }
@@ -265,7 +278,7 @@ class ReconnectableConversationsSocket {
265
278
  if (this._isClosed) {
266
279
  return;
267
280
  }
268
- if (event.code === ABNORMAL_CLOSURE && this._conversationId !== null) {
281
+ if (isReconnectableClose(event.code, event.reason) && this._conversationId !== null) {
269
282
  // We have a conversation to resume — cancel RWS's built-in
270
283
  // auto-reconnect and handle it ourselves with reconnect_conv_id.
271
284
  // _handleClose calls _connect() before notifying listeners,
@@ -275,8 +288,8 @@ class ReconnectableConversationsSocket {
275
288
  rawSocket.close();
276
289
  this._scheduleReconnect();
277
290
  }
278
- // 1006 without conversationId: let RWS handle transport-level
279
- // reconnect normally (starts a fresh conversation).
291
+ // Reconnectable close without conversationId: let RWS handle
292
+ // transport-level reconnect normally (starts a fresh conversation).
280
293
  };
281
294
  rawSocket.addEventListener("message", onMessage);
282
295
  rawSocket.addEventListener("close", onClose);
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "0.32.8";
1
+ export declare const SDK_VERSION = "0.32.10";
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SDK_VERSION = void 0;
4
- exports.SDK_VERSION = "0.32.8";
4
+ exports.SDK_VERSION = "0.32.10";
@@ -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.8",
10
- "User-Agent": "phonic/0.32.8",
9
+ "X-Fern-SDK-Version": "0.32.10",
10
+ "User-Agent": "phonic/0.32.10",
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);
@@ -15,8 +15,9 @@ import * as core from "./core/index.mjs";
15
15
  export declare namespace PhonicClient {
16
16
  type Options = BaseClientOptions & {
17
17
  /**
18
- * When `true`, conversation WebSockets automatically reconnect after an
19
- * abnormal disconnect (WebSocket close code 1006) using `reconnect_conv_id`.
18
+ * **Experimental.** When `true`, conversation WebSockets automatically
19
+ * reconnect and resume after a non-deliberate disconnect (WebSocket close
20
+ * codes 1006, 1012, or 1001/"restarting") using `reconnect_conv_id`.
20
21
  * Defaults to `false` until the behavior is broadly validated in production;
21
22
  * set to `true` to opt in early.
22
23
  */
@@ -6,9 +6,9 @@ import { ConversationsSocket } from "./Socket.mjs";
6
6
  export declare namespace ConversationsClient {
7
7
  type Options = BaseClientOptions & {
8
8
  /**
9
- * When `true`, `connect()` uses session-aware reconnection on abnormal
10
- * disconnect (1006). Set via `PhonicClient` options as
11
- * `reconnectConversationOnAbnormalDisconnect`.
9
+ * **Experimental.** When `true`, `connect()` uses session-aware reconnection
10
+ * on a non-deliberate disconnect (close codes 1006, 1012, or 1001/"restarting").
11
+ * Set via `PhonicClient` options as `reconnectConversationOnAbnormalDisconnect`.
12
12
  */
13
13
  reconnectConversationOnAbnormalDisconnect?: boolean;
14
14
  };
@@ -85,6 +85,8 @@ export interface ConfigOptions {
85
85
  assistant_backchannel_aggressiveness?: number | undefined;
86
86
  /** When not `null`, the agent will call this endpoint to get configuration options for the conversation. */
87
87
  configuration_endpoint?: (ConfigOptions.ConfigurationEndpoint | null) | undefined;
88
+ /** Additional runtime parameters. */
89
+ additional_params?: Record<string, unknown> | undefined;
88
90
  /**
89
91
  * Policy controlling how long transcripts and audio recordings are retained before being deleted.
90
92
  * When `zero_data_retention` is `true`, nothing is retained and `transcripts`/`audio_recordings` are omitted.
@@ -69,6 +69,8 @@ export interface OutboundCallConfig {
69
69
  assistant_backchannel_aggressiveness?: number | undefined;
70
70
  /** When not `null`, at the beginning of the conversation the agent will make a POST request to this endpoint to get configuration options. */
71
71
  configuration_endpoint?: (OutboundCallConfig.ConfigurationEndpoint | null) | undefined;
72
+ /** Additional runtime parameters. */
73
+ additional_params?: Record<string, unknown> | undefined;
72
74
  /** Controls how long transcripts and audio recordings are retained before deletion. */
73
75
  data_retention_policy?: Phonic.DataRetentionPolicy | undefined;
74
76
  }
@@ -2,7 +2,7 @@ import * as core from "../core/index.mjs";
2
2
  import type * as Phonic from "../api/index.mjs";
3
3
  import { ConversationsSocket } from "../api/resources/conversations/client/Socket.mjs";
4
4
  export interface ReconnectableConversationsSocketArgs {
5
- /** Called on 1006 to create a new socket with reconnect_conv_id. May be async (e.g. fresh auth). */
5
+ /** Called on a reconnectable close to create a new socket with reconnect_conv_id. May be async (e.g. fresh auth). */
6
6
  createReconnectSocket: (conversationId: string) => core.ReconnectingWebSocket | Promise<core.ReconnectingWebSocket>;
7
7
  /** Initial socket for the first connection. */
8
8
  socket: core.ReconnectingWebSocket;
@@ -16,9 +16,10 @@ type EventHandlers = {
16
16
  error?: (error: Error) => void;
17
17
  };
18
18
  /**
19
- * Wraps ConversationsSocket with automatic reconnection on 1006.
19
+ * Wraps ConversationsSocket with automatic reconnection on a reconnectable
20
+ * close (1006, 1012, or 1001/"restarting" — see isReconnectableClose).
20
21
  *
21
- * On abnormal closure, creates a brand new ReconnectingWebSocket (via the
22
+ * On such a close, creates a brand new ReconnectingWebSocket (via the
22
23
  * createReconnectSocket factory) and wraps it in a fresh ConversationsSocket,
23
24
  * forwarding all events to user-registered handlers.
24
25
  *
@@ -60,7 +61,7 @@ export declare class ReconnectableConversationsSocket {
60
61
  sendMute(message: Phonic.MutePayload): void;
61
62
  sendUnmute(message: Phonic.UnmutePayload): void;
62
63
  /**
63
- * Not supported — reconnection after 1006 is handled automatically.
64
+ * Not supported — reconnection after a dropped connection is handled automatically.
64
65
  * To start a new conversation, create a new socket via client.conversations.connect().
65
66
  */
66
67
  connect(): never;
@@ -10,20 +10,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import * as core from "../core/index.mjs";
11
11
  import { ConversationsSocket } from "../api/resources/conversations/client/Socket.mjs";
12
12
  import { fromJson } from "../core/json.mjs";
13
- /** 1006 is the only close code that indicates an unexpected disconnect
14
- * worth reconnecting for. All other codes (1000, 4000, 4800, etc.)
15
- * are intentional server-side closes. */
16
13
  const ABNORMAL_CLOSURE = 1006;
14
+ const SERVICE_RESTART = 1012;
15
+ const GOING_AWAY = 1001;
16
+ /** Whether a close means the disconnect was NOT a deliberate end of the
17
+ * conversation, so the SDK should transparently reconnect and resume it:
18
+ * - 1006 abnormal closure (socket died with no close frame)
19
+ * - 1012 service restart — an edge proxy/load-balancer restart closes the
20
+ * client with 1012/"restarting"; the conversation is still alive
21
+ * server-side within the grace window
22
+ * - 1001 "going away" ONLY when the reason is "restarting" — a proxy drain
23
+ * can surface to the client as 1001/"restarting" instead of 1012. A bare
24
+ * 1001 (empty/other reason) is a deliberate close (the caller ended the
25
+ * conversation, tab closed/suspended) and must NOT reconnect.
26
+ * Matches the server's reconnect policy. All other codes (1000, 4000,
27
+ * 4800, ...) are intentional closes. */
28
+ const isReconnectableClose = (code, reason) => code === ABNORMAL_CLOSURE || code === SERVICE_RESTART || (code === GOING_AWAY && reason === "restarting");
17
29
  const BASE_RECONNECT_DELAY_MS = 500;
18
30
  const MAX_RECONNECT_DELAY_MS = 5000;
19
31
  /** Safety cap: stop retrying if the server is completely unreachable.
20
32
  * In normal operation the server's terminal codes (4800/4801) stop
21
- * retries much sooner (within the 10s grace period). */
33
+ * retries much sooner (within the 30s grace period). */
22
34
  const MAX_RECONNECT_ATTEMPTS = 10;
23
35
  /**
24
- * Wraps ConversationsSocket with automatic reconnection on 1006.
36
+ * Wraps ConversationsSocket with automatic reconnection on a reconnectable
37
+ * close (1006, 1012, or 1001/"restarting" — see isReconnectableClose).
25
38
  *
26
- * On abnormal closure, creates a brand new ReconnectingWebSocket (via the
39
+ * On such a close, creates a brand new ReconnectingWebSocket (via the
27
40
  * createReconnectSocket factory) and wraps it in a fresh ConversationsSocket,
28
41
  * forwarding all events to user-registered handlers.
29
42
  *
@@ -105,12 +118,12 @@ export class ReconnectableConversationsSocket {
105
118
  this._safeSend((inner) => inner.sendUnmute(message));
106
119
  }
107
120
  /**
108
- * Not supported — reconnection after 1006 is handled automatically.
121
+ * Not supported — reconnection after a dropped connection is handled automatically.
109
122
  * To start a new conversation, create a new socket via client.conversations.connect().
110
123
  */
111
124
  connect() {
112
125
  throw new Error("connect() is not supported on ReconnectableConversationsSocket. "
113
- + "Reconnection after 1006 is automatic. To start a new conversation, "
126
+ + "Reconnection after an abnormal close is automatic. To start a new conversation, "
114
127
  + "call client.conversations.connect() again.");
115
128
  }
116
129
  close() {
@@ -189,7 +202,7 @@ export class ReconnectableConversationsSocket {
189
202
  catch (_d) {
190
203
  this._pendingReplacement = false;
191
204
  // Connection failed — schedule another attempt.
192
- // The server's grace period (10s) is the natural limit;
205
+ // The server's grace period (30s) is the natural limit;
193
206
  // once it expires, the next attempt will get 4800 and stop.
194
207
  this._scheduleReconnect();
195
208
  }
@@ -229,7 +242,7 @@ export class ReconnectableConversationsSocket {
229
242
  if (this._isClosed) {
230
243
  return;
231
244
  }
232
- if (event.code === ABNORMAL_CLOSURE && this._conversationId !== null) {
245
+ if (isReconnectableClose(event.code, event.reason) && this._conversationId !== null) {
233
246
  // We have a conversation to resume — cancel RWS's built-in
234
247
  // auto-reconnect and handle it ourselves with reconnect_conv_id.
235
248
  // _handleClose calls _connect() before notifying listeners,
@@ -239,8 +252,8 @@ export class ReconnectableConversationsSocket {
239
252
  rawSocket.close();
240
253
  this._scheduleReconnect();
241
254
  }
242
- // 1006 without conversationId: let RWS handle transport-level
243
- // reconnect normally (starts a fresh conversation).
255
+ // Reconnectable close without conversationId: let RWS handle
256
+ // transport-level reconnect normally (starts a fresh conversation).
244
257
  };
245
258
  rawSocket.addEventListener("message", onMessage);
246
259
  rawSocket.addEventListener("close", onClose);
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "0.32.8";
1
+ export declare const SDK_VERSION = "0.32.10";
@@ -1 +1 @@
1
- export const SDK_VERSION = "0.32.8";
1
+ export const SDK_VERSION = "0.32.10";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phonic",
3
- "version": "0.32.8",
3
+ "version": "0.32.10",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",