@absolutejs/voice 0.0.22-beta.451 → 0.0.22-beta.453

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.
@@ -3430,6 +3430,7 @@ var readString = (value) => typeof value === "string" && value.trim() ? value :
3430
3430
  var readNumber2 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
3431
3431
  var readProofTrendMaxLiveP95 = (report) => report.summary.maxLiveP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.liveLatency?.p95Ms));
3432
3432
  var readProofTrendMaxProviderP95 = (report) => report.summary.maxProviderP95Ms ?? maxNumber((report.summary.providers ?? []).map((provider) => provider.p95Ms)) ?? maxNumber(report.cycles.flatMap((cycle) => (cycle.providers ?? []).map((provider) => provider.p95Ms)));
3433
+ var readProofTrendMaxReconnectP95 = (report) => report.summary.maxReconnectP95Ms ?? report.summary.reconnect?.resumeLatencyP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.reconnect?.resumeLatencyP95Ms));
3433
3434
  var readProofTrendMaxTurnP95 = (report) => report.summary.maxTurnP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.turnLatency?.p95Ms));
3434
3435
  var readRuntimeChannelMetric = (report, key) => {
3435
3436
  const summaryValue = report.summary.runtimeChannel?.[key];
@@ -3491,6 +3492,42 @@ var aggregateProofTrendRuntimeChannel = (channels) => {
3491
3492
  status: channels.some((channel) => channel.status === "fail") ? "fail" : channels.some((channel) => channel.status === "warn") ? "warn" : channels.every((channel) => channel.status === "pass") ? "pass" : undefined
3492
3493
  };
3493
3494
  };
3495
+ var aggregateProofTrendReconnect = (reconnects) => {
3496
+ if (reconnects.length === 0) {
3497
+ return;
3498
+ }
3499
+ const hasFailure = reconnects.some((reconnect) => reconnect.status === "fail" || reconnect.exhausted === true || reconnect.reconnected === false || reconnect.resumed === false);
3500
+ return {
3501
+ attempts: maxNumber(reconnects.map((reconnect) => reconnect.attempts)),
3502
+ exhausted: reconnects.some((reconnect) => reconnect.exhausted === true),
3503
+ maxAttempts: maxNumber(reconnects.map((reconnect) => reconnect.maxAttempts)),
3504
+ resumeLatencyP95Ms: maxNumber(reconnects.map((reconnect) => reconnect.resumeLatencyP95Ms)),
3505
+ reconnected: reconnects.some((reconnect) => reconnect.reconnected === true),
3506
+ resumed: reconnects.some((reconnect) => reconnect.resumed === true),
3507
+ samples: reconnects.reduce((total, reconnect) => total + (reconnect.samples ?? 0), 0),
3508
+ snapshotCount: reconnects.reduce((total, reconnect) => total + (reconnect.snapshotCount ?? 0), 0),
3509
+ status: hasFailure ? "fail" : reconnects.some((reconnect) => reconnect.status === "warn") ? "warn" : "pass"
3510
+ };
3511
+ };
3512
+ var summarizeReconnectTraceEvidence = (events) => {
3513
+ const reconnectEvents = events.filter((event) => event.type === "client.reconnect");
3514
+ if (reconnectEvents.length === 0) {
3515
+ return;
3516
+ }
3517
+ const statuses = reconnectEvents.map((event) => readString(readTraceRecord(event).status)).filter((status) => status !== undefined);
3518
+ const reconnectPayloads = reconnectEvents.map((event) => readTraceRecord(event));
3519
+ return {
3520
+ attempts: maxNumber(reconnectPayloads.map((payload) => readNumber2(payload.attempts))),
3521
+ exhausted: statuses.includes("exhausted"),
3522
+ maxAttempts: maxNumber(reconnectPayloads.map((payload) => readNumber2(payload.maxAttempts))),
3523
+ resumeLatencyP95Ms: percentile(reconnectPayloads.map((payload) => readNumber2(payload.resumeLatencyP95Ms) ?? readNumber2(payload.resumeLatencyMs)).filter((value) => value !== undefined), 95),
3524
+ reconnected: statuses.includes("reconnecting"),
3525
+ resumed: statuses.includes("resumed") || statuses.includes("pass"),
3526
+ samples: reconnectEvents.length,
3527
+ snapshotCount: reconnectEvents.length,
3528
+ status: reconnectEvents.some((event) => isFailingTraceStatus(readTraceStatus(readTraceRecord(event)))) ? "fail" : "pass"
3529
+ };
3530
+ };
3494
3531
  var readTraceRecord = (event) => event.payload;
3495
3532
  var readTraceProfileId = (events, options) => {
3496
3533
  for (const event of events) {
@@ -3638,6 +3675,7 @@ var buildVoiceRealCallProfileEvidenceFromTraceEvents = (events, options = {}) =>
3638
3675
  }).filter((value) => value !== undefined);
3639
3676
  const turnP95Ms = summarizeTurnTraceP95(sessionEvents);
3640
3677
  const providerP95Ms = maxNumber(providers.map((provider) => provider.p95Ms));
3678
+ const reconnect = summarizeReconnectTraceEvidence(sessionEvents);
3641
3679
  const runtimeChannel = summarizeRuntimeChannelTraceEvidence(sessionEvents);
3642
3680
  const surfaces = readRealCallProfileTraceSurfaces(sessionEvents);
3643
3681
  if (providers.length === 0 && runtimeChannel === undefined && liveLatencies.length === 0 && surfaces.length === 0) {
@@ -3653,6 +3691,7 @@ var buildVoiceRealCallProfileEvidenceFromTraceEvents = (events, options = {}) =>
3653
3691
  profileLabel: options.profileLabels?.[profileId] ?? (profileId === options.defaultProfileId ? options.defaultProfileLabel : undefined),
3654
3692
  providerP95Ms,
3655
3693
  providers,
3694
+ reconnect,
3656
3695
  runtimeChannel,
3657
3696
  sessionId,
3658
3697
  surfaces: surfaces.length > 0 ? surfaces : undefined,
@@ -3660,11 +3699,46 @@ var buildVoiceRealCallProfileEvidenceFromTraceEvents = (events, options = {}) =>
3660
3699
  };
3661
3700
  }).filter((evidence) => evidence !== undefined);
3662
3701
  };
