@absolutejs/voice 0.0.22-beta.361 → 0.0.22-beta.362

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/dist/index.d.ts CHANGED
@@ -31,8 +31,8 @@ export { assertVoiceCompetitiveCoverage, buildVoiceCompetitiveCoverageReport, cr
31
31
  export type { VoiceCompetitiveCoverageAssertionInput, VoiceCompetitiveCoverageAssertionReport, VoiceCompetitiveCoverageIssue, VoiceCompetitiveCoverageLevel, VoiceCompetitiveCoverageReport, VoiceCompetitiveCoverageReportInput, VoiceCompetitiveCoverageRoutesOptions, VoiceCompetitiveCoverageStatus, VoiceCompetitiveCoverageSummary, VoiceCompetitiveDepthLevel, VoiceCompetitiveEvidence, VoiceCompetitiveSurface } from './competitiveCoverage';
32
32
  export type { VoicePlatformCoverageAssertionInput, VoicePlatformCoverageAssertionReport, VoicePlatformCoverageEvidence, VoicePlatformCoverageRoutesOptions, VoicePlatformCoverageStatus, VoicePlatformCoverageSummary, VoicePlatformCoverageSummaryInput, VoicePlatformCoverageSurface } from './platformCoverage';
33
33
  export { assertVoiceProofTrendEvidence, buildEmptyVoiceProofTrendReport, buildVoiceProofTrendProfileSummaries, buildVoiceProofTrendRecommendationReport, buildVoiceProofTrendReportFromRealCallProfiles, buildVoiceProofTrendReport, buildVoiceRealCallProfileDefaults, buildVoiceRealCallProfileHistoryReport, createVoiceProofTrendRecommendationRoutes, createVoiceProofTrendRoutes, createVoiceRealCallProfileHistoryRoutes, DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS, DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS, evaluateVoiceProofTrendEvidence, formatVoiceProofTrendAge, normalizeVoiceProofTrendReport, readVoiceProofTrendReportFile, renderVoiceProofTrendRecommendationHTML, renderVoiceProofTrendRecommendationMarkdown, renderVoiceRealCallProfileHistoryHTML, renderVoiceRealCallProfileHistoryMarkdown, resolveVoiceRealCallProfileProviderRoute } from './proofTrends';
34
- export { applyVoiceProfileSwitchGuard, buildVoiceProfileSwitchLiveDecisionReport, createVoiceProfileSwitchLiveDecisionRoutes, createVoiceProfileSwitchPolicyProofRoutes, recommendVoiceProfileSwitch, renderVoiceProfileSwitchLiveDecisionHTML, renderVoiceProfileSwitchPolicyProofHTML, runVoiceProfileSwitchPolicyProof } from './profileSwitchRecommendation';
35
- export type { VoiceProfileSwitchGuardAction, VoiceProfileSwitchGuardDecision, VoiceProfileSwitchGuardMode, VoiceProfileSwitchGuardOptions, VoiceProfileSwitchObservedSignals, VoiceProfileSwitchLiveDecisionEvidence, VoiceProfileSwitchLiveDecisionReport, VoiceProfileSwitchLiveDecisionReportOptions, VoiceProfileSwitchLiveDecisionRoutesOptions, VoiceProfileSwitchLiveDecisionSession, VoiceProfileSwitchPolicyProofCase, VoiceProfileSwitchPolicyProofCaseResult, VoiceProfileSwitchPolicyProofOptions, VoiceProfileSwitchPolicyProofReport, VoiceProfileSwitchPolicyProofRoutesOptions, VoiceProfileSwitchRecommendation, VoiceProfileSwitchRecommendationOptions } from './profileSwitchRecommendation';
34
+ export { applyVoiceProfileSwitchGuard, buildVoiceProfileSwitchReadinessReport, buildVoiceProfileSwitchLiveDecisionReport, createVoiceProfileSwitchLiveDecisionRoutes, createVoiceProfileSwitchPolicyProofRoutes, createVoiceProfileSwitchReadinessRoutes, recommendVoiceProfileSwitch, renderVoiceProfileSwitchLiveDecisionHTML, renderVoiceProfileSwitchPolicyProofHTML, renderVoiceProfileSwitchReadinessHTML, runVoiceProfileSwitchPolicyProof } from './profileSwitchRecommendation';
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
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 } from './proofTrends';
package/dist/index.js CHANGED
@@ -5844,6 +5844,126 @@ var createVoiceProfileSwitchLiveDecisionRoutes = (options) => {
5844
5844
  }
