add (very basic) agent rendering to webapp
This commit is contained in:
parent
9951e7bcaf
commit
918ab5f95e
7 changed files with 60 additions and 20 deletions
|
@ -78,8 +78,12 @@ export class Client extends EventEmitter {
|
||||||
username = uo + i++;
|
username = uo + i++;
|
||||||
} while (this.room.clients.some(u => u.username === username))
|
} while (this.room.clients.some(u => u.username === username))
|
||||||
}
|
}
|
||||||
|
if (!this.room.agents.some(a => a.filename === joinMsg.data.agent)) {
|
||||||
|
this.socket.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.agent = htmlentities.encode(joinMsg.data.agent);
|
this.agent = joinMsg.data.agent;
|
||||||
this.emit('join');
|
this.emit('join');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,15 +73,10 @@ app.register(FastifyStatic, {
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/api/agents", (req, res) => {
|
app.get("/api/agents", (req, res) => {
|
||||||
return config.agents.map(a => {
|
return config.agents;
|
||||||
return {
|
|
||||||
url: `/api/agents/${a.filename}`,
|
|
||||||
name: a.friendlyName
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let room = new MSAgentChatRoom(config.chat, tts);
|
let room = new MSAgentChatRoom(config.chat, config.agents, tts);
|
||||||
|
|
||||||
app.register(async app => {
|
app.register(async app => {
|
||||||
app.get("/api/socket", {websocket: true}, (socket, req) => {
|
app.get("/api/socket", {websocket: true}, (socket, req) => {
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import { MSAgentAddUserMessage, MSAgentChatMessage, MSAgentInitMessage, MSAgentProtocolMessage, MSAgentProtocolMessageType, MSAgentRemoveUserMessage } from "@msagent-chat/protocol";
|
import { MSAgentAddUserMessage, MSAgentChatMessage, MSAgentInitMessage, MSAgentProtocolMessage, MSAgentProtocolMessageType, MSAgentRemoveUserMessage } from "@msagent-chat/protocol";
|
||||||
import { Client } from "./client.js";
|
import { Client } from "./client.js";
|
||||||
import { TTSClient } from "./tts.js";
|
import { TTSClient } from "./tts.js";
|
||||||
import { ChatConfig } from "./config.js";
|
import { AgentConfig, ChatConfig } from "./config.js";
|
||||||
import * as htmlentities from 'html-entities';
|
import * as htmlentities from 'html-entities';
|
||||||
|
|
||||||
export class MSAgentChatRoom {
|
export class MSAgentChatRoom {
|
||||||
|
agents: AgentConfig[];
|
||||||
clients: Client[];
|
clients: Client[];
|
||||||
tts: TTSClient | null;
|
tts: TTSClient | null;
|
||||||
msgId : number = 0;
|
msgId : number = 0;
|
||||||
config: ChatConfig;
|
config: ChatConfig;
|
||||||
|
|
||||||
constructor(config: ChatConfig, tts: TTSClient | null) {
|
constructor(config: ChatConfig, agents: AgentConfig[], tts: TTSClient | null) {
|
||||||
|
this.agents = agents;
|
||||||
this.clients = [];
|
this.clients = [];
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.tts = tts;
|
this.tts = tts;
|
||||||
|
|
|
@ -32,6 +32,9 @@
|
||||||
<input type="text" id="logonRoom" placeholder="Optional"/>
|
<input type="text" id="logonRoom" placeholder="Optional"/>
|
||||||
</div>
|
</div>
|
||||||
<div id="logonButtonsContainer">
|
<div id="logonButtonsContainer">
|
||||||
|
<select id="agentSelect">
|
||||||
|
<option value="" disabled selected hidden>Agent</option>
|
||||||
|
</select>
|
||||||
<button type="submit" id="logonButton">Log on</button>
|
<button type="submit" id="logonButton">Log on</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { createNanoEvents, Emitter, Unsubscribe } from 'nanoevents';
|
import { createNanoEvents, Emitter, Unsubscribe } from 'nanoevents';
|
||||||
import { MSAgentAddUserMessage, MSAgentChatMessage, MSAgentInitMessage, MSAgentJoinMessage, MSAgentProtocolMessage, MSAgentProtocolMessageType, MSAgentRemoveUserMessage, MSAgentTalkMessage } from '@msagent-chat/protocol';
|
import { MSAgentAddUserMessage, MSAgentChatMessage, MSAgentInitMessage, MSAgentJoinMessage, MSAgentProtocolMessage, MSAgentProtocolMessageType, MSAgentRemoveUserMessage, MSAgentTalkMessage } from '@msagent-chat/protocol';
|
||||||
import { User } from './user';
|
import { User } from './user';
|
||||||
|
import { agentCreateCharacterFromUrl } from '@msagent-chat/msagent.js';
|
||||||
|
|
||||||
export interface MSAgentClientEvents {
|
export interface MSAgentClientEvents {
|
||||||
close: () => void;
|
close: () => void;
|
||||||
|
@ -10,6 +11,11 @@ export interface MSAgentClientEvents {
|
||||||
chat: (user: User, msg: string) => void;
|
chat: (user: User, msg: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface APIAgentInfo {
|
||||||
|
friendlyName: string;
|
||||||
|
filename: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class MSAgentClient {
|
export class MSAgentClient {
|
||||||
private url: string;
|
private url: string;
|
||||||
private socket: WebSocket | null;
|
private socket: WebSocket | null;
|
||||||
|
@ -19,10 +25,12 @@ export class MSAgentClient {
|
||||||
private charlimit: number = 0;
|
private charlimit: number = 0;
|
||||||
|
|
||||||
private username: string | null = null;
|
private username: string | null = null;
|
||||||
|
private agentContainer: HTMLElement;
|
||||||
private agent: string | null = null;
|
private agent: string | null = null;
|
||||||
|
|
||||||
constructor(url: string) {
|
constructor(url: string, agentContainer: HTMLElement) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
this.agentContainer = agentContainer;
|
||||||
this.socket = null;
|
this.socket = null;
|
||||||
this.events = createNanoEvents();
|
this.events = createNanoEvents();
|
||||||
this.users = [];
|
this.users = [];
|
||||||
|
@ -32,6 +40,11 @@ export class MSAgentClient {
|
||||||
return this.events.on(event, callback);
|
return this.events.on(event, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getAgents() {
|
||||||
|
let res = await fetch(this.url + "/api/agents");
|
||||||
|
return await res.json() as APIAgentInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
connect(): Promise<void> {
|
connect(): Promise<void> {
|
||||||
return new Promise(res => {
|
return new Promise(res => {
|
||||||
let url = new URL(this.url);
|
let url = new URL(this.url);
|
||||||
|
@ -104,7 +117,7 @@ export class MSAgentClient {
|
||||||
return this.charlimit;
|
return this.charlimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleMessage(data: string) {
|
private async handleMessage(data: string) {
|
||||||
let msg: MSAgentProtocolMessage;
|
let msg: MSAgentProtocolMessage;
|
||||||
try {
|
try {
|
||||||
msg = JSON.parse(data);
|
msg = JSON.parse(data);
|
||||||
|
@ -118,13 +131,22 @@ export class MSAgentClient {
|
||||||
this.username = initMsg.data.username;
|
this.username = initMsg.data.username;
|
||||||
this.agent = initMsg.data.agent;
|
this.agent = initMsg.data.agent;
|
||||||
this.charlimit = initMsg.data.charlimit;
|
this.charlimit = initMsg.data.charlimit;
|
||||||
this.users.push(...initMsg.data.users.map(u => new User(u.username, u.agent)));
|
for (let _user of initMsg.data.users) {
|
||||||
|
let agent = await agentCreateCharacterFromUrl(this.url + "/api/agents/" + _user.agent);
|
||||||
|
agent.addToDom(this.agentContainer);
|
||||||
|
agent.show();
|
||||||
|
let user = new User(_user.username, agent);
|
||||||
|
this.users.push(user);
|
||||||
|
}
|
||||||
this.events.emit('join');
|
this.events.emit('join');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSAgentProtocolMessageType.AddUser: {
|
case MSAgentProtocolMessageType.AddUser: {
|
||||||
let addUserMsg = msg as MSAgentAddUserMessage
|
let addUserMsg = msg as MSAgentAddUserMessage;
|
||||||
let user = new User(addUserMsg.data.username, addUserMsg.data.agent);
|
let agent = await agentCreateCharacterFromUrl(this.url + "/api/agents/" + addUserMsg.data.agent);
|
||||||
|
agent.addToDom(this.agentContainer);
|
||||||
|
agent.show();
|
||||||
|
let user = new User(addUserMsg.data.username, agent);
|
||||||
this.users.push(user);
|
this.users.push(user);
|
||||||
this.events.emit('adduser', user);
|
this.events.emit('adduser', user);
|
||||||
break;
|
break;
|
||||||
|
@ -133,6 +155,7 @@ export class MSAgentClient {
|
||||||
let remUserMsg = msg as MSAgentRemoveUserMessage;
|
let remUserMsg = msg as MSAgentRemoveUserMessage;
|
||||||
let user = this.users.find(u => u.username === remUserMsg.data.username);
|
let user = this.users.find(u => u.username === remUserMsg.data.username);
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
user.agent.hide(true);
|
||||||
if (this.playingAudio.has(user!.username)) {
|
if (this.playingAudio.has(user!.username)) {
|
||||||
this.playingAudio.delete(user!.username);
|
this.playingAudio.delete(user!.username);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,21 @@ import { MSWindow, MSWindowStartPosition } from "./MSWindow.js";
|
||||||
import { agentInit } from "@msagent-chat/msagent.js";
|
import { agentInit } from "@msagent-chat/msagent.js";
|
||||||
import { MSAgentClient } from "./client.js";
|
import { MSAgentClient } from "./client.js";
|
||||||
|
|
||||||
let Room : MSAgentClient | null = null;
|
|
||||||
|
|
||||||
const elements = {
|
const elements = {
|
||||||
logonView: document.getElementById("logonView") as HTMLDivElement,
|
logonView: document.getElementById("logonView") as HTMLDivElement,
|
||||||
logonWindow: document.getElementById("logonWindow") as HTMLDivElement,
|
logonWindow: document.getElementById("logonWindow") as HTMLDivElement,
|
||||||
logonForm: document.getElementById("logonForm") as HTMLFormElement,
|
logonForm: document.getElementById("logonForm") as HTMLFormElement,
|
||||||
logonUsername: document.getElementById("logonUsername") as HTMLInputElement,
|
logonUsername: document.getElementById("logonUsername") as HTMLInputElement,
|
||||||
|
agentSelect: document.getElementById("agentSelect") as HTMLSelectElement,
|
||||||
|
|
||||||
chatView: document.getElementById("chatView") as HTMLDivElement,
|
chatView: document.getElementById("chatView") as HTMLDivElement,
|
||||||
chatInput: document.getElementById("chatInput") as HTMLInputElement,
|
chatInput: document.getElementById("chatInput") as HTMLInputElement,
|
||||||
chatSendBtn: document.getElementById("chatSendBtn") as HTMLButtonElement
|
chatSendBtn: document.getElementById("chatSendBtn") as HTMLButtonElement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let Room : MSAgentClient = new MSAgentClient(`${window.location.protocol}//${window.location.host}`, elements.chatView);
|
||||||
|
|
||||||
let logonWindow = new MSWindow(elements.logonWindow, {
|
let logonWindow = new MSWindow(elements.logonWindow, {
|
||||||
width: 500,
|
width: 500,
|
||||||
height: 275,
|
height: 275,
|
||||||
|
@ -39,9 +41,12 @@ elements.chatSendBtn.addEventListener('click', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
async function connectToRoom() {
|
async function connectToRoom() {
|
||||||
Room = new MSAgentClient(`${window.location.protocol}//${window.location.host}`);
|
if (!elements.agentSelect.value) {
|
||||||
|
alert("Please select an agent.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
await Room.connect();
|
await Room.connect();
|
||||||
await Room.join(elements.logonUsername.value, "test");
|
await Room.join(elements.logonUsername.value, elements.agentSelect.value);
|
||||||
elements.chatInput.maxLength = Room.getCharlimit();
|
elements.chatInput.maxLength = Room.getCharlimit();
|
||||||
logonWindow.hide();
|
logonWindow.hide();
|
||||||
elements.logonView.style.display = "none";
|
elements.logonView.style.display = "none";
|
||||||
|
@ -50,6 +55,12 @@ async function connectToRoom() {
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
await agentInit();
|
await agentInit();
|
||||||
|
for (const agent of await Room.getAgents()) {
|
||||||
|
let option = document.createElement("option");
|
||||||
|
option.innerText = agent.friendlyName;
|
||||||
|
option.value = agent.filename;
|
||||||
|
elements.agentSelect.appendChild(option);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function talk() {
|
function talk() {
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
import { Agent } from "@msagent-chat/msagent.js";
|
||||||
|
|
||||||
export class User {
|
export class User {
|
||||||
username: string;
|
username: string;
|
||||||
agent: string;
|
agent: Agent
|
||||||
|
|
||||||
constructor(username: string, agent: string) {
|
constructor(username: string, agent: Agent) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.agent = agent;
|
this.agent = agent;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue