Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(treewide): native CommonJS #176

Merged
merged 17 commits into from
Nov 29, 2024
9 changes: 9 additions & 0 deletions .changeset/eight-carrots-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@livekit/agents": minor
"@livekit/agents-plugin-deepgram": minor
"@livekit/agents-plugin-elevenlabs": minor
"@livekit/agents-plugin-openai": minor
"@livekit/agents-plugin-silero": minor
---

support native CommonJS
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ originally written in Python.

<!--END_DESCRIPTION-->

> [!WARNING]
> We are aware of a bug concerning users of tsx under certain conditions. See [this
> issue](https://github.com/livekit/agents-js/issues/147) for more details and a fix.

## ✨ [NEW] OpenAI Realtime API support

We're partnering with OpenAI on a new MultimodalAgent API in the Agents framework. This class
Expand Down
2 changes: 1 addition & 1 deletion REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ SPDX-License-Identifier = "Apache-2.0"

# project configuration files
[[annotations]]
path = [".prettierrc", ".prettierignore", ".eslintrc", "**.json"]
path = [".prettierrc", ".prettierignore", ".eslintrc", "**.json", "**/tsup.config.ts"]
SPDX-FileCopyrightText = "2024 LiveKit, Inc."
SPDX-License-Identifier = "Apache-2.0"

Expand Down
24 changes: 17 additions & 7 deletions agents/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,52 @@
"version": "0.4.6",
"description": "LiveKit Agents - Node.js",
"main": "dist/index.js",
"require": "dist/index.cjs",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
},
"author": "LiveKit",
"type": "module",
"repository": "[email protected]:livekit/agents-js.git",
"license": "Apache-2.0",
"files": [
"dist",
"src"
"src",
"README.md"
],
"scripts": {
"build": "tsc",
"build": "tsup --onSuccess \"tsc --declaration --emitDeclarationOnly\"",
"clean": "rm -rf dist",
"clean:build": "pnpm clean && pnpm build",
"lint": "eslint -f unix \"src/**/*.ts\"",
"api:check": "api-extractor run --typescript-compiler-folder ../node_modules/typescript",
"api:update": "api-extractor run --local --typescript-compiler-folder ../node_modules/typescript --verbose"
},
"devDependencies": {
"@livekit/rtc-node": "^0.12.1",
"@microsoft/api-extractor": "^7.35.0",
"@livekit/rtc-node": "^0.11.1",
"@types/node": "^22.5.5",
"@types/ws": "^8.5.10",
"tsup": "^8.3.5",
"typescript": "^5.0.0"
},
"dependencies": {
"@livekit/mutex": "^1.1.0",
"@livekit/protocol": "^1.27.1",
"@livekit/mutex": "^1.1.1",
"@livekit/protocol": "^1.29.1",
"@livekit/typed-emitter": "^3.0.0",
"commander": "^12.0.0",
"livekit-server-sdk": "^2.8.1",
"livekit-server-sdk": "^2.9.2",
"pino": "^8.19.0",
"pino-pretty": "^11.0.0",
"ws": "^8.16.0",
"zod": "^3.23.8"
},
"peerDependencies": {
"@livekit/rtc-node": "^0.11.1"
"@livekit/rtc-node": "^0.12.1"
}
}
130 changes: 66 additions & 64 deletions agents/src/ipc/job_main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,77 +88,79 @@ const startJob = (
return { ctx, task };
};

