@vinaverse/client 0.1.0-alpha.1 → 0.1.0-alpha.11

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 (55) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +127 -1
  3. package/dist/agent/index.cjs +3321 -0
  4. package/dist/agent/index.cjs.map +1 -0
  5. package/dist/agent/index.d.cts +57 -0
  6. package/dist/agent/index.d.ts +57 -0
  7. package/dist/agent/index.js +99 -0
  8. package/dist/agent/index.js.map +1 -0
  9. package/dist/backend/index.cjs +295 -0
  10. package/dist/backend/index.cjs.map +1 -0
  11. package/dist/backend/index.d.cts +82 -0
  12. package/dist/backend/index.d.ts +82 -0
  13. package/dist/backend/index.js +277 -0
  14. package/dist/backend/index.js.map +1 -0
  15. package/dist/chunk-46D3FSLU.js +997 -0
  16. package/dist/chunk-46D3FSLU.js.map +1 -0
  17. package/dist/chunk-D56MNG3E.js +9 -0
  18. package/dist/chunk-D56MNG3E.js.map +1 -0
  19. package/dist/{chunk-AWHPWRGT.js → chunk-GWLLUOFY.js} +71 -15
  20. package/dist/chunk-GWLLUOFY.js.map +1 -0
  21. package/dist/chunk-JI6HUXH3.js +861 -0
  22. package/dist/chunk-JI6HUXH3.js.map +1 -0
  23. package/dist/contract-Be2oVHNr.d.cts +6 -0
  24. package/dist/contract-Be2oVHNr.d.ts +6 -0
  25. package/dist/conversation/index.cjs +356 -27
  26. package/dist/conversation/index.cjs.map +1 -1
  27. package/dist/conversation/index.d.cts +23 -307
  28. package/dist/conversation/index.d.ts +23 -307
  29. package/dist/conversation/index.js +36 -760
  30. package/dist/conversation/index.js.map +1 -1
  31. package/dist/history/index.cjs +282 -0
  32. package/dist/history/index.cjs.map +1 -0
  33. package/dist/history/index.d.cts +91 -0
  34. package/dist/history/index.d.ts +91 -0
  35. package/dist/history/index.js +261 -0
  36. package/dist/history/index.js.map +1 -0
  37. package/dist/index.cjs +70 -8
  38. package/dist/index.cjs.map +1 -1
  39. package/dist/index.d.cts +2 -1
  40. package/dist/index.d.ts +2 -1
  41. package/dist/index.js +2 -1
  42. package/dist/runtime-6O0qIPmo.d.cts +394 -0
  43. package/dist/runtime-CNgz2_8G.d.ts +394 -0
  44. package/dist/{session--W6JXfwo.d.cts → session-D0ijOQX3.d.cts} +3330 -1614
  45. package/dist/{session--W6JXfwo.d.ts → session-D0ijOQX3.d.ts} +3330 -1614
  46. package/dist/store-CGRSxVcL.d.ts +414 -0
  47. package/dist/store-CxoHwd64.d.cts +414 -0
  48. package/dist/testing/index.cjs +418 -0
  49. package/dist/testing/index.cjs.map +1 -0
  50. package/dist/testing/index.d.cts +97 -0
  51. package/dist/testing/index.d.ts +97 -0
  52. package/dist/testing/index.js +403 -0
  53. package/dist/testing/index.js.map +1 -0
  54. package/package.json +105 -11
  55. package/dist/chunk-AWHPWRGT.js.map +0 -1
