@vinaverse/client 0.1.0-alpha.10 → 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 (51) hide show
  1. package/README.md +19 -3
  2. package/dist/agent/index.cjs +2 -0
  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 +1 -1
  7. package/dist/backend/index.cjs +37 -10
  8. package/dist/backend/index.cjs.map +1 -1
  9. package/dist/backend/index.d.cts +13 -3
  10. package/dist/backend/index.d.ts +13 -3
  11. package/dist/backend/index.js +38 -11
  12. package/dist/backend/index.js.map +1 -1
  13. package/dist/chunk-D56MNG3E.js +9 -0
  14. package/dist/{chunk-YNUHXJD6.js.map → chunk-D56MNG3E.js.map} +1 -1
  15. package/dist/{chunk-O3NLAZGZ.js → chunk-JI6HUXH3.js} +4 -2
  16. package/dist/chunk-JI6HUXH3.js.map +1 -0
  17. package/dist/contract-Be2oVHNr.d.cts +6 -0
  18. package/dist/contract-Be2oVHNr.d.ts +6 -0
  19. package/dist/conversation/index.cjs +2 -2
  20. package/dist/conversation/index.cjs.map +1 -1
  21. package/dist/conversation/index.d.cts +5 -5
  22. package/dist/conversation/index.d.ts +5 -5
  23. package/dist/conversation/index.js +1 -1
  24. package/dist/history/index.cjs +282 -0
  25. package/dist/history/index.cjs.map +1 -0
  26. package/dist/history/index.d.cts +91 -0
  27. package/dist/history/index.d.ts +91 -0
  28. package/dist/history/index.js +261 -0
  29. package/dist/history/index.js.map +1 -0
  30. package/dist/index.cjs +2 -2
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +2 -2
  33. package/dist/index.d.ts +2 -2
  34. package/dist/index.js +1 -1
  35. package/dist/{runtime-Z1RI10lU.d.ts → runtime-6O0qIPmo.d.cts} +25 -2
  36. package/dist/{runtime-CISPp9nJ.d.cts → runtime-CNgz2_8G.d.ts} +25 -2
  37. package/dist/{session-CPz4pcPu.d.cts → session-D0ijOQX3.d.cts} +98 -5
  38. package/dist/{session-CPz4pcPu.d.ts → session-D0ijOQX3.d.ts} +98 -5
  39. package/dist/{store-DZka9T2-.d.ts → store-CGRSxVcL.d.ts} +1 -1
  40. package/dist/{store-BxiicOKG.d.cts → store-CxoHwd64.d.cts} +1 -1
  41. package/dist/testing/index.cjs +158 -14
  42. package/dist/testing/index.cjs.map +1 -1
  43. package/dist/testing/index.d.cts +42 -5
  44. package/dist/testing/index.d.ts +42 -5
  45. package/dist/testing/index.js +159 -15
  46. package/dist/testing/index.js.map +1 -1
  47. package/package.json +24 -1
  48. package/dist/chunk-O3NLAZGZ.js.map +0 -1
  49. package/dist/chunk-YNUHXJD6.js +0 -9
  50. package/dist/contract-DmQs8amJ.d.cts +0 -6
  51. package/dist/contract-DmQs8amJ.d.ts +0 -6
@@ -1,37 +1,115 @@
1
- import { AgentRefusal } from '../chunk-O3NLAZGZ.js';
1
+ import { AgentRefusal } from '../chunk-JI6HUXH3.js';
2
2
  import '../chunk-46D3FSLU.js';
3
3
  import '../chunk-GWLLUOFY.js';
4
4
 
5
5
  // src/testing/index.ts
6
+ var CURSOR = /^mock:(\d+)$/;
7
+ var refusal = (kind, reason) => Object.assign(
8
+ new AgentRefusal(kind, {
9
+ reason,
10
+ code: reason === "not_found" ? "conversation_not_found" : "unavailable"
11
+ }),
12
+ { retryable: false }
13
+ );
6
14
  var sentences = (text) => text.match(/[^.!?]+[.!?]*\s*/g) ?? [text];
