@vinaverse/client 0.1.0-alpha.6 → 0.1.0-alpha.8

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.
Files changed (49) hide show
  1. package/README.md +69 -7
  2. package/dist/agent/index.cjs +526 -75
  3. package/dist/agent/index.cjs.map +1 -1
  4. package/dist/agent/index.d.cts +3 -3
  5. package/dist/agent/index.d.ts +3 -3
  6. package/dist/agent/index.js +2 -2
  7. package/dist/backend/index.cjs +268 -0
  8. package/dist/backend/index.cjs.map +1 -0
  9. package/dist/backend/index.d.cts +72 -0
  10. package/dist/backend/index.d.ts +72 -0
  11. package/dist/backend/index.js +250 -0
  12. package/dist/backend/index.js.map +1 -0
  13. package/dist/{chunk-ZWG2TMUL.js → chunk-46D3FSLU.js} +24 -2
  14. package/dist/chunk-46D3FSLU.js.map +1 -0
  15. package/dist/chunk-DI4DPUNA.js +843 -0
  16. package/dist/chunk-DI4DPUNA.js.map +1 -0
  17. package/dist/chunk-YNUHXJD6.js +9 -0
  18. package/dist/{chunk-VSJDVLCP.js.map → chunk-YNUHXJD6.js.map} +1 -1
  19. package/dist/contract-DmQs8amJ.d.cts +6 -0
  20. package/dist/contract-DmQs8amJ.d.ts +6 -0
  21. package/dist/conversation/index.cjs +24 -2
  22. package/dist/conversation/index.cjs.map +1 -1
  23. package/dist/conversation/index.d.cts +5 -5
  24. package/dist/conversation/index.d.ts +5 -5
  25. package/dist/conversation/index.js +3 -3
  26. package/dist/index.cjs +2 -2
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +2 -2
  29. package/dist/index.d.ts +2 -2
  30. package/dist/index.js +1 -1
  31. package/dist/{runtime-DLJbJkSr.d.ts → runtime-A4ovUdrc.d.cts} +147 -21
  32. package/dist/{runtime-CErMdYxJ.d.cts → runtime-B6_l8--U.d.ts} +147 -21
  33. package/dist/{session-8W3fRNeb.d.cts → session-CPz4pcPu.d.cts} +246 -7
  34. package/dist/{session-8W3fRNeb.d.ts → session-CPz4pcPu.d.ts} +246 -7
  35. package/dist/{store-C7FtS5AY.d.cts → store-BxiicOKG.d.cts} +32 -2
  36. package/dist/{store-DFk0ayh8.d.ts → store-DZka9T2-.d.ts} +32 -2
  37. package/dist/testing/index.cjs +38 -1
  38. package/dist/testing/index.cjs.map +1 -1
  39. package/dist/testing/index.d.cts +15 -4
  40. package/dist/testing/index.d.ts +15 -4
  41. package/dist/testing/index.js +40 -3
  42. package/dist/testing/index.js.map +1 -1
  43. package/package.json +41 -2
  44. package/dist/chunk-VSJDVLCP.js +0 -9
  45. package/dist/chunk-XPES5PZ3.js +0 -416
  46. package/dist/chunk-XPES5PZ3.js.map +0 -1
  47. package/dist/chunk-ZWG2TMUL.js.map +0 -1
  48. package/dist/contract-_NMdPjgN.d.cts +0 -6
  49. package/dist/contract-_NMdPjgN.d.ts +0 -6
