pocketstation 0.0.0-stage → 0.1.6
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/LICENSE +21 -0
- package/README.md +619 -2
- package/THIRD_PARTY_NOTICES.md +478 -0
- package/bin/pocketstation-demo.mjs +357 -0
- package/dist/browser/index.d.ts +12 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +11 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/latency-report.d.ts +2 -0
- package/dist/browser/latency-report.d.ts.map +1 -0
- package/dist/browser/latency-report.js +27 -0
- package/dist/browser/latency-report.js.map +1 -0
- package/dist/browser/operation-signal.d.ts +2 -0
- package/dist/browser/operation-signal.d.ts.map +1 -0
- package/dist/browser/operation-signal.js +31 -0
- package/dist/browser/operation-signal.js.map +1 -0
- package/dist/browser/relay-publisher.d.ts +32 -0
- package/dist/browser/relay-publisher.d.ts.map +1 -0
- package/dist/browser/relay-publisher.js +653 -0
- package/dist/browser/relay-publisher.js.map +1 -0
- package/dist/browser/relay-session.d.ts +36 -0
- package/dist/browser/relay-session.d.ts.map +1 -0
- package/dist/browser/relay-session.js +859 -0
- package/dist/browser/relay-session.js.map +1 -0
- package/dist/browser/signaling.d.ts +2 -0
- package/dist/browser/signaling.d.ts.map +1 -0
- package/dist/browser/signaling.js +253 -0
- package/dist/browser/signaling.js.map +1 -0
- package/dist/browser/types.d.ts +204 -0
- package/dist/browser/types.d.ts.map +1 -0
- package/dist/browser/types.js +2 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/cjs/browser/index.d.ts +12 -0
- package/dist/cjs/browser/index.d.ts.map +1 -0
- package/dist/cjs/browser/index.js +21 -0
- package/dist/cjs/browser/index.js.map +1 -0
- package/dist/cjs/browser/latency-report.d.ts +2 -0
- package/dist/cjs/browser/latency-report.d.ts.map +1 -0
- package/dist/cjs/browser/latency-report.js +30 -0
- package/dist/cjs/browser/latency-report.js.map +1 -0
- package/dist/cjs/browser/operation-signal.d.ts +2 -0
- package/dist/cjs/browser/operation-signal.d.ts.map +1 -0
- package/dist/cjs/browser/operation-signal.js +34 -0
- package/dist/cjs/browser/operation-signal.js.map +1 -0
- package/dist/cjs/browser/relay-publisher.d.ts +32 -0
- package/dist/cjs/browser/relay-publisher.d.ts.map +1 -0
- package/dist/cjs/browser/relay-publisher.js +657 -0
- package/dist/cjs/browser/relay-publisher.js.map +1 -0
- package/dist/cjs/browser/relay-session.d.ts +36 -0
- package/dist/cjs/browser/relay-session.d.ts.map +1 -0
- package/dist/cjs/browser/relay-session.js +865 -0
- package/dist/cjs/browser/relay-session.js.map +1 -0
- package/dist/cjs/browser/signaling.d.ts +2 -0
- package/dist/cjs/browser/signaling.d.ts.map +1 -0
- package/dist/cjs/browser/signaling.js +257 -0
- package/dist/cjs/browser/signaling.js.map +1 -0
- package/dist/cjs/browser/types.d.ts +204 -0
- package/dist/cjs/browser/types.d.ts.map +1 -0
- package/dist/cjs/browser/types.js +3 -0
- package/dist/cjs/browser/types.js.map +1 -0
- package/dist/cjs/compatibility.d.ts +28 -0
- package/dist/cjs/compatibility.d.ts.map +1 -0
- package/dist/cjs/compatibility.js +41 -0
- package/dist/cjs/compatibility.js.map +1 -0
- package/dist/cjs/control/control-client.d.ts +43 -0
- package/dist/cjs/control/control-client.d.ts.map +1 -0
- package/dist/cjs/control/control-client.js +775 -0
- package/dist/cjs/control/control-client.js.map +1 -0
- package/dist/cjs/control/index.d.ts +5 -0
- package/dist/cjs/control/index.d.ts.map +1 -0
- package/dist/cjs/control/index.js +16 -0
- package/dist/cjs/control/index.js.map +1 -0
- package/dist/cjs/control/invitation-locator.d.ts +3 -0
- package/dist/cjs/control/invitation-locator.d.ts.map +1 -0
- package/dist/cjs/control/invitation-locator.js +9 -0
- package/dist/cjs/control/invitation-locator.js.map +1 -0
- package/dist/cjs/control/session-owner.d.ts +24 -0
- package/dist/cjs/control/session-owner.d.ts.map +1 -0
- package/dist/cjs/control/session-owner.js +127 -0
- package/dist/cjs/control/session-owner.js.map +1 -0
- package/dist/cjs/control/types.d.ts +158 -0
- package/dist/cjs/control/types.d.ts.map +1 -0
- package/dist/cjs/control/types.js +85 -0
- package/dist/cjs/control/types.js.map +1 -0
- package/dist/cjs/demo/audio-windows.d.ts +39 -0
- package/dist/cjs/demo/audio-windows.d.ts.map +1 -0
- package/dist/cjs/demo/audio-windows.js +242 -0
- package/dist/cjs/demo/audio-windows.js.map +1 -0
- package/dist/cjs/demo/faster-whisper.d.ts +98 -0
- package/dist/cjs/demo/faster-whisper.d.ts.map +1 -0
- package/dist/cjs/demo/faster-whisper.js +355 -0
- package/dist/cjs/demo/faster-whisper.js.map +1 -0
- package/dist/cjs/demo/index.d.ts +6 -0
- package/dist/cjs/demo/index.d.ts.map +1 -0
- package/dist/cjs/demo/index.js +23 -0
- package/dist/cjs/demo/index.js.map +1 -0
- package/dist/cjs/demo/openai-realtime.d.ts +101 -0
- package/dist/cjs/demo/openai-realtime.d.ts.map +1 -0
- package/dist/cjs/demo/openai-realtime.js +853 -0
- package/dist/cjs/demo/openai-realtime.js.map +1 -0
- package/dist/cjs/demo/transcript.d.ts +29 -0
- package/dist/cjs/demo/transcript.d.ts.map +1 -0
- package/dist/cjs/demo/transcript.js +77 -0
- package/dist/cjs/demo/transcript.js.map +1 -0
- package/dist/cjs/demo/whisper-cli-model.d.ts +20 -0
- package/dist/cjs/demo/whisper-cli-model.d.ts.map +1 -0
- package/dist/cjs/demo/whisper-cli-model.js +192 -0
- package/dist/cjs/demo/whisper-cli-model.js.map +1 -0
- package/dist/cjs/demo/window-signal.d.ts +11 -0
- package/dist/cjs/demo/window-signal.d.ts.map +1 -0
- package/dist/cjs/demo/window-signal.js +58 -0
- package/dist/cjs/demo/window-signal.js.map +1 -0
- package/dist/cjs/errors.d.ts +11 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +18 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.d.ts +14 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +20 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/node/aec.d.ts +76 -0
- package/dist/cjs/node/aec.d.ts.map +1 -0
- package/dist/cjs/node/aec.js +106 -0
- package/dist/cjs/node/aec.js.map +1 -0
- package/dist/cjs/node/application-audio.d.ts +144 -0
- package/dist/cjs/node/application-audio.d.ts.map +1 -0
- package/dist/cjs/node/application-audio.js +250 -0
- package/dist/cjs/node/application-audio.js.map +1 -0
- package/dist/cjs/node/capture.d.ts +104 -0
- package/dist/cjs/node/capture.d.ts.map +1 -0
- package/dist/cjs/node/capture.js +236 -0
- package/dist/cjs/node/capture.js.map +1 -0
- package/dist/cjs/node/connector.d.ts +414 -0
- package/dist/cjs/node/connector.d.ts.map +1 -0
- package/dist/cjs/node/connector.js +756 -0
- package/dist/cjs/node/connector.js.map +1 -0
- package/dist/cjs/node/endpoint.d.ts +169 -0
- package/dist/cjs/node/endpoint.d.ts.map +1 -0
- package/dist/cjs/node/endpoint.js +581 -0
- package/dist/cjs/node/endpoint.js.map +1 -0
- package/dist/cjs/node/errors.d.ts +203 -0
- package/dist/cjs/node/errors.d.ts.map +1 -0
- package/dist/cjs/node/errors.js +477 -0
- package/dist/cjs/node/errors.js.map +1 -0
- package/dist/cjs/node/event-input.d.ts +56 -0
- package/dist/cjs/node/event-input.d.ts.map +1 -0
- package/dist/cjs/node/event-input.js +207 -0
- package/dist/cjs/node/event-input.js.map +1 -0
- package/dist/cjs/node/events.d.ts +260 -0
- package/dist/cjs/node/events.d.ts.map +1 -0
- package/dist/cjs/node/events.js +475 -0
- package/dist/cjs/node/events.js.map +1 -0
- package/dist/cjs/node/extensions.d.ts +117 -0
- package/dist/cjs/node/extensions.d.ts.map +1 -0
- package/dist/cjs/node/extensions.js +140 -0
- package/dist/cjs/node/extensions.js.map +1 -0
- package/dist/cjs/node/graph.d.ts +460 -0
- package/dist/cjs/node/graph.d.ts.map +1 -0
- package/dist/cjs/node/graph.js +920 -0
- package/dist/cjs/node/graph.js.map +1 -0
- package/dist/cjs/node/identity.d.ts +56 -0
- package/dist/cjs/node/identity.d.ts.map +1 -0
- package/dist/cjs/node/identity.js +67 -0
- package/dist/cjs/node/identity.js.map +1 -0
- package/dist/cjs/node/index.d.ts +31 -0
- package/dist/cjs/node/index.d.ts.map +1 -0
- package/dist/cjs/node/index.js +279 -0
- package/dist/cjs/node/index.js.map +1 -0
- package/dist/cjs/node/native-package.d.ts +2 -0
- package/dist/cjs/node/native-package.d.ts.map +1 -0
- package/dist/cjs/node/native-package.js +39 -0
- package/dist/cjs/node/native-package.js.map +1 -0
- package/dist/cjs/node/native.d.ts +1262 -0
- package/dist/cjs/node/native.d.ts.map +1 -0
- package/dist/cjs/node/native.js +13 -0
- package/dist/cjs/node/native.js.map +1 -0
- package/dist/cjs/node/observations.d.ts +500 -0
- package/dist/cjs/node/observations.d.ts.map +1 -0
- package/dist/cjs/node/observations.js +574 -0
- package/dist/cjs/node/observations.js.map +1 -0
- package/dist/cjs/node/operator.d.ts +117 -0
- package/dist/cjs/node/operator.d.ts.map +1 -0
- package/dist/cjs/node/operator.js +408 -0
- package/dist/cjs/node/operator.js.map +1 -0
- package/dist/cjs/node/provider.d.ts +276 -0
- package/dist/cjs/node/provider.d.ts.map +1 -0
- package/dist/cjs/node/provider.js +1088 -0
- package/dist/cjs/node/provider.js.map +1 -0
- package/dist/cjs/node/recording.d.ts +78 -0
- package/dist/cjs/node/recording.d.ts.map +1 -0
- package/dist/cjs/node/recording.js +153 -0
- package/dist/cjs/node/recording.js.map +1 -0
- package/dist/cjs/node/relay.d.ts +105 -0
- package/dist/cjs/node/relay.d.ts.map +1 -0
- package/dist/cjs/node/relay.js +398 -0
- package/dist/cjs/node/relay.js.map +1 -0
- package/dist/cjs/node/session.d.ts +414 -0
- package/dist/cjs/node/session.d.ts.map +1 -0
- package/dist/cjs/node/session.js +1212 -0
- package/dist/cjs/node/session.js.map +1 -0
- package/dist/cjs/node/sidecar.d.ts +179 -0
- package/dist/cjs/node/sidecar.d.ts.map +1 -0
- package/dist/cjs/node/sidecar.js +453 -0
- package/dist/cjs/node/sidecar.js.map +1 -0
- package/dist/cjs/node/signals.d.ts +177 -0
- package/dist/cjs/node/signals.d.ts.map +1 -0
- package/dist/cjs/node/signals.js +344 -0
- package/dist/cjs/node/signals.js.map +1 -0
- package/dist/cjs/node/source.d.ts +105 -0
- package/dist/cjs/node/source.d.ts.map +1 -0
- package/dist/cjs/node/source.js +271 -0
- package/dist/cjs/node/source.js.map +1 -0
- package/dist/cjs/node/sources.d.ts +334 -0
- package/dist/cjs/node/sources.d.ts.map +1 -0
- package/dist/cjs/node/sources.js +618 -0
- package/dist/cjs/node/sources.js.map +1 -0
- package/dist/cjs/node/streams.d.ts +163 -0
- package/dist/cjs/node/streams.d.ts.map +1 -0
- package/dist/cjs/node/streams.js +369 -0
- package/dist/cjs/node/streams.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/require-package.cjs +6 -0
- package/dist/cjs/require-package.d.cts +1 -0
- package/dist/cjs/voice/capabilities.d.ts +132 -0
- package/dist/cjs/voice/capabilities.d.ts.map +1 -0
- package/dist/cjs/voice/capabilities.js +207 -0
- package/dist/cjs/voice/capabilities.js.map +1 -0
- package/dist/cjs/voice/configuration.d.ts +129 -0
- package/dist/cjs/voice/configuration.d.ts.map +1 -0
- package/dist/cjs/voice/configuration.js +251 -0
- package/dist/cjs/voice/configuration.js.map +1 -0
- package/dist/cjs/voice/conversation.d.ts +220 -0
- package/dist/cjs/voice/conversation.d.ts.map +1 -0
- package/dist/cjs/voice/conversation.js +1389 -0
- package/dist/cjs/voice/conversation.js.map +1 -0
- package/dist/cjs/voice/duplex.d.ts +28 -0
- package/dist/cjs/voice/duplex.d.ts.map +1 -0
- package/dist/cjs/voice/duplex.js +19 -0
- package/dist/cjs/voice/duplex.js.map +1 -0
- package/dist/cjs/voice/errors.d.ts +44 -0
- package/dist/cjs/voice/errors.d.ts.map +1 -0
- package/dist/cjs/voice/errors.js +77 -0
- package/dist/cjs/voice/errors.js.map +1 -0
- package/dist/cjs/voice/events.d.ts +34 -0
- package/dist/cjs/voice/events.d.ts.map +1 -0
- package/dist/cjs/voice/events.js +47 -0
- package/dist/cjs/voice/events.js.map +1 -0
- package/dist/cjs/voice/index.d.ts +18 -0
- package/dist/cjs/voice/index.d.ts.map +1 -0
- package/dist/cjs/voice/index.js +55 -0
- package/dist/cjs/voice/index.js.map +1 -0
- package/dist/cjs/voice/response.d.ts +56 -0
- package/dist/cjs/voice/response.d.ts.map +1 -0
- package/dist/cjs/voice/response.js +74 -0
- package/dist/cjs/voice/response.js.map +1 -0
- package/dist/cjs/voice/speech-detection.d.ts +40 -0
- package/dist/cjs/voice/speech-detection.d.ts.map +1 -0
- package/dist/cjs/voice/speech-detection.js +43 -0
- package/dist/cjs/voice/speech-detection.js.map +1 -0
- package/dist/cjs/voice/synthesis.d.ts +47 -0
- package/dist/cjs/voice/synthesis.d.ts.map +1 -0
- package/dist/cjs/voice/synthesis.js +50 -0
- package/dist/cjs/voice/synthesis.js.map +1 -0
- package/dist/cjs/voice/transcription.d.ts +55 -0
- package/dist/cjs/voice/transcription.d.ts.map +1 -0
- package/dist/cjs/voice/transcription.js +75 -0
- package/dist/cjs/voice/transcription.js.map +1 -0
- package/dist/cjs/voice/turns.d.ts +94 -0
- package/dist/cjs/voice/turns.d.ts.map +1 -0
- package/dist/cjs/voice/turns.js +145 -0
- package/dist/cjs/voice/turns.js.map +1 -0
- package/dist/cjs/voice/validation.d.ts +17 -0
- package/dist/cjs/voice/validation.d.ts.map +1 -0
- package/dist/cjs/voice/validation.js +104 -0
- package/dist/cjs/voice/validation.js.map +1 -0
- package/dist/compatibility.d.ts +28 -0
- package/dist/compatibility.d.ts.map +1 -0
- package/dist/compatibility.js +37 -0
- package/dist/compatibility.js.map +1 -0
- package/dist/control/control-client.d.ts +43 -0
- package/dist/control/control-client.d.ts.map +1 -0
- package/dist/control/control-client.js +769 -0
- package/dist/control/control-client.js.map +1 -0
- package/dist/control/index.d.ts +5 -0
- package/dist/control/index.d.ts.map +1 -0
- package/dist/control/index.js +5 -0
- package/dist/control/index.js.map +1 -0
- package/dist/control/invitation-locator.d.ts +3 -0
- package/dist/control/invitation-locator.d.ts.map +1 -0
- package/dist/control/invitation-locator.js +6 -0
- package/dist/control/invitation-locator.js.map +1 -0
- package/dist/control/session-owner.d.ts +24 -0
- package/dist/control/session-owner.d.ts.map +1 -0
- package/dist/control/session-owner.js +123 -0
- package/dist/control/session-owner.js.map +1 -0
- package/dist/control/types.d.ts +158 -0
- package/dist/control/types.d.ts.map +1 -0
- package/dist/control/types.js +79 -0
- package/dist/control/types.js.map +1 -0
- package/dist/demo/audio-windows.d.ts +39 -0
- package/dist/demo/audio-windows.d.ts.map +1 -0
- package/dist/demo/audio-windows.js +235 -0
- package/dist/demo/audio-windows.js.map +1 -0
- package/dist/demo/faster-whisper.d.ts +98 -0
- package/dist/demo/faster-whisper.d.ts.map +1 -0
- package/dist/demo/faster-whisper.js +348 -0
- package/dist/demo/faster-whisper.js.map +1 -0
- package/dist/demo/index.d.ts +6 -0
- package/dist/demo/index.d.ts.map +1 -0
- package/dist/demo/index.js +6 -0
- package/dist/demo/index.js.map +1 -0
- package/dist/demo/openai-realtime.d.ts +101 -0
- package/dist/demo/openai-realtime.d.ts.map +1 -0
- package/dist/demo/openai-realtime.js +845 -0
- package/dist/demo/openai-realtime.js.map +1 -0
- package/dist/demo/transcript.d.ts +29 -0
- package/dist/demo/transcript.d.ts.map +1 -0
- package/dist/demo/transcript.js +73 -0
- package/dist/demo/transcript.js.map +1 -0
- package/dist/demo/whisper-cli-model.d.ts +20 -0
- package/dist/demo/whisper-cli-model.d.ts.map +1 -0
- package/dist/demo/whisper-cli-model.js +186 -0
- package/dist/demo/whisper-cli-model.js.map +1 -0
- package/dist/demo/window-signal.d.ts +11 -0
- package/dist/demo/window-signal.d.ts.map +1 -0
- package/dist/demo/window-signal.js +53 -0
- package/dist/demo/window-signal.js.map +1 -0
- package/dist/errors.d.ts +11 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +14 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/node/aec.d.ts +76 -0
- package/dist/node/aec.d.ts.map +1 -0
- package/dist/node/aec.js +99 -0
- package/dist/node/aec.js.map +1 -0
- package/dist/node/application-audio.d.ts +144 -0
- package/dist/node/application-audio.d.ts.map +1 -0
- package/dist/node/application-audio.js +233 -0
- package/dist/node/application-audio.js.map +1 -0
- package/dist/node/capture.d.ts +104 -0
- package/dist/node/capture.d.ts.map +1 -0
- package/dist/node/capture.js +231 -0
- package/dist/node/capture.js.map +1 -0
- package/dist/node/connector.d.ts +414 -0
- package/dist/node/connector.d.ts.map +1 -0
- package/dist/node/connector.js +706 -0
- package/dist/node/connector.js.map +1 -0
- package/dist/node/endpoint.d.ts +169 -0
- package/dist/node/endpoint.d.ts.map +1 -0
- package/dist/node/endpoint.js +568 -0
- package/dist/node/endpoint.js.map +1 -0
- package/dist/node/errors.d.ts +203 -0
- package/dist/node/errors.d.ts.map +1 -0
- package/dist/node/errors.js +436 -0
- package/dist/node/errors.js.map +1 -0
- package/dist/node/event-input.d.ts +56 -0
- package/dist/node/event-input.d.ts.map +1 -0
- package/dist/node/event-input.js +200 -0
- package/dist/node/event-input.js.map +1 -0
- package/dist/node/events.d.ts +260 -0
- package/dist/node/events.d.ts.map +1 -0
- package/dist/node/events.js +470 -0
- package/dist/node/events.js.map +1 -0
- package/dist/node/extensions.d.ts +117 -0
- package/dist/node/extensions.d.ts.map +1 -0
- package/dist/node/extensions.js +133 -0
- package/dist/node/extensions.js.map +1 -0
- package/dist/node/graph.d.ts +460 -0
- package/dist/node/graph.d.ts.map +1 -0
- package/dist/node/graph.js +904 -0
- package/dist/node/graph.js.map +1 -0
- package/dist/node/identity.d.ts +56 -0
- package/dist/node/identity.d.ts.map +1 -0
- package/dist/node/identity.js +54 -0
- package/dist/node/identity.js.map +1 -0
- package/dist/node/index.d.ts +31 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +31 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/native-package.d.ts +2 -0
- package/dist/node/native-package.d.ts.map +1 -0
- package/dist/node/native-package.js +36 -0
- package/dist/node/native-package.js.map +1 -0
- package/dist/node/native.d.ts +1262 -0
- package/dist/node/native.d.ts.map +1 -0
- package/dist/node/native.js +10 -0
- package/dist/node/native.js.map +1 -0
- package/dist/node/observations.d.ts +500 -0
- package/dist/node/observations.d.ts.map +1 -0
- package/dist/node/observations.js +563 -0
- package/dist/node/observations.js.map +1 -0
- package/dist/node/operator.d.ts +117 -0
- package/dist/node/operator.d.ts.map +1 -0
- package/dist/node/operator.js +398 -0
- package/dist/node/operator.js.map +1 -0
- package/dist/node/provider.d.ts +276 -0
- package/dist/node/provider.d.ts.map +1 -0
- package/dist/node/provider.js +1077 -0
- package/dist/node/provider.js.map +1 -0
- package/dist/node/recording.d.ts +78 -0
- package/dist/node/recording.d.ts.map +1 -0
- package/dist/node/recording.js +147 -0
- package/dist/node/recording.js.map +1 -0
- package/dist/node/relay.d.ts +105 -0
- package/dist/node/relay.d.ts.map +1 -0
- package/dist/node/relay.js +389 -0
- package/dist/node/relay.js.map +1 -0
- package/dist/node/session.d.ts +414 -0
- package/dist/node/session.d.ts.map +1 -0
- package/dist/node/session.js +1197 -0
- package/dist/node/session.js.map +1 -0
- package/dist/node/sidecar.d.ts +179 -0
- package/dist/node/sidecar.d.ts.map +1 -0
- package/dist/node/sidecar.js +441 -0
- package/dist/node/sidecar.js.map +1 -0
- package/dist/node/signals.d.ts +177 -0
- package/dist/node/signals.d.ts.map +1 -0
- package/dist/node/signals.js +338 -0
- package/dist/node/signals.js.map +1 -0
- package/dist/node/source.d.ts +105 -0
- package/dist/node/source.d.ts.map +1 -0
- package/dist/node/source.js +260 -0
- package/dist/node/source.js.map +1 -0
- package/dist/node/sources.d.ts +334 -0
- package/dist/node/sources.d.ts.map +1 -0
- package/dist/node/sources.js +605 -0
- package/dist/node/sources.js.map +1 -0
- package/dist/node/streams.d.ts +163 -0
- package/dist/node/streams.d.ts.map +1 -0
- package/dist/node/streams.js +362 -0
- package/dist/node/streams.js.map +1 -0
- package/dist/require-package.cjs +6 -0
- package/dist/require-package.d.cts +1 -0
- package/dist/voice/capabilities.d.ts +132 -0
- package/dist/voice/capabilities.d.ts.map +1 -0
- package/dist/voice/capabilities.js +198 -0
- package/dist/voice/capabilities.js.map +1 -0
- package/dist/voice/configuration.d.ts +129 -0
- package/dist/voice/configuration.d.ts.map +1 -0
- package/dist/voice/configuration.js +244 -0
- package/dist/voice/configuration.js.map +1 -0
- package/dist/voice/conversation.d.ts +220 -0
- package/dist/voice/conversation.d.ts.map +1 -0
- package/dist/voice/conversation.js +1383 -0
- package/dist/voice/conversation.js.map +1 -0
- package/dist/voice/duplex.d.ts +28 -0
- package/dist/voice/duplex.d.ts.map +1 -0
- package/dist/voice/duplex.js +15 -0
- package/dist/voice/duplex.js.map +1 -0
- package/dist/voice/errors.d.ts +44 -0
- package/dist/voice/errors.d.ts.map +1 -0
- package/dist/voice/errors.js +67 -0
- package/dist/voice/errors.js.map +1 -0
- package/dist/voice/events.d.ts +34 -0
- package/dist/voice/events.d.ts.map +1 -0
- package/dist/voice/events.js +43 -0
- package/dist/voice/events.js.map +1 -0
- package/dist/voice/index.d.ts +18 -0
- package/dist/voice/index.d.ts.map +1 -0
- package/dist/voice/index.js +18 -0
- package/dist/voice/index.js.map +1 -0
- package/dist/voice/response.d.ts +56 -0
- package/dist/voice/response.d.ts.map +1 -0
- package/dist/voice/response.js +67 -0
- package/dist/voice/response.js.map +1 -0
- package/dist/voice/speech-detection.d.ts +40 -0
- package/dist/voice/speech-detection.d.ts.map +1 -0
- package/dist/voice/speech-detection.js +39 -0
- package/dist/voice/speech-detection.js.map +1 -0
- package/dist/voice/synthesis.d.ts +47 -0
- package/dist/voice/synthesis.d.ts.map +1 -0
- package/dist/voice/synthesis.js +45 -0
- package/dist/voice/synthesis.js.map +1 -0
- package/dist/voice/transcription.d.ts +55 -0
- package/dist/voice/transcription.d.ts.map +1 -0
- package/dist/voice/transcription.js +71 -0
- package/dist/voice/transcription.js.map +1 -0
- package/dist/voice/turns.d.ts +94 -0
- package/dist/voice/turns.d.ts.map +1 -0
- package/dist/voice/turns.js +138 -0
- package/dist/voice/turns.js.map +1 -0
- package/dist/voice/validation.d.ts +17 -0
- package/dist/voice/validation.d.ts.map +1 -0
- package/dist/voice/validation.js +86 -0
- package/dist/voice/validation.js.map +1 -0
- package/dist/wrappers/browser.mjs +8 -0
- package/dist/wrappers/control.mjs +9 -0
- package/dist/wrappers/demo.mjs +15 -0
- package/dist/wrappers/node.mjs +242 -0
- package/dist/wrappers/root.mjs +5 -0
- package/dist/wrappers/voice.mjs +35 -0
- package/package.json +177 -4
- package/src/browser/index.ts +33 -0
- package/src/browser/latency-report.ts +44 -0
- package/src/browser/operation-signal.ts +44 -0
- package/src/browser/relay-publisher.ts +856 -0
- package/src/browser/relay-session.ts +1121 -0
- package/src/browser/signaling.ts +335 -0
- package/src/browser/types.ts +222 -0
- package/src/compatibility.ts +58 -0
- package/src/control/control-client.ts +1058 -0
- package/src/control/index.ts +33 -0
- package/src/control/invitation-locator.ts +6 -0
- package/src/control/session-owner.ts +115 -0
- package/src/control/types.ts +257 -0
- package/src/demo/audio-windows.ts +344 -0
- package/src/demo/faster-whisper.ts +499 -0
- package/src/demo/index.ts +33 -0
- package/src/demo/openai-realtime.ts +1050 -0
- package/src/demo/transcript.ts +90 -0
- package/src/demo/whisper-cli-model.ts +190 -0
- package/src/demo/window-signal.ts +55 -0
- package/src/errors.ts +14 -0
- package/src/index.ts +18 -0
- package/src/node/aec.ts +177 -0
- package/src/node/application-audio.ts +422 -0
- package/src/node/capture.ts +336 -0
- package/src/node/connector.ts +633 -0
- package/src/node/endpoint.ts +835 -0
- package/src/node/errors.ts +524 -0
- package/src/node/event-input.ts +286 -0
- package/src/node/events.ts +834 -0
- package/src/node/extensions.ts +260 -0
- package/src/node/graph.ts +1295 -0
- package/src/node/identity.ts +110 -0
- package/src/node/index.ts +501 -0
- package/src/node/native-package.ts +47 -0
- package/src/node/native.ts +1534 -0
- package/src/node/observations.ts +1173 -0
- package/src/node/operator.ts +622 -0
- package/src/node/provider.ts +1537 -0
- package/src/node/recording.ts +295 -0
- package/src/node/relay.ts +597 -0
- package/src/node/session.ts +1937 -0
- package/src/node/sidecar.ts +598 -0
- package/src/node/signals.ts +590 -0
- package/src/node/source.ts +433 -0
- package/src/node/sources.ts +965 -0
- package/src/node/streams.ts +543 -0
- package/src/require-package.cjs +6 -0
- package/src/require-package.d.cts +1 -0
- package/src/voice/capabilities.ts +309 -0
- package/src/voice/configuration.ts +375 -0
- package/src/voice/conversation.ts +2227 -0
- package/src/voice/duplex.ts +55 -0
- package/src/voice/errors.ts +99 -0
- package/src/voice/events.ts +77 -0
- package/src/voice/index.ts +122 -0
- package/src/voice/response.ts +123 -0
- package/src/voice/speech-detection.ts +88 -0
- package/src/voice/synthesis.ts +109 -0
- package/src/voice/transcription.ts +133 -0
- package/src/voice/turns.ts +224 -0
- package/src/voice/validation.ts +131 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PocketStation contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,620 @@
|
|
|
1
|
-
#
|
|
1
|
+
# PocketStation for JavaScript
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The Node API is designed to capture audio from a desktop application, the whole
|
|
4
|
+
computer, or a microphone on macOS, Windows, and Linux. Each source stays
|
|
5
|
+
separate and every frame includes its source, stream, timing, and sequence
|
|
6
|
+
information. The current platform evidence is listed below; it does not yet
|
|
7
|
+
cover all three operating systems.
|
|
8
|
+
|
|
9
|
+
The package uses the PocketStation Rust engine for capture, routing, and
|
|
10
|
+
shutdown. JavaScript receives audio after it leaves the realtime capture code,
|
|
11
|
+
so model calls and application work do not run on an audio callback.
|
|
12
|
+
|
|
13
|
+
> The Node SDK remains under active development. Version 0.1.5 is published;
|
|
14
|
+
> version 0.1.6 is unreleased and uses PocketStation Core 1.1.15.
|
|
15
|
+
> Existing macOS evidence covers selected-application capture and installed
|
|
16
|
+
> same-host Relay receipt in
|
|
17
|
+
> Chromium, Firefox, and WebKit. Windows and Linux packages, WAN/TURN behavior,
|
|
18
|
+
> and the remaining Rust/Python features still require their own proof.
|
|
19
|
+
|
|
20
|
+
Version 0.1.6 adds explicit application process sets on macOS 26 and newer.
|
|
21
|
+
Discover immutable process observations, select 1–32 original process instances,
|
|
22
|
+
and route their shared `SourceOutput` through the existing Session API. Start
|
|
23
|
+
times retain their full 64-bit range as `bigint`. Replacements are never followed
|
|
24
|
+
automatically; changed membership requires a new Session. See
|
|
25
|
+
[exact application process sets](docs/concepts/sources-and-permissions.md#exact-application-process-sets)
|
|
26
|
+
for selection, platform and lifecycle limits. These additions do not extend the
|
|
27
|
+
installed-package or physical-capture claims above to a new release.
|
|
28
|
+
|
|
29
|
+
## Package installation and module modes
|
|
30
|
+
|
|
31
|
+
The root `pocketstation` archive contains JavaScript and declarations. Its exact
|
|
32
|
+
versioned optional native dependency supplies the Node-API addon for macOS or
|
|
33
|
+
Windows on arm64/x64, or glibc Linux on arm64/x64. These six package definitions
|
|
34
|
+
are distribution targets; each release must separately qualify its advertised
|
|
35
|
+
binaries. Musl Linux is unsupported and fails with `package.unsupported_target`.
|
|
36
|
+
|
|
37
|
+
Install with optional dependencies enabled. `package.native_missing` names the
|
|
38
|
+
missing platform package and an explicit install command; a mismatched native
|
|
39
|
+
version fails with `package.version_mismatch`. There is no install script,
|
|
40
|
+
checkout-relative binary fallback, or download at runtime.
|
|
41
|
+
|
|
42
|
+
All six public entry points support Node ESM and CommonJS. In one Node process,
|
|
43
|
+
`import` and `require` share classes, errors and singleton values. The root,
|
|
44
|
+
browser, control and voice ESM builds remain available to browser tooling;
|
|
45
|
+
`pocketstation/node` and `pocketstation/demo` require Node. Browser code does not
|
|
46
|
+
load a native addon. Optional example transport `ws` remains separately installed.
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
## Capture an application
|
|
50
|
+
|
|
51
|
+
Choose the running application by its exact display name or application ID:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { capture } from "pocketstation/node";
|
|
55
|
+
|
|
56
|
+
const audio = await capture("Spotify");
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Read source-aware PCM frames. Leaving the loop finishes this concise Capture:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
for await (const frame of audio) {
|
|
63
|
+
console.log(frame.sourceId, frame.timestampStartNs, frame.samples);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`frame.samples` is interleaved `Float32Array` PCM. IDs, sequence numbers, and
|
|
68
|
+
nanosecond timestamps are `bigint`, so JavaScript does not round native 64-bit
|
|
69
|
+
values.
|
|
70
|
+
|
|
71
|
+
## Add a microphone
|
|
72
|
+
|
|
73
|
+
PocketStation never opens a microphone unless your code asks for one:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
const audio = await capture("Zoom", { microphone: true });
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Application and microphone frames share the iterator but keep different
|
|
80
|
+
`sourceId` and `stemId` values. A slow reader can therefore be diagnosed without
|
|
81
|
+
guessing which source produced a frame.
|
|
82
|
+
|
|
83
|
+
The concise object exposes `audio.session`, `audio.application`, and the optional
|
|
84
|
+
`audio.microphone` Stem. Advanced routing therefore extends the same Session;
|
|
85
|
+
there is no smaller second engine behind `capture()`.
|
|
86
|
+
|
|
87
|
+
To capture all desktop output instead of one application, declare it explicitly:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { Session, Source } from "pocketstation/node";
|
|
91
|
+
|
|
92
|
+
const session = new Session();
|
|
93
|
+
const desktop = session.capture(Source.systemAudio());
|
|
94
|
+
desktop.send(session.audio());
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Own Session lifecycle from JavaScript
|
|
98
|
+
|
|
99
|
+
Use the separate, browser-safe control entry point when trusted application
|
|
100
|
+
code owns Session creation and receiver authorization. It uses web-standard
|
|
101
|
+
`fetch`; importing it does not load the native addon or the browser WebRTC
|
|
102
|
+
client:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { ControlClient } from "pocketstation/control";
|
|
106
|
+
|
|
107
|
+
using control = new ControlClient("https://control.example");
|
|
108
|
+
const credentials = await control.createSession({
|
|
109
|
+
requiredBuses: ["application", "microphone"],
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const snapshot = await control.session(
|
|
113
|
+
credentials.sessionId,
|
|
114
|
+
credentials.sourceToken,
|
|
115
|
+
);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Every operation has a finite deadline and accepts an `AbortSignal`. Responses
|
|
119
|
+
are size-bounded and strictly decoded. `SecretToken` redacts normal string and
|
|
120
|
+
JSON conversion; `exposeSecret()` is the deliberate transport boundary.
|
|
121
|
+
Creating subscriber credentials and invitations requires the source-owner
|
|
122
|
+
token, so those operations belong in trusted application or server code—not an
|
|
123
|
+
untrusted phone or public browser bundle.
|
|
124
|
+
|
|
125
|
+
See [Control Session lifecycle](docs/reference/control-plane.md) for the full
|
|
126
|
+
create, inspect, subscribe, invite, delete, cancellation, and error contract.
|
|
127
|
+
|
|
128
|
+
## Define provider-neutral voice components
|
|
129
|
+
|
|
130
|
+
Import immutable voice values and provider lifecycle interfaces without loading
|
|
131
|
+
the Node native addon or browser WebRTC code:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
import {
|
|
135
|
+
ConversationConfig,
|
|
136
|
+
ResponseCapabilities,
|
|
137
|
+
TranscriptUpdate,
|
|
138
|
+
TranscriptionCapabilities,
|
|
139
|
+
VoiceCapabilities,
|
|
140
|
+
} from "pocketstation/voice";
|
|
141
|
+
|
|
142
|
+
const capabilities = new VoiceCapabilities({
|
|
143
|
+
transcription: new TranscriptionCapabilities({ streaming: true }),
|
|
144
|
+
response: new ResponseCapabilities({
|
|
145
|
+
streaming: true,
|
|
146
|
+
cancellation: true,
|
|
147
|
+
}),
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const config = new ConversationConfig();
|
|
151
|
+
const finalTranscript = new TranscriptUpdate({
|
|
152
|
+
utteranceId: "speech-1",
|
|
153
|
+
revision: 1,
|
|
154
|
+
text: "ship the answer",
|
|
155
|
+
stablePrefix: "ship the answer",
|
|
156
|
+
final: true,
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`pocketstation/voice` covers the provider-neutral capability, configuration,
|
|
161
|
+
transcript, turn, response, synthesis, speech-activity, duplex, event, failure,
|
|
162
|
+
and bounded conversation orchestration available in Python. Every retained
|
|
163
|
+
collection is copied and frozen, and every count or deadline has a finite
|
|
164
|
+
limit. Providers receive `AbortSignal` cancellation, while selected generated
|
|
165
|
+
output is cancelled without stopping capture or the owning Session.
|
|
166
|
+
|
|
167
|
+
After declaring a transcript `BusSubscription` and an `AudioInput`, compose the
|
|
168
|
+
workflow on the same Session:
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
const conversation = session.conversation({
|
|
172
|
+
transcripts,
|
|
173
|
+
output: assistantAudio,
|
|
174
|
+
respond: async (update, context, signal) => answer(update, context, signal),
|
|
175
|
+
synthesize: (chunk, turn, signal) => speech(chunk, turn, signal),
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
await using running = await session.start();
|
|
179
|
+
const outcome = await conversation.run(running);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Separate STT/response/synthesis/VAD providers and one stateful duplex provider
|
|
183
|
+
use the same finite lifecycle through `Conversation.fromComponents()` and
|
|
184
|
+
`Conversation.fromDuplex()`. The SDK does not bundle a model or provider.
|
|
185
|
+
|
|
186
|
+
## Record or process the same Stem
|
|
187
|
+
|
|
188
|
+
Capture does not need to be repeated for each destination. The same Stem can be
|
|
189
|
+
read by Node and recorded as a separate WAV file:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
const session = new Session({ recordingRoot: "./recordings" });
|
|
193
|
+
const application = session.capture(Source.application("Spotify"));
|
|
194
|
+
|
|
195
|
+
application.send(session.audio());
|
|
196
|
+
application.record("application");
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Operators and custom Endpoints use open identifiers and named ports. They may
|
|
200
|
+
be implemented in JavaScript, a trusted native extension, or a managed process.
|
|
201
|
+
Core validates the complete Session before capture starts and reports the exact
|
|
202
|
+
Operator, node, or port when compilation fails. The JavaScript package does not
|
|
203
|
+
compile a second execution plan.
|
|
204
|
+
|
|
205
|
+
Read [Route, process, and record media](docs/guides/compose-a-session.md) for
|
|
206
|
+
named ports, generated audio, compiler diagnostics, and delivery settings.
|
|
207
|
+
|
|
208
|
+
## Publish independent Stems to Relay
|
|
209
|
+
|
|
210
|
+
Use `RelaySession` to own the remote Session and its renewable owner credential.
|
|
211
|
+
The service URL can point to standalone Relay or its managed control-plane
|
|
212
|
+
mount; both expose the same Session API. One publisher carries the named
|
|
213
|
+
AudioBuses while Core keeps application and microphone Stems independent:
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
import { RelaySession, Session, Source } from "pocketstation/node";
|
|
217
|
+
|
|
218
|
+
await using remote = await RelaySession.create({
|
|
219
|
+
controlPlaneUrl: "https://service.example",
|
|
220
|
+
requiredBuses: ["application", "microphone"],
|
|
221
|
+
});
|
|
222
|
+
const session = new Session();
|
|
223
|
+
const application = session.capture(Source.application("Zoom"));
|
|
224
|
+
const microphone = session.capture(Source.microphone());
|
|
225
|
+
const publisher = remote.publisher(session);
|
|
226
|
+
application.publish(publisher, "application");
|
|
227
|
+
microphone.publish(publisher, "microphone");
|
|
228
|
+
|
|
229
|
+
await using live = await session.start();
|
|
230
|
+
await remote.waitForPublisher();
|
|
231
|
+
const invitation = await remote.createReceiverInvitation({ busId: "application" });
|
|
232
|
+
// Deliberate credential disclosure: deliver only to the intended receiver.
|
|
233
|
+
const receiverUrl = invitation.exposeShareUrl();
|
|
234
|
+
// Keep this scope open while your application uses the live Session.
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Create a separate invitation for the microphone bus when needed. Readable words
|
|
238
|
+
navigate to the Session; the URL's fragment carries the existing join credential.
|
|
239
|
+
Normal invitation formatting redacts that credential. `session.relay()` remains
|
|
240
|
+
available when the caller already owns the connection and credential lifecycle.
|
|
241
|
+
|
|
242
|
+
The Node addon uses the released Rust Relay Connector for Opus, RTP, WebRTC,
|
|
243
|
+
and signaling. JavaScript does not encode audio or maintain another media
|
|
244
|
+
queue. Relay startup completes before `session.start()` returns, uses a finite
|
|
245
|
+
deadline, and closes with the Session.
|
|
246
|
+
|
|
247
|
+
`transport: 'webrtc'` is the default on both `RelaySession.create()` and
|
|
248
|
+
`session.relay()`. Ordinary native builds use the released
|
|
249
|
+
`pocketstation-relay 0.1.6` Connector and include WebSocket publication by default.
|
|
250
|
+
Check `relayWebsocketAvailable()` from `pocketstation/node` before selecting
|
|
251
|
+
`transport: 'websocket'`. Older addons and builds without the `relay-websocket`
|
|
252
|
+
feature report `false`; selection then fails with `relay.transport_unavailable`
|
|
253
|
+
before creating a remote Session or declaring a publisher. It never falls back
|
|
254
|
+
to another transport automatically.
|
|
255
|
+
|
|
256
|
+
Static WebSocket publication uses the same Connector. It ignores unused
|
|
257
|
+
advertised ICE metadata after bounded response validation; WebRTC still rejects
|
|
258
|
+
TURN and credential-bearing ICE configuration. The
|
|
259
|
+
[integration guide](docs/guides/integrations.md#select-a-static-relay-transport)
|
|
260
|
+
describes this capability boundary. Owner credential renewal does not replace a
|
|
261
|
+
credential already attached to a native publisher; automatic media renewal and
|
|
262
|
+
reconnect are separate capabilities.
|
|
263
|
+
Native WebSocket proxy settings do not configure JavaScript management HTTP;
|
|
264
|
+
an appropriate `ControlClient` fetch implementation remains application-owned.
|
|
265
|
+
|
|
266
|
+
The microphone remains opt-in. A selected application can be the only
|
|
267
|
+
published source when that is all the receiver needs. See the
|
|
268
|
+
[runnable Relay example](examples/publish-to-relay.ts) for configuration.
|
|
269
|
+
|
|
270
|
+
## Publish caller-owned browser audio
|
|
271
|
+
|
|
272
|
+
The browser-only entry can publish one live `MediaStream` audio track to one
|
|
273
|
+
capability-scoped `AudioBus`. Your application obtains microphone permission
|
|
274
|
+
and retains track ownership:
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import { RelayPublisher } from "pocketstation/browser";
|
|
278
|
+
|
|
279
|
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
280
|
+
const publisher = new RelayPublisher({
|
|
281
|
+
signalUrl,
|
|
282
|
+
sessionId,
|
|
283
|
+
busId: "user-microphone",
|
|
284
|
+
publisherToken,
|
|
285
|
+
iceServers,
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
await publisher.publish(stream);
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
`publish()` resolves only after browser WebRTC statistics contain an outbound
|
|
292
|
+
audio packet. This proves media delivery started; it does not prove speech or
|
|
293
|
+
non-silence. `disconnect()` closes PocketStation resources but deliberately
|
|
294
|
+
does not stop the caller-owned track. Mint `publisherToken` with
|
|
295
|
+
`ControlClient.issuePublisherCredentials()`; never hand the Session-owner token
|
|
296
|
+
to browser media code. Keep bearer credentials out of URLs and browser storage.
|
|
297
|
+
See [Publish and receive Relay audio in a browser](docs/reference/browser-relay.md).
|
|
298
|
+
|
|
299
|
+
## Send audio to application code
|
|
300
|
+
|
|
301
|
+
Use a Connector for a socket, encoder, provider client, or another destination
|
|
302
|
+
that consumes source-aware PCM:
|
|
303
|
+
|
|
304
|
+
```ts
|
|
305
|
+
import { Capture, connector } from "pocketstation/node";
|
|
306
|
+
|
|
307
|
+
const destination = connector((frame) => {
|
|
308
|
+
console.log(frame.sourceId, frame.sequenceNumber, frame.samples);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const declaration = new Capture({ application: "Zoom", streamAudio: false });
|
|
312
|
+
declaration.application.sendTo(destination);
|
|
313
|
+
await using live = await declaration.start();
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
The class form adds `start()`, `send()`, and `stop()` for destinations that own
|
|
317
|
+
resources. Sending application and microphone Stems to the same Connector uses
|
|
318
|
+
one instance and preserves both Source identities.
|
|
319
|
+
|
|
320
|
+
Read [Add JavaScript Sources, Operators, and destinations](docs/guides/provider-authoring.md)
|
|
321
|
+
for the class form, typed Sources, Operators, and multi-input Endpoints.
|
|
322
|
+
|
|
323
|
+
## Read an Operator result
|
|
324
|
+
|
|
325
|
+
Subscribe to a named output before starting the Session, then read it from the
|
|
326
|
+
running Session. Operators can come from application code, an installed
|
|
327
|
+
provider package, a native extension, or a managed process:
|
|
328
|
+
|
|
329
|
+
```ts
|
|
330
|
+
import {
|
|
331
|
+
PortSpec,
|
|
332
|
+
Session,
|
|
333
|
+
SignalSpec,
|
|
334
|
+
Source,
|
|
335
|
+
defineOperator,
|
|
336
|
+
} from "pocketstation/node";
|
|
337
|
+
|
|
338
|
+
const audio = SignalSpec.audio();
|
|
339
|
+
const text = SignalSpec.text();
|
|
340
|
+
const levelMeter = defineOperator({
|
|
341
|
+
id: "com.example.operator.level-meter.v1",
|
|
342
|
+
inputs: [PortSpec.input("audio", audio)],
|
|
343
|
+
outputs: [PortSpec.output("level", text)],
|
|
344
|
+
create: () => ({
|
|
345
|
+
process(value) {
|
|
346
|
+
if (value.payload.kind !== "audio") return [];
|
|
347
|
+
const peak = value.payload.samples.reduce(
|
|
348
|
+
(current, sample) => Math.max(current, Math.abs(sample)),
|
|
349
|
+
0,
|
|
350
|
+
);
|
|
351
|
+
return [{ output: "level", data: peak.toFixed(3) }];
|
|
352
|
+
},
|
|
353
|
+
}),
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
const session = new Session();
|
|
357
|
+
const application = session.capture(Source.application("Zoom"));
|
|
358
|
+
const meter = session.operator(levelMeter);
|
|
359
|
+
application.connect(meter.input("audio"));
|
|
360
|
+
|
|
361
|
+
const subscription = session.subscribe(meter.output("level"), { signal: text });
|
|
362
|
+
|
|
363
|
+
await using running = await session.start();
|
|
364
|
+
for await (const value of running.signals(subscription)) {
|
|
365
|
+
if (value.payload.kind === "text") {
|
|
366
|
+
console.log(value.payload.text);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
Each value includes the source and stream identity retained from its input.
|
|
372
|
+
Derived values also identify the Operator that produced them. A
|
|
373
|
+
subscription has one reader, can be closed without stopping the Session, and
|
|
374
|
+
reports its current queue depth and delivery totals through `metrics()`.
|
|
375
|
+
|
|
376
|
+
Read [Consume Operator output](docs/guides/signal-streams.md) for timeout,
|
|
377
|
+
end-of-stream, cancellation, queue, and payload behavior.
|
|
378
|
+
|
|
379
|
+
## Feed audio your application already has
|
|
380
|
+
|
|
381
|
+
Use an `AudioInput` when a provider, network connection, decoder, or voice
|
|
382
|
+
model already gives your application PCM:
|
|
383
|
+
|
|
384
|
+
```ts
|
|
385
|
+
import { Session } from "pocketstation/node";
|
|
386
|
+
|
|
387
|
+
const session = new Session({ frameDurationMs: 10 });
|
|
388
|
+
const input = session.audioInput("agent audio");
|
|
389
|
+
input.output.send(session.audio());
|
|
390
|
+
|
|
391
|
+
await session.run(async () => {
|
|
392
|
+
await input.write(samples);
|
|
393
|
+
input.close();
|
|
394
|
+
});
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
`samples` is normally a `Float32Array` containing one complete interleaved
|
|
398
|
+
frame. A `Buffer` is also accepted when it contains little-endian IEEE 754
|
|
399
|
+
float32 values. PocketStation copies an accepted frame before the write
|
|
400
|
+
returns, so the producer can reuse its array immediately.
|
|
401
|
+
|
|
402
|
+
The default input holds at most eight frames waiting for Core. `tryWrite()`
|
|
403
|
+
reports `AudioInputFullError` immediately. `write()` waits up to one second and
|
|
404
|
+
accepts an `AbortSignal`; timing out or aborting that wait does not close the
|
|
405
|
+
input or stop the Session.
|
|
406
|
+
|
|
407
|
+
Read [Feed application-owned PCM](docs/guides/application-audio.md) for format,
|
|
408
|
+
capacity, discontinuity, selected-output cancellation, and shutdown behavior.
|
|
409
|
+
|
|
410
|
+
## Add compiled or process-isolated implementations
|
|
411
|
+
|
|
412
|
+
Load a trusted native extension when a Source, Operator, or Endpoint is shipped
|
|
413
|
+
as a PocketStation ABI library:
|
|
414
|
+
|
|
415
|
+
```ts
|
|
416
|
+
const session = new Session();
|
|
417
|
+
await session.loadNativeExtensionLibrary("/opt/acme/libacme_audio.dylib");
|
|
418
|
+
|
|
419
|
+
const source = session.source("com.acme.source.audio.v1");
|
|
420
|
+
source.output("audio").send(session.audio());
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
Use a `SidecarProcess` when an implementation runs in another language or
|
|
424
|
+
needs process isolation. Core starts it without a shell, completes the PKSS
|
|
425
|
+
handshake, applies explicit message sizes and deadlines, and reaps it during
|
|
426
|
+
Session shutdown.
|
|
427
|
+
|
|
428
|
+
Read [Run compiled extensions and managed processes](docs/guides/extensions-and-sidecars.md)
|
|
429
|
+
for security, configuration, queue saturation, finite reads, process state,
|
|
430
|
+
and cleanup.
|
|
431
|
+
|
|
432
|
+
## Discover sources before capture
|
|
433
|
+
|
|
434
|
+
Discovery lets an application present the real sources reported by the host
|
|
435
|
+
instead of asking a user to type a name:
|
|
436
|
+
|
|
437
|
+
```ts
|
|
438
|
+
import { Source, discoverSources } from "pocketstation/node";
|
|
439
|
+
|
|
440
|
+
const applications = await discoverSources({
|
|
441
|
+
type: "kind",
|
|
442
|
+
kind: "application",
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
const selected = Source.fromDiscovered(applications[0]);
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
Each result includes its display name, native application or device identity,
|
|
449
|
+
current state, audio format, and how long its selector may be reused. A
|
|
450
|
+
discovered output device is informational; application, input-device, and
|
|
451
|
+
system-mix results can be turned into Session Sources.
|
|
452
|
+
|
|
453
|
+
Read microphone permission without prompting:
|
|
454
|
+
|
|
455
|
+
```ts
|
|
456
|
+
import { microphonePermissionObservation } from "pocketstation/node";
|
|
457
|
+
|
|
458
|
+
const permission = await microphonePermissionObservation();
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
`not-observable` is kept distinct from `allowed` and `denied`. PocketStation
|
|
462
|
+
does not infer permission from a generic capture failure. The host application
|
|
463
|
+
remains responsible for explaining and requesting operating-system permission.
|
|
464
|
+
|
|
465
|
+
## Observe source failure
|
|
466
|
+
|
|
467
|
+
The Session reports lifecycle and failure events separately from audio:
|
|
468
|
+
|
|
469
|
+
```ts
|
|
470
|
+
for await (const event of running.events) {
|
|
471
|
+
if (event.type === "source-failure") {
|
|
472
|
+
console.error(event.failure.stableId, event.failure.operation);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
When an application or device disappears, the event keeps its Source and Stem
|
|
478
|
+
identity and states whether rediscovery and a new Session are required. It does
|
|
479
|
+
not silently switch to another application or microphone.
|
|
480
|
+
|
|
481
|
+
Inspect current delivery and timing without consuming the audio stream:
|
|
482
|
+
|
|
483
|
+
```ts
|
|
484
|
+
const metrics = await running.metrics();
|
|
485
|
+
|
|
486
|
+
for (const route of metrics.routes) {
|
|
487
|
+
console.log(route.routeId, route.delivery.framesDroppedTotal);
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
All counters, identities, and nanosecond values are `bigint`. The final result
|
|
492
|
+
retains the last metrics, the complete terminal event, and recording or trace
|
|
493
|
+
results when those features were enabled.
|
|
494
|
+
|
|
495
|
+
Read [Understand a running Session](docs/guides/observe-a-session.md) for queue
|
|
496
|
+
depth, latency percentiles, retained failures, multistem results, and trace
|
|
497
|
+
validation.
|
|
498
|
+
|
|
499
|
+
## Stop or cancel
|
|
500
|
+
|
|
501
|
+
`stop()` finishes accepted work and returns the Session outcome. `cancel()` asks
|
|
502
|
+
the engine to stop without draining pending work. Both operations are
|
|
503
|
+
idempotent through the JavaScript `RunningSession` object.
|
|
504
|
+
|
|
505
|
+
```ts
|
|
506
|
+
const outcome = await running.stop();
|
|
507
|
+
|
|
508
|
+
if (!outcome.success) {
|
|
509
|
+
console.error(outcome);
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
Enable a checksummed lifecycle trace when a reproducible shutdown record is
|
|
514
|
+
needed:
|
|
515
|
+
|
|
516
|
+
```ts
|
|
517
|
+
import { Session, SessionTrace } from "pocketstation/node";
|
|
518
|
+
|
|
519
|
+
const session = new Session({ trace: { path: "./meeting.pkstrace" } });
|
|
520
|
+
// Declare Sources and destinations, then start and stop the Session.
|
|
521
|
+
|
|
522
|
+
const trace = SessionTrace.read("./meeting.pkstrace");
|
|
523
|
+
console.log(trace.validate());
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
Breaking an audio loop releases that reader; it does not stop the Session.
|
|
527
|
+
Pass an `AbortSignal` when the reader needs its own cancellation:
|
|
528
|
+
|
|
529
|
+
```ts
|
|
530
|
+
for await (const frame of running.audio.frames({ signal })) {
|
|
531
|
+
consume(frame);
|
|
532
|
+
}
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
Direct reads distinguish a wait that expired from a stream that ended:
|
|
536
|
+
|
|
537
|
+
```ts
|
|
538
|
+
import { END_OF_STREAM } from "pocketstation/node";
|
|
539
|
+
|
|
540
|
+
const value = await running.audio.read({ timeoutMs: 100 });
|
|
541
|
+
|
|
542
|
+
if (value === undefined) {
|
|
543
|
+
// No frame arrived within 100 ms.
|
|
544
|
+
} else if (value === END_OF_STREAM) {
|
|
545
|
+
// The Session ended and no received frames remain.
|
|
546
|
+
}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
## Current API status
|
|
550
|
+
|
|
551
|
+
Read [platform support](docs/operations/platform-support.md) for supported
|
|
552
|
+
environments and limitations, and [Session lifecycle](docs/concepts/session-lifecycle.md)
|
|
553
|
+
for native ownership, cancellation and shutdown.
|
|
554
|
+
|
|
555
|
+
Browser Relay receiving is exposed from `pocketstation/browser`. It stays
|
|
556
|
+
separate so browser builds never load a native addon:
|
|
557
|
+
|
|
558
|
+
```ts
|
|
559
|
+
import { RelayReceiver } from "pocketstation/browser";
|
|
560
|
+
|
|
561
|
+
const receiver = new RelayReceiver({ locator: joinCode }, { controlPlaneUrl: controlUrl });
|
|
562
|
+
audio.srcObject = await receiver.connect();
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
Read [Receive Relay audio in a browser](docs/reference/browser-relay.md) for
|
|
566
|
+
direct subscriber access, lifecycle handling, receiver observations, and the
|
|
567
|
+
current proof level.
|
|
568
|
+
|
|
569
|
+
## Develop from source
|
|
570
|
+
|
|
571
|
+
Node 20.17 or newer and the Rust toolchain are required while the npm package is
|
|
572
|
+
still in development.
|
|
573
|
+
|
|
574
|
+
```bash
|
|
575
|
+
npm install
|
|
576
|
+
npm run typecheck
|
|
577
|
+
npm test
|
|
578
|
+
npm run native:check
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
For source development, `npm run build:native` builds and stages the local
|
|
582
|
+
platform package under `npm/` and installs a copy in this checkout's
|
|
583
|
+
`node_modules`. `npm run build:typescript` builds both module forms without
|
|
584
|
+
loading native code. Packed-consumer gates install the root and real local
|
|
585
|
+
native tarballs into a separate temporary project.
|
|
586
|
+
|
|
587
|
+
After the build, run the application-capture example and enter the name of a
|
|
588
|
+
running application when prompted:
|
|
589
|
+
|
|
590
|
+
```bash
|
|
591
|
+
npm run example:capture
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
Add `-- --microphone` only when you also want the default microphone.
|
|
595
|
+
|
|
596
|
+
The repository uses the released `pocketstation` Rust crate in normal builds.
|
|
597
|
+
Local source overrides are used only for an explicitly recorded Core
|
|
598
|
+
qualification and are removed before packaging.
|
|
599
|
+
|
|
600
|
+
## License
|
|
601
|
+
|
|
602
|
+
MIT
|
|
603
|
+
|
|
604
|
+
Readable Relay names may use short natural words such as `owl-sun`, `rice-river`,
|
|
605
|
+
`silly-mountain` or `lemon-corpus`. They are navigation, not credentials: pass
|
|
606
|
+
the complete generated share URL. Clients accept the retained legacy compound
|
|
607
|
+
syntax without duplicating Relay's vocabulary or exposing a grammar prefix.
|
|
608
|
+
|
|
609
|
+
Readable receiver names follow Relay's configured allocation policy by default.
|
|
610
|
+
Pass integer `wordCount: 2` through `wordCount: 15` to `createInvitation` or
|
|
611
|
+
`createReceiverInvitation` only when a fixed length is needed. Deprecated
|
|
612
|
+
`visibility` still selects formatting; it cannot be combined with `wordCount`
|
|
613
|
+
and never changes authorization. Names do not carry authority: both formats
|
|
614
|
+
require the same opaque join credential, and links remain redacted by default.
|
|
615
|
+
|
|
616
|
+
Invitation and preview results expose the actual `wordCount`. Explicit response
|
|
617
|
+
counts must match the name; old responses without a count remain accepted only
|
|
618
|
+
for their original two/three-word formats. All readable locators have at most
|
|
619
|
+
134 ASCII bytes, 2–15 words and 3–24 letters per word (the latter preserves old
|
|
620
|
+
compound names). Vocabulary and phrase generation remain owned by Relay.
|