@absolutejs/voice 0.0.22-beta.374 → 0.0.22-beta.376

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 CHANGED
@@ -1545,6 +1545,8 @@ const recoveryJobs = createVoiceSQLiteRealCallProfileRecoveryJobStore({
1545
1545
  });
1546
1546
  ```
1547
1547
 
1548
+ Recovery routes expose recent persisted jobs at `${path}/actions/jobs`. Stores can implement `list({ limit, actionId, status })`; the bundled memory and SQLite stores both support it.
1549
+
1548
1550
  Use `createVoiceProfileTraceTagger(...)` when the app already has a trace store and needs every appended trace to carry a benchmark profile label. It wraps any `VoiceTraceEventStore`, preserves the underlying store behavior, and adds `profileId`/`benchmarkProfileId` metadata and payload fields that real-call profile history can ingest later.
1549
1551
 
1550
1552
  ```ts
@@ -68,6 +68,7 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
68
68
  }
69
69
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
70
70
  };
71
+ var __require = import.meta.require;
71
72
 
72
73
  // src/angular/voice-ops-status.service.ts
73
74
  import { computed, Injectable, signal } from "@angular/core";
@@ -68,6 +68,7 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
68
68
  }
69
69
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
70
70
  };
71
+ var __require = import.meta.require;
71
72
 
72
73
  // src/client/connection.ts
73
74
  var WS_OPEN = 1;
@@ -3907,7 +3908,6 @@ var defineVoicePlatformCoverageElement = (tagName = "absolute-voice-platform-cov
3907
3908
  };
3908
3909
  // src/proofTrends.ts
3909
3910
  import { Elysia } from "elysia";
3910
- import { Database } from "bun:sqlite";
3911
3911
  var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
