@absolutejs/voice 0.0.22-beta.380 → 0.0.22-beta.382

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.
@@ -4668,7 +4668,7 @@ var buildRealCallProfileReadinessIssues = (report, options) => {
4668
4668
  var uniqueRealCallProfileActions = (actions) => {
4669
4669
  const seen = new Set;
4670
4670
  return actions.filter((action) => {
4671
- const key = `${action.method ?? "GET"}:${action.href}:${action.label}`;
4671
+ const key = `${action.method ?? "GET"}:${action.href}:${action.label}:${action.profileId ?? ""}`;
4672
4672
  if (seen.has(key)) {
4673
4673
  return false;
4674
4674
  }
@@ -4676,6 +4676,16 @@ var uniqueRealCallProfileActions = (actions) => {
4676
4676
  return true;
4677
4677
  });
4678
4678
  };
4679
+ var appendRealCallRecoveryActionQuery = (href, query) => {
4680
+ const entries = Object.entries(query).filter((entry) => entry[1] !== undefined);
4681
+ if (entries.length === 0) {
4682
+ return href;
4683
+ }
4684
+ const [base = href, hash = ""] = href.split("#");
4685
+ const separator = base.includes("?") ? "&" : "?";
4686
+ const search = new URLSearchParams(entries).toString();
4687
+ return `${base}${separator}${search}${hash ? `#${hash}` : ""}`;
4688
+ };
4679
4689
  var buildVoiceRealCallProfileRecoveryActions = (report, options = {}) => {
4680
4690
  const actions = [
4681
4691
  {
@@ -4696,20 +4706,41 @@ var buildVoiceRealCallProfileRecoveryActions = (report, options = {}) => {
4696
4706
  const missingProfiles = [...requiredProfiles].filter((profileId) => !profilesById.has(profileId));
4697
4707
  const warningProfiles = report.defaults.profiles.filter((profile) => (requiredProfiles.size === 0 || requiredProfiles.has(profile.profileId)) && profile.status !== "pass");
4698
4708
  const missingRoleProfiles = report.defaults.profiles.filter((profile) => (options.requiredProviderRoles ?? []).some((role) => !profile.providerRoutes[role]));
4709
+ const summariesByProfile = new Map((report.summary.profiles ?? []).map((profile) => [profile.id, profile]));
4710
+ const missingDepthProfiles = [...requiredProfiles].filter((profileId) => {
4711
+ const summaryProfile = summariesByProfile.get(profileId);
4712
+ if (options.minProfileCycles !== undefined && (summaryProfile?.cycles ?? 0) < options.minProfileCycles) {
4713
+ return true;
4714
+ }
4715
+ if (options.minProfileSessions !== undefined && (summaryProfile?.sessionCount ?? 0) < options.minProfileSessions) {
4716
+ return true;
4717
+ }
4718
+ const requiredProfileSurfaces = options.requiredProfileSurfaces;
4719
+ const requiredSurfaces = requiredProfileSurfaces === undefined ? [] : Array.isArray(requiredProfileSurfaces) ? requiredProfileSurfaces : requiredProfileSurfaces[profileId] ?? [];
4720
+ const observedSurfaces = new Set(summaryProfile?.surfaces ?? []);
4721
+ return requiredSurfaces.some((surface) => !observedSurfaces.has(surface));
4722
+ });
4699
4723
  const ageMs = report.trend.ageMs ?? (report.generatedAt ? Date.now() - new Date(report.generatedAt).getTime() : undefined);
4700
- if (missingProfiles.length > 0 || warningProfiles.length > 0 || missingRoleProfiles.length > 0 || options.minCycles !== undefined && (report.summary.cycles ?? 0) < options.minCycles || options.minActionableProfiles !== undefined && report.defaults.summary.actionableProfiles < options.minActionableProfiles) {
4701
- actions.push({
4702
- description: "Run browser profile proof to collect microphone, WebSocket, live-latency, and provider traces for missing profiles.",
4703
- href: options.browserProofHref ?? "/voice/browser-call-profiles",
4704
- id: "collect-browser-proof",
4705
- label: "Run browser profile proof"
4706
- });
4707
- actions.push({
4708
- description: "Run phone profile proof when required profiles depend on carrier, telephony media, or noisy-call evidence.",
4709
- href: options.phoneProofHref ?? "/api/voice/phone/smoke",
4710
- id: "collect-phone-proof",
4711
- label: "Run phone profile proof"
4712
- });
4724
+ const needsProfileProof = missingProfiles.length > 0 || warningProfiles.length > 0 || missingRoleProfiles.length > 0 || missingDepthProfiles.length > 0 || options.minCycles !== undefined && (report.summary.cycles ?? 0) < options.minCycles || options.minActionableProfiles !== undefined && report.defaults.summary.actionableProfiles < options.minActionableProfiles;
4725
+ if (needsProfileProof) {
4726
+ const targetProfileIds = missingProfiles.length > 0 || missingDepthProfiles.length > 0 ? [...new Set([...missingProfiles, ...missingDepthProfiles])] : [...requiredProfiles];
4727
+ const targets = targetProfileIds.length > 0 ? targetProfileIds : [undefined];
4728
+ for (const profileId of targets) {
4729
+ actions.push({
4730
+ description: profileId ? `Run browser profile proof for ${profileId} to collect microphone, WebSocket, live-latency, and provider traces.` : "Run browser profile proof to collect microphone, WebSocket, live-latency, and provider traces for missing profiles.",
4731
+ href: appendRealCallRecoveryActionQuery(options.browserProofHref ?? "/voice/browser-call-profiles", { profileId }),
4732
+ id: "collect-browser-proof",
4733
+ label: profileId ? `Run browser profile proof for ${profileId}` : "Run browser profile proof",
4734
+ profileId
4735
+ });
4736
+ actions.push({
4737
+ description: profileId ? `Run phone profile proof for ${profileId} when the profile depends on carrier, telephony media, or noisy-call evidence.` : "Run phone profile proof when required profiles depend on carrier, telephony media, or noisy-call evidence.",
4738
+ href: appendRealCallRecoveryActionQuery(options.phoneProofHref ?? "/api/voice/phone/smoke", { profileId }),
4739
+ id: "collect-phone-proof",
4740
+ label: profileId ? `Run phone profile proof for ${profileId}` : "Run phone profile proof",
4741
+ profileId
4742
+ });
4743
+ }
4713
4744
  }
4714
4745
  if (options.maxAgeMs !== undefined && (ageMs === undefined || ageMs > options.maxAgeMs)) {
4715
4746
  actions.push({
@@ -5559,22 +5590,22 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
5559
5590
  productionReadinessHref: options.productionReadinessHref ?? actionPath("refresh")
5560
5591
  }).map((action) => ({
5561
5592
  ...action,
5562
- href: action.id === "collect-browser-proof" ? actionPath("collect-browser-proof") : action.id === "collect-phone-proof" ? actionPath("collect-phone-proof") : action.id === "collect-provider-role-evidence" ? actionPath("collect-provider-role-evidence") : action.href,
5593
+ href: action.id === "collect-browser-proof" ? appendRealCallRecoveryActionQuery(actionPath("collect-browser-proof"), { profileId: action.profileId }) : action.id === "collect-phone-proof" ? appendRealCallRecoveryActionQuery(actionPath("collect-phone-proof"), { profileId: action.profileId }) : action.id === "collect-provider-role-evidence" ? actionPath("collect-provider-role-evidence") : action.href,
5563
5594
  method: action.id === "refresh" && (action.label === "Open real-call profile history" || action.label === "Open operations records") ? "GET" : "POST"
5564
5595
  }));
5565
5596
  return { actions, generatedAt: new Date().toISOString(), report };
5566
5597
  };
5567
- const runActionHandler = async (actionId, report) => {
5598
+ const runActionHandler = async (actionId, report, profileId) => {
5568
5599
  const handler = options.handlers?.[actionId];
5569
5600
  if (!handler) {
5570
5601
  return;
5571
5602
  }
5572
- return await handler({ actionId, report });
5603
+ return await handler({ actionId, profileId, report });
5573
5604
  };
5574
- const runActionAsJob = async (actionId, report) => {
5605
+ const runActionAsJob = async (actionId, report, profileId) => {
5575
5606
  const job = await options.jobStore?.create({
5576
5607
  actionId,
5577
- message: `Queued real-call profile recovery action: ${actionId}.`,
5608
+ message: `Queued real-call profile recovery action: ${actionId}${profileId ? ` for ${profileId}` : ""}.`,
5578
5609
  status: "queued"
5579
5610
  });
5580
5611
  if (!job) {
@@ -5590,7 +5621,7 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
5590
5621
  updatedAt: startedAt
5591
5622
  });
5592
5623
  try {
5593
- const result = await runActionHandler(actionId, report);
5624
+ const result = await runActionHandler(actionId, report, profileId);
5594
5625
  const completedAt = new Date().toISOString();
5595
5626
  const ok = result?.ok ?? true;
5596
5627
  const status = result?.jobStatus ?? (result?.status === "fail" || ok === false ? "fail" : "pass");
@@ -5625,7 +5656,7 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
5625
5656
  status: "pass"
5626
5657
  };
5627
5658
  };
5628
- const runAction = async (actionId) => {
5659
+ const runAction = async (actionId, profileId) => {
5629
5660
  const report = await loadReport();
5630
5661
  const handler = options.handlers?.[actionId];
5631
5662
  if (!handler) {
@@ -5638,12 +5669,12 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
5638
5669
  };
5639
5670
  }
5640
5671
  if (options.jobStore && asyncActionIds.has(actionId)) {
5641
- const queued = await runActionAsJob(actionId, report);
5672
+ const queued = await runActionAsJob(actionId, report, profileId);
5642
5673
  if (queued) {
5643
5674
  return queued;
5644
5675
  }
5645
5676
  }
5646
- const result = await runActionHandler(actionId, report);
5677
+ const result = await runActionHandler(actionId, report, profileId);
5647
5678
  return {
5648
5679
  actionId,
5649
5680
  generatedAt: new Date().toISOString(),
@@ -5702,8 +5733,12 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
5702
5733
  });
5703
5734
  });
5704
5735
  for (const actionId of Object.keys(realCallProfileActionPaths)) {
5705
- routes.post(actionPath(actionId), async ({ set }) => {
5706
- const result = await runAction(actionId);
5736
+ routes.post(actionPath(actionId), async ({
5737
+ query,
5738
+ set
5739
+ }) => {
5740
+ const profileId = query.profileId?.trim() || undefined;
5741
+ const result = await runAction(actionId, profileId);
5707
5742
  if (!result.ok) {
5708
5743
  set.status = 501;
5709
5744
  }
package/dist/index.js CHANGED
@@ -16137,7 +16137,7 @@ var buildRealCallProfileReadinessIssues = (report, options) => {
16137
16137
  var uniqueRealCallProfileActions = (actions) => {
16138
16138
  const seen = new Set;
16139
16139
  return actions.filter((action) => {
16140
- const key = `${action.method ?? "GET"}:${action.href}:${action.label}`;
16140
+ const key = `${action.method ?? "GET"}:${action.href}:${action.label}:${action.profileId ?? ""}`;
16141
16141
  if (seen.has(key)) {
16142
16142
  return false;
16143
16143
  }
@@ -16145,6 +16145,16 @@ var uniqueRealCallProfileActions = (actions) => {
16145
16145
  return true;
16146
16146
  });
16147
16147
  };
16148
+ var appendRealCallRecoveryActionQuery = (href, query) => {
16149
+ const entries = Object.entries(query).filter((entry) => entry[1] !== undefined);
16150
+ if (entries.length === 0) {
16151
+ return href;
16152
+ }
16153
+ const [base = href, hash = ""] = href.split("#");
16154
+ const separator = base.includes("?") ? "&" : "?";
16155
+ const search = new URLSearchParams(entries).toString();
16156
+ return `${base}${separator}${search}${hash ? `#${hash}` : ""}`;
16157
+ };
16148
16158
  var buildVoiceRealCallProfileRecoveryActions = (report, options = {}) => {
16149
16159
  const actions = [
16150
16160
  {
@@ -16165,20 +16175,41 @@ var buildVoiceRealCallProfileRecoveryActions = (report, options = {}) => {
16165
16175
  const missingProfiles = [...requiredProfiles].filter((profileId) => !profilesById.has(profileId));
16166
16176
  const warningProfiles = report.defaults.profiles.filter((profile) => (requiredProfiles.size === 0 || requiredProfiles.has(profile.profileId)) && profile.status !== "pass");
16167
16177
  const missingRoleProfiles = report.defaults.profiles.filter((profile) => (options.requiredProviderRoles ?? []).some((role) => !profile.providerRoutes[role]));
16178
+ const summariesByProfile = new Map((report.summary.profiles ?? []).map((profile) => [profile.id, profile]));
16179
+ const missingDepthProfiles = [...requiredProfiles].filter((profileId) => {
16180
+ const summaryProfile = summariesByProfile.get(profileId);
16181
+ if (options.minProfileCycles !== undefined && (summaryProfile?.cycles ?? 0) < options.minProfileCycles) {
16182
+ return true;
16183
+ }
16184
+ if (options.minProfileSessions !== undefined && (summaryProfile?.sessionCount ?? 0) < options.minProfileSessions) {
16185
+ return true;
16186
+ }
16187
+ const requiredProfileSurfaces = options.requiredProfileSurfaces;
16188
+ const requiredSurfaces = requiredProfileSurfaces === undefined ? [] : Array.isArray(requiredProfileSurfaces) ? requiredProfileSurfaces : requiredProfileSurfaces[profileId] ?? [];
16189
+ const observedSurfaces = new Set(summaryProfile?.surfaces ?? []);
16190
+ return requiredSurfaces.some((surface) => !observedSurfaces.has(surface));
16191
+ });
16168
16192
  const ageMs = report.trend.ageMs ?? (report.generatedAt ? Date.now() - new Date(report.generatedAt).getTime() : undefined);
16169
- if (missingProfiles.length > 0 || warningProfiles.length > 0 || missingRoleProfiles.length > 0 || options.minCycles !== undefined && (report.summary.cycles ?? 0) < options.minCycles || options.minActionableProfiles !== undefined && report.defaults.summary.actionableProfiles < options.minActionableProfiles) {
16170
- actions.push({
16171
- description: "Run browser profile proof to collect microphone, WebSocket, live-latency, and provider traces for missing profiles.",
16172
- href: options.browserProofHref ?? "/voice/browser-call-profiles",
16173
- id: "collect-browser-proof",
16174
- label: "Run browser profile proof"
16175
- });
16176
- actions.push({
16177
- description: "Run phone profile proof when required profiles depend on carrier, telephony media, or noisy-call evidence.",
16178
- href: options.phoneProofHref ?? "/api/voice/phone/smoke",
16179
- id: "collect-phone-proof",
16180
- label: "Run phone profile proof"
16181
- });
16193
+ const needsProfileProof = missingProfiles.length > 0 || warningProfiles.length > 0 || missingRoleProfiles.length > 0 || missingDepthProfiles.length > 0 || options.minCycles !== undefined && (report.summary.cycles ?? 0) < options.minCycles || options.minActionableProfiles !== undefined && report.defaults.summary.actionableProfiles < options.minActionableProfiles;
16194
+ if (needsProfileProof) {
16195
+ const targetProfileIds = missingProfiles.length > 0 || missingDepthProfiles.length > 0 ? [...new Set([...missingProfiles, ...missingDepthProfiles])] : [...requiredProfiles];
16196
+ const targets = targetProfileIds.length > 0 ? targetProfileIds : [undefined];
16197
+ for (const profileId of targets) {
16198
+ actions.push({
16199
+ description: profileId ? `Run browser profile proof for ${profileId} to collect microphone, WebSocket, live-latency, and provider traces.` : "Run browser profile proof to collect microphone, WebSocket, live-latency, and provider traces for missing profiles.",
16200
+ href: appendRealCallRecoveryActionQuery(options.browserProofHref ?? "/voice/browser-call-profiles", { profileId }),
16201
+ id: "collect-browser-proof",
16202
+ label: profileId ? `Run browser profile proof for ${profileId}` : "Run browser profile proof",
16203
+ profileId
16204
+ });
16205
+ actions.push({
16206
+ description: profileId ? `Run phone profile proof for ${profileId} when the profile depends on carrier, telephony media, or noisy-call evidence.` : "Run phone profile proof when required profiles depend on carrier, telephony media, or noisy-call evidence.",
16207
+ href: appendRealCallRecoveryActionQuery(options.phoneProofHref ?? "/api/voice/phone/smoke", { profileId }),
16208
+ id: "collect-phone-proof",
16209
+ label: profileId ? `Run phone profile proof for ${profileId}` : "Run phone profile proof",
16210
+ profileId
16211
+ });
16212
+ }
16182
16213
  }
16183
16214
  if (options.maxAgeMs !== undefined && (ageMs === undefined || ageMs > options.maxAgeMs)) {
16184
16215
  actions.push({
@@ -17028,22 +17059,22 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
17028
17059
  productionReadinessHref: options.productionReadinessHref ?? actionPath("refresh")
17029
17060
  }).map((action) => ({
17030
17061
  ...action,
17031
- href: action.id === "collect-browser-proof" ? actionPath("collect-browser-proof") : action.id === "collect-phone-proof" ? actionPath("collect-phone-proof") : action.id === "collect-provider-role-evidence" ? actionPath("collect-provider-role-evidence") : action.href,
17062
+ href: action.id === "collect-browser-proof" ? appendRealCallRecoveryActionQuery(actionPath("collect-browser-proof"), { profileId: action.profileId }) : action.id === "collect-phone-proof" ? appendRealCallRecoveryActionQuery(actionPath("collect-phone-proof"), { profileId: action.profileId }) : action.id === "collect-provider-role-evidence" ? actionPath("collect-provider-role-evidence") : action.href,
17032
17063
  method: action.id === "refresh" && (action.label === "Open real-call profile history" || action.label === "Open operations records") ? "GET" : "POST"
17033
17064
  }));
17034
17065
  return { actions, generatedAt: new Date().toISOString(), report };
17035
17066
  };
17036
- const runActionHandler = async (actionId, report) => {
17067
+ const runActionHandler = async (actionId, report, profileId) => {
17037
17068
  const handler = options.handlers?.[actionId];
17038
17069
  if (!handler) {
17039
17070
  return;
17040
17071
  }
17041
- return await handler({ actionId, report });
17072
+ return await handler({ actionId, profileId, report });
17042
17073
  };
17043
- const runActionAsJob = async (actionId, report) => {
17074
+ const runActionAsJob = async (actionId, report, profileId) => {
17044
17075
  const job = await options.jobStore?.create({
17045
17076
  actionId,
17046
- message: `Queued real-call profile recovery action: ${actionId}.`,
17077
+ message: `Queued real-call profile recovery action: ${actionId}${profileId ? ` for ${profileId}` : ""}.`,
17047
17078
  status: "queued"
17048
17079
  });
17049
17080
  if (!job) {
@@ -17059,7 +17090,7 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
17059
17090
  updatedAt: startedAt
17060
17091
  });
17061
17092
  try {
17062
- const result = await runActionHandler(actionId, report);
17093
+ const result = await runActionHandler(actionId, report, profileId);
17063
17094
  const completedAt = new Date().toISOString();
17064
17095
  const ok = result?.ok ?? true;
17065
17096
  const status = result?.jobStatus ?? (result?.status === "fail" || ok === false ? "fail" : "pass");
@@ -17094,7 +17125,7 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
17094
17125
  status: "pass"
17095
17126
  };
17096
17127
  };
17097
- const runAction = async (actionId) => {
17128
+ const runAction = async (actionId, profileId) => {
17098
17129
  const report = await loadReport();
17099
17130
  const handler = options.handlers?.[actionId];
17100
17131
  if (!handler) {
@@ -17107,12 +17138,12 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
17107
17138
  };
17108
17139
  }
17109
17140
  if (options.jobStore && asyncActionIds.has(actionId)) {
17110
- const queued = await runActionAsJob(actionId, report);
17141
+ const queued = await runActionAsJob(actionId, report, profileId);
17111
17142
  if (queued) {
17112
17143
  return queued;
17113
17144
  }
17114
17145
  }
17115
- const result = await runActionHandler(actionId, report);
17146
+ const result = await runActionHandler(actionId, report, profileId);
17116
17147
  return {
17117
17148
  actionId,
17118
17149
  generatedAt: new Date().toISOString(),
@@ -17171,8 +17202,12 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
17171
17202
  });
17172
17203
  });
17173
17204
  for (const actionId of Object.keys(realCallProfileActionPaths)) {
17174
- routes.post(actionPath(actionId), async ({ set }) => {
17175
- const result = await runAction(actionId);
17205
+ routes.post(actionPath(actionId), async ({
17206
+ query,
17207
+ set
17208
+ }) => {
17209
+ const profileId = query.profileId?.trim() || undefined;
17210
+ const result = await runAction(actionId, profileId);
17176
17211
  if (!result.ok) {
17177
17212
  set.status = 501;
17178
17213
  }
@@ -377,6 +377,7 @@ export type VoiceRealCallProfileHistoryRoutesOptions = Omit<VoiceRealCallProfile
377
377
  export type VoiceRealCallProfileRecoveryActionId = 'collect-browser-proof' | 'collect-phone-proof' | 'collect-provider-role-evidence' | 'refresh';
378
378
  export type VoiceRealCallProfileRecoveryAction = VoiceProductionReadinessAction & {
379
379
  id: VoiceRealCallProfileRecoveryActionId;
380
+ profileId?: string;
380
381
  };
381
382
  export type VoiceRealCallProfileReadinessCheckOptions = {
382
383
  browserProofHref?: string;
@@ -409,6 +410,7 @@ export type VoiceRealCallProfileRecoveryJobHistoryCheckOptions = {
409
410
  };
410
411
  export type VoiceRealCallProfileRecoveryActionHandlerInput = {
411
412
  actionId: VoiceRealCallProfileRecoveryActionId;
413
+ profileId?: string;
412
414
  report: VoiceRealCallProfileHistoryReport;
413
415
  };
414
416
  export type VoiceRealCallProfileRecoveryActionResult = {
@@ -2255,7 +2255,7 @@ var buildRealCallProfileReadinessIssues = (report, options) => {
2255
2255
  var uniqueRealCallProfileActions = (actions) => {
2256
2256
  const seen = new Set;
2257
2257
  return actions.filter((action) => {
2258
- const key = `${action.method ?? "GET"}:${action.href}:${action.label}`;
2258
+ const key = `${action.method ?? "GET"}:${action.href}:${action.label}:${action.profileId ?? ""}`;
2259
2259
  if (seen.has(key)) {
2260
2260
  return false;
2261
2261
  }
@@ -2263,6 +2263,16 @@ var uniqueRealCallProfileActions = (actions) => {
2263
2263
  return true;
2264
2264
  });
2265
2265
  };
2266
+ var appendRealCallRecoveryActionQuery = (href, query) => {
2267
+ const entries = Object.entries(query).filter((entry) => entry[1] !== undefined);
2268
+ if (entries.length === 0) {
2269
+ return href;
2270
+ }
2271
+ const [base = href, hash = ""] = href.split("#");
2272
+ const separator = base.includes("?") ? "&" : "?";
2273
+ const search = new URLSearchParams(entries).toString();
2274
+ return `${base}${separator}${search}${hash ? `#${hash}` : ""}`;
2275
+ };
2266
2276
  var buildVoiceRealCallProfileRecoveryActions = (report, options = {}) => {
2267
2277
  const actions = [
2268
2278
  {
@@ -2283,20 +2293,41 @@ var buildVoiceRealCallProfileRecoveryActions = (report, options = {}) => {
2283
2293
  const missingProfiles = [...requiredProfiles].filter((profileId) => !profilesById.has(profileId));
2284
2294
  const warningProfiles = report.defaults.profiles.filter((profile) => (requiredProfiles.size === 0 || requiredProfiles.has(profile.profileId)) && profile.status !== "pass");
2285
2295
  const missingRoleProfiles = report.defaults.profiles.filter((profile) => (options.requiredProviderRoles ?? []).some((role) => !profile.providerRoutes[role]));
2296
+ const summariesByProfile = new Map((report.summary.profiles ?? []).map((profile) => [profile.id, profile]));
2297
+ const missingDepthProfiles = [...requiredProfiles].filter((profileId) => {
2298
+ const summaryProfile = summariesByProfile.get(profileId);
2299
+ if (options.minProfileCycles !== undefined && (summaryProfile?.cycles ?? 0) < options.minProfileCycles) {
2300
+ return true;
2301
+ }
2302
+ if (options.minProfileSessions !== undefined && (summaryProfile?.sessionCount ?? 0) < options.minProfileSessions) {
2303
+ return true;
2304
+ }
2305
+ const requiredProfileSurfaces = options.requiredProfileSurfaces;
2306
+ const requiredSurfaces = requiredProfileSurfaces === undefined ? [] : Array.isArray(requiredProfileSurfaces) ? requiredProfileSurfaces : requiredProfileSurfaces[profileId] ?? [];
2307
+ const observedSurfaces = new Set(summaryProfile?.surfaces ?? []);
2308
+ return requiredSurfaces.some((surface) => !observedSurfaces.has(surface));
2309
+ });
2286
2310
  const ageMs = report.trend.ageMs ?? (report.generatedAt ? Date.now() - new Date(report.generatedAt).getTime() : undefined);
2287
- if (missingProfiles.length > 0 || warningProfiles.length > 0 || missingRoleProfiles.length > 0 || options.minCycles !== undefined && (report.summary.cycles ?? 0) < options.minCycles || options.minActionableProfiles !== undefined && report.defaults.summary.actionableProfiles < options.minActionableProfiles) {
2288
- actions.push({
2289
- description: "Run browser profile proof to collect microphone, WebSocket, live-latency, and provider traces for missing profiles.",
2290
- href: options.browserProofHref ?? "/voice/browser-call-profiles",
2291
- id: "collect-browser-proof",
2292
- label: "Run browser profile proof"
2293
- });
2294
- actions.push({
2295
- description: "Run phone profile proof when required profiles depend on carrier, telephony media, or noisy-call evidence.",
2296
- href: options.phoneProofHref ?? "/api/voice/phone/smoke",
2297
- id: "collect-phone-proof",
2298
- label: "Run phone profile proof"
2299
- });
2311
+ const needsProfileProof = missingProfiles.length > 0 || warningProfiles.length > 0 || missingRoleProfiles.length > 0 || missingDepthProfiles.length > 0 || options.minCycles !== undefined && (report.summary.cycles ?? 0) < options.minCycles || options.minActionableProfiles !== undefined && report.defaults.summary.actionableProfiles < options.minActionableProfiles;
2312
+ if (needsProfileProof) {
2313
+ const targetProfileIds = missingProfiles.length > 0 || missingDepthProfiles.length > 0 ? [...new Set([...missingProfiles, ...missingDepthProfiles])] : [...requiredProfiles];
2314
+ const targets = targetProfileIds.length > 0 ? targetProfileIds : [undefined];
2315
+ for (const profileId of targets) {
2316
+ actions.push({
2317
+ description: profileId ? `Run browser profile proof for ${profileId} to collect microphone, WebSocket, live-latency, and provider traces.` : "Run browser profile proof to collect microphone, WebSocket, live-latency, and provider traces for missing profiles.",
2318
+ href: appendRealCallRecoveryActionQuery(options.browserProofHref ?? "/voice/browser-call-profiles", { profileId }),
2319
+ id: "collect-browser-proof",
2320
+ label: profileId ? `Run browser profile proof for ${profileId}` : "Run browser profile proof",
2321
+ profileId
2322
+ });
2323
+ actions.push({
2324
+ description: profileId ? `Run phone profile proof for ${profileId} when the profile depends on carrier, telephony media, or noisy-call evidence.` : "Run phone profile proof when required profiles depend on carrier, telephony media, or noisy-call evidence.",
2325
+ href: appendRealCallRecoveryActionQuery(options.phoneProofHref ?? "/api/voice/phone/smoke", { profileId }),
2326
+ id: "collect-phone-proof",
2327
+ label: profileId ? `Run phone profile proof for ${profileId}` : "Run phone profile proof",
2328
+ profileId
2329
+ });
2330
+ }
2300
2331
  }
2301
2332
  if (options.maxAgeMs !== undefined && (ageMs === undefined || ageMs > options.maxAgeMs)) {
2302
2333
  actions.push({
@@ -3146,22 +3177,22 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
3146
3177
  productionReadinessHref: options.productionReadinessHref ?? actionPath("refresh")
3147
3178
  }).map((action) => ({
3148
3179
  ...action,
3149
- href: action.id === "collect-browser-proof" ? actionPath("collect-browser-proof") : action.id === "collect-phone-proof" ? actionPath("collect-phone-proof") : action.id === "collect-provider-role-evidence" ? actionPath("collect-provider-role-evidence") : action.href,
3180
+ href: action.id === "collect-browser-proof" ? appendRealCallRecoveryActionQuery(actionPath("collect-browser-proof"), { profileId: action.profileId }) : action.id === "collect-phone-proof" ? appendRealCallRecoveryActionQuery(actionPath("collect-phone-proof"), { profileId: action.profileId }) : action.id === "collect-provider-role-evidence" ? actionPath("collect-provider-role-evidence") : action.href,
3150
3181
  method: action.id === "refresh" && (action.label === "Open real-call profile history" || action.label === "Open operations records") ? "GET" : "POST"
3151
3182
  }));
3152
3183
  return { actions, generatedAt: new Date().toISOString(), report };
3153
3184
  };
3154
- const runActionHandler = async (actionId, report) => {
3185
+ const runActionHandler = async (actionId, report, profileId) => {
3155
3186
  const handler = options.handlers?.[actionId];
3156
3187
  if (!handler) {
3157
3188
  return;
3158
3189
  }
3159
- return await handler({ actionId, report });
3190
+ return await handler({ actionId, profileId, report });
3160
3191
  };
3161
- const runActionAsJob = async (actionId, report) => {
3192
+ const runActionAsJob = async (actionId, report, profileId) => {
3162
3193
  const job = await options.jobStore?.create({
3163
3194
  actionId,
3164
- message: `Queued real-call profile recovery action: ${actionId}.`,
3195
+ message: `Queued real-call profile recovery action: ${actionId}${profileId ? ` for ${profileId}` : ""}.`,
3165
3196
  status: "queued"
3166
3197
  });
3167
3198
  if (!job) {
@@ -3177,7 +3208,7 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
3177
3208
  updatedAt: startedAt
3178
3209
  });
3179
3210
  try {
3180
- const result = await runActionHandler(actionId, report);
3211
+ const result = await runActionHandler(actionId, report, profileId);
3181
3212
  const completedAt = new Date().toISOString();
3182
3213
  const ok = result?.ok ?? true;
3183
3214
  const status = result?.jobStatus ?? (result?.status === "fail" || ok === false ? "fail" : "pass");
@@ -3212,7 +3243,7 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
3212
3243
  status: "pass"
3213
3244
  };
3214
3245
  };
3215
- const runAction = async (actionId) => {
3246
+ const runAction = async (actionId, profileId) => {
3216
3247
  const report = await loadReport();
3217
3248
  const handler = options.handlers?.[actionId];
3218
3249
  if (!handler) {
@@ -3225,12 +3256,12 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
3225
3256
  };
3226
3257
  }
3227
3258
  if (options.jobStore && asyncActionIds.has(actionId)) {
3228
- const queued = await runActionAsJob(actionId, report);
3259
+ const queued = await runActionAsJob(actionId, report, profileId);
3229
3260
  if (queued) {
3230
3261
  return queued;
3231
3262
  }
3232
3263
  }
3233
- const result = await runActionHandler(actionId, report);
3264
+ const result = await runActionHandler(actionId, report, profileId);
3234
3265
  return {
3235
3266
  actionId,
3236
3267
  generatedAt: new Date().toISOString(),
@@ -3289,8 +3320,12 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
3289
3320
  });
3290
3321
  });
3291
3322
  for (const actionId of Object.keys(realCallProfileActionPaths)) {
3292
- routes.post(actionPath(actionId), async ({ set }) => {
3293
- const result = await runAction(actionId);
3323
+ routes.post(actionPath(actionId), async ({
3324
+ query,
3325
+ set
3326
+ }) => {
3327
+ const profileId = query.profileId?.trim() || undefined;
3328
+ const result = await runAction(actionId, profileId);
3294
3329
  if (!result.ok) {
3295
3330
  set.status = 501;
3296
3331
  }
package/dist/vue/index.js CHANGED
@@ -2176,7 +2176,7 @@ var buildRealCallProfileReadinessIssues = (report, options) => {
2176
2176
  var uniqueRealCallProfileActions = (actions) => {
2177
2177
  const seen = new Set;
2178
2178
  return actions.filter((action) => {
2179
- const key = `${action.method ?? "GET"}:${action.href}:${action.label}`;
2179
+ const key = `${action.method ?? "GET"}:${action.href}:${action.label}:${action.profileId ?? ""}`;
2180
2180
  if (seen.has(key)) {
2181
2181
  return false;
2182
2182
  }
@@ -2184,6 +2184,16 @@ var uniqueRealCallProfileActions = (actions) => {
2184
2184
  return true;
2185
2185
  });
2186
2186
  };
2187
+ var appendRealCallRecoveryActionQuery = (href, query) => {
2188
+ const entries = Object.entries(query).filter((entry) => entry[1] !== undefined);
2189
+ if (entries.length === 0) {
2190
+ return href;
2191
+ }
2192
+ const [base = href, hash = ""] = href.split("#");
2193
+ const separator = base.includes("?") ? "&" : "?";
2194
+ const search = new URLSearchParams(entries).toString();
2195
+ return `${base}${separator}${search}${hash ? `#${hash}` : ""}`;
2196
+ };
2187
2197
  var buildVoiceRealCallProfileRecoveryActions = (report, options = {}) => {
2188
2198
  const actions = [
2189
2199
  {
@@ -2204,20 +2214,41 @@ var buildVoiceRealCallProfileRecoveryActions = (report, options = {}) => {
2204
2214
  const missingProfiles = [...requiredProfiles].filter((profileId) => !profilesById.has(profileId));
2205
2215
  const warningProfiles = report.defaults.profiles.filter((profile) => (requiredProfiles.size === 0 || requiredProfiles.has(profile.profileId)) && profile.status !== "pass");
2206
2216
  const missingRoleProfiles = report.defaults.profiles.filter((profile) => (options.requiredProviderRoles ?? []).some((role) => !profile.providerRoutes[role]));
2217
+ const summariesByProfile = new Map((report.summary.profiles ?? []).map((profile) => [profile.id, profile]));
2218
+ const missingDepthProfiles = [...requiredProfiles].filter((profileId) => {
2219
+ const summaryProfile = summariesByProfile.get(profileId);
2220
+ if (options.minProfileCycles !== undefined && (summaryProfile?.cycles ?? 0) < options.minProfileCycles) {
2221
+ return true;
2222
+ }
2223
+ if (options.minProfileSessions !== undefined && (summaryProfile?.sessionCount ?? 0) < options.minProfileSessions) {
2224
+ return true;
2225
+ }
2226
+ const requiredProfileSurfaces = options.requiredProfileSurfaces;
2227
+ const requiredSurfaces = requiredProfileSurfaces === undefined ? [] : Array.isArray(requiredProfileSurfaces) ? requiredProfileSurfaces : requiredProfileSurfaces[profileId] ?? [];
2228
+ const observedSurfaces = new Set(summaryProfile?.surfaces ?? []);
2229
+ return requiredSurfaces.some((surface) => !observedSurfaces.has(surface));
2230
+ });
2207
2231
  const ageMs = report.trend.ageMs ?? (report.generatedAt ? Date.now() - new Date(report.generatedAt).getTime() : undefined);
2208
- if (missingProfiles.length > 0 || warningProfiles.length > 0 || missingRoleProfiles.length > 0 || options.minCycles !== undefined && (report.summary.cycles ?? 0) < options.minCycles || options.minActionableProfiles !== undefined && report.defaults.summary.actionableProfiles < options.minActionableProfiles) {
2209
- actions.push({
2210
- description: "Run browser profile proof to collect microphone, WebSocket, live-latency, and provider traces for missing profiles.",
2211
- href: options.browserProofHref ?? "/voice/browser-call-profiles",
2212
- id: "collect-browser-proof",
2213
- label: "Run browser profile proof"
2214
- });
2215
- actions.push({
2216
- description: "Run phone profile proof when required profiles depend on carrier, telephony media, or noisy-call evidence.",
2217
- href: options.phoneProofHref ?? "/api/voice/phone/smoke",
2218
- id: "collect-phone-proof",
2219
- label: "Run phone profile proof"
2220
- });
2232
+ const needsProfileProof = missingProfiles.length > 0 || warningProfiles.length > 0 || missingRoleProfiles.length > 0 || missingDepthProfiles.length > 0 || options.minCycles !== undefined && (report.summary.cycles ?? 0) < options.minCycles || options.minActionableProfiles !== undefined && report.defaults.summary.actionableProfiles < options.minActionableProfiles;
2233
+ if (needsProfileProof) {
2234
+ const targetProfileIds = missingProfiles.length > 0 || missingDepthProfiles.length > 0 ? [...new Set([...missingProfiles, ...missingDepthProfiles])] : [...requiredProfiles];
2235
+ const targets = targetProfileIds.length > 0 ? targetProfileIds : [undefined];
2236
+ for (const profileId of targets) {
2237
+ actions.push({
2238
+ description: profileId ? `Run browser profile proof for ${profileId} to collect microphone, WebSocket, live-latency, and provider traces.` : "Run browser profile proof to collect microphone, WebSocket, live-latency, and provider traces for missing profiles.",
2239
+ href: appendRealCallRecoveryActionQuery(options.browserProofHref ?? "/voice/browser-call-profiles", { profileId }),
2240
+ id: "collect-browser-proof",
2241
+ label: profileId ? `Run browser profile proof for ${profileId}` : "Run browser profile proof",
2242
+ profileId
2243
+ });
2244
+ actions.push({
2245
+ description: profileId ? `Run phone profile proof for ${profileId} when the profile depends on carrier, telephony media, or noisy-call evidence.` : "Run phone profile proof when required profiles depend on carrier, telephony media, or noisy-call evidence.",
2246
+ href: appendRealCallRecoveryActionQuery(options.phoneProofHref ?? "/api/voice/phone/smoke", { profileId }),
2247
+ id: "collect-phone-proof",
2248
+ label: profileId ? `Run phone profile proof for ${profileId}` : "Run phone profile proof",
2249
+ profileId
2250
+ });
2251
+ }
2221
2252
  }
2222
2253
  if (options.maxAgeMs !== undefined && (ageMs === undefined || ageMs > options.maxAgeMs)) {
2223
2254
  actions.push({
@@ -3067,22 +3098,22 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
3067
3098
  productionReadinessHref: options.productionReadinessHref ?? actionPath("refresh")
3068
3099
  }).map((action) => ({
3069
3100
  ...action,
3070
- href: action.id === "collect-browser-proof" ? actionPath("collect-browser-proof") : action.id === "collect-phone-proof" ? actionPath("collect-phone-proof") : action.id === "collect-provider-role-evidence" ? actionPath("collect-provider-role-evidence") : action.href,
3101
+ href: action.id === "collect-browser-proof" ? appendRealCallRecoveryActionQuery(actionPath("collect-browser-proof"), { profileId: action.profileId }) : action.id === "collect-phone-proof" ? appendRealCallRecoveryActionQuery(actionPath("collect-phone-proof"), { profileId: action.profileId }) : action.id === "collect-provider-role-evidence" ? actionPath("collect-provider-role-evidence") : action.href,
3071
3102
  method: action.id === "refresh" && (action.label === "Open real-call profile history" || action.label === "Open operations records") ? "GET" : "POST"
3072
3103
  }));
3073
3104
  return { actions, generatedAt: new Date().toISOString(), report };
3074
3105
  };
3075
- const runActionHandler = async (actionId, report) => {
3106
+ const runActionHandler = async (actionId, report, profileId) => {
3076
3107
  const handler = options.handlers?.[actionId];
3077
3108
  if (!handler) {
3078
3109
  return;
3079
3110
  }
3080
- return await handler({ actionId, report });
3111
+ return await handler({ actionId, profileId, report });
3081
3112
  };
3082
- const runActionAsJob = async (actionId, report) => {
3113
+ const runActionAsJob = async (actionId, report, profileId) => {
3083
3114
  const job = await options.jobStore?.create({
3084
3115
  actionId,
3085
- message: `Queued real-call profile recovery action: ${actionId}.`,
3116
+ message: `Queued real-call profile recovery action: ${actionId}${profileId ? ` for ${profileId}` : ""}.`,
3086
3117
  status: "queued"
3087
3118
  });
3088
3119
  if (!job) {
@@ -3098,7 +3129,7 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
3098
3129
  updatedAt: startedAt
3099
3130
  });
3100
3131
  try {
3101
- const result = await runActionHandler(actionId, report);
3132
+ const result = await runActionHandler(actionId, report, profileId);
3102
3133
  const completedAt = new Date().toISOString();
3103
3134
  const ok = result?.ok ?? true;
3104
3135
  const status = result?.jobStatus ?? (result?.status === "fail" || ok === false ? "fail" : "pass");
@@ -3133,7 +3164,7 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
3133
3164
  status: "pass"
3134
3165
  };
3135
3166
  };
3136
- const runAction = async (actionId) => {
3167
+ const runAction = async (actionId, profileId) => {
3137
3168
  const report = await loadReport();
3138
3169
  const handler = options.handlers?.[actionId];
3139
3170
  if (!handler) {
@@ -3146,12 +3177,12 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
3146
3177
  };
3147
3178
  }
3148
3179
  if (options.jobStore && asyncActionIds.has(actionId)) {
3149
- const queued = await runActionAsJob(actionId, report);
3180
+ const queued = await runActionAsJob(actionId, report, profileId);
3150
3181
  if (queued) {
3151
3182
  return queued;
3152
3183
  }
3153
3184
  }
3154
- const result = await runActionHandler(actionId, report);
3185
+ const result = await runActionHandler(actionId, report, profileId);
3155
3186
  return {
3156
3187
  actionId,
3157
3188
  generatedAt: new Date().toISOString(),
@@ -3210,8 +3241,12 @@ var createVoiceRealCallProfileRecoveryActionRoutes = (options = {}) => {
3210
3241
  });
3211
3242
  });
3212
3243
  for (const actionId of Object.keys(realCallProfileActionPaths)) {
3213
- routes.post(actionPath(actionId), async ({ set }) => {
3214
- const result = await runAction(actionId);
3244
+ routes.post(actionPath(actionId), async ({
3245
+ query,
3246
+ set
3247
+ }) => {
3248
+ const profileId = query.profileId?.trim() || undefined;
3249
+ const result = await runAction(actionId, profileId);
3215
3250
  if (!result.ok) {
3216
3251
  set.status = 501;
3217
3252
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.380",
3
+ "version": "0.0.22-beta.382",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",