diff --git a/server/src/client.ts b/server/src/client.ts
index 698e3de..b0dec7d 100644
--- a/server/src/client.ts
+++ b/server/src/client.ts
@@ -78,8 +78,12 @@ export class Client extends EventEmitter {
username = uo + i++;
} 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.agent = htmlentities.encode(joinMsg.data.agent);
+ this.agent = joinMsg.data.agent;
this.emit('join');
break;
}
diff --git a/server/src/index.ts b/server/src/index.ts
index 29e9e8b..30f9443 100644
--- a/server/src/index.ts
+++ b/server/src/index.ts
@@ -73,15 +73,10 @@ app.register(FastifyStatic, {
});
app.get("/api/agents", (req, res) => {
- return config.agents.map(a => {
- return {
- url: `/api/agents/${a.filename}`,
- name: a.friendlyName
- }
- });
+ return config.agents;
});
-let room = new MSAgentChatRoom(config.chat, tts);
+let room = new MSAgentChatRoom(config.chat, config.agents, tts);
app.register(async app => {
app.get("/api/socket", {websocket: true}, (socket, req) => {
diff --git a/server/src/room.ts b/server/src/room.ts
index c9d2266..3d6ed1e 100644
--- a/server/src/room.ts
+++ b/server/src/room.ts
@@ -1,16 +1,18 @@
import { MSAgentAddUserMessage, MSAgentChatMessage, MSAgentInitMessage, MSAgentProtocolMessage, MSAgentProtocolMessageType, MSAgentRemoveUserMessage } from "@msagent-chat/protocol";
import { Client } from "./client.js";
import { TTSClient } from "./tts.js";
-import { ChatConfig } from "./config.js";
+import { AgentConfig, ChatConfig } from "./config.js";
import * as htmlentities from 'html-entities';
export class MSAgentChatRoom {
+ agents: AgentConfig[];
clients: Client[];
tts: TTSClient | null;
msgId : number = 0;
config: ChatConfig;
- constructor(config: ChatConfig, tts: TTSClient | null) {
+ constructor(config: ChatConfig, agents: AgentConfig[], tts: TTSClient | null) {
+ this.agents = agents;
this.clients = [];
this.config = config;
this.tts = tts;
diff --git a/webapp/src/html/index.html b/webapp/src/html/index.html
index 1cdbd41..0113958 100644
--- a/webapp/src/html/index.html
+++ b/webapp/src/html/index.html
@@ -32,6 +32,9 @@
+
diff --git a/webapp/src/ts/client.ts b/webapp/src/ts/client.ts
index 60817d7..6144620 100644
--- a/webapp/src/ts/client.ts
+++ b/webapp/src/ts/client.ts
@@ -1,6 +1,7 @@
import { createNanoEvents, Emitter, Unsubscribe } from 'nanoevents';
import { MSAgentAddUserMessage, MSAgentChatMessage, MSAgentInitMessage, MSAgentJoinMessage, MSAgentProtocolMessage, MSAgentProtocolMessageType, MSAgentRemoveUserMessage, MSAgentTalkMessage } from '@msagent-chat/protocol';
import { User } from './user';
+import { agentCreateCharacterFromUrl } from '@msagent-chat/msagent.js';
export interface MSAgentClientEvents {
close: () => void;
@@ -10,6 +11,11 @@ export interface MSAgentClientEvents {
chat: (user: User, msg: string) => void;
}
+export interface APIAgentInfo {
+ friendlyName: string;
+ filename: string;
+}
+
export class MSAgentClient {
private url: string;
private socket: WebSocket | null;
@@ -19,10 +25,12 @@ export class MSAgentClient {
private charlimit: number = 0;
private username: string | null = null;
+ private agentContainer: HTMLElement;
private agent: string | null = null;
- constructor(url: string) {
+ constructor(url: string, agentContainer: HTMLElement) {
this.url = url;
+ this.agentContainer = agentContainer;
this.socket = null;
this.events = createNanoEvents();
this.users = [];
@@ -32,6 +40,11 @@ export class MSAgentClient {
return this.events.on(event, callback);
}
+ async getAgents() {
+ let res = await fetch(this.url + "/api/agents");
+ return await res.json() as APIAgentInfo[];
+ }
+
connect(): Promise {
return new Promise(res => {
let url = new URL(this.url);
@@ -104,7 +117,7 @@ export class MSAgentClient {
return this.charlimit;
}
- private handleMessage(data: string) {
+ private async handleMessage(data: string) {
let msg: MSAgentProtocolMessage;
try {
msg = JSON.parse(data);
@@ -118,13 +131,22 @@ export class MSAgentClient {
this.username = initMsg.data.username;
this.agent = initMsg.data.agent;
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');
break;
}
case MSAgentProtocolMessageType.AddUser: {
- let addUserMsg = msg as MSAgentAddUserMessage
- let user = new User(addUserMsg.data.username, addUserMsg.data.agent);
+ let addUserMsg = msg as MSAgentAddUserMessage;
+ 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.events.emit('adduser', user);
break;
@@ -133,6 +155,7 @@ export class MSAgentClient {
let remUserMsg = msg as MSAgentRemoveUserMessage;
let user = this.users.find(u => u.username === remUserMsg.data.username);
if (!user) return;
+ user.agent.hide(true);
if (this.playingAudio.has(user!.username)) {
this.playingAudio.delete(user!.username);
}
diff --git a/webapp/src/ts/main.ts b/webapp/src/ts/main.ts
index 514c490..94c84ab 100644
--- a/webapp/src/ts/main.ts
+++ b/webapp/src/ts/main.ts
@@ -2,19 +2,21 @@ import { MSWindow, MSWindowStartPosition } from "./MSWindow.js";
import { agentInit } from "@msagent-chat/msagent.js";
import { MSAgentClient } from "./client.js";
-let Room : MSAgentClient | null = null;
const elements = {
logonView: document.getElementById("logonView") as HTMLDivElement,
logonWindow: document.getElementById("logonWindow") as HTMLDivElement,
logonForm: document.getElementById("logonForm") as HTMLFormElement,
logonUsername: document.getElementById("logonUsername") as HTMLInputElement,
+ agentSelect: document.getElementById("agentSelect") as HTMLSelectElement,
chatView: document.getElementById("chatView") as HTMLDivElement,
chatInput: document.getElementById("chatInput") as HTMLInputElement,
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, {
width: 500,
height: 275,
@@ -39,9 +41,12 @@ elements.chatSendBtn.addEventListener('click', () => {
});
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.join(elements.logonUsername.value, "test");
+ await Room.join(elements.logonUsername.value, elements.agentSelect.value);
elements.chatInput.maxLength = Room.getCharlimit();
logonWindow.hide();
elements.logonView.style.display = "none";
@@ -50,6 +55,12 @@ async function connectToRoom() {
document.addEventListener('DOMContentLoaded', async () => {
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() {
diff --git a/webapp/src/ts/user.ts b/webapp/src/ts/user.ts
index 6b5f588..58e6dc3 100644
--- a/webapp/src/ts/user.ts
+++ b/webapp/src/ts/user.ts
@@ -1,8 +1,10 @@
+import { Agent } from "@msagent-chat/msagent.js";
+
export class User {
username: string;
- agent: string;
+ agent: Agent
- constructor(username: string, agent: string) {
+ constructor(username: string, agent: Agent) {
this.username = username;
this.agent = agent;
}