@absolutejs/voice 0.0.22-beta.243 → 0.0.22-beta.244
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/README.md +32 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +207 -0
- package/dist/postCallAnalysis.d.ts +98 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ Use this checklist when a buyer asks, "How do I know this replaces a hosted voic
|
|
|
68
68
|
| Can I prove provider fallback and latency? | provider contract matrix, provider status UI, `/turn-latency`, `/live-latency` | Provider choice, fallback behavior, server turn timing, browser p50/p95 timing |
|
|
69
69
|
| Can operators intervene safely? | live-ops routes, action center, ops action audit routes, operations record | Pause/resume/takeover, injected instructions, operator action audit trail |
|
|
70
70
|
| Can I run outbound campaigns? | `/voice/campaigns`, `/voice/campaigns/observability`, `/api/voice/campaigns/readiness-proof` | Recipient import evidence, consent/dedupe checks, scheduling policy, worker-safe attempts |
|
|
71
|
-
| Can I handle post-call workflow? | reviews, tasks, integration events, outcome contracts, operations record |
|
|
71
|
+
| Can I handle post-call workflow? | `createVoicePostCallAnalysisRoutes(...)`, reviews, tasks, integration events, outcome contracts, operations record | Extracted-field proof, task creation, webhook/sink delivery, matched session proof |
|
|
72
72
|
| Can I keep data in my infrastructure? | `/data-control`, `/data-control/audit.md`, retention dry-run/apply routes | Customer-owned storage, redaction, audit export, guarded deletion, zero-retention planning |
|
|
73
73
|
| Can I prove release readiness? | `/production-readiness`, `/ops-recovery`, delivery runtime, readiness profiles | Deploy gates for session health, audits, delivery queues, provider/campaign/phone proof |
|
|
74
74
|
|
|
@@ -82,6 +82,37 @@ For a demo, the fastest convincing path is:
|
|
|
82
82
|
|
|
83
83
|
If those five surfaces are green and linked, the buyer can see the core difference from Vapi-style hosted orchestration: the operational proof lives inside the app, not in a vendor dashboard.
|
|
84
84
|
|
|
85
|
+
## Post-Call Analysis Proof
|
|
86
|
+
|
|
87
|
+
Use `createVoicePostCallAnalysisRoutes(...)` when the hosted-platform feature you need is call analysis plus follow-up proof. It validates that required extracted fields exist, expected ops tasks were created, integration/webhook events delivered, and the report links back to `/voice-operations/:sessionId`.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { createVoicePostCallAnalysisRoutes } from '@absolutejs/voice';
|
|
91
|
+
|
|
92
|
+
app.use(
|
|
93
|
+
createVoicePostCallAnalysisRoutes({
|
|
94
|
+
path: '/api/voice/post-call-analysis',
|
|
95
|
+
operationRecordBasePath: '/voice-operations/:sessionId',
|
|
96
|
+
reviews: runtime.reviews,
|
|
97
|
+
tasks: runtime.tasks,
|
|
98
|
+
integrationEvents: runtime.events,
|
|
99
|
+
source: ({ reviewId, sessionId }) => ({
|
|
100
|
+
reviewId,
|
|
101
|
+
sessionId,
|
|
102
|
+
// Use your own extractor output here, for example fields persisted from an LLM/tool result.
|
|
103
|
+
extractedFields: loadExtractedPostCallFields(reviewId ?? sessionId)
|
|
104
|
+
}),
|
|
105
|
+
fields: [
|
|
106
|
+
{ path: 'review.postCall.target', label: 'customer target' },
|
|
107
|
+
{ path: 'customerId' },
|
|
108
|
+
{ path: 'category' }
|
|
109
|
+
],
|
|
110
|
+
requiredTaskKinds: ['support-triage'],
|
|
111
|
+
requireDeliveredIntegrationEvent: true
|
|
112
|
+
})
|
|
113
|
+
);
|
|
114
|
+
```
|
|
115
|
+
|
|
85
116
|
## Use-Case Recipe: Support Triage
|
|
86
117
|
|
|
87
118
|
Use this path when you want a Vapi-style support assistant that can answer web or phone calls, look up customer context, route billing issues to a specialist, create follow-up work, and leave one debuggable call record. It is a recipe over primitives, not a support app kit.
|
package/dist/index.d.ts
CHANGED
|
@@ -83,6 +83,7 @@ export { createVoiceCallReviewFromSession, recordVoiceRuntimeOps } from './runti
|
|
|
83
83
|
export { createVoiceOpsRuntime } from './opsRuntime';
|
|
84
84
|
export { resolveVoiceOpsPreset } from './opsPresets';
|
|
85
85
|
export { resolveVoiceOutcomeRecipe } from './outcomeRecipes';
|
|
86
|
+
export { buildVoicePostCallAnalysisReport, createVoicePostCallAnalysisRoutes, renderVoicePostCallAnalysisMarkdown } from './postCallAnalysis';
|
|
86
87
|
export { createId, createVoiceSessionRecord } from './store';
|
|
87
88
|
export { createVoiceSTTRoutingCorrectionHandler, resolveVoiceSTTRoutingStrategy } from './routing';
|
|
88
89
|
export { applyRiskTieredPhraseHintCorrections, applyPhraseHintCorrections, createDomainLexicon, createDomainPhraseHints, createPhraseHintCorrectionHandler, createRiskyTurnCorrectionHandler } from './correction';
|
|
@@ -135,6 +136,7 @@ export type { VoiceToolContractCase, VoiceToolContractCaseReport, VoiceToolContr
|
|
|
135
136
|
export type { VoiceOpsRuntime, VoiceOpsRuntimeConfig, VoiceOpsRuntimeSummary, VoiceOpsRuntimeSinkWorkerConfig, VoiceOpsRuntimeTaskWorkerConfig, VoiceOpsRuntimeTickResult, VoiceOpsRuntimeWebhookWorkerConfig } from './opsRuntime';
|
|
136
137
|
export type { VoiceOpsPresetName, VoiceOpsPresetOverrides, VoiceResolvedOpsPreset } from './opsPresets';
|
|
137
138
|
export type { VoiceOutcomeRecipe, VoiceOutcomeRecipeName, VoiceOutcomeRecipeOptions } from './outcomeRecipes';
|
|
139
|
+
export type { VoicePostCallAnalysisFieldRequirement, VoicePostCallAnalysisFieldResult, VoicePostCallAnalysisIssue, VoicePostCallAnalysisIssueCode, VoicePostCallAnalysisOptions, VoicePostCallAnalysisReport, VoicePostCallAnalysisRoutesOptions, VoicePostCallAnalysisStatus } from './postCallAnalysis';
|
|
138
140
|
export type { VoiceCRMActivitySinkOptions, VoiceHubSpotTaskSinkOptions, VoiceHubSpotTaskUpdateSinkOptions, VoiceHelpdeskTicketSinkOptions, VoiceIntegrationHTTPSinkOptions, VoiceIntegrationSink, VoiceIntegrationSinkDeliveryResult, VoiceLinearIssueSinkOptions, VoiceLinearIssueUpdateSinkOptions, VoiceZendeskTicketSinkOptions, VoiceZendeskTicketUpdateSinkOptions } from './opsSinks';
|
|
139
141
|
export type { VoiceOpsWebhookEnvelope, VoiceOpsWebhookEntity, VoiceOpsWebhookLinkResolver, VoiceOpsWebhookReceiverRoutesOptions, VoiceOpsWebhookSinkOptions, VoiceOpsWebhookVerificationResult } from './opsWebhook';
|
|
140
142
|
export type { VoiceHandoffDelivery, VoiceHandoffDeliveryRecord, VoiceHandoffDeliveryRecordInput, VoiceHandoffFanoutResult, VoiceQueuedHandoffDeliveryOptions, VoiceTwilioRedirectHandoffAdapterOptions, VoiceWebhookHandoffAdapterOptions } from './handoff';
|
package/dist/index.js
CHANGED
|
@@ -28727,6 +28727,210 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
|
|
|
28727
28727
|
taskPolicies: mergePolicies(preset.taskPolicies, overrides.taskPolicies)
|
|
28728
28728
|
};
|
|
28729
28729
|
};
|
|
28730
|
+
// src/postCallAnalysis.ts
|
|
28731
|
+
import { Elysia as Elysia49 } from "elysia";
|
|
28732
|
+
var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
|
|
28733
|
+
var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
|
|
28734
|
+
var getPathValue3 = (source, path) => {
|
|
28735
|
+
const parts = path.split(".").filter(Boolean);
|
|
28736
|
+
let current = source;
|
|
28737
|
+
for (const part of parts) {
|
|
28738
|
+
if (!current || typeof current !== "object" || Array.isArray(current)) {
|
|
28739
|
+
return;
|
|
28740
|
+
}
|
|
28741
|
+
current = current[part];
|
|
28742
|
+
}
|
|
28743
|
+
return current;
|
|
28744
|
+
};
|
|
28745
|
+
var hasValue2 = (value) => {
|
|
28746
|
+
if (value === undefined || value === null) {
|
|
28747
|
+
return false;
|
|
28748
|
+
}
|
|
28749
|
+
if (typeof value === "string") {
|
|
28750
|
+
return value.trim().length > 0;
|
|
28751
|
+
}
|
|
28752
|
+
if (Array.isArray(value)) {
|
|
28753
|
+
return value.length > 0;
|
|
28754
|
+
}
|
|
28755
|
+
return true;
|
|
28756
|
+
};
|
|
28757
|
+
var matchesReview = (reviewId, id) => Boolean(reviewId && id && (id === reviewId || id.startsWith(`${reviewId}:`)));
|
|
28758
|
+
var matchesSession = (sessionId, event) => {
|
|
28759
|
+
const payloadSessionId = event.payload.sessionId;
|
|
28760
|
+
return Boolean(sessionId && (event.id === sessionId || event.id.startsWith(`${sessionId}:`) || payloadSessionId === sessionId));
|
|
28761
|
+
};
|
|
28762
|
+
var matchesIntegrationEvent = (input) => {
|
|
28763
|
+
const payloadReviewId = input.event.payload.reviewId;
|
|
28764
|
+
return matchesReview(input.reviewId, input.event.id) || payloadReviewId === input.reviewId || matchesSession(input.sessionId, input.event);
|
|
28765
|
+
};
|
|
28766
|
+
var normalizeOperationRecordHref = (basePath, sessionId) => {
|
|
28767
|
+
if (!basePath || !sessionId) {
|
|
28768
|
+
return;
|
|
28769
|
+
}
|
|
28770
|
+
return basePath.includes(":sessionId") ? basePath.replace(":sessionId", encodeURIComponent(sessionId)) : `${basePath.replace(/\/$/, "")}/${encodeURIComponent(sessionId)}`;
|
|
28771
|
+
};
|
|
28772
|
+
var isPostCallAnalysisReport = (value) => ("status" in value) && ("summary" in value) && Array.isArray(value.issues);
|
|
28773
|
+
var buildVoicePostCallAnalysisReport = async (options = {}) => {
|
|
28774
|
+
const reviews = await asArray(options.reviews);
|
|
28775
|
+
const review = options.review ?? reviews.find((candidate) => options.reviewId ? candidate.id === options.reviewId : options.sessionId ? candidate.id.startsWith(`${options.sessionId}:`) : false);
|
|
28776
|
+
const reviewId = options.reviewId ?? review?.id;
|
|
28777
|
+
const sessionId = options.sessionId ?? (reviewId?.endsWith(":review") ? reviewId.slice(0, -":review".length) : undefined);
|
|
28778
|
+
const allTasks = await asArray(options.tasks);
|
|
28779
|
+
const tasks = allTasks.filter((task) => reviewId ? task.reviewId === reviewId || task.intakeId === reviewId || matchesReview(reviewId, task.id) : false);
|
|
28780
|
+
const allIntegrationEvents = await asArray(options.integrationEvents);
|
|
28781
|
+
const integrationEvents = allIntegrationEvents.filter((event) => matchesIntegrationEvent({ event, reviewId, sessionId }));
|
|
28782
|
+
const fieldSource = {
|
|
28783
|
+
extractedFields: options.extractedFields ?? {},
|
|
28784
|
+
review
|
|
28785
|
+
};
|
|
28786
|
+
const fields = (options.fields ?? []).map((field) => {
|
|
28787
|
+
const value = getPathValue3(fieldSource.extractedFields, field.path) ?? getPathValue3(fieldSource, field.path);
|
|
28788
|
+
const required = field.required !== false;
|
|
28789
|
+
return {
|
|
28790
|
+
label: field.label ?? field.path,
|
|
28791
|
+
ok: !required || hasValue2(value),
|
|
28792
|
+
path: field.path,
|
|
28793
|
+
required,
|
|
28794
|
+
value
|
|
28795
|
+
};
|
|
28796
|
+
});
|
|
28797
|
+
const requiredTaskKinds = options.requiredTaskKinds ?? [];
|
|
28798
|
+
const missingTaskKinds = requiredTaskKinds.filter((kind) => !tasks.some((task) => task.kind === kind));
|
|
28799
|
+
const deliveredIntegrationEvents = integrationEvents.filter((event) => event.deliveryStatus === "delivered").length;
|
|
28800
|
+
const failedIntegrationEvents = integrationEvents.filter((event) => event.deliveryStatus === "failed").length;
|
|
28801
|
+
const issues = [];
|
|
28802
|
+
if (!review) {
|
|
28803
|
+
issues.push({
|
|
28804
|
+
code: "voice.post_call_analysis.review_missing",
|
|
28805
|
+
label: "Review missing",
|
|
28806
|
+
severity: "fail"
|
|
28807
|
+
});
|
|
28808
|
+
} else if (review.summary.pass === false) {
|
|
28809
|
+
issues.push({
|
|
28810
|
+
code: "voice.post_call_analysis.review_failed",
|
|
28811
|
+
detail: review.errors.join("; ") || review.summary.outcome,
|
|
28812
|
+
label: "Review failed",
|
|
28813
|
+
severity: "fail"
|
|
28814
|
+
});
|
|
28815
|
+
}
|
|
28816
|
+
for (const field of fields) {
|
|
28817
|
+
if (field.required && !field.ok) {
|
|
28818
|
+
issues.push({
|
|
28819
|
+
code: "voice.post_call_analysis.required_field_missing",
|
|
28820
|
+
detail: field.path,
|
|
28821
|
+
label: `Missing ${field.label}`,
|
|
28822
|
+
severity: "fail"
|
|
28823
|
+
});
|
|
28824
|
+
}
|
|
28825
|
+
}
|
|
28826
|
+
for (const kind of missingTaskKinds) {
|
|
28827
|
+
issues.push({
|
|
28828
|
+
code: "voice.post_call_analysis.required_task_missing",
|
|
28829
|
+
detail: kind,
|
|
28830
|
+
label: `Missing ${kind} task`,
|
|
28831
|
+
severity: "fail"
|
|
28832
|
+
});
|
|
28833
|
+
}
|
|
28834
|
+
if (options.requireDeliveredIntegrationEvent && deliveredIntegrationEvents === 0) {
|
|
28835
|
+
issues.push({
|
|
28836
|
+
code: "voice.post_call_analysis.integration_missing",
|
|
28837
|
+
label: "Delivered integration event missing",
|
|
28838
|
+
severity: "fail"
|
|
28839
|
+
});
|
|
28840
|
+
}
|
|
28841
|
+
if (failedIntegrationEvents > 0) {
|
|
28842
|
+
issues.push({
|
|
28843
|
+
code: "voice.post_call_analysis.integration_failed",
|
|
28844
|
+
detail: `${failedIntegrationEvents} failed integration event(s)`,
|
|
28845
|
+
label: "Integration delivery failed",
|
|
28846
|
+
severity: "warn"
|
|
28847
|
+
});
|
|
28848
|
+
}
|
|
28849
|
+
const status = issues.some((issue) => issue.severity === "fail") ? "fail" : issues.length > 0 ? "warn" : "pass";
|
|
28850
|
+
return {
|
|
28851
|
+
checkedAt: options.at ?? Date.now(),
|
|
28852
|
+
fields,
|
|
28853
|
+
integrationEvents,
|
|
28854
|
+
issues,
|
|
28855
|
+
operationRecordHref: normalizeOperationRecordHref(options.operationRecordBasePath, sessionId),
|
|
28856
|
+
review,
|
|
28857
|
+
reviewId,
|
|
28858
|
+
sessionId,
|
|
28859
|
+
status,
|
|
28860
|
+
summary: {
|
|
28861
|
+
deliveredIntegrationEvents,
|
|
28862
|
+
failedIntegrationEvents,
|
|
28863
|
+
fields: fields.length,
|
|
28864
|
+
missingRequiredFields: fields.filter((field) => field.required && !field.ok).length,
|
|
28865
|
+
missingRequiredTasks: missingTaskKinds.length,
|
|
28866
|
+
requiredFields: fields.filter((field) => field.required).length,
|
|
28867
|
+
requiredTaskKinds: requiredTaskKinds.length,
|
|
28868
|
+
tasks: tasks.length
|
|
28869
|
+
},
|
|
28870
|
+
tasks
|
|
28871
|
+
};
|
|
28872
|
+
};
|
|
28873
|
+
var renderVoicePostCallAnalysisMarkdown = (report) => {
|
|
28874
|
+
const lines = [
|
|
28875
|
+
"# Voice Post-Call Analysis",
|
|
28876
|
+
"",
|
|
28877
|
+
`Status: ${report.status}`,
|
|
28878
|
+
`Checked: ${new Date(report.checkedAt).toISOString()}`,
|
|
28879
|
+
report.reviewId ? `Review: ${report.reviewId}` : undefined,
|
|
28880
|
+
report.sessionId ? `Session: ${report.sessionId}` : undefined,
|
|
28881
|
+
report.operationRecordHref ? `Operations record: ${report.operationRecordHref}` : undefined,
|
|
28882
|
+
"",
|
|
28883
|
+
"## Summary",
|
|
28884
|
+
`- Fields: ${report.summary.fields}`,
|
|
28885
|
+
`- Missing required fields: ${report.summary.missingRequiredFields}`,
|
|
28886
|
+
`- Tasks: ${report.summary.tasks}`,
|
|
28887
|
+
`- Missing required tasks: ${report.summary.missingRequiredTasks}`,
|
|
28888
|
+
`- Delivered integration events: ${report.summary.deliveredIntegrationEvents}`,
|
|
28889
|
+
`- Failed integration events: ${report.summary.failedIntegrationEvents}`,
|
|
28890
|
+
"",
|
|
28891
|
+
"## Issues",
|
|
28892
|
+
...report.issues.length ? report.issues.map((issue) => `- ${issue.severity}: ${issue.code} - ${issue.label}${issue.detail ? ` (${issue.detail})` : ""}`) : ["- none"]
|
|
28893
|
+
].filter((line) => line !== undefined);
|
|
28894
|
+
return `${lines.join(`
|
|
28895
|
+
`)}
|
|
28896
|
+
`;
|
|
28897
|
+
};
|
|
28898
|
+
var resolvePostCallAnalysisReport = async (options, input) => {
|
|
28899
|
+
const source = options.source === undefined ? options : typeof options.source === "function" ? await options.source(input) : options.source;
|
|
28900
|
+
const merged = {
|
|
28901
|
+
...options,
|
|
28902
|
+
...source,
|
|
28903
|
+
reviewId: input.reviewId ?? source.reviewId ?? options.reviewId,
|
|
28904
|
+
sessionId: input.sessionId ?? source.sessionId ?? options.sessionId
|
|
28905
|
+
};
|
|
28906
|
+
return isPostCallAnalysisReport(merged) ? merged : buildVoicePostCallAnalysisReport(merged);
|
|
28907
|
+
};
|
|
28908
|
+
var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
28909
|
+
const path = options.path ?? "/api/voice/post-call-analysis";
|
|
28910
|
+
const routes = new Elysia49({
|
|
28911
|
+
name: options.name ?? "absolutejs-voice-post-call-analysis"
|
|
28912
|
+
});
|
|
28913
|
+
routes.get(path, async ({ query }) => {
|
|
28914
|
+
const report = await resolvePostCallAnalysisReport(options, {
|
|
28915
|
+
reviewId: typeof query.reviewId === "string" ? query.reviewId : undefined,
|
|
28916
|
+
sessionId: typeof query.sessionId === "string" ? query.sessionId : undefined
|
|
28917
|
+
});
|
|
28918
|
+
return Response.json(report, { headers: options.headers });
|
|
28919
|
+
});
|
|
28920
|
+
routes.get(`${path}.md`, async ({ query }) => {
|
|
28921
|
+
const report = await resolvePostCallAnalysisReport(options, {
|
|
28922
|
+
reviewId: typeof query.reviewId === "string" ? query.reviewId : undefined,
|
|
28923
|
+
sessionId: typeof query.sessionId === "string" ? query.sessionId : undefined
|
|
28924
|
+
});
|
|
28925
|
+
return new Response(renderVoicePostCallAnalysisMarkdown(report), {
|
|
28926
|
+
headers: {
|
|
28927
|
+
"content-type": "text/markdown; charset=utf-8",
|
|
28928
|
+
...options.headers
|
|
28929
|
+
}
|
|
28930
|
+
});
|
|
28931
|
+
});
|
|
28932
|
+
return routes;
|
|
28933
|
+
};
|
|
28730
28934
|
// src/correction.ts
|
|
28731
28935
|
var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
28732
28936
|
var buildAliasMatcher = (alias) => new RegExp(`(?<![\\p{L}\\p{N}'])${escapeRegExp(alias)}(?![\\p{L}\\p{N}'])`, "giu");
|
|
@@ -29219,6 +29423,7 @@ export {
|
|
|
29219
29423
|
renderVoiceProviderContractMatrixHTML,
|
|
29220
29424
|
renderVoiceProviderCapabilityHTML,
|
|
29221
29425
|
renderVoiceProductionReadinessHTML,
|
|
29426
|
+
renderVoicePostCallAnalysisMarkdown,
|
|
29222
29427
|
renderVoicePhoneAgentProductionSmokeHTML,
|
|
29223
29428
|
renderVoiceOutcomeContractHTML,
|
|
29224
29429
|
renderVoiceOpsStatusHTML,
|
|
@@ -29414,6 +29619,7 @@ export {
|
|
|
29414
29619
|
createVoicePostgresCampaignStore,
|
|
29415
29620
|
createVoicePostgresAuditSinkDeliveryStore,
|
|
29416
29621
|
createVoicePostgresAuditEventStore,
|
|
29622
|
+
createVoicePostCallAnalysisRoutes,
|
|
29417
29623
|
createVoicePlivoCampaignDialer,
|
|
29418
29624
|
createVoicePlatformCoverageRoutes,
|
|
29419
29625
|
createVoicePhoneAgentProductionSmokeRoutes,
|
|
@@ -29570,6 +29776,7 @@ export {
|
|
|
29570
29776
|
buildVoiceProofTrendReport,
|
|
29571
29777
|
buildVoiceProductionReadinessReport,
|
|
29572
29778
|
buildVoiceProductionReadinessGate,
|
|
29779
|
+
buildVoicePostCallAnalysisReport,
|
|
29573
29780
|
buildVoicePlatformCoverageSummary,
|
|
29574
29781
|
buildVoiceOpsTaskFromSLABreach,
|
|
29575
29782
|
buildVoiceOpsTaskFromReview,
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Elysia } from 'elysia';
|
|
2
|
+
import type { StoredVoiceIntegrationEvent, StoredVoiceOpsTask, VoiceIntegrationEventStore, VoiceOpsTaskKind, VoiceOpsTaskStore } from './ops';
|
|
3
|
+
import type { StoredVoiceCallReviewArtifact, VoiceCallReviewStore } from './testing/review';
|
|
4
|
+
export type VoicePostCallAnalysisStatus = 'fail' | 'pass' | 'warn';
|
|
5
|
+
export type VoicePostCallAnalysisFieldRequirement = {
|
|
6
|
+
label?: string;
|
|
7
|
+
path: string;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type VoicePostCallAnalysisFieldResult = {
|
|
11
|
+
label: string;
|
|
12
|
+
ok: boolean;
|
|
13
|
+
path: string;
|
|
14
|
+
required: boolean;
|
|
15
|
+
value?: unknown;
|
|
16
|
+
};
|
|
17
|
+
export type VoicePostCallAnalysisIssueCode = 'voice.post_call_analysis.integration_failed' | 'voice.post_call_analysis.integration_missing' | 'voice.post_call_analysis.required_field_missing' | 'voice.post_call_analysis.required_task_missing' | 'voice.post_call_analysis.review_failed' | 'voice.post_call_analysis.review_missing';
|
|
18
|
+
export type VoicePostCallAnalysisIssue = {
|
|
19
|
+
code: VoicePostCallAnalysisIssueCode;
|
|
20
|
+
detail?: string;
|
|
21
|
+
label: string;
|
|
22
|
+
severity: Exclude<VoicePostCallAnalysisStatus, 'pass'>;
|
|
23
|
+
};
|
|
24
|
+
export type VoicePostCallAnalysisReport = {
|
|
25
|
+
checkedAt: number;
|
|
26
|
+
fields: VoicePostCallAnalysisFieldResult[];
|
|
27
|
+
integrationEvents: StoredVoiceIntegrationEvent[];
|
|
28
|
+
issues: VoicePostCallAnalysisIssue[];
|
|
29
|
+
operationRecordHref?: string;
|
|
30
|
+
review?: StoredVoiceCallReviewArtifact;
|
|
31
|
+
reviewId?: string;
|
|
32
|
+
sessionId?: string;
|
|
33
|
+
status: VoicePostCallAnalysisStatus;
|
|
34
|
+
summary: {
|
|
35
|
+
deliveredIntegrationEvents: number;
|
|
36
|
+
failedIntegrationEvents: number;
|
|
37
|
+
fields: number;
|
|
38
|
+
missingRequiredFields: number;
|
|
39
|
+
missingRequiredTasks: number;
|
|
40
|
+
requiredFields: number;
|
|
41
|
+
requiredTaskKinds: number;
|
|
42
|
+
tasks: number;
|
|
43
|
+
};
|
|
44
|
+
tasks: StoredVoiceOpsTask[];
|
|
45
|
+
};
|
|
46
|
+
export type VoicePostCallAnalysisOptions = {
|
|
47
|
+
at?: number;
|
|
48
|
+
extractedFields?: Record<string, unknown>;
|
|
49
|
+
fields?: VoicePostCallAnalysisFieldRequirement[];
|
|
50
|
+
integrationEvents?: StoredVoiceIntegrationEvent[] | VoiceIntegrationEventStore;
|
|
51
|
+
operationRecordBasePath?: string;
|
|
52
|
+
requireDeliveredIntegrationEvent?: boolean;
|
|
53
|
+
requiredTaskKinds?: VoiceOpsTaskKind[];
|
|
54
|
+
review?: StoredVoiceCallReviewArtifact;
|
|
55
|
+
reviewId?: string;
|
|
56
|
+
reviews?: StoredVoiceCallReviewArtifact[] | VoiceCallReviewStore;
|
|
57
|
+
sessionId?: string;
|
|
58
|
+
tasks?: StoredVoiceOpsTask[] | VoiceOpsTaskStore;
|
|
59
|
+
};
|
|
60
|
+
export type VoicePostCallAnalysisRoutesOptions = VoicePostCallAnalysisOptions & {
|
|
61
|
+
headers?: HeadersInit;
|
|
62
|
+
name?: string;
|
|
63
|
+
path?: string;
|
|
64
|
+
source?: ((input: {
|
|
65
|
+
reviewId?: string;
|
|
66
|
+
sessionId?: string;
|
|
67
|
+
}) => Promise<VoicePostCallAnalysisOptions | VoicePostCallAnalysisReport> | VoicePostCallAnalysisOptions | VoicePostCallAnalysisReport) | VoicePostCallAnalysisOptions | VoicePostCallAnalysisReport;
|
|
68
|
+
};
|
|
69
|
+
export declare const buildVoicePostCallAnalysisReport: (options?: VoicePostCallAnalysisOptions) => Promise<VoicePostCallAnalysisReport>;
|
|
70
|
+
export declare const renderVoicePostCallAnalysisMarkdown: (report: VoicePostCallAnalysisReport) => string;
|
|
71
|
+
export declare const createVoicePostCallAnalysisRoutes: (options?: VoicePostCallAnalysisRoutesOptions) => Elysia<"", {
|
|
72
|
+
decorator: {};
|
|
73
|
+
store: {};
|
|
74
|
+
derive: {};
|
|
75
|
+
resolve: {};
|
|
76
|
+
}, {
|
|
77
|
+
typebox: {};
|
|
78
|
+
error: {};
|
|
79
|
+
}, {
|
|
80
|
+
schema: {};
|
|
81
|
+
standaloneSchema: {};
|
|
82
|
+
macro: {};
|
|
83
|
+
macroFn: {};
|
|
84
|
+
parser: {};
|
|
85
|
+
response: {};
|
|
86
|
+
}, {}, {
|
|
87
|
+
derive: {};
|
|
88
|
+
resolve: {};
|
|
89
|
+
schema: {};
|
|
90
|
+
standaloneSchema: {};
|
|
91
|
+
response: {};
|
|
92
|
+
}, {
|
|
93
|
+
derive: {};
|
|
94
|
+
resolve: {};
|
|
95
|
+
schema: {};
|
|
96
|
+
standaloneSchema: {};
|
|
97
|
+
response: {};
|
|
98
|
+
}>;
|