-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support for room configuration inside tokens (#324)
* Support for room configuration inside tokens * changeset * add dispatch APIs via AgentDispatch client * some updates * docs * some docs changes
- Loading branch information
Showing
18 changed files
with
343 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'livekit-server-sdk': minor | ||
--- | ||
|
||
Explicit agent dispatch via API and token |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { RoomAgentDispatch, RoomConfiguration } from '@livekit/protocol'; | ||
import { AccessToken, AgentDispatchClient } from 'livekit-server-sdk'; | ||
|
||
const roomName = 'my-room'; | ||
const agentName = 'test-agent'; | ||
|
||
/** | ||
* This example demonstrates how to have an agent join a room without using | ||
* the automatic dispatch. | ||
* In order to use this feature, you must have an agent running with `agentName` set | ||
* when defining your WorkerOptions. | ||
* | ||
* A dispatch requests the agent to enter a specific room with optional metadata. | ||
*/ | ||
async function createExplicitDispatch() { | ||
const agentDispatchClient = new AgentDispatchClient(process.env.LIVEKIT_URL); | ||
|
||
// this will create invoke an agent with agentName: test-agent to join `my-room` | ||
const dispatch = await agentDispatchClient.createDispatch(roomName, agentName, { | ||
metadata: '{"mydata": "myvalue"}', | ||
}); | ||
console.log('created dispatch', dispatch); | ||
|
||
const dispatches = await agentDispatchClient.listDispatches(roomName); | ||
console.log(`there are ${dispatches.length} dispatches in ${roomName}`); | ||
} | ||
|
||
/** | ||
* When agent name is set, the agent will no longer be automatically dispatched | ||
* to new rooms. If you want that agent to be dispatched to a new room as soon as | ||
* the participant connects, you can set the roomConfig with the agent | ||
* definition in the access token. | ||
*/ | ||
async function createTokenWithAgentDispatch(): Promise<string> { | ||
const at = new AccessToken(); | ||
at.identity = 'my-participant'; | ||
at.addGrant({ roomJoin: true, room: roomName }); | ||
at.roomConfig = new RoomConfiguration({ | ||
agents: [ | ||
new RoomAgentDispatch({ | ||
agentName: agentName, | ||
metadata: '{"mydata": "myvalue"}', | ||
}), | ||
], | ||
}); | ||
return await at.toJwt(); | ||
} | ||
|
||
createTokenWithAgentDispatch().then((token) => { | ||
console.log('created participant token', token); | ||
}); | ||
|
||
console.log('creating explicit dispatch'); | ||
createExplicitDispatch(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"name": "agent-dispatch", | ||
"version": "0.0.1", | ||
"description": "An example demonstrating dispatching agents with an API call", | ||
"private": "true", | ||
"author": "LiveKit", | ||
"license": "Apache-2.0", | ||
"type": "module", | ||
"main": "index.ts", | ||
"scripts": { | ||
"build": "tsc --incremental", | ||
"lint": "eslint -f unix \"**/*.ts\"" | ||
}, | ||
"dependencies": { | ||
"dotenv": "^16.4.5", | ||
"livekit-server-sdk": "workspace:*", | ||
"@livekit/protocol": "^1.27.1" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^20.10.4", | ||
"tsx": "^4.7.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"compilerOptions": { | ||
"module": "ES2022", | ||
"esModuleInterop": true, | ||
"target": "es2022", | ||
"moduleResolution": "node", | ||
"sourceMap": true, | ||
"outDir": "dist" | ||
}, | ||
"lib": ["es2022"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"compilerOptions": { | ||
"module": "ES2022", | ||
"esModuleInterop": true, | ||
"target": "es2022", | ||
"moduleResolution": "node", | ||
"sourceMap": true, | ||
"outDir": "dist" | ||
}, | ||
"lib": ["es2022"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// SPDX-FileCopyrightText: 2024 LiveKit, Inc. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
import { | ||
AgentDispatch, | ||
CreateAgentDispatchRequest, | ||
DeleteAgentDispatchRequest, | ||
ListAgentDispatchRequest, | ||
ListAgentDispatchResponse, | ||
} from '@livekit/protocol'; | ||
import ServiceBase from './ServiceBase'; | ||
import { type Rpc, TwirpRpc, livekitPackage } from './TwirpRPC'; | ||
|
||
interface CreateDispatchOptions { | ||
// any custom data to send along with the job. | ||
// note: this is different from room and participant metadata | ||
metadata?: string; | ||
} | ||
|
||
const svc = 'AgentDispatchService'; | ||
|
||
/** | ||
* Client to access Agent APIs | ||
*/ | ||
export class AgentDispatchClient extends ServiceBase { | ||
private readonly rpc: Rpc; | ||
|
||
/** | ||
* @param host - hostname including protocol. i.e. 'https://<project>.livekit.cloud' | ||
* @param apiKey - API Key, can be set in env var LIVEKIT_API_KEY | ||
* @param secret - API Secret, can be set in env var LIVEKIT_API_SECRET | ||
*/ | ||
constructor(host: string, apiKey?: string, secret?: string) { | ||
super(apiKey, secret); | ||
this.rpc = new TwirpRpc(host, livekitPackage); | ||
} | ||
|
||
/** | ||
* Create an explicit dispatch for an agent to join a room. To use explicit | ||
* dispatch, your agent must be registered with an `agentName`. | ||
* @param roomName - name of the room to dispatch to | ||
* @param agentName - name of the agent to dispatch | ||
* @param options - optional metadata to send along with the dispatch | ||
* @returns the dispatch that was created | ||
*/ | ||
async createDispatch( | ||
roomName: string, | ||
agentName: string, | ||
options?: CreateDispatchOptions, | ||
): Promise<AgentDispatch> { | ||
const req = new CreateAgentDispatchRequest({ | ||
room: roomName, | ||
agentName, | ||
metadata: options?.metadata, | ||
}).toJson(); | ||
const data = await this.rpc.request( | ||
svc, | ||
'CreateDispatch', | ||
req, | ||
await this.authHeader({ roomAdmin: true, room: roomName }), | ||
); | ||
return AgentDispatch.fromJson(data, { ignoreUnknownFields: true }); | ||
} | ||
|
||
/** | ||
* Delete an explicit dispatch for an agent in a room. | ||
* @param dispatchId - id of the dispatch to delete | ||
* @param roomName - name of the room the dispatch is for | ||
*/ | ||
async deleteDispatch(dispatchId: string, roomName: string): Promise<void> { | ||
const req = new DeleteAgentDispatchRequest({ | ||
dispatchId, | ||
room: roomName, | ||
}).toJson(); | ||
await this.rpc.request( | ||
svc, | ||
'DeleteDispatch', | ||
req, | ||
await this.authHeader({ roomAdmin: true, room: roomName }), | ||
); | ||
} | ||
|
||
/** | ||
* Get an Agent dispatch by ID | ||
* @param dispatchId - id of the dispatch to get | ||
* @param roomName - name of the room the dispatch is for | ||
* @returns the dispatch that was found, or undefined if not found | ||
*/ | ||
async getDispatch(dispatchId: string, roomName: string): Promise<AgentDispatch | undefined> { | ||
const req = new ListAgentDispatchRequest({ | ||
dispatchId, | ||
room: roomName, | ||
}).toJson(); | ||
const data = await this.rpc.request( | ||
svc, | ||
'ListDispatch', | ||
req, | ||
await this.authHeader({ roomAdmin: true, room: roomName }), | ||
); | ||
const res = ListAgentDispatchResponse.fromJson(data, { ignoreUnknownFields: true }); | ||
if (res.agentDispatches.length === 0) { | ||
return undefined; | ||
} | ||
return res.agentDispatches[0]; | ||
} | ||
|
||
/** | ||
* List all agent dispatches for a room | ||
* @param roomName - name of the room to list dispatches for | ||
* @returns the list of dispatches | ||
*/ | ||
async listDispatch(roomName: string): Promise<AgentDispatch[]> { | ||
const req = new ListAgentDispatchRequest({ | ||
room: roomName, | ||
}).toJson(); | ||
const data = await this.rpc.request( | ||
svc, | ||
'ListDispatch', | ||
req, | ||
await this.authHeader({ roomAdmin: true, room: roomName }), | ||
); | ||
const res = ListAgentDispatchResponse.fromJson(data, { ignoreUnknownFields: true }); | ||
return res.agentDispatches; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
e389115
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is breaking changing something. I'was working and subtly started to got this error
I tried to update all my packages and did updated livekit-server-sdk to 2.8.0, but nothing
looks like @livekit/agents requires 2.6.1 version of node-sdk