3702
+ var normalizeReconnectReport = (report) => ("contract" in report) ? report.contract : report;
3703
+ var buildVoiceRealCallProfileEvidenceFromReconnectProofReports = (input, options = {}) => {
3704
+ const reports = Array.isArray(input) ? input : [input];
3705
+ const profileId = options.profileId ?? "reconnect-resume";
3706
+ return reports.map((report, index) => {
3707
+ const contract = normalizeReconnectReport(report);
3708
+ const generatedAt = "generatedAt" in report ? report.generatedAt : new Date(contract.checkedAt).toISOString();
3709
+ const ok = "ok" in report ? report.ok : contract.pass;
3710
+ const operationsRecordHref = typeof options.operationsRecordHref === "function" ? options.operationsRecordHref(report, index) : options.operationsRecordHref;
3711
+ const sessionId = typeof options.sessionId === "function" ? options.sessionId(report, index) : options.sessionId ?? `reconnect-proof-${String(index + 1)}-${String(contract.checkedAt)}`;
3712
+ return {
3713
+ generatedAt,
3714
+ ok,
3715
+ operationsRecordHref,
3716
+ profileDescription: options.profileDescription,
3717
+ profileId,
3718
+ profileLabel: options.profileLabel,
3719
+ reconnect: {
3720
+ attempts: contract.summary.attempts,
3721
+ exhausted: contract.summary.exhausted,
3722
+ maxAttempts: contract.summary.maxAttempts,
3723
+ resumeLatencyP95Ms: contract.resumeLatencyP95Ms,
3724
+ reconnected: contract.summary.reconnected,
3725
+ resumed: contract.summary.resumed,
3726
+ samples: 1,
3727
+ snapshotCount: contract.snapshotCount,
3728
+ status: ok ? "pass" : "fail"
3729
+ },
3730
+ sessionId,
3731
+ surfaces: [...new Set(["reconnect", ...options.surfaces ?? []])].sort()
3732
+ };
3733
+ });
3734
+ };
3663
3735
  var loadVoiceRealCallProfileEvidenceFromTraceStore = async (options) => buildVoiceRealCallProfileEvidenceFromTraceEvents(await options.store.list({ limit: options.limit ?? 5000 }), options);
3736
+ var loadVoiceRealCallProfileEvidenceFromStore = async (options) => options.store.list(options);
3664
3737
  var realCallProfileTraceSignalTypes = new Set([
3665
3738
  "client.barge_in",
3666
3739
  "client.browser_media",
3667
3740
  "client.live_latency",
3741
+ "client.reconnect",
3668
3742
  "client.telephony_media",
3669
3743
  "provider.decision",
3670
3744
  "session.error",
@@ -3727,15 +3801,16 @@ var readProofTrendProviders = (reports) => aggregateProofTrendProviders(reports.
3727
3801
  var exceedsProofTrendBudget = (value, budget) => value !== undefined && (!Number.isFinite(value) || value > budget);
3728
3802
  var readProofTrendProfileStatus = (profile, budgets) => {
3729
3803
  const runtimeChannel = profile.runtimeChannel;
3730
- const hasBudgetEvidence = profile.maxLiveP95Ms !== undefined || profile.maxProviderP95Ms !== undefined || profile.maxTurnP95Ms !== undefined || profile.providers?.some((provider) => provider.p95Ms !== undefined) === true || runtimeChannel?.maxFirstAudioLatencyMs !== undefined || runtimeChannel?.maxInterruptionP95Ms !== undefined || runtimeChannel?.maxJitterMs !== undefined || runtimeChannel?.maxTimestampDriftMs !== undefined || runtimeChannel?.maxBackpressureEvents !== undefined;
3731
- const budgetFailed = exceedsProofTrendBudget(profile.maxLiveP95Ms, budgets.maxLiveP95Ms) || exceedsProofTrendBudget(profile.maxProviderP95Ms, budgets.maxProviderP95Ms) || exceedsProofTrendBudget(profile.maxTurnP95Ms, budgets.maxTurnP95Ms) || exceedsProofTrendBudget(runtimeChannel?.maxFirstAudioLatencyMs, budgets.maxRuntimeFirstAudioLatencyMs) || exceedsProofTrendBudget(runtimeChannel?.maxInterruptionP95Ms, budgets.maxRuntimeInterruptionP95Ms) || exceedsProofTrendBudget(runtimeChannel?.maxJitterMs, budgets.maxRuntimeJitterMs) || exceedsProofTrendBudget(runtimeChannel?.maxTimestampDriftMs, budgets.maxRuntimeTimestampDriftMs) || exceedsProofTrendBudget(runtimeChannel?.maxBackpressureEvents, 0);
3804
+ const reconnect = profile.reconnect;
3805
+ const hasBudgetEvidence = profile.maxLiveP95Ms !== undefined || profile.maxProviderP95Ms !== undefined || profile.maxReconnectP95Ms !== undefined || profile.maxTurnP95Ms !== undefined || profile.providers?.some((provider) => provider.p95Ms !== undefined) === true || runtimeChannel?.maxFirstAudioLatencyMs !== undefined || runtimeChannel?.maxInterruptionP95Ms !== undefined || runtimeChannel?.maxJitterMs !== undefined || runtimeChannel?.maxTimestampDriftMs !== undefined || runtimeChannel?.maxBackpressureEvents !== undefined || reconnect?.resumeLatencyP95Ms !== undefined || reconnect?.samples !== undefined;
3806
+ const budgetFailed = exceedsProofTrendBudget(profile.maxLiveP95Ms, budgets.maxLiveP95Ms) || exceedsProofTrendBudget(profile.maxProviderP95Ms, budgets.maxProviderP95Ms) || exceedsProofTrendBudget(profile.maxReconnectP95Ms ?? reconnect?.resumeLatencyP95Ms, budgets.maxReconnectP95Ms) || exceedsProofTrendBudget(profile.maxTurnP95Ms, budgets.maxTurnP95Ms) || exceedsProofTrendBudget(runtimeChannel?.maxFirstAudioLatencyMs, budgets.maxRuntimeFirstAudioLatencyMs) || exceedsProofTrendBudget(runtimeChannel?.maxInterruptionP95Ms, budgets.maxRuntimeInterruptionP95Ms) || exceedsProofTrendBudget(runtimeChannel?.maxJitterMs, budgets.maxRuntimeJitterMs) || exceedsProofTrendBudget(runtimeChannel?.maxTimestampDriftMs, budgets.maxRuntimeTimestampDriftMs) || exceedsProofTrendBudget(runtimeChannel?.maxBackpressureEvents, 0) || reconnect?.status === "fail";
3732
3807
  if (budgetFailed || !hasBudgetEvidence && profile.status === "fail") {
3733
3808
  return "fail";
3734
3809
  }
3735
- if (profile.status === "warn" || runtimeChannel?.status === "warn" || profile.providers?.some((provider) => provider.status === "warn") === true) {
3810
+ if (profile.status === "warn" || reconnect?.status === "warn" || runtimeChannel?.status === "warn" || profile.providers?.some((provider) => provider.status === "warn") === true) {
3736
3811
  return "warn";
3737
3812
  }
3738
- if (hasBudgetEvidence || profile.status === "pass" || runtimeChannel?.status === "pass" || profile.providers?.some((provider) => provider.status === "pass") === true) {
3813
+ if (hasBudgetEvidence || profile.status === "pass" || reconnect?.status === "pass" || runtimeChannel?.status === "pass" || profile.providers?.some((provider) => provider.status === "pass") === true) {
3739
3814
  return "pass";
3740
3815
  }
3741
3816
  return;
@@ -3745,6 +3820,7 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
3745
3820
  const definitions = options.profiles ?? DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS;
3746
3821
  const providerCap = options.maxProviderP95Ms ?? 1000;
3747
3822
  const liveCap = options.maxLiveP95Ms ?? 800;
3823
+ const reconnectCap = options.maxReconnectP95Ms ?? 1500;
3748
3824
  const turnCap = options.maxTurnP95Ms ?? 700;
3749
3825
  const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
3750
3826
  const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
@@ -3753,6 +3829,7 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
3753
3829
  const budgets = {
3754
3830
  maxLiveP95Ms: liveCap,
3755
3831
  maxProviderP95Ms: providerCap,
3832
+ maxReconnectP95Ms: reconnectCap,
3756
3833
  maxRuntimeFirstAudioLatencyMs: runtimeFirstAudioCap,
3757
3834
  maxRuntimeInterruptionP95Ms: runtimeInterruptionCap,
3758
3835
  maxRuntimeJitterMs: runtimeJitterCap,
@@ -3775,8 +3852,10 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
3775
3852
  label: definition.label ?? profiles.find(Boolean)?.label,
3776
3853
  maxLiveP95Ms: maxNumber(profiles.map((profile) => profile.maxLiveP95Ms)),
3777
3854
  maxProviderP95Ms: maxNumber(profiles.map((profile) => profile.maxProviderP95Ms)),
3855
+ maxReconnectP95Ms: maxNumber(profiles.map((profile) => profile.maxReconnectP95Ms)),
3778
3856
  maxTurnP95Ms: maxNumber(profiles.map((profile) => profile.maxTurnP95Ms)),
3779
3857
  providers: aggregateProofTrendProviders(profiles.flatMap((profile) => profile.providers ?? [])),
3858
+ reconnect: aggregateProofTrendReconnect(profiles.map((profile) => profile.reconnect).filter((reconnect) => reconnect !== undefined)),
3780
3859
  runtimeChannel: aggregateProofTrendRuntimeChannel(profiles.map((profile) => profile.runtimeChannel).filter((channel) => channel !== undefined)),
3781
3860
  sessionCount: profiles.reduce((total, profile) => total + (profile.sessionCount ?? 0), 0),
3782
3861
  surfaces: [
@@ -3816,6 +3895,7 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
3816
3895
  var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
3817
3896
  const providerCap = options.maxProviderP95Ms ?? 1000;
3818
3897
  const liveCap = options.maxLiveP95Ms ?? 800;
3898
+ const reconnectCap = options.maxReconnectP95Ms ?? 1500;
3819
3899
  const turnCap = options.maxTurnP95Ms ?? 700;
3820
3900
  const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
3821
3901
  const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
@@ -3824,6 +3904,7 @@ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
3824
3904
  const budgets = {
3825
3905
  maxLiveP95Ms: liveCap,
3826
3906
  maxProviderP95Ms: providerCap,
3907
+ maxReconnectP95Ms: reconnectCap,
3827
3908
  maxRuntimeFirstAudioLatencyMs: runtimeFirstAudioCap,
3828
3909
  maxRuntimeInterruptionP95Ms: runtimeInterruptionCap,
3829
3910
  maxRuntimeJitterMs: runtimeJitterCap,
@@ -3853,8 +3934,10 @@ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
3853
3934
  label: definition.label ?? matchingEvidence.find((evidence) => evidence.profileLabel)?.profileLabel,
3854
3935
  maxLiveP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.liveP95Ms)),
3855
3936
  maxProviderP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.providerP95Ms)),
3937
+ maxReconnectP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.reconnect?.resumeLatencyP95Ms)),
3856
3938
  maxTurnP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.turnP95Ms)),
3857
3939
  providers: aggregateProofTrendProviders(matchingEvidence.flatMap((evidence) => evidence.providers ?? [])),
3940
+ reconnect: aggregateProofTrendReconnect(matchingEvidence.map((evidence) => evidence.reconnect).filter((reconnect) => reconnect !== undefined)),
3858
3941
  runtimeChannel: aggregateProofTrendRuntimeChannel(matchingEvidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined)),