7
15
  function createMockAgent(options = {}) {
8
16
  const now = options.now ?? (() => Date.now());
17
+ const at = () => new Date(now()).toISOString();
9
18
  const conversations = /* @__PURE__ */ new Map();
10
19
  const sessions = /* @__PURE__ */ new Map();
11
20
  const log = {
12
21
  sessions: [],
13
22
  feedback: [],
14
23
  contexts: [],
15
- ended: 0
24
+ ended: 0,
25
+ lists: [],
26
+ reads: [],
27
+ deleted: []
16
28
  };
17
29
  let attempts = 0;
18
30
  let count = 0;
31
+ for (const c of options.history ?? []) {
32
+ const started = c.startedAt ?? at();
33
+ const items = c.items.map((item, n) => {
34
+ const id = `h_${c.id}_${n + 1}`;
35
+ const turn = `turn_${c.id}_${n + 1}`;
36
+ if ("card" in item)
37
+ return {
38
+ type: "card",
39
+ id,
40
+ turn_id: turn,
41
+ at: item.at ?? started,
42
+ card: item.card,
43
+ ...item.card.kind === "proposal" ? { proposal_outcome: item.proposal_outcome ?? "pending" } : {}
44
+ };
45
+ return {
46
+ type: "message",
47
+ id,
48
+ role: item.role,
49
+ text: item.text,
50
+ at: item.at ?? started,
51
+ event_id: id,
52
+ turn_id: turn,
53
+ ...item.interrupted ? { interrupted: true } : {},
54
+ ...item.refusal ? { refusal: true } : {}
55
+ };
56
+ });
57
+ conversations.set(c.id, {
58
+ id: c.id,
59
+ mode: c.mode ?? "customer",
60
+ scope: c.scope ?? null,
61
+ agent: c.agent ?? "mock_agent",
62
+ title: c.title ?? null,
63
+ started_at: started,
64
+ state: c.state ?? "ended",
65
+ items
66
+ });
67
+ }
68
+ const lastActivity = (held) => held.items.at(-1)?.at ?? held.started_at;
69
+ const summaryOf = (held) => ({
70
+ id: held.id,
71
+ agent: held.agent,
72
+ experience_mode: held.mode,
73
+ ...held.scope === null ? {} : { business_scope_id: held.scope },
74
+ title: held.title ?? held.started_at.slice(0, 10),
75
+ title_source: held.title ? "intent" : "date",
76
+ started_at: held.started_at,
77
+ last_activity_at: lastActivity(held),
78
+ message_count: held.items.filter((i) => i.type === "message").length,
79
+ state: held.state
80
+ });
81
+ const offsetOf = (cursor) => {
82
+ if (cursor === null) return 0;
83
+ const m = CURSOR.exec(cursor);
84
+ if (!m) throw refusal("unavailable", "server");
85
+ return Number(m[1]);
86
+ };
19
87
  const backend = {
20
88
  async openSession(request) {
21
89
  log.sessions.push(request);
22
90
  attempts++;
23
- const refusal = options.refuse?.(request, attempts);
24
- if (refusal === "unreachable")
91
+ const refusal2 = options.refuse?.(request, attempts);
92
+ if (refusal2 === "unreachable")
25
93
  throw Object.assign(new Error("mock: unreachable"), {
26
94
  retryable: true,
27
95
  reason: "network"
28
96
  });
29
- if (refusal) throw new AgentRefusal(refusal);
97
+ if (refusal2) throw new AgentRefusal(refusal2);
30
98
  if (request.conversationId !== null && !conversations.has(request.conversationId))
31
99
  throw new AgentRefusal("ended", { code: "conversation_not_found" });
32
100
  count++;
33
101
  const conversation = request.conversationId ?? `cnv_MOCK${count}`;
34
- if (!conversations.has(conversation)) conversations.set(conversation, []);
102
+ if (!conversations.has(conversation))
103
+ conversations.set(conversation, {
104
+ id: conversation,
105
+ mode: request.key.mode,
106
+ scope: request.key.scope ?? null,
107
+ agent: request.agent ?? "mock_agent",
108
+ title: null,
109
+ started_at: at(),
110
+ state: "open",
111
+ items: []
112
+ });
35
113
  const id = `ses_MOCK${count}`;
36
114
  sessions.set(id, { conversation, key: `${request.key.mode}` });
37
115
  const session = {
@@ -67,13 +145,50 @@ function createMockAgent(options = {}) {
67
145
  },
68
146
  async endSessions() {
69
147
  log.ended++;
148
+ },
149
+ async listConversations(query) {
150
+ log.lists.push(query);
151
+ const from = offsetOf(query.cursor);
152
+ const limit = query.limit ?? 20;
153
+ const all = [...conversations.values()].filter(
154
+ (c) => c.mode === query.mode && c.scope === (query.scope ?? null) && (query.agent === null || c.agent === query.agent) && c.items.some((i) => i.type === "message")
155
+ ).map(summaryOf).sort(
156
+ (a, b) => b.last_activity_at.localeCompare(a.last_activity_at) || b.id.localeCompare(a.id)
157
+ );
158
+ const data = all.slice(from, from + limit);
159
+ return {
160
+ data,
161
+ next_cursor: from + limit < all.length ? `mock:${from + limit}` : null
162
+ };
163
+ },
164
+ async readConversation(conversationId, page) {
165
+ log.reads.push({ conversationId, ...page });
166
+ const held = conversations.get(conversationId);
167
+ if (!held) throw refusal("ended", "not_found");
168
+ const limit = page.limit ?? 30;
169
+ const end = page.cursor === null ? held.items.length : offsetOf(page.cursor);
170
+ const start = Math.max(0, end - limit);
171
+ return {
172
+ data: held.items.slice(start, end),
173
+ next_cursor: start > 0 ? `mock:${start}` : null
174
+ };
175
+ },
176
+ async deleteConversation(conversationId) {
177
+ log.deleted.push(conversationId);
178
+ if (!conversations.delete(conversationId))
179
+ throw refusal("ended", "not_found");
180
+ for (const [id, s] of sessions)
181
+ if (s.conversation === conversationId) sessions.delete(id);
70
182
  }
71
183
  };
72
184
  const webSocket = (url) => {
73
185
  const sessionId = /sessions\/([^/]+)\/realtime/.exec(url)?.[1] ?? "";
74
186
  const held = sessions.get(sessionId);
75
- const said = held ? conversations.get(held.conversation) ?? [] : [];
76
- let turn = said.filter((s) => s.role === "person").length;
187
+ const items = held ? conversations.get(held.conversation)?.items ?? [] : [];
188
+ const said = () => items.filter(
189
+ (i) => i.type === "message"
190
+ );
191
+ let turn = said().filter((s) => s.role === "person").length;
77
192
  let state = 0;
78
193
  const socket = {
79
194
  get readyState() {
@@ -91,7 +206,15 @@ function createMockAgent(options = {}) {
91
206
  const text = String(frame.text ?? "");
92
207
  turn++;
93
208
  const turnId = `turn_MOCK${turn}`;
94
- said.push({ role: "person", text, id });
209
+ items.push({
210
+ type: "message",
211
+ id: `p_${turnId}`,
212
+ role: "person",
213
+ text,
214
+ at: at(),
215
+ event_id: id,
216
+ turn_id: turnId
217
+ });
95
218
  const answer = options.script?.[turn - 1] ?? options.reply?.(text, { turn, key: held?.key ?? "" }) ?? `You said: ${text}`;
96
219
  const reply = typeof answer === "string" ? { text: answer } : answer;
97
220
  deliver({ type: "turn.started", turn_id: turnId, client_event_id: id });
@@ -116,10 +239,28 @@ function createMockAgent(options = {}) {
116
239
  turn_id: turnId,
117
240
  text: so.trim()
118
241
  });
119
- said.push({ role: "assistant", text: so.trim(), id: turnId });
242
+ items.push({
243
+ type: "message",
244
+ id: `a_${turnId}`,
245
+ role: "assistant",
246
+ text: so.trim(),
247
+ at: at(),
248
+ event_id: turnId,
249
+ turn_id: turnId
250
+ });
120
251
  }
121
- if (reply.cards?.length)
252
+ if (reply.cards?.length) {
122
253
  deliver({ type: "ui.cards", turn_id: turnId, cards: reply.cards });
254
+ for (const card of reply.cards)
255
+ items.push({
256
+ type: "card",
257
+ id: card.id,
258
+ turn_id: turnId,
259
+ at: at(),
260
+ card,
261
+ ...card.kind === "proposal" ? { proposal_outcome: "pending" } : {}
262
+ });
263
+ }
123
264
  deliver({ type: "turn.completed", turn_id: turnId });
124
265
  },
125
266
  close(code) {
@@ -136,7 +277,8 @@ function createMockAgent(options = {}) {
136
277
  setTimeout(() => {
137
278
  state = 1;
138
279
  socket.onopen?.({});
139
- const resumed = said.length > 0;
280
+ const transcript = said();
281
+ const resumed = transcript.length > 0;
140
282
  socket.onmessage?.({
141
283
  data: JSON.stringify({
142
284
  type: "session.ready",
@@ -145,11 +287,13 @@ function createMockAgent(options = {}) {
145
287
  limits: {},
146
288
  disclosure: options.disclosure ?? "An AI agent. Powered by Vinaverse.",
147
289
  ...resumed ? {
148
- transcript: said.map((s) => ({
290
+ transcript: transcript.map((s) => ({
149
291
  role: s.role,
150
292
  text: s.text,
151
- id: s.id,
152
- at: new Date(now()).toISOString()
293
+ id: s.event_id,
294
+ at: s.at,
295
+ ...s.turn_id ? { turn_id: s.turn_id } : {},
296
+ ...s.interrupted ? { interrupted: true } : {}
153
297
  }))
154
298
  } : {}
155
299
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/testing/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// @vinaverse/client/testing: a scripted agent for an app's mock mode and tests, with no tenant and no network. It is an\n// `AgentBackend` (sessions, fresh secrets, status, feedback) and a WebSocket factory that speaks the realtime protocol:\n// session.ready (resumed with the conversation's transcript), replies streamed sentence by sentence, cards, a turn that\n// fails, refusals when opening (ended, unreachable, unavailable). The app scripts only its own answers.\nimport type {\n AgentBackend,\n AgentSessionRequest,\n AgentStatusRead,\n} from '../agent/runtime.js';\nimport { AgentRefusal } from '../agent/runtime.js';\nimport type { ConversationSession } from '../conversation/store.js';\nimport type { Card, Welcome } from '../events.js';\nimport type { WebSocketFactory, WebSocketLike } from '../session.js';\n\n/** One reply of the scripted agent. */\nexport interface MockReply {\n readonly text?: string;\n readonly cards?: readonly Card[];\n /** The turn fails before any text, with this code (`internal`, `timeout`, …). */\n readonly fail?: string;\n}\n\nexport interface MockAgentOptions {\n /** Replies in order, one per turn (text, cards, a failure), after which `reply` (or the echo) answers. */\n readonly script?: readonly (MockReply | string)[];\n /** The agent's answer to the person's text. Default: the `script`, then an echo. */\n readonly reply?: (\n text: string,\n context: { readonly turn: number; readonly key: string },\n ) => MockReply | string;\n readonly agentName?: string;\n readonly disclosure?: string;\n readonly welcome?: Welcome;\n /** A refusal when opening a session (the scripted backend's answer), by request. */\n readonly refuse?: (\n request: AgentSessionRequest,\n attempt: number,\n ) => 'ended' | 'unreachable' | 'unavailable' | undefined;\n /** How long a session lives. Default 30 minutes. */\n readonly sessionMs?: number;\n readonly status?: AgentStatusRead;\n /** The clock sessions are dated by; default the device's. */\n readonly now?: () => number;\n}\n\nexport interface MockAgent {\n readonly backend: AgentBackend;\n /** The store's transport: `conversation.transport.webSocket`. */\n readonly webSocket: WebSocketFactory;\n /** What the app sent: feedback, sessions asked for, places told. */\n readonly log: {\n readonly sessions: AgentSessionRequest[];\n readonly feedback: unknown[];\n readonly contexts: unknown[];\n readonly ended: number;\n };\n}\n\ninterface Said {\n readonly role: 'person' | 'assistant';\n readonly text: string;\n readonly id: string;\n}\n\nconst sentences = (text: string) => text.match(/[^.!?]+[.!?]*\\s*/g) ?? [text];\n\nexport function createMockAgent(options: MockAgentOptions = {}): MockAgent {\n const now = options.now ?? (() => Date.now());\n const conversations = new Map<string, Said[]>();\n const sessions = new Map<string, { conversation: string; key: string }>();\n const log = {\n sessions: [] as AgentSessionRequest[],\n feedback: [] as unknown[],\n contexts: [] as unknown[],\n ended: 0,\n };\n let attempts = 0;\n let count = 0;\n\n const backend: AgentBackend = {\n async openSession(request) {\n log.sessions.push(request);\n attempts++;\n const refusal = options.refuse?.(request, attempts);\n if (refusal === 'unreachable')\n throw Object.assign(new Error('mock: unreachable'), {\n retryable: true,\n reason: 'network',\n });\n if (refusal) throw new AgentRefusal(refusal);\n if (\n request.conversationId !== null &&\n !conversations.has(request.conversationId)\n )\n throw new AgentRefusal('ended', { code: 'conversation_not_found' });\n count++;\n const conversation = request.conversationId ?? `cnv_MOCK${count}`;\n if (!conversations.has(conversation)) conversations.set(conversation, []);\n const id = `ses_MOCK${count}`;\n sessions.set(id, { conversation, key: `${request.key.mode}` });\n const session: ConversationSession = {\n id,\n realtime_url: `wss://mock.vinaverse.invalid/v1/sessions/${id}/realtime`,\n turns_url: `https://mock.vinaverse.invalid/v1/sessions/${id}/turns`,\n client_secret: `vv_cs_${'mock'.repeat(6)}`,\n conversation_id: conversation,\n expires_at: new Date(\n now() + (options.sessionMs ?? 30 * 60_000),\n ).toISOString(),\n ...(options.agentName\n ? { agent: { display_name: options.agentName } }\n : {}),\n ...(options.disclosure ? { disclosure: options.disclosure } : {}),\n ...(options.welcome ? { welcome: options.welcome } : {}),\n };\n return session;\n },\n async refreshSecret() {\n return `vv_cs_${'mock'.repeat(6)}`;\n },\n async updateContext(sessionId, place, revision) {\n log.contexts.push({ sessionId, place, revision });\n },\n async status() {\n return (\n options.status ?? {\n available: true,\n launcher: true,\n displayName: options.agentName ?? null,\n }\n );\n },\n async sendFeedback(feedback) {\n log.feedback.push(feedback);\n },\n async endSessions() {\n log.ended++;\n },\n };\n\n const webSocket: WebSocketFactory = (url) => {\n const sessionId = /sessions\\/([^/]+)\\/realtime/.exec(url)?.[1] ?? '';\n const held = sessions.get(sessionId);\n const said = held ? (conversations.get(held.conversation) ?? []) : [];\n let turn = said.filter((s) => s.role === 'person').length;\n let state = 0;\n const socket: WebSocketLike = {\n get readyState() {\n return state;\n },\n onopen: null,\n onmessage: null,\n onclose: null,\n onerror: null,\n send(data) {\n const frame = JSON.parse(data) as Record<string, unknown>;\n if (frame.type === 'ping') return deliver({ type: 'pong' });\n if (frame.type !== 'input.text') return;\n const id = String(frame.client_event_id ?? '');\n const text = String(frame.text ?? '');\n turn++;\n const turnId = `turn_MOCK${turn}`;\n said.push({ role: 'person', text, id });\n const answer =\n options.script?.[turn - 1] ??\n options.reply?.(text, { turn, key: held?.key ?? '' }) ??\n `You said: ${text}`;\n const reply: MockReply =\n typeof answer === 'string' ? { text: answer } : answer;\n deliver({ type: 'turn.started', turn_id: turnId, client_event_id: id });\n if (reply.fail) {\n deliver({\n type: 'turn.failed',\n turn_id: turnId,\n code: reply.fail,\n message: '',\n retryable: true,\n });\n return;\n }\n let so = '';\n for (const part of reply.text ? sentences(reply.text) : []) {\n so += part;\n deliver({ type: 'message.delta', turn_id: turnId, text: part });\n }\n if (reply.text) {\n deliver({\n type: 'message.completed',\n turn_id: turnId,\n text: so.trim(),\n });\n said.push({ role: 'assistant', text: so.trim(), id: turnId });\n }\n if (reply.cards?.length)\n deliver({ type: 'ui.cards', turn_id: turnId, cards: reply.cards });\n deliver({ type: 'turn.completed', turn_id: turnId });\n },\n close(code) {\n if (state === 3) return;\n state = 3;\n setTimeout(() => socket.onclose?.({ code: code ?? 1000 }), 0);\n },\n };\n function deliver(event: unknown) {\n setTimeout(() => {\n if (state === 1) socket.onmessage?.({ data: JSON.stringify(event) });\n }, 0);\n }\n setTimeout(() => {\n state = 1;\n socket.onopen?.({});\n const resumed = said.length > 0;\n socket.onmessage?.({\n data: JSON.stringify({\n type: 'session.ready',\n session: { id: sessionId, status: 'open' },\n resumed,\n limits: {},\n disclosure:\n options.disclosure ?? 'An AI agent. Powered by Vinaverse.',\n ...(resumed\n ? {\n transcript: said.map((s) => ({\n role: s.role,\n text: s.text,\n id: s.id,\n at: new Date(now()).toISOString(),\n })),\n }\n : {}),\n }),\n });\n }, 0);\n return socket;\n };\n\n return { backend, webSocket, log };\n}\n\n/** Cards as a tenant's tools would give them, for mock replies and tests. */\nexport const mockCards = {\n professional(id: string, extra: Partial<Card> = {}): Card {\n return {\n id,\n kind: 'professional',\n title: 'Riley Sample',\n subtitle: 'Barber · Los Angeles',\n ref: { type: 'professional', id },\n images: [\n {\n url: `https://images.example.test/${id}.webp`,\n width: 1600,\n height: 1000,\n },\n ],\n rating: { value_ppm: 4_800_000, count: 132 },\n price_from: { amount: 4500, currency: 'USD' },\n actions: [],\n source: { tool: 'search_professionals', call_id: 'call_MOCK' },\n ...extra,\n } as Card;\n },\n workspace(id: string, extra: Partial<Card> = {}): Card {\n return {\n id,\n kind: 'workspace',\n title: 'Suite 4',\n subtitle: 'Private suite · Atlanta',\n ref: { type: 'workspace', id },\n price_from: { amount: 6500, currency: 'USD' },\n actions: [],\n source: { tool: 'search_spaces', call_id: 'call_MOCK' },\n ...extra,\n } as Card;\n },\n /** A proposal the person confirms in the app (`confirm_mode: tenant_app`), pending for a day unless `expires_at`. */\n proposal(\n id: string,\n proposal: {\n readonly topic?: string;\n readonly title?: string;\n readonly summary?: string;\n readonly expires_at?: string;\n } = {},\n ): Card {\n const title = proposal.title ?? 'Silk press with Riley';\n return {\n id,\n kind: 'proposal',\n title,\n actions: [],\n source: { tool: 'create_proposal', call_id: 'call_MOCK' },\n proposal: {\n id: `prp_${id}`,\n status: 'pending',\n topic: proposal.topic ?? 'booking',\n title,\n summary: proposal.summary ?? 'Wednesday at 10:00 · $45',\n fields: [],\n expires_at:\n proposal.expires_at ??\n new Date(Date.now() + 24 * 3_600_000).toISOString(),\n confirm_mode: 'tenant_app',\n },\n } as Card;\n },\n /** Times to book, from `start` on the hour, one an hour. */\n timeSlots(id: string, start: string, count = 3): Card {\n const at = Date.parse(start);\n return {\n id,\n kind: 'time_slots',\n title: 'Open times',\n slots: Array.from({ length: count }, (_, i) => ({\n id: `slot_${i + 1}`,\n start: new Date(at + i * 3_600_000).toISOString(),\n end: new Date(at + (i + 1) * 3_600_000).toISOString(),\n })),\n actions: [],\n source: { tool: 'get_availability', call_id: 'call_MOCK' },\n } as Card;\n },\n links(id: string): Card {\n return {\n id,\n kind: 'links',\n title: 'Pages that can help',\n links: [\n {\n label: 'Help center',\n url: 'https://help.example.test/',\n purpose: 'help',\n },\n {\n label: 'Contact us',\n url: 'https://help.example.test/contact',\n purpose: 'contact',\n },\n ],\n actions: [],\n source: { tool: 'scope', call_id: 'turn_MOCK' },\n } as Card;\n },\n};\n"]}
1
+ {"version":3,"sources":["../../src/testing/index.ts"],"names":["refusal"],"mappings":"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","file":"index.js","sourcesContent":["// @vinaverse/client/testing: a scripted agent for an app's mock mode and tests, with no tenant and no network. It is an\n// `AgentBackend` (sessions, fresh secrets, status, feedback, history) and a WebSocket factory that speaks the realtime\n// protocol: session.ready (resumed with the conversation's transcript), replies streamed sentence by sentence, cards, a\n// turn that fails, refusals when opening (ended, unreachable, unavailable). History as the contract serves it: the\n// conversations scripted (`history`) and the ones the person has here, listed a page at a time, read back with their\n// cards, refusals and proposal outcomes, deleted (then unknown: `not_found`). The app scripts only its own answers.\nimport type {\n AgentBackend,\n AgentSessionRequest,\n AgentStatusRead,\n} from '../agent/runtime.js';\nimport { AgentRefusal } from '../agent/runtime.js';\nimport type { ConversationSession } from '../conversation/store.js';\nimport type { Card, Schemas, Welcome } from '../events.js';\nimport type { WebSocketFactory, WebSocketLike } from '../session.js';\n\ntype HistoryItem = Schemas['TimelineItem'];\ntype Summary = Schemas['ConversationSummary'];\n\n/** A message of a scripted past conversation. */\nexport interface MockHistoryMessage {\n readonly role: 'person' | 'assistant' | 'staff';\n readonly text: string;\n /** A guardrail refused this turn (on the person's text, and on the fixed line said instead of an answer). */\n readonly refusal?: true;\n /** `assistant` only: the reply stopped before it finished. */\n readonly interrupted?: boolean;\n readonly at?: string;\n}\n/** A card a turn of a scripted past conversation drew; a proposal with what became of it. */\nexport interface MockHistoryCard {\n readonly card: Card;\n readonly proposal_outcome?:\n | 'pending'\n | 'confirmed'\n | 'declined'\n | 'failed'\n | 'expired';\n readonly at?: string;\n}\n/** A past conversation the mock serves in history (and resumes on \"Continue\" with its messages). */\nexport interface MockConversation {\n readonly id: string;\n /** Default: the day it started. */\n readonly title?: string;\n /** Default `customer`. */\n readonly mode?: string;\n readonly scope?: string | null;\n readonly agent?: string;\n readonly startedAt?: string;\n /** Default: the last item's `at`, else `startedAt`. */\n readonly lastActivityAt?: string;\n /** Default `ended`; `open` can be continued. */\n readonly state?: 'open' | 'ended';\n readonly items: readonly (MockHistoryMessage | MockHistoryCard)[];\n}\n\n/** One reply of the scripted agent. */\nexport interface MockReply {\n readonly text?: string;\n readonly cards?: readonly Card[];\n /** The turn fails before any text, with this code (`internal`, `timeout`, …). */\n readonly fail?: string;\n}\n\nexport interface MockAgentOptions {\n /** Replies in order, one per turn (text, cards, a failure), after which `reply` (or the echo) answers. */\n readonly script?: readonly (MockReply | string)[];\n /** The agent's answer to the person's text. Default: the `script`, then an echo. */\n readonly reply?: (\n text: string,\n context: { readonly turn: number; readonly key: string },\n ) => MockReply | string;\n readonly agentName?: string;\n readonly disclosure?: string;\n readonly welcome?: Welcome;\n /** A refusal when opening a session (the scripted backend's answer), by request. */\n readonly refuse?: (\n request: AgentSessionRequest,\n attempt: number,\n ) => 'ended' | 'unreachable' | 'unavailable' | undefined;\n /** How long a session lives. Default 30 minutes. */\n readonly sessionMs?: number;\n readonly status?: AgentStatusRead;\n /** The clock sessions are dated by; default the device's. */\n readonly now?: () => number;\n /** Past conversations history serves, beside the ones the person has here. */\n readonly history?: readonly MockConversation[];\n}\n\nexport interface MockAgent {\n readonly backend: AgentBackend;\n /** The store's transport: `conversation.transport.webSocket`. */\n readonly webSocket: WebSocketFactory;\n /** What the app sent: feedback, sessions asked for, places told, history asked for and deleted. */\n readonly log: {\n readonly sessions: AgentSessionRequest[];\n readonly feedback: unknown[];\n readonly contexts: unknown[];\n readonly ended: number;\n readonly lists: unknown[];\n readonly reads: unknown[];\n readonly deleted: string[];\n };\n}\n\n/** A conversation the mock holds: as history lists it, with its items as history reads them. */\ninterface Held {\n readonly id: string;\n readonly mode: string;\n readonly scope: string | null;\n readonly agent: string;\n readonly title: string | null;\n readonly started_at: string;\n state: 'open' | 'ended';\n readonly items: HistoryItem[];\n}\n\nconst CURSOR = /^mock:(\\d+)$/;\nconst refusal = (\n kind: 'ended' | 'unavailable',\n reason: 'not_found' | 'server',\n) =>\n Object.assign(\n new AgentRefusal(kind, {\n reason,\n code: reason === 'not_found' ? 'conversation_not_found' : 'unavailable',\n }),\n { retryable: false },\n );\n\nconst sentences = (text: string) => text.match(/[^.!?]+[.!?]*\\s*/g) ?? [text];\n\nexport function createMockAgent(options: MockAgentOptions = {}): MockAgent {\n const now = options.now ?? (() => Date.now());\n const at = () => new Date(now()).toISOString();\n const conversations = new Map<string, Held>();\n const sessions = new Map<string, { conversation: string; key: string }>();\n const log = {\n sessions: [] as AgentSessionRequest[],\n feedback: [] as unknown[],\n contexts: [] as unknown[],\n ended: 0,\n lists: [] as unknown[],\n reads: [] as unknown[],\n deleted: [] as string[],\n };\n let attempts = 0;\n let count = 0;\n for (const c of options.history ?? []) {\n const started = c.startedAt ?? at();\n const items = c.items.map((item, n): HistoryItem => {\n const id = `h_${c.id}_${n + 1}`;\n const turn = `turn_${c.id}_${n + 1}`;\n if ('card' in item)\n return {\n type: 'card',\n id,\n turn_id: turn,\n at: item.at ?? started,\n card: item.card,\n ...(item.card.kind === 'proposal'\n ? { proposal_outcome: item.proposal_outcome ?? 'pending' }\n : {}),\n };\n return {\n type: 'message',\n id,\n role: item.role,\n text: item.text,\n at: item.at ?? started,\n event_id: id,\n turn_id: turn,\n ...(item.interrupted ? { interrupted: true } : {}),\n ...(item.refusal ? { refusal: true } : {}),\n };\n });\n conversations.set(c.id, {\n id: c.id,\n mode: c.mode ?? 'customer',\n scope: c.scope ?? null,\n agent: c.agent ?? 'mock_agent',\n title: c.title ?? null,\n started_at: started,\n state: c.state ?? 'ended',\n items,\n });\n }\n const lastActivity = (held: Held) => held.items.at(-1)?.at ?? held.started_at;\n const summaryOf = (held: Held): Summary => ({\n id: held.id,\n agent: held.agent,\n experience_mode: held.mode as Summary['experience_mode'],\n ...(held.scope === null ? {} : { business_scope_id: held.scope }),\n title: held.title ?? held.started_at.slice(0, 10),\n title_source: held.title ? 'intent' : 'date',\n started_at: held.started_at,\n last_activity_at: lastActivity(held),\n message_count: held.items.filter((i) => i.type === 'message').length,\n state: held.state,\n });\n /** `cursor` as an offset the mock wrote; another one is refused as the gateway refuses a stale cursor. */\n const offsetOf = (cursor: string | null) => {\n if (cursor === null) return 0;\n const m = CURSOR.exec(cursor);\n if (!m) throw refusal('unavailable', 'server');\n return Number(m[1]);\n };\n\n const backend: AgentBackend = {\n async openSession(request) {\n log.sessions.push(request);\n attempts++;\n const refusal = options.refuse?.(request, attempts);\n if (refusal === 'unreachable')\n throw Object.assign(new Error('mock: unreachable'), {\n retryable: true,\n reason: 'network',\n });\n if (refusal) throw new AgentRefusal(refusal);\n if (\n request.conversationId !== null &&\n !conversations.has(request.conversationId)\n )\n throw new AgentRefusal('ended', { code: 'conversation_not_found' });\n count++;\n const conversation = request.conversationId ?? `cnv_MOCK${count}`;\n if (!conversations.has(conversation))\n conversations.set(conversation, {\n id: conversation,\n mode: request.key.mode,\n scope: request.key.scope ?? null,\n agent: request.agent ?? 'mock_agent',\n title: null,\n started_at: at(),\n state: 'open',\n items: [],\n });\n const id = `ses_MOCK${count}`;\n sessions.set(id, { conversation, key: `${request.key.mode}` });\n const session: ConversationSession = {\n id,\n realtime_url: `wss://mock.vinaverse.invalid/v1/sessions/${id}/realtime`,\n turns_url: `https://mock.vinaverse.invalid/v1/sessions/${id}/turns`,\n client_secret: `vv_cs_${'mock'.repeat(6)}`,\n conversation_id: conversation,\n expires_at: new Date(\n now() + (options.sessionMs ?? 30 * 60_000),\n ).toISOString(),\n ...(options.agentName\n ? { agent: { display_name: options.agentName } }\n : {}),\n ...(options.disclosure ? { disclosure: options.disclosure } : {}),\n ...(options.welcome ? { welcome: options.welcome } : {}),\n };\n return session;\n },\n async refreshSecret() {\n return `vv_cs_${'mock'.repeat(6)}`;\n },\n async updateContext(sessionId, place, revision) {\n log.contexts.push({ sessionId, place, revision });\n },\n async status() {\n return (\n options.status ?? {\n available: true,\n launcher: true,\n displayName: options.agentName ?? null,\n }\n );\n },\n async sendFeedback(feedback) {\n log.feedback.push(feedback);\n },\n async endSessions() {\n log.ended++;\n },\n async listConversations(query) {\n log.lists.push(query);\n const from = offsetOf(query.cursor);\n const limit = query.limit ?? 20;\n const all = [...conversations.values()]\n .filter(\n (c) =>\n c.mode === query.mode &&\n c.scope === (query.scope ?? null) &&\n (query.agent === null || c.agent === query.agent) &&\n c.items.some((i) => i.type === 'message'),\n )\n .map(summaryOf)\n .sort(\n (a, b) =>\n b.last_activity_at.localeCompare(a.last_activity_at) ||\n b.id.localeCompare(a.id),\n );\n const data = all.slice(from, from + limit);\n return {\n data,\n next_cursor: from + limit < all.length ? `mock:${from + limit}` : null,\n };\n },\n async readConversation(conversationId, page) {\n log.reads.push({ conversationId, ...page });\n const held = conversations.get(conversationId);\n if (!held) throw refusal('ended', 'not_found');\n const limit = page.limit ?? 30;\n // Newest page first: `cursor` is how many items from the start the page before began at.\n const end =\n page.cursor === null ? held.items.length : offsetOf(page.cursor);\n const start = Math.max(0, end - limit);\n return {\n data: held.items.slice(start, end),\n next_cursor: start > 0 ? `mock:${start}` : null,\n };\n },\n async deleteConversation(conversationId) {\n log.deleted.push(conversationId);\n if (!conversations.delete(conversationId))\n throw refusal('ended', 'not_found');\n for (const [id, s] of sessions)\n if (s.conversation === conversationId) sessions.delete(id);\n },\n };\n\n const webSocket: WebSocketFactory = (url) => {\n const sessionId = /sessions\\/([^/]+)\\/realtime/.exec(url)?.[1] ?? '';\n const held = sessions.get(sessionId);\n const items = held\n ? (conversations.get(held.conversation)?.items ?? [])\n : [];\n const said = () =>\n items.filter(\n (i): i is Extract<HistoryItem, { type: 'message' }> =>\n i.type === 'message',\n );\n let turn = said().filter((s) => s.role === 'person').length;\n let state = 0;\n const socket: WebSocketLike = {\n get readyState() {\n return state;\n },\n onopen: null,\n onmessage: null,\n onclose: null,\n onerror: null,\n send(data) {\n const frame = JSON.parse(data) as Record<string, unknown>;\n if (frame.type === 'ping') return deliver({ type: 'pong' });\n if (frame.type !== 'input.text') return;\n const id = String(frame.client_event_id ?? '');\n const text = String(frame.text ?? '');\n turn++;\n const turnId = `turn_MOCK${turn}`;\n items.push({\n type: 'message',\n id: `p_${turnId}`,\n role: 'person',\n text,\n at: at(),\n event_id: id,\n turn_id: turnId,\n });\n const answer =\n options.script?.[turn - 1] ??\n options.reply?.(text, { turn, key: held?.key ?? '' }) ??\n `You said: ${text}`;\n const reply: MockReply =\n typeof answer === 'string' ? { text: answer } : answer;\n deliver({ type: 'turn.started', turn_id: turnId, client_event_id: id });\n if (reply.fail) {\n deliver({\n type: 'turn.failed',\n turn_id: turnId,\n code: reply.fail,\n message: '',\n retryable: true,\n });\n return;\n }\n let so = '';\n for (const part of reply.text ? sentences(reply.text) : []) {\n so += part;\n deliver({ type: 'message.delta', turn_id: turnId, text: part });\n }\n if (reply.text) {\n deliver({\n type: 'message.completed',\n turn_id: turnId,\n text: so.trim(),\n });\n items.push({\n type: 'message',\n id: `a_${turnId}`,\n role: 'assistant',\n text: so.trim(),\n at: at(),\n event_id: turnId,\n turn_id: turnId,\n });\n }\n if (reply.cards?.length) {\n deliver({ type: 'ui.cards', turn_id: turnId, cards: reply.cards });\n for (const card of reply.cards)\n items.push({\n type: 'card',\n id: card.id,\n turn_id: turnId,\n at: at(),\n card,\n ...(card.kind === 'proposal'\n ? { proposal_outcome: 'pending' }\n : {}),\n });\n }\n deliver({ type: 'turn.completed', turn_id: turnId });\n },\n close(code) {\n if (state === 3) return;\n state = 3;\n setTimeout(() => socket.onclose?.({ code: code ?? 1000 }), 0);\n },\n };\n function deliver(event: unknown) {\n setTimeout(() => {\n if (state === 1) socket.onmessage?.({ data: JSON.stringify(event) });\n }, 0);\n }\n setTimeout(() => {\n state = 1;\n socket.onopen?.({});\n const transcript = said();\n const resumed = transcript.length > 0;\n socket.onmessage?.({\n data: JSON.stringify({\n type: 'session.ready',\n session: { id: sessionId, status: 'open' },\n resumed,\n limits: {},\n disclosure:\n options.disclosure ?? 'An AI agent. Powered by Vinaverse.',\n ...(resumed\n ? {\n transcript: transcript.map((s) => ({\n role: s.role,\n text: s.text,\n id: s.event_id,\n at: s.at,\n ...(s.turn_id ? { turn_id: s.turn_id } : {}),\n ...(s.interrupted ? { interrupted: true } : {}),\n })),\n }\n : {}),\n }),\n });\n }, 0);\n return socket;\n };\n\n return { backend, webSocket, log };\n}\n\n/** Cards as a tenant's tools would give them, for mock replies and tests. */\nexport const mockCards = {\n professional(id: string, extra: Partial<Card> = {}): Card {\n return {\n id,\n kind: 'professional',\n title: 'Riley Sample',\n subtitle: 'Barber · Los Angeles',\n ref: { type: 'professional', id },\n images: [\n {\n url: `https://images.example.test/${id}.webp`,\n width: 1600,\n height: 1000,\n },\n ],\n rating: { value_ppm: 4_800_000, count: 132 },\n price_from: { amount: 4500, currency: 'USD' },\n actions: [],\n source: { tool: 'search_professionals', call_id: 'call_MOCK' },\n ...extra,\n } as Card;\n },\n workspace(id: string, extra: Partial<Card> = {}): Card {\n return {\n id,\n kind: 'workspace',\n title: 'Suite 4',\n subtitle: 'Private suite · Atlanta',\n ref: { type: 'workspace', id },\n price_from: { amount: 6500, currency: 'USD' },\n actions: [],\n source: { tool: 'search_spaces', call_id: 'call_MOCK' },\n ...extra,\n } as Card;\n },\n /** A proposal the person confirms in the app (`confirm_mode: tenant_app`), pending for a day unless `expires_at`. */\n proposal(\n id: string,\n proposal: {\n readonly topic?: string;\n readonly title?: string;\n readonly summary?: string;\n readonly expires_at?: string;\n } = {},\n ): Card {\n const title = proposal.title ?? 'Silk press with Riley';\n return {\n id,\n kind: 'proposal',\n title,\n actions: [],\n source: { tool: 'create_proposal', call_id: 'call_MOCK' },\n proposal: {\n id: `prp_${id}`,\n status: 'pending',\n topic: proposal.topic ?? 'booking',\n title,\n summary: proposal.summary ?? 'Wednesday at 10:00 · $45',\n fields: [],\n expires_at:\n proposal.expires_at ??\n new Date(Date.now() + 24 * 3_600_000).toISOString(),\n confirm_mode: 'tenant_app',\n },\n } as Card;\n },\n /** Times to book, from `start` on the hour, one an hour. */\n timeSlots(id: string, start: string, count = 3): Card {\n const at = Date.parse(start);\n return {\n id,\n kind: 'time_slots',\n title: 'Open times',\n slots: Array.from({ length: count }, (_, i) => ({\n id: `slot_${i + 1}`,\n start: new Date(at + i * 3_600_000).toISOString(),\n end: new Date(at + (i + 1) * 3_600_000).toISOString(),\n })),\n actions: [],\n source: { tool: 'get_availability', call_id: 'call_MOCK' },\n } as Card;\n },\n links(id: string): Card {\n return {\n id,\n kind: 'links',\n title: 'Pages that can help',\n links: [\n {\n label: 'Help center',\n url: 'https://help.example.test/',\n purpose: 'help',\n },\n {\n label: 'Contact us',\n url: 'https://help.example.test/contact',\n purpose: 'contact',\n },\n ],\n actions: [],\n source: { tool: 'scope', call_id: 'turn_MOCK' },\n } as Card;\n },\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vinaverse/client",
3
- "version": "0.1.0-alpha.10",
3
+ "version": "0.1.0-alpha.11",
4
4
  "description": "Vinaverse for apps: the realtime session client (WebSocket with SSE fallback, resume, typed events and cards). No UI.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Vinaverse, Inc.",
@@ -78,6 +78,20 @@
78
78
  "default": "./dist/backend/index.cjs"
79
79
  }
80
80
  },
81
+ "./history": {
82
+ "react-native": {
83
+ "types": "./dist/history/index.d.cts",
84
+ "default": "./dist/history/index.cjs"
85
+ },
86
+ "import": {
87
+ "types": "./dist/history/index.d.ts",
88
+ "default": "./dist/history/index.js"
89
+ },
90
+ "require": {
91
+ "types": "./dist/history/index.d.cts",
92
+ "default": "./dist/history/index.cjs"
93
+ }
94
+ },
81
95
  "./testing": {
82
96
  "react-native": {
83
97
  "types": "./dist/testing/index.d.cts",
@@ -110,6 +124,9 @@
110
124
  ],
111
125
  "backend": [
112
126
  "./dist/backend/index.d.cts"
127
+ ],
128
+ "history": [
129
+ "./dist/history/index.d.cts"
113
130
  ]
114
131
  }
115
132
  },
@@ -144,6 +161,12 @@
144
161
  "path": "dist/backend/index.js",
145
162
  "import": "*",
146
163
  "limit": "2.25 kB"
164
+ },
165
+ {
166
+ "name": "@vinaverse/client/history (ESM, everything: the history and transcript stores and historyItems)",
167
+ "path": "dist/history/index.js",
168
+ "import": "*",
169
+ "limit": "2 kB"
147
170
  }
148
171
  ],
149
172
  "scripts": {