5845
5845
  return routes;
5846
5846
  };
5847
+ var statusFromIssues = (issues) => issues.some((issue) => issue.status === "fail") ? "fail" : issues.length > 0 ? "warn" : "pass";
5848
+ var buildVoiceProfileSwitchReadinessReport = async (options) => {
5849
+ const live = await buildVoiceProfileSwitchLiveDecisionReport(options);
5850
+ const policy = options.policyProof === false || options.policyProof === undefined ? undefined : await runVoiceProfileSwitchPolicyProof(options.policyProof);
5851
+ const issues = [];
5852
+ const requireLiveDecisions = options.requireLiveDecisions ?? true;
5853
+ const requireAudit = options.requireAudit ?? Boolean(options.autoMode);
5854
+ const requireTrace = options.requireTrace ?? true;
5855
+ const requirePolicyProof = options.requirePolicyProof ?? Boolean(options.policyProof);
5856
+ const requireAllowedProfilePolicy = options.requireAllowedProfilePolicy ?? Boolean(options.autoMode);
5857
+ const maxBlockedRatio = options.maxBlockedRatio ?? 0.5;
5858
+ const maxAutoAppliedRatio = options.maxAutoAppliedRatio ?? 0.75;
5859
+ const decisions = live.summary.decisions;
5860
+ const blockedRatio = decisions > 0 ? live.summary.blocked / decisions : 0;
5861
+ const autoAppliedRatio = decisions > 0 ? live.summary.autoApplied / decisions : 0;
5862
+ if (requireLiveDecisions && decisions === 0) {
5863
+ issues.push({
5864
+ code: "voice.profile_switch.live_decisions_missing",
5865
+ message: "No live profile switch guard decisions have been recorded.",
5866
+ status: "fail"
5867
+ });
5868
+ }
5869
+ if (requireAudit && live.summary.auditEvents === 0) {
5870
+ issues.push({
5871
+ code: "voice.profile_switch.audit_missing",
5872
+ message: "Profile switch guard readiness requires audit evidence.",
5873
+ status: "fail"
5874
+ });
5875
+ }
5876
+ if (requireTrace && live.summary.traceEvents === 0) {
5877
+ issues.push({
5878
+ code: "voice.profile_switch.trace_missing",
5879
+ message: "Profile switch guard readiness requires trace evidence.",
5880
+ status: "warn"
5881
+ });
5882
+ }
5883
+ if (requirePolicyProof && !policy) {
5884
+ issues.push({
5885
+ code: "voice.profile_switch.policy_proof_missing",
5886
+ message: "Profile switch policy proof was not configured.",
5887
+ status: "fail"
5888
+ });
5889
+ }
5890
+ if (policy && !policy.ok) {
5891
+ issues.push({
5892
+ code: "voice.profile_switch.policy_proof_failed",
5893
+ message: "Profile switch policy proof has failing cases.",
5894
+ status: "fail"
5895
+ });
5896
+ }
5897
+ if (requireAllowedProfilePolicy && (options.policyProof === false || !options.policyProof?.allowedProfileIds || options.policyProof.allowedProfileIds.length === 0)) {
5898
+ issues.push({
5899
+ code: "voice.profile_switch.allowed_policy_missing",
5900
+ message: "Auto profile switching should declare an allowedProfileIds policy.",
5901
+ status: "warn"
5902
+ });
5903
+ }
5904
+ if (decisions > 0 && blockedRatio > maxBlockedRatio) {
5905
+ issues.push({
5906
+ code: "voice.profile_switch.blocked_ratio_high",
5907
+ message: `Blocked profile switch decisions are ${Math.round(blockedRatio * 100)}%, above the ${Math.round(maxBlockedRatio * 100)}% threshold.`,
5908
+ status: "warn"
5909
+ });
5910
+ }
5911
+ if (decisions > 0 && autoAppliedRatio > maxAutoAppliedRatio) {
5912
+ issues.push({
5913
+ code: "voice.profile_switch.auto_applied_ratio_high",
5914
+ message: `Auto-applied profile switch decisions are ${Math.round(autoAppliedRatio * 100)}%, above the ${Math.round(maxAutoAppliedRatio * 100)}% threshold.`,
5915
+ status: "warn"
5916
+ });
5917
+ }
5918
+ return {
5919
+ generatedAt: new Date().toISOString(),
5920
+ issues,
5921
+ live,
5922
+ policy,
5923
+ status: statusFromIssues(issues),
5924
+ summary: {
5925
+ auditEvents: live.summary.auditEvents,
5926
+ autoApplied: live.summary.autoApplied,
5927
+ blocked: live.summary.blocked,
5928
+ decisions,
5929
+ policyCases: policy?.summary.total,
5930
+ sessions: live.summary.sessions,
5931
+ switches: live.summary.switches,
5932
+ traceEvents: live.summary.traceEvents
5933
+ }
5934
+ };
5935
+ };
5936
+ var renderVoiceProfileSwitchReadinessHTML = (report, options = {}) => {
5937
+ const title = options.title ?? "Voice Profile Switch Readiness";
5938
+ const issues = report.issues.map((issue) => `<li class="${escapeHtml3(issue.status)}"><strong>${escapeHtml3(issue.code)}</strong><p>${escapeHtml3(issue.message)}</p></li>`).join("");
5939
+ const sessions = report.live.sessions.map((session) => `<tr><td>${escapeHtml3(session.sessionId)}</td><td>${escapeHtml3(session.actions.join(", ") || "none")}</td><td>${String(session.decisions.length)}</td><td>${String(session.autoApplied)}</td><td>${escapeHtml3(session.blockedByPolicy.join(", ") || "none")}</td></tr>`).join("");
5940
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml3(title)}</title><style>:root{color-scheme:dark;background:#0b1020;color:#eff6ff;font-family:ui-sans-serif,system-ui,sans-serif}body{margin:0;padding:32px;background:radial-gradient(circle at top left,rgba(59,130,246,.2),transparent 34%),#0b1020}main{max-width:1140px;margin:0 auto}.hero,.card{background:rgba(15,23,42,.82);border:1px solid rgba(147,197,253,.24);border-radius:24px;margin-bottom:18px;padding:24px}.status{border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.pass{background:rgba(34,197,94,.18);color:#bbf7d0}.warn{background:rgba(245,158,11,.18);color:#fde68a}.fail{background:rgba(239,68,68,.18);color:#fecaca}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin-top:16px}.metric{background:#0f172a;border:1px solid rgba(147,197,253,.2);border-radius:18px;padding:16px}.metric span{color:#93c5fd;display:block;font-size:.75rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.metric strong{display:block;font-size:1.8rem;margin-top:8px}ul{display:grid;gap:10px;list-style:none;padding:0}li{border-radius:16px;padding:14px}li p{margin:.35rem 0 0}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid rgba(147,197,253,.18);padding:12px;text-align:left}pre{background:#020617;border-radius:18px;color:#dbeafe;overflow:auto;padding:18px}</style></head><body><main><section class="hero"><h1>${escapeHtml3(title)}</h1><p>Deploy-facing readiness for profile switching: policy proof, audit evidence, trace evidence, and live session behavior.</p><p class="status ${escapeHtml3(report.status)}">${escapeHtml3(report.status.toUpperCase())}</p><div class="grid"><div class="metric"><span>Sessions</span><strong>${String(report.summary.sessions)}</strong></div><div class="metric"><span>Decisions</span><strong>${String(report.summary.decisions)}</strong></div><div class="metric"><span>Policy cases</span><strong>${String(report.summary.policyCases ?? 0)}</strong></div><div class="metric"><span>Audit</span><strong>${String(report.summary.auditEvents)}</strong></div><div class="metric"><span>Trace</span><strong>${String(report.summary.traceEvents)}</strong></div></div></section><section class="card"><h2>Issues</h2>${issues ? `<ul>${issues}</ul>` : '<p class="pass status">No readiness issues.</p>'}</section><section class="card"><h2>Live Sessions</h2>${sessions ? `<table><thead><tr><th>Session</th><th>Actions</th><th>Decisions</th><th>Auto applied</th><th>Blocked by</th></tr></thead><tbody>${sessions}</tbody></table>` : "<p>No live guard sessions found.</p>"}</section><section class="card"><h2>Raw Report</h2><pre>${stringifyForHtml(report)}</pre></section></main></body></html>`;
5941
+ };
5942
+ var createVoiceProfileSwitchReadinessRoutes = (options) => {
5943
+ const path = options.path ?? "/api/voice/profile-switch-readiness";
5944
+ const htmlPath = options.htmlPath === undefined ? "/voice/profile-switch-readiness" : options.htmlPath;
5945
+ const routes = new Elysia({
5946
+ name: options.name ?? "absolutejs-voice-profile-switch-readiness"
5947
+ }).get(path, async ({ query }) => buildVoiceProfileSwitchReadinessReport({
5948
+ ...options,
5949
+ limit: typeof query.limit === "string" && Number.isFinite(Number(query.limit)) ? Number(query.limit) : options.limit,
5950
+ sessionId: typeof query.sessionId === "string" && query.sessionId.trim() ? query.sessionId.trim() : options.sessionId
5951
+ }));
5952
+ if (htmlPath) {
5953
+ routes.get(htmlPath, async ({ query }) => {
5954
+ const report = await buildVoiceProfileSwitchReadinessReport({
5955
+ ...options,
5956
+ limit: typeof query.limit === "string" && Number.isFinite(Number(query.limit)) ? Number(query.limit) : options.limit,
5957
+ sessionId: typeof query.sessionId === "string" && query.sessionId.trim() ? query.sessionId.trim() : options.sessionId
5958
+ });
5959
+ const render = options.render ?? ((input) => renderVoiceProfileSwitchReadinessHTML(input, { title: options.title }));
5960
+ return new Response(await render(report), {
5961
+ headers: { "Content-Type": "text/html; charset=utf-8" }
5962
+ });
5963
+ });
5964
+ }
5965
+ return routes;
5966
+ };
5847
5967
 
