@absolutejs/voice 0.0.22-beta.375 → 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
@@ -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) {
@@ -4682,6 +4689,7 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
4682
4689
  payload TEXT NOT NULL
4683
4690
  )`);
4684
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`);
4685
4693
  const upsertStatement = database.query(`INSERT INTO "${tableName}" (id, sort_at, payload)
4686
4694
  VALUES (?1, ?2, ?3)
4687
4695
  ON CONFLICT(id) DO UPDATE SET sort_at = excluded.sort_at, payload = excluded.payload`);
@@ -4708,6 +4716,10 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
4708
4716
  get(id) {
4709
4717
  return readJob(id);
4710
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
+ },
4711
4723
  update(id, update) {
4712
4724
  const existing = readJob(id);
4713
4725
  if (!existing) {
@@ -5448,6 +5460,32 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
5448
5460
  };
5449
5461
  };
5450
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
+ });
5451
5489
  routes.get(`${path}/actions/:jobId`, async ({
5452
5490
  params,
5453
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
@@ -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) {
@@ -16151,6 +16158,7 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
16151
16158
  payload TEXT NOT NULL
16152
16159
  )`);
16153
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`);
16154
16162
  const upsertStatement = database.query(`INSERT INTO "${tableName}" (id, sort_at, payload)
16155
16163
  VALUES (?1, ?2, ?3)
16156
16164
  ON CONFLICT(id) DO UPDATE SET sort_at = excluded.sort_at, payload = excluded.payload`);
@@ -16177,6 +16185,10 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
16177
16185
  get(id) {
16178
16186
  return readJob(id);
16179
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
+ },
16180
16192
  update(id, update) {
16181
16193
  const existing = readJob(id);
16182
16194
  if (!existing) {
@@ -16917,6 +16929,32 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
16917
16929
  };
16918
16930
  };
16919
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
+ });
16920
16958
  routes.get(`${path}/actions/:jobId`, async ({
16921
16959
  params,
16922
16960
  set
@@ -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 = {
@@ -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) {
@@ -2269,6 +2276,7 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
2269
2276
  payload TEXT NOT NULL
2270
2277
  )`);
2271
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`);
2272
2280
  const upsertStatement = database.query(`INSERT INTO "${tableName}" (id, sort_at, payload)
2273
2281
  VALUES (?1, ?2, ?3)
2274
2282
  ON CONFLICT(id) DO UPDATE SET sort_at = excluded.sort_at, payload = excluded.payload`);
@@ -2295,6 +2303,10 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
2295
2303
  get(id) {
2296
2304
  return readJob(id);
2297
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
+ },
2298
2310
  update(id, update) {
2299
2311
  const existing = readJob(id);
2300
2312
  if (!existing) {
@@ -3035,6 +3047,32 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
3035
3047
  };
3036
3048
  };
3037
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
+ });
3038
3076
  routes.get(`${path}/actions/:jobId`, async ({
3039
3077
  params,
3040
3078
  set
package/dist/vue/index.js CHANGED
@@ -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) {
@@ -2190,6 +2197,7 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
2190
2197
  payload TEXT NOT NULL
2191
2198
  )`);
2192
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`);
2193
2201
  const upsertStatement = database.query(`INSERT INTO "${tableName}" (id, sort_at, payload)
2194
2202
  VALUES (?1, ?2, ?3)
2195
2203
  ON CONFLICT(id) DO UPDATE SET sort_at = excluded.sort_at, payload = excluded.payload`);
@@ -2216,6 +2224,10 @@ var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
2216
2224
  get(id) {
2217
2225
  return readJob(id);
2218
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
+ },
2219
2231
  update(id, update) {
2220
2232
  const existing = readJob(id);
2221
2233
  if (!existing) {
@@ -2956,6 +2968,32 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
2956
2968
  };
2957
2969
  };
2958
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
+ });
2959
2997
  routes.get(`${path}/actions/:jobId`, async ({
2960
2998
  params,
2961
2999
  set
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.375",
3
+ "version": "0.0.22-beta.376",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",