@framers/agentos 0.13.44 → 0.13.46

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.
Files changed (40) hide show
  1. package/dist/core/llm/providers/implementations/ClaudeCodeCLIBridge.d.ts +13 -1
  2. package/dist/core/llm/providers/implementations/ClaudeCodeCLIBridge.d.ts.map +1 -1
  3. package/dist/core/llm/providers/implementations/ClaudeCodeCLIBridge.js +35 -8
  4. package/dist/core/llm/providers/implementations/ClaudeCodeCLIBridge.js.map +1 -1
  5. package/dist/core/llm/providers/implementations/ClaudeCodeProvider.d.ts.map +1 -1
  6. package/dist/core/llm/providers/implementations/ClaudeCodeProvider.js +2 -1
  7. package/dist/core/llm/providers/implementations/ClaudeCodeProvider.js.map +1 -1
  8. package/dist/core/llm/providers/implementations/GeminiCLIBridge.d.ts.map +1 -1
  9. package/dist/core/llm/providers/implementations/GeminiCLIBridge.js +31 -12
  10. package/dist/core/llm/providers/implementations/GeminiCLIBridge.js.map +1 -1
  11. package/dist/core/llm/providers/implementations/GeminiCLIProvider.d.ts.map +1 -1
  12. package/dist/core/llm/providers/implementations/GeminiCLIProvider.js +2 -1
  13. package/dist/core/llm/providers/implementations/GeminiCLIProvider.js.map +1 -1
  14. package/dist/io/hearing/pieces/cut.d.ts +30 -0
  15. package/dist/io/hearing/pieces/cut.d.ts.map +1 -0
  16. package/dist/io/hearing/pieces/cut.js +175 -0
  17. package/dist/io/hearing/pieces/cut.js.map +1 -0
  18. package/dist/io/hearing/pieces/index.d.ts +11 -0
  19. package/dist/io/hearing/pieces/index.d.ts.map +1 -0
  20. package/dist/io/hearing/pieces/index.js +11 -0
  21. package/dist/io/hearing/pieces/index.js.map +1 -0
  22. package/dist/io/hearing/pieces/plan.d.ts +17 -0
  23. package/dist/io/hearing/pieces/plan.d.ts.map +1 -0
  24. package/dist/io/hearing/pieces/plan.js +29 -0
  25. package/dist/io/hearing/pieces/plan.js.map +1 -0
  26. package/dist/io/hearing/pieces/read.d.ts +47 -0
  27. package/dist/io/hearing/pieces/read.d.ts.map +1 -0
  28. package/dist/io/hearing/pieces/read.js +96 -0
  29. package/dist/io/hearing/pieces/read.js.map +1 -0
  30. package/dist/io/hearing/pieces/wav.d.ts +15 -0
  31. package/dist/io/hearing/pieces/wav.d.ts.map +1 -0
  32. package/dist/io/hearing/pieces/wav.js +75 -0
  33. package/dist/io/hearing/pieces/wav.js.map +1 -0
  34. package/dist/safety/sandbox/subprocess/CLISubprocessBridge.d.ts +5 -0
  35. package/dist/safety/sandbox/subprocess/CLISubprocessBridge.d.ts.map +1 -1
  36. package/dist/safety/sandbox/subprocess/CLISubprocessBridge.js +21 -0
  37. package/dist/safety/sandbox/subprocess/CLISubprocessBridge.js.map +1 -1
  38. package/dist/safety/sandbox/subprocess/types.d.ts +4 -1
  39. package/dist/safety/sandbox/subprocess/types.d.ts.map +1 -1
  40. package/package.json +14 -1