3912
3912
  var DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS = [
3913
3913
  {
@@ -4649,6 +4649,13 @@ var createVoiceInMemoryRealCallProfileRecoveryJobStore = (options = {}) => {
4649
4649
  get(id) {
4650
4650
  return jobs.get(id);
4651
4651
  },
4652
+ list(input = {}) {
4653
+ const limit = Number.isFinite(input.limit) && input.limit !== undefined && input.limit > 0 ? Math.floor(input.limit) : 50;
4654
+ return [...jobs.values()].filter((job) => !input.actionId || job.actionId === input.actionId).filter((job) => !input.status || job.status === input.status).sort((first, second) => {
4655
+ const updatedDelta = Date.parse(second.updatedAt) - Date.parse(first.updatedAt);
4656
+ return updatedDelta === 0 ? second.id.localeCompare(first.id) : updatedDelta;
4657
+ }).slice(0, limit);
4658
+ },
4652
4659
  update(id, update) {
4653
4660
  const existing = jobs.get(id);
4654
4661
  if (!existing) {
@@ -4666,7 +4673,8 @@ var createVoiceInMemoryRealCallProfileRecoveryJobStore = (options = {}) => {
4666
4673
  };
4667
4674
  var normalizeRealCallRecoveryJobTableName = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice_real_call_profile_recovery_jobs";
4668
4675
  var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
4669
- const database = options.database ?? new Database(options.path ?? ":memory:", {
4676
+ const { Database: SQLiteDatabase } = __require("bun:sqlite");
4677
+ const database = options.database ?? new SQLiteDatabase(options.path ?? ":memory:", {
4670
4678
  create: true
4671
4679
  });
4672
4680
  const tableName = normalizeRealCallRecoveryJobTableName(options.tableName ?? "voice_real_call_profile_recovery_jobs");
@@ -4681,6 +4689,7 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
4681
4689
  payload TEXT NOT NULL
4682
4690
  )`);
4683
4691
  const selectStatement = database.query(`SELECT payload FROM "${tableName}" WHERE id = ?1 LIMIT 1`);
4692
+ const listStatement = database.query(`SELECT payload FROM "${tableName}" ORDER BY sort_at DESC, id DESC`);
4684
4693
  const upsertStatement = database.query(`INSERT INTO "${tableName}" (id, sort_at, payload)
4685
4694
  VALUES (?1, ?2, ?3)
4686
4695
  ON CONFLICT(id) DO UPDATE SET sort_at = excluded.sort_at, payload = excluded.payload`);
@@ -4707,6 +4716,10 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
4707
4716
  get(id) {
4708
4717
  return readJob(id);
4709
4718
  },
4719
+ list(input = {}) {
4720
+ const limit = Number.isFinite(input.limit) && input.limit !== undefined && input.limit > 0 ? Math.floor(input.limit) : 50;
4721
+ return listStatement.all().map((row) => JSON.parse(row.payload)).filter((job) => !input.actionId || job.actionId === input.actionId).filter((job) => !input.status || job.status === input.status).slice(0, limit);
4722
+ },
4710
4723
  update(id, update) {
4711
4724
  const existing = readJob(id);
4712
4725
  if (!existing) {
@@ -5447,6 +5460,32 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
5447
5460
  };
5448
5461
  };
5449
5462
  routes.get(`${path}/actions`, async () => Response.json(await listActions(), { headers: options.headers }));
5463
+ routes.get(`${path}/actions/jobs`, async ({
5464
+ query,
5465
+ set
5466
+ }) => {
5467
+ if (!options.jobStore?.list) {
5468
+ set.status = 501;
5469
+ return Response.json({
5470
+ jobs: [],
5471
+ message: "No real-call profile recovery job list store is configured.",
5472
+ ok: false
5473
+ }, { headers: options.headers });
5474
+ }
5475
+ const actionId = Object.keys(realCallProfileActionPaths).includes(query.actionId ?? "") ? query.actionId : undefined;
5476
+ const status = ["fail", "pass", "queued", "running"].includes(query.status ?? "") ? query.status : undefined;
5477
+ const limit = Number(query.limit);
5478
+ const jobs = await options.jobStore.list({
5479
+ actionId,
5480
+ limit: Number.isFinite(limit) && limit > 0 ? limit : undefined,
5481
+ status
5482
+ });
5483
+ return Response.json({
5484
+ generatedAt: new Date().toISOString(),
5485
+ jobs,
5486
+ ok: true
5487
+ }, { headers: options.headers });
5488
+ });
5450
5489
  routes.get(`${path}/actions/:jobId`, async ({
5451
5490
  params,
5452
5491
  set
package/dist/index.d.ts CHANGED
@@ -35,7 +35,7 @@ export { applyVoiceProfileSwitchGuard, buildVoiceProfileSwitchReadinessReport, b
35
35
  export type { VoiceProfileSwitchGuardAction, VoiceProfileSwitchGuardDecision, VoiceProfileSwitchGuardMode, VoiceProfileSwitchGuardOptions, VoiceProfileSwitchObservedSignals, VoiceProfileSwitchLiveDecisionEvidence, VoiceProfileSwitchLiveDecisionReport, VoiceProfileSwitchLiveDecisionReportOptions, VoiceProfileSwitchLiveDecisionRoutesOptions, VoiceProfileSwitchLiveDecisionSession, VoiceProfileSwitchPolicyProofCase, VoiceProfileSwitchPolicyProofCaseResult, VoiceProfileSwitchPolicyProofOptions, VoiceProfileSwitchPolicyProofReport, VoiceProfileSwitchPolicyProofRoutesOptions, VoiceProfileSwitchReadinessIssue, VoiceProfileSwitchReadinessOptions, VoiceProfileSwitchReadinessReport, VoiceProfileSwitchReadinessRoutesOptions, VoiceProfileSwitchReadinessStatus, VoiceProfileSwitchRecommendation, VoiceProfileSwitchRecommendationOptions } from './profileSwitchRecommendation';
36
36
  export { buildVoiceProviderDecisionTraceReport, createVoiceProviderDecisionTraceEvent, createVoiceProviderDecisionTraceRoutes, listVoiceProviderDecisionTraces, renderVoiceProviderDecisionTraceHTML, renderVoiceProviderDecisionTraceMarkdown } from './providerDecisionTraces';
37
37
  export type { VoiceProviderDecisionStatus, VoiceProviderDecisionSurfaceReport, VoiceProviderDecisionTrace, VoiceProviderDecisionTraceInput, VoiceProviderDecisionTraceIssue, VoiceProviderDecisionTraceReport, VoiceProviderDecisionTraceReportOptions, VoiceProviderDecisionTraceRoutesOptions } from './providerDecisionTraces';
38
- export type { VoiceProofTrendAssertionInput, VoiceProofTrendAssertionReport, VoiceProofTrendCycle, VoiceProofTrendProfileDefinition, VoiceProofTrendProfileRecommendation, VoiceProofTrendProfileSummaryOptions, VoiceProofTrendProfileSummary, VoiceProofTrendProviderRecommendation, VoiceProofTrendProviderSummary, VoiceProofTrendRecommendation, VoiceProofTrendRecommendationOptions, VoiceProofTrendRecommendationReport, VoiceProofTrendRecommendationRoutesOptions, VoiceProofTrendRecommendationStatus, VoiceProofTrendRecommendationSurface, VoiceProofTrendRealCallProfileEvidence, VoiceProofTrendRealCallProfileReportOptions, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, VoiceProofTrendRuntimeChannelSummary, VoiceProofTrendStatus, VoiceProofTrendSummary, VoiceRealCallProfileDefault, VoiceRealCallProfileDefaultsOptions, VoiceRealCallProfileDefaultsReport, VoiceRealCallProfileHistoryOptions, VoiceRealCallProfileHistoryReport, VoiceRealCallProfileHistoryRoutesOptions, VoiceRealCallProfileProviderRouteOptions, VoiceRealCallProfileReadinessCheckOptions, VoiceRealCallProfileRecoveryActionOptions, VoiceRealCallProfileRecoveryAction, VoiceRealCallProfileRecoveryActionHandler, VoiceRealCallProfileRecoveryActionHandlerInput, VoiceRealCallProfileRecoveryActionId, VoiceRealCallProfileRecoveryActionResult, VoiceRealCallProfileRecoveryActionRoutesOptions, VoiceRealCallProfileRecoveryJob, VoiceRealCallProfileRecoveryJobCreateInput, VoiceRealCallProfileRecoveryJobStatus, VoiceRealCallProfileRecoveryJobStore, VoiceRealCallProfileRecoveryJobUpdate, VoiceSQLiteRealCallProfileRecoveryJobStoreOptions, VoiceRealCallProfileTraceEvidenceOptions, VoiceRealCallProfileTraceStoreEvidenceOptions } from './proofTrends';
38
+ export type { VoiceProofTrendAssertionInput, VoiceProofTrendAssertionReport, VoiceProofTrendCycle, VoiceProofTrendProfileDefinition, VoiceProofTrendProfileRecommendation, VoiceProofTrendProfileSummaryOptions, VoiceProofTrendProfileSummary, VoiceProofTrendProviderRecommendation, VoiceProofTrendProviderSummary, VoiceProofTrendRecommendation, VoiceProofTrendRecommendationOptions, VoiceProofTrendRecommendationReport, VoiceProofTrendRecommendationRoutesOptions, VoiceProofTrendRecommendationStatus, VoiceProofTrendRecommendationSurface, VoiceProofTrendRealCallProfileEvidence, VoiceProofTrendRealCallProfileReportOptions, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, VoiceProofTrendRuntimeChannelSummary, VoiceProofTrendStatus, VoiceProofTrendSummary, VoiceRealCallProfileDefault, VoiceRealCallProfileDefaultsOptions, VoiceRealCallProfileDefaultsReport, VoiceRealCallProfileHistoryOptions, VoiceRealCallProfileHistoryReport, VoiceRealCallProfileHistoryRoutesOptions, VoiceRealCallProfileProviderRouteOptions, VoiceRealCallProfileReadinessCheckOptions, VoiceRealCallProfileRecoveryActionOptions, VoiceRealCallProfileRecoveryAction, VoiceRealCallProfileRecoveryActionHandler, VoiceRealCallProfileRecoveryActionHandlerInput, VoiceRealCallProfileRecoveryActionId, VoiceRealCallProfileRecoveryActionResult, VoiceRealCallProfileRecoveryActionRoutesOptions, VoiceRealCallProfileRecoveryJob, VoiceRealCallProfileRecoveryJobCreateInput, VoiceRealCallProfileRecoveryJobListOptions, VoiceRealCallProfileRecoveryJobStatus, VoiceRealCallProfileRecoveryJobStore, VoiceRealCallProfileRecoveryJobUpdate, VoiceSQLiteRealCallProfileRecoveryJobStoreOptions, VoiceRealCallProfileTraceEvidenceOptions, VoiceRealCallProfileTraceStoreEvidenceOptions } from './proofTrends';
39
39
  export { assertVoiceSloCalibration, buildVoiceSloCalibrationReport, buildVoiceSloReadinessThresholdReport, createVoiceSloReadinessThresholdOptions, createVoiceSloReadinessThresholdRoutes, createVoiceSloThresholdProfile, createVoiceSloCalibrationRoutes, renderVoiceSloCalibrationMarkdown, renderVoiceSloReadinessThresholdHTML, renderVoiceSloReadinessThresholdMarkdown } from './sloCalibration';
40
40
  export type { VoiceSloCalibrationMetricKey, VoiceSloCalibrationOptions, VoiceSloCalibrationReport, VoiceSloCalibrationRoutesOptions, VoiceSloCalibrationSample, VoiceSloCalibrationStatus, VoiceSloCalibrationThreshold, VoiceSloCalibrationThresholds, VoiceSloReadinessThresholdReport, VoiceSloReadinessThresholdReportOptions, VoiceSloReadinessThresholdOptions, VoiceSloReadinessThresholdRoutesOptions, VoiceSloThresholdProfile } from './sloCalibration';
41
41
  export { assertVoiceLiveOpsControlEvidence, assertVoiceLiveOpsEvidence, buildVoiceLiveOpsControlState, createVoiceLiveOpsController, createVoiceLiveOpsRoutes, createVoiceMemoryLiveOpsControlStore, evaluateVoiceLiveOpsControlEvidence, evaluateVoiceLiveOpsEvidence, getVoiceLiveOpsControlStatus, VOICE_LIVE_OPS_ACTIONS } from './liveOps';
package/dist/index.js CHANGED
@@ -68,6 +68,7 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
68
68
  }
69
69
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
70
70
  };
71
+ var __require = import.meta.require;
71
72
 
72
73
  // src/audioConditioning.ts
73
74
  var DEFAULT_TARGET_LEVEL = 0.08;
@@ -15376,7 +15377,6 @@ var createVoiceCompetitiveCoverageRoutes = (options) => {
15376
15377
  };
15377
15378
  // src/proofTrends.ts
15378
15379
  import { Elysia as Elysia22 } from "elysia";
15379
- import { Database } from "bun:sqlite";
15380
15380
  var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
15381
15381
  var DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS = [
15382
15382
  {
@@ -16118,6 +16118,13 @@ var createVoiceInMemoryRealCallProfileRecoveryJobStore = (options = {}) => {
16118
16118
  get(id) {
16119
16119
  return jobs.get(id);
16120
16120
  },
16121
+ list(input = {}) {
16122
+ const limit = Number.isFinite(input.limit) && input.limit !== undefined && input.limit > 0 ? Math.floor(input.limit) : 50;
16123
+ return [...jobs.values()].filter((job) => !input.actionId || job.actionId === input.actionId).filter((job) => !input.status || job.status === input.status).sort((first, second) => {
16124
+ const updatedDelta = Date.parse(second.updatedAt) - Date.parse(first.updatedAt);
16125
+ return updatedDelta === 0 ? second.id.localeCompare(first.id) : updatedDelta;
16126
+ }).slice(0, limit);
16127
+ },
16121
16128
  update(id, update) {
16122
16129
  const existing = jobs.get(id);
16123
16130
  if (!existing) {
@@ -16135,7 +16142,8 @@ var createVoiceInMemoryRealCallProfileRecoveryJobStore = (options = {}) => {
16135
16142
  };
16136
16143
  var normalizeRealCallRecoveryJobTableName = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice_real_call_profile_recovery_jobs";
16137
16144
  var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
16138
- const database = options.database ?? new Database(options.path ?? ":memory:", {
16145
+ const { Database: SQLiteDatabase } = __require("bun:sqlite");
16146
+ const database = options.database ?? new SQLiteDatabase(options.path ?? ":memory:", {
16139
16147
  create: true
16140
16148
  });
16141
16149
  const tableName = normalizeRealCallRecoveryJobTableName(options.tableName ?? "voice_real_call_profile_recovery_jobs");
@@ -16150,6 +16158,7 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
16150
16158
  payload TEXT NOT NULL
16151
16159
  )`);
16152
16160
  const selectStatement = database.query(`SELECT payload FROM "${tableName}" WHERE id = ?1 LIMIT 1`);
16161
+ const listStatement = database.query(`SELECT payload FROM "${tableName}" ORDER BY sort_at DESC, id DESC`);
16153
16162
  const upsertStatement = database.query(`INSERT INTO "${tableName}" (id, sort_at, payload)
16154
16163
  VALUES (?1, ?2, ?3)
16155
16164
  ON CONFLICT(id) DO UPDATE SET sort_at = excluded.sort_at, payload = excluded.payload`);
@@ -16176,6 +16185,10 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
16176
16185
  get(id) {
16177
16186
  return readJob(id);
16178
16187
  },
16188
+ list(input = {}) {
16189
+ const limit = Number.isFinite(input.limit) && input.limit !== undefined && input.limit > 0 ? Math.floor(input.limit) : 50;
16190
+ return listStatement.all().map((row) => JSON.parse(row.payload)).filter((job) => !input.actionId || job.actionId === input.actionId).filter((job) => !input.status || job.status === input.status).slice(0, limit);
16191
+ },
16179
16192
  update(id, update) {
16180
16193
  const existing = readJob(id);
16181
16194
  if (!existing) {
@@ -16916,6 +16929,32 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
16916
16929
  };
16917
16930
  };
16918
16931
  routes.get(`${path}/actions`, async () => Response.json(await listActions(), { headers: options.headers }));
16932
+ routes.get(`${path}/actions/jobs`, async ({
16933
+ query,
16934
+ set
16935
+ }) => {
16936
+ if (!options.jobStore?.list) {
16937
+ set.status = 501;
16938
+ return Response.json({
16939
+ jobs: [],
16940
+ message: "No real-call profile recovery job list store is configured.",
16941
+ ok: false
16942
+ }, { headers: options.headers });
16943
+ }
16944
+ const actionId = Object.keys(realCallProfileActionPaths).includes(query.actionId ?? "") ? query.actionId : undefined;
16945
+ const status = ["fail", "pass", "queued", "running"].includes(query.status ?? "") ? query.status : undefined;
16946
+ const limit = Number(query.limit);
16947
+ const jobs = await options.jobStore.list({
16948
+ actionId,
16949
+ limit: Number.isFinite(limit) && limit > 0 ? limit : undefined,
16950
+ status
16951
+ });
16952
+ return Response.json({
16953
+ generatedAt: new Date().toISOString(),
16954
+ jobs,
16955
+ ok: true
16956
+ }, { headers: options.headers });
16957
+ });
16919
16958
  routes.get(`${path}/actions/:jobId`, async ({
16920
16959
  params,
16921
16960
  set
@@ -23619,7 +23658,7 @@ import { Elysia as Elysia45 } from "elysia";
23619
23658
 
23620
23659
  // src/telephony/plivo.ts
23621
23660
  import { Buffer as Buffer5 } from "buffer";
23622
- import { Database as Database2 } from "bun:sqlite";
23661
+ import { Database } from "bun:sqlite";
23623
23662
  import { Elysia as Elysia41 } from "elysia";
23624
23663
 
23625
23664
  // src/telephony/contract.ts
@@ -24746,7 +24785,7 @@ var resolvePlivoNonceTableName = (input) => {
24746
24785
  };
24747
24786
  var getPlivoNonceExpiresAt = (ttlSeconds) => typeof ttlSeconds === "number" && ttlSeconds > 0 ? Date.now() + Math.ceil(ttlSeconds * 1000) : null;
24748
24787
  var createVoiceSQLitePlivoWebhookNonceStore = (options) => {
24749
- const database = options.database ?? new Database2(options.path ?? ":memory:", {
24788
+ const database = options.database ?? new Database(options.path ?? ":memory:", {
24750
24789
  create: true
24751
24790
  });
24752
24791
  const tableName = resolvePlivoNonceTableName({
@@ -25146,7 +25185,7 @@ var createPlivoVoiceRoutes = (options = {}) => {
25146
25185
 
25147
25186
  // src/telephony/telnyx.ts
25148
25187
  import { Buffer as Buffer6 } from "buffer";
25149
- import { Database as Database3 } from "bun:sqlite";
25188
+ import { Database as Database2 } from "bun:sqlite";
25150
25189
  import { Elysia as Elysia42 } from "elysia";
25151
25190
  var escapeXml4 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
25152
25191
  var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
@@ -25346,7 +25385,7 @@ var resolveTelnyxEventTableName = (input) => {
25346
25385
  };
25347
25386
  var getTelnyxEventExpiresAt = (ttlSeconds) => typeof ttlSeconds === "number" && ttlSeconds > 0 ? Date.now() + Math.ceil(ttlSeconds * 1000) : null;
25348
25387
  var createVoiceSQLiteTelnyxWebhookEventStore = (options) => {
25349
- const database = options.database ?? new Database3(options.path ?? ":memory:", {
25388
+ const database = options.database ?? new Database2(options.path ?? ":memory:", {
25350
25389
  create: true
25351
25390
  });
25352
25391
  const tableName = resolveTelnyxEventTableName({
@@ -29077,7 +29116,7 @@ var createVoicePostgresRuntimeStorage = (options) => {
29077
29116
  };
29078
29117
 
29079
29118
  // src/sqliteStore.ts
29080
- import { Database as Database4 } from "bun:sqlite";
29119
+ import { Database as Database3 } from "bun:sqlite";
29081
29120
  var normalizeTableNameSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
29082
29121
  var resolveTableName = (input) => {
29083
29122
  if (input.options.tableName) {
@@ -29088,7 +29127,7 @@ var resolveTableName = (input) => {
29088
29127
  return `${prefix}_${fallback}`;
29089
29128
  };
29090
29129
  var openVoiceSQLiteDatabase = (path) => {
29091
- const database = new Database4(path, {
29130
+ const database = new Database3(path, {
29092
29131
  create: true
29093
29132
  });
29094
29133
  database.exec("PRAGMA journal_mode = WAL;");
@@ -29867,7 +29906,7 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
29867
29906
 
29868
29907
  // src/observabilityExport.ts
29869
29908
  import { Elysia as Elysia53 } from "elysia";
29870
- import { Database as Database5 } from "bun:sqlite";
29909
+ import { Database as Database4 } from "bun:sqlite";
29871
29910
  import { createHash } from "crypto";
29872
29911
  import { mkdir as mkdir4, readFile as readFile2, stat, unlink } from "fs/promises";
29873
29912
  import { join as join3 } from "path";
@@ -31486,7 +31525,7 @@ var loadVoiceObservabilityExportReplaySource = async (source) => {
31486
31525
  if (!source.database && !source.path) {
31487
31526
  throw new Error("SQLite observability export replay requires source.database or source.path.");
31488
31527
  }
31489
- const database = source.database ?? new Database5(source.path, { create: false });
31528
+ const database = source.database ?? new Database4(source.path, { create: false });
31490
31529
  const table2 = quoteObservabilityIdentifier(normalizeObservabilityIdentifier(source.tableName));
31491
31530
  const row2 = database.query(`SELECT manifest_json, artifact_index_json, payload_json FROM ${table2} WHERE run_id = $runId`).get({ $runId: source.runId });
31492
31531
  if (!row2) {
@@ -31563,7 +31602,7 @@ var deliverObservabilityExportToSQLite = async (input) => {
31563
31602
  if (!input.destination.database && !input.destination.path) {
31564
31603
  throw new Error("SQLite observability export delivery requires destination.database or destination.path.");
31565
31604
  }
31566
- const database = input.destination.database ?? new Database5(input.destination.path, { create: true });
31605
+ const database = input.destination.database ?? new Database4(input.destination.path, { create: true });
31567
31606
  const table = quoteObservabilityIdentifier(normalizeObservabilityIdentifier(input.destination.tableName));
31568
31607
  const record = buildObservabilityExportDatabaseRecord(input);
31569
31608
  database.exec(`CREATE TABLE IF NOT EXISTS ${table} (
@@ -1,5 +1,5 @@
1
1
  import { Elysia } from 'elysia';
2
- import { Database } from 'bun:sqlite';
2
+ import type { Database } from 'bun:sqlite';
3
3
  import type { VoiceProductionReadinessAction, VoiceProductionReadinessCheck } from './productionReadiness';
4
4
  import type { StoredVoiceTraceEvent, VoiceTraceEventStore } from './trace';
5
5
  export type VoiceProofTrendStatus = 'empty' | 'fail' | 'pass' | 'stale';
@@ -414,9 +414,15 @@ export type VoiceRealCallProfileRecoveryJobCreateInput = {
414
414
  status?: VoiceRealCallProfileRecoveryJobStatus;
415
415
  };
416
416
  export type VoiceRealCallProfileRecoveryJobUpdate = Partial<Pick<VoiceRealCallProfileRecoveryJob, 'completedAt' | 'message' | 'ok' | 'report' | 'startedAt' | 'status' | 'updatedAt'>>;
417
+ export type VoiceRealCallProfileRecoveryJobListOptions = {
418
+ actionId?: VoiceRealCallProfileRecoveryActionId;
419
+ limit?: number;
420
+ status?: VoiceRealCallProfileRecoveryJobStatus;
421
+ };
417
422
  export type VoiceRealCallProfileRecoveryJobStore = {
418
423
  create(input: VoiceRealCallProfileRecoveryJobCreateInput): Promise<VoiceRealCallProfileRecoveryJob> | VoiceRealCallProfileRecoveryJob;
419
424
  get(id: string): Promise<VoiceRealCallProfileRecoveryJob | undefined> | VoiceRealCallProfileRecoveryJob | undefined;
425
+ list?(options?: VoiceRealCallProfileRecoveryJobListOptions): Promise<VoiceRealCallProfileRecoveryJob[]> | VoiceRealCallProfileRecoveryJob[];
420
426
  update(id: string, update: VoiceRealCallProfileRecoveryJobUpdate): Promise<VoiceRealCallProfileRecoveryJob | undefined> | VoiceRealCallProfileRecoveryJob | undefined;
421
427
  };
422
428
  export type VoiceSQLiteRealCallProfileRecoveryJobStoreOptions = {
@@ -68,6 +68,7 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
68
68
  }
69
69
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
70
70
  };
71
+ var __require = import.meta.require;
71
72
 
72
73
  // src/react/useVoiceOpsStatus.tsx
73
74
  import { useEffect, useRef, useSyncExternalStore } from "react";
@@ -1494,7 +1495,6 @@ var useVoiceProofTrends = (path = "/api/voice/proof-trends", options = {}) => {
1494
1495
 
1495
1496
  // src/proofTrends.ts
1496
1497
  import { Elysia } from "elysia";
1497
- import { Database } from "bun:sqlite";
1498
1498
  var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
1499
1499
  var DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS = [
1500
1500
  {
@@ -2236,6 +2236,13 @@ var createVoiceInMemoryRealCallProfileRecoveryJobStore = (options = {}) => {
2236
2236
  get(id) {
2237
2237
  return jobs.get(id);
2238
2238
  },
2239
+ list(input = {}) {
2240
+ const limit = Number.isFinite(input.limit) && input.limit !== undefined && input.limit > 0 ? Math.floor(input.limit) : 50;
2241
+ return [...jobs.values()].filter((job) => !input.actionId || job.actionId === input.actionId).filter((job) => !input.status || job.status === input.status).sort((first, second) => {
2242
+ const updatedDelta = Date.parse(second.updatedAt) - Date.parse(first.updatedAt);
2243
+ return updatedDelta === 0 ? second.id.localeCompare(first.id) : updatedDelta;
2244
+ }).slice(0, limit);
2245
+ },
2239
2246
  update(id, update) {
2240
2247
  const existing = jobs.get(id);
2241
2248
  if (!existing) {
@@ -2253,7 +2260,8 @@ var createVoiceInMemoryRealCallProfileRecoveryJobStore = (options = {}) => {
2253
2260
  };
2254
2261
  var normalizeRealCallRecoveryJobTableName = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice_real_call_profile_recovery_jobs";
2255
2262
  var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
2256
- const database = options.database ?? new Database(options.path ?? ":memory:", {
2263
+ const { Database: SQLiteDatabase } = __require("bun:sqlite");
2264
+ const database = options.database ?? new SQLiteDatabase(options.path ?? ":memory:", {
2257
2265
  create: true
2258
2266
  });
2259
2267
  const tableName = normalizeRealCallRecoveryJobTableName(options.tableName ?? "voice_real_call_profile_recovery_jobs");
@@ -2268,6 +2276,7 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
2268
2276
  payload TEXT NOT NULL
2269
2277
  )`);
2270
2278
  const selectStatement = database.query(`SELECT payload FROM "${tableName}" WHERE id = ?1 LIMIT 1`);
2279
+ const listStatement = database.query(`SELECT payload FROM "${tableName}" ORDER BY sort_at DESC, id DESC`);
2271
2280
  const upsertStatement = database.query(`INSERT INTO "${tableName}" (id, sort_at, payload)
2272
2281
  VALUES (?1, ?2, ?3)
2273
2282
  ON CONFLICT(id) DO UPDATE SET sort_at = excluded.sort_at, payload = excluded.payload`);
@@ -2294,6 +2303,10 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
2294
2303
  get(id) {
2295
2304
  return readJob(id);
2296
2305
  },
2306
+ list(input = {}) {
2307
+ const limit = Number.isFinite(input.limit) && input.limit !== undefined && input.limit > 0 ? Math.floor(input.limit) : 50;
2308
+ return listStatement.all().map((row) => JSON.parse(row.payload)).filter((job) => !input.actionId || job.actionId === input.actionId).filter((job) => !input.status || job.status === input.status).slice(0, limit);
2309
+ },
2297
2310
  update(id, update) {
2298
2311
  const existing = readJob(id);
2299
2312
  if (!existing) {
@@ -3034,6 +3047,32 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
3034
3047
  };
3035
3048
  };
3036
3049
  routes.get(`${path}/actions`, async () => Response.json(await listActions(), { headers: options.headers }));
3050
+ routes.get(`${path}/actions/jobs`, async ({
3051
+ query,
3052
+ set
3053
+ }) => {
3054
+ if (!options.jobStore?.list) {
3055
+ set.status = 501;
3056
+ return Response.json({
3057
+ jobs: [],
3058
+ message: "No real-call profile recovery job list store is configured.",
3059
+ ok: false
3060
+ }, { headers: options.headers });
3061
+ }
3062
+ const actionId = Object.keys(realCallProfileActionPaths).includes(query.actionId ?? "") ? query.actionId : undefined;
3063
+ const status = ["fail", "pass", "queued", "running"].includes(query.status ?? "") ? query.status : undefined;
3064
+ const limit = Number(query.limit);
3065
+ const jobs = await options.jobStore.list({
3066
+ actionId,
3067
+ limit: Number.isFinite(limit) && limit > 0 ? limit : undefined,
3068
+ status
3069
+ });
3070
+ return Response.json({
3071
+ generatedAt: new Date().toISOString(),
3072
+ jobs,
3073
+ ok: true
3074
+ }, { headers: options.headers });
3075
+ });
3037
3076
  routes.get(`${path}/actions/:jobId`, async ({
3038
3077
  params,
3039
3078
  set
@@ -68,6 +68,7 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
68
68
  }
69
69
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
70
70
  };
71
+ var __require = import.meta.require;
71
72
 
72
73
  // src/client/campaignDialerProof.ts
73
74
  var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
@@ -68,6 +68,7 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
68
68
  }
69
69
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
70
70
  };
71
+ var __require = import.meta.require;
71
72
 
72
73
  // src/turnDetection.ts
73
74
  var DEFAULT_SILENCE_MS = 700;
package/dist/vue/index.js CHANGED
@@ -68,6 +68,7 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
68
68
  }
69
69
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
70
70
  };
71
+ var __require = import.meta.require;
71
72
 
72
73
  // src/vue/VoiceOpsStatus.ts
73
74
  import { defineComponent, h } from "vue";
@@ -1415,7 +1416,6 @@ import { defineComponent as defineComponent5, h as h5 } from "vue";
1415
1416
 
1416
1417
  // src/proofTrends.ts
1417
1418
  import { Elysia } from "elysia";
1418
- import { Database } from "bun:sqlite";
1419
1419
  var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
1420
1420
  var DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS = [
1421
1421
  {
@@ -2157,6 +2157,13 @@ var createVoiceInMemoryRealCallProfileRecoveryJobStore = (options = {}) => {
2157
2157
  get(id) {
2158
2158
  return jobs.get(id);
2159
2159
  },
2160
+ list(input = {}) {
2161
+ const limit = Number.isFinite(input.limit) && input.limit !== undefined && input.limit > 0 ? Math.floor(input.limit) : 50;
2162
+ return [...jobs.values()].filter((job) => !input.actionId || job.actionId === input.actionId).filter((job) => !input.status || job.status === input.status).sort((first, second) => {
2163
+ const updatedDelta = Date.parse(second.updatedAt) - Date.parse(first.updatedAt);
2164
+ return updatedDelta === 0 ? second.id.localeCompare(first.id) : updatedDelta;
2165
+ }).slice(0, limit);
2166
+ },
2160
2167
  update(id, update) {
2161
2168
  const existing = jobs.get(id);
2162
2169
  if (!existing) {
@@ -2174,7 +2181,8 @@ var createVoiceInMemoryRealCallProfileRecoveryJobStore = (options = {}) => {
2174
2181
  };
2175
2182
  var normalizeRealCallRecoveryJobTableName = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice_real_call_profile_recovery_jobs";
2176
2183
  var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
2177
- const database = options.database ?? new Database(options.path ?? ":memory:", {
2184
+ const { Database: SQLiteDatabase } = __require("bun:sqlite");
2185
+ const database = options.database ?? new SQLiteDatabase(options.path ?? ":memory:", {
2178
2186
  create: true
2179
2187
  });
2180
2188
  const tableName = normalizeRealCallRecoveryJobTableName(options.tableName ?? "voice_real_call_profile_recovery_jobs");
@@ -2189,6 +2197,7 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
2189
2197
  payload TEXT NOT NULL
2190
2198
  )`);
2191
2199
  const selectStatement = database.query(`SELECT payload FROM "${tableName}" WHERE id = ?1 LIMIT 1`);
2200
+ const listStatement = database.query(`SELECT payload FROM "${tableName}" ORDER BY sort_at DESC, id DESC`);
2192
2201
  const upsertStatement = database.query(`INSERT INTO "${tableName}" (id, sort_at, payload)
2193
2202
  VALUES (?1, ?2, ?3)
2194
2203
  ON CONFLICT(id) DO UPDATE SET sort_at = excluded.sort_at, payload = excluded.payload`);
@@ -2215,6 +2224,10 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
2215
2224
  get(id) {
2216
2225
  return readJob(id);
2217
2226
  },
2227
+ list(input = {}) {
2228
+ const limit = Number.isFinite(input.limit) && input.limit !== undefined && input.limit > 0 ? Math.floor(input.limit) : 50;
2229
+ return listStatement.all().map((row) => JSON.parse(row.payload)).filter((job) => !input.actionId || job.actionId === input.actionId).filter((job) => !input.status || job.status === input.status).slice(0, limit);
2230
+ },
2218
2231
  update(id, update) {
2219
2232
  const existing = readJob(id);
2220
2233
  if (!existing) {
@@ -2955,6 +2968,32 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
2955
2968
  };
2956
2969
  };
2957
2970
  routes.get(`${path}/actions`, async () => Response.json(await listActions(), { headers: options.headers }));
2971
+ routes.get(`${path}/actions/jobs`, async ({
2972
+ query,
2973
+ set
2974
+ }) => {
2975
+ if (!options.jobStore?.list) {
2976
+ set.status = 501;
2977
+ return Response.json({
2978
+ jobs: [],
2979
+ message: "No real-call profile recovery job list store is configured.",
2980
+ ok: false
2981
+ }, { headers: options.headers });
2982
+ }
2983
+ const actionId = Object.keys(realCallProfileActionPaths).includes(query.actionId ?? "") ? query.actionId : undefined;
2984
+ const status = ["fail", "pass", "queued", "running"].includes(query.status ?? "") ? query.status : undefined;
2985
+ const limit = Number(query.limit);
2986
+ const jobs = await options.jobStore.list({
2987
+ actionId,
2988
+ limit: Number.isFinite(limit) && limit > 0 ? limit : undefined,
2989
+ status
2990
+ });
2991
+ return Response.json({
2992
+ generatedAt: new Date().toISOString(),
2993
+ jobs,
2994
+ ok: true
2995
+ }, { headers: options.headers });
2996
+ });
2958
2997
  routes.get(`${path}/actions/:jobId`, async ({
2959
2998
  params,
2960
2999
  set
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.374",
3
+ "version": "0.0.22-beta.376",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",