3859
3942
  sessionCount: new Set(matchingEvidence.map((evidence) => evidence.sessionId)).size,
3860
3943
  surfaces: [
@@ -3873,6 +3956,7 @@ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
3873
3956
  ok: evidence.ok !== false,
3874
3957
  providers: evidence.providers,
3875
3958
  runtimeChannel: evidence.runtimeChannel,
3959
+ reconnect: evidence.reconnect,
3876
3960
  turnLatency: evidence.turnP95Ms === undefined ? undefined : {
3877
3961
  p95Ms: evidence.turnP95Ms,
3878
3962
  samples: 1,
@@ -3883,9 +3967,11 @@ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
3883
3967
  cycles: options.evidence.length,
3884
3968
  maxLiveP95Ms: maxNumber(options.evidence.map((evidence) => evidence.liveP95Ms)),
3885
3969
  maxProviderP95Ms: maxNumber(options.evidence.map((evidence) => evidence.providerP95Ms)),
3970
+ maxReconnectP95Ms: maxNumber(options.evidence.map((evidence) => evidence.reconnect?.resumeLatencyP95Ms)),
3886
3971
  maxTurnP95Ms: maxNumber(options.evidence.map((evidence) => evidence.turnP95Ms)),
3887
3972
  profiles,
3888
3973
  providers: aggregateProofTrendProviders(options.evidence.flatMap((evidence) => evidence.providers ?? [])),
3974
+ reconnect: aggregateProofTrendReconnect(options.evidence.map((evidence) => evidence.reconnect).filter((reconnect) => reconnect !== undefined)),
3889
3975
  runtimeChannel: aggregateProofTrendRuntimeChannel(options.evidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined))
3890
3976
  };
3891
3977
  return buildVoiceProofTrendReport({
@@ -4490,6 +4576,74 @@ var createVoiceInMemoryRealCallProfileRecoveryJobStore = (options = {}) => {
4490
4576
  }
4491
4577
  };
4492
4578
  };