package/dist/index.d.cts CHANGED
@@ -1,4 +1,5 @@
1
- export { A as AnswerInput, h as AuthMode, b as CONTRACT, c as Card, d as CardKind, e as ClientErrorCode, j as ClientEvent, C as ClientSecret, k as Connection, l as ConversationEngine, m as ConversationState, F as FetchLike, n as Frame, H as HeldCard, f as HeldQuestion, M as Message, g as Proposal, P as ProposalOutcome, Q as Question, R as Reconnect, o as ServerEvent, p as ServerEventOf, q as ServerEventType, r as SessionEvents, S as SessionInfo, a as SessionOptions, s as SessionStatus, t as SseTarget, T as ToolLine, u as TranscriptItem, v as TurnInput, V as VinaverseClientError, w as VinaverseSession, W as WebSocketFactory, x as WebSocketLike, y as cardActionSse, i as isKnownCard, z as sseFrames, B as turnSse } from './session--W6JXfwo.cjs';
1
+ export { C as CONTRACT } from './contract-Be2oVHNr.cjs';
2
+ export { A as AnswerInput, h as AuthMode, a as Card, d as CardKind, e as ClientErrorCode, j as ClientEvent, k as ClientSecret, l as Connection, m as ConversationEngine, n as ConversationState, F as FetchLike, o as Frame, H as HeldCard, f as HeldQuestion, M as Message, P as Proposal, g as ProposalOutcome, Q as Question, R as Reconnect, S as Schemas, p as ServerEvent, q as ServerEventOf, r as ServerEventType, s as SessionEvents, t as SessionInfo, u as SessionOptions, v as SessionStatus, w as SseTarget, T as ToolLine, x as TranscriptItem, y as TurnInput, V as VinaverseClientError, z as VinaverseSession, B as WebSocketFactory, D as WebSocketLike, E as cardActionSse, G as components, i as isKnownCard, I as operations, J as paths, K as sseFrames, L as turnSse } from './session-D0ijOQX3.cjs';
2
3
 