if (process.send) {
// process.argv:
// [0] `node'
// [1] import.meta.filename
// [2] import.meta.filename of function containing entry file
const moduleFile = process.argv[2];
const agent: Agent = await import(pathToFileURL(moduleFile!).href).then((module) => {
const agent = module.default;
if (agent === undefined || !isAgent(agent)) {
throw new Error(`Unable to load agent: Missing or invalid default export in ${moduleFile}`);
}
return agent;
});
if (!agent.prewarm) {
agent.prewarm = defaultInitializeProcessFunc;
}

// don't do anything on C-c
// this is handled in cli, triggering a termination of all child processes at once.
process.on('SIGINT', () => {});

await once(process, 'message').then(([msg]: IPCMessage[]) => {
msg = msg!;
if (msg.case !== 'initializeRequest') {
throw new Error('first message must be InitializeRequest');
(async () => {
if (process.send) {
// process.argv:
// [0] `node'
// [1] import.meta.filename
// [2] import.meta.filename of function containing entry file
const moduleFile = process.argv[2];
const agent: Agent = await import(pathToFileURL(moduleFile!).pathname).then((module) => {
const agent = module.default;
if (agent === undefined || !isAgent(agent)) {
throw new Error(`Unable to load agent: Missing or invalid default export in ${moduleFile}`);
}
return agent;
});
if (!agent.prewarm) {
agent.prewarm = defaultInitializeProcessFunc;
}
initializeLogger(msg.value.loggerOptions);
});
const proc = new JobProcess();
let logger = log().child({ pid: proc.pid });

logger.debug('initializing job runner');
agent.prewarm(proc);
logger.debug('job runner initialized');
process.send({ case: 'initializeResponse' });

let job: JobTask | undefined = undefined;
const closeEvent = new EventEmitter();
// don't do anything on C-c
// this is handled in cli, triggering a termination of all child processes at once.
process.on('SIGINT', () => {});

const orphanedTimeout = setTimeout(() => {
logger.warn('process orphaned, shutting down');
process.exit();
}, ORPHANED_TIMEOUT);

process.on('message', (msg: IPCMessage) => {
switch (msg.case) {
case 'pingRequest': {
orphanedTimeout.refresh();
process.send!({
case: 'pongResponse',
value: { lastTimestamp: msg.value.timestamp, timestamp: Date.now() },
});
break;
await once(process, 'message').then(([msg]: IPCMessage[]) => {
msg = msg!;
if (msg.case !== 'initializeRequest') {
throw new Error('first message must be InitializeRequest');
}
case 'startJobRequest': {
if (job) {
throw new Error('job task already running');
initializeLogger(msg.value.loggerOptions);
});
const proc = new JobProcess();
let logger = log().child({ pid: proc.pid });

logger.debug('initializing job runner');
agent.prewarm(proc);
logger.debug('job runner initialized');
process.send({ case: 'initializeResponse' });

let job: JobTask | undefined = undefined;
const closeEvent = new EventEmitter();

const orphanedTimeout = setTimeout(() => {
logger.warn('process orphaned, shutting down');
process.exit();
}, ORPHANED_TIMEOUT);

process.on('message', (msg: IPCMessage) => {
switch (msg.case) {
case 'pingRequest': {
orphanedTimeout.refresh();
process.send!({
case: 'pongResponse',
value: { lastTimestamp: msg.value.timestamp, timestamp: Date.now() },
});
break;
}
case 'startJobRequest': {
if (job) {
throw new Error('job task already running');
}

logger = logger.child({ jobID: msg.value.runningJob.job.id });
logger = logger.child({ jobID: msg.value.runningJob.job.id });

job = startJob(proc, agent.entry, msg.value.runningJob, closeEvent, logger);
logger.debug('job started');
break;
}
case 'shutdownRequest': {
if (!job) {
job = startJob(proc, agent.entry, msg.value.runningJob, closeEvent, logger);
logger.debug('job started');
break;
}
closeEvent.emit('close', '');
case 'shutdownRequest': {
if (!job) {
break;
}
closeEvent.emit('close', '');
}
}
}
});
}
});
}
})();
8 changes: 8 additions & 0 deletions agents/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { defineConfig } from 'tsup';

import defaults from '../tsup.config';

export default defineConfig({
...defaults,
});

6 changes: 4 additions & 2 deletions examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@
"minimal": "pnpm exec tsx src/multimodal_agent.ts"
},
"devDependencies": {
"@types/node": "^22.5.5",
"tsx": "^4.19.2",
"typescript": "^5.0.0"
},
"dependencies": {
"@livekit/agents": "workspace:*",
"@livekit/agents-plugin-deepgram": "workspace:*",
"@livekit/agents-plugin-elevenlabs": "workspace:*",
"@livekit/agents-plugin-silero": "workspace:*",
"@livekit/agents-plugin-openai": "workspace:*",
"@livekit/rtc-node": "^0.11.1",
"@livekit/agents-plugin-silero": "workspace:*",
"@livekit/rtc-node": "^0.12.1",
"zod": "^3.23.8"
},
"version": null
Expand Down
20 changes: 15 additions & 5 deletions plugins/deepgram/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,45 @@
"version": "0.4.6",
"description": "Deepgram plugin for LiveKit Agents for Node.js",
"main": "dist/index.js",
"require": "dist/index.cjs",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
},
"author": "LiveKit",
"type": "module",
"repository": "[email protected]:livekit/agents-js.git",
"license": "Apache-2.0",
"files": [
"dist",
"src"
"src",
"README.md"
],
"scripts": {
"build": "tsc",
"build": "tsup --onSuccess \"tsc --declaration --emitDeclarationOnly\"",
"clean": "rm -rf dist",
"clean:build": "pnpm clean && pnpm build",
"lint": "eslint -f unix \"src/**/*.{ts,js}\"",
"api:check": "api-extractor run --typescript-compiler-folder ../../node_modules/typescript",
"api:update": "api-extractor run --local --typescript-compiler-folder ../../node_modules/typescript --verbose"
},
"devDependencies": {
"@microsoft/api-extractor": "^7.35.0",
"@livekit/agents": "workspace:^",
"@livekit/rtc-node": "^0.11.1",
"@livekit/rtc-node": "^0.12.1",
"@microsoft/api-extractor": "^7.35.0",
"@types/ws": "^8.5.10",
"tsup": "^8.3.5",
"typescript": "^5.0.0"
},
"dependencies": {
"ws": "^8.16.0"
},
"peerDependencies": {
"@livekit/agents": "workspace:^",
"@livekit/rtc-node": "^0.11.1"
"@livekit/rtc-node": "^0.12.1"
}
}
7 changes: 7 additions & 0 deletions plugins/deepgram/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from 'tsup';

import defaults from '../../tsup.config';

export default defineConfig({
...defaults,
});
20 changes: 15 additions & 5 deletions plugins/elevenlabs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,45 @@
"version": "0.4.6",
"description": "ElevenLabs plugin for LiveKit Node Agents",
"main": "dist/index.js",
"require": "dist/index.cjs",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
},
"author": "LiveKit",
"type": "module",
"repository": "[email protected]:livekit/agents-js.git",
"license": "Apache-2.0",
"files": [
"dist",
"src"
"src",
"README.md"
],
"scripts": {
"build": "tsc",
"build": "tsup --onSuccess \"tsc --declaration --emitDeclarationOnly\"",
"clean": "rm -rf dist",
"clean:build": "pnpm clean && pnpm build",
"lint": "eslint -f unix \"src/**/*.{ts,js}\"",
"api:check": "api-extractor run --typescript-compiler-folder ../../node_modules/typescript",
"api:update": "api-extractor run --local --typescript-compiler-folder ../../node_modules/typescript --verbose"
},
"devDependencies": {
"@microsoft/api-extractor": "^7.35.0",
"@livekit/agents": "workspace:^",
"@livekit/rtc-node": "^0.11.1",
"@livekit/rtc-node": "^0.12.1",
"@microsoft/api-extractor": "^7.35.0",
"@types/ws": "^8.5.10",
"tsup": "^8.3.5",
"typescript": "^5.0.0"
},
"dependencies": {
"ws": "^8.16.0"
},
"peerDependencies": {
"@livekit/agents": "workspace:^",
"@livekit/rtc-node": "^0.11.1"
"@livekit/rtc-node": "^0.12.1"
}
}
3 changes: 1 addition & 2 deletions plugins/elevenlabs/src/tts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: Apache-2.0
import { AsyncIterableQueue, log, tokenize, tts } from '@livekit/agents';
import type { WordStream } from '@livekit/agents/dist/tokenize/tokenizer.js';
import { AudioFrame } from '@livekit/rtc-node';
import { randomUUID } from 'node:crypto';
import { URL } from 'node:url';
Expand Down Expand Up @@ -141,7 +140,7 @@ export class SynthesizeStream extends tts.SynthesizeStream {
}

async #run() {
const segments = new AsyncIterableQueue<WordStream>();
const segments = new AsyncIterableQueue<tokenize.WordStream>();

const tokenizeInput = async () => {
let stream: tokenize.WordStream | null = null;
Expand Down
7 changes: 7 additions & 0 deletions plugins/elevenlabs/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from 'tsup';

import defaults from '../../tsup.config';

export default defineConfig({
...defaults,
});
Loading