@telnyx/voice-agent-tester 0.2.0

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.
@@ -0,0 +1,4 @@
1
+ # Code owners for voice-agent-tester
2
+ # See: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
3
+
4
+ * @lucasassisrosa
@@ -0,0 +1,29 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Use Node.js 20.x
18
+ uses: actions/setup-node@v4
19
+ with:
20
+ node-version: "20"
21
+ cache: "npm"
22
+
23
+ - name: Install dependencies
24
+ run: npm ci
25
+
26
+ - name: Run tests
27
+ run: npm test
28
+ env:
29
+ CI: true
@@ -0,0 +1,72 @@
1
+ name: Draft release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ ref:
7
+ description: "Git ref (branch or tag) to draft from"
8
+ required: false
9
+ default: "main"
10
+ prerelease:
11
+ description: "Pre-release identifier"
12
+ required: false
13
+ default: "none"
14
+ type: choice
15
+ options:
16
+ - none
17
+ - alpha
18
+ - beta
19
+ - rc
20
+ increment:
21
+ description: "Version bump (only if prerelease is 'none')"
22
+ required: false
23
+ default: "patch"
24
+ type: choice
25
+ options:
26
+ - patch
27
+ - minor
28
+ - major
29
+
30
+ jobs:
31
+ draft:
32
+ name: "@telnyx/voice-agent-tester Draft release"
33
+ runs-on: ubuntu-latest
34
+
35
+ env:
36
+ TARGET_REF: ${{ github.event.inputs.ref || 'main' }}
37
+ PRERELEASE_ARGS: ${{ github.event.inputs.prerelease && github.event.inputs.prerelease != 'none' && format(' --preRelease={0} --github.preRelease', github.event.inputs.prerelease) || '' }}
38
+ INCREMENT_ARG: ${{ github.event.inputs.prerelease && github.event.inputs.prerelease != 'none' && ' --increment=prerelease' || github.event.inputs.increment && format(' --increment={0}', github.event.inputs.increment) || '' }}
39
+
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+ with:
43
+ ref: ${{ env.TARGET_REF }}
44
+ fetch-depth: 0
45
+ token: ${{ secrets.GITHUB_TOKEN }}
46
+
47
+ - name: Setup Git user
48
+ run: |
49
+ git config user.name TelnyxIntegrations
50
+ git config user.email integrations@telnyx.com
51
+
52
+ - name: Use Node.js 20.x
53
+ uses: actions/setup-node@v4
54
+ with:
55
+ node-version: "20"
56
+ cache: "npm"
57
+ registry-url: https://registry.npmjs.org/
58
+
59
+ - name: Install dependencies
60
+ run: npm ci
61
+
62
+ - name: Run tests
63
+ run: npm test
64
+ env:
65
+ CI: true
66
+
67
+ - name: Create draft release
68
+ run: |
69
+ npx release-it --ci --github.draft --no-npm.publish${{ env.INCREMENT_ARG }}${{ env.PRERELEASE_ARGS }}
70
+ env:
71
+ NPM_TOKEN: ${{ secrets.NPM_CI_TOKEN }}
72
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,39 @@
1
+ name: Publish release
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ if: github.event.release.prerelease == false
10
+ name: "@telnyx/voice-agent-tester Publish release"
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ with:
16
+ ref: "main"
17
+ fetch-depth: 0
18
+ token: ${{ secrets.GITHUB_TOKEN }}
19
+
20
+ - name: Setup Git user
21
+ run: |
22
+ git config user.name TelnyxIntegrations
23
+ git config user.email integrations@telnyx.com
24
+
25
+ - name: Use Node.js 20.x
26
+ uses: actions/setup-node@v4
27
+ with:
28
+ node-version: "20"
29
+ cache: "npm"
30
+ registry-url: https://registry.npmjs.org/
31
+
32
+ - name: Install dependencies
33
+ run: npm ci
34
+
35
+ - name: Publish package
36
+ run: npm publish --access public
37
+ env:
38
+ CI: true
39
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_CI_TOKEN }}
@@ -0,0 +1,31 @@
1
+ {
2
+ "git": {
3
+ "commitMessage": "chore: release v${version}",
4
+ "tagAnnotation": "Release v${version}",
5
+ "tagName": "v${version}"
6
+ },
7
+ "github": {
8
+ "release": true,
9
+ "releaseName": "v${version}"
10
+ },
11
+ "npm": {
12
+ "publish": false
13
+ },
14
+ "plugins": {
15
+ "@release-it/conventional-changelog": {
16
+ "preset": {
17
+ "name": "conventionalcommits",
18
+ "types": [
19
+ { "type": "feat", "section": "Features" },
20
+ { "type": "fix", "section": "Bug Fixes" },
21
+ { "type": "perf", "section": "Performance Improvements" },
22
+ { "type": "docs", "section": "Documentation" },
23
+ { "type": "refactor", "section": "Code Refactoring" },
24
+ { "type": "test", "section": "Tests" },
25
+ { "type": "chore", "section": "Chores" }
26
+ ]
27
+ },
28
+ "infile": "CHANGELOG.md"
29
+ }
30
+ }
31
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,30 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0 (2026-01-16)
4
+
5
+ ### Features
6
+
7
+ * add debug flag for diagnostic and increase timeout limit ([fb3874b](https://github.com/team-telnyx/voice-agent-tester/commit/fb3874b5531a5237757fe2e9f218a095d8cf6dee))
8
+ * add default telnyx widget options ([d62e74f](https://github.com/team-telnyx/voice-agent-tester/commit/d62e74f1e0bdacff49dab67595a866110be861a4))
9
+ * add dynamic params support ([57397f2](https://github.com/team-telnyx/voice-agent-tester/commit/57397f20c6aecafcf0aef89c1699ff6ebee2e839))
10
+ * add elevenlabs provider ([d605f22](https://github.com/team-telnyx/voice-agent-tester/commit/d605f2260d78755bbe1c4f64d8f283f2167cc194))
11
+ * add release process ([acbffc2](https://github.com/team-telnyx/voice-agent-tester/commit/acbffc23efdcd2aa325049b940a94c3dc09694bb))
12
+ * add vapi application along ([a712397](https://github.com/team-telnyx/voice-agent-tester/commit/a7123972de82df52d0b45126159b5afa32afabfd))
13
+ * add workflow files ([f950bcf](https://github.com/team-telnyx/voice-agent-tester/commit/f950bcf7cd80994e74158347c674a49baa338ca2))
14
+ * automatically create integration secret ([e043e5a](https://github.com/team-telnyx/voice-agent-tester/commit/e043e5a9dd2df9453bc6b1a872a29b93d62779cc))
15
+ * handle dynamic provider param fields requirements ([4bdc7b0](https://github.com/team-telnyx/voice-agent-tester/commit/4bdc7b0ff2a8049836552fc5f59b6ab2dbb28e17))
16
+ * initial benchmark setup for telnyx voice ai ([8233c96](https://github.com/team-telnyx/voice-agent-tester/commit/8233c963ba3f7fe933c0f97d14e7c07146f1faf4))
17
+ * make provider required ([48ad25d](https://github.com/team-telnyx/voice-agent-tester/commit/48ad25d8c92acbd375ae23feade69cb8deb7dd2c))
18
+ * refactor naming ([b6857d9](https://github.com/team-telnyx/voice-agent-tester/commit/b6857d95e48c247287b6ae1ef713c62b889a4b34))
19
+ * release prepare ([8b78136](https://github.com/team-telnyx/voice-agent-tester/commit/8b7813697f4dc25beef4e9f0153d74888783f3e2))
20
+ * remove unused code ([42e2908](https://github.com/team-telnyx/voice-agent-tester/commit/42e2908720335541733c0e5eef68bba88139293a))
21
+ * update benchmark providers ([55623ba](https://github.com/team-telnyx/voice-agent-tester/commit/55623ba713b9dbb4ddf0abcd51d3be58dc5d5b8a))
22
+ * update benchmarking setup ([8b7eb5d](https://github.com/team-telnyx/voice-agent-tester/commit/8b7eb5d7e97d24ddd010c440851e97cb29a166e9))
23
+ * update model on telnyx import for better latency ([bbe941f](https://github.com/team-telnyx/voice-agent-tester/commit/bbe941fc0c8acdb158c3275685027084431ab2ed))
24
+ * update parameters usage on provider choice ([8e2def5](https://github.com/team-telnyx/voice-agent-tester/commit/8e2def5f701e679ce6e9b8fcad2c71c57b96d372))
25
+ * update params ([62c79b0](https://github.com/team-telnyx/voice-agent-tester/commit/62c79b0f22b9729c6e4ae8b8defb4502fb85fa57))
26
+ * update params and logic on import ([03142fb](https://github.com/team-telnyx/voice-agent-tester/commit/03142fb143d9981c09298beff19408ab42825676))
27
+
28
+ ### Bug Fixes
29
+
30
+ * update logs in benchmark app ([26a238d](https://github.com/team-telnyx/voice-agent-tester/commit/26a238ddf0077868da1d877b7d9e89b17b5f7b50))
package/CLAUDE.md ADDED
@@ -0,0 +1,72 @@
1
+ # Voice Agent Tester - Development Guidelines
2
+
3
+ ## Design Overview
4
+
5
+ ### Purpose
6
+ A CLI tool for automated testing of voice agents using Puppeteer. It executes test scenarios against voice-enabled web applications, records audio/video, transcribes responses, and evaluates them using AI.
7
+
8
+ ### Architecture
9
+
10
+ ```
11
+ src/
12
+ ├── index.js # CLI entry point (yargs argument parsing)
13
+ ├── voice-agent-tester.js # Core test execution engine
14
+ ├── report.js # CSV report generation
15
+ ├── server.js # Express assets server
16
+ └── transcription.js # OpenAI Whisper transcription
17
+
18
+ javascript/ # Browser-injected scripts for audio hooks
19
+ applications/ # Application YAML configs
20
+ scenarios/ # Scenario YAML configs
21
+ output/ # Recordings and reports
22
+ ```
23
+
24
+ ### Key Components
25
+
26
+ - **VoiceAgentTester**: Main class that launches browser, executes steps, handles events
27
+ - **ReportGenerator**: Tracks metrics and generates CSV reports
28
+ - **Assets Server**: Serves audio files and temporary HTML pages
29
+
30
+ ### Test Execution Flow
31
+
32
+ 1. Parse CLI arguments and load YAML configs
33
+ 2. Create combinations of applications × scenarios
34
+ 3. For each test run:
35
+ - Launch browser (with puppeteer-stream for recording)
36
+ - Navigate to application URL
37
+ - Inject audio hook scripts
38
+ - Execute application steps then scenario steps
39
+ - Record metrics and save recordings
40
+ - Close browser
41
+
42
+ ### Event System
43
+
44
+ Browser-to-Node communication via `__publishEvent()`:
45
+ - `audiostart` / `audiostop` - Voice activity detection
46
+ - `speechend` - TTS completion
47
+ - `recordingstart` / `recordingcomplete` - Audio recording lifecycle
48
+
49
+ ## Coding Standards
50
+
51
+ - Use simple JavaScript (ES modules)
52
+ - Keep functions short and focused
53
+ - Prefer async/await over callbacks
54
+ - Use descriptive variable and function names
55
+
56
+ ## Testing
57
+
58
+ - Avoid using mocks as much as possible
59
+ - Write unit tests for methods without dependencies
60
+ - Write integration tests for all features and CLI flags
61
+ - Tests should be self-contained and not require external services
62
+
63
+ ## Dependencies
64
+
65
+ - Only add new dependencies when truly necessary
66
+ - Prefer built-in Node.js modules when available
67
+
68
+ ## Git Commits
69
+
70
+ - Use single-line commit messages
71
+ - Keep messages concise and descriptive
72
+ - Focus on what changed, not implementation details
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Telnyx
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 ADDED
@@ -0,0 +1,92 @@
1
+ # Voice Agent Tester (Telnyx Fork)
2
+
3
+ [![CI](https://github.com/team-telnyx/voice-agent-tester/actions/workflows/ci.yml/badge.svg)](https://github.com/team-telnyx/voice-agent-tester/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/@telnyx/voice-agent-tester.svg)](https://www.npmjs.com/package/@telnyx/voice-agent-tester)
5
+
6
+ This is a [Telnyx](https://telnyx.com) fork of [livetok-ai/voice-agent-tester](https://github.com/livetok-ai/voice-agent-tester). For base documentation (installation, configuration, actions, etc.), see the [original README](https://github.com/livetok-ai/voice-agent-tester#readme).
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @telnyx/voice-agent-tester
12
+ ```
13
+
14
+ ## Fork Enhancements
15
+
16
+ ### CLI Options
17
+ | Option | Description |
18
+ |--------|-------------|
19
+ | `--assistant-id` | Assistant/agent ID for direct benchmarking (Telnyx, ElevenLabs, Vapi) |
20
+ | `--api-key` | Telnyx API key for authentication and import operations |
21
+ | `--provider` | Import from external provider (`vapi`, `elevenlabs`, `retell`) into Telnyx |
22
+ | `--provider-api-key` | External provider API key (required with `--provider`) |
23
+ | `--provider-import-id` | Provider assistant/agent ID to import (required with `--provider`) |
24
+ | `--params` | Additional URL template params (e.g., `--params branchId=xxx,shareKey=yyy`) |
25
+ | `--debug` | Enable detailed timeout diagnostics with WebRTC stats |
26
+
27
+ ### Multi-Provider Support
28
+ - **Direct benchmarking**: Use `--assistant-id` with any provider's YAML config
29
+ - **Provider import**: Import assistants from Vapi/ElevenLabs/Retell into Telnyx via `--provider`
30
+ - **Auto-configuration**: Automatic integration secret management and web call enablement
31
+
32
+ ### Debug & Diagnostics
33
+ When `--debug` is enabled, timeout events include WebRTC RTP statistics (packets received, bytes transferred, jitter, packet loss).
34
+
35
+ ## Usage Examples
36
+
37
+ ### Telnyx Assistant (Direct)
38
+
39
+ Benchmark a Telnyx AI assistant directly using the Telnyx widget:
40
+
41
+ ```bash
42
+ npm run start -- \
43
+ -a benchmarks/applications/telnyx.yaml \
44
+ -s benchmarks/scenarios/appointment.yaml \
45
+ --assistant-id <TELNYX_ASSISTANT_ID>
46
+ ```
47
+
48
+ ### ElevenLabs Agent (Direct)
49
+
50
+ Benchmark an ElevenLabs conversational agent. Use `--params` for optional `branchId`:
51
+
52
+ ```bash
53
+ npm run start -- \
54
+ -a benchmarks/applications/elevenlabs.yaml \
55
+ -s benchmarks/scenarios/appointment.yaml \
56
+ --assistant-id <ELEVENLABS_AGENT_ID> \
57
+ --params branchId=<BRANCH_ID>
58
+ ```
59
+
60
+ ### Vapi Assistant (Direct)
61
+
62
+ Benchmark a Vapi assistant using their embedded widget. Requires `shareKey` via `--params`:
63
+
64
+ ```bash
65
+ npm run start -- \
66
+ -a benchmarks/applications/vapi.yaml \
67
+ -s benchmarks/scenarios/appointment.yaml \
68
+ --assistant-id <VAPI_ASSISTANT_ID> \
69
+ --params shareKey=<SHARE_KEY>
70
+ ```
71
+
72
+ ### Import from Provider to Telnyx
73
+
74
+ Import an assistant from an external provider (Vapi, ElevenLabs, Retell) into Telnyx and benchmark:
75
+
76
+ ```bash
77
+ npm run start -- \
78
+ -a benchmarks/applications/telnyx.yaml \
79
+ -s benchmarks/scenarios/appointment.yaml \
80
+ --provider vapi \
81
+ --api-key <TELNYX_API_KEY> \
82
+ --provider-api-key <VAPI_API_KEY> \
83
+ --provider-import-id <VAPI_ASSISTANT_ID>
84
+ ```
85
+
86
+ - `--api-key`: Your Telnyx API key (for creating the import)
87
+ - `--provider-api-key`: The external provider's API key (for fetching the assistant)
88
+ - `--provider-import-id`: The assistant ID from the provider to import
89
+
90
+ ## License
91
+
92
+ MIT
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,86 @@
1
+ // Check if we're in the AudioWorklet context
2
+ if (typeof AudioWorkletProcessor !== 'undefined') {
3
+
4
+ class RecordingProcessor extends AudioWorkletProcessor {
5
+ constructor() {
6
+ super();
7
+ this.isRecording = false;
8
+ this.recordedBuffers = [];
9
+
10
+ // Listen for messages from the main thread
11
+ this.port.onmessage = (event) => {
12
+ const { command } = event.data;
13
+
14
+ switch (command) {
15
+ case 'start':
16
+ this.startRecording();
17
+ break;
18
+ case 'stop':
19
+ this.stopRecording();
20
+ break;
21
+ }
22
+ };
23
+ }
24
+
25
+ startRecording() {
26
+ this.isRecording = true;
27
+ this.recordedBuffers = [];
28
+ console.log('AudioWorklet: Recording started');
29
+ }
30
+
31
+ stopRecording() {
32
+ this.isRecording = false;
33
+
34
+ // Combine all recorded buffers
35
+ const totalLength = this.recordedBuffers.reduce((acc, buffer) => acc + buffer.length, 0);
36
+ const combinedBuffer = new Float32Array(totalLength);
37
+
38
+ let offset = 0;
39
+ for (const buffer of this.recordedBuffers) {
40
+ combinedBuffer.set(buffer, offset);
41
+ offset += buffer.length;
42
+ }
43
+
44
+ // Send the recorded data back to the main thread
45
+ this.port.postMessage({
46
+ command: 'recordingComplete',
47
+ audioData: combinedBuffer,
48
+ sampleRate: sampleRate
49
+ });
50
+
51
+ this.recordedBuffers = [];
52
+ console.log('AudioWorklet: Recording stopped, data sent to main thread');
53
+ }
54
+
55
+ process(inputs, outputs, parameters) {
56
+ const input = inputs[0];
57
+ const output = outputs[0];
58
+
59
+ // Pass audio through (input to output)
60
+ if (input.length > 0 && output.length > 0) {
61
+ const inputChannel = input[0];
62
+ const outputChannel = output[0];
63
+
64
+ // Copy input to output to maintain audio flow
65
+ for (let i = 0; i < inputChannel.length; i++) {
66
+ outputChannel[i] = inputChannel[i];
67
+ }
68
+
69
+ // Record audio if recording is active
70
+ if (this.isRecording && inputChannel.length > 0) {
71
+ const buffer = new Float32Array(inputChannel.length);
72
+ buffer.set(inputChannel);
73
+ this.recordedBuffers.push(buffer);
74
+ }
75
+ }
76
+
77
+ // Keep the processor alive
78
+ return true;
79
+ }
80
+ }
81
+
82
+ registerProcessor('recording-processor', RecordingProcessor);
83
+
84
+ } else {
85
+ console.warn('AudioWorkletProcessor not available - this module should only be loaded in an AudioWorklet context');
86
+ }
Binary file
Binary file
@@ -0,0 +1,10 @@
1
+ url: "https://elevenlabs.io/app/talk-to?agent_id={{assistantId}}&branch_id={{branchId}}"
2
+ steps:
3
+ - action: wait_for_element
4
+ selector: "button[data-agent-id]"
5
+ - action: sleep
6
+ time: 3000
7
+ - action: click
8
+ selector: "button[data-agent-id]"
9
+ - action: sleep
10
+ time: 2000
@@ -0,0 +1,10 @@
1
+ url: "https://portal.telnyx.com/#/ai-widget-demo?assistantId={{assistantId}}"
2
+ steps:
3
+ - action: wait_for_element
4
+ selector: "telnyx-ai-agent"
5
+ - action: sleep
6
+ time: 3000
7
+ - action: click
8
+ selector: "telnyx-ai-agent"
9
+ - action: sleep
10
+ time: 4000
@@ -0,0 +1,10 @@
1
+ url: "https://vapi.ai/?demo=true&shareKey={{shareKey}}&assistantId={{assistantId}}"
2
+ steps:
3
+ - action: wait_for_element
4
+ selector: "button[aria-label='Talk to Vapi']"
5
+ - action: sleep
6
+ time: 3000
7
+ - action: click
8
+ selector: "button[aria-label='Talk to Vapi']"
9
+ - action: sleep
10
+ time: 2000
@@ -0,0 +1,16 @@
1
+ tags:
2
+ - default
3
+ steps:
4
+ - action: wait_for_voice
5
+ - action: wait_for_silence
6
+ - action: sleep
7
+ time: 1000
8
+ - action: speak
9
+ file: hello_make_an_appointment.mp3
10
+ - action: wait_for_voice
11
+ metrics: elapsed_time
12
+ - action: wait_for_silence
13
+ - action: speak
14
+ file: appointment_data.mp3
15
+ - action: wait_for_voice
16
+ metrics: elapsed_time