4579
+ var normalizeRealCallProfileEvidenceTableName = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice_real_call_profile_evidence";
4580
+ var parseRealCallProfileEvidenceBoundary = (value) => value === undefined ? undefined : value instanceof Date ? value.getTime() : typeof value === "number" ? value : Date.parse(value);
4581
+ var readRealCallProfileEvidenceSortTime = (evidence, fallback) => Date.parse(evidence.generatedAt ?? fallback) || Date.parse(fallback);
4582
+ var createVoiceSQLiteRealCallProfileEvidenceStore = (options = {}) => {
4583
+ const { Database: SQLiteDatabase } = __require("bun:sqlite");
4584
+ const database = options.database ?? new SQLiteDatabase(options.path ?? ":memory:", {
4585
+ create: true
4586
+ });
4587
+ const tableName = normalizeRealCallProfileEvidenceTableName(options.tableName ?? "voice_real_call_profile_evidence");
4588
+ const now = () => (options.now ?? (() => new Date))().toISOString();
4589
+ const createId = () => `${options.idPrefix ?? "voice-profile-evidence"}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
4590
+ database.exec("PRAGMA journal_mode = WAL;");
4591
+ database.exec("PRAGMA synchronous = NORMAL;");
4592
+ database.exec("PRAGMA busy_timeout = 5000;");
4593
+ database.exec(`CREATE TABLE IF NOT EXISTS "${tableName}" (
4594
+ id TEXT PRIMARY KEY,
4595
+ sort_at INTEGER NOT NULL,
4596
+ profile_id TEXT NOT NULL,
4597
+ session_id TEXT NOT NULL,
4598
+ created_at TEXT NOT NULL,
4599
+ payload TEXT NOT NULL
4600
+ )`);
4601
+ const selectStatement = database.query(`SELECT payload FROM "${tableName}" WHERE id = ?1 LIMIT 1`);
4602
+ const listStatement = database.query(`SELECT payload FROM "${tableName}" ORDER BY sort_at DESC, id DESC`);
4603
+ const upsertStatement = database.query(`INSERT INTO "${tableName}" (id, sort_at, profile_id, session_id, created_at, payload)
4604
+ VALUES (?1, ?2, ?3, ?4, ?5, ?6)
4605
+ ON CONFLICT(id) DO UPDATE SET
4606
+ sort_at = excluded.sort_at,
4607
+ profile_id = excluded.profile_id,
4608
+ session_id = excluded.session_id,
4609
+ created_at = excluded.created_at,
4610
+ payload = excluded.payload`);
4611
+ const deleteStatement = database.query(`DELETE FROM "${tableName}" WHERE id = ?1`);
4612
+ const writeEvidence = (record) => {
4613
+ upsertStatement.run(record.id, readRealCallProfileEvidenceSortTime(record, record.createdAt), record.profileId, record.sessionId, record.createdAt, JSON.stringify(record));
4614
+ return record;
4615
+ };
4616
+ const readEvidence = (id) => {
4617
+ const row = selectStatement.get(id);
4618
+ return row ? JSON.parse(row.payload) : undefined;
4619
+ };
4620
+ const matchesListOptions = (record, input) => {
4621
+ const evidenceTime = readRealCallProfileEvidenceSortTime(record, record.createdAt);
4622
+ const since = parseRealCallProfileEvidenceBoundary(input.since);
4623
+ const until = parseRealCallProfileEvidenceBoundary(input.until);
4624
+ return (!input.profileId || record.profileId === input.profileId) && (!input.sessionId || record.sessionId === input.sessionId) && (since === undefined || Number.isNaN(since) || evidenceTime >= since) && (until === undefined || Number.isNaN(until) || evidenceTime <= until);
4625
+ };
4626
+ return {
4627
+ append(input) {
4628
+ const createdAt = input.createdAt ?? now();
4629
+ return writeEvidence({
4630
+ ...input,
4631
+ createdAt,
4632
+ id: input.id ?? createId()
4633
+ });
4634
+ },
4635
+ get(id) {
4636
+ return readEvidence(id);
4637
+ },
4638
+ list(input = {}) {
4639
+ const limit = Number.isFinite(input.limit) && input.limit !== undefined && input.limit > 0 ? Math.floor(input.limit) : 500;
4640
+ return listStatement.all().map((row) => JSON.parse(row.payload)).filter((record) => matchesListOptions(record, input)).slice(0, limit);
4641
+ },
4642
+ remove(id) {
4643
+ deleteStatement.run(id);
4644
+ }
4645
+ };
4646
+ };
4493
4647
  var normalizeRealCallRecoveryJobTableName = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice_real_call_profile_recovery_jobs";
4494
4648
  var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
4495
4649
  const { Database: SQLiteDatabase } = __require("bun:sqlite");
@@ -4704,10 +4858,12 @@ var buildVoiceRealCallProfileHistoryReport = (options = {}) => {
4704
4858
  failedReports: history.filter((report) => report.ok !== true).length,
4705
4859
  maxLiveP95Ms: maxNumber(profileHistory.map(readProofTrendMaxLiveP95)),
4706
4860
  maxProviderP95Ms: maxNumber(profileHistory.map(readProofTrendMaxProviderP95)),
4861
+ maxReconnectP95Ms: maxNumber(profileHistory.map(readProofTrendMaxReconnectP95)),
4707
4862
  maxTurnP95Ms: maxNumber(profileHistory.map(readProofTrendMaxTurnP95)),
4708
4863
  profileCount: profiles.length,
4709
4864
  profiles,
4710
4865
  providers: readProofTrendProviders(profileHistory),
4866
+ reconnect: aggregateProofTrendReconnect(profileHistory.map((report) => report.summary.reconnect).filter((reconnect) => reconnect !== undefined)),
4711
4867
  runtimeChannel: aggregateProofTrendRuntimeChannel(profileHistory.map(readProofTrendRuntimeChannel).filter((channel) => channel !== undefined))
4712
4868
  };
4713
4869
  const trend = buildVoiceProofTrendReport({
@@ -4741,6 +4897,13 @@ var buildVoiceRealCallProfileHistoryReport = (options = {}) => {
4741
4897
  trend
4742
4898
  };
4743
4899
  };
4900
+ var buildVoiceRealCallProfileHistoryReportFromStore = async (options) => {
4901
+ const evidence = await options.store.list(options);
4902
+ return buildVoiceRealCallProfileHistoryReport({
4903
+ ...options,
4904
+ evidence
4905
+ });
4906
+ };
4744
4907
  var normalizeProviderStatus = (status) => status === "pass" ? "pass" : status === "fail" ? "fail" : "warn";
4745
4908
  var providerSortScore = (provider) => [
4746
4909
  recommendationStatusRank[provider.status],
package/dist/vue/index.js CHANGED
@@ -3351,6 +3351,7 @@ var readString = (value) => typeof value === "string" && value.trim() ? value :
3351
3351
  var readNumber2 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
3352
3352
  var readProofTrendMaxLiveP95 = (report) => report.summary.maxLiveP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.liveLatency?.p95Ms));
3353
3353
  var readProofTrendMaxProviderP95 = (report) => report.summary.maxProviderP95Ms ?? maxNumber((report.summary.providers ?? []).map((provider) => provider.p95Ms)) ?? maxNumber(report.cycles.flatMap((cycle) => (cycle.providers ?? []).map((provider) => provider.p95Ms)));
3354
+ var readProofTrendMaxReconnectP95 = (report) => report.summary.maxReconnectP95Ms ?? report.summary.reconnect?.resumeLatencyP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.reconnect?.resumeLatencyP95Ms));
3354
3355
  var readProofTrendMaxTurnP95 = (report) => report.summary.maxTurnP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.turnLatency?.p95Ms));
3355
3356
  var readRuntimeChannelMetric = (report, key) => {
3356
3357
  const summaryValue = report.summary.runtimeChannel?.[key];
@@ -3412,6 +3413,42 @@ var aggregateProofTrendRuntimeChannel = (channels) => {
3412
3413
  status: channels.some((channel) => channel.status === "fail") ? "fail" : channels.some((channel) => channel.status === "warn") ? "warn" : channels.every((channel) => channel.status === "pass") ? "pass" : undefined
3413
3414
  };
3414
3415
  };
3416
+ var aggregateProofTrendReconnect = (reconnects) => {
3417
+ if (reconnects.length === 0) {
3418
+ return;
3419
+ }
3420
+ const hasFailure = reconnects.some((reconnect) => reconnect.status === "fail" || reconnect.exhausted === true || reconnect.reconnected === false || reconnect.resumed === false);
3421
+ return {
3422
+ attempts: maxNumber(reconnects.map((reconnect) => reconnect.attempts)),
3423
+ exhausted: reconnects.some((reconnect) => reconnect.exhausted === true),
3424
+ maxAttempts: maxNumber(reconnects.map((reconnect) => reconnect.maxAttempts)),
3425
+ resumeLatencyP95Ms: maxNumber(reconnects.map((reconnect) => reconnect.resumeLatencyP95Ms)),
3426
+ reconnected: reconnects.some((reconnect) => reconnect.reconnected === true),
3427
+ resumed: reconnects.some((reconnect) => reconnect.resumed === true),
3428
+ samples: reconnects.reduce((total, reconnect) => total + (reconnect.samples ?? 0), 0),
3429
+ snapshotCount: reconnects.reduce((total, reconnect) => total + (reconnect.snapshotCount ?? 0), 0),
3430
+ status: hasFailure ? "fail" : reconnects.some((reconnect) => reconnect.status === "warn") ? "warn" : "pass"
3431
+ };
3432
+ };
3433
+ var summarizeReconnectTraceEvidence = (events) => {
3434
+ const reconnectEvents = events.filter((event) => event.type === "client.reconnect");
3435
+ if (reconnectEvents.length === 0) {
3436
+ return;
3437
+ }
3438
+ const statuses = reconnectEvents.map((event) => readString(readTraceRecord(event).status)).filter((status) => status !== undefined);
3439
+ const reconnectPayloads = reconnectEvents.map((event) => readTraceRecord(event));
3440
+ return {
3441
+ attempts: maxNumber(reconnectPayloads.map((payload) => readNumber2(payload.attempts))),
3442
+ exhausted: statuses.includes("exhausted"),
3443
+ maxAttempts: maxNumber(reconnectPayloads.map((payload) => readNumber2(payload.maxAttempts))),
3444
+ resumeLatencyP95Ms: percentile(reconnectPayloads.map((payload) => readNumber2(payload.resumeLatencyP95Ms) ?? readNumber2(payload.resumeLatencyMs)).filter((value) => value !== undefined), 95),
3445
+ reconnected: statuses.includes("reconnecting"),
3446
+ resumed: statuses.includes("resumed") || statuses.includes("pass"),
3447
+ samples: reconnectEvents.length,
3448
+ snapshotCount: reconnectEvents.length,
3449
+ status: reconnectEvents.some((event) => isFailingTraceStatus(readTraceStatus(readTraceRecord(event)))) ? "fail" : "pass"
3450
+ };
3451
+ };
3415
3452
  var readTraceRecord = (event) => event.payload;
3416
3453
  var readTraceProfileId = (events, options) => {
3417
3454
  for (const event of events) {
@@ -3559,6 +3596,7 @@ var buildVoiceRealCallProfileEvidenceFromTraceEvents = (events, options = {}) =>
3559
3596
  }).filter((value) => value !== undefined);
3560
3597
  const turnP95Ms = summarizeTurnTraceP95(sessionEvents);
3561
3598
  const providerP95Ms = maxNumber(providers.map((provider) => provider.p95Ms));
3599
+ const reconnect = summarizeReconnectTraceEvidence(sessionEvents);
3562
3600
  const runtimeChannel = summarizeRuntimeChannelTraceEvidence(sessionEvents);
3563
3601
  const surfaces = readRealCallProfileTraceSurfaces(sessionEvents);
3564
3602
  if (providers.length === 0 && runtimeChannel === undefined && liveLatencies.length === 0 && surfaces.length === 0) {
@@ -3574,6 +3612,7 @@ var buildVoiceRealCallProfileEvidenceFromTraceEvents = (events, options = {}) =>
3574
3612
  profileLabel: options.profileLabels?.[profileId] ?? (profileId === options.defaultProfileId ? options.defaultProfileLabel : undefined),
3575
3613
  providerP95Ms,
3576
3614
  providers,
3615
+ reconnect,
3577
3616
  runtimeChannel,
3578
3617
  sessionId,
3579
3618
  surfaces: surfaces.length > 0 ? surfaces : undefined,
@@ -3581,11 +3620,46 @@ var buildVoiceRealCallProfileEvidenceFromTraceEvents = (events, options = {}) =>
3581
3620
  };
3582
3621
  }).filter((evidence) => evidence !== undefined);
3583
3622
  };
3623
+ var normalizeReconnectReport = (report) => ("contract" in report) ? report.contract : report;
3624
+ var buildVoiceRealCallProfileEvidenceFromReconnectProofReports = (input, options = {}) => {
3625
+ const reports = Array.isArray(input) ? input : [input];
3626
+ const profileId = options.profileId ?? "reconnect-resume";
3627
+ return reports.map((report, index) => {
3628
+ const contract = normalizeReconnectReport(report);
3629
+ const generatedAt = "generatedAt" in report ? report.generatedAt : new Date(contract.checkedAt).toISOString();
3630
+ const ok = "ok" in report ? report.ok : contract.pass;
3631
+ const operationsRecordHref = typeof options.operationsRecordHref === "function" ? options.operationsRecordHref(report, index) : options.operationsRecordHref;
3632
+ const sessionId = typeof options.sessionId === "function" ? options.sessionId(report, index) : options.sessionId ?? `reconnect-proof-${String(index + 1)}-${String(contract.checkedAt)}`;
3633
+ return {
3634
+ generatedAt,
3635
+ ok,
3636
+ operationsRecordHref,
3637
+ profileDescription: options.profileDescription,
3638
+ profileId,
3639
+ profileLabel: options.profileLabel,
3640
+ reconnect: {
3641
+ attempts: contract.summary.attempts,
3642
+ exhausted: contract.summary.exhausted,
3643
+ maxAttempts: contract.summary.maxAttempts,
3644
+ resumeLatencyP95Ms: contract.resumeLatencyP95Ms,
3645
+ reconnected: contract.summary.reconnected,
3646
+ resumed: contract.summary.resumed,
3647
+ samples: 1,
3648
+ snapshotCount: contract.snapshotCount,
3649
+ status: ok ? "pass" : "fail"
3650
+ },
3651
+ sessionId,
3652
+ surfaces: [...new Set(["reconnect", ...options.surfaces ?? []])].sort()
3653
+ };
3654
+ });
3655
+ };
3584
3656
  var loadVoiceRealCallProfileEvidenceFromTraceStore = async (options) => buildVoiceRealCallProfileEvidenceFromTraceEvents(await options.store.list({ limit: options.limit ?? 5000 }), options);
3657
+ var loadVoiceRealCallProfileEvidenceFromStore = async (options) => options.store.list(options);
3585
3658
  var realCallProfileTraceSignalTypes = new Set([
3586
3659
  "client.barge_in",
3587
3660
  "client.browser_media",
3588
3661
  "client.live_latency",
3662
+ "client.reconnect",
3589
3663
  "client.telephony_media",
3590
3664
  "provider.decision",
3591
3665
  "session.error",
@@ -3648,15 +3722,16 @@ var readProofTrendProviders = (reports) => aggregateProofTrendProviders(reports.
3648
3722
  var exceedsProofTrendBudget = (value, budget) => value !== undefined && (!Number.isFinite(value) || value > budget);
3649
3723
  var readProofTrendProfileStatus = (profile, budgets) => {
3650
3724
  const runtimeChannel = profile.runtimeChannel;
3651
- const hasBudgetEvidence = profile.maxLiveP95Ms !== undefined || profile.maxProviderP95Ms !== undefined || profile.maxTurnP95Ms !== undefined || profile.providers?.some((provider) => provider.p95Ms !== undefined) === true || runtimeChannel?.maxFirstAudioLatencyMs !== undefined || runtimeChannel?.maxInterruptionP95Ms !== undefined || runtimeChannel?.maxJitterMs !== undefined || runtimeChannel?.maxTimestampDriftMs !== undefined || runtimeChannel?.maxBackpressureEvents !== undefined;
3652
- const budgetFailed = exceedsProofTrendBudget(profile.maxLiveP95Ms, budgets.maxLiveP95Ms) || exceedsProofTrendBudget(profile.maxProviderP95Ms, budgets.maxProviderP95Ms) || exceedsProofTrendBudget(profile.maxTurnP95Ms, budgets.maxTurnP95Ms) || exceedsProofTrendBudget(runtimeChannel?.maxFirstAudioLatencyMs, budgets.maxRuntimeFirstAudioLatencyMs) || exceedsProofTrendBudget(runtimeChannel?.maxInterruptionP95Ms, budgets.maxRuntimeInterruptionP95Ms) || exceedsProofTrendBudget(runtimeChannel?.maxJitterMs, budgets.maxRuntimeJitterMs) || exceedsProofTrendBudget(runtimeChannel?.maxTimestampDriftMs, budgets.maxRuntimeTimestampDriftMs) || exceedsProofTrendBudget(runtimeChannel?.maxBackpressureEvents, 0);
3725
+ const reconnect = profile.reconnect;
3726
+ const hasBudgetEvidence = profile.maxLiveP95Ms !== undefined || profile.maxProviderP95Ms !== undefined || profile.maxReconnectP95Ms !== undefined || profile.maxTurnP95Ms !== undefined || profile.providers?.some((provider) => provider.p95Ms !== undefined) === true || runtimeChannel?.maxFirstAudioLatencyMs !== undefined || runtimeChannel?.maxInterruptionP95Ms !== undefined || runtimeChannel?.maxJitterMs !== undefined || runtimeChannel?.maxTimestampDriftMs !== undefined || runtimeChannel?.maxBackpressureEvents !== undefined || reconnect?.resumeLatencyP95Ms !== undefined || reconnect?.samples !== undefined;
3727
+ const budgetFailed = exceedsProofTrendBudget(profile.maxLiveP95Ms, budgets.maxLiveP95Ms) || exceedsProofTrendBudget(profile.maxProviderP95Ms, budgets.maxProviderP95Ms) || exceedsProofTrendBudget(profile.maxReconnectP95Ms ?? reconnect?.resumeLatencyP95Ms, budgets.maxReconnectP95Ms) || exceedsProofTrendBudget(profile.maxTurnP95Ms, budgets.maxTurnP95Ms) || exceedsProofTrendBudget(runtimeChannel?.maxFirstAudioLatencyMs, budgets.maxRuntimeFirstAudioLatencyMs) || exceedsProofTrendBudget(runtimeChannel?.maxInterruptionP95Ms, budgets.maxRuntimeInterruptionP95Ms) || exceedsProofTrendBudget(runtimeChannel?.maxJitterMs, budgets.maxRuntimeJitterMs) || exceedsProofTrendBudget(runtimeChannel?.maxTimestampDriftMs, budgets.maxRuntimeTimestampDriftMs) || exceedsProofTrendBudget(runtimeChannel?.maxBackpressureEvents, 0) || reconnect?.status === "fail";
3653
3728
  if (budgetFailed || !hasBudgetEvidence && profile.status === "fail") {
3654
3729
  return "fail";
3655
3730
  }
3656
- if (profile.status === "warn" || runtimeChannel?.status === "warn" || profile.providers?.some((provider) => provider.status === "warn") === true) {
3731
+ if (profile.status === "warn" || reconnect?.status === "warn" || runtimeChannel?.status === "warn" || profile.providers?.some((provider) => provider.status === "warn") === true) {
3657
3732
  return "warn";
3658
3733
  }
3659
- if (hasBudgetEvidence || profile.status === "pass" || runtimeChannel?.status === "pass" || profile.providers?.some((provider) => provider.status === "pass") === true) {
3734
+ if (hasBudgetEvidence || profile.status === "pass" || reconnect?.status === "pass" || runtimeChannel?.status === "pass" || profile.providers?.some((provider) => provider.status === "pass") === true) {
3660
3735
  return "pass";
3661
3736
  }
3662
3737
  return;
@@ -3666,6 +3741,7 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
3666
3741
  const definitions = options.profiles ?? DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS;
3667
3742
  const providerCap = options.maxProviderP95Ms ?? 1000;
3668
3743
  const liveCap = options.maxLiveP95Ms ?? 800;
3744
+ const reconnectCap = options.maxReconnectP95Ms ?? 1500;
3669
3745
  const turnCap = options.maxTurnP95Ms ?? 700;
3670
3746
  const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
3671
3747
  const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
@@ -3674,6 +3750,7 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
3674
3750
  const budgets = {
3675
3751
  maxLiveP95Ms: liveCap,
3676
3752
  maxProviderP95Ms: providerCap,
3753
+ maxReconnectP95Ms: reconnectCap,
3677
3754
  maxRuntimeFirstAudioLatencyMs: runtimeFirstAudioCap,
3678
3755
  maxRuntimeInterruptionP95Ms: runtimeInterruptionCap,
3679
3756
  maxRuntimeJitterMs: runtimeJitterCap,
@@ -3696,8 +3773,10 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
3696
3773
  label: definition.label ?? profiles.find(Boolean)?.label,
3697
3774
  maxLiveP95Ms: maxNumber(profiles.map((profile) => profile.maxLiveP95Ms)),
3698
3775
  maxProviderP95Ms: maxNumber(profiles.map((profile) => profile.maxProviderP95Ms)),
3776
+ maxReconnectP95Ms: maxNumber(profiles.map((profile) => profile.maxReconnectP95Ms)),
3699
3777
  maxTurnP95Ms: maxNumber(profiles.map((profile) => profile.maxTurnP95Ms)),
3700
3778
  providers: aggregateProofTrendProviders(profiles.flatMap((profile) => profile.providers ?? [])),
3779
+ reconnect: aggregateProofTrendReconnect(profiles.map((profile) => profile.reconnect).filter((reconnect) => reconnect !== undefined)),
3701
3780
  runtimeChannel: aggregateProofTrendRuntimeChannel(profiles.map((profile) => profile.runtimeChannel).filter((channel) => channel !== undefined)),
3702
3781
  sessionCount: profiles.reduce((total, profile) => total + (profile.sessionCount ?? 0), 0),
3703
3782
  surfaces: [
@@ -3737,6 +3816,7 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
3737
3816
  var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
3738
3817
  const providerCap = options.maxProviderP95Ms ?? 1000;
3739
3818
  const liveCap = options.maxLiveP95Ms ?? 800;
3819
+ const reconnectCap = options.maxReconnectP95Ms ?? 1500;
3740
3820
  const turnCap = options.maxTurnP95Ms ?? 700;
3741
3821
  const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
3742
3822
  const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
@@ -3745,6 +3825,7 @@ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
3745
3825
  const budgets = {
3746
3826
  maxLiveP95Ms: liveCap,
3747
3827
  maxProviderP95Ms: providerCap,
3828
+ maxReconnectP95Ms: reconnectCap,
3748
3829
  maxRuntimeFirstAudioLatencyMs: runtimeFirstAudioCap,
3749
3830
  maxRuntimeInterruptionP95Ms: runtimeInterruptionCap,
3750
3831
  maxRuntimeJitterMs: runtimeJitterCap,
@@ -3774,8 +3855,10 @@ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
3774
3855
  label: definition.label ?? matchingEvidence.find((evidence) => evidence.profileLabel)?.profileLabel,
3775
3856
  maxLiveP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.liveP95Ms)),
3776
3857
  maxProviderP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.providerP95Ms)),
3858
+ maxReconnectP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.reconnect?.resumeLatencyP95Ms)),
3777
3859
  maxTurnP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.turnP95Ms)),
3778
3860
  providers: aggregateProofTrendProviders(matchingEvidence.flatMap((evidence) => evidence.providers ?? [])),
3861
+ reconnect: aggregateProofTrendReconnect(matchingEvidence.map((evidence) => evidence.reconnect).filter((reconnect) => reconnect !== undefined)),
3779
3862
  runtimeChannel: aggregateProofTrendRuntimeChannel(matchingEvidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined)),
3780
3863
  sessionCount: new Set(matchingEvidence.map((evidence) => evidence.sessionId)).size,
3781
3864
  surfaces: [
@@ -3794,6 +3877,7 @@ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
3794
3877
  ok: evidence.ok !== false,
3795
3878
  providers: evidence.providers,
3796
3879
  runtimeChannel: evidence.runtimeChannel,
3880
+ reconnect: evidence.reconnect,
3797
3881
  turnLatency: evidence.turnP95Ms === undefined ? undefined : {
3798
3882
  p95Ms: evidence.turnP95Ms,
3799
3883
  samples: 1,
@@ -3804,9 +3888,11 @@ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
3804
3888
  cycles: options.evidence.length,
3805
3889
  maxLiveP95Ms: maxNumber(options.evidence.map((evidence) => evidence.liveP95Ms)),
3806
3890
  maxProviderP95Ms: maxNumber(options.evidence.map((evidence) => evidence.providerP95Ms)),
3891
+ maxReconnectP95Ms: maxNumber(options.evidence.map((evidence) => evidence.reconnect?.resumeLatencyP95Ms)),
3807
3892
  maxTurnP95Ms: maxNumber(options.evidence.map((evidence) => evidence.turnP95Ms)),
3808
3893
  profiles,
3809
3894
  providers: aggregateProofTrendProviders(options.evidence.flatMap((evidence) => evidence.providers ?? [])),
3895
+ reconnect: aggregateProofTrendReconnect(options.evidence.map((evidence) => evidence.reconnect).filter((reconnect) => reconnect !== undefined)),
3810
3896
  runtimeChannel: aggregateProofTrendRuntimeChannel(options.evidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined))
3811
3897
  };
3812
3898
  return buildVoiceProofTrendReport({
@@ -4411,6 +4497,74 @@ var createVoiceInMemoryRealCallProfileRecoveryJobStore = (options = {}) => {
4411
4497
  }
4412
4498
  };
4413
4499
  };
4500
+ var normalizeRealCallProfileEvidenceTableName = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice_real_call_profile_evidence";
4501
+ var parseRealCallProfileEvidenceBoundary = (value) => value === undefined ? undefined : value instanceof Date ? value.getTime() : typeof value === "number" ? value : Date.parse(value);
4502
+ var readRealCallProfileEvidenceSortTime = (evidence, fallback) => Date.parse(evidence.generatedAt ?? fallback) || Date.parse(fallback);
4503
+ var createVoiceSQLiteRealCallProfileEvidenceStore = (options = {}) => {
4504
+ const { Database: SQLiteDatabase } = __require("bun:sqlite");
4505
+ const database = options.database ?? new SQLiteDatabase(options.path ?? ":memory:", {
4506
+ create: true
4507
+ });
4508
+ const tableName = normalizeRealCallProfileEvidenceTableName(options.tableName ?? "voice_real_call_profile_evidence");
4509
+ const now = () => (options.now ?? (() => new Date))().toISOString();
4510
+ const createId = () => `${options.idPrefix ?? "voice-profile-evidence"}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
4511
+ database.exec("PRAGMA journal_mode = WAL;");
4512
+ database.exec("PRAGMA synchronous = NORMAL;");
4513
+ database.exec("PRAGMA busy_timeout = 5000;");
4514
+ database.exec(`CREATE TABLE IF NOT EXISTS "${tableName}" (
4515
+ id TEXT PRIMARY KEY,
4516
+ sort_at INTEGER NOT NULL,
4517
+ profile_id TEXT NOT NULL,
4518
+ session_id TEXT NOT NULL,
4519
+ created_at TEXT NOT NULL,
4520
+ payload TEXT NOT NULL
4521
+ )`);
4522
+ const selectStatement = database.query(`SELECT payload FROM "${tableName}" WHERE id = ?1 LIMIT 1`);
4523
+ const listStatement = database.query(`SELECT payload FROM "${tableName}" ORDER BY sort_at DESC, id DESC`);
4524
+ const upsertStatement = database.query(`INSERT INTO "${tableName}" (id, sort_at, profile_id, session_id, created_at, payload)
4525
+ VALUES (?1, ?2, ?3, ?4, ?5, ?6)
4526
+ ON CONFLICT(id) DO UPDATE SET
4527
+ sort_at = excluded.sort_at,
4528
+ profile_id = excluded.profile_id,
4529
+ session_id = excluded.session_id,
4530
+ created_at = excluded.created_at,
4531
+ payload = excluded.payload`);
4532
+ const deleteStatement = database.query(`DELETE FROM "${tableName}" WHERE id = ?1`);
4533
+ const writeEvidence = (record) => {
4534
+ upsertStatement.run(record.id, readRealCallProfileEvidenceSortTime(record, record.createdAt), record.profileId, record.sessionId, record.createdAt, JSON.stringify(record));
4535
+ return record;
4536
+ };
4537
+ const readEvidence = (id) => {
4538
+ const row = selectStatement.get(id);
4539
+ return row ? JSON.parse(row.payload) : undefined;
4540
+ };
4541
+ const matchesListOptions = (record, input) => {
4542
+ const evidenceTime = readRealCallProfileEvidenceSortTime(record, record.createdAt);
4543
+ const since = parseRealCallProfileEvidenceBoundary(input.since);
4544
+ const until = parseRealCallProfileEvidenceBoundary(input.until);
4545
+ return (!input.profileId || record.profileId === input.profileId) && (!input.sessionId || record.sessionId === input.sessionId) && (since === undefined || Number.isNaN(since) || evidenceTime >= since) && (until === undefined || Number.isNaN(until) || evidenceTime <= until);
4546
+ };
4547
+ return {
4548
+ append(input) {
4549
+ const createdAt = input.createdAt ?? now();
4550
+ return writeEvidence({
4551
+ ...input,
4552
+ createdAt,
4553
+ id: input.id ?? createId()
4554
+ });
4555
+ },
4556
+ get(id) {
4557
+ return readEvidence(id);
4558
+ },
4559
+ list(input = {}) {
4560
+ const limit = Number.isFinite(input.limit) && input.limit !== undefined && input.limit > 0 ? Math.floor(input.limit) : 500;
4561
+ return listStatement.all().map((row) => JSON.parse(row.payload)).filter((record) => matchesListOptions(record, input)).slice(0, limit);
4562
+ },
4563
+ remove(id) {
4564
+ deleteStatement.run(id);
4565
+ }
4566
+ };
4567
+ };
4414
4568
  var normalizeRealCallRecoveryJobTableName = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice_real_call_profile_recovery_jobs";
