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
|
@@ -22,13 +22,18 @@ export interface UpdateToolRequest {
|
|
|
22
22
|
/** The static context returned to the agent. Only applicable to custom_context tools. */
|
|
23
23
|
context?: string;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* For `custom_webhook` tools: `location` is required for POST, defaults to `"query_string"` for GET.
|
|
25
|
+
* 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). Replaces the tool's existing parameters, including the form they are stored in.
|
|
26
|
+
* For `custom_webhook` tools: when sending an array, `location` is required for POST and defaults to `"query_string"` for GET, and `parameter_locations` must not be sent; when sending a JSON Schema object, placement is supplied in `parameter_locations`.
|
|
28
27
|
* For `custom_websocket`, `built_in_transfer_to_phone_number`, and `built_in_transfer_to_agent` tools: `location` must not be specified.
|
|
29
28
|
*/
|
|
30
|
-
parameters?:
|
|
31
|
-
/**
|
|
29
|
+
parameters?: UpdateToolRequest.Parameters;
|
|
30
|
+
/**
|
|
31
|
+
* 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.
|
|
32
|
+
* Can be sent on its own to move existing parameters without resending `parameters`; entries are merged over the tool's current placement, so parameters left out keep where they were.
|
|
33
|
+
* Every key must name a top-level parameter. For POST webhooks, every parameter needs a placement. For GET webhooks, unplaced parameters default to `"query_string"` and `"request_body"` is not allowed.
|
|
34
|
+
*/
|
|
35
|
+
parameter_locations?: Record<string, UpdateToolRequest.ParameterLocations.Value>;
|
|
36
|
+
/** HTTP method for webhook tools. When switching from POST to GET, a tool with request body parameters must also send new `parameters` (or `parameter_locations`) placing them in the query string. */
|
|
32
37
|
endpoint_method?: UpdateToolRequest.EndpointMethod;
|
|
33
38
|
/** URL for webhook tools. Must be a publicly routable HTTPS URL without embedded credentials. */
|
|
34
39
|
endpoint_url?: string;
|
|
@@ -56,6 +61,8 @@ export interface UpdateToolRequest {
|
|
|
56
61
|
wait_for_speech_before_tool_call?: boolean;
|
|
57
62
|
/** When true, forbids the agent from speaking after executing the tool. Available for custom_context, custom_webhook and custom_websocket tools. */
|
|
58
63
|
forbid_speech_after_tool_call?: boolean;
|
|
64
|
+
/** When true, forbids the agent from calling the tool right after it has spoken. Available for custom_webhook and custom_websocket tools. */
|
|
65
|
+
forbid_tool_call_after_speech?: boolean;
|
|
59
66
|
/** 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. */
|
|
60
67
|
allow_tool_chaining?: boolean;
|
|
61
68
|
/** 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. */
|
|
@@ -68,7 +75,20 @@ export declare namespace UpdateToolRequest {
|
|
|
68
75
|
readonly Async: "async";
|
|
69
76
|
};
|
|
70
77
|
type ExecutionMode = (typeof ExecutionMode)[keyof typeof ExecutionMode];
|
|
71
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* 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). Replaces the tool's existing parameters, including the form they are stored in.
|
|
80
|
+
* For `custom_webhook` tools: when sending an array, `location` is required for POST and defaults to `"query_string"` for GET, and `parameter_locations` must not be sent; when sending a JSON Schema object, placement is supplied in `parameter_locations`.
|
|
81
|
+
* For `custom_websocket`, `built_in_transfer_to_phone_number`, and `built_in_transfer_to_agent` tools: `location` must not be specified.
|
|
82
|
+
*/
|
|
83
|
+
type Parameters = Phonic.ToolParameter[] | Phonic.ToolParametersJsonSchema;
|
|
84
|
+
namespace ParameterLocations {
|
|
85
|
+
const Value: {
|
|
86
|
+
readonly RequestBody: "request_body";
|
|
87
|
+
readonly QueryString: "query_string";
|
|
88
|
+
};
|
|
89
|
+
type Value = (typeof Value)[keyof typeof Value];
|
|
90
|
+
}
|
|
91
|
+
/** HTTP method for webhook tools. When switching from POST to GET, a tool with request body parameters must also send new `parameters` (or `parameter_locations`) placing them in the query string. */
|
|
72
92
|
const EndpointMethod: {
|
|
73
93
|
readonly Get: "GET";
|
|
74
94
|
readonly Post: "POST";
|
|
@@ -6,7 +6,14 @@ export var UpdateToolRequest;
|
|
|
6
6
|
Sync: "sync",
|
|
7
7
|
Async: "async",
|
|
8
8
|
};
|
|
9
|
-
|
|
9
|
+
let ParameterLocations;
|
|
10
|
+
(function (ParameterLocations) {
|
|
11
|
+
ParameterLocations.Value = {
|
|
12
|
+
RequestBody: "request_body",
|
|
13
|
+
QueryString: "query_string",
|
|
14
|
+
};
|
|
15
|
+
})(ParameterLocations = UpdateToolRequest.ParameterLocations || (UpdateToolRequest.ParameterLocations = {}));
|
|
16
|
+
/** HTTP method for webhook tools. When switching from POST to GET, a tool with request body parameters must also send new `parameters` (or `parameter_locations`) placing them in the query string. */
|
|
10
17
|
UpdateToolRequest.EndpointMethod = {
|
|
11
18
|
Get: "GET",
|
|
12
19
|
Post: "POST",
|
|
@@ -84,7 +84,7 @@ export interface Agent {
|
|
|
84
84
|
vad_min_silence_duration_ms?: number | undefined;
|
|
85
85
|
/** Voice activity detection threshold. */
|
|
86
86
|
vad_threshold?: number | undefined;
|
|
87
|
-
/** When `true`, PII and PHI are redacted from text transcripts (e.g. replaced with tags like `[PHONE
|
|
87
|
+
/** 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. */
|
|
88
88
|
enable_redaction?: boolean | undefined;
|
|
89
89
|
/** The URL-friendly slug of the agent. */
|
|
90
90
|
slug?: string | undefined;
|
|
@@ -69,7 +69,7 @@ export interface ConfigOptions {
|
|
|
69
69
|
tools?: Phonic.ToolDefinition[] | undefined;
|
|
70
70
|
/** Template variables for system prompt and welcome message */
|
|
71
71
|
template_variables?: Record<string, string> | undefined;
|
|
72
|
-
/** When `true`, PII and PHI are redacted from text transcripts (e.g. replaced with tags like `[PHONE
|
|
72
|
+
/** 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. */
|
|
73
73
|
enable_redaction?: boolean | undefined;
|
|
74
74
|
/** Names of pre-configured MCP servers to make available to the assistant. Names must be unique. */
|
|
75
75
|
mcp_servers?: string[] | undefined;
|
|
@@ -86,7 +86,7 @@ export interface CreateAgentRequest {
|
|
|
86
86
|
vad_min_silence_duration_ms?: number | undefined;
|
|
87
87
|
/** Voice activity detection threshold. */
|
|
88
88
|
vad_threshold?: number | undefined;
|
|
89
|
-
/** When `true`, PII and PHI are redacted from text transcripts (e.g. replaced with tags like `[PHONE
|
|
89
|
+
/** 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. */
|
|
90
90
|
enable_redaction?: boolean | undefined;
|
|
91
91
|
/** Array of MCP server IDs to make available to the agent. */
|
|
92
92
|
mcp_server_ids?: string[] | undefined;
|
|
@@ -15,6 +15,8 @@ export interface InlineWebSocketTool {
|
|
|
15
15
|
wait_for_speech_before_tool_call?: boolean | undefined;
|
|
16
16
|
/** When true, prevents the assistant from speaking after executing the tool. */
|
|
17
17
|
forbid_speech_after_tool_call?: boolean | undefined;
|
|
18
|
+
/** When true, prevents the assistant from calling the tool right after it has spoken. */
|
|
19
|
+
forbid_tool_call_after_speech?: boolean | undefined;
|
|
18
20
|
/** When true, allows the assistant to call another tool after this tool. */
|
|
19
21
|
allow_tool_chaining?: boolean | undefined;
|
|
20
22
|
/** For async tools, when true, the assistant waits for the response and speaks when it arrives. */
|
|
@@ -47,7 +47,7 @@ export interface OutboundCallConfig {
|
|
|
47
47
|
min_words_to_interrupt?: number | undefined;
|
|
48
48
|
/** Array of built-in or custom tool names to use. */
|
|
49
49
|
tools?: OutboundCallConfig.Tools.Item[] | undefined;
|
|
50
|
-
/** When `true`, PII and PHI are redacted from text transcripts (e.g. replaced with tags like `[PHONE
|
|
50
|
+
/** 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. */
|
|
51
51
|
enable_redaction?: boolean | undefined;
|
|
52
52
|
/** The speech-to-speech model to use. */
|
|
53
53
|
model?: "merritt" | undefined;
|
|
@@ -11,8 +11,17 @@ export interface Tool {
|
|
|
11
11
|
type: Tool.Type;
|
|
12
12
|
/** Mode of operation - sync waits for response, async continues without waiting. */
|
|
13
13
|
execution_mode?: Tool.ExecutionMode | undefined;
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The tool's parameters, returned in the same form they were defined in.
|
|
16
|
+
* Tools defined with a flat list of parameters return an array of parameter definitions (with `location` included inline for `custom_webhook` tools).
|
|
17
|
+
* Tools defined with a raw JSON Schema object return that object; for `custom_webhook` tools the parameter placement is then returned separately in `parameter_locations`.
|
|
18
|
+
*/
|
|
19
|
+
parameters: Tool.Parameters;
|
|
20
|
+
/**
|
|
21
|
+
* Where each top-level parameter is sent in the webhook request, as a map from parameter name to location.
|
|
22
|
+
* Only returned for `custom_webhook` tools whose `parameters` are a raw JSON Schema object. Tools defined with a flat list of parameters carry `location` inline on each parameter instead.
|
|
23
|
+
*/
|
|
24
|
+
parameter_locations?: Record<string, Tool.ParameterLocations.Value> | undefined;
|
|
16
25
|
/** HTTP method for webhook tools. */
|
|
17
26
|
endpoint_method?: Tool.EndpointMethod | undefined;
|
|
18
27
|
/** URL for webhook tools. */
|
|
@@ -43,6 +52,8 @@ export interface Tool {
|
|
|
43
52
|
wait_for_speech_before_tool_call?: boolean | undefined;
|
|
44
53
|
/** When true, forbids the agent from speaking after executing the tool. Available for custom_context, custom_webhook and custom_websocket tools. */
|
|
45
54
|
forbid_speech_after_tool_call?: boolean | undefined;
|
|
55
|
+
/** When true, forbids the agent from calling the tool right after it has spoken. Available for custom_webhook and custom_websocket tools. */
|
|
56
|
+
forbid_tool_call_after_speech?: boolean | undefined;
|
|
46
57
|
/** 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. */
|
|
47
58
|
allow_tool_chaining?: boolean | undefined;
|
|
48
59
|
/** 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. */
|
|
@@ -73,6 +84,19 @@ export declare namespace Tool {
|
|
|
73
84
|
readonly Async: "async";
|
|
74
85
|
};
|
|
75
86
|
type ExecutionMode = (typeof ExecutionMode)[keyof typeof ExecutionMode];
|
|
87
|
+
/**
|
|
88
|
+
* The tool's parameters, returned in the same form they were defined in.
|
|
89
|
+
* Tools defined with a flat list of parameters return an array of parameter definitions (with `location` included inline for `custom_webhook` tools).
|
|
90
|
+
* Tools defined with a raw JSON Schema object return that object; for `custom_webhook` tools the parameter placement is then returned separately in `parameter_locations`.
|
|
91
|
+
*/
|
|
92
|
+
type Parameters = Phonic.ToolParameter[] | Phonic.ToolParametersJsonSchema;
|
|
93
|
+
namespace ParameterLocations {
|
|
94
|
+
const Value: {
|
|
95
|
+
readonly RequestBody: "request_body";
|
|
96
|
+
readonly QueryString: "query_string";
|
|
97
|
+
};
|
|
98
|
+
type Value = (typeof Value)[keyof typeof Value];
|
|
99
|
+
}
|
|
76
100
|
/** HTTP method for webhook tools. */
|
|
77
101
|
const EndpointMethod: {
|
|
78
102
|
readonly Get: "GET";
|
|
@@ -17,6 +17,13 @@ export var Tool;
|
|
|
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 = Tool.ParameterLocations || (Tool.ParameterLocations = {}));
|
|
20
27
|
/** HTTP method for webhook tools. */
|
|
21
28
|
Tool.EndpointMethod = {
|
|
22
29
|
Get: "GET",
|
|
@@ -3,6 +3,8 @@ export interface ToolParameter {
|
|
|
3
3
|
type: ToolParameter.Type;
|
|
4
4
|
/** Required only when type is "array". The type of items in the array. */
|
|
5
5
|
item_type?: ToolParameter.ItemType | undefined;
|
|
6
|
+
/** Required only when type is "enum". The fixed set of allowed string values for the parameter. Values must be unique and non-empty. */
|
|
7
|
+
enum_values?: string[] | undefined;
|
|
6
8
|
/** The parameter name. */
|
|
7
9
|
name: string;
|
|
8
10
|
/** Description of the parameter. */
|
|
@@ -14,7 +16,7 @@ export interface ToolParameter {
|
|
|
14
16
|
* - For GET webhooks: defaults to `"query_string"` and `"request_body"` is not allowed.
|
|
15
17
|
* - For POST webhooks: required, can be either `"request_body"` or `"query_string"`.
|
|
16
18
|
* - Not allowed for `custom_websocket`, `built_in_transfer_to_phone_number`, or `built_in_transfer_to_agent` tools.
|
|
17
|
-
* When
|
|
19
|
+
* When switching a webhook tool's `endpoint_method` from POST to GET, its request body parameters must be re-sent with `"query_string"` locations.
|
|
18
20
|
*/
|
|
19
21
|
location?: ToolParameter.Location | undefined;
|
|
20
22
|
}
|
|
@@ -26,6 +28,7 @@ export declare namespace ToolParameter {
|
|
|
26
28
|
readonly Number: "number";
|
|
27
29
|
readonly Boolean: "boolean";
|
|
28
30
|
readonly Array: "array";
|
|
31
|
+
readonly Enum: "enum";
|
|
29
32
|
};
|
|
30
33
|
type Type = (typeof Type)[keyof typeof Type];
|
|
31
34
|
/** Required only when type is "array". The type of items in the array. */
|
|
@@ -41,7 +44,7 @@ export declare namespace ToolParameter {
|
|
|
41
44
|
* - For GET webhooks: defaults to `"query_string"` and `"request_body"` is not allowed.
|
|
42
45
|
* - For POST webhooks: required, can be either `"request_body"` or `"query_string"`.
|
|
43
46
|
* - Not allowed for `custom_websocket`, `built_in_transfer_to_phone_number`, or `built_in_transfer_to_agent` tools.
|
|
44
|
-
* When
|
|
47
|
+
* When switching a webhook tool's `endpoint_method` from POST to GET, its request body parameters must be re-sent with `"query_string"` locations.
|
|
45
48
|
*/
|
|
46
49
|
const Location: {
|
|
47
50
|
readonly RequestBody: "request_body";
|
|
@@ -8,6 +8,7 @@ export var ToolParameter;
|
|
|
8
8
|
Number: "number",
|
|
9
9
|
Boolean: "boolean",
|
|
10
10
|
Array: "array",
|
|
11
|
+
Enum: "enum",
|
|
11
12
|
};
|
|
12
13
|
/** Required only when type is "array". The type of items in the array. */
|
|
13
14
|
ToolParameter.ItemType = {
|
|
@@ -21,7 +22,7 @@ export var ToolParameter;
|
|
|
21
22
|
* - For GET webhooks: defaults to `"query_string"` and `"request_body"` is not allowed.
|
|
22
23
|
* - For POST webhooks: required, can be either `"request_body"` or `"query_string"`.
|
|
23
24
|
* - Not allowed for `custom_websocket`, `built_in_transfer_to_phone_number`, or `built_in_transfer_to_agent` tools.
|
|
24
|
-
* When
|
|
25
|
+
* When switching a webhook tool's `endpoint_method` from POST to GET, its request body parameters must be re-sent with `"query_string"` locations.
|
|
25
26
|
*/
|
|
26
27
|
ToolParameter.Location = {
|
|
27
28
|
RequestBody: "request_body",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tool's parameters expressed as a raw JSON Schema object, for parameters that the flat `ToolParameter` list cannot express: nested objects, arrays of objects, `anyOf` variants, `null`, and non-string enums.
|
|
3
|
+
* Each entry in `properties` is a JSON Schema value supporting `type` (`"string"`, `"integer"`, `"number"`, `"boolean"`, `"null"`, `"array"`, `"object"`), `description`, `enum` (string parameters only), `items` (for arrays), `properties`/`required`/`additionalProperties` (for objects) and `anyOf`. Values may be nested up to 5 levels deep.
|
|
4
|
+
* Parameter names cannot be any of the reserved names that Phonic injects into every tool call: `call_info`, `conversation_id`, `from_phone_number`, `to_phone_number`, `twilio_call_sid`.
|
|
5
|
+
* For `custom_webhook` tools, parameter placement is supplied separately in `parameter_locations` rather than inline on the schema.
|
|
6
|
+
*/
|
|
7
|
+
export interface ToolParametersJsonSchema {
|
|
8
|
+
type: "object";
|
|
9
|
+
/** The tool's top-level parameters, as a map from parameter name to its JSON Schema. */
|
|
10
|
+
properties: Record<string, unknown>;
|
|
11
|
+
/** The names of the required top-level parameters. Every name must be defined in `properties`. */
|
|
12
|
+
required?: string[] | undefined;
|
|
13
|
+
/** Must be `false`. Tool parameter schemas do not allow properties beyond the ones declared. */
|
|
14
|
+
additionalProperties?: false | undefined;
|
|
15
|
+
}
|
|
@@ -68,6 +68,7 @@ export * from "./ToolCallPayload.mjs";
|
|
|
68
68
|
export * from "./ToolDefinition.mjs";
|
|
69
69
|
export * from "./ToolName.mjs";
|
|
70
70
|
export * from "./ToolParameter.mjs";
|
|
71
|
+
export * from "./ToolParametersJsonSchema.mjs";
|
|
71
72
|
export * from "./UnmutePayload.mjs";
|
|
72
73
|
export * from "./UpdateSystemPromptPayload.mjs";
|
|
73
74
|
export * from "./UpdateToolsSubsetPayload.mjs";
|
|
@@ -68,6 +68,7 @@ export * from "./ToolCallPayload.mjs";
|
|
|
68
68
|
export * from "./ToolDefinition.mjs";
|
|
69
69
|
export * from "./ToolName.mjs";
|
|
70
70
|
export * from "./ToolParameter.mjs";
|
|
71
|
+
export * from "./ToolParametersJsonSchema.mjs";
|
|
71
72
|
export * from "./UnmutePayload.mjs";
|
|
72
73
|
export * from "./UpdateSystemPromptPayload.mjs";
|
|
73
74
|
export * from "./UpdateToolsSubsetPayload.mjs";
|
|
@@ -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;
|
|
@@ -44,6 +44,11 @@ const MAX_RECONNECT_ATTEMPTS = 10;
|
|
|
44
44
|
* with a terminal close code (4800 session expired, 4801 invalid state),
|
|
45
45
|
* the safety cap is reached, or the user calls close().
|
|
46
46
|
*
|
|
47
|
+
* A reconnectable close is not surfaced to the user's close handler while the
|
|
48
|
+
* reconnect is in flight. The close is emitted only when reconnection has
|
|
49
|
+
* failed, meaning the conversation is closing. Closes that are not
|
|
50
|
+
* reconnectable (1000, 4000, etc) are not affected and will pass through.
|
|
51
|
+
*
|
|
47
52
|
* Uses composition rather than inheritance to avoid coupling to the parent's
|
|
48
53
|
* private event handler registration or ReconnectingWebSocket internals.
|
|
49
54
|
*/
|
|
@@ -56,6 +61,8 @@ export class ReconnectableConversationsSocket {
|
|
|
56
61
|
this._cleanupWireListeners = null;
|
|
57
62
|
this._pendingReconnect = null;
|
|
58
63
|
this._pendingReplacement = false;
|
|
64
|
+
this._lastSuppressedClose = null;
|
|
65
|
+
this._gaveUp = false;
|
|
59
66
|
this._createReconnectSocket = args.createReconnectSocket;
|
|
60
67
|
this._abortSignal = args.abortSignal != undefined ? args.abortSignal : null;
|
|
61
68
|
this._inner = new ConversationsSocket({ socket: args.socket });
|
|
@@ -134,15 +141,36 @@ export class ReconnectableConversationsSocket {
|
|
|
134
141
|
clearTimeout(this._pendingReconnect);
|
|
135
142
|
this._pendingReconnect = null;
|
|
136
143
|
}
|
|
144
|
+
// Close before detaching: ConversationsSocket.close() synthesizes a
|
|
145
|
+
// 1000 close event, and a user-initiated close should still surface one.
|
|
146
|
+
this._inner.close();
|
|
137
147
|
(_a = this._cleanupWireListeners) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
138
148
|
this._cleanupWireListeners = null;
|
|
139
|
-
this._inner.close();
|
|
140
149
|
}
|
|
141
150
|
waitForOpen() {
|
|
142
151
|
return __awaiter(this, void 0, void 0, function* () {
|
|
143
152
|
return this._inner.waitForOpen();
|
|
144
153
|
});
|
|
145
154
|
}
|
|
155
|
+
_willReconnectAfter(event) {
|
|
156
|
+
return (!this._isClosed
|
|
157
|
+
&& !this._gaveUp
|
|
158
|
+
&& this._conversationId !== null
|
|
159
|
+
&& isReconnectableClose(event.code, event.reason));
|
|
160
|
+
}
|
|
161
|
+
_giveUp() {
|
|
162
|
+
var _a, _b;
|
|
163
|
+
this._pendingReplacement = false;
|
|
164
|
+
if (this._gaveUp || this._isClosed) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
this._gaveUp = true;
|
|
168
|
+
const suppressed = this._lastSuppressedClose;
|
|
169
|
+
this._lastSuppressedClose = null;
|
|
170
|
+
if (suppressed !== null) {
|
|
171
|
+
(_b = (_a = this._handlers).close) === null || _b === void 0 ? void 0 : _b.call(_a, suppressed);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
146
174
|
_getReconnectDelay() {
|
|
147
175
|
// Exponential backoff: 500ms, 1s, 2s, 4s, capped at 5s
|
|
148
176
|
const delay = BASE_RECONNECT_DELAY_MS * Math.pow(2, this._reconnectAttempts - 1);
|
|
@@ -151,12 +179,18 @@ export class ReconnectableConversationsSocket {
|
|
|
151
179
|
/** Schedule a reconnection attempt after backoff delay. */
|
|
152
180
|
_scheduleReconnect() {
|
|
153
181
|
var _a, _b, _c;
|
|
154
|
-
|
|
182
|
+
// With no conversation the close was never suppressed, so unlike the
|
|
183
|
+
// branches below there is nothing to emit.
|
|
184
|
+
if (this._isClosed || this._conversationId === null) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if ((_a = this._abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) {
|
|
188
|
+
this._giveUp();
|
|
155
189
|
return;
|
|
156
190
|
}
|
|
157
191
|
if (this._reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
|
158
|
-
this._pendingReplacement = false;
|
|
159
192
|
(_c = (_b = this._handlers).error) === null || _c === void 0 ? void 0 : _c.call(_b, new Error("Max reconnect attempts reached"));
|
|
193
|
+
this._giveUp();
|
|
160
194
|
return;
|
|
161
195
|
}
|
|
162
196
|
// Clear any existing timer to prevent orphaned timeouts
|
|
@@ -167,24 +201,70 @@ export class ReconnectableConversationsSocket {
|
|
|
167
201
|
const delay = this._getReconnectDelay();
|
|
168
202
|
this._pendingReplacement = true;
|
|
169
203
|
this._pendingReconnect = setTimeout(() => {
|
|
204
|
+
var _a;
|
|
170
205
|
this._pendingReconnect = null;
|
|
171
206
|
if (this._isClosed) {
|
|
172
207
|
this._pendingReplacement = false;
|
|
173
208
|
return;
|
|
174
209
|
}
|
|
210
|
+
if ((_a = this._abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) {
|
|
211
|
+
this._giveUp();
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
175
214
|
void this._doReconnect();
|
|
176
215
|
}, delay);
|
|
177
216
|
}
|
|
217
|
+
/** Settle as soon as the abort signal fires rather than waiting on the
|
|
218
|
+
* factory, whose promise is caller-supplied (it awaits fresh auth) and
|
|
219
|
+
* may never settle — the suppressed close would stay hidden forever.
|
|
220
|
+
* Resolves null when aborted; a socket arriving afterwards is closed
|
|
221
|
+
* rather than leaked. The listener is removed once the factory settles,
|
|
222
|
+
* so a long-lived conversation does not accumulate them on the signal. */
|
|
223
|
+
_createSocketOrAbort(created) {
|
|
224
|
+
const signal = this._abortSignal;
|
|
225
|
+
if (signal === null) {
|
|
226
|
+
return created;
|
|
227
|
+
}
|
|
228
|
+
const discardLate = () => {
|
|
229
|
+
void created.then((socket) => socket.close()).catch(() => undefined);
|
|
230
|
+
};
|
|
231
|
+
if (signal.aborted) {
|
|
232
|
+
discardLate();
|
|
233
|
+
return Promise.resolve(null);
|
|
234
|
+
}
|
|
235
|
+
return new Promise((resolve, reject) => {
|
|
236
|
+
const onAbort = () => {
|
|
237
|
+
discardLate();
|
|
238
|
+
resolve(null);
|
|
239
|
+
};
|
|
240
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
241
|
+
created.then((socket) => {
|
|
242
|
+
signal.removeEventListener("abort", onAbort);
|
|
243
|
+
resolve(socket);
|
|
244
|
+
}, (error) => {
|
|
245
|
+
signal.removeEventListener("abort", onAbort);
|
|
246
|
+
reject(error);
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
}
|
|
178
250
|
/** Perform the actual reconnection attempt. */
|
|
179
251
|
_doReconnect() {
|
|
180
252
|
return __awaiter(this, void 0, void 0, function* () {
|
|
181
253
|
var _a, _b;
|
|
182
254
|
try {
|
|
183
255
|
const created = this._createReconnectSocket(this._conversationId);
|
|
184
|
-
const newRawSocket = created instanceof Promise ? yield created : created;
|
|
256
|
+
const newRawSocket = created instanceof Promise ? yield this._createSocketOrAbort(created) : created;
|
|
257
|
+
if (newRawSocket === null) {
|
|
258
|
+
// Aborted while the factory was still in flight.
|
|
259
|
+
this._giveUp();
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
185
262
|
if (this._isClosed || ((_a = this._abortSignal) === null || _a === void 0 ? void 0 : _a.aborted)) {
|
|
186
263
|
this._pendingReplacement = false;
|
|
187
264
|
newRawSocket.close();
|
|
265
|
+
if (!this._isClosed) {
|
|
266
|
+
this._giveUp();
|
|
267
|
+
}
|
|
188
268
|
return;
|
|
189
269
|
}
|
|
190
270
|
// Clean up the old socket: remove our custom listeners and close
|
|
@@ -197,7 +277,7 @@ export class ReconnectableConversationsSocket {
|
|
|
197
277
|
catch ( /* already closed from 1006 */_c) { /* already closed from 1006 */ }
|
|
198
278
|
const newInner = new ConversationsSocket({ socket: newRawSocket });
|
|
199
279
|
this._inner = newInner;
|
|
200
|
-
this._wireInner(newInner, newRawSocket);
|
|
280
|
+
this._wireInner(newInner, newRawSocket, true);
|
|
201
281
|
}
|
|
202
282
|
catch (_d) {
|
|
203
283
|
this._pendingReplacement = false;
|
|
@@ -208,17 +288,41 @@ export class ReconnectableConversationsSocket {
|
|
|
208
288
|
}
|
|
209
289
|
});
|
|
210
290
|
}
|
|
211
|
-
_wireInner(inner, rawSocket) {
|
|
212
|
-
//
|
|
213
|
-
//
|
|
214
|
-
//
|
|
291
|
+
_wireInner(inner, rawSocket, isReplacement = false) {
|
|
292
|
+
// A replacement that closes before ever opening failed at the transport
|
|
293
|
+
// level, and its code says nothing about why: ReconnectingWebSocket
|
|
294
|
+
// synthesizes 1000 for connect errors and timeouts (_handleError ->
|
|
295
|
+
// _disconnect). Read it as a failed attempt rather than as a close.
|
|
296
|
+
// _isClosed excluded: close() also reaches this via the synthesized
|
|
297
|
+
// 1000, and a user-initiated close is a close, not a failed attempt.
|
|
298
|
+
let opened = false;
|
|
299
|
+
const isFailedAttempt = () => isReplacement && !opened && !this._isClosed;
|
|
300
|
+
// Clearing _pendingReplacement before the user's open handler keeps
|
|
301
|
+
// sends made inside that handler from being dropped.
|
|
215
302
|
inner.on("open", () => {
|
|
216
303
|
var _a, _b;
|
|
304
|
+
opened = true;
|
|
217
305
|
this._pendingReplacement = false;
|
|
306
|
+
this._lastSuppressedClose = null;
|
|
218
307
|
(_b = (_a = this._handlers).open) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
219
308
|
});
|
|
220
309
|
inner.on("message", (msg) => { var _a, _b; return (_b = (_a = this._handlers).message) === null || _b === void 0 ? void 0 : _b.call(_a, msg); });
|
|
221
|
-
|
|
310
|
+
// ConversationsSocket registers this in its constructor, so it runs
|
|
311
|
+
// before the rawSocket close listener below that schedules the
|
|
312
|
+
// reconnect — the decision cannot be read off reconnect state here.
|
|
313
|
+
inner.on("close", (ev) => {
|
|
314
|
+
var _a, _b;
|
|
315
|
+
// Leave _lastSuppressedClose holding the original drop, so _giveUp
|
|
316
|
+
// reports what went wrong rather than this attempt's code.
|
|
317
|
+
if (isFailedAttempt()) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (this._willReconnectAfter(ev)) {
|
|
321
|
+
this._lastSuppressedClose = ev;
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
(_b = (_a = this._handlers).close) === null || _b === void 0 ? void 0 : _b.call(_a, ev);
|
|
325
|
+
});
|
|
222
326
|
inner.on("error", (err) => { var _a, _b; return (_b = (_a = this._handlers).error) === null || _b === void 0 ? void 0 : _b.call(_a, err); });
|
|
223
327
|
// Intercept raw messages to capture conversation_id and reset reconnect counter
|
|
224
328
|
const onMessage = (event) => {
|
|
@@ -238,8 +342,15 @@ export class ReconnectableConversationsSocket {
|
|
|
238
342
|
// ignore — inner socket handles parse errors
|
|
239
343
|
}
|
|
240
344
|
};
|
|
345
|
+
// After giving up this is a plain pass-through: the close was already
|
|
346
|
+
// forwarded above, and retrying would repeat the give-up error.
|
|
241
347
|
const onClose = (event) => {
|
|
242
|
-
if (this._isClosed) {
|
|
348
|
+
if (this._isClosed || this._gaveUp) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
if (isFailedAttempt()) {
|
|
352
|
+
rawSocket.close();
|
|
353
|
+
this._scheduleReconnect();
|
|
243
354
|
return;
|
|
244
355
|
}
|
|
245
356
|
if (isReconnectableClose(event.code, event.reason) && this._conversationId !== null) {
|
|
@@ -258,6 +369,11 @@ export class ReconnectableConversationsSocket {
|
|
|
258
369
|
rawSocket.addEventListener("message", onMessage);
|
|
259
370
|
rawSocket.addEventListener("close", onClose);
|
|
260
371
|
this._cleanupWireListeners = () => {
|
|
372
|
+
// ConversationsSocket.close() synthesizes a 1000 close event, so a
|
|
373
|
+
// discarded socket would otherwise report a spurious normal closure.
|
|
374
|
+
for (const event of ["open", "message", "close", "error"]) {
|
|
375
|
+
inner.on(event, undefined);
|
|
376
|
+
}
|
|
261
377
|
rawSocket.removeEventListener("message", onMessage);
|
|
262
378
|
rawSocket.removeEventListener("close", onClose);
|
|
263
379
|
};
|
package/dist/esm/version.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.32.
|
|
1
|
+
export declare const SDK_VERSION = "0.32.14";
|
package/dist/esm/version.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = "0.32.
|
|
1
|
+
export const SDK_VERSION = "0.32.14";
|