5848
5968
  // src/plugin.ts
5849
5969
  var resolveQueryScenario = (query) => {
@@ -37824,6 +37944,7 @@ export {
37824
37944
  renderVoiceProviderCapabilityHTML,
37825
37945
  renderVoiceProofTrendRecommendationMarkdown,
37826
37946
  renderVoiceProofTrendRecommendationHTML,
37947
+ renderVoiceProfileSwitchReadinessHTML,
37827
37948
  renderVoiceProfileSwitchPolicyProofHTML,
37828
37949
  renderVoiceProfileSwitchLiveDecisionHTML,
37829
37950
  renderVoiceProductionReadinessHTML,
@@ -38079,6 +38200,7 @@ export {
38079
38200
  createVoiceProviderCapabilityHTMLHandler,
38080
38201
  createVoiceProofTrendRoutes,
38081
38202
  createVoiceProofTrendRecommendationRoutes,
38203
+ createVoiceProfileSwitchReadinessRoutes,
38082
38204
  createVoiceProfileSwitchPolicyProofRoutes,
38083
38205
  createVoiceProfileSwitchLiveDecisionRoutes,
38084
38206
  createVoiceProductionReadinessRoutes,
@@ -38281,6 +38403,7 @@ export {
38281
38403
  buildVoiceProofTrendReport,
38282
38404
  buildVoiceProofTrendRecommendationReport,
38283
38405
  buildVoiceProofTrendProfileSummaries,
38406
+ buildVoiceProfileSwitchReadinessReport,
38284
38407
  buildVoiceProfileSwitchLiveDecisionReport,
38285
38408
  buildVoiceProductionReadinessReport,
38286
38409
  buildVoiceProductionReadinessGate,
@@ -173,6 +173,47 @@ export type VoiceProfileSwitchLiveDecisionRoutesOptions = VoiceProfileSwitchLive
173
173
  render?: (report: VoiceProfileSwitchLiveDecisionReport) => string | Promise<string>;
174
174
  title?: string;
175
175
  };
176
+ export type VoiceProfileSwitchReadinessStatus = 'fail' | 'pass' | 'warn';
177
+ export type VoiceProfileSwitchReadinessIssue = {
178
+ code: string;
179
+ message: string;
180
+ status: Exclude<VoiceProfileSwitchReadinessStatus, 'pass'>;
181
+ };
182
+ export type VoiceProfileSwitchReadinessReport = {
183
+ generatedAt: string;
184
+ issues: VoiceProfileSwitchReadinessIssue[];
185
+ live: VoiceProfileSwitchLiveDecisionReport;
186
+ policy?: VoiceProfileSwitchPolicyProofReport;
187
+ status: VoiceProfileSwitchReadinessStatus;
188
+ summary: {
189
+ auditEvents: number;
190
+ autoApplied: number;
191
+ blocked: number;
192
+ decisions: number;
193
+ policyCases?: number;
194
+ sessions: number;
195
+ switches: number;
196
+ traceEvents: number;
197
+ };
198
+ };
199
+ export type VoiceProfileSwitchReadinessOptions = VoiceProfileSwitchLiveDecisionReportOptions & {
200
+ autoMode?: boolean;
201
+ maxBlockedRatio?: number;
202
+ maxAutoAppliedRatio?: number;
203
+ policyProof?: false | VoiceProfileSwitchPolicyProofOptions;
204
+ requireAudit?: boolean;
205
+ requireAllowedProfilePolicy?: boolean;
206
+ requireLiveDecisions?: boolean;
207
+ requirePolicyProof?: boolean;
208
+ requireTrace?: boolean;
209
+ };
210
+ export type VoiceProfileSwitchReadinessRoutesOptions = VoiceProfileSwitchReadinessOptions & {
211
+ htmlPath?: false | string;
212
+ name?: string;
213
+ path?: string;
214
+ render?: (report: VoiceProfileSwitchReadinessReport) => string | Promise<string>;
215
+ title?: string;
216
+ };
176
217
  export declare const recommendVoiceProfileSwitch: (options: VoiceProfileSwitchRecommendationOptions) => VoiceProfileSwitchRecommendation;
177
218
  export declare const applyVoiceProfileSwitchGuard: (options: VoiceProfileSwitchGuardOptions) => Promise<VoiceProfileSwitchGuardDecision>;
178
219
  export declare const runVoiceProfileSwitchPolicyProof: (options: VoiceProfileSwitchPolicyProofOptions) => Promise<VoiceProfileSwitchPolicyProofReport>;
@@ -263,3 +304,47 @@ export declare const createVoiceProfileSwitchLiveDecisionRoutes: (options: Voice
263
304
  standaloneSchema: {};
264
305
  response: {};
265
306
  }>;
307
+ export declare const buildVoiceProfileSwitchReadinessReport: (options: VoiceProfileSwitchReadinessOptions) => Promise<VoiceProfileSwitchReadinessReport>;
308
+ export declare const renderVoiceProfileSwitchReadinessHTML: (report: VoiceProfileSwitchReadinessReport, options?: {
309
+ title?: string;
310
+ }) => string;
311
+ export declare const createVoiceProfileSwitchReadinessRoutes: (options: VoiceProfileSwitchReadinessRoutesOptions) => Elysia<"", {
312
+ decorator: {};
313
+ store: {};
314
+ derive: {};
315
+ resolve: {};
316
+ }, {
317
+ typebox: {};
318
+ error: {};
319
+ }, {
320
+ schema: {};
321
+ standaloneSchema: {};
322
+ macro: {};
323
+ macroFn: {};
324
+ parser: {};
325
+ response: {};
326
+ }, {
327
+ [x: string]: {
328
+ get: {
329
+ body: unknown;
330
+ params: {};
331
+ query: unknown;
332
+ headers: unknown;
333
+ response: {
334
+ 200: VoiceProfileSwitchReadinessReport;
335
+ };
336
+ };
337
+ };
338
+ }, {
339
+ derive: {};
340
+ resolve: {};
341
+ schema: {};
342
+ standaloneSchema: {};
343
+ response: {};
344
+ }, {
345
+ derive: {};
346
+ resolve: {};
347
+ schema: {};
348
+ standaloneSchema: {};
349
+ response: {};
350
+ }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.361",
3
+ "version": "0.0.22-beta.362",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",