@vinaverse/server 0.1.0-alpha.7 → 0.1.0-alpha.9
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 +4 -0
- package/dist/api.cjs +18 -0
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +18 -3
- package/dist/api.d.ts +18 -3
- package/dist/api.js +18 -0
- package/dist/api.js.map +1 -1
- package/dist/express.d.cts +2 -2
- package/dist/express.d.ts +2 -2
- package/dist/fastify.d.cts +2 -2
- package/dist/fastify.d.ts +2 -2
- package/dist/hono.d.cts +2 -2
- package/dist/hono.d.ts +2 -2
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/lambda.d.cts +2 -2
- package/dist/lambda.d.ts +2 -2
- package/dist/{provider-DBKNrV8Z.d.ts → provider-CbLgJEXQ.d.ts} +1 -1
- package/dist/{provider-fCKVIR_Y.d.cts → provider-ytczljc-.d.cts} +1 -1
- package/dist/{vinaverse-v1.d-DGSY4GsY.d.cts → vinaverse-v1.d-DT7a1T80.d.cts} +246 -7
- package/dist/{vinaverse-v1.d-DGSY4GsY.d.ts → vinaverse-v1.d-DT7a1T80.d.ts} +246 -7
- package/package.json +1 -1
|
@@ -73,6 +73,30 @@ interface paths {
|
|
|
73
73
|
patch?: never;
|
|
74
74
|
trace?: never;
|
|
75
75
|
};
|
|
76
|
+
"/v1/conversations": {
|
|
77
|
+
parameters: {
|
|
78
|
+
query?: never;
|
|
79
|
+
header?: never;
|
|
80
|
+
path?: never;
|
|
81
|
+
cookie?: never;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* A person's past conversations with one agent, newest activity first
|
|
85
|
+
* @description v1-draft.21 (VIN-246): the conversations a history screen lists, for one subject and one agent, on one side of the app (`experience_mode`, and for a business `business_scope_id`, as the conversation was bound when it started). Newest activity first; ties by `id`.
|
|
86
|
+
* **Access.** A service key only, never a client secret: the app asks the tenant's backend, which checks the person and calls this. The key needs `conversations:read` (a key without scopes has every scope) and sees its own tenant and environment only.
|
|
87
|
+
* **What is listed.** Only what the tenant's `transcript_retention` still keeps: a conversation past it, a deleted one (`deleteConversation`) or an erased subject's is never listed, nor one where nothing was said (a session opened and left). A subject Vinaverse holds nothing for gets an empty page, the same as one with no conversations, so the answer never says whether a subject exists.
|
|
88
|
+
* **The title** is deterministic and never the person's words: from the conversation's last search intent (`title_source: intent`, for example "Haircut · Los Angeles", in the subject's locale), else the date it started (`title_source: date`). There is no preview of the messages.
|
|
89
|
+
* **Paging.** `next_cursor` is opaque and signed. It is bound to the filters, the key's tenant and environment, and expires after 24 hours: a cursor changed, used with other filters or expired is `400 invalid_request` at `/cursor`, and the caller starts again without it. An outage is `503 unavailable` (retryable), never an empty page: the app does not take it as "no conversations".
|
|
90
|
+
*/
|
|
91
|
+
get: operations["listConversations"];
|
|
92
|
+
put?: never;
|
|
93
|
+
post?: never;
|
|
94
|
+
delete?: never;
|
|
95
|
+
options?: never;
|
|
96
|
+
head?: never;
|
|
97
|
+
patch?: never;
|
|
98
|
+
trace?: never;
|
|
99
|
+
};
|
|
76
100
|
"/v1/conversations/{conversation_id}": {
|
|
77
101
|
parameters: {
|
|
78
102
|
query?: never;
|
|
@@ -95,6 +119,42 @@ interface paths {
|
|
|
95
119
|
get: operations["getConversation"];
|
|
96
120
|
put?: never;
|
|
97
121
|
post?: never;
|
|
122
|
+
/**
|
|
123
|
+
* Delete one of a person's conversations, everywhere
|
|
124
|
+
* @description v1-draft.21 (VIN-246): the person deletes a conversation from their history, through the tenant's backend. A service key with `conversations:write`, for its own tenant and environment; `subject_id` must be the conversation's subject.
|
|
125
|
+
* **What it does, before it answers.** - Ends the conversation's open sessions: their sockets get `session.closed` with `reason: deleted` and
|
|
126
|
+
* close with `4403` (a client that does not know `deleted` reads it as `revoked`). Their status ends as
|
|
127
|
+
* `deleted`.
|
|
128
|
+
* - Blanks every copy of the conversation's messages, cards, screening texts and state (and the guided flow's
|
|
129
|
+
* answers), across both sides of the app, and leaves no title or count behind.
|
|
130
|
+
* - Fences late writes: a turn still running, a webhook retry or a worker job that finishes after the delete
|
|
131
|
+
* records nothing for it (a deletion barrier, kept as long as the longest session could run).
|
|
132
|
+
* - Frees its `conversation_key`: a session with the same key afterwards starts a new conversation.
|
|
133
|
+
* **Answers.** `200` with the number of sessions revoked. An unknown id, another tenant's, environment's or subject's, or one already deleted or erased: `404 not_found`, the same answer for each, so it never says whether the conversation exists. Deleting is not erasing the subject (`eraseSubject`): the person's other conversations and memory stay.
|
|
134
|
+
*/
|
|
135
|
+
delete: operations["deleteConversation"];
|
|
136
|
+
options?: never;
|
|
137
|
+
head?: never;
|
|
138
|
+
patch?: never;
|
|
139
|
+
trace?: never;
|
|
140
|
+
};
|
|
141
|
+
"/v1/conversations/{conversation_id}/messages": {
|
|
142
|
+
parameters: {
|
|
143
|
+
query?: never;
|
|
144
|
+
header?: never;
|
|
145
|
+
path?: never;
|
|
146
|
+
cookie?: never;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* One past conversation, as one ordered timeline of messages and cards
|
|
150
|
+
* @description v1-draft.21 (VIN-246): what a history screen draws when the person opens a past conversation. A service key with `conversations:read`, for its own tenant and environment; `subject_id` must be the conversation's subject.
|
|
151
|
+
* **The timeline.** One list of messages and the cards their turns drew, in the order they happened, each with an `id` that is stable and unique within the conversation. The first page is the newest; within a page, oldest first; `next_cursor` pages toward older items. A message carries `event_id`, the identifier its live event gave it (as `TranscriptItem.id`: an `assistant` message's `turn_id`, a `person` message's `client_event_id`, a `staff` message's `message_id`), so an app merges what it drew live, or a resumed `session.ready.transcript`, into the fetched history by `role` and `event_id` instead of replacing either. An input the runtime never recorded is not in it, as in the transcript.
|
|
152
|
+
* **Cards from history are read-only.** An app draws their actions disabled: a past slot, price or availability is not checked again, so a tap would act on stale data. The person asks again in the conversation, and a fresh turn draws fresh cards.
|
|
153
|
+
* **What is kept.** Only what the tenant's `transcript_retention` still keeps; a conversation past it is `410 conversation_expired`. An unknown id, another tenant's, environment's or subject's, or a deleted or erased one: `404 not_found`, the same answer for each. A cursor changed, used for another conversation or expired (24 hours) is `400 invalid_request` at `/cursor`. An outage is `503 unavailable`, never an empty timeline.
|
|
154
|
+
*/
|
|
155
|
+
get: operations["listConversationMessages"];
|
|
156
|
+
put?: never;
|
|
157
|
+
post?: never;
|
|
98
158
|
delete?: never;
|
|
99
159
|
options?: never;
|
|
100
160
|
head?: never;
|
|
@@ -144,7 +204,7 @@ interface paths {
|
|
|
144
204
|
put?: never;
|
|
145
205
|
/**
|
|
146
206
|
* A fresh client secret for an open session
|
|
147
|
-
* @description A service key with the `sessions:write` scope gets a new connect secret for an open session, for an app that missed the connect window or connects from another device (whose connection then replaces the open one, with close code 4409). The previous secret no longer authenticates a new connection or an SSE turn. A socket already open stays open and keeps its session: refreshing never drops the person's live connection. To cut it off, revoke the session (`revokeSession`). An ended session is `409 session_closed`.
|
|
207
|
+
* @description A service key with the `sessions:write` scope gets a new connect secret for an open session, for an app that missed the connect window or connects from another device (whose connection then replaces the open one, with close code 4409). The previous secret no longer authenticates a new connection or an SSE turn. A socket already open stays open and keeps its session: refreshing never drops the person's live connection. To cut it off, revoke the session (`revokeSession`). An ended session is `409 session_closed`. With an optional `Idempotency-Key` (declared in v1-draft.22), a retry within 24 hours answers the secret first issued for that key instead of a newer one.
|
|
148
208
|
*/
|
|
149
209
|
post: operations["refreshClientSecret"];
|
|
150
210
|
delete?: never;
|
|
@@ -1484,10 +1544,10 @@ interface components {
|
|
|
1484
1544
|
turns: number;
|
|
1485
1545
|
handoff_ticket_ids?: string[];
|
|
1486
1546
|
/**
|
|
1487
|
-
* @description Why the session ended. `server_restart` is reserved and never appears here: it never ends a session (`docs/realtime-protocol.md` §2).
|
|
1547
|
+
* @description Why the session ended. `server_restart` is reserved and never appears here: it never ends a session (`docs/realtime-protocol.md` §2). `deleted` (v1-draft.21): its conversation was deleted from history.
|
|
1488
1548
|
* @enum {string}
|
|
1489
1549
|
*/
|
|
1490
|
-
end_reason?: "expired" | "revoked" | "limit_reached" | "idle" | "server_restart" | "user_left";
|
|
1550
|
+
end_reason?: "expired" | "revoked" | "limit_reached" | "idle" | "server_restart" | "user_left" | "deleted";
|
|
1491
1551
|
/** Format: date-time */
|
|
1492
1552
|
created_at: string;
|
|
1493
1553
|
/** Format: date-time */
|
|
@@ -1960,6 +2020,83 @@ interface components {
|
|
|
1960
2020
|
/** Format: date-time */
|
|
1961
2021
|
at: string;
|
|
1962
2022
|
};
|
|
2023
|
+
ConversationPage: {
|
|
2024
|
+
data: components["schemas"]["ConversationSummary"][];
|
|
2025
|
+
next_cursor: string | null;
|
|
2026
|
+
};
|
|
2027
|
+
/** @description v1-draft.21: one past conversation as a history screen lists it. No message text: the title is from the conversation's last search intent or its date, never the person's words. */
|
|
2028
|
+
ConversationSummary: {
|
|
2029
|
+
id: components["schemas"]["ConversationId"];
|
|
2030
|
+
agent: string;
|
|
2031
|
+
experience_mode: components["schemas"]["ExperienceMode"];
|
|
2032
|
+
business_scope_id?: components["schemas"]["BusinessScopeId"];
|
|
2033
|
+
title: string;
|
|
2034
|
+
/**
|
|
2035
|
+
* @description `intent`: the last search intent (service and place); `date`: the day it started
|
|
2036
|
+
* @enum {string}
|
|
2037
|
+
*/
|
|
2038
|
+
title_source: "intent" | "date";
|
|
2039
|
+
/** Format: date-time */
|
|
2040
|
+
started_at: string;
|
|
2041
|
+
/** Format: date-time */
|
|
2042
|
+
last_activity_at: string;
|
|
2043
|
+
/** @description the messages its timeline holds (cards not counted) */
|
|
2044
|
+
message_count: number;
|
|
2045
|
+
/**
|
|
2046
|
+
* @description `open`: a session can resume it; `ended`: it can only be read
|
|
2047
|
+
* @enum {string}
|
|
2048
|
+
*/
|
|
2049
|
+
state: "open" | "ended";
|
|
2050
|
+
};
|
|
2051
|
+
TimelinePage: {
|
|
2052
|
+
data: components["schemas"]["TimelineItem"][];
|
|
2053
|
+
/** @description the next older page; null at the conversation's start */
|
|
2054
|
+
next_cursor: string | null;
|
|
2055
|
+
};
|
|
2056
|
+
/**
|
|
2057
|
+
* @description v1-draft.21: one item of a past conversation, a message or a card its turn drew. `id` is stable and unique within the conversation; a message's `event_id` is its live event's identifier (`TranscriptItem.id`), the key an app merges live and resumed messages by, with `role`. A card is read-only in history.
|
|
2058
|
+
* Unlike `session.ready.transcript`, the history holds a guardrail's refusals: the person's message a guardrail refused and the fixed line said instead of an answer both carry `refusal: true`, so the app draws them as it drew them live (muted, never offered again). A `proposal` card carries `proposal_outcome`, what became of it.
|
|
2059
|
+
*/
|
|
2060
|
+
TimelineItem: {
|
|
2061
|
+
/** @constant */
|
|
2062
|
+
type: "message";
|
|
2063
|
+
id: string;
|
|
2064
|
+
/**
|
|
2065
|
+
* @description a client tolerates a role it does not know, as in `TranscriptItem`
|
|
2066
|
+
* @enum {string}
|
|
2067
|
+
*/
|
|
2068
|
+
role: "person" | "assistant" | "staff";
|
|
2069
|
+
text: string;
|
|
2070
|
+
/** Format: date-time */
|
|
2071
|
+
at: string;
|
|
2072
|
+
/** @description absent on a `person` message sent without a `client_event_id` */
|
|
2073
|
+
event_id?: string;
|
|
2074
|
+
turn_id?: string;
|
|
2075
|
+
/** @description `assistant` only, present only when true: the reply stopped before it finished */
|
|
2076
|
+
interrupted?: boolean;
|
|
2077
|
+
/**
|
|
2078
|
+
* @description Present only when true: a guardrail refused this turn. On a `person` message, the text it refused (as recorded, card-like digits masked); on an `assistant` message, the fixed line said instead of an answer.
|
|
2079
|
+
* @constant
|
|
2080
|
+
*/
|
|
2081
|
+
refusal?: true;
|
|
2082
|
+
} | {
|
|
2083
|
+
/** @constant */
|
|
2084
|
+
type: "card";
|
|
2085
|
+
id: string;
|
|
2086
|
+
turn_id: string;
|
|
2087
|
+
/** Format: date-time */
|
|
2088
|
+
at: string;
|
|
2089
|
+
card: components["schemas"]["Card"];
|
|
2090
|
+
/**
|
|
2091
|
+
* @description A `proposal` card only, always present on one: the outcome the app reported for it (`ui.action` `confirmed`, `declined`, `failed` or `expired`), or `pending` while none was reported. Draw it as settled; a past proposal is never confirmed from history.
|
|
2092
|
+
* @enum {string}
|
|
2093
|
+
*/
|
|
2094
|
+
proposal_outcome?: "pending" | "confirmed" | "declined" | "failed" | "expired";
|
|
2095
|
+
};
|
|
2096
|
+
ConversationDeleted: {
|
|
2097
|
+
conversation_id: components["schemas"]["ConversationId"];
|
|
2098
|
+
sessions_revoked: number;
|
|
2099
|
+
};
|
|
1963
2100
|
/** @description A time slot the person picked on a `time_slots` card (v1-draft.17, `docs/realtime-protocol.md` §6): the slot's `id`, and the `call_id` of the tool call the card came from (the card's `source.call_id`), so the runtime checks the pick against the evidence it holds for that call. Both are copied from the card; never built by the app. */
|
|
1964
2101
|
SlotSelection: {
|
|
1965
2102
|
id: string;
|
|
@@ -2256,10 +2393,10 @@ interface components {
|
|
|
2256
2393
|
/** @constant */
|
|
2257
2394
|
type: "session.closed";
|
|
2258
2395
|
/**
|
|
2259
|
-
* @description `replaced`: a newer session of the same conversation was created (close code `4409`)
|
|
2396
|
+
* @description `replaced`: a newer session of the same conversation was created (close code `4409`). `deleted` (v1-draft.21): the person deleted the conversation from their history (`deleteConversation`, close code `4403`); drop it from the app's store and never resume it. A client that does not know `deleted` reads it as `revoked`, as any unknown reason.
|
|
2260
2397
|
* @enum {string}
|
|
2261
2398
|
*/
|
|
2262
|
-
reason: "expired" | "revoked" | "limit_reached" | "idle" | "server_restart" | "replaced";
|
|
2399
|
+
reason: "expired" | "revoked" | "limit_reached" | "idle" | "server_restart" | "replaced" | "deleted";
|
|
2263
2400
|
} | {
|
|
2264
2401
|
/** @constant */
|
|
2265
2402
|
type: "ui.answer.recorded";
|
|
@@ -2838,6 +2975,8 @@ interface components {
|
|
|
2838
2975
|
};
|
|
2839
2976
|
parameters: {
|
|
2840
2977
|
IdempotencyKey: string;
|
|
2978
|
+
/** @description Accepted, not required (declared in v1-draft.22). Scoped to the tenant and environment: the same key and request within 24 hours answers the first success again (`Idempotent-Replayed: true`); the same key with another request is `409 idempotency_conflict`. */
|
|
2979
|
+
OptionalIdempotencyKey: string;
|
|
2841
2980
|
MediaJobId: string;
|
|
2842
2981
|
ConversationId: components["schemas"]["ConversationId"];
|
|
2843
2982
|
SessionId: string;
|
|
@@ -2913,6 +3052,39 @@ interface operations {
|
|
|
2913
3052
|
503: components["responses"]["Problem"];
|
|
2914
3053
|
};
|
|
2915
3054
|
};
|
|
3055
|
+
listConversations: {
|
|
3056
|
+
parameters: {
|
|
3057
|
+
query: {
|
|
3058
|
+
subject_id: components["schemas"]["SubjectId"];
|
|
3059
|
+
agent: string;
|
|
3060
|
+
/** @description the side of the app; left out, the agent's template's */
|
|
3061
|
+
experience_mode?: components["schemas"]["ExperienceMode"];
|
|
3062
|
+
/** @description the business the person acts for; only with `experience_mode=business` */
|
|
3063
|
+
business_scope_id?: components["schemas"]["BusinessScopeId"];
|
|
3064
|
+
limit?: number;
|
|
3065
|
+
cursor?: string;
|
|
3066
|
+
};
|
|
3067
|
+
header?: never;
|
|
3068
|
+
path?: never;
|
|
3069
|
+
cookie?: never;
|
|
3070
|
+
};
|
|
3071
|
+
requestBody?: never;
|
|
3072
|
+
responses: {
|
|
3073
|
+
/** @description Newest activity first. */
|
|
3074
|
+
200: {
|
|
3075
|
+
headers: {
|
|
3076
|
+
[name: string]: unknown;
|
|
3077
|
+
};
|
|
3078
|
+
content: {
|
|
3079
|
+
"application/json": components["schemas"]["ConversationPage"];
|
|
3080
|
+
};
|
|
3081
|
+
};
|
|
3082
|
+
400: components["responses"]["Problem"];
|
|
3083
|
+
401: components["responses"]["Problem"];
|
|
3084
|
+
403: components["responses"]["Problem"];
|
|
3085
|
+
503: components["responses"]["Problem"];
|
|
3086
|
+
};
|
|
3087
|
+
};
|
|
2916
3088
|
getConversation: {
|
|
2917
3089
|
parameters: {
|
|
2918
3090
|
query?: never;
|
|
@@ -2939,6 +3111,66 @@ interface operations {
|
|
|
2939
3111
|
410: components["responses"]["Problem"];
|
|
2940
3112
|
};
|
|
2941
3113
|
};
|
|
3114
|
+
deleteConversation: {
|
|
3115
|
+
parameters: {
|
|
3116
|
+
query: {
|
|
3117
|
+
subject_id: components["schemas"]["SubjectId"];
|
|
3118
|
+
};
|
|
3119
|
+
header?: never;
|
|
3120
|
+
path: {
|
|
3121
|
+
conversation_id: components["parameters"]["ConversationId"];
|
|
3122
|
+
};
|
|
3123
|
+
cookie?: never;
|
|
3124
|
+
};
|
|
3125
|
+
requestBody?: never;
|
|
3126
|
+
responses: {
|
|
3127
|
+
/** @description Deleted. */
|
|
3128
|
+
200: {
|
|
3129
|
+
headers: {
|
|
3130
|
+
[name: string]: unknown;
|
|
3131
|
+
};
|
|
3132
|
+
content: {
|
|
3133
|
+
"application/json": components["schemas"]["ConversationDeleted"];
|
|
3134
|
+
};
|
|
3135
|
+
};
|
|
3136
|
+
401: components["responses"]["Problem"];
|
|
3137
|
+
403: components["responses"]["Problem"];
|
|
3138
|
+
404: components["responses"]["Problem"];
|
|
3139
|
+
503: components["responses"]["Problem"];
|
|
3140
|
+
};
|
|
3141
|
+
};
|
|
3142
|
+
listConversationMessages: {
|
|
3143
|
+
parameters: {
|
|
3144
|
+
query: {
|
|
3145
|
+
subject_id: components["schemas"]["SubjectId"];
|
|
3146
|
+
limit?: number;
|
|
3147
|
+
cursor?: string;
|
|
3148
|
+
};
|
|
3149
|
+
header?: never;
|
|
3150
|
+
path: {
|
|
3151
|
+
conversation_id: components["parameters"]["ConversationId"];
|
|
3152
|
+
};
|
|
3153
|
+
cookie?: never;
|
|
3154
|
+
};
|
|
3155
|
+
requestBody?: never;
|
|
3156
|
+
responses: {
|
|
3157
|
+
/** @description The newest page first; oldest first within a page. */
|
|
3158
|
+
200: {
|
|
3159
|
+
headers: {
|
|
3160
|
+
[name: string]: unknown;
|
|
3161
|
+
};
|
|
3162
|
+
content: {
|
|
3163
|
+
"application/json": components["schemas"]["TimelinePage"];
|
|
3164
|
+
};
|
|
3165
|
+
};
|
|
3166
|
+
400: components["responses"]["Problem"];
|
|
3167
|
+
401: components["responses"]["Problem"];
|
|
3168
|
+
403: components["responses"]["Problem"];
|
|
3169
|
+
404: components["responses"]["Problem"];
|
|
3170
|
+
410: components["responses"]["Problem"];
|
|
3171
|
+
503: components["responses"]["Problem"];
|
|
3172
|
+
};
|
|
3173
|
+
};
|
|
2942
3174
|
getSession: {
|
|
2943
3175
|
parameters: {
|
|
2944
3176
|
query?: never;
|
|
@@ -2965,7 +3197,10 @@ interface operations {
|
|
|
2965
3197
|
revokeSession: {
|
|
2966
3198
|
parameters: {
|
|
2967
3199
|
query?: never;
|
|
2968
|
-
header?:
|
|
3200
|
+
header?: {
|
|
3201
|
+
/** @description Accepted, not required (declared in v1-draft.22). Scoped to the tenant and environment: the same key and request within 24 hours answers the first success again (`Idempotent-Replayed: true`); the same key with another request is `409 idempotency_conflict`. */
|
|
3202
|
+
"Idempotency-Key"?: components["parameters"]["OptionalIdempotencyKey"];
|
|
3203
|
+
};
|
|
2969
3204
|
path: {
|
|
2970
3205
|
session_id: components["parameters"]["SessionId"];
|
|
2971
3206
|
};
|
|
@@ -2983,12 +3218,16 @@ interface operations {
|
|
|
2983
3218
|
};
|
|
2984
3219
|
};
|
|
2985
3220
|
404: components["responses"]["Problem"];
|
|
3221
|
+
409: components["responses"]["Problem"];
|
|
2986
3222
|
};
|
|
2987
3223
|
};
|
|
2988
3224
|
refreshClientSecret: {
|
|
2989
3225
|
parameters: {
|
|
2990
3226
|
query?: never;
|
|
2991
|
-
header?:
|
|
3227
|
+
header?: {
|
|
3228
|
+
/** @description Accepted, not required (declared in v1-draft.22). Scoped to the tenant and environment: the same key and request within 24 hours answers the first success again (`Idempotent-Replayed: true`); the same key with another request is `409 idempotency_conflict`. */
|
|
3229
|
+
"Idempotency-Key"?: components["parameters"]["OptionalIdempotencyKey"];
|
|
3230
|
+
};
|
|
2992
3231
|
path: {
|
|
2993
3232
|
session_id: components["parameters"]["SessionId"];
|
|
2994
3233
|
};
|