3
4
  /**
4
5
  * The client secret, checked: an app holds only the session's `vv_cs_` secret, which the tenant's backend got from
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { A as AnswerInput, h as AuthMode, b as CONTRACT, c as Card, d as CardKind, e as ClientErrorCode, j as ClientEvent, C as ClientSecret, k as Connection, l as ConversationEngine, m as ConversationState, F as FetchLike, n as Frame, H as HeldCard, f as HeldQuestion, M as Message, g as Proposal, P as ProposalOutcome, Q as Question, R as Reconnect, o as ServerEvent, p as ServerEventOf, q as ServerEventType, r as SessionEvents, S as SessionInfo, a as SessionOptions, s as SessionStatus, t as SseTarget, T as ToolLine, u as TranscriptItem, v as TurnInput, V as VinaverseClientError, w as VinaverseSession, W as WebSocketFactory, x as WebSocketLike, y as cardActionSse, i as isKnownCard, z as sseFrames, B as turnSse } from './session--W6JXfwo.js';
1
+ export { C as CONTRACT } from './contract-Be2oVHNr.js';
2
+ export { A as AnswerInput, h as AuthMode, a as Card, d as CardKind, e as ClientErrorCode, j as ClientEvent, k as ClientSecret, l as Connection, m as ConversationEngine, n as ConversationState, F as FetchLike, o as Frame, H as HeldCard, f as HeldQuestion, M as Message, P as Proposal, g as ProposalOutcome, Q as Question, R as Reconnect, S as Schemas, p as ServerEvent, q as ServerEventOf, r as ServerEventType, s as SessionEvents, t as SessionInfo, u as SessionOptions, v as SessionStatus, w as SseTarget, T as ToolLine, x as TranscriptItem, y as TurnInput, V as VinaverseClientError, z as VinaverseSession, B as WebSocketFactory, D as WebSocketLike, E as cardActionSse, G as components, i as isKnownCard, I as operations, J as paths, K as sseFrames, L as turnSse } from './session-D0ijOQX3.js';
2
3
 
3
4
  /**
4
5
  * The client secret, checked: an app holds only the session's `vv_cs_` secret, which the tenant's backend got from
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
- export { CONTRACT, ConversationEngine, VinaverseClientError, VinaverseSession, cardActionSse, clientSecret, isKnownCard, sseFrames, turnSse } from './chunk-AWHPWRGT.js';
1
+ export { CONTRACT } from './chunk-D56MNG3E.js';
2
+ export { ConversationEngine, VinaverseClientError, VinaverseSession, cardActionSse, clientSecret, isKnownCard, sseFrames, turnSse } from './chunk-GWLLUOFY.js';
2
3
  //# sourceMappingURL=index.js.map
3
4
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,394 @@
1
+ import { S as SessionRequest, b as ConversationSession, C as ConversationStore, f as ConversationPersistence, a as ConversationOptions } from './store-CxoHwd64.cjs';
2
+ import { S as Schemas, k as ClientSecret } from './session-D0ijOQX3.cjs';
3
+
4
+ /** Whose conversation: a person (null for a guest), the app's side, the business acted for, and the thread. */
5
+ interface AgentKey {
6
+ readonly subject: string | null;
7
+ readonly mode: string;
8
+ readonly scope?: string | null;
9
+ /** Default `chat`; a flow of its own (a business setup, say) is another thread. */
10
+ readonly thread?: string;
11
+ }
12
+ type ScreenContext = Schemas['ScreenContext'];
13
+ /**
14
+ * Where the person asks from, in the contract's vocabulary (`ScreenContext`: the screen, the entity, the filters): told
15
+ * to the agent as data (`Session.screen_context`), never as their words. The tenant's backend vouches for it.
16
+ */
17
+ interface AgentPlace {
18
+ readonly screen: ScreenContext['screen'];
19
+ readonly entity?: {
20
+ readonly type: string;
21
+ readonly id: string;
22
+ } | null;
23
+ readonly filters?: ScreenContext['filters'];
24
+ }
25
+ /** How the person came in: the kit's parts say `launcher` and `ask`; an app adds `deep_link` or its own words. */
26
+ type AgentEntryPoint = 'launcher' | 'ask' | 'deep_link' | (string & Record<never, never>);
27
+ /** What the runtime asks the tenant's backend for: a session, for this key, told this place. */
28
+ interface AgentSessionRequest extends SessionRequest {
29
+ readonly key: AgentKey;
30
+ /**
31
+ * This session creation's id: the same through its retries, so the backend uses it as the gateway's idempotency key
32
+ * and never opens twice; a new one for every creation (a first open, a resume, continue-here, a rollover). A creation
33
+ * that could not reach the backend keeps it, and its whole request, for the next try, the person's "try again" too,
34
+ * for 24 hours. An `unknown_open` answer is final: not retried under it.
35
+ */
36
+ readonly openId: string;
37
+ /** The runtime's `agent`, for a backend that serves more than one. */
38
+ readonly agent: string | null;
39
+ readonly place: AgentPlace | null;
40
+ /**
41
+ * The place's revision (`ScreenContext.revision`): higher than any the session was told before, and lower than any
42
+ * `updateContext` after it, so the API keeps the newest place across a session's rollover.
43
+ */
44
+ readonly placeRevision: number;
45
+ /** How the person came in (`launcher`, `ask`, `deep_link`, the app's own words), passed through. */
46
+ readonly entryPoint: AgentEntryPoint | null;
47
+ }
48
+ /** Why there is no session, typed, so an app never needs sentinel errors of its own. */
49
+ type AgentFailureReason =
50
+ /** The conversation is over (its session's own end, or a refusal with no finer reason). */
51
+ 'ended'
52
+ /** The conversation asked for does not exist for this person (deleted, or never theirs). */
53
+ | 'not_found'
54
+ /** Past the time the conversation is kept. */
55
+ | 'expired'
56
+ /** The conversation belongs to another business, mode or agent than the key's. */
57
+ | 'mismatch'
58
+ /** The conversation's flow is completed; a new one starts when the person asks. */
59
+ | 'completed'
60
+ /** The person may not act for this business or conversation. */
61
+ | 'forbidden'
62
+ /** The server holds a newer screen context than the one told (an update, never a session). */
63
+ | 'conflict'
64
+ /** The backend could not tell whether the session opened: unavailable, never retried, its `openId` kept for support. */
65
+ | 'unknown_open'
66
+ /** The person's sign-in was refused by the tenant's API. */
67
+ | 'auth'
68
+ /** The agent is switched off for this tenant, mode or person. */
69
+ | 'off' | 'rate_limited'
70
+ /** No network, a timeout: retried, then said. */
71
+ | 'network'
72
+ /** The tenant's API or Vinaverse failed (5xx): retried, then said. */
73
+ | 'server'
74
+ /** The backend answered with a session the runtime will not use (not wss://, a field missing). */
75
+ | 'invalid_session' | 'unknown';
76
+ /**
77
+ * A refusal from the backend, typed: `ended` (the conversation is over; a new one starts only when the person asks) or
78
+ * `unavailable` with its reason. An error with `retryable: true` (and its `reason`, `network` by default) is waited out
79
+ * by the retry policy, then said as `unreachable`.
80
+ */
81
+ declare class AgentRefusal extends Error {
82
+ readonly kind: 'ended' | 'unavailable';
83
+ readonly reason: AgentFailureReason;
84
+ readonly code: string | null;
85
+ constructor(kind: 'ended' | 'unavailable', options?: {
86
+ readonly reason?: AgentFailureReason;
87
+ readonly code?: string;
88
+ readonly message?: string;
89
+ });
90
+ }
91
+ interface AgentStatus {
92
+ readonly available: boolean;
93
+ /** The floating launcher may show. */
94
+ readonly launcher: boolean;
95
+ readonly displayName: string | null;
96
+ readonly avatarUrl: string | null;
97
+ readonly features: {
98
+ readonly history: boolean;
99
+ readonly memory: boolean;
100
+ readonly businessAgent: boolean;
101
+ readonly businessSetup: boolean;
102
+ };
103
+ }
104
+ /** The status as the backend reads it; what it leaves out is off. */
105
+ interface AgentStatusRead {
106
+ readonly available: boolean;
107
+ readonly launcher?: boolean;
108
+ readonly displayName?: string | null;
109
+ readonly avatarUrl?: string | null;
110
+ readonly features?: Partial<AgentStatus['features']>;
111
+ }
112
+ /** The status and where its read stands, so a screen tells "reading" from "could not read". */
113
+ interface AgentStatusState {
114
+ readonly status: AgentStatus | null;
115
+ readonly reading: boolean;
116
+ readonly failed: boolean;
117
+ }
118
+ /** The tenant's backend: the one piece of integration an app writes. */
119
+ interface AgentBackend {
120
+ /** A session from the tenant's API (it creates it at Vinaverse with its service key), or an `AgentRefusal`. */
121
+ openSession(request: AgentSessionRequest): Promise<ConversationSession>;
122
+ /**
123
+ * A fresh client secret for the same session (before its end): a `ClientSecret` `{ value, expires_at }`, or its
124
+ * value. A refusal (`session_closed`: the session is over) goes on with the conversation in a new session.
125
+ */
126
+ refreshSecret?(sessionId: string): Promise<ClientSecret | string>;
127
+ /**
128
+ * The person's place changed while the chat is open: the tenant's backend tells Vinaverse
129
+ * (`PUT /v1/sessions/{id}/context`). A place cleared (`tell({ place: null })`) comes as `{ screen: 'other' }`.
130
+ * `revision` only grows for a conversation, across its sessions. A conflict (`decodeBackendFailure`'s
131
+ * `context_conflict`, or a refusal with reason `conflict`, with the server's `currentRevision`) is sent once more
132
+ * above it, then said as `moved`. Absent, or refused otherwise, the kit offers a question about the new place.
133
+ */
134
+ updateContext?(sessionId: string, place: AgentPlace, revision: number): Promise<void>;
135
+ /** Whether the agent is offered, and what it can do. Absent: available, nothing extra. */
136
+ status?(signal?: AbortSignal): Promise<AgentStatusRead>;
137
+ /** A thumbs on a whole reply; best effort, never an error for the person. */
138
+ sendFeedback?(feedback: {
139
+ readonly sessionId: string;
140
+ readonly turnId: string;
141
+ readonly rating: AgentRating;
142
+ }): Promise<void>;
143
+ /** Sign-out: end the person's open sessions at the tenant's API. */
144
+ endSessions?(): Promise<void>;
145
+ /** History's delete: the tenant's API deletes the person's conversation (authenticated, theirs only). */
146
+ deleteConversation?(conversationId: string): Promise<void>;
147
+ /**
148
+ * History: the person's past conversations with the agent, newest activity first, a page at a time (`cursor` from
149
+ * the page before). The person comes from the backend's authentication, never from here.
150
+ */
151
+ listConversations?(query: {
152
+ readonly mode: string;
153
+ readonly scope: string | null;
154
+ readonly agent: string | null;
155
+ readonly limit?: number;
156
+ readonly cursor: string | null;
157
+ }, signal?: AbortSignal): Promise<Schemas['ConversationPage']>;
158
+ /** History: a past conversation's messages and cards, the newest page first, oldest first within a page. */
159
+ readConversation?(conversationId: string, page: {
160
+ readonly limit?: number;
161
+ readonly cursor: string | null;
162
+ }, signal?: AbortSignal): Promise<Schemas['TimelinePage']>;
163
+ }
164
+ type AgentRating = 'up' | 'down';
165
+ type AgentFailure = 'ended' | 'unreachable' | 'unavailable';
166
+ type AgentEventType = 'session_opened' | 'session_resumed' | 'session_retried' | 'session_failed' | 'conversation_ended' | 'context_updated' | 'rated' | 'chip_tapped' | 'card_action' | 'target_opened' | 'link_opened' | 'launcher_shown' | 'launcher_opened' | 'launcher_greeted' | 'greeting_closed' | 'message_sent' | 'reply_completed' | 'card_shown';
167
+ /** For the app's analytics: what happened, for which conversation, with nothing the person said. */
168
+ interface AgentEvent {
169
+ readonly type: AgentEventType;
170
+ /** The conversation, as a hash of its key (`hashKey`): stable, and never the person's id. */
171
+ readonly key?: string;
172
+ readonly sessionId?: string;
173
+ readonly failure?: AgentFailure;
174
+ readonly reason?: AgentFailureReason;
175
+ readonly attempt?: number;
176
+ readonly turnId?: string;
177
+ readonly rating?: AgentRating;
178
+ readonly cardId?: string;
179
+ readonly kind?: string;
180
+ /** Where the person opened from (`launcher`, `ask`, `deep_link`, the app's own words). */
181
+ readonly from?: AgentEntryPoint;
182
+ }
183
+ /** What a UI draws around the store: why there is no session, whether the person moved, the thumbs given. */
184
+ interface AgentConversationState {
185
+ readonly failure: AgentFailure | null;
186
+ readonly reason: AgentFailureReason | null;
187
+ /** The API's own code for the failure (`conversation_expired`, …), when it gave one. */
188
+ readonly code: string | null;
189
+ /** The session was told another place than the one the person now asks from, and it could not be told live. */
190
+ readonly moved: boolean;
191
+ readonly ratings: ReadonlyMap<string, AgentRating>;
192
+ readonly sessionId: string | null;
193
+ /**
194
+ * The conversation the key holds: the one it continues before a session opens, then its session's. Null for a new
195
+ * one not yet opened. History's delete compares against it (`deleteConversation` does).
196
+ */
197
+ readonly conversationId: string | null;
198
+ /** The open the backend could not settle (`unknown_open`), for support; null otherwise. */
199
+ readonly openId: string | null;
200
+ }
201
+ interface AgentConversation {
202
+ /** The key as a string, for the app's own maps and the events. */
203
+ readonly key: string;
204
+ readonly store: ConversationStore;
205
+ /**
206
+ * A view attaches: kept, with its connection, while any view is attached. The first time, it starts. Returns the
207
+ * detach: with no view attached it is suspended (no pings; closed with `closeInBackground`) while its session lives
208
+ * (`keepAlive: 'session'`), and let go when it has none, is past its end, or `keepAlive` is `'view'`. Separate from the
209
+ * app's background, which the platform adapter tells the store.
210
+ */
211
+ show(open?: {
212
+ readonly place?: AgentPlace | null;
213
+ readonly entryPoint?: AgentEntryPoint | null;
214
+ }): () => void;
215
+ /**
216
+ * The place and the way in changed while a view is attached: told live where the backend can, else on the next
217
+ * session. `undefined` keeps what was told; `null` clears it.
218
+ */
219
+ tell(open: {
220
+ readonly place?: AgentPlace | null;
221
+ readonly entryPoint?: AgentEntryPoint | null;
222
+ }): void;
223
+ getState(): AgentConversationState;
224
+ subscribe(listener: () => void): () => void;
225
+ /** Asks for a session again, after the backend could not be reached. */
226
+ retry(): void;
227
+ /**
228
+ * Whether a reply can be rated: one this runtime saw given live. A reply restored from the device or a resumed
229
+ * transcript cannot be, until the API rates a turn by its conversation; the kits draw no thumbs for it.
230
+ */
231
+ canRate(turnId: string): boolean;
232
+ /** A thumbs on a whole reply, against the session it was given in; a change of mind only is sent again. */
233
+ rate(turnId: string, rating: AgentRating): void;
234
+ /**
235
+ * Sends the person's `text` once in this conversation's life (a chip tapped twice, a retried tap). It is shown as
236
+ * theirs: only words they typed or tapped, never the app's in their name.
237
+ */
238
+ sendOnce(text: string): void;
239
+ }
240
+ /** When the runtime tries the backend again: before each try, a delay; `isRetryable` decides which errors are waited out. */
241
+ interface AgentRetryPolicy {
242
+ readonly delays: readonly number[];
243
+ readonly isRetryable?: (error: unknown) => boolean;
244
+ }
245
+ /** The time the runtime judges a session's end by: the server's, when the app has it (a clock synced from responses). */
246
+ interface AgentClock {
247
+ now(): number;
248
+ }
249
+ interface AgentRuntimeOptions {
250
+ readonly backend: AgentBackend;
251
+ /**
252
+ * The agent this runtime talks to (its id at Vinaverse). It is part of every key, so two agents sharing the device's
253
+ * storage (`conversation.persistence`) never share a conversation. Default: none (one agent per storage namespace).
254
+ */
255
+ readonly agent?: string;
256
+ /** The store's own options (locale, time zone, deep-link prefixes, transport, persistence, closeInBackground…). */
257
+ readonly conversation?: Omit<ConversationOptions, 'getSession' | 'refreshSecret' | 'clock'>;
258
+ /** Default: 500, 1500, 3500 ms, for errors with `retryable: true`; applied to `openSession` and `refreshSecret`. */
259
+ readonly retry?: AgentRetryPolicy;
260
+ /** Default: the device's clock. Give the server's: a phone set wrong otherwise reuses a dead session or drops a live one. */
261
+ readonly clock?: AgentClock;
262
+ /** `session` (default): kept while its session lives with no view attached; `view`: let go when the last view goes. */
263
+ readonly keepAlive?: 'session' | 'view';
264
+ /** How long a status read stays fresh. Default 5 minutes. */
265
+ readonly statusStaleMs?: number;
266
+ /**
267
+ * DANGEROUS: for mocks and local development only. Lets a leg's session address be plaintext (`ws://`, `http://`),
268
+ * which would carry the person's messages and the session's secret unencrypted. Off by default, whatever transport
269
+ * the app supplies; outside `__DEV__` the runtime warns once.
270
+ */
271
+ readonly insecureAddresses?: AgentInsecureAddresses;
272
+ readonly onEvent?: (event: AgentEvent) => void;
273
+ /**
274
+ * Where the launcher remembers it greeted a person (the app's preferences store). Given here, the launcher reads and
275
+ * writes it through the runtime (`greetings`), a sign-out fences it, and `erase()` removes it.
276
+ */
277
+ readonly greetingStorage?: ConversationPersistence;
278
+ /**
279
+ * Keys an earlier version of the app or the kit wrote that no index lists, for a storage with neither `keys` nor
280
+ * `removePrefix`: removed by every sign-out from `conversation.persistence`, and by `erase()` from `greetingStorage`
281
+ * too. The migration that makes their removal certain on such a storage.
282
+ */
283
+ readonly legacyKeys?: readonly string[];
284
+ /** Where the runtime's warnings go (the app's logger, crash reporter); default `console.warn`. */
285
+ readonly onWarning?: (message: string, warning: AgentWarning) => void;
286
+ }
287
+ /**
288
+ * What a warning is about, for an app's logger to count without reading the message: `insecure_addresses` (a leg let
289
+ * off the wss:// and https:// check outside development), `callback_threw` (the app's `onEvent` or `onActivity` threw;
290
+ * `callback` names it), `events_dropped` (the oldest analytics events, while the salt is read).
291
+ */
292
+ interface AgentWarning {
293
+ readonly code: 'insecure_addresses' | 'callback_threw' | 'events_dropped';
294
+ readonly callback?: 'onEvent' | 'onActivity';
295
+ }
296
+ /** The legs whose session address may be plaintext: `realtime` (the WebSocket), `turns` (HTTP). */
297
+ interface AgentInsecureAddresses {
298
+ readonly realtime?: boolean;
299
+ readonly turns?: boolean;
300
+ }
301
+ interface AgentRuntime {
302
+ /** The app's backend, as given: history (`@vinaverse/client/history`) reads its pages through it. */
303
+ readonly backend: AgentBackend;
304
+ /** The key's conversation: the same while it lives; a new one after `startNew`, `dispose` or its end. */
305
+ conversation(key: AgentKey): AgentConversation;
306
+ /**
307
+ * The key's conversation as it stands, ending nothing and telling no one: for a render (`useSyncExternalStore`).
308
+ * One past its session's end is ended when it is next shown, and subscribers then read the key's next one.
309
+ */
310
+ peek(key: AgentKey): AgentConversation;
311
+ /** A new conversation for the key from the person's next opening; the old one is let go and forgotten. */
312
+ startNew(key: AgentKey): void;
313
+ /**
314
+ * Closes the key's conversation now; the next opening continues it in a new session. What the device kept of it and
315
+ * the conversation it continues stay: `forget` removes them.
316
+ */
317
+ dispose(key: AgentKey): void;
318
+ /**
319
+ * Closes the key's conversation and forgets it on this device: the conversation it continued and the transcript kept
320
+ * by `persistence`. History's "delete" calls it after the tenant's backend deleted the conversation.
321
+ */
322
+ forget(key: AgentKey): void;
323
+ /** Ends every conversation no view shows that is past its session's end. The kits call it when the app comes back. */
324
+ sweep(): void;
325
+ /**
326
+ * History's delete: the backend deletes the conversation, then the device forgets it, only where the key still
327
+ * continues that conversation (an older history entry never forgets the key's newer one).
328
+ */
329
+ deleteConversation(key: AgentKey, conversationId: string): Promise<void>;
330
+ /**
331
+ * The person's erasure on this device: a sign-out, plus the launcher's greeting records (`greetingStorage`) and the
332
+ * analytics salt, every key this version and alpha.5 or alpha.6 wrote. Keys no index lists (an earlier version's, a
333
+ * write lost with its process) are found only when the storage has `keys` or `removePrefix`.
334
+ */
335
+ erase(): Promise<void>;
336
+ /** The launcher's greeting storage, under the sign-out fence; null without `greetingStorage`. */
337
+ readonly greetings: ConversationPersistence | null;
338
+ /**
339
+ * The key goes on with this conversation (history's "Continue"): pinned for the key and opened through the backend's
340
+ * resume. One that is gone (404, 410: the backend's `AgentRefusal('ended')`) is said as `ended`, never replaced by a
341
+ * new one silently.
342
+ */
343
+ continue(key: AgentKey, conversationId: string): AgentConversation;
344
+ /**
345
+ * Every conversation closed and forgotten, and everything this runtime kept on the device (every transcript it ever
346
+ * wrote under `conversation.persistenceKey`, even of conversations already closed), the status and the name; then
347
+ * the backend is told to end the sessions at the same time. A late answer from before (a session, a status, a write)
348
+ * changes nothing. Kept on purpose: the launcher's greeting records and the analytics salt (`erase` takes them).
349
+ */
350
+ signOut(): Promise<void>;
351
+ /** The agent's status, read from the backend at most every `statusStaleMs`. */
352
+ status(): Promise<AgentStatus>;
353
+ getStatus(): AgentStatus | null;
354
+ /**
355
+ * The status with where its read stands: `reading` while one is out, `failed` when the last one could not be read
356
+ * (the status held before, if any, stays). One object until it changes, for `useSyncExternalStore`.
357
+ */
358
+ getStatusState(): AgentStatusState;
359
+ /**
360
+ * Which person's turn it is on this device: a number that changes at every sign-out and erasure. Work begun under an
361
+ * older one (a history page, a transcript) is dropped when it lands.
362
+ */
363
+ epoch(): number;
364
+ /** The agent's name: from the newest session, else from the status. */
365
+ getName(): string | null;
366
+ /** Told when the status or name changes, and when a key's conversation is let go (its next one is another). */
367
+ subscribe(listener: () => void): () => void;
368
+ /** An event from a kit or the app, passed to `onEvent`. */
369
+ emit(event: AgentEvent): void;
370
+ }
371
+ /**
372
+ * Where the launcher remembers that it greeted a person in a mode, the key its storage sees. Encoded so a guest
373
+ * (`null`) is never a person whose id is "guest".
374
+ */
375
+ declare function greetedKey(subject: string | null, mode: string): string;
376
+ /**
377
+ * A conversation's key as analytics sees it: SHA-256 of the install's salt and the key, 128 bits in hex. Stable per
378
+ * install (the runtime keeps the salt in the app's storage until `erase()`), never the person's id, and not
379
+ * recomputable from a guessed id without the salt.
380
+ */
381
+ declare function hashKey(key: string, salt: string): string;
382
+ /**
383
+ * The key as a string: one conversation per agent, person, mode, business and thread. Encoded as a JSON array, so no
384
+ * value can pass for another (a guest is `null`, never a subject named "guest"; a `|` in an id is just a character).
385
+ */
386
+ declare function agentKey(key: AgentKey, agent?: string | null): string;
387
+ declare function createAgentRuntime(options: AgentRuntimeOptions): AgentRuntime;
388
+ /**
389
+ * An `AgentRefusal`, also one made by another copy of this package (the mock in `@vinaverse/client/testing`, the
390
+ * backend helpers in `@vinaverse/client/backend`, a second install): recognised by its name and kind, not its class.
391
+ */
392
+ declare function isRefusal(error: unknown): error is AgentRefusal;
393
+
394
+ export { type AgentBackend as A, type AgentClock as a, type AgentConversation as b, type AgentConversationState as c, type AgentEntryPoint as d, type AgentEvent as e, type AgentEventType as f, type AgentFailure as g, type AgentFailureReason as h, type AgentInsecureAddresses as i, type AgentKey as j, type AgentPlace as k, type AgentRating as l, AgentRefusal as m, type AgentRetryPolicy as n, type AgentRuntime as o, type AgentRuntimeOptions as p, type AgentSessionRequest as q, type AgentStatus as r, type AgentStatusRead as s, type AgentStatusState as t, type AgentWarning as u, agentKey as v, createAgentRuntime as w, greetedKey as x, hashKey as y, isRefusal as z };