Merge pull request #24 from multica-ai/ldnvnbl/hub-gateway-config
Add gateway URL configuration to Hub Console
This commit is contained in:
commit
1bf2b47fca
3 changed files with 61 additions and 9 deletions
|
|
@ -2,6 +2,7 @@ import {
|
|||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Delete,
|
||||
Param,
|
||||
Body,
|
||||
|
|
@ -23,6 +24,15 @@ export class AppController {
|
|||
};
|
||||
}
|
||||
|
||||
@Put("hub/gateway")
|
||||
updateGateway(@Body() body: { url: string }) {
|
||||
this.hub.reconnect(body.url);
|
||||
return {
|
||||
url: this.hub.url,
|
||||
connectionState: this.hub.connectionState,
|
||||
};
|
||||
}
|
||||
|
||||
@Get("agents")
|
||||
listAgents() {
|
||||
return this.hub.listAgents().map((id) => {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@
|
|||
.agent-list { list-style: none; }
|
||||
.agent-list li { display: flex; justify-content: space-between; align-items: center; padding: 0.6rem 0; border-bottom: 1px solid #222; font-family: monospace; font-size: 0.85rem; }
|
||||
.agent-list li:last-child { border-bottom: none; }
|
||||
.gateway-form { display: flex; gap: 0.5rem; align-items: center; margin-top: 0.8rem; }
|
||||
.gateway-form input { background: #0a0a0a; color: #e0e0e0; border: 1px solid #444; border-radius: 4px; padding: 0.4rem 0.6rem; font-size: 0.85rem; font-family: monospace; flex: 1; }
|
||||
.gateway-form input:focus { outline: none; border-color: #666; }
|
||||
button { background: #2a2a2a; color: #e0e0e0; border: 1px solid #444; border-radius: 4px; padding: 0.4rem 0.8rem; cursor: pointer; font-size: 0.8rem; }
|
||||
button:hover { background: #3a3a3a; }
|
||||
.btn-create { background: #1a3a1a; border-color: #2a5a2a; }
|
||||
|
|
@ -30,6 +33,10 @@
|
|||
<div class="card">
|
||||
<h2>Hub Status</h2>
|
||||
<div class="hub-info" id="hub-info">Loading...</div>
|
||||
<div class="gateway-form">
|
||||
<input type="text" id="gateway-url" placeholder="Gateway URL">
|
||||
<button class="btn-create" onclick="updateGateway()">Connect</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
|
|
@ -56,6 +63,11 @@
|
|||
`<span>State: <b style="color:${stateColor}">${hubRes.connectionState}</b></span>` +
|
||||
`<span>Agents: <b>${hubRes.agentCount}</b></span>`;
|
||||
|
||||
const input = document.getElementById('gateway-url');
|
||||
if (!input.dataset.edited) {
|
||||
input.value = hubRes.url;
|
||||
}
|
||||
|
||||
const list = document.getElementById('agent-list');
|
||||
if (agentsRes.length === 0) {
|
||||
list.innerHTML = '<li class="empty">No agents</li>';
|
||||
|
|
@ -66,6 +78,23 @@
|
|||
}
|
||||
}
|
||||
|
||||
document.getElementById('gateway-url').addEventListener('input', function() {
|
||||
this.dataset.edited = '1';
|
||||
});
|
||||
|
||||
async function updateGateway() {
|
||||
const input = document.getElementById('gateway-url');
|
||||
const url = input.value.trim();
|
||||
if (!url) return;
|
||||
await fetch(`${API}/hub/gateway`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ url }),
|
||||
});
|
||||
input.dataset.edited = '';
|
||||
refresh();
|
||||
}
|
||||
|
||||
async function createAgent() {
|
||||
await fetch(`${API}/agents`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' });
|
||||
refresh();
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import { GatewayClient } from "../shared/gateway-sdk/client.js";
|
|||
export class Hub {
|
||||
private readonly agents = new Map<string, Agent>();
|
||||
private readonly agentSenders = new Map<string, string>();
|
||||
private readonly client: GatewayClient;
|
||||
readonly url: string;
|
||||
private client: GatewayClient;
|
||||
url: string;
|
||||
readonly path: string;
|
||||
readonly deviceId: string;
|
||||
|
||||
|
|
@ -21,9 +21,13 @@ export class Hub {
|
|||
this.url = url;
|
||||
this.path = path ?? "/ws";
|
||||
this.deviceId = getDeviceId();
|
||||
this.client = this.createClient(this.url);
|
||||
this.client.connect();
|
||||
}
|
||||
|
||||
this.client = new GatewayClient({
|
||||
url: this.url,
|
||||
private createClient(url: string): GatewayClient {
|
||||
const client = new GatewayClient({
|
||||
url,
|
||||
path: this.path,
|
||||
deviceId: this.deviceId,
|
||||
deviceType: "client",
|
||||
|
|
@ -31,19 +35,19 @@ export class Hub {
|
|||
reconnectDelay: 1000,
|
||||
});
|
||||
|
||||
this.client.onStateChange((state) => {
|
||||
client.onStateChange((state) => {
|
||||
console.log(`[Hub] Connection state: ${state}`);
|
||||
});
|
||||
|
||||
this.client.onRegistered((deviceId) => {
|
||||
client.onRegistered((deviceId) => {
|
||||
console.log(`[Hub] Registered as: ${deviceId}`);
|
||||
});
|
||||
|
||||
this.client.onError((err) => {
|
||||
client.onError((err) => {
|
||||
console.error(`[Hub] Connection error:`, err.message);
|
||||
});
|
||||
|
||||
this.client.onMessage((msg) => {
|
||||
client.onMessage((msg) => {
|
||||
console.log(`[Hub] Received message: id=${msg.id} from=${msg.from} to=${msg.to} action=${msg.action} payload=${JSON.stringify(msg.payload)}`);
|
||||
const payload = msg.payload as { agentId?: string; content?: string } | undefined;
|
||||
const agentId = payload?.agentId;
|
||||
|
|
@ -61,10 +65,19 @@ export class Hub {
|
|||
}
|
||||
});
|
||||
|
||||
this.client.onSendError((err) => {
|
||||
client.onSendError((err) => {
|
||||
console.error(`[Hub] Send error: messageId=${err.messageId} code=${err.code} error=${err.error}`);
|
||||
});
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
/** 重连到新的 Gateway 地址 */
|
||||
reconnect(url: string): void {
|
||||
console.log(`[Hub] Reconnecting to ${url}`);
|
||||
this.client.disconnect();
|
||||
this.url = url;
|
||||
this.client = this.createClient(url);
|
||||
this.client.connect();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue