@absolutejs/voice 0.0.22-beta.221 → 0.0.22-beta.222
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 +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +101 -2
- package/dist/observabilityExport.d.ts +31 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2791,7 +2791,7 @@ const exportReport = await buildVoiceObservabilityExport({
|
|
|
2791
2791
|
});
|
|
2792
2792
|
```
|
|
2793
2793
|
|
|
2794
|
-
The route helper exposes JSON at `/api/voice/observability-export`, Markdown at `/voice/observability-export.md`, and HTML at `/voice/observability-export`. Path-backed artifacts are hashed with SHA-256 by default, include byte size and freshness metadata, and can fail the export when required evidence is missing or stale. Failed trace/audit deliveries fail the export report, pending deliveries warn, and every trace/audit envelope includes the linked operations-record URL when one is configured. This is the primitive to use when customers ask how voice evidence leaves the app without going through a hosted vendor dashboard.
|
|
2794
|
+
The route helper exposes JSON at `/api/voice/observability-export`, an artifact index at `/api/voice/observability-export/artifacts`, per-artifact downloads at `/api/voice/observability-export/artifacts/:artifactId`, Markdown at `/voice/observability-export.md`, and HTML at `/voice/observability-export`. Path-backed artifacts are hashed with SHA-256 by default, include byte size and freshness metadata, and can fail the export when required evidence is missing or stale. Failed trace/audit deliveries fail the export report, pending deliveries warn, and every trace/audit envelope includes the linked operations-record URL when one is configured. This is the primitive to use when customers ask how voice evidence leaves the app without going through a hosted vendor dashboard.
|
|
2795
2795
|
|
|
2796
2796
|
Pass the same report into production readiness when export health should block deploys:
|
|
2797
2797
|
|
package/dist/index.d.ts
CHANGED
|
@@ -53,7 +53,7 @@ export { createVoiceReadinessProfile, recommendVoiceReadinessProfile } from './r
|
|
|
53
53
|
export { buildVoiceProviderContractMatrix, createVoiceProviderContractMatrixHTMLHandler, createVoiceProviderContractMatrixJSONHandler, createVoiceProviderContractMatrixPreset, createVoiceProviderContractMatrixRoutes, evaluateVoiceProviderStackGaps, renderVoiceProviderContractMatrixHTML, recommendVoiceProviderStack } from './providerStackRecommendations';
|
|
54
54
|
export { buildVoiceOpsConsoleReport, createVoiceOpsConsoleRoutes, renderVoiceOpsConsoleHTML } from './opsConsoleRoutes';
|
|
55
55
|
export { buildVoiceOperationsRecord, createVoiceOperationsRecordRoutes, renderVoiceOperationsRecordHTML, renderVoiceOperationsRecordIncidentMarkdown } from './operationsRecord';
|
|
56
|
-
export { buildVoiceObservabilityExport, createVoiceObservabilityExportRoutes, renderVoiceObservabilityExportMarkdown } from './observabilityExport';
|
|
56
|
+
export { buildVoiceObservabilityArtifactIndex, buildVoiceObservabilityExport, createVoiceObservabilityExportRoutes, renderVoiceObservabilityExportMarkdown } from './observabilityExport';
|
|
57
57
|
export { buildVoiceOpsRecoveryReadinessCheck, buildVoiceOpsRecoveryReport, createVoiceOpsRecoveryRoutes, renderVoiceOpsRecoveryHTML, renderVoiceOpsRecoveryMarkdown } from './opsRecovery';
|
|
58
58
|
export { buildVoiceIncidentBundle, createStoredVoiceIncidentBundleArtifact, createVoiceIncidentBundleRoutes, createVoiceMemoryIncidentBundleStore, pruneVoiceIncidentBundleArtifacts, saveVoiceIncidentBundleArtifact } from './incidentBundle';
|
|
59
59
|
export { summarizeVoiceOpsStatus } from './opsStatus';
|
|
@@ -118,7 +118,7 @@ export type { VoiceProductionReadinessAction, VoiceProductionReadinessAuditOptio
|
|
|
118
118
|
export type { VoiceReadinessProfileName, VoiceReadinessProfileOptions, VoiceReadinessProfileRecommendation, VoiceReadinessProfileRecommendationScore, VoiceReadinessProfileRoutesOptions } from './readinessProfiles';
|
|
119
119
|
export type { VoiceProviderStackChoice, VoiceProviderStackCapabilities, VoiceProviderStackCapabilityGap, VoiceProviderStackCapabilityGapInput, VoiceProviderStackCapabilityGapReport, VoiceProviderContractCheck, VoiceProviderContractCheckStatus, VoiceProviderContractDefinition, VoiceProviderContractMatrixHandlerOptions, VoiceProviderContractMatrixHTMLHandlerOptions, VoiceProviderContractMatrixInput, VoiceProviderContractMatrixPresetOptions, VoiceProviderContractMatrixReport, VoiceProviderContractMatrixRoutesOptions, VoiceProviderContractMatrixRow, VoiceProviderStackInput, VoiceProviderStackKind, VoiceProviderStackRecommendation } from './providerStackRecommendations';
|
|
120
120
|
export type { VoiceOperationsRecord, VoiceOperationsRecordAgentHandoff, VoiceOperationsRecordAuditSummary, VoiceOperationsRecordIntegrationEventSummary, VoiceOperationsRecordOptions, VoiceOperationsRecordOutcome, VoiceOperationsRecordProviderDecision, VoiceOperationsRecordReviewSummary, VoiceOperationsRecordRoutesOptions, VoiceOperationsRecordStatus, VoiceOperationsRecordTaskSummary, VoiceOperationsRecordTranscriptTurn, VoiceOperationsRecordTool } from './operationsRecord';
|
|
121
|
-
export type { VoiceObservabilityExportArtifact, VoiceObservabilityExportArtifactKind, VoiceObservabilityExportDeliverySummary, VoiceObservabilityExportEnvelope, VoiceObservabilityExportIssue, VoiceObservabilityExportIssueCode, VoiceObservabilityExportOptions, VoiceObservabilityExportRedactionSummary, VoiceObservabilityExportReport, VoiceObservabilityExportRoutesOptions, VoiceObservabilityExportStatus } from './observabilityExport';
|
|
121
|
+
export type { VoiceObservabilityExportArtifact, VoiceObservabilityExportArtifactChecksum, VoiceObservabilityExportArtifactFreshness, VoiceObservabilityExportArtifactIndex, VoiceObservabilityExportArtifactIndexItem, VoiceObservabilityExportArtifactKind, VoiceObservabilityExportDeliverySummary, VoiceObservabilityExportEnvelope, VoiceObservabilityExportIssue, VoiceObservabilityExportIssueCode, VoiceObservabilityExportOptions, VoiceObservabilityExportRedactionSummary, VoiceObservabilityExportReport, VoiceObservabilityExportRoutesOptions, VoiceObservabilityExportStatus } from './observabilityExport';
|
|
122
122
|
export type { VoiceOpsRecoveryFailedSession, VoiceOpsRecoveryInterventionSummary, VoiceOpsRecoveryIssue, VoiceOpsRecoveryIssueCode, VoiceOpsRecoveryLinks, VoiceOpsRecoveryProviderSummary, VoiceOpsRecoveryReport, VoiceOpsRecoveryReportOptions, VoiceOpsRecoveryRoutesOptions, VoiceOpsRecoveryStatus } from './opsRecovery';
|
|
123
123
|
export type { StoredVoiceIncidentBundleArtifact, VoiceIncidentBundle, VoiceIncidentBundleArtifactOptions, VoiceIncidentBundleFormat, VoiceIncidentBundleOptions, VoiceIncidentBundleRetentionOptions, VoiceIncidentBundleRetentionReport, VoiceIncidentBundleRoutesOptions, VoiceIncidentBundleStore, VoiceIncidentBundleStoreFilter, VoiceIncidentBundleSummary } from './incidentBundle';
|
|
124
124
|
export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds } from './qualityRoutes';
|
package/dist/index.js
CHANGED
|
@@ -24982,6 +24982,36 @@ var checksumFile = async (path) => {
|
|
|
24982
24982
|
const buffer = await readFile2(path);
|
|
24983
24983
|
return createHash("sha256").update(buffer).digest("hex");
|
|
24984
24984
|
};
|
|
24985
|
+
var inferContentType = (artifact) => {
|
|
24986
|
+
if (artifact.contentType) {
|
|
24987
|
+
return artifact.contentType;
|
|
24988
|
+
}
|
|
24989
|
+
const path = artifact.path ? stripArtifactPathAnchor(artifact.path) : "";
|
|
24990
|
+
if (path.endsWith(".json")) {
|
|
24991
|
+
return "application/json; charset=utf-8";
|
|
24992
|
+
}
|
|
24993
|
+
if (path.endsWith(".md") || path.endsWith(".markdown")) {
|
|
24994
|
+
return "text/markdown; charset=utf-8";
|
|
24995
|
+
}
|
|
24996
|
+
if (path.endsWith(".html")) {
|
|
24997
|
+
return "text/html; charset=utf-8";
|
|
24998
|
+
}
|
|
24999
|
+
if (path.endsWith(".png")) {
|
|
25000
|
+
return "image/png";
|
|
25001
|
+
}
|
|
25002
|
+
if (path.endsWith(".jpg") || path.endsWith(".jpeg")) {
|
|
25003
|
+
return "image/jpeg";
|
|
25004
|
+
}
|
|
25005
|
+
if (path.endsWith(".txt") || path.endsWith(".log")) {
|
|
25006
|
+
return "text/plain; charset=utf-8";
|
|
25007
|
+
}
|
|
25008
|
+
return "application/octet-stream";
|
|
25009
|
+
};
|
|
25010
|
+
var addArtifactDownloadHrefs = (artifacts, links) => artifacts.map((artifact) => ({
|
|
25011
|
+
...artifact,
|
|
25012
|
+
contentType: artifact.contentType ?? inferContentType(artifact),
|
|
25013
|
+
downloadHref: artifact.downloadHref ?? (artifact.path ? links?.artifactDownload?.(artifact) : undefined)
|
|
25014
|
+
}));
|
|
24985
25015
|
var verifyArtifact = async (artifact, options) => {
|
|
24986
25016
|
const now = options.now ?? Date.now();
|
|
24987
25017
|
const maxAgeMs = artifact.maxAgeMs ?? options.maxAgeMs;
|
|
@@ -25171,7 +25201,7 @@ var buildVoiceObservabilityExport = async (options = {}) => {
|
|
|
25171
25201
|
const traceDeliverySummary = traceDeliveries ? await summarizeVoiceTraceSinkDeliveries(traceDeliveries) : undefined;
|
|
25172
25202
|
const auditDeliverySummary = auditDeliveries ? await summarizeVoiceAuditSinkDeliveries(auditDeliveries) : undefined;
|
|
25173
25203
|
const operationArtifacts = operationsRecords.map((record) => createOperationArtifact(record, options.links?.operationsRecord?.(record.sessionId)));
|
|
25174
|
-
const artifacts = await verifyArtifacts([...operationArtifacts, ...options.artifacts ?? []], options.artifactIntegrity);
|
|
25204
|
+
const artifacts = addArtifactDownloadHrefs(await verifyArtifacts([...operationArtifacts, ...options.artifacts ?? []], options.artifactIntegrity), options.links);
|
|
25175
25205
|
const operationHrefBySessionId = new Map(sessionIds.map((sessionId) => [
|
|
25176
25206
|
sessionId,
|
|
25177
25207
|
options.links?.operationsRecord?.(sessionId)
|
|
@@ -25252,19 +25282,87 @@ ${artifacts}
|
|
|
25252
25282
|
${issues}
|
|
25253
25283
|
`;
|
|
25254
25284
|
};
|
|
25285
|
+
var buildVoiceObservabilityArtifactIndex = (report) => {
|
|
25286
|
+
const artifacts = report.artifacts.map((artifact) => ({
|
|
25287
|
+
bytes: artifact.bytes,
|
|
25288
|
+
checksum: artifact.checksum,
|
|
25289
|
+
contentType: artifact.contentType,
|
|
25290
|
+
downloadHref: artifact.downloadHref,
|
|
25291
|
+
freshness: artifact.freshness,
|
|
25292
|
+
href: artifact.href,
|
|
25293
|
+
id: artifact.id,
|
|
25294
|
+
kind: artifact.kind,
|
|
25295
|
+
label: artifact.label,
|
|
25296
|
+
required: artifact.required,
|
|
25297
|
+
sessionId: artifact.sessionId,
|
|
25298
|
+
status: artifact.status
|
|
25299
|
+
}));
|
|
25300
|
+
return {
|
|
25301
|
+
artifacts,
|
|
25302
|
+
checkedAt: report.checkedAt,
|
|
25303
|
+
status: report.status,
|
|
25304
|
+
summary: {
|
|
25305
|
+
downloadable: artifacts.filter((artifact) => artifact.downloadHref).length,
|
|
25306
|
+
failed: artifacts.filter((artifact) => artifact.status === "fail").length,
|
|
25307
|
+
required: artifacts.filter((artifact) => artifact.required).length,
|
|
25308
|
+
total: artifacts.length,
|
|
25309
|
+
warn: artifacts.filter((artifact) => artifact.status === "warn").length
|
|
25310
|
+
}
|
|
25311
|
+
};
|
|
25312
|
+
};
|
|
25255
25313
|
var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
25256
25314
|
const path = options.path ?? "/api/voice/observability-export";
|
|
25315
|
+
const artifactIndexPath = options.artifactIndexPath ?? `${path}/artifacts`;
|
|
25316
|
+
const artifactDownloadPath = options.artifactDownloadPath ?? `${path}/artifacts`;
|
|
25257
25317
|
const markdownPath = options.markdownPath ?? "/voice/observability-export.md";
|
|
25258
25318
|
const htmlPath = options.htmlPath ?? "/voice/observability-export";
|
|
25259
25319
|
const headers = {
|
|
25260
25320
|
"cache-control": "no-store",
|
|
25261
25321
|
...options.headers ?? {}
|
|
25262
25322
|
};
|
|
25263
|
-
const buildReport = () => buildVoiceObservabilityExport(
|
|
25323
|
+
const buildReport = () => buildVoiceObservabilityExport({
|
|
25324
|
+
...options,
|
|
25325
|
+
links: {
|
|
25326
|
+
...options.links,
|
|
25327
|
+
artifactDownload: options.links?.artifactDownload ?? (artifactDownloadPath ? (artifact) => `${artifactDownloadPath}/${encodeURIComponent(artifact.id)}` : undefined)
|
|
25328
|
+
}
|
|
25329
|
+
});
|
|
25264
25330
|
const app = new Elysia42({
|
|
25265
25331
|
name: options.name ?? "absolute-voice-observability-export"
|
|
25266
25332
|
});
|
|
25267
25333
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
25334
|
+
if (artifactIndexPath !== false) {
|
|
25335
|
+
app.get(artifactIndexPath, async () => Response.json(buildVoiceObservabilityArtifactIndex(await buildReport()), { headers }));
|
|
25336
|
+
}
|
|
25337
|
+
if (artifactDownloadPath !== false) {
|
|
25338
|
+
app.get(`${artifactDownloadPath}/:artifactId`, async ({ params }) => {
|
|
25339
|
+
const artifactId = decodeURIComponent(params.artifactId);
|
|
25340
|
+
const report = await buildReport();
|
|
25341
|
+
const artifact = report.artifacts.find((item) => item.id === artifactId);
|
|
25342
|
+
if (!artifact?.path) {
|
|
25343
|
+
return Response.json({ error: "Artifact is not downloadable.", artifactId }, { headers, status: 404 });
|
|
25344
|
+
}
|
|
25345
|
+
try {
|
|
25346
|
+
const body = await readFile2(stripArtifactPathAnchor(artifact.path));
|
|
25347
|
+
return new Response(body, {
|
|
25348
|
+
headers: {
|
|
25349
|
+
...headers,
|
|
25350
|
+
"content-disposition": `attachment; filename="${encodeURIComponent(artifact.id)}"`,
|
|
25351
|
+
"content-type": artifact.contentType ?? inferContentType(artifact),
|
|
25352
|
+
...artifact.checksum ? {
|
|
25353
|
+
"x-absolute-voice-artifact-sha256": artifact.checksum.value
|
|
25354
|
+
} : {},
|
|
25355
|
+
"x-absolute-voice-artifact-id": artifact.id,
|
|
25356
|
+
...artifact.freshness ? {
|
|
25357
|
+
"x-absolute-voice-artifact-freshness": artifact.freshness.status
|
|
25358
|
+
} : {}
|
|
25359
|
+
}
|
|
25360
|
+
});
|
|
25361
|
+
} catch {
|
|
25362
|
+
return Response.json({ error: "Artifact file is not available.", artifactId }, { headers, status: 404 });
|
|
25363
|
+
}
|
|
25364
|
+
});
|
|
25365
|
+
}
|
|
25268
25366
|
if (markdownPath !== false) {
|
|
25269
25367
|
app.get(markdownPath, async () => {
|
|
25270
25368
|
const report = await buildReport();
|
|
@@ -28291,6 +28389,7 @@ export {
|
|
|
28291
28389
|
buildVoiceOpsActionHistoryReport,
|
|
28292
28390
|
buildVoiceOperationsRecord,
|
|
28293
28391
|
buildVoiceObservabilityExport,
|
|
28392
|
+
buildVoiceObservabilityArtifactIndex,
|
|
28294
28393
|
buildVoiceLiveOpsControlState,
|
|
28295
28394
|
buildVoiceLatencySLOGate,
|
|
28296
28395
|
buildVoiceIncidentBundle,
|
|
@@ -21,6 +21,7 @@ export type VoiceObservabilityExportArtifact = {
|
|
|
21
21
|
bytes?: number;
|
|
22
22
|
checksum?: VoiceObservabilityExportArtifactChecksum;
|
|
23
23
|
contentType?: string;
|
|
24
|
+
downloadHref?: string;
|
|
24
25
|
freshness?: VoiceObservabilityExportArtifactFreshness;
|
|
25
26
|
generatedAt?: number | string;
|
|
26
27
|
href?: string;
|
|
@@ -80,6 +81,32 @@ export type VoiceObservabilityExportReport = {
|
|
|
80
81
|
traceEvents: number;
|
|
81
82
|
};
|
|
82
83
|
};
|
|
84
|
+
export type VoiceObservabilityExportArtifactIndexItem = {
|
|
85
|
+
bytes?: number;
|
|
86
|
+
checksum?: VoiceObservabilityExportArtifactChecksum;
|
|
87
|
+
contentType?: string;
|
|
88
|
+
downloadHref?: string;
|
|
89
|
+
freshness?: VoiceObservabilityExportArtifactFreshness;
|
|
90
|
+
href?: string;
|
|
91
|
+
id: string;
|
|
92
|
+
kind: VoiceObservabilityExportArtifactKind;
|
|
93
|
+
label: string;
|
|
94
|
+
required?: boolean;
|
|
95
|
+
sessionId?: string;
|
|
96
|
+
status?: VoiceObservabilityExportStatus;
|
|
97
|
+
};
|
|
98
|
+
export type VoiceObservabilityExportArtifactIndex = {
|
|
99
|
+
artifacts: VoiceObservabilityExportArtifactIndexItem[];
|
|
100
|
+
checkedAt: number;
|
|
101
|
+
status: VoiceObservabilityExportStatus;
|
|
102
|
+
summary: {
|
|
103
|
+
downloadable: number;
|
|
104
|
+
failed: number;
|
|
105
|
+
required: number;
|
|
106
|
+
total: number;
|
|
107
|
+
warn: number;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
83
110
|
export type VoiceObservabilityExportOptions = {
|
|
84
111
|
artifacts?: VoiceObservabilityExportArtifact[];
|
|
85
112
|
artifactIntegrity?: {
|
|
@@ -94,6 +121,7 @@ export type VoiceObservabilityExportOptions = {
|
|
|
94
121
|
events?: StoredVoiceTraceEvent[];
|
|
95
122
|
includeOperationsRecords?: boolean;
|
|
96
123
|
links?: {
|
|
124
|
+
artifactDownload?: (artifact: VoiceObservabilityExportArtifact) => string;
|
|
97
125
|
operationsRecord?: (sessionId: string) => string;
|
|
98
126
|
};
|
|
99
127
|
operationsRecords?: VoiceOperationsRecord[];
|
|
@@ -104,6 +132,8 @@ export type VoiceObservabilityExportOptions = {
|
|
|
104
132
|
};
|
|
105
133
|
export type VoiceObservabilityExportRoutesOptions = VoiceObservabilityExportOptions & {
|
|
106
134
|
headers?: HeadersInit;
|
|
135
|
+
artifactDownloadPath?: false | string;
|
|
136
|
+
artifactIndexPath?: false | string;
|
|
107
137
|
htmlPath?: false | string;
|
|
108
138
|
markdownPath?: false | string;
|
|
109
139
|
name?: string;
|
|
@@ -115,6 +145,7 @@ export declare const buildVoiceObservabilityExport: (options?: VoiceObservabilit
|
|
|
115
145
|
export declare const renderVoiceObservabilityExportMarkdown: (report: VoiceObservabilityExportReport, options?: {
|
|
116
146
|
title?: string;
|
|
117
147
|
}) => string;
|
|
148
|
+
export declare const buildVoiceObservabilityArtifactIndex: (report: VoiceObservabilityExportReport) => VoiceObservabilityExportArtifactIndex;
|
|
118
149
|
export declare const createVoiceObservabilityExportRoutes: (options?: VoiceObservabilityExportRoutesOptions) => Elysia<"", {
|
|
119
150
|
decorator: {};
|
|
120
151
|
store: {};
|