@absolutejs/voice 0.0.22-beta.209 → 0.0.22-beta.210

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 (2) hide show
  1. package/README.md +230 -0
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -249,6 +249,236 @@ The demo UI should show a mic button, transcript, current specialist badge, read
249
249
 
250
250
  This recipe covers the hosted-platform expectations that matter for support triage: assistant entrypoint, business tools, specialist handoff, post-call task creation, simulation proof, tool contract proof, production readiness, audit-compatible runtime storage, and a call-log replacement at `/voice-operations/:sessionId`.
251
251
 
252
+ ## Use-Case Recipe: Appointment Scheduling
253
+
254
+ Use this path when the assistant needs to check availability, book a slot, create a confirmation task, and prove the post-call workflow before production traffic. This is the self-hosted version of a hosted scheduling agent: your app owns the calendar tool, booking policy, storage, follow-up tasks, and call evidence.
255
+
256
+ The production shape is:
257
+
258
+ 1. Persist sessions, traces, reviews, tasks, integration events, and audit events in app-owned runtime storage.
259
+ 2. Define `check_availability` and `book_appointment` as server-side tools with deterministic tool contracts.
260
+ 3. Use `resolveVoiceOutcomeRecipe('appointment-booking')` so completed calls create appointment-confirmation work.
261
+ 4. Add an outcome contract that requires a completed session, review, task, and integration events.
262
+ 5. Mount simulation, outcome-contract, readiness, and operations-record routes so scheduling regressions fail before live calls.
263
+
264
+ ```ts
265
+ import { Elysia } from 'elysia';
266
+ import {
267
+ createVoiceAgent,
268
+ createVoiceAgentTool,
269
+ createVoiceFileRuntimeStorage,
270
+ createVoiceOperationsRecordRoutes,
271
+ createVoiceOutcomeContractRoutes,
272
+ createVoiceProductionReadinessRoutes,
273
+ createVoiceSimulationSuiteRoutes,
274
+ createVoiceToolContractRoutes,
275
+ createVoiceToolRuntimeContractDefaults,
276
+ resolveVoiceOutcomeRecipe,
277
+ voice
278
+ } from '@absolutejs/voice';
279
+ import { deepgram } from '@absolutejs/voice-deepgram';
280
+
281
+ const runtime = createVoiceFileRuntimeStorage({
282
+ directory: '.voice-runtime/appointments'
283
+ });
284
+
285
+ const checkAvailability = createVoiceAgentTool({
286
+ name: 'check_availability',
287
+ description: 'Return open appointment slots for a service and date.',
288
+ parameters: {
289
+ type: 'object',
290
+ properties: {
291
+ date: { type: 'string' },
292
+ service: { type: 'string' }
293
+ },
294
+ required: ['date', 'service']
295
+ },
296
+ execute: async ({ args }) => ({
297
+ date: args.date,
298
+ service: args.service,
299
+ slots: ['2026-05-04T15:00:00-04:00', '2026-05-04T16:30:00-04:00']
300
+ })
301
+ });
302
+
303
+ const bookAppointment = createVoiceAgentTool({
304
+ name: 'book_appointment',
305
+ description: 'Book a confirmed appointment slot.',
306
+ parameters: {
307
+ type: 'object',
308
+ properties: {
309
+ customerName: { type: 'string' },
310
+ phone: { type: 'string' },
311
+ service: { type: 'string' },
312
+ startsAt: { type: 'string' }
313
+ },
314
+ required: ['customerName', 'phone', 'service', 'startsAt']
315
+ },
316
+ execute: async ({ args }) => ({
317
+ appointmentId: `appt_${args.startsAt}`,
318
+ customerName: args.customerName,
319
+ phone: args.phone,
320
+ service: args.service,
321
+ startsAt: args.startsAt,
322
+ status: 'confirmed'
323
+ })
324
+ });
325
+
326
+ const scheduler = createVoiceAgent({
327
+ id: 'scheduler',
328
+ system: 'Collect caller details, check availability, book an appointment, and summarize the confirmation.',
329
+ tools: [checkAvailability, bookAppointment],
330
+ trace: runtime.traces,
331
+ model: {
332
+ async generate({ tools }) {
333
+ return {
334
+ assistantText: `I can check times and book the appointment. Available tools: ${tools.map((tool) => tool.name).join(', ')}`
335
+ };
336
+ }
337
+ }
338
+ });
339
+
340
+ const toolContractDefinitions = [
341
+ {
342
+ id: 'check-availability-contract',
343
+ label: 'Availability returns bookable slots',
344
+ tool: checkAvailability,
345
+ cases: [
346
+ {
347
+ id: 'consultation-slots',
348
+ args: { date: '2026-05-04', service: 'consultation' },
349
+ expect: { expectStatus: 'ok' }
350
+ }
351
+ ],
352
+ defaultRuntime: createVoiceToolRuntimeContractDefaults()
353
+ },
354
+ {
355
+ id: 'book-appointment-contract',
356
+ label: 'Booking returns a confirmed appointment',
357
+ tool: bookAppointment,
358
+ cases: [
359
+ {
360
+ id: 'confirmed-consultation',
361
+ args: {
362
+ customerName: 'Ada Lovelace',
363
+ phone: '+15551234567',
364
+ service: 'consultation',
365
+ startsAt: '2026-05-04T15:00:00-04:00'
366
+ },
367
+ expect: {
368
+ expectedResult: {
369
+ appointmentId: 'appt_2026-05-04T15:00:00-04:00',
370
+ customerName: 'Ada Lovelace',
371
+ phone: '+15551234567',
372
+ service: 'consultation',
373
+ startsAt: '2026-05-04T15:00:00-04:00',
374
+ status: 'confirmed'
375
+ },
376
+ expectStatus: 'ok'
377
+ }
378
+ }
379
+ ],
380
+ defaultRuntime: createVoiceToolRuntimeContractDefaults()
381
+ }
382
+ ];
383
+
384
+ const outcomeContractDefinitions = [
385
+ {
386
+ id: 'appointment-booked',
387
+ label: 'Completed appointment call produces follow-up work',
388
+ expectedDisposition: 'completed',
389
+ minSessions: 1,
390
+ minTasks: 1,
391
+ requireIntegrationEvents: ['call.completed', 'review.saved', 'task.created'],
392
+ requireReview: true,
393
+ requireTask: true
394
+ }
395
+ ];
396
+
397
+ const app = new Elysia()
398
+ .use(
399
+ voice({
400
+ path: '/voice/appointments',
401
+ preset: 'reliability',
402
+ session: runtime.session,
403
+ stt: deepgram({
404
+ apiKey: process.env.DEEPGRAM_API_KEY!,
405
+ model: 'flux-general-en'
406
+ }),
407
+ trace: runtime.traces,
408
+ onTurn: scheduler.onTurn,
409
+ onComplete: async () => {},
410
+ ops: {
411
+ ...resolveVoiceOutcomeRecipe('appointment-booking', {
412
+ assignee: 'scheduling-oncall',
413
+ queue: 'appointments'
414
+ }),
415
+ events: runtime.events,
416
+ reviews: runtime.reviews,
417
+ tasks: runtime.tasks
418
+ }
419
+ })
420
+ )
421
+ .use(
422
+ createVoiceToolContractRoutes({
423
+ contracts: toolContractDefinitions,
424
+ htmlPath: '/voice/appointments/tool-contracts',
425
+ path: '/api/voice/appointments/tool-contracts'
426
+ })
427
+ )
428
+ .use(
429
+ createVoiceOutcomeContractRoutes({
430
+ contracts: outcomeContractDefinitions,
431
+ events: runtime.events,
432
+ htmlPath: '/voice/appointments/outcome-contracts',
433
+ operationsRecordHref: '/voice-operations/:sessionId',
434
+ path: '/api/voice/appointments/outcome-contracts',
435
+ reviews: runtime.reviews,
436
+ sessions: runtime.session,
437
+ tasks: runtime.tasks
438
+ })
439
+ )
440
+ .use(
441
+ createVoiceSimulationSuiteRoutes({
442
+ htmlPath: '/voice/appointments/simulations',
443
+ operationsRecordHref: '/voice-operations/:sessionId',
444
+ outcomes: {
445
+ contracts: outcomeContractDefinitions,
446
+ events: runtime.events,
447
+ reviews: runtime.reviews,
448
+ sessions: runtime.session,
449
+ tasks: runtime.tasks
450
+ },
451
+ path: '/api/voice/appointments/simulations',
452
+ tools: toolContractDefinitions
453
+ })
454
+ )
455
+ .use(
456
+ createVoiceOperationsRecordRoutes({
457
+ htmlPath: '/voice-operations/:sessionId',
458
+ integrationEvents: runtime.events,
459
+ path: '/api/voice-operations/:sessionId',
460
+ reviews: runtime.reviews,
461
+ store: runtime.traces,
462
+ tasks: runtime.tasks
463
+ })
464
+ )
465
+ .use(
466
+ createVoiceProductionReadinessRoutes({
467
+ htmlPath: '/production-readiness',
468
+ links: {
469
+ operationsRecords: '/voice-operations/:sessionId',
470
+ simulations: '/voice/appointments/simulations'
471
+ },
472
+ path: '/api/production-readiness',
473
+ store: runtime.traces
474
+ })
475
+ );
476
+ ```
477
+
478
+ The UI should keep the scheduling flow simple: microphone, transcript, selected slot, booking status, confirmation task link, `/voice/appointments/simulations`, `/voice/appointments/outcome-contracts`, `/production-readiness`, and `/voice-operations/:sessionId`. If the booking or confirmation proof fails, the operator should start at the outcome contract and follow the linked operations record.
479
+
480
+ This recipe covers the hosted-platform expectations that matter for appointment scheduling: scheduling tools, deterministic tool proof, post-call confirmation work, outcome validation, simulation proof, production readiness, and one call-log replacement for debugging.
481
+
252
482
  ## How This Differs From Hosted Voice Platforms
253
483
 
254
484
  Hosted voice-agent platforms are strongest when you want a managed dashboard, phone-number provisioning, hosted orchestration, and campaign tooling out of the box.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.209",
3
+ "version": "0.0.22-beta.210",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",