mirror of https://github.com/OpenVidu/openvidu.git
openvidu-testapp: added controls for Agent Dispatch API
parent
fdd0441e8e
commit
9d4b11ed58
|
|
@ -127,6 +127,14 @@ mat-chip-row {
|
|||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
.agent-dispatch-options {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
#agent-restart-policy-select {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
#ingress-url-type-select {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -256,6 +256,68 @@
|
|||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div>
|
||||
<label class="label">Agent Dispatch API</label>
|
||||
<mat-form-field class="inner-text-input" [style.fontSize.px]=14>
|
||||
<mat-label>Room</mat-label>
|
||||
<input matInput id="agent-room-name-field" placeholder="Room" [(ngModel)]="agentRoomName">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="inner-text-input" [style.fontSize.px]=14>
|
||||
<mat-label>Agent name</mat-label>
|
||||
<input matInput id="agent-name-field" placeholder="Agent name" [(ngModel)]="agentName">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="inner-text-input" [style.fontSize.px]=14>
|
||||
<mat-label>Dispatch ID</mat-label>
|
||||
<input matInput id="agent-dispatch-id-field" placeholder="Dispatch ID" [(ngModel)]="agentDispatchId">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="button-group">
|
||||
<span style="display: inline-block" [matTooltip]="!agentRoomName ? 'Room required' : 'Agent name required'"
|
||||
[matTooltipDisabled]="!!agentRoomName && !!agentName">
|
||||
<button mat-button id="create-dispatch-api-btn" (click)="createDispatch()"
|
||||
[disabled]="!agentRoomName || !agentName">Create Dispatch</button>
|
||||
</span>
|
||||
<span style="display: inline-block" matTooltip='"Room" required' [matTooltipDisabled]="!!agentRoomName">
|
||||
<button mat-button id="list-dispatch-api-btn" (click)="listDispatch()" [disabled]="!agentRoomName">List
|
||||
Dispatch</button>
|
||||
</span>
|
||||
<span style="display: inline-block" matTooltip='"Room" and "Dispatch ID" required'
|
||||
[matTooltipDisabled]="!!agentRoomName && !!agentDispatchId">
|
||||
<button mat-button id="get-dispatch-api-btn" (click)="getDispatch()"
|
||||
[disabled]="!agentRoomName || !agentDispatchId">Get Dispatch</button>
|
||||
</span>
|
||||
<span style="display: inline-block" matTooltip='"Room" and "Dispatch ID" required'
|
||||
[matTooltipDisabled]="!!agentRoomName && !!agentDispatchId">
|
||||
<button mat-button id="delete-dispatch-api-btn" (click)="deleteDispatch()"
|
||||
[disabled]="!agentRoomName || !agentDispatchId">Delete Dispatch</button>
|
||||
</span>
|
||||
<span style="display: inline-block" matTooltip='"Room" required' [matTooltipDisabled]="!!agentRoomName">
|
||||
<button mat-button id="delete-all-dispatch-api-btn" (click)="deleteAllDispatch()" [disabled]="!agentRoomName"
|
||||
style="font-style: italic; font-size: 0.75rem; margin-left: 5px;">Delete all</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<label class="label">Dispatch options</label>
|
||||
<div class="agent-dispatch-options">
|
||||
<mat-form-field class="inner-text-input" [style.fontSize.px]=14>
|
||||
<mat-label>Metadata</mat-label>
|
||||
<input matInput id="agent-metadata-field" placeholder="Metadata" [(ngModel)]="agentMetadata">
|
||||
</mat-form-field>
|
||||
<mat-form-field id="agent-restart-policy-select">
|
||||
<mat-label>Restart policy</mat-label>
|
||||
<mat-select [(value)]="agentRestartPolicySelected">
|
||||
@for (policy of AGENT_RESTART_POLICIES; track policy) {
|
||||
<mat-option [value]="policy.value" [id]="'mat-option-' + policy.viewValue">
|
||||
{{policy.viewValue}}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<mat-form-field id="response-text-area" appearance="fill">
|
||||
<textarea id="api-response-text-area" [(ngModel)]="response" matInput readonly></textarea>
|
||||
<button mat-button id="clear-response-text-area-btn" (click)="response=''">Clear</button>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import { MatSelectModule } from '@angular/material/select';
|
|||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
import { VideoCodec } from '@livekit/protocol';
|
||||
import { JobRestartPolicy, VideoCodec } from '@livekit/protocol';
|
||||
import { LocalParticipant } from 'livekit-client';
|
||||
|
||||
import {
|
||||
|
|
@ -84,6 +84,17 @@ export class RoomApiDialogComponent {
|
|||
ingressUrlType: string = 'HTTP';
|
||||
ingressUrlUri: string;
|
||||
|
||||
agentRoomName: string;
|
||||
agentName: string = 'speech-processing';
|
||||
agentDispatchId: string;
|
||||
agentMetadata: string;
|
||||
agentRestartPolicySelected: JobRestartPolicy = JobRestartPolicy.JRP_ON_FAILURE;
|
||||
|
||||
AGENT_RESTART_POLICIES: { value: JobRestartPolicy; viewValue: string }[] = [
|
||||
{ value: JobRestartPolicy.JRP_ON_FAILURE, viewValue: 'On failure' },
|
||||
{ value: JobRestartPolicy.JRP_NEVER, viewValue: 'Never' },
|
||||
];
|
||||
|
||||
response: string;
|
||||
|
||||
INGRESS_INPUT_TYPES: { value: IngressInput; viewValue: string }[] = [
|
||||
|
|
@ -141,6 +152,7 @@ export class RoomApiDialogComponent {
|
|||
.values()
|
||||
.next().value?.trackSid!;
|
||||
this.ingressRoomName = this.room?.name;
|
||||
this.agentRoomName = this.room?.name;
|
||||
}
|
||||
|
||||
async listRooms() {
|
||||
|
|
@ -365,6 +377,81 @@ export class RoomApiDialogComponent {
|
|||
}
|
||||
}
|
||||
|
||||
async createDispatch() {
|
||||
console.log('Creating agent dispatch');
|
||||
try {
|
||||
const dispatch = await this.roomApiService.createDispatch(
|
||||
this.agentRoomName,
|
||||
this.agentName,
|
||||
this.agentMetadata || undefined,
|
||||
this.agentRestartPolicySelected
|
||||
);
|
||||
this.response = JSON.stringify(dispatch, null, 4);
|
||||
this.agentDispatchId = dispatch.id;
|
||||
} catch (error: any) {
|
||||
this.response = error;
|
||||
}
|
||||
}
|
||||
|
||||
async getDispatch() {
|
||||
console.log('Getting agent dispatch');
|
||||
try {
|
||||
const dispatch = await this.roomApiService.getDispatch(
|
||||
this.agentDispatchId,
|
||||
this.agentRoomName
|
||||
);
|
||||
this.response = dispatch
|
||||
? JSON.stringify(dispatch, null, 4)
|
||||
: 'Dispatch not found';
|
||||
} catch (error: any) {
|
||||
this.response = error;
|
||||
}
|
||||
}
|
||||
|
||||
async listDispatch() {
|
||||
console.log('Listing agent dispatches');
|
||||
try {
|
||||
const dispatches = await this.roomApiService.listDispatch(
|
||||
this.agentRoomName
|
||||
);
|
||||
this.response = JSON.stringify(dispatches, null, 4);
|
||||
} catch (error: any) {
|
||||
this.response = error;
|
||||
}
|
||||
}
|
||||
|
||||
async deleteDispatch() {
|
||||
console.log('Deleting agent dispatch');
|
||||
try {
|
||||
await this.roomApiService.deleteDispatch(
|
||||
this.agentDispatchId,
|
||||
this.agentRoomName
|
||||
);
|
||||
this.response = 'Agent dispatch deleted';
|
||||
} catch (error: any) {
|
||||
this.response = error;
|
||||
}
|
||||
}
|
||||
|
||||
async deleteAllDispatch() {
|
||||
console.log('Deleting all agent dispatches');
|
||||
try {
|
||||
const promises: Promise<void>[] = [];
|
||||
const dispatches = await this.roomApiService.listDispatch(
|
||||
this.agentRoomName
|
||||
);
|
||||
dispatches.forEach((d) => {
|
||||
promises.push(
|
||||
this.roomApiService.deleteDispatch(d.id, this.agentRoomName)
|
||||
);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
this.response = 'Deleted ' + promises.length + ' agent dispatches';
|
||||
} catch (error: any) {
|
||||
this.response = error;
|
||||
}
|
||||
}
|
||||
|
||||
addRtmpUrl(event: MatChipInputEvent): void {
|
||||
const value = (event.value || '').trim();
|
||||
if (value) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
|
|||
|
||||
import {
|
||||
AccessToken,
|
||||
AgentDispatchClient,
|
||||
CreateIngressOptions,
|
||||
DirectFileOutput,
|
||||
EgressClient,
|
||||
|
|
@ -25,7 +26,9 @@ import {
|
|||
import { LivekitParamsService } from './livekit-params.service';
|
||||
import { VideoQuality } from 'livekit-client';
|
||||
import {
|
||||
AgentDispatch,
|
||||
IngressVideoEncodingOptions,
|
||||
JobRestartPolicy,
|
||||
VideoCodec,
|
||||
VideoLayer,
|
||||
} from '@livekit/protocol';
|
||||
|
|
@ -46,6 +49,7 @@ export class RoomApiService {
|
|||
private roomServiceClient: RoomServiceClient;
|
||||
private egressClient: EgressClient;
|
||||
private ingressClient: IngressClient;
|
||||
private agentDispatchClient: AgentDispatchClient;
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
|
|
@ -66,6 +70,11 @@ export class RoomApiService {
|
|||
this.livekitParamsService.getParams().livekitApiKey,
|
||||
this.livekitParamsService.getParams().livekitApiSecret
|
||||
);
|
||||
this.agentDispatchClient = new AgentDispatchClient(
|
||||
this.getRestUrl(),
|
||||
this.livekitParamsService.getParams().livekitApiKey,
|
||||
this.livekitParamsService.getParams().livekitApiSecret
|
||||
);
|
||||
}
|
||||
|
||||
async createToken(
|
||||
|
|
@ -328,6 +337,38 @@ export class RoomApiService {
|
|||
return await ingressClient.deleteIngress(ingressId);
|
||||
}
|
||||
|
||||
/*
|
||||
* Agent Dispatch API
|
||||
* https://docs.livekit.io/reference/agents/agent-dispatch-service-api/
|
||||
*/
|
||||
|
||||
async createDispatch(
|
||||
roomName: string,
|
||||
agentName: string,
|
||||
metadata?: string,
|
||||
restartPolicy?: JobRestartPolicy
|
||||
): Promise<AgentDispatch> {
|
||||
return await this.agentDispatchClient.createDispatch(roomName, agentName, {
|
||||
metadata,
|
||||
restartPolicy,
|
||||
});
|
||||
}
|
||||
|
||||
async getDispatch(
|
||||
dispatchId: string,
|
||||
roomName: string
|
||||
): Promise<AgentDispatch | undefined> {
|
||||
return await this.agentDispatchClient.getDispatch(dispatchId, roomName);
|
||||
}
|
||||
|
||||
async listDispatch(roomName: string): Promise<AgentDispatch[]> {
|
||||
return await this.agentDispatchClient.listDispatch(roomName);
|
||||
}
|
||||
|
||||
async deleteDispatch(dispatchId: string, roomName: string): Promise<void> {
|
||||
return await this.agentDispatchClient.deleteDispatch(dispatchId, roomName);
|
||||
}
|
||||
|
||||
private getRestUrl() {
|
||||
const wsUrl = this.livekitParamsService.getParams().livekitUrl;
|
||||
const protocol =
|
||||
|
|
|
|||
Loading…
Reference in New Issue