@@ -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;
@@ -767,10 +827,10 @@ interface components {
767
827
  turns: number;
768
828
  handoff_ticket_ids?: string[];
769
829
  /**
770
- * @description Why the session ended. `server_restart` is reserved and never appears here: it never ends a session (`docs/realtime-protocol.md` §2).
830
+ * @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.
771
831
  * @enum {string}
772
832
  */
773
- end_reason?: "expired" | "revoked" | "limit_reached" | "idle" | "server_restart" | "user_left";
833
+ end_reason?: "expired" | "revoked" | "limit_reached" | "idle" | "server_restart" | "user_left" | "deleted";
774
834
  /** Format: date-time */
775
835
  created_at: string;
776
836
  /** Format: date-time */
@@ -1243,6 +1303,83 @@ interface components {
1243
1303
  /** Format: date-time */
1244
1304
  at: string;
1245
1305
  };
1306
+ ConversationPage: {
1307
+ data: components["schemas"]["ConversationSummary"][];
1308
+ next_cursor: string | null;
1309
+ };
1310
+ /** @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. */
1311
+ ConversationSummary: {
1312
+ id: components["schemas"]["ConversationId"];
1313
+ agent: string;
1314
+ experience_mode: components["schemas"]["ExperienceMode"];
1315
+ business_scope_id?: components["schemas"]["BusinessScopeId"];
1316
+ title: string;
1317
+ /**
1318
+ * @description `intent`: the last search intent (service and place); `date`: the day it started
1319
+ * @enum {string}
1320
+ */
1321
+ title_source: "intent" | "date";
1322
+ /** Format: date-time */
1323
+ started_at: string;
1324
+ /** Format: date-time */
1325
+ last_activity_at: string;
1326
+ /** @description the messages its timeline holds (cards not counted) */
1327
+ message_count: number;
1328
+ /**
1329
+ * @description `open`: a session can resume it; `ended`: it can only be read
1330
+ * @enum {string}
1331
+ */
1332
+ state: "open" | "ended";
1333
+ };
1334
+ TimelinePage: {
1335
+ data: components["schemas"]["TimelineItem"][];
1336
+ /** @description the next older page; null at the conversation's start */
1337
+ next_cursor: string | null;
1338
+ };
1339
+ /**
1340
+ * @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.
1341
+ * 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.
1342
+ */
1343
+ TimelineItem: {
1344
+ /** @constant */
1345
+ type: "message";
1346
+ id: string;
1347
+ /**
1348
+ * @description a client tolerates a role it does not know, as in `TranscriptItem`
1349
+ * @enum {string}
1350
+ */
1351
+ role: "person" | "assistant" | "staff";
1352
+ text: string;
1353
+ /** Format: date-time */
1354
+ at: string;
1355
+ /** @description absent on a `person` message sent without a `client_event_id` */
1356
+ event_id?: string;
1357
+ turn_id?: string;
1358
+ /** @description `assistant` only, present only when true: the reply stopped before it finished */
1359
+ interrupted?: boolean;
1360
+ /**
1361
+ * @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.
1362
+ * @constant
1363
+ */
1364
+ refusal?: true;
1365
+ } | {
1366
+ /** @constant */
1367
+ type: "card";
1368
+ id: string;
1369
+ turn_id: string;
1370
+ /** Format: date-time */
1371
+ at: string;
1372
+ card: components["schemas"]["Card"];
1373
+ /**
1374
+ * @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.
1375
+ * @enum {string}
1376
+ */
1377
+ proposal_outcome?: "pending" | "confirmed" | "declined" | "failed" | "expired";
1378
+ };
1379
+ ConversationDeleted: {
1380
+ conversation_id: components["schemas"]["ConversationId"];
1381
+ sessions_revoked: number;
1382
+ };
1246
1383
  /** @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. */
1247
1384
  SlotSelection: {
1248
1385
  id: string;
@@ -1539,10 +1676,10 @@ interface components {
1539
1676
  /** @constant */
1540
1677
  type: "session.closed";
1541
1678
  /**
1542
- * @description `replaced`: a newer session of the same conversation was created (close code `4409`)
1679
+ * @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.
1543
1680
  * @enum {string}
1544
1681
  */
1545
- reason: "expired" | "revoked" | "limit_reached" | "idle" | "server_restart" | "replaced";
1682
+ reason: "expired" | "revoked" | "limit_reached" | "idle" | "server_restart" | "replaced" | "deleted";
1546
1683
  } | {
1547
1684
  /** @constant */
1548
1685
  type: "ui.answer.recorded";
@@ -2121,6 +2258,8 @@ interface components {
2121
2258
  };
2122
2259
  parameters: {
2123
2260
  IdempotencyKey: string;
2261
+ /** @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`. */
2262
+ OptionalIdempotencyKey: string;
2124
2263
  MediaJobId: string;
2125
2264
  ConversationId: components["schemas"]["ConversationId"];
2126
2265
  SessionId: string;
@@ -2196,6 +2335,39 @@ interface operations {
2196
2335
  503: components["responses"]["Problem"];
2197
2336
  };
2198
2337
  };
2338
+ listConversations: {
2339
+ parameters: {
2340
+ query: {
2341
+ subject_id: components["schemas"]["SubjectId"];
2342
+ agent: string;
2343
+ /** @description the side of the app; left out, the agent's template's */
2344
+ experience_mode?: components["schemas"]["ExperienceMode"];
2345
+ /** @description the business the person acts for; only with `experience_mode=business` */
2346
+ business_scope_id?: components["schemas"]["BusinessScopeId"];
2347
+ limit?: number;
2348
+ cursor?: string;
2349
+ };
2350
+ header?: never;
2351
+ path?: never;
2352
+ cookie?: never;
2353
+ };
2354
+ requestBody?: never;
2355
+ responses: {
2356
+ /** @description Newest activity first. */
2357
+ 200: {
2358
+ headers: {
2359
+ [name: string]: unknown;
2360
+ };
2361
+ content: {
2362
+ "application/json": components["schemas"]["ConversationPage"];
2363
+ };
2364
+ };
2365
+ 400: components["responses"]["Problem"];
2366
+ 401: components["responses"]["Problem"];
2367
+ 403: components["responses"]["Problem"];
2368
+ 503: components["responses"]["Problem"];
2369
+ };
2370
+ };
2199
2371
  getConversation: {
2200
2372
  parameters: {
2201
2373
  query?: never;
@@ -2222,6 +2394,66 @@ interface operations {
2222
2394
  410: components["responses"]["Problem"];
2223
2395
  };
2224
2396
  };
2397
+ deleteConversation: {
2398
+ parameters: {
2399
+ query: {
2400
+ subject_id: components["schemas"]["SubjectId"];
2401
+ };
2402
+ header?: never;
2403
+ path: {
2404
+ conversation_id: components["parameters"]["ConversationId"];
2405
+ };
2406
+ cookie?: never;
2407
+ };
2408
+ requestBody?: never;
2409
+ responses: {
2410
+ /** @description Deleted. */
2411
+ 200: {
2412
+ headers: {
2413
+ [name: string]: unknown;
2414
+ };
2415
+ content: {
2416
+ "application/json": components["schemas"]["ConversationDeleted"];
2417
+ };
2418
+ };
2419
+ 401: components["responses"]["Problem"];
2420
+ 403: components["responses"]["Problem"];
2421
+ 404: components["responses"]["Problem"];
2422
+ 503: components["responses"]["Problem"];
2423
+ };
2424
+ };
2425
+ listConversationMessages: {
2426
+ parameters: {
2427
+ query: {
2428
+ subject_id: components["schemas"]["SubjectId"];
2429
+ limit?: number;
2430
+ cursor?: string;
2431
+ };
2432
+ header?: never;
2433
+ path: {
2434
+ conversation_id: components["parameters"]["ConversationId"];
2435
+ };
2436
+ cookie?: never;
2437
+ };
2438
+ requestBody?: never;
2439
+ responses: {
2440
+ /** @description The newest page first; oldest first within a page. */
2441
+ 200: {
2442
+ headers: {
2443
+ [name: string]: unknown;
2444
+ };
2445
+ content: {
2446
+ "application/json": components["schemas"]["TimelinePage"];
2447
+ };
2448
+ };
2449
+ 400: components["responses"]["Problem"];
2450
+ 401: components["responses"]["Problem"];
2451
+ 403: components["responses"]["Problem"];
2452
+ 404: components["responses"]["Problem"];
2453
+ 410: components["responses"]["Problem"];
2454
+ 503: components["responses"]["Problem"];
2455
+ };
2456
+ };
2225
2457
  getSession: {
2226
2458
  parameters: {
2227
2459
  query?: never;
@@ -2248,7 +2480,10 @@ interface operations {
2248
2480
  revokeSession: {
2249
2481
  parameters: {
2250
2482
  query?: never;
2251
- header?: never;
2483
+ header?: {
2484
+ /** @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`. */
2485
+ "Idempotency-Key"?: components["parameters"]["OptionalIdempotencyKey"];
2486
+ };
2252
2487
  path: {
2253
2488
  session_id: components["parameters"]["SessionId"];
2254
2489
  };
@@ -2266,12 +2501,16 @@ interface operations {
2266
2501
  };
2267
2502
  };
2268
2503
  404: components["responses"]["Problem"];
2504
+ 409: components["responses"]["Problem"];
2269
2505
  };
2270
2506
  };
2271
2507
  refreshClientSecret: {
2272
2508
  parameters: {
2273
2509
  query?: never;
2274
- header?: never;
2510
+ header?: {
2511
+ /** @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`. */
2512
+ "Idempotency-Key"?: components["parameters"]["OptionalIdempotencyKey"];
2513
+ };
2275
2514
  path: {
2276
2515
  session_id: components["parameters"]["SessionId"];
2277
2516
  };