@absolutejs/voice 0.0.22-beta.463 → 0.0.22-beta.464
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/angular/index.js +265 -0
- package/dist/client/htmxBootstrap.js +330 -7
- package/dist/client/index.js +265 -0
- package/dist/generated/htmxBootstrapBundle.d.ts +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +591 -50
- package/dist/mediaPipelineRoutes.d.ts +55 -1
- package/dist/mediaPipelineSurfaces.d.ts +48 -0
- package/dist/react/index.js +265 -0
- package/dist/svelte/index.js +265 -0
- package/dist/testing/index.js +265 -0
- package/dist/vue/index.js +265 -0
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Elysia } from "elysia";
|
|
2
|
-
import { type MediaFrame, type MediaInterruptionReport, type MediaPipelineCalibrationInput, type MediaPipelineCalibrationReport, type MediaPipelineStatus, type MediaProcessorGraphReport, type MediaQualityReport, type MediaResamplingPlan, type MediaTransportReport, type MediaVadReport } from "@absolutejs/media";
|
|
2
|
+
import { type MediaFrame, type MediaInterruptionReport, type MediaPipelineCalibrationIssue, type MediaPipelineCalibrationInput, type MediaPipelineCalibrationReport, type MediaPipelineStatus, type MediaProcessorGraphReport, type MediaProcessorGraphSummary, type MediaQualityReport, type MediaQualitySummary, type MediaResamplingPlan, type MediaTransportReport, type MediaTransportSummary, type MediaVadReport } from "@absolutejs/media";
|
|
3
3
|
export type VoiceMediaPipelineReportOptions = MediaPipelineCalibrationInput & {
|
|
4
4
|
frames?: readonly MediaFrame[];
|
|
5
5
|
maxInterruptionLatencyMs?: number;
|
|
@@ -115,3 +115,57 @@ export declare const createVoiceMediaPipelineRoutes: (options?: VoiceMediaPipeli
|
|
|
115
115
|
standaloneSchema: {};
|
|
116
116
|
response: {};
|
|
117
117
|
}>;
|
|
118
|
+
export type VoiceMediaPipelineCalibrationSummary = {
|
|
119
|
+
assistantAudioFrames: number;
|
|
120
|
+
backpressureFrames: number;
|
|
121
|
+
firstAudioLatencyMs?: number;
|
|
122
|
+
inputAudioFrames: number;
|
|
123
|
+
interruptionFrames: number;
|
|
124
|
+
issueCodes: readonly string[];
|
|
125
|
+
jitterMs?: number;
|
|
126
|
+
resamplingRequired: boolean;
|
|
127
|
+
status: MediaPipelineStatus;
|
|
128
|
+
surface: string;
|
|
129
|
+
traceLinkedFrames: number;
|
|
130
|
+
turnCommitFrames: number;
|
|
131
|
+
};
|
|
132
|
+
export type VoiceMediaPipelineProofArtifactLinks = {
|
|
133
|
+
processorGraph?: string;
|
|
134
|
+
quality?: string;
|
|
135
|
+
transport?: string;
|
|
136
|
+
};
|
|
137
|
+
export type VoiceMediaPipelineProofSummary = {
|
|
138
|
+
artifacts?: VoiceMediaPipelineProofArtifactLinks;
|
|
139
|
+
calibration: VoiceMediaPipelineCalibrationSummary;
|
|
140
|
+
checkedAt: number;
|
|
141
|
+
frames: number;
|
|
142
|
+
interruption: {
|
|
143
|
+
interruptionFrames: number;
|
|
144
|
+
issueCodes: readonly string[];
|
|
145
|
+
latenciesMs: readonly number[];
|
|
146
|
+
status: MediaPipelineStatus;
|
|
147
|
+
};
|
|
148
|
+
issueCodes: readonly string[];
|
|
149
|
+
issues: readonly MediaPipelineCalibrationIssue[];
|
|
150
|
+
ok: boolean;
|
|
151
|
+
processorGraph?: MediaProcessorGraphSummary;
|
|
152
|
+
quality: MediaQualitySummary;
|
|
153
|
+
resampling?: {
|
|
154
|
+
ratio: number;
|
|
155
|
+
required: boolean;
|
|
156
|
+
status: MediaPipelineStatus;
|
|
157
|
+
};
|
|
158
|
+
sessionIds: readonly string[];
|
|
159
|
+
status: MediaPipelineStatus;
|
|
160
|
+
surface: string;
|
|
161
|
+
transport?: MediaTransportSummary;
|
|
162
|
+
vad: {
|
|
163
|
+
inputAudioFrames: number;
|
|
164
|
+
segmentCount: number;
|
|
165
|
+
status: MediaPipelineStatus;
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
export type VoiceMediaPipelineProofSummaryOptions = {
|
|
169
|
+
artifacts?: VoiceMediaPipelineProofArtifactLinks;
|
|
170
|
+
};
|
|
171
|
+
export declare const summarizeVoiceMediaPipelineReport: (report: VoiceMediaPipelineReport, options?: VoiceMediaPipelineProofSummaryOptions) => VoiceMediaPipelineProofSummary;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type MediaProcessorGraphSummary, type MediaQualitySummary, type MediaTransportSummary } from "@absolutejs/media";
|
|
2
|
+
import type { VoiceIncidentTimelineEvent } from "./incidentTimeline";
|
|
3
|
+
import type { VoiceMediaPipelineReport } from "./mediaPipelineRoutes";
|
|
4
|
+
import type { VoiceProductionReadinessCheck } from "./productionReadiness";
|
|
5
|
+
export type VoiceMediaPipelineIssueSource = "calibration" | "interruption" | "processor-graph" | "quality" | "transport";
|
|
6
|
+
export type VoiceMediaPipelineIssueEntry = {
|
|
7
|
+
code: string;
|
|
8
|
+
message: string;
|
|
9
|
+
severity: "error" | "warning";
|
|
10
|
+
source: VoiceMediaPipelineIssueSource;
|
|
11
|
+
surface: string;
|
|
12
|
+
};
|
|
13
|
+
export declare const extractVoiceMediaPipelineIssueEntries: (report: VoiceMediaPipelineReport) => readonly VoiceMediaPipelineIssueEntry[];
|
|
14
|
+
export type VoiceMediaPipelineReadinessOptions = {
|
|
15
|
+
baseHref?: string;
|
|
16
|
+
label?: string;
|
|
17
|
+
};
|
|
18
|
+
export declare const buildVoiceMediaPipelineReadinessChecks: (report: VoiceMediaPipelineReport, options?: VoiceMediaPipelineReadinessOptions) => readonly VoiceProductionReadinessCheck[];
|
|
19
|
+
export type VoiceMediaPipelineIncidentOptions = {
|
|
20
|
+
baseHref?: string;
|
|
21
|
+
category?: VoiceIncidentTimelineEvent["category"];
|
|
22
|
+
now?: () => number;
|
|
23
|
+
source?: string;
|
|
24
|
+
};
|
|
25
|
+
export declare const buildVoiceMediaPipelineIncidentEvents: (report: VoiceMediaPipelineReport, options?: VoiceMediaPipelineIncidentOptions) => readonly VoiceIncidentTimelineEvent[];
|
|
26
|
+
export type VoiceMediaPipelineArtifactKind = "processor-graph" | "quality" | "transport";
|
|
27
|
+
export type VoiceMediaPipelineArtifactRecord = {
|
|
28
|
+
href?: string;
|
|
29
|
+
jsonPath: string;
|
|
30
|
+
kind: VoiceMediaPipelineArtifactKind;
|
|
31
|
+
markdownPath: string;
|
|
32
|
+
summary: MediaProcessorGraphSummary | MediaQualitySummary | MediaTransportSummary;
|
|
33
|
+
};
|
|
34
|
+
export type VoiceMediaPipelineArtifactWriteOptions = {
|
|
35
|
+
dir: string;
|
|
36
|
+
hrefBase?: string;
|
|
37
|
+
report: VoiceMediaPipelineReport;
|
|
38
|
+
slugPrefix?: string;
|
|
39
|
+
};
|
|
40
|
+
export type VoiceMediaPipelineArtifactWriteResult = {
|
|
41
|
+
artifacts: VoiceMediaPipelineArtifactRecord[];
|
|
42
|
+
hrefs: {
|
|
43
|
+
processorGraph?: string;
|
|
44
|
+
quality?: string;
|
|
45
|
+
transport?: string;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export declare const writeVoiceMediaPipelineArtifacts: (options: VoiceMediaPipelineArtifactWriteOptions) => Promise<VoiceMediaPipelineArtifactWriteResult>;
|
package/dist/react/index.js
CHANGED
|
@@ -11087,6 +11087,8 @@ var serverMessageToAction = (message) => {
|
|
|
11087
11087
|
};
|
|
11088
11088
|
|
|
11089
11089
|
// node_modules/@absolutejs/media/dist/index.js
|
|
11090
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
11091
|
+
import { join } from "path";
|
|
11090
11092
|
var formatLabel = (format) => `${format.container}/${format.encoding}/${String(format.sampleRateHz)}hz/${String(format.channels)}ch`;
|
|
11091
11093
|
var formatMatches = (actual, expected) => actual.container === expected.container && actual.encoding === expected.encoding && actual.sampleRateHz === expected.sampleRateHz && actual.channels === expected.channels;
|
|
11092
11094
|
var pushIssue = (issues, severity, code, message) => {
|
|
@@ -11747,6 +11749,269 @@ var buildMediaPipelineCalibrationReport = (input = {}) => {
|
|
|
11747
11749
|
turnCommitFrames: turnCommitFrames.length
|
|
11748
11750
|
};
|
|
11749
11751
|
};
|
|
11752
|
+
var DEFAULT_METADATA_DENY = [
|
|
11753
|
+
"audioPayload",
|
|
11754
|
+
"auth",
|
|
11755
|
+
"authorization",
|
|
11756
|
+
"cookie",
|
|
11757
|
+
"email",
|
|
11758
|
+
"phone",
|
|
11759
|
+
"phoneNumber",
|
|
11760
|
+
"rawPayload",
|
|
11761
|
+
"secret",
|
|
11762
|
+
"token",
|
|
11763
|
+
"transcript",
|
|
11764
|
+
"utterance"
|
|
11765
|
+
];
|
|
11766
|
+
var DEFAULT_TRUNCATE = 8;
|
|
11767
|
+
var issueCodes = (issues) => Array.from(new Set(issues.map((issue) => issue.code)));
|
|
11768
|
+
var lastEventKind = (events) => events[events.length - 1]?.kind;
|
|
11769
|
+
var formatOptionalMs = (value) => value === undefined ? "n/a" : `${String(Math.round(value))}ms`;
|
|
11770
|
+
var formatRatio = (value) => `${(value * 100).toFixed(1)}%`;
|
|
11771
|
+
var escapeMarkdownCell = (value) => value.replace(/\|/g, "\\|").replace(/\n/g, " ");
|
|
11772
|
+
var renderIssuesTable = (issues) => {
|
|
11773
|
+
if (issues.length === 0) {
|
|
11774
|
+
return `- No issues.
|
|
11775
|
+
`;
|
|
11776
|
+
}
|
|
11777
|
+
const rows = issues.map((issue) => `| ${issue.severity} | ${escapeMarkdownCell(issue.code)} | ${escapeMarkdownCell(issue.message)} |`).join(`
|
|
11778
|
+
`);
|
|
11779
|
+
return `| Severity | Code | Message |
|
|
11780
|
+
| --- | --- | --- |
|
|
11781
|
+
${rows}
|
|
11782
|
+
`;
|
|
11783
|
+
};
|
|
11784
|
+
var summarizeMediaQualityReport = (report) => ({
|
|
11785
|
+
backpressureEvents: report.backpressureEvents,
|
|
11786
|
+
description: `${report.totalFrames} frame(s), ${report.gapCount} gap(s), speech ${formatRatio(report.speechRatio)}, status ${report.status}.`,
|
|
11787
|
+
driftMs: report.timestampDriftMs,
|
|
11788
|
+
frameCount: report.totalFrames,
|
|
11789
|
+
gapCount: report.gapCount,
|
|
11790
|
+
issueCodes: issueCodes(report.issues),
|
|
11791
|
+
issueCount: report.issues.length,
|
|
11792
|
+
jitterMs: report.jitterMs,
|
|
11793
|
+
silenceRatio: report.silenceRatio,
|
|
11794
|
+
speechRatio: report.speechRatio,
|
|
11795
|
+
status: report.status
|
|
11796
|
+
});
|
|
11797
|
+
var summarizeMediaTransportReport = (report) => ({
|
|
11798
|
+
backpressureEvents: report.backpressureEvents,
|
|
11799
|
+
description: `${report.name}: ${report.state}, in ${report.inputFrames}, out ${report.outputFrames}, backpressure ${report.backpressureEvents}.`,
|
|
11800
|
+
errors: report.events.filter((event) => event.kind === "error").length,
|
|
11801
|
+
inputFrames: report.inputFrames,
|
|
11802
|
+
lastEventKind: lastEventKind(report.events),
|
|
11803
|
+
name: report.name,
|
|
11804
|
+
outputFrames: report.outputFrames,
|
|
11805
|
+
state: report.state,
|
|
11806
|
+
status: report.status
|
|
11807
|
+
});
|
|
11808
|
+
var summarizeMediaProcessorGraphReport = (report) => {
|
|
11809
|
+
const errorIssueCodes = Array.from(new Set(report.errors.map((event) => event.kind)));
|
|
11810
|
+
return {
|
|
11811
|
+
backpressureEvents: report.backpressure.events.length,
|
|
11812
|
+
description: `${report.name}: ${report.state}, ${report.nodes.length} node(s), in ${report.inputFrames}, out ${report.emittedFrames}, dropped ${report.droppedFrames}.`,
|
|
11813
|
+
droppedFrames: report.droppedFrames,
|
|
11814
|
+
edgeCount: report.edges.length,
|
|
11815
|
+
edgeEventCount: report.edgeEvents.length,
|
|
11816
|
+
emittedFrames: report.emittedFrames,
|
|
11817
|
+
errorCount: report.errors.length,
|
|
11818
|
+
inputFrames: report.inputFrames,
|
|
11819
|
+
issueCodes: errorIssueCodes,
|
|
11820
|
+
lifecycleEventCount: report.lifecycleEvents.length,
|
|
11821
|
+
name: report.name,
|
|
11822
|
+
nodeCount: report.nodes.length,
|
|
11823
|
+
state: report.state,
|
|
11824
|
+
status: report.status,
|
|
11825
|
+
timingMaxMs: report.timing.maxNodeMs
|
|
11826
|
+
};
|
|
11827
|
+
};
|
|
11828
|
+
var renderMediaQualityMarkdown = (report, options = {}) => {
|
|
11829
|
+
const title = options.title ?? "Media Quality Report";
|
|
11830
|
+
const lines = [
|
|
11831
|
+
`# ${title}`,
|
|
11832
|
+
"",
|
|
11833
|
+
`Status: **${report.status}**`,
|
|
11834
|
+
"",
|
|
11835
|
+
"| Metric | Value |",
|
|
11836
|
+
"| --- | ---: |",
|
|
11837
|
+
`| Total frames | ${report.totalFrames} |`,
|
|
11838
|
+
`| Input audio | ${report.inputAudioFrames} |`,
|
|
11839
|
+
`| Assistant audio | ${report.assistantAudioFrames} |`,
|
|
11840
|
+
`| Gaps | ${report.gapCount} |`,
|
|
11841
|
+
`| Jitter | ${formatOptionalMs(report.jitterMs)} |`,
|
|
11842
|
+
`| Timestamp drift | ${formatOptionalMs(report.timestampDriftMs)} |`,
|
|
11843
|
+
`| Speech ratio | ${formatRatio(report.speechRatio)} |`,
|
|
11844
|
+
`| Silence ratio | ${formatRatio(report.silenceRatio)} |`,
|
|
11845
|
+
`| Backpressure events | ${report.backpressureEvents} |`,
|
|
11846
|
+
"",
|
|
11847
|
+
"## Issues",
|
|
11848
|
+
"",
|
|
11849
|
+
renderIssuesTable(report.issues).trimEnd()
|
|
11850
|
+
];
|
|
11851
|
+
return `${lines.join(`
|
|
11852
|
+
`)}
|
|
11853
|
+
`;
|
|
11854
|
+
};
|
|
11855
|
+
var renderMediaTransportMarkdown = (report, options = {}) => {
|
|
11856
|
+
const title = options.title ?? `Media Transport: ${report.name}`;
|
|
11857
|
+
const limit = options.redact?.truncateArraysAt ?? DEFAULT_TRUNCATE;
|
|
11858
|
+
const events = report.events.slice(-limit);
|
|
11859
|
+
const eventRows = events.length === 0 ? "- No transport events recorded." : ["| At | Kind | State | Buffered | Error |", "| --- | --- | --- | ---: | --- |"].concat(events.map((event) => `| ${event.at} | ${event.kind} | ${event.state} | ${event.bufferedFrames ?? ""} | ${escapeMarkdownCell(event.error ?? "")} |`)).join(`
|
|
11860
|
+
`);
|
|
11861
|
+
const lines = [
|
|
11862
|
+
`# ${title}`,
|
|
11863
|
+
"",
|
|
11864
|
+
`Status: **${report.status}** \xB7 State: **${report.state}**`,
|
|
11865
|
+
"",
|
|
11866
|
+
"| Metric | Value |",
|
|
11867
|
+
"| --- | ---: |",
|
|
11868
|
+
`| Input frames | ${report.inputFrames} |`,
|
|
11869
|
+
`| Output frames | ${report.outputFrames} |`,
|
|
11870
|
+
`| Backpressure events | ${report.backpressureEvents} |`,
|
|
11871
|
+
`| Connected | ${report.connected ? "yes" : "no"} |`,
|
|
11872
|
+
`| Closed | ${report.closed ? "yes" : "no"} |`,
|
|
11873
|
+
`| Failed | ${report.failed ? "yes" : "no"} |`,
|
|
11874
|
+
"",
|
|
11875
|
+
`## Last ${events.length} event(s)`,
|
|
11876
|
+
"",
|
|
11877
|
+
eventRows
|
|
11878
|
+
];
|
|
11879
|
+
return `${lines.join(`
|
|
11880
|
+
`)}
|
|
11881
|
+
`;
|
|
11882
|
+
};
|
|
11883
|
+
var renderMediaProcessorGraphMarkdown = (report, options = {}) => {
|
|
11884
|
+
const title = options.title ?? `Media Processor Graph: ${report.name}`;
|
|
11885
|
+
const limit = options.redact?.truncateArraysAt ?? DEFAULT_TRUNCATE;
|
|
11886
|
+
const nodeRows = report.nodes.map((node) => `| ${escapeMarkdownCell(node.name)} | ${node.kind} | ${node.status} | ${node.inputFrames} | ${node.emittedFrames} | ${node.droppedFrames} | ${node.errors.length} |`).join(`
|
|
11887
|
+
`);
|
|
11888
|
+
const edgeRows = report.edges.slice(0, limit).map((edge) => `| ${escapeMarkdownCell(edge.from)} | ${escapeMarkdownCell(edge.to)} | ${edge.status} | ${edge.emittedFrames} |`).join(`
|
|
11889
|
+
`);
|
|
11890
|
+
const issues = report.errors.map((event) => ({
|
|
11891
|
+
code: event.kind,
|
|
11892
|
+
message: event.error ?? `Processor graph ${event.kind} (state ${event.state}).`,
|
|
11893
|
+
severity: "error"
|
|
11894
|
+
}));
|
|
11895
|
+
const lines = [
|
|
11896
|
+
`# ${title}`,
|
|
11897
|
+
"",
|
|
11898
|
+
`Status: **${report.status}** \xB7 State: **${report.state}**`,
|
|
11899
|
+
"",
|
|
11900
|
+
"| Metric | Value |",
|
|
11901
|
+
"| --- | ---: |",
|
|
11902
|
+
`| Nodes | ${report.nodes.length} |`,
|
|
11903
|
+
`| Input frames | ${report.inputFrames} |`,
|
|
11904
|
+
`| Emitted frames | ${report.emittedFrames} |`,
|
|
11905
|
+
`| Dropped frames | ${report.droppedFrames} |`,
|
|
11906
|
+
`| Lifecycle events | ${report.lifecycleEvents.length} |`,
|
|
11907
|
+
`| Edge events | ${report.edgeEvents.length} |`,
|
|
11908
|
+
`| Backpressure events | ${report.backpressure.events.length} |`,
|
|
11909
|
+
`| Timing max | ${formatOptionalMs(report.timing.maxNodeMs)} |`,
|
|
11910
|
+
`| Timing average | ${formatOptionalMs(report.timing.averageNodeMs)} |`,
|
|
11911
|
+
"",
|
|
11912
|
+
"## Nodes",
|
|
11913
|
+
"",
|
|
11914
|
+
nodeRows ? `| Node | Kind | Status | In | Out | Dropped | Errors |
|
|
11915
|
+
| --- | --- | --- | ---: | ---: | ---: | ---: |
|
|
11916
|
+
${nodeRows}` : "- No nodes.",
|
|
11917
|
+
"",
|
|
11918
|
+
`## Edges (showing up to ${limit})`,
|
|
11919
|
+
"",
|
|
11920
|
+
edgeRows ? `| From | To | Status | Frames |
|
|
11921
|
+
| --- | --- | --- | ---: |
|
|
11922
|
+
${edgeRows}` : "- No edges.",
|
|
11923
|
+
"",
|
|
11924
|
+
"## Errors",
|
|
11925
|
+
"",
|
|
11926
|
+
renderIssuesTable(issues).trimEnd()
|
|
11927
|
+
];
|
|
11928
|
+
return `${lines.join(`
|
|
11929
|
+
`)}
|
|
11930
|
+
`;
|
|
11931
|
+
};
|
|
11932
|
+
var truncateArrays = (value, limit, seen) => {
|
|
11933
|
+
if (Array.isArray(value)) {
|
|
11934
|
+
const head = value.slice(0, limit).map((entry) => truncateArrays(entry, limit, seen));
|
|
11935
|
+
if (value.length > limit) {
|
|
11936
|
+
return [...head, { truncated: value.length - limit }];
|
|
11937
|
+
}
|
|
11938
|
+
return head;
|
|
11939
|
+
}
|
|
11940
|
+
if (value && typeof value === "object") {
|
|
11941
|
+
if (seen.has(value))
|
|
11942
|
+
return value;
|
|
11943
|
+
seen.add(value);
|
|
11944
|
+
const next = {};
|
|
11945
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
11946
|
+
next[key] = truncateArrays(entry, limit, seen);
|
|
11947
|
+
}
|
|
11948
|
+
return next;
|
|
11949
|
+
}
|
|
11950
|
+
return value;
|
|
11951
|
+
};
|
|
11952
|
+
var applyRedaction = (value, options, seen) => {
|
|
11953
|
+
const mode = options.mode ?? "omit";
|
|
11954
|
+
const maskValue = options.maskValue ?? "[redacted]";
|
|
11955
|
+
const allow = new Set(options.metadataAllow ?? []);
|
|
11956
|
+
const deny = new Set(options.metadataDeny ?? DEFAULT_METADATA_DENY);
|
|
11957
|
+
const walk = (input) => {
|
|
11958
|
+
if (Array.isArray(input)) {
|
|
11959
|
+
return input.map((entry) => walk(entry));
|
|
11960
|
+
}
|
|
11961
|
+
if (input && typeof input === "object") {
|
|
11962
|
+
if (seen.has(input))
|
|
11963
|
+
return input;
|
|
11964
|
+
seen.add(input);
|
|
11965
|
+
const next = {};
|
|
11966
|
+
for (const [key, entry] of Object.entries(input)) {
|
|
11967
|
+
if (allow.has(key)) {
|
|
11968
|
+
next[key] = entry;
|
|
11969
|
+
continue;
|
|
11970
|
+
}
|
|
11971
|
+
if (deny.has(key)) {
|
|
11972
|
+
if (mode === "mask")
|
|
11973
|
+
next[key] = maskValue;
|
|
11974
|
+
continue;
|
|
11975
|
+
}
|
|
11976
|
+
next[key] = walk(entry);
|
|
11977
|
+
}
|
|
11978
|
+
return next;
|
|
11979
|
+
}
|
|
11980
|
+
return input;
|
|
11981
|
+
};
|
|
11982
|
+
return walk(value);
|
|
11983
|
+
};
|
|
11984
|
+
var redactMediaReport = (report, options = {}) => {
|
|
11985
|
+
const limit = options.truncateArraysAt ?? DEFAULT_TRUNCATE;
|
|
11986
|
+
const truncated = truncateArrays(report, limit, new WeakSet);
|
|
11987
|
+
return applyRedaction(truncated, options, new WeakSet);
|
|
11988
|
+
};
|
|
11989
|
+
var buildArtifactPair = (report, summary, markdown, options) => {
|
|
11990
|
+
const jsonValue = options.redact ? redactMediaReport(report, options.redact) : report;
|
|
11991
|
+
return {
|
|
11992
|
+
json: JSON.stringify(jsonValue, null, 2),
|
|
11993
|
+
jsonValue,
|
|
11994
|
+
markdown,
|
|
11995
|
+
summary
|
|
11996
|
+
};
|
|
11997
|
+
};
|
|
11998
|
+
var buildMediaQualityArtifact = (report, options = {}) => buildArtifactPair(report, summarizeMediaQualityReport(report), renderMediaQualityMarkdown(report, options), options);
|
|
11999
|
+
var buildMediaTransportArtifact = (report, options = {}) => buildArtifactPair(report, summarizeMediaTransportReport(report), renderMediaTransportMarkdown(report, options), options);
|
|
12000
|
+
var buildMediaProcessorGraphArtifact = (report, options = {}) => buildArtifactPair(report, summarizeMediaProcessorGraphReport(report), renderMediaProcessorGraphMarkdown(report, options), options);
|
|
12001
|
+
var writeMediaArtifact = async (input) => {
|
|
12002
|
+
await mkdir(input.dir, { recursive: true });
|
|
12003
|
+
const jsonPath = join(input.dir, `${input.slug}.json`);
|
|
12004
|
+
const markdownPath = join(input.dir, `${input.slug}.md`);
|
|
12005
|
+
await Promise.all([
|
|
12006
|
+
writeFile(jsonPath, input.json, "utf8"),
|
|
12007
|
+
writeFile(markdownPath, input.markdown, "utf8")
|
|
12008
|
+
]);
|
|
12009
|
+
return {
|
|
12010
|
+
jsonPath,
|
|
12011
|
+
markdownPath,
|
|
12012
|
+
summary: input.summary
|
|
12013
|
+
};
|
|
12014
|
+
};
|
|
11750
12015
|
|
|
11751
12016
|
// src/client/browserMedia.ts
|
|
11752
12017
|
var DEFAULT_BROWSER_MEDIA_PATH = "/api/voice/browser-media";
|
package/dist/svelte/index.js
CHANGED
|
@@ -4262,6 +4262,8 @@ var serverMessageToAction = (message) => {
|
|
|
4262
4262
|
};
|
|
4263
4263
|
|
|
4264
4264
|
// node_modules/@absolutejs/media/dist/index.js
|
|
4265
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
4266
|
+
import { join } from "path";
|
|
4265
4267
|
var formatLabel = (format) => `${format.container}/${format.encoding}/${String(format.sampleRateHz)}hz/${String(format.channels)}ch`;
|
|
4266
4268
|
var formatMatches = (actual, expected) => actual.container === expected.container && actual.encoding === expected.encoding && actual.sampleRateHz === expected.sampleRateHz && actual.channels === expected.channels;
|
|
4267
4269
|
var pushIssue = (issues, severity, code, message) => {
|
|
@@ -4922,6 +4924,269 @@ var buildMediaPipelineCalibrationReport = (input = {}) => {
|
|
|
4922
4924
|
turnCommitFrames: turnCommitFrames.length
|
|
4923
4925
|
};
|
|
4924
4926
|
};
|
|
4927
|
+
var DEFAULT_METADATA_DENY = [
|
|
4928
|
+
"audioPayload",
|
|
4929
|
+
"auth",
|
|
4930
|
+
"authorization",
|
|
4931
|
+
"cookie",
|
|
4932
|
+
"email",
|
|
4933
|
+
"phone",
|
|
4934
|
+
"phoneNumber",
|
|
4935
|
+
"rawPayload",
|
|
4936
|
+
"secret",
|
|
4937
|
+
"token",
|
|
4938
|
+
"transcript",
|
|
4939
|
+
"utterance"
|
|
4940
|
+
];
|
|
4941
|
+
var DEFAULT_TRUNCATE = 8;
|
|
4942
|
+
var issueCodes = (issues) => Array.from(new Set(issues.map((issue) => issue.code)));
|
|
4943
|
+
var lastEventKind = (events) => events[events.length - 1]?.kind;
|
|
4944
|
+
var formatOptionalMs = (value) => value === undefined ? "n/a" : `${String(Math.round(value))}ms`;
|
|
4945
|
+
var formatRatio = (value) => `${(value * 100).toFixed(1)}%`;
|
|
4946
|
+
var escapeMarkdownCell = (value) => value.replace(/\|/g, "\\|").replace(/\n/g, " ");
|
|
4947
|
+
var renderIssuesTable = (issues) => {
|
|
4948
|
+
if (issues.length === 0) {
|
|
4949
|
+
return `- No issues.
|
|
4950
|
+
`;
|
|
4951
|
+
}
|
|
4952
|
+
const rows = issues.map((issue) => `| ${issue.severity} | ${escapeMarkdownCell(issue.code)} | ${escapeMarkdownCell(issue.message)} |`).join(`
|
|
4953
|
+
`);
|
|
4954
|
+
return `| Severity | Code | Message |
|
|
4955
|
+
| --- | --- | --- |
|
|
4956
|
+
${rows}
|
|
4957
|
+
`;
|
|
4958
|
+
};
|
|
4959
|
+
var summarizeMediaQualityReport = (report) => ({
|
|
4960
|
+
backpressureEvents: report.backpressureEvents,
|
|
4961
|
+
description: `${report.totalFrames} frame(s), ${report.gapCount} gap(s), speech ${formatRatio(report.speechRatio)}, status ${report.status}.`,
|
|
4962
|
+
driftMs: report.timestampDriftMs,
|
|
4963
|
+
frameCount: report.totalFrames,
|
|
4964
|
+
gapCount: report.gapCount,
|
|
4965
|
+
issueCodes: issueCodes(report.issues),
|
|
4966
|
+
issueCount: report.issues.length,
|
|
4967
|
+
jitterMs: report.jitterMs,
|
|
4968
|
+
silenceRatio: report.silenceRatio,
|
|
4969
|
+
speechRatio: report.speechRatio,
|
|
4970
|
+
status: report.status
|
|
4971
|
+
});
|
|
4972
|
+
var summarizeMediaTransportReport = (report) => ({
|
|
4973
|
+
backpressureEvents: report.backpressureEvents,
|
|
4974
|
+
description: `${report.name}: ${report.state}, in ${report.inputFrames}, out ${report.outputFrames}, backpressure ${report.backpressureEvents}.`,
|
|
4975
|
+
errors: report.events.filter((event) => event.kind === "error").length,
|
|
4976
|
+
inputFrames: report.inputFrames,
|
|
4977
|
+
lastEventKind: lastEventKind(report.events),
|
|
4978
|
+
name: report.name,
|
|
4979
|
+
outputFrames: report.outputFrames,
|
|
4980
|
+
state: report.state,
|
|
4981
|
+
status: report.status
|
|
4982
|
+
});
|
|
4983
|
+
var summarizeMediaProcessorGraphReport = (report) => {
|
|
4984
|
+
const errorIssueCodes = Array.from(new Set(report.errors.map((event) => event.kind)));
|
|
4985
|
+
return {
|
|
4986
|
+
backpressureEvents: report.backpressure.events.length,
|
|
4987
|
+
description: `${report.name}: ${report.state}, ${report.nodes.length} node(s), in ${report.inputFrames}, out ${report.emittedFrames}, dropped ${report.droppedFrames}.`,
|
|
4988
|
+
droppedFrames: report.droppedFrames,
|
|
4989
|
+
edgeCount: report.edges.length,
|
|
4990
|
+
edgeEventCount: report.edgeEvents.length,
|
|
4991
|
+
emittedFrames: report.emittedFrames,
|
|
4992
|
+
errorCount: report.errors.length,
|
|
4993
|
+
inputFrames: report.inputFrames,
|
|
4994
|
+
issueCodes: errorIssueCodes,
|
|
4995
|
+
lifecycleEventCount: report.lifecycleEvents.length,
|
|
4996
|
+
name: report.name,
|
|
4997
|
+
nodeCount: report.nodes.length,
|
|
4998
|
+
state: report.state,
|
|
4999
|
+
status: report.status,
|
|
5000
|
+
timingMaxMs: report.timing.maxNodeMs
|
|
5001
|
+
};
|
|
5002
|
+
};
|
|
5003
|
+
var renderMediaQualityMarkdown = (report, options = {}) => {
|
|
5004
|
+
const title = options.title ?? "Media Quality Report";
|
|
5005
|
+
const lines = [
|
|
5006
|
+
`# ${title}`,
|
|
5007
|
+
"",
|
|
5008
|
+
`Status: **${report.status}**`,
|
|
5009
|
+
"",
|
|
5010
|
+
"| Metric | Value |",
|
|
5011
|
+
"| --- | ---: |",
|
|
5012
|
+
`| Total frames | ${report.totalFrames} |`,
|
|
5013
|
+
`| Input audio | ${report.inputAudioFrames} |`,
|
|
5014
|
+
`| Assistant audio | ${report.assistantAudioFrames} |`,
|
|
5015
|
+
`| Gaps | ${report.gapCount} |`,
|
|
5016
|
+
`| Jitter | ${formatOptionalMs(report.jitterMs)} |`,
|
|
5017
|
+
`| Timestamp drift | ${formatOptionalMs(report.timestampDriftMs)} |`,
|
|
5018
|
+
`| Speech ratio | ${formatRatio(report.speechRatio)} |`,
|
|
5019
|
+
`| Silence ratio | ${formatRatio(report.silenceRatio)} |`,
|
|
5020
|
+
`| Backpressure events | ${report.backpressureEvents} |`,
|
|
5021
|
+
"",
|
|
5022
|
+
"## Issues",
|
|
5023
|
+
"",
|
|
5024
|
+
renderIssuesTable(report.issues).trimEnd()
|
|
5025
|
+
];
|
|
5026
|
+
return `${lines.join(`
|
|
5027
|
+
`)}
|
|
5028
|
+
`;
|
|
5029
|
+
};
|
|
5030
|
+
var renderMediaTransportMarkdown = (report, options = {}) => {
|
|
5031
|
+
const title = options.title ?? `Media Transport: ${report.name}`;
|
|
5032
|
+
const limit = options.redact?.truncateArraysAt ?? DEFAULT_TRUNCATE;
|
|
5033
|
+
const events = report.events.slice(-limit);
|
|
5034
|
+
const eventRows = events.length === 0 ? "- No transport events recorded." : ["| At | Kind | State | Buffered | Error |", "| --- | --- | --- | ---: | --- |"].concat(events.map((event) => `| ${event.at} | ${event.kind} | ${event.state} | ${event.bufferedFrames ?? ""} | ${escapeMarkdownCell(event.error ?? "")} |`)).join(`
|
|
5035
|
+
`);
|
|
5036
|
+
const lines = [
|
|
5037
|
+
`# ${title}`,
|
|
5038
|
+
"",
|
|
5039
|
+
`Status: **${report.status}** \xB7 State: **${report.state}**`,
|
|
5040
|
+
"",
|
|
5041
|
+
"| Metric | Value |",
|
|
5042
|
+
"| --- | ---: |",
|
|
5043
|
+
`| Input frames | ${report.inputFrames} |`,
|
|
5044
|
+
`| Output frames | ${report.outputFrames} |`,
|
|
5045
|
+
`| Backpressure events | ${report.backpressureEvents} |`,
|
|
5046
|
+
`| Connected | ${report.connected ? "yes" : "no"} |`,
|
|
5047
|
+
`| Closed | ${report.closed ? "yes" : "no"} |`,
|
|
5048
|
+
`| Failed | ${report.failed ? "yes" : "no"} |`,
|
|
5049
|
+
"",
|
|
5050
|
+
`## Last ${events.length} event(s)`,
|
|
5051
|
+
"",
|
|
5052
|
+
eventRows
|
|
5053
|
+
];
|
|
5054
|
+
return `${lines.join(`
|
|
5055
|
+
`)}
|
|
5056
|
+
`;
|
|
5057
|
+
};
|
|
5058
|
+
var renderMediaProcessorGraphMarkdown = (report, options = {}) => {
|
|
5059
|
+
const title = options.title ?? `Media Processor Graph: ${report.name}`;
|
|
5060
|
+
const limit = options.redact?.truncateArraysAt ?? DEFAULT_TRUNCATE;
|
|
5061
|
+
const nodeRows = report.nodes.map((node) => `| ${escapeMarkdownCell(node.name)} | ${node.kind} | ${node.status} | ${node.inputFrames} | ${node.emittedFrames} | ${node.droppedFrames} | ${node.errors.length} |`).join(`
|
|
5062
|
+
`);
|
|
5063
|
+
const edgeRows = report.edges.slice(0, limit).map((edge) => `| ${escapeMarkdownCell(edge.from)} | ${escapeMarkdownCell(edge.to)} | ${edge.status} | ${edge.emittedFrames} |`).join(`
|
|
5064
|
+
`);
|
|
5065
|
+
const issues = report.errors.map((event) => ({
|
|
5066
|
+
code: event.kind,
|
|
5067
|
+
message: event.error ?? `Processor graph ${event.kind} (state ${event.state}).`,
|
|
5068
|
+
severity: "error"
|
|
5069
|
+
}));
|
|
5070
|
+
const lines = [
|
|
5071
|
+
`# ${title}`,
|
|
5072
|
+
"",
|
|
5073
|
+
`Status: **${report.status}** \xB7 State: **${report.state}**`,
|
|
5074
|
+
"",
|
|
5075
|
+
"| Metric | Value |",
|
|
5076
|
+
"| --- | ---: |",
|
|
5077
|
+
`| Nodes | ${report.nodes.length} |`,
|
|
5078
|
+
`| Input frames | ${report.inputFrames} |`,
|
|
5079
|
+
`| Emitted frames | ${report.emittedFrames} |`,
|
|
5080
|
+
`| Dropped frames | ${report.droppedFrames} |`,
|
|
5081
|
+
`| Lifecycle events | ${report.lifecycleEvents.length} |`,
|
|
5082
|
+
`| Edge events | ${report.edgeEvents.length} |`,
|
|
5083
|
+
`| Backpressure events | ${report.backpressure.events.length} |`,
|
|
5084
|
+
`| Timing max | ${formatOptionalMs(report.timing.maxNodeMs)} |`,
|
|
5085
|
+
`| Timing average | ${formatOptionalMs(report.timing.averageNodeMs)} |`,
|
|
5086
|
+
"",
|
|
5087
|
+
"## Nodes",
|
|
5088
|
+
"",
|
|
5089
|
+
nodeRows ? `| Node | Kind | Status | In | Out | Dropped | Errors |
|
|
5090
|
+
| --- | --- | --- | ---: | ---: | ---: | ---: |
|
|
5091
|
+
${nodeRows}` : "- No nodes.",
|
|
5092
|
+
"",
|
|
5093
|
+
`## Edges (showing up to ${limit})`,
|
|
5094
|
+
"",
|
|
5095
|
+
edgeRows ? `| From | To | Status | Frames |
|
|
5096
|
+
| --- | --- | --- | ---: |
|
|
5097
|
+
${edgeRows}` : "- No edges.",
|
|
5098
|
+
"",
|
|
5099
|
+
"## Errors",
|
|
5100
|
+
"",
|
|
5101
|
+
renderIssuesTable(issues).trimEnd()
|
|
5102
|
+
];
|
|
5103
|
+
return `${lines.join(`
|
|
5104
|
+
`)}
|
|
5105
|
+
`;
|
|
5106
|
+
};
|
|
5107
|
+
var truncateArrays = (value, limit, seen) => {
|
|
5108
|
+
if (Array.isArray(value)) {
|
|
5109
|
+
const head = value.slice(0, limit).map((entry) => truncateArrays(entry, limit, seen));
|
|
5110
|
+
if (value.length > limit) {
|
|
5111
|
+
return [...head, { truncated: value.length - limit }];
|
|
5112
|
+
}
|
|
5113
|
+
return head;
|
|
5114
|
+
}
|
|
5115
|
+
if (value && typeof value === "object") {
|
|
5116
|
+
if (seen.has(value))
|
|
5117
|
+
return value;
|
|
5118
|
+
seen.add(value);
|
|
5119
|
+
const next = {};
|
|
5120
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
5121
|
+
next[key] = truncateArrays(entry, limit, seen);
|
|
5122
|
+
}
|
|
5123
|
+
return next;
|
|
5124
|
+
}
|
|
5125
|
+
return value;
|
|
5126
|
+
};
|
|
5127
|
+
var applyRedaction = (value, options, seen) => {
|
|
5128
|
+
const mode = options.mode ?? "omit";
|
|
5129
|
+
const maskValue = options.maskValue ?? "[redacted]";
|
|
5130
|
+
const allow = new Set(options.metadataAllow ?? []);
|
|
5131
|
+
const deny = new Set(options.metadataDeny ?? DEFAULT_METADATA_DENY);
|
|
5132
|
+
const walk = (input) => {
|
|
5133
|
+
if (Array.isArray(input)) {
|
|
5134
|
+
return input.map((entry) => walk(entry));
|
|
5135
|
+
}
|
|
5136
|
+
if (input && typeof input === "object") {
|
|
5137
|
+
if (seen.has(input))
|
|
5138
|
+
return input;
|
|
5139
|
+
seen.add(input);
|
|
5140
|
+
const next = {};
|
|
5141
|
+
for (const [key, entry] of Object.entries(input)) {
|
|
5142
|
+
if (allow.has(key)) {
|
|
5143
|
+
next[key] = entry;
|
|
5144
|
+
continue;
|
|
5145
|
+
}
|
|
5146
|
+
if (deny.has(key)) {
|
|
5147
|
+
if (mode === "mask")
|
|
5148
|
+
next[key] = maskValue;
|
|
5149
|
+
continue;
|
|
5150
|
+
}
|
|
5151
|
+
next[key] = walk(entry);
|
|
5152
|
+
}
|
|
5153
|
+
return next;
|
|
5154
|
+
}
|
|
5155
|
+
return input;
|
|
5156
|
+
};
|
|
5157
|
+
return walk(value);
|
|
5158
|
+
};
|
|
5159
|
+
var redactMediaReport = (report, options = {}) => {
|
|
5160
|
+
const limit = options.truncateArraysAt ?? DEFAULT_TRUNCATE;
|
|
5161
|
+
const truncated = truncateArrays(report, limit, new WeakSet);
|
|
5162
|
+
return applyRedaction(truncated, options, new WeakSet);
|
|
5163
|
+
};
|
|
5164
|
+
var buildArtifactPair = (report, summary, markdown, options) => {
|
|
5165
|
+
const jsonValue = options.redact ? redactMediaReport(report, options.redact) : report;
|
|
5166
|
+
return {
|
|
5167
|
+
json: JSON.stringify(jsonValue, null, 2),
|
|
5168
|
+
jsonValue,
|
|
5169
|
+
markdown,
|
|
5170
|
+
summary
|
|
5171
|
+
};
|
|
5172
|
+
};
|
|
5173
|
+
var buildMediaQualityArtifact = (report, options = {}) => buildArtifactPair(report, summarizeMediaQualityReport(report), renderMediaQualityMarkdown(report, options), options);
|
|
5174
|
+
var buildMediaTransportArtifact = (report, options = {}) => buildArtifactPair(report, summarizeMediaTransportReport(report), renderMediaTransportMarkdown(report, options), options);
|
|
5175
|
+
var buildMediaProcessorGraphArtifact = (report, options = {}) => buildArtifactPair(report, summarizeMediaProcessorGraphReport(report), renderMediaProcessorGraphMarkdown(report, options), options);
|
|
5176
|
+
var writeMediaArtifact = async (input) => {
|
|
5177
|
+
await mkdir(input.dir, { recursive: true });
|
|
5178
|
+
const jsonPath = join(input.dir, `${input.slug}.json`);
|
|
5179
|
+
const markdownPath = join(input.dir, `${input.slug}.md`);
|
|
5180
|
+
await Promise.all([
|
|
5181
|
+
writeFile(jsonPath, input.json, "utf8"),
|
|
5182
|
+
writeFile(markdownPath, input.markdown, "utf8")
|
|
5183
|
+
]);
|
|
5184
|
+
return {
|
|
5185
|
+
jsonPath,
|
|
5186
|
+
markdownPath,
|
|
5187
|
+
summary: input.summary
|
|
5188
|
+
};
|
|
5189
|
+
};
|
|
4925
5190
|
|
|
4926
5191
|
// src/client/browserMedia.ts
|
|
4927
5192
|
var DEFAULT_BROWSER_MEDIA_PATH = "/api/voice/browser-media";
|