@absolutejs/voice 0.0.22-beta.29 → 0.0.22-beta.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/handoffHealth.d.ts +94 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +197 -0
- package/package.json +1 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Elysia } from 'elysia';
|
|
2
|
+
import type { StoredVoiceTraceEvent, VoiceTraceEventStore } from './trace';
|
|
3
|
+
export type VoiceHandoffHealthStatus = 'delivered' | 'failed' | 'skipped';
|
|
4
|
+
export type VoiceHandoffHealthDelivery = {
|
|
5
|
+
adapterId: string;
|
|
6
|
+
adapterKind?: string;
|
|
7
|
+
deliveredAt?: number;
|
|
8
|
+
deliveredTo?: string;
|
|
9
|
+
error?: string;
|
|
10
|
+
status: VoiceHandoffHealthStatus;
|
|
11
|
+
};
|
|
12
|
+
export type VoiceHandoffHealthEvent = {
|
|
13
|
+
action?: string;
|
|
14
|
+
at: number;
|
|
15
|
+
deliveries: VoiceHandoffHealthDelivery[];
|
|
16
|
+
reason?: string;
|
|
17
|
+
replayHref?: string;
|
|
18
|
+
sessionId: string;
|
|
19
|
+
status: VoiceHandoffHealthStatus;
|
|
20
|
+
target?: string;
|
|
21
|
+
};
|
|
22
|
+
export type VoiceHandoffHealthSummary = {
|
|
23
|
+
byAction: Record<string, number>;
|
|
24
|
+
byAdapter: Record<string, Record<VoiceHandoffHealthStatus, number>>;
|
|
25
|
+
byStatus: Record<VoiceHandoffHealthStatus, number>;
|
|
26
|
+
events: VoiceHandoffHealthEvent[];
|
|
27
|
+
failed: number;
|
|
28
|
+
total: number;
|
|
29
|
+
};
|
|
30
|
+
export type VoiceHandoffHealthSummaryOptions = {
|
|
31
|
+
events?: StoredVoiceTraceEvent[];
|
|
32
|
+
limit?: number;
|
|
33
|
+
q?: string;
|
|
34
|
+
replayHref?: false | string | ((event: Omit<VoiceHandoffHealthEvent, 'replayHref'>) => string);
|
|
35
|
+
status?: VoiceHandoffHealthStatus | 'all';
|
|
36
|
+
store?: VoiceTraceEventStore;
|
|
37
|
+
};
|
|
38
|
+
export type VoiceHandoffHealthHTMLHandlerOptions = VoiceHandoffHealthSummaryOptions & {
|
|
39
|
+
headers?: HeadersInit;
|
|
40
|
+
render?: (summary: VoiceHandoffHealthSummary) => string | Promise<string>;
|
|
41
|
+
};
|
|
42
|
+
export type VoiceHandoffHealthRoutesOptions = VoiceHandoffHealthHTMLHandlerOptions & {
|
|
43
|
+
htmlPath?: false | string;
|
|
44
|
+
name?: string;
|
|
45
|
+
path?: string;
|
|
46
|
+
};
|
|
47
|
+
export declare const summarizeVoiceHandoffHealth: (options?: VoiceHandoffHealthSummaryOptions) => Promise<VoiceHandoffHealthSummary>;
|
|
48
|
+
export declare const renderVoiceHandoffHealthHTML: (summary: VoiceHandoffHealthSummary) => string;
|
|
49
|
+
export declare const createVoiceHandoffHealthJSONHandler: (options?: VoiceHandoffHealthSummaryOptions) => ({ query }: {
|
|
50
|
+
query?: Record<string, string | undefined>;
|
|
51
|
+
}) => Promise<VoiceHandoffHealthSummary>;
|
|
52
|
+
export declare const createVoiceHandoffHealthHTMLHandler: (options?: VoiceHandoffHealthHTMLHandlerOptions) => ({ query }: {
|
|
53
|
+
query?: Record<string, string | undefined>;
|
|
54
|
+
}) => Promise<Response>;
|
|
55
|
+
export declare const createVoiceHandoffHealthRoutes: (options?: VoiceHandoffHealthRoutesOptions) => Elysia<"", {
|
|
56
|
+
decorator: {};
|
|
57
|
+
store: {};
|
|
58
|
+
derive: {};
|
|
59
|
+
resolve: {};
|
|
60
|
+
}, {
|
|
61
|
+
typebox: {};
|
|
62
|
+
error: {};
|
|
63
|
+
}, {
|
|
64
|
+
schema: {};
|
|
65
|
+
standaloneSchema: {};
|
|
66
|
+
macro: {};
|
|
67
|
+
macroFn: {};
|
|
68
|
+
parser: {};
|
|
69
|
+
response: {};
|
|
70
|
+
}, {
|
|
71
|
+
[x: string]: {
|
|
72
|
+
get: {
|
|
73
|
+
body: unknown;
|
|
74
|
+
params: {};
|
|
75
|
+
query: unknown;
|
|
76
|
+
headers: unknown;
|
|
77
|
+
response: {
|
|
78
|
+
200: VoiceHandoffHealthSummary;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
}, {
|
|
83
|
+
derive: {};
|
|
84
|
+
resolve: {};
|
|
85
|
+
schema: {};
|
|
86
|
+
standaloneSchema: {};
|
|
87
|
+
response: {};
|
|
88
|
+
}, {
|
|
89
|
+
derive: {};
|
|
90
|
+
resolve: {};
|
|
91
|
+
schema: {};
|
|
92
|
+
standaloneSchema: {};
|
|
93
|
+
response: {};
|
|
94
|
+
}>;
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export { createVoiceMemoryStore } from './memoryStore';
|
|
|
15
15
|
export { createVoiceCRMActivitySink, createVoiceHelpdeskTicketSink, createVoiceIntegrationHTTPSink, createVoiceHubSpotTaskSink, createVoiceHubSpotTaskSyncSinks, createVoiceHubSpotTaskUpdateSink, createVoiceLinearIssueSink, createVoiceLinearIssueSyncSinks, createVoiceLinearIssueUpdateSink, createVoiceZendeskTicketSink, createVoiceZendeskTicketSyncSinks, createVoiceZendeskTicketUpdateSink, deliverVoiceIntegrationEventToSinks } from './opsSinks';
|
|
16
16
|
export { createVoiceOpsWebhookEnvelope, createVoiceOpsWebhookReceiverRoutes, createVoiceOpsWebhookSink, verifyVoiceOpsWebhookSignature } from './opsWebhook';
|
|
17
17
|
export { createVoiceTwilioRedirectHandoffAdapter, createVoiceWebhookHandoffAdapter, deliverVoiceHandoff } from './handoff';
|
|
18
|
+
export { createVoiceHandoffHealthHTMLHandler, createVoiceHandoffHealthJSONHandler, createVoiceHandoffHealthRoutes, renderVoiceHandoffHealthHTML, summarizeVoiceHandoffHealth } from './handoffHealth';
|
|
18
19
|
export { createVoiceIntegrationSinkWorker, createVoiceIntegrationSinkWorkerLoop, createVoiceOpsTaskWorker, createVoiceOpsTaskProcessorWorker, createVoiceOpsTaskProcessorWorkerLoop, createVoiceRedisIdempotencyStore, createVoiceRedisTaskLeaseCoordinator, createVoiceTraceSinkDeliveryWorker, createVoiceTraceSinkDeliveryWorkerLoop, createVoiceWebhookDeliveryWorker, createVoiceWebhookDeliveryWorkerLoop, summarizeVoiceTraceSinkDeliveries, summarizeVoiceOpsTaskQueue, summarizeVoiceIntegrationEvents } from './queue';
|
|
19
20
|
export { assignVoiceOpsTask, applyVoiceOpsTaskAssignmentRule, applyVoiceOpsTaskPolicy, buildVoiceOpsTaskFromReview, buildVoiceOpsTaskFromSLABreach, claimVoiceOpsTask, completeVoiceOpsTask, createVoiceExternalObjectMap, createVoiceExternalObjectMapId, createVoiceCallCompletedEvent, createVoiceTaskSLABreachedEvent, deadLetterVoiceOpsTask, deliverVoiceIntegrationEvent, failVoiceOpsTask, hasVoiceOpsTaskSLABreach, heartbeatVoiceOpsTask, isVoiceOpsTaskOverdue, markVoiceOpsTaskSLABreached, matchesVoiceOpsTaskAssignmentRule, resolveVoiceOpsTaskAgeBucket, createVoiceIntegrationEvent, createVoiceReviewSavedEvent, resolveVoiceOpsTaskAssignment, resolveVoiceOpsTaskPolicy, requeueVoiceOpsTask, createVoiceTaskCreatedEvent, createVoiceTaskUpdatedEvent, listVoiceOpsTasks, reopenVoiceOpsTask, startVoiceOpsTask, summarizeVoiceOpsTaskAnalytics, summarizeVoiceOpsTasks, withVoiceIntegrationEventId, withVoiceOpsTaskId } from './ops';
|
|
20
21
|
export { createVoiceSession } from './session';
|
|
@@ -42,6 +43,7 @@ export type { VoiceOutcomeRecipe, VoiceOutcomeRecipeName, VoiceOutcomeRecipeOpti
|
|
|
42
43
|
export type { VoiceCRMActivitySinkOptions, VoiceHubSpotTaskSinkOptions, VoiceHubSpotTaskUpdateSinkOptions, VoiceHelpdeskTicketSinkOptions, VoiceIntegrationHTTPSinkOptions, VoiceIntegrationSink, VoiceIntegrationSinkDeliveryResult, VoiceLinearIssueSinkOptions, VoiceLinearIssueUpdateSinkOptions, VoiceZendeskTicketSinkOptions, VoiceZendeskTicketUpdateSinkOptions } from './opsSinks';
|
|
43
44
|
export type { VoiceOpsWebhookEnvelope, VoiceOpsWebhookEntity, VoiceOpsWebhookLinkResolver, VoiceOpsWebhookReceiverRoutesOptions, VoiceOpsWebhookSinkOptions, VoiceOpsWebhookVerificationResult } from './opsWebhook';
|
|
44
45
|
export type { VoiceHandoffDelivery, VoiceHandoffFanoutResult, VoiceTwilioRedirectHandoffAdapterOptions, VoiceWebhookHandoffAdapterOptions } from './handoff';
|
|
46
|
+
export type { VoiceHandoffHealthDelivery, VoiceHandoffHealthEvent, VoiceHandoffHealthHTMLHandlerOptions, VoiceHandoffHealthRoutesOptions, VoiceHandoffHealthStatus, VoiceHandoffHealthSummary, VoiceHandoffHealthSummaryOptions } from './handoffHealth';
|
|
45
47
|
export type { StoredVoiceCallReviewArtifact, VoiceCallReviewArtifact, VoiceCallReviewConfig, VoiceCallReviewPostCallSummary, VoiceCallReviewRecorder, VoiceCallReviewRecorderOptions, VoiceCallReviewStore, VoiceCallReviewSummary, VoiceCallReviewTimelineEvent } from './testing/review';
|
|
46
48
|
export type { VoiceFileRuntimeStorage, VoiceFileStoreOptions } from './fileStore';
|
|
47
49
|
export type { StoredVoiceTraceEvent, VoiceTraceEvaluation, VoiceTraceEvaluationOptions, VoiceTraceEvent, VoiceTraceEventFilter, VoiceTraceEventStore, VoiceTraceEventType, VoiceTraceIssue, VoiceTraceIssueSeverity, VoiceTraceHTTPSinkOptions, VoiceTracePruneFilter, VoiceTracePruneOptions, VoiceTracePruneResult, VoiceTraceRedactionConfig, VoiceTraceRedactionOptions, VoiceTraceRedactionReplacement, VoiceResolvedTraceRedactionOptions, VoiceTraceSink, VoiceTraceSinkDeliveryQueueStatus, VoiceTraceSinkDeliveryRecord, VoiceTraceSinkDeliveryResult, VoiceTraceSinkDeliveryStatus, VoiceTraceSinkDeliveryStore, VoiceTraceSinkFanoutResult, VoiceTraceSinkStoreOptions, VoiceTraceSummary } from './trace';
|
package/dist/index.js
CHANGED
|
@@ -9362,6 +9362,198 @@ var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
|
9362
9362
|
parse: "text"
|
|
9363
9363
|
});
|
|
9364
9364
|
};
|
|
9365
|
+
// src/handoffHealth.ts
|
|
9366
|
+
import { Elysia as Elysia6 } from "elysia";
|
|
9367
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
9368
|
+
var getString4 = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
9369
|
+
var isStatus = (value) => value === "delivered" || value === "failed" || value === "skipped";
|
|
9370
|
+
var increment3 = (record, key) => {
|
|
9371
|
+
record[key] = (record[key] ?? 0) + 1;
|
|
9372
|
+
};
|
|
9373
|
+
var normalizeDelivery = (adapterId, value) => {
|
|
9374
|
+
const record = value && typeof value === "object" ? value : {};
|
|
9375
|
+
return {
|
|
9376
|
+
adapterId: getString4(record.adapterId) ?? adapterId,
|
|
9377
|
+
adapterKind: getString4(record.adapterKind),
|
|
9378
|
+
deliveredAt: typeof record.deliveredAt === "number" ? record.deliveredAt : undefined,
|
|
9379
|
+
deliveredTo: getString4(record.deliveredTo),
|
|
9380
|
+
error: getString4(record.error),
|
|
9381
|
+
status: isStatus(record.status) ? record.status : "failed"
|
|
9382
|
+
};
|
|
9383
|
+
};
|
|
9384
|
+
var normalizeDeliveries = (payload) => {
|
|
9385
|
+
const deliveries = payload.deliveries;
|
|
9386
|
+
if (!deliveries || typeof deliveries !== "object") {
|
|
9387
|
+
return [];
|
|
9388
|
+
}
|
|
9389
|
+
return Object.entries(deliveries).map(([adapterId, value]) => normalizeDelivery(adapterId, value));
|
|
9390
|
+
};
|
|
9391
|
+
var resolveReplayHref = (event, replayHref) => {
|
|
9392
|
+
if (replayHref === false) {
|
|
9393
|
+
return;
|
|
9394
|
+
}
|
|
9395
|
+
if (typeof replayHref === "function") {
|
|
9396
|
+
return replayHref(event);
|
|
9397
|
+
}
|
|
9398
|
+
return `${replayHref ?? "/api/voice-sessions"}/${encodeURIComponent(event.sessionId)}/replay/htmx`;
|
|
9399
|
+
};
|
|
9400
|
+
var summarizeVoiceHandoffHealth = async (options = {}) => {
|
|
9401
|
+
const sourceEvents = options.events ?? await options.store?.list() ?? [];
|
|
9402
|
+
const search = options.q?.trim().toLowerCase();
|
|
9403
|
+
const byAction = {};
|
|
9404
|
+
const byAdapter = {};
|
|
9405
|
+
const byStatus = {
|
|
9406
|
+
delivered: 0,
|
|
9407
|
+
failed: 0,
|
|
9408
|
+
skipped: 0
|
|
9409
|
+
};
|
|
9410
|
+
const events = sourceEvents.filter((event) => event.type === "call.handoff").map((event) => {
|
|
9411
|
+
const status = isStatus(event.payload.status) ? event.payload.status : "failed";
|
|
9412
|
+
const deliveries = normalizeDeliveries(event.payload);
|
|
9413
|
+
const item = {
|
|
9414
|
+
action: getString4(event.payload.action),
|
|
9415
|
+
at: event.at,
|
|
9416
|
+
deliveries,
|
|
9417
|
+
reason: getString4(event.payload.reason),
|
|
9418
|
+
sessionId: event.sessionId,
|
|
9419
|
+
status,
|
|
9420
|
+
target: getString4(event.payload.target)
|
|
9421
|
+
};
|
|
9422
|
+
return {
|
|
9423
|
+
...item,
|
|
9424
|
+
replayHref: resolveReplayHref(item, options.replayHref)
|
|
9425
|
+
};
|
|
9426
|
+
}).filter((event) => {
|
|
9427
|
+
if (options.status && options.status !== "all" && event.status !== options.status) {
|
|
9428
|
+
return false;
|
|
9429
|
+
}
|
|
9430
|
+
if (!search) {
|
|
9431
|
+
return true;
|
|
9432
|
+
}
|
|
9433
|
+
return [
|
|
9434
|
+
event.action,
|
|
9435
|
+
event.reason,
|
|
9436
|
+
event.sessionId,
|
|
9437
|
+
event.status,
|
|
9438
|
+
event.target,
|
|
9439
|
+
...event.deliveries.flatMap((delivery) => [
|
|
9440
|
+
delivery.adapterId,
|
|
9441
|
+
delivery.adapterKind,
|
|
9442
|
+
delivery.deliveredTo,
|
|
9443
|
+
delivery.error,
|
|
9444
|
+
delivery.status
|
|
9445
|
+
])
|
|
9446
|
+
].some((value) => value?.toLowerCase().includes(search));
|
|
9447
|
+
}).sort((left, right) => right.at - left.at).slice(0, options.limit ?? 50);
|
|
9448
|
+
for (const event of events) {
|
|
9449
|
+
byStatus[event.status] += 1;
|
|
9450
|
+
if (event.action) {
|
|
9451
|
+
increment3(byAction, event.action);
|
|
9452
|
+
}
|
|
9453
|
+
for (const delivery of event.deliveries) {
|
|
9454
|
+
byAdapter[delivery.adapterId] ??= {
|
|
9455
|
+
delivered: 0,
|
|
9456
|
+
failed: 0,
|
|
9457
|
+
skipped: 0
|
|
9458
|
+
};
|
|
9459
|
+
byAdapter[delivery.adapterId][delivery.status] += 1;
|
|
9460
|
+
}
|
|
9461
|
+
}
|
|
9462
|
+
return {
|
|
9463
|
+
byAction,
|
|
9464
|
+
byAdapter,
|
|
9465
|
+
byStatus,
|
|
9466
|
+
events,
|
|
9467
|
+
failed: byStatus.failed,
|
|
9468
|
+
total: events.length
|
|
9469
|
+
};
|
|
9470
|
+
};
|
|
9471
|
+
var renderMetricGrid = (summary) => [
|
|
9472
|
+
'<section class="voice-handoff-health-grid">',
|
|
9473
|
+
`<article><span>Total</span><strong>${String(summary.total)}</strong></article>`,
|
|
9474
|
+
`<article><span>Delivered</span><strong>${String(summary.byStatus.delivered)}</strong></article>`,
|
|
9475
|
+
`<article><span>Failed</span><strong>${String(summary.byStatus.failed)}</strong></article>`,
|
|
9476
|
+
`<article><span>Skipped</span><strong>${String(summary.byStatus.skipped)}</strong></article>`,
|
|
9477
|
+
"</section>"
|
|
9478
|
+
].join("");
|
|
9479
|
+
var renderActionSummary = (summary) => {
|
|
9480
|
+
const actions = Object.entries(summary.byAction).sort((left, right) => right[1] - left[1]);
|
|
9481
|
+
const adapters = Object.entries(summary.byAdapter).sort(([left], [right]) => left.localeCompare(right));
|
|
9482
|
+
return [
|
|
9483
|
+
'<section class="voice-handoff-health-columns">',
|
|
9484
|
+
"<article><h3>Actions</h3>",
|
|
9485
|
+
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${escapeHtml7(action)}: ${String(count)}</li>`).join("")}</ul>`,
|
|
9486
|
+
"</article>",
|
|
9487
|
+
"<article><h3>Adapters</h3>",
|
|
9488
|
+
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${escapeHtml7(adapterId)}: ${String(counts.delivered)} delivered / ${String(counts.failed)} failed / ${String(counts.skipped)} skipped</li>`).join("")}</ul>`,
|
|
9489
|
+
"</article>",
|
|
9490
|
+
"</section>"
|
|
9491
|
+
].join("");
|
|
9492
|
+
};
|
|
9493
|
+
var renderVoiceHandoffHealthHTML = (summary) => [
|
|
9494
|
+
'<div class="voice-handoff-health">',
|
|
9495
|
+
renderMetricGrid(summary),
|
|
9496
|
+
renderActionSummary(summary),
|
|
9497
|
+
"<section>",
|
|
9498
|
+
"<h3>Recent Handoffs</h3>",
|
|
9499
|
+
summary.events.length === 0 ? '<p class="voice-handoff-health-empty">No handoffs found.</p>' : [
|
|
9500
|
+
'<div class="voice-handoff-health-events">',
|
|
9501
|
+
...summary.events.map((event) => [
|
|
9502
|
+
`<article class="${escapeHtml7(event.status)}">`,
|
|
9503
|
+
'<div class="voice-handoff-health-event-header">',
|
|
9504
|
+
`<strong>${escapeHtml7(event.action ?? "handoff")}</strong>`,
|
|
9505
|
+
`<span>${escapeHtml7(event.status)}</span>`,
|
|
9506
|
+
"</div>",
|
|
9507
|
+
`<p><small>${escapeHtml7(event.sessionId)}</small></p>`,
|
|
9508
|
+
event.target ? `<p>Target: ${escapeHtml7(event.target)}</p>` : "",
|
|
9509
|
+
event.reason ? `<p>Reason: ${escapeHtml7(event.reason)}</p>` : "",
|
|
9510
|
+
event.deliveries.length ? `<ul>${event.deliveries.map((delivery) => [
|
|
9511
|
+
"<li>",
|
|
9512
|
+
`${escapeHtml7(delivery.adapterId)}: ${escapeHtml7(delivery.status)}`,
|
|
9513
|
+
delivery.deliveredTo ? ` to ${escapeHtml7(delivery.deliveredTo)}` : "",
|
|
9514
|
+
delivery.error ? ` (${escapeHtml7(delivery.error)})` : "",
|
|
9515
|
+
"</li>"
|
|
9516
|
+
].join("")).join("")}</ul>` : "",
|
|
9517
|
+
event.replayHref ? `<p><a href="${escapeHtml7(event.replayHref)}">Open replay</a></p>` : "",
|
|
9518
|
+
"</article>"
|
|
9519
|
+
].join("")),
|
|
9520
|
+
"</div>"
|
|
9521
|
+
].join(""),
|
|
9522
|
+
"</section>",
|
|
9523
|
+
"</div>"
|
|
9524
|
+
].join("");
|
|
9525
|
+
var createVoiceHandoffHealthJSONHandler = (options = {}) => async ({ query }) => summarizeVoiceHandoffHealth({
|
|
9526
|
+
...options,
|
|
9527
|
+
limit: typeof query?.limit === "string" ? Number(query.limit) : options.limit,
|
|
9528
|
+
q: query?.q ?? options.q,
|
|
9529
|
+
status: query?.status === "delivered" || query?.status === "failed" || query?.status === "skipped" || query?.status === "all" ? query.status : options.status
|
|
9530
|
+
});
|
|
9531
|
+
var createVoiceHandoffHealthHTMLHandler = (options = {}) => async ({ query }) => {
|
|
9532
|
+
const summary = await summarizeVoiceHandoffHealth({
|
|
9533
|
+
...options,
|
|
9534
|
+
limit: typeof query?.limit === "string" ? Number(query.limit) : options.limit,
|
|
9535
|
+
q: query?.q ?? options.q,
|
|
9536
|
+
status: query?.status === "delivered" || query?.status === "failed" || query?.status === "skipped" || query?.status === "all" ? query.status : options.status
|
|
9537
|
+
});
|
|
9538
|
+
const body = await (options.render?.(summary) ?? renderVoiceHandoffHealthHTML(summary));
|
|
9539
|
+
return new Response(body, {
|
|
9540
|
+
headers: {
|
|
9541
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
9542
|
+
...options.headers
|
|
9543
|
+
}
|
|
9544
|
+
});
|
|
9545
|
+
};
|
|
9546
|
+
var createVoiceHandoffHealthRoutes = (options = {}) => {
|
|
9547
|
+
const path = options.path ?? "/api/voice-handoffs";
|
|
9548
|
+
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
9549
|
+
const routes = new Elysia6({
|
|
9550
|
+
name: options.name ?? "absolutejs-voice-handoff-health"
|
|
9551
|
+
}).get(path, createVoiceHandoffHealthJSONHandler(options));
|
|
9552
|
+
if (htmlPath) {
|
|
9553
|
+
routes.get(htmlPath, createVoiceHandoffHealthHTMLHandler(options));
|
|
9554
|
+
}
|
|
9555
|
+
return routes;
|
|
9556
|
+
};
|
|
9365
9557
|
// src/queue.ts
|
|
9366
9558
|
var releaseLeaseScript = `
|
|
9367
9559
|
if redis.call("GET", KEYS[1]) == ARGV[1] then
|
|
@@ -11339,6 +11531,7 @@ export {
|
|
|
11339
11531
|
summarizeVoiceOpsTaskQueue,
|
|
11340
11532
|
summarizeVoiceOpsTaskAnalytics,
|
|
11341
11533
|
summarizeVoiceIntegrationEvents,
|
|
11534
|
+
summarizeVoiceHandoffHealth,
|
|
11342
11535
|
summarizeVoiceAssistantRuns,
|
|
11343
11536
|
summarizeVoiceAssistantHealth,
|
|
11344
11537
|
startVoiceOpsTask,
|
|
@@ -11361,6 +11554,7 @@ export {
|
|
|
11361
11554
|
renderVoiceTraceHTML,
|
|
11362
11555
|
renderVoiceSessionsHTML,
|
|
11363
11556
|
renderVoiceProviderHealthHTML,
|
|
11557
|
+
renderVoiceHandoffHealthHTML,
|
|
11364
11558
|
renderVoiceCallReviewMarkdown,
|
|
11365
11559
|
renderVoiceCallReviewHTML,
|
|
11366
11560
|
renderVoiceAssistantHealthHTML,
|
|
@@ -11459,6 +11653,9 @@ export {
|
|
|
11459
11653
|
createVoiceHubSpotTaskSyncSinks,
|
|
11460
11654
|
createVoiceHubSpotTaskSink,
|
|
11461
11655
|
createVoiceHelpdeskTicketSink,
|
|
11656
|
+
createVoiceHandoffHealthRoutes,
|
|
11657
|
+
createVoiceHandoffHealthJSONHandler,
|
|
11658
|
+
createVoiceHandoffHealthHTMLHandler,
|
|
11462
11659
|
createVoiceFileTraceSinkDeliveryStore,
|
|
11463
11660
|
createVoiceFileTraceEventStore,
|
|
11464
11661
|
createVoiceFileTaskStore,
|