4415
4569
  var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
4416
4570
  const { Database: SQLiteDatabase } = __require("bun:sqlite");
@@ -4625,10 +4779,12 @@ var buildVoiceRealCallProfileHistoryReport = (options = {}) => {
4625
4779
  failedReports: history.filter((report) => report.ok !== true).length,
4626
4780
  maxLiveP95Ms: maxNumber(profileHistory.map(readProofTrendMaxLiveP95)),
4627
4781
  maxProviderP95Ms: maxNumber(profileHistory.map(readProofTrendMaxProviderP95)),
4782
+ maxReconnectP95Ms: maxNumber(profileHistory.map(readProofTrendMaxReconnectP95)),
4628
4783
  maxTurnP95Ms: maxNumber(profileHistory.map(readProofTrendMaxTurnP95)),
4629
4784
  profileCount: profiles.length,
4630
4785
  profiles,
4631
4786
  providers: readProofTrendProviders(profileHistory),
4787
+ reconnect: aggregateProofTrendReconnect(profileHistory.map((report) => report.summary.reconnect).filter((reconnect) => reconnect !== undefined)),
4632
4788
  runtimeChannel: aggregateProofTrendRuntimeChannel(profileHistory.map(readProofTrendRuntimeChannel).filter((channel) => channel !== undefined))
4633
4789
  };
4634
4790
  const trend = buildVoiceProofTrendReport({
@@ -4662,6 +4818,13 @@ var buildVoiceRealCallProfileHistoryReport = (options = {}) => {
4662
4818
  trend
4663
4819
  };
4664
4820
  };
4821
+ var buildVoiceRealCallProfileHistoryReportFromStore = async (options) => {
4822
+ const evidence = await options.store.list(options);
4823
+ return buildVoiceRealCallProfileHistoryReport({
4824
+ ...options,
4825
+ evidence
4826
+ });
4827
+ };
4665
4828
  var normalizeProviderStatus = (status) => status === "pass" ? "pass" : status === "fail" ? "fail" : "warn";
4666
4829
  var providerSortScore = (provider) => [
4667
4830
  recommendationStatusRank[provider.status],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.451",
3
+ "version": "0.0.22-beta.453",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",