@absolutejs/voice 0.0.22-beta.232 → 0.0.22-beta.234
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 +26 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +231 -0
- package/dist/observabilityExport.d.ts +71 -0
- package/dist/productionReadiness.d.ts +14 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2773,6 +2773,25 @@ console.log(voiceObservabilityExportSchemaId, voiceObservabilityExportSchemaVers
|
|
|
2773
2773
|
|
|
2774
2774
|
Use `validateVoiceObservabilityExportRecord(...)` or `assertVoiceObservabilityExportRecord(...)` when reading customer-owned records back from SQLite, Postgres, S3, a webhook collector, a warehouse, or a SIEM. The validator accepts manifests, artifact indexes, delivery reports, delivery receipts, delivery histories, and database payload records, then checks the stable schema id/version plus the minimum shape required for safe ingestion.
|
|
2775
2775
|
|
|
2776
|
+
Use `replayVoiceObservabilityExport(...)` when you need to prove an already-delivered evidence bundle is still usable:
|
|
2777
|
+
|
|
2778
|
+
```ts
|
|
2779
|
+
import { replayVoiceObservabilityExport } from '@absolutejs/voice';
|
|
2780
|
+
|
|
2781
|
+
const replay = await replayVoiceObservabilityExport({
|
|
2782
|
+
kind: 'sqlite',
|
|
2783
|
+
path: '.voice-runtime/observability-exports.sqlite',
|
|
2784
|
+
runId: '2026-04-29T17-20-51.032Z',
|
|
2785
|
+
tableName: 'voice_observability_exports'
|
|
2786
|
+
});
|
|
2787
|
+
|
|
2788
|
+
if (replay.status !== 'pass') {
|
|
2789
|
+
console.error(replay.issues);
|
|
2790
|
+
}
|
|
2791
|
+
```
|
|
2792
|
+
|
|
2793
|
+
Replay sources support supplied records plus file, S3, SQLite, and Postgres delivery targets. The replay report re-validates the manifest/index/database payload, counts artifacts and delivery destinations, flags failed artifacts or destinations, and gives a readiness-style `pass`, `warn`, or `fail` result for customer-owned evidence pipelines.
|
|
2794
|
+
|
|
2776
2795
|
```ts
|
|
2777
2796
|
import {
|
|
2778
2797
|
buildVoiceObservabilityExport,
|
|
@@ -2876,12 +2895,18 @@ app.use(
|
|
|
2876
2895
|
maxAgeMs: 60 * 60 * 1000,
|
|
2877
2896
|
store: observabilityExportDeliveryReceipts
|
|
2878
2897
|
},
|
|
2898
|
+
observabilityExportReplay: {
|
|
2899
|
+
kind: 'sqlite',
|
|
2900
|
+
path: '.voice-runtime/observability-exports.sqlite',
|
|
2901
|
+
runId: 'latest-proof-pack',
|
|
2902
|
+
tableName: 'voice_observability_exports'
|
|
2903
|
+
},
|
|
2879
2904
|
store: runtimeStorage.traces
|
|
2880
2905
|
})
|
|
2881
2906
|
);
|
|
2882
2907
|
```
|
|
2883
2908
|
|
|
2884
|
-
Readiness adds `Observability export` and `Observability export
|
|
2909
|
+
Readiness adds `Observability export`, `Observability export delivery`, and `Observability export replay` checks. Failed export manifests fail the deploy gate, delivery receipt history can fail or warn when no successful delivery exists or the latest success is older than your configured freshness window, and replay health can fail the gate when customer-owned evidence cannot be read back cleanly from file, S3, SQLite, or Postgres.
|
|
2885
2910
|
|
|
2886
2911
|
## Production Voice Ops
|
|
2887
2912
|
|
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 { assertVoiceObservabilityExportRecord, buildVoiceObservabilityArtifactIndex, buildVoiceObservabilityExportDeliveryHistory, buildVoiceObservabilityExport, assertVoiceObservabilityExportSchema, createVoiceObservabilityExportSchema, createVoiceFileObservabilityExportDeliveryReceiptStore, createVoiceMemoryObservabilityExportDeliveryReceiptStore, createVoiceObservabilityExportRoutes, deliverVoiceObservabilityExport, renderVoiceObservabilityExportMarkdown, validateVoiceObservabilityExportRecord, voiceObservabilityExportSchemaId, voiceObservabilityExportSchemaVersion } from './observabilityExport';
|
|
56
|
+
export { assertVoiceObservabilityExportRecord, buildVoiceObservabilityArtifactIndex, buildVoiceObservabilityExportDeliveryHistory, buildVoiceObservabilityExportReplayReport, buildVoiceObservabilityExport, assertVoiceObservabilityExportSchema, createVoiceObservabilityExportSchema, createVoiceFileObservabilityExportDeliveryReceiptStore, createVoiceMemoryObservabilityExportDeliveryReceiptStore, createVoiceObservabilityExportRoutes, deliverVoiceObservabilityExport, loadVoiceObservabilityExportReplaySource, replayVoiceObservabilityExport, renderVoiceObservabilityExportMarkdown, validateVoiceObservabilityExportRecord, voiceObservabilityExportSchemaId, voiceObservabilityExportSchemaVersion } 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, VoiceObservabilityExportArtifactChecksum, VoiceObservabilityExportArtifactFreshness, VoiceObservabilityExportArtifactIndex, VoiceObservabilityExportArtifactIndexItem, VoiceObservabilityExportArtifactKind, VoiceObservabilityExportDeliverySummary, VoiceObservabilityExportDeliveryDestination, VoiceObservabilityExportDeliveryDestinationResult, VoiceObservabilityExportDeliveryHistory, VoiceObservabilityExportDeliveryOptions, VoiceObservabilityExportDeliveryReceipt, VoiceObservabilityExportDeliveryReceiptStore, VoiceObservabilityExportDeliveryReport, VoiceObservabilityExportEnvelope, VoiceObservabilityExportIssue, VoiceObservabilityExportIssueCode, VoiceObservabilityExportOptions, VoiceObservabilityExportIngestedRecordKind, VoiceObservabilityExportRedactionSummary, VoiceObservabilityExportRecordValidationOptions, VoiceObservabilityExportReport, VoiceObservabilityExportRoutesOptions, VoiceObservabilityExportSchema, VoiceObservabilityExportStatus, VoiceObservabilityExportValidationIssue, VoiceObservabilityExportValidationResult } from './observabilityExport';
|
|
121
|
+
export type { VoiceObservabilityExportArtifact, VoiceObservabilityExportArtifactChecksum, VoiceObservabilityExportArtifactFreshness, VoiceObservabilityExportArtifactIndex, VoiceObservabilityExportArtifactIndexItem, VoiceObservabilityExportArtifactKind, VoiceObservabilityExportDeliverySummary, VoiceObservabilityExportDeliveryDestination, VoiceObservabilityExportDeliveryDestinationResult, VoiceObservabilityExportDeliveryHistory, VoiceObservabilityExportDeliveryOptions, VoiceObservabilityExportDeliveryReceipt, VoiceObservabilityExportDeliveryReceiptStore, VoiceObservabilityExportDeliveryReport, VoiceObservabilityExportEnvelope, VoiceObservabilityExportIssue, VoiceObservabilityExportIssueCode, VoiceObservabilityExportOptions, VoiceObservabilityExportIngestedRecordKind, VoiceObservabilityExportRedactionSummary, VoiceObservabilityExportRecordValidationOptions, VoiceObservabilityExportReplayIssue, VoiceObservabilityExportReplayIssueCode, VoiceObservabilityExportReplayRecords, VoiceObservabilityExportReplayReport, VoiceObservabilityExportReplaySource, VoiceObservabilityExportReport, VoiceObservabilityExportRoutesOptions, VoiceObservabilityExportSchema, VoiceObservabilityExportStatus, VoiceObservabilityExportValidationIssue, VoiceObservabilityExportValidationResult } 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
|
@@ -23309,6 +23309,10 @@ var writeS3Object = async (input) => {
|
|
|
23309
23309
|
type: input.contentType
|
|
23310
23310
|
});
|
|
23311
23311
|
};
|
|
23312
|
+
var readS3ObjectText = async (input) => {
|
|
23313
|
+
const file = input.client.file(input.key, input.options);
|
|
23314
|
+
return await file.text();
|
|
23315
|
+
};
|
|
23312
23316
|
var quoteObservabilityIdentifier = (value) => `"${value.replace(/"/g, '""')}"`;
|
|
23313
23317
|
var normalizeObservabilityIdentifier = (value) => value?.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice_observability_exports";
|
|
23314
23318
|
var buildObservabilityExportDatabaseRecord = (input) => ({
|
|
@@ -23321,6 +23325,190 @@ var buildObservabilityExportDatabaseRecord = (input) => ({
|
|
|
23321
23325
|
schema: input.report.schema,
|
|
23322
23326
|
status: input.report.status
|
|
23323
23327
|
});
|
|
23328
|
+
var parseObservabilityExportJson = (value) => typeof value === "string" ? JSON.parse(value) : value;
|
|
23329
|
+
var collectReplayDeliveryDestinations = (value) => {
|
|
23330
|
+
if (!isRecord2(value)) {
|
|
23331
|
+
return [];
|
|
23332
|
+
}
|
|
23333
|
+
if (Array.isArray(value.destinations)) {
|
|
23334
|
+
return value.destinations.filter((destination) => isRecord2(destination));
|
|
23335
|
+
}
|
|
23336
|
+
if (Array.isArray(value.receipts)) {
|
|
23337
|
+
return value.receipts.flatMap((receipt) => collectReplayDeliveryDestinations(receipt));
|
|
23338
|
+
}
|
|
23339
|
+
return [];
|
|
23340
|
+
};
|
|
23341
|
+
var replayIssueSeverity = (status) => status === "fail" ? "fail" : "warn";
|
|
23342
|
+
var buildVoiceObservabilityExportReplayReport = (records) => {
|
|
23343
|
+
const manifest = records.manifest ?? (isRecord2(records.databaseRecord) ? records.databaseRecord.manifest : undefined);
|
|
23344
|
+
const artifactIndex = records.artifactIndex ?? (isRecord2(records.databaseRecord) ? records.databaseRecord.artifactIndex : undefined);
|
|
23345
|
+
const validations = {
|
|
23346
|
+
artifactIndex: validateVoiceObservabilityExportRecord(artifactIndex, {
|
|
23347
|
+
kind: "artifact-index"
|
|
23348
|
+
}),
|
|
23349
|
+
databaseRecord: records.databaseRecord ? validateVoiceObservabilityExportRecord(records.databaseRecord, {
|
|
23350
|
+
kind: "database-record"
|
|
23351
|
+
}) : undefined,
|
|
23352
|
+
deliveryHistory: records.deliveryHistory ? validateVoiceObservabilityExportRecord(records.deliveryHistory, {
|
|
23353
|
+
kind: "delivery-history"
|
|
23354
|
+
}) : undefined,
|
|
23355
|
+
deliveryReceipt: records.deliveryReceipt ? validateVoiceObservabilityExportRecord(records.deliveryReceipt, {
|
|
23356
|
+
kind: "delivery-receipt"
|
|
23357
|
+
}) : undefined,
|
|
23358
|
+
deliveryReport: records.deliveryReport ? validateVoiceObservabilityExportRecord(records.deliveryReport, {
|
|
23359
|
+
kind: "delivery-report"
|
|
23360
|
+
}) : undefined,
|
|
23361
|
+
manifest: validateVoiceObservabilityExportRecord(manifest, {
|
|
23362
|
+
kind: "manifest"
|
|
23363
|
+
})
|
|
23364
|
+
};
|
|
23365
|
+
const validationIssues = Object.entries(validations).flatMap(([kind, result]) => result?.issues.map((issue) => ({
|
|
23366
|
+
kind,
|
|
23367
|
+
issue
|
|
23368
|
+
})) ?? []);
|
|
23369
|
+
const manifestRecord = isRecord2(manifest) ? manifest : undefined;
|
|
23370
|
+
const artifactIndexRecord = isRecord2(artifactIndex) ? artifactIndex : undefined;
|
|
23371
|
+
const artifacts = [
|
|
23372
|
+
...Array.isArray(manifestRecord?.artifacts) ? manifestRecord.artifacts : [],
|
|
23373
|
+
...Array.isArray(artifactIndexRecord?.artifacts) ? artifactIndexRecord.artifacts : []
|
|
23374
|
+
].filter((artifact) => isRecord2(artifact));
|
|
23375
|
+
const failedArtifacts = artifacts.filter((artifact) => artifact.status === "fail");
|
|
23376
|
+
const deliveryDestinations = [
|
|
23377
|
+
...collectReplayDeliveryDestinations(records.deliveryReport),
|
|
23378
|
+
...collectReplayDeliveryDestinations(records.deliveryReceipt),
|
|
23379
|
+
...collectReplayDeliveryDestinations(records.deliveryHistory)
|
|
23380
|
+
];
|
|
23381
|
+
const failedDeliveryDestinations = deliveryDestinations.filter((destination) => destination.status === "failed");
|
|
23382
|
+
const issues = [
|
|
23383
|
+
...!records.manifest && !isRecord2(records.databaseRecord) ? [
|
|
23384
|
+
{
|
|
23385
|
+
code: "voice.observability.export_replay.missing_record",
|
|
23386
|
+
label: "Export manifest",
|
|
23387
|
+
severity: "fail",
|
|
23388
|
+
value: "manifest"
|
|
23389
|
+
}
|
|
23390
|
+
] : [],
|
|
23391
|
+
...!records.artifactIndex && !isRecord2(records.databaseRecord) ? [
|
|
23392
|
+
{
|
|
23393
|
+
code: "voice.observability.export_replay.missing_record",
|
|
23394
|
+
label: "Artifact index",
|
|
23395
|
+
severity: "fail",
|
|
23396
|
+
value: "artifact-index"
|
|
23397
|
+
}
|
|
23398
|
+
] : [],
|
|
23399
|
+
...validationIssues.map(({ kind, issue }) => ({
|
|
23400
|
+
code: "voice.observability.export_replay.validation_failed",
|
|
23401
|
+
detail: issue.message,
|
|
23402
|
+
label: `Invalid ${kind}`,
|
|
23403
|
+
severity: "fail",
|
|
23404
|
+
value: issue.path
|
|
23405
|
+
})),
|
|
23406
|
+
...manifestRecord && (manifestRecord.status === "fail" || manifestRecord.status === "warn") ? [
|
|
23407
|
+
{
|
|
23408
|
+
code: "voice.observability.export_replay.export_failed",
|
|
23409
|
+
label: "Export manifest status",
|
|
23410
|
+
severity: replayIssueSeverity(manifestRecord.status),
|
|
23411
|
+
value: manifestRecord.status
|
|
23412
|
+
}
|
|
23413
|
+
] : [],
|
|
23414
|
+
...failedArtifacts.map((artifact) => ({
|
|
23415
|
+
code: "voice.observability.export_replay.artifact_failed",
|
|
23416
|
+
label: "Export artifact status",
|
|
23417
|
+
severity: "fail",
|
|
23418
|
+
value: artifact.id
|
|
23419
|
+
})),
|
|
23420
|
+
...failedDeliveryDestinations.map((destination) => ({
|
|
23421
|
+
code: "voice.observability.export_replay.delivery_failed",
|
|
23422
|
+
label: "Export delivery destination",
|
|
23423
|
+
severity: "fail",
|
|
23424
|
+
value: destination.destinationId
|
|
23425
|
+
}))
|
|
23426
|
+
];
|
|
23427
|
+
return {
|
|
23428
|
+
checkedAt: Date.now(),
|
|
23429
|
+
issues,
|
|
23430
|
+
records: validations,
|
|
23431
|
+
status: issues.some((issue) => issue.severity === "fail") ? "fail" : issues.some((issue) => issue.severity === "warn") ? "warn" : "pass",
|
|
23432
|
+
summary: {
|
|
23433
|
+
artifacts: new Set(artifacts.map((artifact) => artifact.id)).size,
|
|
23434
|
+
deliveryDestinations: deliveryDestinations.length,
|
|
23435
|
+
failedArtifacts: failedArtifacts.length,
|
|
23436
|
+
failedDeliveryDestinations: failedDeliveryDestinations.length,
|
|
23437
|
+
validationIssues: validationIssues.length
|
|
23438
|
+
}
|
|
23439
|
+
};
|
|
23440
|
+
};
|
|
23441
|
+
var loadVoiceObservabilityExportReplaySource = async (source) => {
|
|
23442
|
+
if (source.kind === "records") {
|
|
23443
|
+
return source;
|
|
23444
|
+
}
|
|
23445
|
+
if (source.kind === "file") {
|
|
23446
|
+
const root = join3(source.directory, source.runId);
|
|
23447
|
+
const receiptPath = source.receiptDirectory ? join3(source.receiptDirectory, `${encodeURIComponent(deliveryReceiptId(source.runId))}.json`) : undefined;
|
|
23448
|
+
const deliveryReceipt = receiptPath ? await Bun.file(receiptPath).text().then(JSON.parse).catch(() => {
|
|
23449
|
+
return;
|
|
23450
|
+
}) : undefined;
|
|
23451
|
+
return {
|
|
23452
|
+
artifactIndex: JSON.parse(await Bun.file(join3(root, "artifact-index.json")).text()),
|
|
23453
|
+
deliveryReceipt,
|
|
23454
|
+
manifest: JSON.parse(await Bun.file(join3(root, "manifest.json")).text())
|
|
23455
|
+
};
|
|
23456
|
+
}
|
|
23457
|
+
if (source.kind === "s3") {
|
|
23458
|
+
const client = source.client ?? new Bun.S3Client(source);
|
|
23459
|
+
const s3Options = source;
|
|
23460
|
+
const rootKey = joinS3Key(normalizeExportS3KeyPrefix(source.keyPrefix), source.runId);
|
|
23461
|
+
return {
|
|
23462
|
+
artifactIndex: JSON.parse(await readS3ObjectText({
|
|
23463
|
+
client,
|
|
23464
|
+
key: joinS3Key(rootKey, "artifact-index.json"),
|
|
23465
|
+
options: s3Options
|
|
23466
|
+
})),
|
|
23467
|
+
manifest: JSON.parse(await readS3ObjectText({
|
|
23468
|
+
client,
|
|
23469
|
+
key: joinS3Key(rootKey, "manifest.json"),
|
|
23470
|
+
options: s3Options
|
|
23471
|
+
}))
|
|
23472
|
+
};
|
|
23473
|
+
}
|
|
23474
|
+
if (source.kind === "sqlite") {
|
|
23475
|
+
if (!source.database && !source.path) {
|
|
23476
|
+
throw new Error("SQLite observability export replay requires source.database or source.path.");
|
|
23477
|
+
}
|
|
23478
|
+
const database = source.database ?? new Database(source.path, { create: false });
|
|
23479
|
+
const table2 = quoteObservabilityIdentifier(normalizeObservabilityIdentifier(source.tableName));
|
|
23480
|
+
const row2 = database.query(`SELECT manifest_json, artifact_index_json, payload_json FROM ${table2} WHERE run_id = $runId`).get({ $runId: source.runId });
|
|
23481
|
+
if (!row2) {
|
|
23482
|
+
throw new Error(`No observability export found for run ${source.runId}.`);
|
|
23483
|
+
}
|
|
23484
|
+
return {
|
|
23485
|
+
artifactIndex: parseObservabilityExportJson(row2.artifact_index_json),
|
|
23486
|
+
databaseRecord: parseObservabilityExportJson(row2.payload_json),
|
|
23487
|
+
manifest: parseObservabilityExportJson(row2.manifest_json)
|
|
23488
|
+
};
|
|
23489
|
+
}
|
|
23490
|
+
const sql = source.sql ?? (source.connectionString ? (() => {
|
|
23491
|
+
const client = new Bun.SQL(source.connectionString);
|
|
23492
|
+
return { unsafe: client.unsafe.bind(client) };
|
|
23493
|
+
})() : undefined);
|
|
23494
|
+
if (!sql) {
|
|
23495
|
+
throw new Error("Postgres observability export replay requires source.sql or source.connectionString.");
|
|
23496
|
+
}
|
|
23497
|
+
const schema = normalizeObservabilityIdentifier(source.schemaName ?? "public");
|
|
23498
|
+
const table = normalizeObservabilityIdentifier(source.tableName);
|
|
23499
|
+
const qualifiedTable = `${quoteObservabilityIdentifier(schema)}.${quoteObservabilityIdentifier(table)}`;
|
|
23500
|
+
const rows = await sql.unsafe(`SELECT manifest_json, artifact_index_json, payload FROM ${qualifiedTable} WHERE run_id = $1`, [source.runId]);
|
|
23501
|
+
const row = rows[0];
|
|
23502
|
+
if (!row) {
|
|
23503
|
+
throw new Error(`No observability export found for run ${source.runId}.`);
|
|
23504
|
+
}
|
|
23505
|
+
return {
|
|
23506
|
+
artifactIndex: parseObservabilityExportJson(row.artifact_index_json),
|
|
23507
|
+
databaseRecord: parseObservabilityExportJson(row.payload),
|
|
23508
|
+
manifest: parseObservabilityExportJson(row.manifest_json)
|
|
23509
|
+
};
|
|
23510
|
+
};
|
|
23511
|
+
var replayVoiceObservabilityExport = async (source) => buildVoiceObservabilityExportReplayReport(await loadVoiceObservabilityExportReplaySource(source));
|
|
23324
23512
|
var deliverObservabilityExportToSQLite = async (input) => {
|
|
23325
23513
|
if (!input.destination.database && !input.destination.path) {
|
|
23326
23514
|
throw new Error("SQLite observability export delivery requires destination.database or destination.path.");
|
|
@@ -24121,6 +24309,7 @@ var readinessGateCodes = {
|
|
|
24121
24309
|
"Operator action history": "voice.readiness.operator_action_history",
|
|
24122
24310
|
"Ops recovery": "voice.readiness.ops_recovery",
|
|
24123
24311
|
"Observability export delivery": "voice.readiness.observability_export_delivery",
|
|
24312
|
+
"Observability export replay": "voice.readiness.observability_export_replay",
|
|
24124
24313
|
"Phone agent production smoke": "voice.readiness.phone_agent_smoke",
|
|
24125
24314
|
"Provider contract matrix": "voice.readiness.provider_contract_matrix",
|
|
24126
24315
|
"Provider fallback recovery": "voice.readiness.provider_fallback_recovery",
|
|
@@ -24429,6 +24618,14 @@ var resolveObservabilityExportDeliveryHistory = async (options, input) => {
|
|
|
24429
24618
|
}
|
|
24430
24619
|
return;
|
|
24431
24620
|
};
|
|
24621
|
+
var isVoiceObservabilityExportReplayReport = (value) => typeof value.checkedAt === "number" && Array.isArray(value.issues) && typeof value.status === "string" && ("summary" in value);
|
|
24622
|
+
var resolveObservabilityExportReplay = async (options, input) => {
|
|
24623
|
+
if (!options.observabilityExportReplay) {
|
|
24624
|
+
return;
|
|
24625
|
+
}
|
|
24626
|
+
const source = typeof options.observabilityExportReplay === "function" ? await options.observabilityExportReplay(input) : options.observabilityExportReplay;
|
|
24627
|
+
return isVoiceObservabilityExportReplayReport(source) ? source : replayVoiceObservabilityExport(source);
|
|
24628
|
+
};
|
|
24432
24629
|
var summarizeTraceDeliveries = async (options) => {
|
|
24433
24630
|
if (!options.traceDeliveries) {
|
|
24434
24631
|
return;
|
|
@@ -24589,6 +24786,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
24589
24786
|
opsRecovery,
|
|
24590
24787
|
observabilityExport,
|
|
24591
24788
|
observabilityExportDeliveryHistory,
|
|
24789
|
+
observabilityExportReplay,
|
|
24592
24790
|
proofSources
|
|
24593
24791
|
] = await Promise.all([
|
|
24594
24792
|
evaluateVoiceQuality({ events }),
|
|
@@ -24626,6 +24824,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
24626
24824
|
resolveOpsRecovery(options, { query, request }),
|
|
24627
24825
|
resolveObservabilityExport(options, { query, request }),
|
|
24628
24826
|
resolveObservabilityExportDeliveryHistory(options, { query, request }),
|
|
24827
|
+
resolveObservabilityExportReplay(options, { query, request }),
|
|
24629
24828
|
resolveProofSources(options, { query, request })
|
|
24630
24829
|
]);
|
|
24631
24830
|
const deliveryRuntime = summarizeDeliveryRuntime(deliveryRuntimeSummary);
|
|
@@ -24868,6 +25067,15 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
24868
25067
|
totalDestinations: observabilityExportDeliveryHistory.history.summary.totalDestinations
|
|
24869
25068
|
};
|
|
24870
25069
|
})() : undefined;
|
|
25070
|
+
const observabilityExportReplaySummary = observabilityExportReplay ? {
|
|
25071
|
+
artifacts: observabilityExportReplay.summary.artifacts,
|
|
25072
|
+
deliveryDestinations: observabilityExportReplay.summary.deliveryDestinations,
|
|
25073
|
+
failedArtifacts: observabilityExportReplay.summary.failedArtifacts,
|
|
25074
|
+
failedDeliveryDestinations: observabilityExportReplay.summary.failedDeliveryDestinations,
|
|
25075
|
+
issues: observabilityExportReplay.issues.length,
|
|
25076
|
+
status: observabilityExportReplay.status,
|
|
25077
|
+
validationIssues: observabilityExportReplay.summary.validationIssues
|
|
25078
|
+
} : undefined;
|
|
24871
25079
|
if (agentSquadContractSummary) {
|
|
24872
25080
|
checks.push({
|
|
24873
25081
|
detail: agentSquadContractSummary.status === "pass" ? `${agentSquadContractSummary.passed} agent squad contract(s) are passing.` : agentSquadContractSummary.total === 0 ? "No agent squad contracts are configured." : `${agentSquadContractSummary.failed} agent squad contract(s) failed.`,
|
|
@@ -24964,6 +25172,25 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
24964
25172
|
]
|
|
24965
25173
|
});
|
|
24966
25174
|
}
|
|
25175
|
+
if (observabilityExportReplaySummary && observabilityExportReplay) {
|
|
25176
|
+
const firstIssue = observabilityExportReplay.issues[0];
|
|
25177
|
+
const href = options.links?.observabilityExportDeliveries ?? options.links?.observabilityExport ?? "/api/voice/observability-export/deliveries";
|
|
25178
|
+
checks.push({
|
|
25179
|
+
detail: observabilityExportReplaySummary.status === "pass" ? `${observabilityExportReplaySummary.artifacts} exported artifact(s) and ${observabilityExportReplaySummary.deliveryDestinations} delivery destination(s) replay from customer-owned evidence.` : firstIssue?.detail ?? `${observabilityExportReplaySummary.issues} observability export replay issue(s) need review.`,
|
|
25180
|
+
href,
|
|
25181
|
+
label: "Observability export replay",
|
|
25182
|
+
proofSource: proofSource("observabilityExportReplay", "observabilityExportDeliveryHistory", "observability"),
|
|
25183
|
+
status: observabilityExportReplaySummary.status,
|
|
25184
|
+
value: `${observabilityExportReplaySummary.validationIssues} validation issue(s)`,
|
|
25185
|
+
actions: observabilityExportReplaySummary.status === "pass" ? [] : [
|
|
25186
|
+
{
|
|
25187
|
+
description: "Replay the customer-owned observability export from file, S3, SQLite, or Postgres and inspect validation, artifact, or delivery failures.",
|
|
25188
|
+
href,
|
|
25189
|
+
label: "Open export replay evidence"
|
|
25190
|
+
}
|
|
25191
|
+
]
|
|
25192
|
+
});
|
|
25193
|
+
}
|
|
24967
25194
|
if (providerStack) {
|
|
24968
25195
|
const missingLanes = providerStack.gaps.filter((gap) => gap.status !== "pass");
|
|
24969
25196
|
checks.push({
|
|
@@ -25227,6 +25454,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
25227
25454
|
} : undefined,
|
|
25228
25455
|
observabilityExport: observabilityExportSummary,
|
|
25229
25456
|
observabilityExportDeliveryHistory: observabilityExportDeliveryHistorySummary,
|
|
25457
|
+
observabilityExportReplay: observabilityExportReplaySummary,
|
|
25230
25458
|
providers: {
|
|
25231
25459
|
degraded: degradedProviders,
|
|
25232
25460
|
total: providers.length
|
|
@@ -28791,6 +29019,7 @@ export {
|
|
|
28791
29019
|
resolveTurnDetectionConfig,
|
|
28792
29020
|
resolveAudioConditioningConfig,
|
|
28793
29021
|
requeueVoiceOpsTask,
|
|
29022
|
+
replayVoiceObservabilityExport,
|
|
28794
29023
|
reopenVoiceOpsTask,
|
|
28795
29024
|
renderVoiceTurnQualityHTML,
|
|
28796
29025
|
renderVoiceTurnLatencyHTML,
|
|
@@ -28865,6 +29094,7 @@ export {
|
|
|
28865
29094
|
parseVoiceTelephonyWebhookEvent,
|
|
28866
29095
|
matchesVoiceOpsTaskAssignmentRule,
|
|
28867
29096
|
markVoiceOpsTaskSLABreached,
|
|
29097
|
+
loadVoiceObservabilityExportReplaySource,
|
|
28868
29098
|
listVoiceRoutingEvents,
|
|
28869
29099
|
listVoiceOpsTasks,
|
|
28870
29100
|
isVoiceOpsTaskOverdue,
|
|
@@ -29163,6 +29393,7 @@ export {
|
|
|
29163
29393
|
buildVoiceOpsConsoleReport,
|
|
29164
29394
|
buildVoiceOpsActionHistoryReport,
|
|
29165
29395
|
buildVoiceOperationsRecord,
|
|
29396
|
+
buildVoiceObservabilityExportReplayReport,
|
|
29166
29397
|
buildVoiceObservabilityExportDeliveryHistory,
|
|
29167
29398
|
buildVoiceObservabilityExport,
|
|
29168
29399
|
buildVoiceObservabilityArtifactIndex,
|
|
@@ -233,6 +233,74 @@ export type VoiceObservabilityExportDeliveryHistory = {
|
|
|
233
233
|
totalDestinations: number;
|
|
234
234
|
};
|
|
235
235
|
};
|
|
236
|
+
export type VoiceObservabilityExportReplayIssueCode = 'voice.observability.export_replay.artifact_failed' | 'voice.observability.export_replay.delivery_failed' | 'voice.observability.export_replay.export_failed' | 'voice.observability.export_replay.missing_record' | 'voice.observability.export_replay.validation_failed';
|
|
237
|
+
export type VoiceObservabilityExportReplayIssue = {
|
|
238
|
+
code: VoiceObservabilityExportReplayIssueCode;
|
|
239
|
+
detail?: string;
|
|
240
|
+
label: string;
|
|
241
|
+
severity: Exclude<VoiceObservabilityExportStatus, 'pass'>;
|
|
242
|
+
value?: number | string;
|
|
243
|
+
};
|
|
244
|
+
export type VoiceObservabilityExportReplayRecords = {
|
|
245
|
+
artifactIndex?: unknown;
|
|
246
|
+
databaseRecord?: unknown;
|
|
247
|
+
deliveryHistory?: unknown;
|
|
248
|
+
deliveryReceipt?: unknown;
|
|
249
|
+
deliveryReport?: unknown;
|
|
250
|
+
manifest?: unknown;
|
|
251
|
+
};
|
|
252
|
+
export type VoiceObservabilityExportReplayReport = {
|
|
253
|
+
checkedAt: number;
|
|
254
|
+
issues: VoiceObservabilityExportReplayIssue[];
|
|
255
|
+
records: {
|
|
256
|
+
artifactIndex: VoiceObservabilityExportValidationResult;
|
|
257
|
+
databaseRecord?: VoiceObservabilityExportValidationResult;
|
|
258
|
+
deliveryHistory?: VoiceObservabilityExportValidationResult;
|
|
259
|
+
deliveryReceipt?: VoiceObservabilityExportValidationResult;
|
|
260
|
+
deliveryReport?: VoiceObservabilityExportValidationResult;
|
|
261
|
+
manifest: VoiceObservabilityExportValidationResult;
|
|
262
|
+
};
|
|
263
|
+
status: VoiceObservabilityExportStatus;
|
|
264
|
+
summary: {
|
|
265
|
+
artifacts: number;
|
|
266
|
+
deliveryDestinations: number;
|
|
267
|
+
failedArtifacts: number;
|
|
268
|
+
failedDeliveryDestinations: number;
|
|
269
|
+
validationIssues: number;
|
|
270
|
+
};
|
|
271
|
+
};
|
|
272
|
+
export type VoiceObservabilityExportReplaySource = {
|
|
273
|
+
artifactIndex?: unknown;
|
|
274
|
+
databaseRecord?: unknown;
|
|
275
|
+
deliveryHistory?: unknown;
|
|
276
|
+
deliveryReceipt?: unknown;
|
|
277
|
+
deliveryReport?: unknown;
|
|
278
|
+
kind: 'records';
|
|
279
|
+
manifest?: unknown;
|
|
280
|
+
} | {
|
|
281
|
+
directory: string;
|
|
282
|
+
kind: 'file';
|
|
283
|
+
receiptDirectory?: string;
|
|
284
|
+
runId: string;
|
|
285
|
+
} | (S3Options & {
|
|
286
|
+
client?: Pick<S3Client, 'file'>;
|
|
287
|
+
keyPrefix?: string;
|
|
288
|
+
kind: 's3';
|
|
289
|
+
runId: string;
|
|
290
|
+
}) | {
|
|
291
|
+
database?: Database;
|
|
292
|
+
kind: 'sqlite';
|
|
293
|
+
path?: string;
|
|
294
|
+
runId: string;
|
|
295
|
+
tableName?: string;
|
|
296
|
+
} | {
|
|
297
|
+
connectionString?: string;
|
|
298
|
+
kind: 'postgres';
|
|
299
|
+
runId: string;
|
|
300
|
+
schemaName?: string;
|
|
301
|
+
sql?: VoicePostgresClient;
|
|
302
|
+
tableName?: string;
|
|
303
|
+
};
|
|
236
304
|
export type VoiceObservabilityExportDeliveryOptions = {
|
|
237
305
|
destinations: VoiceObservabilityExportDeliveryDestination[];
|
|
238
306
|
report: VoiceObservabilityExportReport;
|
|
@@ -276,6 +344,9 @@ export type VoiceObservabilityExportRoutesOptions = VoiceObservabilityExportOpti
|
|
|
276
344
|
render?: (report: VoiceObservabilityExportReport) => string | Promise<string>;
|
|
277
345
|
title?: string;
|
|
278
346
|
};
|
|
347
|
+
export declare const buildVoiceObservabilityExportReplayReport: (records: VoiceObservabilityExportReplayRecords) => VoiceObservabilityExportReplayReport;
|
|
348
|
+
export declare const loadVoiceObservabilityExportReplaySource: (source: VoiceObservabilityExportReplaySource) => Promise<VoiceObservabilityExportReplayRecords>;
|
|
349
|
+
export declare const replayVoiceObservabilityExport: (source: VoiceObservabilityExportReplaySource) => Promise<VoiceObservabilityExportReplayReport>;
|
|
279
350
|
export declare const createVoiceMemoryObservabilityExportDeliveryReceiptStore: () => VoiceObservabilityExportDeliveryReceiptStore;
|
|
280
351
|
export declare const createVoiceFileObservabilityExportDeliveryReceiptStore: (options: {
|
|
281
352
|
directory: string;
|
|
@@ -15,7 +15,7 @@ import type { VoiceProviderContractMatrixReport, VoiceProviderStackCapabilityGap
|
|
|
15
15
|
import { type VoiceProviderSloReport, type VoiceProviderSloReportOptions } from './providerSlo';
|
|
16
16
|
import type { VoiceCampaignReadinessProofReport } from './campaign';
|
|
17
17
|
import { type VoiceOpsRecoveryReport } from './opsRecovery';
|
|
18
|
-
import { type VoiceObservabilityExportDeliveryHistory, type VoiceObservabilityExportDeliveryReceiptStore, type VoiceObservabilityExportReport } from './observabilityExport';
|
|
18
|
+
import { type VoiceObservabilityExportDeliveryHistory, type VoiceObservabilityExportDeliveryReceiptStore, type VoiceObservabilityExportReplayReport, type VoiceObservabilityExportReplaySource, type VoiceObservabilityExportReport } from './observabilityExport';
|
|
19
19
|
export type VoiceProductionReadinessObservabilityExportDeliveryHistoryOptions = {
|
|
20
20
|
failOnMissing?: boolean;
|
|
21
21
|
failOnStale?: boolean;
|
|
@@ -181,6 +181,15 @@ export type VoiceProductionReadinessReport = {
|
|
|
181
181
|
status: VoiceProductionReadinessStatus;
|
|
182
182
|
totalDestinations: number;
|
|
183
183
|
};
|
|
184
|
+
observabilityExportReplay?: {
|
|
185
|
+
artifacts: number;
|
|
186
|
+
deliveryDestinations: number;
|
|
187
|
+
failedArtifacts: number;
|
|
188
|
+
failedDeliveryDestinations: number;
|
|
189
|
+
issues: number;
|
|
190
|
+
status: VoiceProductionReadinessStatus;
|
|
191
|
+
validationIssues: number;
|
|
192
|
+
};
|
|
184
193
|
providers: {
|
|
185
194
|
degraded: number;
|
|
186
195
|
total: number;
|
|
@@ -372,6 +381,10 @@ export type VoiceProductionReadinessRoutesOptions = {
|
|
|
372
381
|
query: Record<string, unknown>;
|
|
373
382
|
request: Request;
|
|
374
383
|
}) => Promise<VoiceObservabilityExportDeliveryHistory | VoiceObservabilityExportDeliveryReceiptStore | VoiceProductionReadinessObservabilityExportDeliveryHistoryOptions> | VoiceObservabilityExportDeliveryHistory | VoiceObservabilityExportDeliveryReceiptStore | VoiceProductionReadinessObservabilityExportDeliveryHistoryOptions);
|
|
384
|
+
observabilityExportReplay?: false | VoiceObservabilityExportReplayReport | VoiceObservabilityExportReplaySource | ((input: {
|
|
385
|
+
query: Record<string, unknown>;
|
|
386
|
+
request: Request;
|
|
387
|
+
}) => Promise<VoiceObservabilityExportReplayReport | VoiceObservabilityExportReplaySource> | VoiceObservabilityExportReplayReport | VoiceObservabilityExportReplaySource);
|
|
375
388
|
path?: string;
|
|
376
389
|
phoneAgentSmokes?: false | readonly VoicePhoneAgentProductionSmokeReport[] | ((input: {
|
|
377
390
|
query: Record<string, unknown>;
|