Skip to content

Commit 7d9521d

Browse files
committed
migrate to vite/vitest, update tests and docs
1 parent 6683597 commit 7d9521d

File tree

6 files changed

+87
-36
lines changed

6 files changed

+87
-36
lines changed

AGENTS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ If you are another agentic IDE, refer to your own documentation for how to insta
4646

4747
Voice AI agents are highly sensitive to excessive latency. For this reason, it's important to design complex agents in a structured manner that minimizes the amount of irrelevant context and unnecessary tools present on requests to the LLM. LiveKit Agents supports handoffs (one agent hands control to another) to support building reliable workflows. You should make use of these features, instead of writing long instruction prompts that cover multiple phases of a conversation. Refer to the [documentation](https://docs.livekit.io/agents/build/workflows/) for more information.
4848

49+
### Submit docs feedback to LiveKit
50+
51+
If you use the LiveKit Docs MCP Server to search or browse documentation, also submit constructive feedback to LiveKit with the submit_docs_feedback tool. Add this to your to-do list when planning work, to ensure you file feedback after completing your other tasks. Useful feedback includes incomplete documentation, broken examples, missing steps or any other documentation gap or issue.
52+
53+
## Testing
54+
55+
When possible, add tests for agent behavior. Read the [documentation](https://docs.livekit.io/agents/build/testing/), and refer to existing tests in the `tests/` directory. Run tests with `uv run pytest`.
56+
57+
Important: When modifying core agent behavior such as instructions, tool descriptions, and tasks/workflows/handoffs, never just guess what will work. Always use test-driven development (TDD) and begin by writing tests for the desired behavior. For instance, if you're planning to add a new tool, write one or more tests for the tool's behavior, then iterate on the tool until the tests pass correctly. This will ensure you are able to produce a working, reliable agent for the user.
58+
4959
## Feature parity with Python SDK
5060

5161
The Node.js SDK for LiveKit Agents has most, but not all, of the same features available in Python SDK for LiveKit Agents. You should always check the documentation for feature availability, and avoid using features that are not available in the Node.js SDK.

package.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
"private": true,
55
"type": "module",
66
"scripts": {
7-
"build": "tsc",
7+
"build": "vite build",
88
"clean": "rm -rf dist",
99
"typecheck": "tsc --noEmit",
1010
"lint": "eslint \"**/*.{ts,js}\"",
1111
"lint:fix": "eslint --fix \"**/*.{ts,js}\"",
1212
"format": "prettier --write \"**/*.{ts,js,json,md}\"",
1313
"format:check": "prettier --check \"**/*.{ts,js,json,md}\"",
14-
"test": "node --test --import tsx",
15-
"test:watch": "node --test --watch --import tsx",
16-
"dev": "tsx src/agent.ts dev",
14+
"test": "vitest --run",
15+
"test:watch": "vitest",
16+
"dev": "pnpm run build && node dist/agent.js dev",
1717
"download-files": "pnpm run build && node dist/agent.js download-files",
1818
"start": "node dist/agent.js start"
1919
},
@@ -22,20 +22,20 @@
2222
"pnpm": ">=10.0.0"
2323
},
2424
"devDependencies": {
25-
"@eslint/js": "^9.38.0",
25+
"@eslint/js": "^9.39.2",
2626
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
27-
"@types/node": "^22.18.11",
28-
"eslint": "^9.38.0",
29-
"globals": "^16.4.0",
30-
"jiti": "^2.6.1",
31-
"tsx": "^4.20.6",
27+
"@types/node": "^22.19.7",
28+
"eslint": "^9.39.2",
29+
"globals": "^16.5.0",
3230
"typescript": "^5.9.3",
33-
"typescript-eslint": "^8.46.2"
31+
"typescript-eslint": "^8.53.1",
32+
"vite": "^7.3.1",
33+
"vitest": "^4.0.18"
3434
},
3535
"dependencies": {
36-
"@livekit/agents": "^1.0.21",
37-
"@livekit/agents-plugin-livekit": "^1.0.21",
38-
"@livekit/agents-plugin-silero": "^1.0.21",
36+
"@livekit/agents": "^1.0.38",
37+
"@livekit/agents-plugin-livekit": "^1.0.38",
38+
"@livekit/agents-plugin-silero": "^1.0.38",
3939
"@livekit/noise-cancellation-node": "^0.1.9",
4040
"dotenv": "^17.2.3",
4141
"zod": "^3.25.76"

src/agent.test.ts

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,47 @@
1-
import assert from 'node:assert';
2-
import { describe, it } from 'node:test';
3-
4-
describe('Agent Configuration', () => {
5-
it('should have Node.js environment available', () => {
6-
// Basic test to ensure Node.js environment is working
7-
assert.ok(typeof process !== 'undefined', 'Process should be available');
8-
assert.ok(typeof process.env !== 'undefined', 'Environment variables should be accessible');
9-
});
1+
import { inference, initializeLogger, voice } from '@livekit/agents';
2+
import { afterEach, beforeEach, describe, it } from 'vitest';
3+
import { Assistant } from './agent';
4+
5+
type TestableAgentSession = InstanceType<typeof voice.AgentSession> & {
6+
run(options: { userInput: string }): voice.testing.RunResult;
7+
};
8+
9+
// Initialize logger for testing
10+
initializeLogger({ pretty: false, level: 'debug' });
11+
12+
describe('agent evaluation', () => {
13+
let session: TestableAgentSession;
14+
let llmInstance: inference.LLM;
1015

11-
it('should be able to import required modules', async () => {
12-
// Test that core Node.js modules work
13-
const path = await import('node:path');
14-
const url = await import('node:url');
16+
beforeEach(async () => {
17+
llmInstance = new inference.LLM({ model: 'openai/gpt-5.1' });
18+
session = new voice.AgentSession({ llm: llmInstance }) as TestableAgentSession;
19+
await session.start({ agent: new Assistant() });
20+
});
1521

16-
assert.ok(typeof path.dirname === 'function', 'Path module should be available');
17-
assert.ok(typeof url.fileURLToPath === 'function', 'URL module should be available');
22+
afterEach(async () => {
23+
await session?.close();
1824
});
1925

20-
it('should have TypeScript compilation working', () => {
21-
// This test file being run means TypeScript compiled successfully
22-
assert.ok(true, 'TypeScript compilation is working');
26+
it('offers assistance', { timeout: 30000 }, async () => {
27+
// Run an agent turn following the user's greeting
28+
const result = await session.run({ userInput: 'Hello' }).wait();
29+
30+
// Evaluate the agent's response for friendliness
31+
await result.expect
32+
.nextEvent()
33+
.isMessage({ role: 'assistant' })
34+
.judge(llmInstance, {
35+
intent: `\
36+
Greets the user in a friendly manner.
37+
38+
Optional context that may or may not be included:
39+
- Offer of assistance with any request the user may have
40+
- Other small talk or chit chat is acceptable, so long as it is friendly and not too intrusive
41+
`,
42+
});
43+
44+
// Assert that there are no unexpected further events
45+
result.expect.noMoreEvents();
2346
});
2447
});

src/agent.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { fileURLToPath } from 'node:url';
1616

1717
dotenv.config({ path: '.env.local' });
1818

19-
class Assistant extends voice.Agent {
19+
export class Assistant extends voice.Agent {
2020
constructor() {
2121
super({
2222
instructions: `You are a helpful voice AI assistant. The user is interacting with you via voice, even if you perceive the conversation as text.
@@ -65,7 +65,7 @@ export default defineAgent({
6565
// A Large Language Model (LLM) is your agent's brain, processing user input and generating a response
6666
// See all providers at https://docs.livekit.io/agents/models/llm/
6767
llm: new inference.LLM({
68-
model: 'openai/gpt-4.1-mini',
68+
model: 'openai/gpt-5.1-mini',
6969
}),
7070

7171
// Text-to-speech (TTS) is your agent's voice, turning the LLM's text into speech that the user can hear
@@ -127,4 +127,7 @@ export default defineAgent({
127127
},
128128
});
129129

130-
cli.runApp(new ServerOptions({ agent: fileURLToPath(import.meta.url) }));
130+
// Only run the CLI if we're not in a test environment
131+
if (process.env.NODE_ENV !== 'test') {
132+
cli.runApp(new ServerOptions({ agent: fileURLToPath(import.meta.url) }));
133+
}

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"include": ["./src/**/*"],
3-
"exclude": ["./dist", "./node_modules"],
3+
"exclude": ["./dist", "./node_modules", "**/*.test.ts", "**/*.spec.ts"],
44
"compilerOptions": {
55
"target": "ES2022",
66
"module": "ES2022",

vite.config.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { defineConfig } from 'vite';
2+
3+
export default defineConfig({
4+
build: {
5+
ssr: 'src/agent.ts', // marks entry as Node
6+
target: 'node18',
7+
sourcemap: true,
8+
outDir: 'dist',
9+
rollupOptions: {
10+
output: {
11+
entryFileNames: 'agent.js',
12+
},
13+
},
14+
},
15+
});

0 commit comments

Comments
 (0)