@@ -0,0 +1,175 @@
1
+ /**
2
+ * @fileoverview The pieces of a recording, cut in the page: packets copied into a container OpenAI takes when the codec
3
+ * allows (no decoding), and otherwise decoded and written as 16 kHz mono 16-bit WAV. On the decode path, each cut
4
+ * moves to the quietest 100 milliseconds within ten seconds before its mark when the search succeeds.
5
+ * @module agentos/io/hearing/pieces/cut
6
+ */
7
+ import { AudioSample, AudioSampleSink, AudioSampleSource, BufferTarget, EncodedAudioPacketSource, EncodedPacketSink, Mp3OutputFormat, Mp4OutputFormat, Output, WavOutputFormat, WebMOutputFormat, ALL_FORMATS, BlobSource, BufferSource, Input, } from 'mediabunny';
8
+ import { planPieces } from './plan.js';
9
+ import { COPY_TARGETS, readAudioInfo, UnreadableAudioError } from './read.js';
10
+ /** Creates a buffered output for a piece's container. */
11
+ function outputFor(extension) {
12
+ const format = extension === 'm4a' ? new Mp4OutputFormat() : extension === 'webm' ? new WebMOutputFormat() : extension === 'mp3' ? new Mp3OutputFormat() : new WavOutputFormat();
13
+ return new Output({ format, target: new BufferTarget() });
14
+ }
15
+ /** The quietest 100 ms frame of the first channel in [from, to); keeps `to` if decoding fails or no frame fits. */
16
+ async function quietestBefore(track, from, to) {
17
+ if (from >= to)
18
+ return to;
19
+ let best = to;
20
+ let bestLevel = Number.POSITIVE_INFINITY;
21
+ let sum = 0;
22
+ let count = 0;
23
+ let frameStart = from;
24
+ try {
25
+ const sink = new AudioSampleSink(track);
26
+ for await (const sample of sink.samples(from, to)) {
27
+ try {
28
+ const floats = new Float32Array(sample.numberOfFrames);
29
+ sample.copyTo(floats, { format: 'f32-planar', planeIndex: 0 });
30
+ const frame = Math.max(1, Math.round(sample.sampleRate / 10));
31
+ // A decoded sample can be shorter than 100 ms and can straddle either edge of the search window.
32
+ const first = Math.max(0, Math.ceil((from - sample.timestamp) * sample.sampleRate));
33
+ const last = Math.min(floats.length, Math.ceil((to - sample.timestamp) * sample.sampleRate));
34
+ for (let offset = first; offset < last; offset += 1) {
35
+ if (count === 0)
36
+ frameStart = sample.timestamp + offset / sample.sampleRate;
37
+ sum += floats[offset] * floats[offset];
38
+ count += 1;
39
+ if (count === frame) {
40
+ const level = sum / count;
41
+ if (level < bestLevel) {
42
+ bestLevel = level;
43
+ best = frameStart + frame / (2 * sample.sampleRate);
44
+ }
45
+ sum = 0;
46
+ count = 0;
47
+ }
48
+ }
49
+ }
50
+ finally {
51
+ sample.close();
52
+ }
53
+ }
54
+ }
55
+ catch {
56
+ return to;
57
+ }
58
+ return best;
59
+ }
60
+ /** One piece by packet copy. */
61
+ async function copyPiece(track, codec, start, end, isLast) {
62
+ const extension = codec === 'pcm-s16' ? 'wav' : COPY_TARGETS[codec].extension;
63
+ const output = outputFor(extension);
64
+ const source = new EncodedAudioPacketSource(codec);
65
+ output.addAudioTrack(source);
66
+ await output.start();
67
+ const sink = new EncodedPacketSink(track);
68
+ const first = await sink.getPacket(start);
69
+ const last = isLast ? undefined : await sink.getPacket(end, { metadataOnly: true });
70
+ const decoderConfig = (await track.getDecoderConfig()) ?? undefined;
71
+ let sent = false;
72
+ if (first !== null) {
73
+ for await (const packet of sink.packets(first, last ?? undefined)) {
74
+ await source.add(packet.clone({ timestamp: packet.timestamp - first.timestamp }), sent ? undefined : { decoderConfig });
75
+ sent = true;
76
+ }
77
+ }
78
+ await output.finalize();
79
+ return new Uint8Array(output.target.buffer);
80
+ }
81
+ /** One piece decoded to 16 kHz mono 16-bit WAV. */
82
+ async function decodePiece(track, start, end) {
83
+ if (!await track.canDecode())
84
+ throw new UnreadableAudioError('cannot_decode');
85
+ const output = outputFor('wav');
86
+ const source = new AudioSampleSource({ codec: 'pcm-s16', transform: { numberOfChannels: 1, sampleRate: 16000 } });
87
+ output.addAudioTrack(source);
88
+ await output.start();
89
+ let sent = false;
90
+ for await (const sample of new AudioSampleSink(track).samples(start, end)) {
91
+ try {
92
+ const first = Math.max(0, Math.min(sample.numberOfFrames, Math.round((start - sample.timestamp) * sample.sampleRate)));
93
+ const last = Math.max(0, Math.min(sample.numberOfFrames, Math.round((end - sample.timestamp) * sample.sampleRate)));
94
+ if (first >= last)
95
+ continue;
96
+ const trimmed = sample.trim(first, last);
97
+ try {
98
+ // Round in frames so timestamp drift cannot create a zero-frame padding sample.
99
+ const offsetFrames = Math.max(0, Math.round((sample.timestamp - start) * sample.sampleRate) + first);
100
+ trimmed.setTimestamp(offsetFrames / sample.sampleRate);
101
+ if (!sent && offsetFrames > 0) {
102
+ const padding = new AudioSample({
103
+ data: new Float32Array(offsetFrames * sample.numberOfChannels),
104
+ format: 'f32',
105
+ sampleRate: sample.sampleRate,
106
+ numberOfChannels: sample.numberOfChannels,
107
+ timestamp: 0,
108
+ });
109
+ try {
110
+ await source.add(padding);
111
+ }
112
+ finally {
113
+ padding.close();
114
+ }
115
+ }
116
+ await source.add(trimmed);
117
+ sent = true;
118
+ }
119
+ finally {
120
+ trimmed.close();
121
+ }
122
+ }
123
+ finally {
124
+ sample.close();
125
+ }
126
+ }
127
+ source.close();
128
+ await output.finalize();
129
+ return new Uint8Array(output.target.buffer);
130
+ }
131
+ /** Cuts a recording; yields its pieces in order. */
132
+ export async function* cutPieces(file, options) {
133
+ const info = await readAudioInfo(file, options.signal);
134
+ options.signal?.throwIfAborted();
135
+ if (info.path === null)
136
+ throw new UnreadableAudioError(info.reason ?? 'unsupported_codec');
137
+ // Validate the options before opening the cutting input. Quiet cuts are planned from their actual starts below.
138
+ planPieces(info.seconds, options);
139
+ const input = new Input({ formats: ALL_FORMATS, source: file instanceof Uint8Array ? new BufferSource(file) : new BlobSource(file) });
140
+ try {
141
+ const track = (await input.getPrimaryAudioTrack());
142
+ const quiet = options.quietSeconds ?? 10;
143
+ let start = 0;
144
+ for (let index = 0; start < info.seconds; index += 1) {
145
+ options.signal?.throwIfAborted();
146
+ let end = Math.min(info.seconds, start + options.pieceSeconds);
147
+ // Keep the planner's one-second tail allowance.
148
+ if (info.seconds - end <= 1)
149
+ end = info.seconds;
150
+ if (info.path === 'decode' && end < info.seconds)
151
+ end = await quietestBefore(track, Math.max(start + options.overlapSeconds + 1, end - quiet), end);
152
+ if (index >= (options.fromIndex ?? 0)) {
153
+ const data = info.path === 'copy' ? await copyPiece(track, info.codec, start, end, end >= info.seconds) : await decodePiece(track, start, end);
154
+ if (data.length > options.maxBytes)
155
+ throw new RangeError(`piece ${index} is ${data.length} bytes, past ${options.maxBytes}`);
156
+ const extension = info.path === 'decode' || info.codec === 'pcm-s16' ? 'wav' : COPY_TARGETS[info.codec].extension;
157
+ yield {
158
+ index,
159
+ startMs: Math.round(start * 1000),
160
+ durationMs: Math.round((end - start) * 1000),
161
+ data,
162
+ mimeType: extension === 'wav' ? 'audio/wav' : COPY_TARGETS[info.codec].mimeType,
163
+ fileName: `piece-${index}.${extension}`,
164
+ };
165
+ }
166
+ if (end >= info.seconds)
167
+ break;
168
+ start = Math.max(0, end - options.overlapSeconds);
169
+ }
170
+ }
171
+ finally {
172
+ input.dispose();
173
+ }
174
+ }
175
+ //# sourceMappingURL=cut.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cut.js","sourceRoot":"","sources":["../../../../src/io/hearing/pieces/cut.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @fileoverview Audio pieces and their batch transcription, in a page or on a server. The only external import is
3
+ * the optional peer Mediabunny; this entry reaches no Node built-in.
4
+ * @module agentos/io/hearing/pieces
5
+ */
6
+ export { planPieces, type PiecePlan } from './plan.js';
7
+ export { readAudioInfo, pieceSeconds, type AudioInfo, UnreadableAudioError, COPY_TARGETS, MAX_COPIED_PCM_BYTES_PER_SECOND } from './read.js';
8
+ export { wavHeaderSeconds, readWavPcm, type WavPcm } from './wav.js';
9
+ export { cutPieces, type AudioPiece, type CutOptions } from './cut.js';
10
+ export { transcribePieces, mergeSeam, lastSentence, PiecesFailed, type TranscribePiecesOptions, type PieceInput, type PieceTranscript, type TranscribePiece, type PieceOutcome, } from '../transcribePieces.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/io/hearing/pieces/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,oBAAoB,EAAE,YAAY,EAAE,+BAA+B,EAAE,MAAM,WAAW,CAAC;AAC7I,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AACvE,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,KAAK,uBAAuB,EAC5B,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @fileoverview Audio pieces and their batch transcription, in a page or on a server. The only external import is
3
+ * the optional peer Mediabunny; this entry reaches no Node built-in.
4
+ * @module agentos/io/hearing/pieces
5
+ */
6
+ export { planPieces } from './plan.js';
7
+ export { readAudioInfo, pieceSeconds, UnreadableAudioError, COPY_TARGETS, MAX_COPIED_PCM_BYTES_PER_SECOND } from './read.js';
8
+ export { wavHeaderSeconds, readWavPcm } from './wav.js';
9
+ export { cutPieces } from './cut.js';
10
+ export { transcribePieces, mergeSeam, lastSentence, PiecesFailed, } from '../transcribePieces.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/io/hearing/pieces/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAkB,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAkB,oBAAoB,EAAE,YAAY,EAAE,+BAA+B,EAAE,MAAM,WAAW,CAAC;AAC7I,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAe,MAAM,UAAU,CAAC;AACrE,OAAO,EAAE,SAAS,EAAoC,MAAM,UAAU,CAAC;AACvE,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,YAAY,GAMb,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @fileoverview Where the pieces of a recording start and end: `pieceSeconds` long, each starting `overlapSeconds`
3
+ * before the one before it ends; a remainder no longer than the overlap and one second joins the piece before it.
4
+ * @module agentos/io/hearing/pieces/plan
5
+ */
6
+ /** One planned piece, in seconds. */
7
+ export interface PiecePlan {
8
+ index: number;
9
+ start: number;
10
+ end: number;
11
+ }
12
+ /** The pieces of a recording of `seconds`. */
13
+ export declare function planPieces(seconds: number, options: {
14
+ pieceSeconds: number;
15
+ overlapSeconds: number;
16
+ }): PiecePlan[];
17
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../../src/io/hearing/pieces/plan.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,qCAAqC;AACrC,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,8CAA8C;AAC9C,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EAAE,CAiBlH"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @fileoverview Where the pieces of a recording start and end: `pieceSeconds` long, each starting `overlapSeconds`
3
+ * before the one before it ends; a remainder no longer than the overlap and one second joins the piece before it.
4
+ * @module agentos/io/hearing/pieces/plan
5
+ */
6
+ /** The pieces of a recording of `seconds`. */
7
+ export function planPieces(seconds, options) {
8
+ const { pieceSeconds, overlapSeconds } = options;
9
+ if (!Number.isFinite(seconds) || seconds <= 0)
10
+ throw new RangeError('planPieces: the length must be a positive number of seconds');
11
+ if (!Number.isFinite(pieceSeconds) || pieceSeconds < 10)
12
+ throw new RangeError('planPieces: a piece must be finite and 10 seconds or more');
13
+ if (!Number.isFinite(overlapSeconds) || overlapSeconds < 0 || overlapSeconds >= pieceSeconds)
14
+ throw new RangeError('planPieces: the overlap must be finite, nonnegative and shorter than a piece');
15
+ const step = pieceSeconds - overlapSeconds;
16
+ const pieces = [];
17
+ for (let start = 0, index = 0; start < seconds; start += step, index += 1) {
18
+ const end = Math.min(seconds, start + pieceSeconds);
19
+ if (pieces.length > 0 && end - start <= overlapSeconds + 1) {
20
+ pieces[pieces.length - 1].end = end;
21
+ break;
22
+ }
23
+ pieces.push({ index, start, end });
24
+ if (end >= seconds)
25
+ break;
26
+ }
27
+ return pieces;
28
+ }
29
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../../src/io/hearing/pieces/plan.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,8CAA8C;AAC9C,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,OAAyD;IACnG,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;IACjD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,6DAA6D,CAAC,CAAC;IACnI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,YAAY,GAAG,EAAE;QAAE,MAAM,IAAI,UAAU,CAAC,2DAA2D,CAAC,CAAC;IAC3I,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,cAAc,GAAG,CAAC,IAAI,cAAc,IAAI,YAAY;QAAE,MAAM,IAAI,UAAU,CAAC,8EAA8E,CAAC,CAAC;IACnM,MAAM,IAAI,GAAG,YAAY,GAAG,cAAc,CAAC;IAC3C,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,GAAG,YAAY,CAAC,CAAC;QACpD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,GAAG,KAAK,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YAC3D,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,GAAG,GAAG,GAAG,CAAC;YACrC,MAAM;QACR,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACnC,IAAI,GAAG,IAAI,OAAO;YAAE,MAAM;IAC5B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @fileoverview What a recording is, read with Mediabunny without decoding: its container, its audio codec, its length,
3
+ * and how its pieces are made. A piece's length read the same way on a server.
4
+ * @module agentos/io/hearing/pieces/read
5
+ */
6
+ /** The containers and codecs a piece is copied into, and the type OpenAI's transcription reads it as. */
7
+ export declare const COPY_TARGETS: {
8
+ readonly aac: {
9
+ readonly extension: "m4a";
10
+ readonly mimeType: "audio/mp4";
11
+ };
12
+ readonly opus: {
13
+ readonly extension: "webm";
14
+ readonly mimeType: "audio/webm";
15
+ };
16
+ readonly vorbis: {
17
+ readonly extension: "webm";
18
+ readonly mimeType: "audio/webm";
19
+ };
20
+ readonly mp3: {
21
+ readonly extension: "mp3";
22
+ readonly mimeType: "audio/mpeg";
23
+ };
24
+ };
25
+ /** PCM above this many bytes a second is decoded to 16 kHz mono (512 kbps). */
26
+ export declare const MAX_COPIED_PCM_BYTES_PER_SECOND = 64000;
27
+ /** Why a file cannot be cut. */
28
+ export declare class UnreadableAudioError extends Error {
29
+ readonly reason: 'container' | 'no_audio' | 'unsupported_codec' | 'cannot_decode';
30
+ constructor(reason: 'container' | 'no_audio' | 'unsupported_codec' | 'cannot_decode');
31
+ }
32
+ /** A recording as read. */
33
+ export interface AudioInfo {
34
+ container: string;
35
+ codec: string | null;
36
+ seconds: number;
37
+ sampleRate: number;
38
+ channels: number;
39
+ /** `copy`: packets copied into a container; `decode`: decoded to 16 kHz mono WAV; null: refused, with `reason`. */
40
+ path: 'copy' | 'decode' | null;
41
+ reason?: UnreadableAudioError['reason'];
42
+ }
43
+ /** Reads a recording's container, codec and length, and decides how its pieces are made. The signal can cancel the packet scan. */
44
+ export declare function readAudioInfo(source: Blob | Uint8Array, signal?: AbortSignal): Promise<AudioInfo>;
45
+ /** A piece's length in seconds, read from its container: what a server measures before it sends the piece on. */
46
+ export declare function pieceSeconds(bytes: Uint8Array): Promise<number>;
47
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../../src/io/hearing/pieces/read.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,yGAAyG;AACzG,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;CAKf,CAAC;AAEX,+EAA+E;AAC/E,eAAO,MAAM,+BAA+B,QAAS,CAAC;AAItD,gCAAgC;AAChC,qBAAa,oBAAqB,SAAQ,KAAK;IACjC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,UAAU,GAAG,mBAAmB,GAAG,eAAe;gBAAxE,MAAM,EAAE,WAAW,GAAG,UAAU,GAAG,mBAAmB,GAAG,eAAe;CAI9F;AAED,2BAA2B;AAC3B,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,mHAAmH;IACnH,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC/B,MAAM,CAAC,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC;CACzC;AAYD,mIAAmI;AACnI,wBAAsB,aAAa,CAAC,MAAM,EAAE,IAAI,GAAG,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAsCvG;AAED,iHAAiH;AACjH,wBAAsB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAYrE"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @fileoverview What a recording is, read with Mediabunny without decoding: its container, its audio codec, its length,
3
+ * and how its pieces are made. A piece's length read the same way on a server.
4
+ * @module agentos/io/hearing/pieces/read
5
+ */
6
+ import { ALL_FORMATS, BlobSource, BufferSource, EncodedPacketSink, Input } from 'mediabunny';
7
+ /** The containers and codecs a piece is copied into, and the type OpenAI's transcription reads it as. */
8
+ export const COPY_TARGETS = {
9
+ aac: { extension: 'm4a', mimeType: 'audio/mp4' },
10
+ opus: { extension: 'webm', mimeType: 'audio/webm' },
11
+ vorbis: { extension: 'webm', mimeType: 'audio/webm' },
12
+ mp3: { extension: 'mp3', mimeType: 'audio/mpeg' },
13
+ };
14
+ /** PCM above this many bytes a second is decoded to 16 kHz mono (512 kbps). */
15
+ export const MAX_COPIED_PCM_BYTES_PER_SECOND = 64000;
16
+ const REFUSED = new Set(['ac3', 'eac3', 'dts']);
17
+ /** Why a file cannot be cut. */
18
+ export class UnreadableAudioError extends Error {
19
+ constructor(reason) {
20
+ super(`the recording cannot be read (${reason})`);
21
+ this.reason = reason;
22
+ this.name = 'UnreadableAudioError';
23
+ }
24
+ }
25
+ function inputOf(source) {
26
+ return new Input({ formats: ALL_FORMATS, source: source instanceof Uint8Array ? new BufferSource(source) : new BlobSource(source) });
27
+ }
28
+ /** The bytes a second of a PCM codec at a rate and channel count, or null for a codec that is not PCM. */
29
+ function pcmBytesPerSecond(codec, sampleRate, channels) {
30
+ const bits = /^pcm-[suf](8|16|24|32|64)/.exec(codec)?.[1] ?? (codec === 'ulaw' || codec === 'alaw' ? '8' : null);
31
+ return bits === null ? null : (Number(bits) / 8) * sampleRate * channels;
32
+ }
33
+ /** Reads a recording's container, codec and length, and decides how its pieces are made. The signal can cancel the packet scan. */
34
+ export async function readAudioInfo(source, signal) {
35
+ signal?.throwIfAborted();
36
+ const input = inputOf(source);
37
+ try {
38
+ let container;
39
+ try {
40
+ container = (await input.getFormat()).name;
41
+ }
42
+ catch {
43
+ throw new UnreadableAudioError('container');
44
+ }
45
+ signal?.throwIfAborted();
46
+ const track = await input.getPrimaryAudioTrack();
47
+ if (track === null)
48
+ return { container, codec: null, seconds: 0, sampleRate: 0, channels: 0, path: null, reason: 'no_audio' };
49
+ const codec = await track.getCodec();
50
+ const [seconds, sampleRate, channels] = await Promise.all([track.computeDuration(), track.getSampleRate(), track.getNumberOfChannels()]);
51
+ signal?.throwIfAborted();
52
+ const base = { container, codec, seconds, sampleRate, channels };
53
+ if (codec === null || REFUSED.has(codec))
54
+ return { ...base, path: null, reason: 'unsupported_codec' };
55
+ if (codec in COPY_TARGETS) {
56
+ // Compressed tracks can exceed the copy limit too; count their packets without decoding or retaining them.
57
+ let bytes = 0;
58
+ for await (const packet of new EncodedPacketSink(track).packets()) {
59
+ signal?.throwIfAborted();
60
+ bytes += packet.data.byteLength;
61
+ if (bytes > seconds * MAX_COPIED_PCM_BYTES_PER_SECOND) {
62
+ return (await track.canDecode()) ? { ...base, path: 'decode' } : { ...base, path: null, reason: 'cannot_decode' };
63
+ }
64
+ }
65
+ signal?.throwIfAborted();
66
+ return { ...base, path: 'copy' };
67
+ }
68
+ const pcm = pcmBytesPerSecond(codec, sampleRate, channels);
69
+ // 'pcm-s16' is little-endian; 'pcm-s16be' and every other PCM codec is decoded (Mediabunny's src/codec.ts lines 59 to 71).
70
+ if (pcm !== null && pcm <= MAX_COPIED_PCM_BYTES_PER_SECOND && codec === 'pcm-s16')
71
+ return { ...base, path: 'copy' };
72
+ return (await track.canDecode()) ? { ...base, path: 'decode' } : { ...base, path: null, reason: 'cannot_decode' };
73
+ }
74
+ finally {
75
+ input.dispose();
76
+ }
77
+ }
78
+ /** A piece's length in seconds, read from its container: what a server measures before it sends the piece on. */
79
+ export async function pieceSeconds(bytes) {
80
+ const input = inputOf(bytes);
81
+ try {
82
+ const track = await input.getPrimaryAudioTrack();
83
+ if (track === null)
84
+ throw new UnreadableAudioError('no_audio');
85
+ return await track.computeDuration();
86
+ }
87
+ catch (error) {
88
+ if (error instanceof UnreadableAudioError)
89
+ throw error;
90
+ throw new UnreadableAudioError('container');
91
+ }
92
+ finally {
93
+ input.dispose();
94
+ }
95
+ }
96
+ //# sourceMappingURL=read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../../../src/io/hearing/pieces/read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @fileoverview WAVE durations and planar PCM samples read through DataView, in a page or on a server.
3
+ * @module agentos/io/hearing/pieces/wav
4
+ */
5
+ /** A WAVE recording's rate, channel count and samples, one array per channel. */
6
+ export interface WavPcm {
7
+ sampleRate: number;
8
+ channels: number;
9
+ samples: Float32Array[];
10
+ }
11
+ /** Reads seconds from the WAVE header's byte rate and declared data length; the sample bytes need not be present. */
12
+ export declare function wavHeaderSeconds(bytes: Uint8Array): number;
13
+ /** Reads 16-bit integer or 32-bit float PCM from a WAVE file into one Float32Array per channel. */
14
+ export declare function readWavPcm(bytes: Uint8Array): WavPcm;
15
+ //# sourceMappingURL=wav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wav.d.ts","sourceRoot":"","sources":["../../../../src/io/hearing/pieces/wav.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,iFAAiF;AACjF,MAAM,WAAW,MAAM;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAoDD,qHAAqH;AACrH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAG1D;AAED,mGAAmG;AACnG,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAcpD"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @fileoverview WAVE durations and planar PCM samples read through DataView, in a page or on a server.
3
+ * @module agentos/io/hearing/pieces/wav
4
+ */
5
+ import { UnreadableAudioError } from './read.js';
6
+ /** Reads RIFF chunks, including padding, without requiring a data chunk's payload for a header read. */
7
+ function chunksOf(bytes, headerOnly) {
8
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
9
+ const fourCC = (offset) => String.fromCharCode(view.getUint8(offset), view.getUint8(offset + 1), view.getUint8(offset + 2), view.getUint8(offset + 3));
10
+ if (bytes.length < 12 || fourCC(0) !== 'RIFF' || fourCC(8) !== 'WAVE')
11
+ throw new UnreadableAudioError('container');
12
+ const limit = view.getUint32(4, true) + 8;
13
+ if (limit < 12 || (!headerOnly && limit > bytes.length))
14
+ throw new UnreadableAudioError('container');
15
+ let formatOffset;
16
+ let dataOffset;
17
+ let dataLength = 0;
18
+ for (let offset = 12; offset + 8 <= Math.min(limit, bytes.length);) {
19
+ const name = fourCC(offset);
20
+ const length = view.getUint32(offset + 4, true);
21
+ const payload = offset + 8;
22
+ if (payload + length > limit)
23
+ throw new UnreadableAudioError('container');
24
+ if (name === 'data') {
25
+ dataOffset ?? (dataOffset = payload);
26
+ if (dataOffset === payload)
27
+ dataLength = length;
28
+ if (headerOnly && formatOffset !== undefined)
29
+ break;
30
+ }
31
+ if (payload + length > bytes.length)
32
+ throw new UnreadableAudioError('container');
33
+ if (name === 'fmt ' && formatOffset === undefined) {
34
+ if (length < 16)
35
+ throw new UnreadableAudioError('container');
36
+ formatOffset = payload;
37
+ }
38
+ offset = payload + length + (length % 2);
39
+ }
40
+ if (formatOffset === undefined || dataOffset === undefined)
41
+ throw new UnreadableAudioError('container');
42
+ const format = view.getUint16(formatOffset, true);
43
+ const channels = view.getUint16(formatOffset + 2, true);
44
+ const sampleRate = view.getUint32(formatOffset + 4, true);
45
+ const byteRate = view.getUint32(formatOffset + 8, true);
46
+ const blockAlign = view.getUint16(formatOffset + 12, true);
47
+ const bits = view.getUint16(formatOffset + 14, true);
48
+ if (channels === 0 || sampleRate === 0 || byteRate === 0 || blockAlign === 0)
49
+ throw new UnreadableAudioError('container');
50
+ return { view, format, channels, sampleRate, byteRate, blockAlign, bits, dataOffset, dataLength };
51
+ }
52
+ /** Reads seconds from the WAVE header's byte rate and declared data length; the sample bytes need not be present. */
53
+ export function wavHeaderSeconds(bytes) {
54
+ const { byteRate, dataLength } = chunksOf(bytes, true);
55
+ return dataLength / byteRate;
56
+ }
57
+ /** Reads 16-bit integer or 32-bit float PCM from a WAVE file into one Float32Array per channel. */
58
+ export function readWavPcm(bytes) {
59
+ const { view, format, channels, sampleRate, byteRate, blockAlign, bits, dataOffset, dataLength } = chunksOf(bytes, false);
60
+ if (!((format === 1 && bits === 16) || (format === 3 && bits === 32)))
61
+ throw new UnreadableAudioError('unsupported_codec');
62
+ const width = bits / 8;
63
+ if (blockAlign !== channels * width || byteRate !== sampleRate * blockAlign || dataLength % blockAlign !== 0)
64
+ throw new UnreadableAudioError('container');
65
+ const frames = dataLength / blockAlign;
66
+ const samples = Array.from({ length: channels }, () => new Float32Array(frames));
67
+ for (let frame = 0; frame < frames; frame += 1) {
68
+ for (let channel = 0; channel < channels; channel += 1) {
69
+ const offset = dataOffset + frame * blockAlign + channel * width;
70
+ samples[channel][frame] = format === 1 ? view.getInt16(offset, true) / 32768 : view.getFloat32(offset, true);
71
+ }
72
+ }
73
+ return { sampleRate, channels, samples };
74
+ }
75
+ //# sourceMappingURL=wav.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wav.js","sourceRoot":"","sources":["../../../../src/io/hearing/pieces/wav.ts"],"names":[],"mappings":"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"}
@@ -108,6 +108,11 @@ export declare abstract class CLISubprocessBridge {
108
108
  * Spawns the binary with `--output-format stream-json` and yields
109
109
  * {@link StreamEvent}s parsed from newline-delimited JSON on stdout.
110
110
  *
111
+ * Read to its end, the stream awaits the process's exit and throws on a
112
+ * failed one. A consumer that stops reading before the end (a `break` in
113
+ * its `for await`, or `return()`) ends the process instead: it is killed,
114
+ * and its outcome is handled here.
115
+ *
111
116
  * @param options — bridge options
112
117
  * @yields typed stream events (text_delta, result, error, system)
113
118
  * @throws {CLISubprocessError} on subprocess failure (via {@link classifyError})
@@ -1 +1 @@
1
- {"version":3,"file":"CLISubprocessBridge.d.ts","sourceRoot":"","sources":["../../../../src/safety/sandbox/subprocess/CLISubprocessBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA8BH,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAKjB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,8BAAsB,mBAAmB;IAIvC,uEAAuE;IACvE,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE/C;;;;;;;OAOG;IACH,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,EAAE;IAEpF;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,kBAAkB;IAEhE;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,GAAG,EAAE,GAAG,GAAG,WAAW,GAAG,IAAI;IAIjE;;;;OAIG;IACH,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY;IAiB3E;;;OAGG;IACH,SAAS,CAAC,kBAAkB,IAAI;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IAOjE;;;OAGG;IACH,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAO9C;;;OAGG;IACG,oBAAoB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAezD;;;OAGG;IACG,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC;IAW5C;;;;;;;;OAQG;IACG,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAoB5D;;;;;;;;OAQG;IACI,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,cAAc,CAAC,WAAW,EAAE,IAAI,EAAE,SAAS,CAAC;CAmDpF"}
1
+ {"version":3,"file":"CLISubprocessBridge.d.ts","sourceRoot":"","sources":["../../../../src/safety/sandbox/subprocess/CLISubprocessBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA8BH,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAKjB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,8BAAsB,mBAAmB;IAIvC,uEAAuE;IACvE,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE/C;;;;;;;OAOG;IACH,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,EAAE;IAEpF;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,kBAAkB;IAEhE;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,GAAG,EAAE,GAAG,GAAG,WAAW,GAAG,IAAI;IAIjE;;;;OAIG;IACH,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY;IAiB3E;;;OAGG;IACH,SAAS,CAAC,kBAAkB,IAAI;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IAOjE;;;OAGG;IACH,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAO9C;;;OAGG;IACG,oBAAoB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAezD;;;OAGG;IACG,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC;IAW5C;;;;;;;;OAQG;IACG,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAoB5D;;;;;;;;;;;;;OAaG;IACI,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,cAAc,CAAC,WAAW,EAAE,IAAI,EAAE,SAAS,CAAC;CAkEpF"}
@@ -169,6 +169,11 @@ export class CLISubprocessBridge {
169
169
  * Spawns the binary with `--output-format stream-json` and yields
170
170
  * {@link StreamEvent}s parsed from newline-delimited JSON on stdout.
171
171
  *
172
+ * Read to its end, the stream awaits the process's exit and throws on a
173
+ * failed one. A consumer that stops reading before the end (a `break` in
174
+ * its `for await`, or `return()`) ends the process instead: it is killed,
175
+ * and its outcome is handled here.
176
+ *
172
177
  * @param options — bridge options
173
178
  * @yields typed stream events (text_delta, result, error, system)
174
179
  * @throws {CLISubprocessError} on subprocess failure (via {@link classifyError})
@@ -189,6 +194,10 @@ export class CLISubprocessBridge {
189
194
  throw this.classifyError(error);
190
195
  }
191
196
  let buffer = '';
197
+ /* Set once stdout has been read to its end and the run is awaited below.
198
+ * A consumer that stops reading early (a break in its for await, or
199
+ * return()) closes this generator at a yield, before that point. */
200
+ let readToEnd = false;
192
201
  try {
193
202
  for await (const chunk of subprocess.stdout) {
194
203
  buffer += chunk.toString();
@@ -217,12 +226,24 @@ export class CLISubprocessBridge {
217
226
  }
218
227
  catch { /* ignore */ }
219
228
  }
229
+ readToEnd = true;
220
230
  /* Ensure non-zero exits after stdout drains still surface as errors. */
221
231
  await subprocess;
222
232
  }
223
233
  catch (error) {
224
234
  throw this.classifyError(error);
225
235
  }
236
+ finally {
237
+ /* Left before the run was awaited: nothing reads the process any more.
238
+ * End it (execa's kill: SIGTERM, then SIGKILL if it outlives the force
239
+ * delay) and handle its outcome, so a failed exit that follows is not an
240
+ * unhandled rejection in the host, which Node raises as an uncaught
241
+ * exception by default. */
242
+ if (!readToEnd) {
243
+ subprocess.kill();
244
+ subprocess.catch(() => undefined);
245
+ }
246
+ }
226
247
  }
227
248
  }
228
249
  //# sourceMappingURL=CLISubprocessBridge.js.map