@teneo-protocol/sdk 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +11 -2
- package/.github/CODEOWNERS +2 -0
- package/.github/ISSUE_TEMPLATE/01-bug.yml +85 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
- package/.github/workflows/claude-code-review.yml +8 -3
- package/.github/workflows/claude-reviewer.yml +6 -4
- package/.github/workflows/publish-npm.yml +1 -0
- package/.github/workflows/push-to-main.yml +1 -1
- package/.github/workflows/top-issue.yml +102 -0
- package/CHANGELOG.md +69 -0
- package/CONCEPTS.md +747 -0
- package/README.md +178 -8
- package/dist/constants.js +8 -8
- package/dist/constants.js.map +1 -1
- package/dist/core/websocket-client.d.ts +15 -3
- package/dist/core/websocket-client.d.ts.map +1 -1
- package/dist/core/websocket-client.js +52 -13
- package/dist/core/websocket-client.js.map +1 -1
- package/dist/formatters/response-formatter.js +4 -0
- package/dist/formatters/response-formatter.js.map +1 -1
- package/dist/handlers/message-handler-registry.js +2 -1
- package/dist/handlers/message-handler-registry.js.map +1 -1
- package/dist/handlers/message-handlers/agent-details-response-handler.d.ts +1666 -0
- package/dist/handlers/message-handlers/agent-details-response-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/agent-details-response-handler.js +38 -0
- package/dist/handlers/message-handlers/agent-details-response-handler.js.map +1 -0
- package/dist/handlers/message-handlers/agent-room-operation-response-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/agent-room-operation-response-handler.js +2 -5
- package/dist/handlers/message-handlers/agent-room-operation-response-handler.js.map +1 -1
- package/dist/handlers/message-handlers/agent-selected-handler.js +2 -5
- package/dist/handlers/message-handlers/agent-selected-handler.js.map +1 -1
- package/dist/handlers/message-handlers/agent-status-update-handler.d.ts +783 -0
- package/dist/handlers/message-handlers/agent-status-update-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/agent-status-update-handler.js +2 -5
- package/dist/handlers/message-handlers/agent-status-update-handler.js.map +1 -1
- package/dist/handlers/message-handlers/agents-list-handler.js +2 -5
- package/dist/handlers/message-handlers/agents-list-handler.js.map +1 -1
- package/dist/handlers/message-handlers/all-agents-response-handler.d.ts +439 -0
- package/dist/handlers/message-handlers/all-agents-response-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/all-agents-response-handler.js +36 -0
- package/dist/handlers/message-handlers/all-agents-response-handler.js.map +1 -0
- package/dist/handlers/message-handlers/auth-error-handler.js +2 -5
- package/dist/handlers/message-handlers/auth-error-handler.js.map +1 -1
- package/dist/handlers/message-handlers/auth-message-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/auth-message-handler.js +6 -5
- package/dist/handlers/message-handlers/auth-message-handler.js.map +1 -1
- package/dist/handlers/message-handlers/auth-required-handler.js +2 -5
- package/dist/handlers/message-handlers/auth-required-handler.js.map +1 -1
- package/dist/handlers/message-handlers/auth-success-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/auth-success-handler.js +6 -5
- package/dist/handlers/message-handlers/auth-success-handler.js.map +1 -1
- package/dist/handlers/message-handlers/base-handler.d.ts +4 -4
- package/dist/handlers/message-handlers/base-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/base-handler.js +3 -1
- package/dist/handlers/message-handlers/base-handler.js.map +1 -1
- package/dist/handlers/message-handlers/challenge-handler.js +3 -2
- package/dist/handlers/message-handlers/challenge-handler.js.map +1 -1
- package/dist/handlers/message-handlers/error-message-handler.js +2 -5
- package/dist/handlers/message-handlers/error-message-handler.js.map +1 -1
- package/dist/handlers/message-handlers/index.d.ts +6 -0
- package/dist/handlers/message-handlers/index.d.ts.map +1 -1
- package/dist/handlers/message-handlers/index.js +33 -1
- package/dist/handlers/message-handlers/index.js.map +1 -1
- package/dist/handlers/message-handlers/list-available-agents-handler.d.ts +783 -0
- package/dist/handlers/message-handlers/list-available-agents-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/list-available-agents-handler.js +2 -5
- package/dist/handlers/message-handlers/list-available-agents-handler.js.map +1 -1
- package/dist/handlers/message-handlers/list-room-agents-handler.d.ts +783 -0
- package/dist/handlers/message-handlers/list-room-agents-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/list-room-agents-handler.js +2 -5
- package/dist/handlers/message-handlers/list-room-agents-handler.js.map +1 -1
- package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts +2 -199
- package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/list-rooms-response-handler.js +4 -6
- package/dist/handlers/message-handlers/list-rooms-response-handler.js.map +1 -1
- package/dist/handlers/message-handlers/ping-pong-handler.js +4 -10
- package/dist/handlers/message-handlers/ping-pong-handler.js.map +1 -1
- package/dist/handlers/message-handlers/rate-limit-notification-handler.d.ts +94 -0
- package/dist/handlers/message-handlers/rate-limit-notification-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/rate-limit-notification-handler.js +35 -0
- package/dist/handlers/message-handlers/rate-limit-notification-handler.js.map +1 -0
- package/dist/handlers/message-handlers/regular-message-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/regular-message-handler.js +4 -6
- package/dist/handlers/message-handlers/regular-message-handler.js.map +1 -1
- package/dist/handlers/message-handlers/room-operation-response-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/room-operation-response-handler.js +2 -5
- package/dist/handlers/message-handlers/room-operation-response-handler.js.map +1 -1
- package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/subscribe-response-handler.js +4 -6
- package/dist/handlers/message-handlers/subscribe-response-handler.js.map +1 -1
- package/dist/handlers/message-handlers/task-quote-handler.d.ts +14 -0
- package/dist/handlers/message-handlers/task-quote-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/task-quote-handler.js +29 -0
- package/dist/handlers/message-handlers/task-quote-handler.js.map +1 -0
- package/dist/handlers/message-handlers/task-response-handler.js +2 -5
- package/dist/handlers/message-handlers/task-response-handler.js.map +1 -1
- package/dist/handlers/message-handlers/types.d.ts +21 -9
- package/dist/handlers/message-handlers/types.d.ts.map +1 -1
- package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/unsubscribe-response-handler.js +4 -6
- package/dist/handlers/message-handlers/unsubscribe-response-handler.js.map +1 -1
- package/dist/handlers/message-handlers/user-authenticated-handler.d.ts +40 -0
- package/dist/handlers/message-handlers/user-authenticated-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/user-authenticated-handler.js +28 -0
- package/dist/handlers/message-handlers/user-authenticated-handler.js.map +1 -0
- package/dist/handlers/message-handlers/user-count-handler.d.ts +49 -0
- package/dist/handlers/message-handlers/user-count-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/user-count-handler.js +31 -0
- package/dist/handlers/message-handlers/user-count-handler.js.map +1 -0
- package/dist/handlers/webhook-handler.d.ts +1 -1
- package/dist/handlers/webhook-handler.d.ts.map +1 -1
- package/dist/handlers/webhook-handler.js +14 -5
- package/dist/handlers/webhook-handler.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/managers/admin-manager.d.ts +116 -0
- package/dist/managers/admin-manager.d.ts.map +1 -0
- package/dist/managers/admin-manager.js +169 -0
- package/dist/managers/admin-manager.js.map +1 -0
- package/dist/managers/agent-registry.d.ts +52 -1
- package/dist/managers/agent-registry.d.ts.map +1 -1
- package/dist/managers/agent-registry.js +145 -6
- package/dist/managers/agent-registry.js.map +1 -1
- package/dist/managers/agent-room-manager.d.ts +1 -7
- package/dist/managers/agent-room-manager.d.ts.map +1 -1
- package/dist/managers/agent-room-manager.js +83 -36
- package/dist/managers/agent-room-manager.js.map +1 -1
- package/dist/managers/connection-manager.js +2 -0
- package/dist/managers/connection-manager.js.map +1 -1
- package/dist/managers/index.d.ts +2 -1
- package/dist/managers/index.d.ts.map +1 -1
- package/dist/managers/index.js +3 -1
- package/dist/managers/index.js.map +1 -1
- package/dist/managers/message-router.d.ts +56 -5
- package/dist/managers/message-router.d.ts.map +1 -1
- package/dist/managers/message-router.js +155 -8
- package/dist/managers/message-router.js.map +1 -1
- package/dist/managers/room-management-manager.d.ts.map +1 -1
- package/dist/managers/room-management-manager.js +9 -7
- package/dist/managers/room-management-manager.js.map +1 -1
- package/dist/managers/room-manager.d.ts +7 -5
- package/dist/managers/room-manager.d.ts.map +1 -1
- package/dist/managers/room-manager.js +14 -10
- package/dist/managers/room-manager.js.map +1 -1
- package/dist/payments/index.d.ts +5 -0
- package/dist/payments/index.d.ts.map +1 -0
- package/dist/payments/index.js +21 -0
- package/dist/payments/index.js.map +1 -0
- package/dist/payments/payment-client.d.ts +74 -0
- package/dist/payments/payment-client.d.ts.map +1 -0
- package/dist/payments/payment-client.js +207 -0
- package/dist/payments/payment-client.js.map +1 -0
- package/dist/teneo-sdk.d.ts +135 -21
- package/dist/teneo-sdk.d.ts.map +1 -1
- package/dist/teneo-sdk.js +268 -26
- package/dist/teneo-sdk.js.map +1 -1
- package/dist/types/categories.d.ts +22 -0
- package/dist/types/categories.d.ts.map +1 -0
- package/dist/types/categories.js +40 -0
- package/dist/types/categories.js.map +1 -0
- package/dist/types/config.d.ts +79 -8
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +62 -5
- package/dist/types/config.js.map +1 -1
- package/dist/types/error-codes.d.ts +8 -0
- package/dist/types/error-codes.d.ts.map +1 -1
- package/dist/types/error-codes.js +9 -0
- package/dist/types/error-codes.js.map +1 -1
- package/dist/types/events.d.ts +44 -0
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/events.js +19 -1
- package/dist/types/events.js.map +1 -1
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +33 -3
- package/dist/types/index.js.map +1 -1
- package/dist/types/messages.d.ts +11219 -423
- package/dist/types/messages.d.ts.map +1 -1
- package/dist/types/messages.js +249 -7
- package/dist/types/messages.js.map +1 -1
- package/dist/utils/bounded-queue.d.ts.map +1 -1
- package/dist/utils/bounded-queue.js +5 -2
- package/dist/utils/bounded-queue.js.map +1 -1
- package/dist/utils/circuit-breaker.js +11 -4
- package/dist/utils/circuit-breaker.js.map +1 -1
- package/dist/utils/deduplication-cache.js +3 -1
- package/dist/utils/deduplication-cache.js.map +1 -1
- package/dist/utils/event-waiter.d.ts +3 -3
- package/dist/utils/event-waiter.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/pricing-resolver.d.ts +26 -0
- package/dist/utils/pricing-resolver.d.ts.map +1 -0
- package/dist/utils/pricing-resolver.js +85 -0
- package/dist/utils/pricing-resolver.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -1
- package/dist/utils/rate-limiter.js +6 -0
- package/dist/utils/rate-limiter.js.map +1 -1
- package/dist/utils/retry-policy.js +1 -0
- package/dist/utils/retry-policy.js.map +1 -1
- package/dist/utils/secure-private-key.js +3 -1
- package/dist/utils/secure-private-key.js.map +1 -1
- package/dist/utils/signature-verifier.d.ts.map +1 -1
- package/dist/utils/signature-verifier.js +3 -1
- package/dist/utils/signature-verifier.js.map +1 -1
- package/examples/.env.example +1 -1
- package/examples/agent-room-management-example.ts +10 -9
- package/examples/basic-usage.ts +3 -4
- package/examples/claude-agent-x-follower/.env.example +1 -1
- package/examples/claude-agent-x-follower/QUICKSTART.md +2 -2
- package/examples/claude-agent-x-follower/README.md +2 -2
- package/examples/claude-agent-x-follower/index.ts +120 -96
- package/examples/n8n-teneo/.env.example +1 -1
- package/examples/n8n-teneo/README.md +1 -1
- package/examples/n8n-teneo/index.ts +54 -44
- package/examples/nestjs-dashboard/.env.example +11 -0
- package/examples/nestjs-dashboard/README.md +297 -0
- package/examples/nestjs-dashboard/nest-cli.json +10 -0
- package/examples/nestjs-dashboard/package.json +44 -0
- package/examples/nestjs-dashboard/pnpm-lock.yaml +3079 -0
- package/examples/nestjs-dashboard/src/app.controller.ts +24 -0
- package/examples/nestjs-dashboard/src/app.module.ts +15 -0
- package/examples/nestjs-dashboard/src/main.ts +32 -0
- package/examples/nestjs-dashboard/src/public/dashboard.html +1144 -0
- package/examples/nestjs-dashboard/src/teneo/agents.controller.ts +54 -0
- package/examples/nestjs-dashboard/src/teneo/events.controller.ts +65 -0
- package/examples/nestjs-dashboard/src/teneo/messages.controller.ts +47 -0
- package/examples/nestjs-dashboard/src/teneo/rooms.controller.ts +258 -0
- package/examples/nestjs-dashboard/src/teneo/teneo.module.ts +13 -0
- package/examples/nestjs-dashboard/src/teneo/teneo.service.ts +484 -0
- package/examples/nestjs-dashboard/tsconfig.json +22 -0
- package/examples/openai-teneo/.env.example +1 -1
- package/examples/openai-teneo/README.md +2 -2
- package/examples/openai-teneo/index.ts +82 -71
- package/examples/production-dashboard/.env.example +1 -1
- package/examples/production-dashboard/README.md +1 -1
- package/examples/production-dashboard/server.ts +2 -2
- package/examples/room-management-example.ts +5 -8
- package/examples/usage/.env.example +1 -1
- package/examples/usage/01-connect.ts +3 -4
- package/examples/usage/02-list-agents.ts +2 -3
- package/examples/usage/03-pick-agent.ts +2 -3
- package/examples/usage/04-find-by-capability.ts +2 -3
- package/examples/usage/05-webhook-example.ts +2 -3
- package/examples/usage/06-simple-api-server.ts +2 -3
- package/examples/usage/07-event-listener.ts +2 -3
- package/examples/webhook-integration.ts +1 -1
- package/examples/x-influencer-battle-server.ts +2 -2
- package/package.json +4 -1
- package/src/core/websocket-client.test.ts +8 -3
- package/src/core/websocket-client.ts +36 -6
- package/src/formatters/response-formatter.test.ts +2 -0
- package/src/formatters/response-formatter.ts +3 -3
- package/src/handlers/message-handlers/agent-details-response-handler.ts +42 -0
- package/src/handlers/message-handlers/agent-room-operation-response-handler.ts +2 -8
- package/src/handlers/message-handlers/agent-status-update-handler.ts +3 -9
- package/src/handlers/message-handlers/all-agents-response-handler.ts +39 -0
- package/src/handlers/message-handlers/auth-message-handler.ts +5 -0
- package/src/handlers/message-handlers/auth-success-handler.ts +6 -1
- package/src/handlers/message-handlers/base-handler.ts +20 -7
- package/src/handlers/message-handlers/index.ts +34 -0
- package/src/handlers/message-handlers/list-room-agents-handler.ts +2 -5
- package/src/handlers/message-handlers/list-rooms-response-handler.ts +4 -2
- package/src/handlers/message-handlers/rate-limit-notification-handler.ts +45 -0
- package/src/handlers/message-handlers/regular-message-handler.ts +3 -2
- package/src/handlers/message-handlers/room-operation-response-handler.ts +3 -6
- package/src/handlers/message-handlers/subscribe-response-handler.ts +12 -2
- package/src/handlers/message-handlers/task-quote-handler.ts +31 -0
- package/src/handlers/message-handlers/types.ts +37 -9
- package/src/handlers/message-handlers/unsubscribe-response-handler.ts +12 -2
- package/src/handlers/message-handlers/user-authenticated-handler.ts +31 -0
- package/src/handlers/message-handlers/user-count-handler.ts +34 -0
- package/src/handlers/webhook-handler.test.ts +3 -2
- package/src/handlers/webhook-handler.ts +13 -7
- package/src/index.ts +21 -0
- package/src/managers/admin-manager.ts +249 -0
- package/src/managers/agent-registry.test.ts +2 -1
- package/src/managers/agent-registry.ts +170 -2
- package/src/managers/agent-room-manager.ts +98 -42
- package/src/managers/index.ts +13 -1
- package/src/managers/message-router.ts +215 -17
- package/src/managers/room-management-manager.ts +4 -7
- package/src/managers/room-manager.ts +11 -15
- package/src/payments/index.ts +22 -0
- package/src/payments/payment-client.ts +240 -0
- package/src/teneo-sdk.ts +302 -27
- package/src/types/categories.ts +45 -0
- package/src/types/config.ts +70 -2
- package/src/types/error-codes.ts +10 -0
- package/src/types/events.test.ts +1 -0
- package/src/types/events.ts +43 -0
- package/src/types/index.ts +56 -0
- package/src/types/messages.test.ts +2 -1
- package/src/types/messages.ts +307 -5
- package/src/utils/bounded-queue.test.ts +1 -1
- package/src/utils/bounded-queue.ts +2 -1
- package/src/utils/circuit-breaker.test.ts +1 -1
- package/src/utils/deduplication-cache.test.ts +1 -1
- package/src/utils/event-waiter.test.ts +1 -1
- package/src/utils/event-waiter.ts +3 -3
- package/src/utils/index.ts +7 -0
- package/src/utils/logger.ts +8 -8
- package/src/utils/pricing-resolver.ts +128 -0
- package/src/utils/rate-limiter.test.ts +1 -1
- package/src/utils/rate-limiter.ts +1 -0
- package/src/utils/signature-verifier.test.ts +2 -2
- package/src/utils/signature-verifier.ts +3 -2
- package/tests/.env.example +7 -0
- package/tests/direct-agent-test.ts +151 -0
- package/tests/integration/real-server.test.ts +2 -0
- package/tests/integration/room-management.test.ts +10 -8
- package/tests/integration/websocket.test.ts +4 -1
- package/tests/payment-flow-test.ts +147 -0
- package/tests/unit/handlers/agent-room-operation-response-handler.test.ts +17 -29
- package/tests/unit/handlers/agent-status-update-handler.test.ts +2 -6
- package/tests/unit/handlers/auth-success-handler-rooms.test.ts +1 -3
- package/tests/unit/handlers/list-available-agents-handler.test.ts +4 -12
- package/tests/unit/handlers/list-room-agents-handler.test.ts +2 -6
- package/tests/unit/handlers/room-operation-response-handler.test.ts +9 -36
- package/tests/unit/managers/agent-room-manager.test.ts +9 -16
- package/tests/unit/managers/room-management-manager.test.ts +21 -39
- package/tsconfig.json +2 -2
- package/vitest.config.ts +1 -0
|
@@ -0,0 +1,1144 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Teneo SDK - NestJS Dashboard</title>
|
|
7
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
8
|
+
<style>
|
|
9
|
+
.status-dot {
|
|
10
|
+
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
11
|
+
}
|
|
12
|
+
@keyframes pulse {
|
|
13
|
+
0%,
|
|
14
|
+
100% {
|
|
15
|
+
opacity: 1;
|
|
16
|
+
}
|
|
17
|
+
50% {
|
|
18
|
+
opacity: 0.5;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
.event-item {
|
|
22
|
+
animation: slideIn 0.3s ease-out;
|
|
23
|
+
}
|
|
24
|
+
@keyframes slideIn {
|
|
25
|
+
from {
|
|
26
|
+
opacity: 0;
|
|
27
|
+
transform: translateY(-10px);
|
|
28
|
+
}
|
|
29
|
+
to {
|
|
30
|
+
opacity: 1;
|
|
31
|
+
transform: translateY(0);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
.scrollbar-thin::-webkit-scrollbar {
|
|
35
|
+
width: 6px;
|
|
36
|
+
}
|
|
37
|
+
.scrollbar-thin::-webkit-scrollbar-track {
|
|
38
|
+
background: #1f2937;
|
|
39
|
+
}
|
|
40
|
+
.scrollbar-thin::-webkit-scrollbar-thumb {
|
|
41
|
+
background: #4b5563;
|
|
42
|
+
border-radius: 3px;
|
|
43
|
+
}
|
|
44
|
+
</style>
|
|
45
|
+
</head>
|
|
46
|
+
<body class="bg-gray-900 text-gray-100">
|
|
47
|
+
<div class="container mx-auto px-4 py-6 max-w-7xl">
|
|
48
|
+
<!-- Header -->
|
|
49
|
+
<div class="mb-8">
|
|
50
|
+
<h1
|
|
51
|
+
class="text-4xl font-bold mb-2 bg-gradient-to-r from-blue-400 to-purple-500 bg-clip-text text-transparent"
|
|
52
|
+
>
|
|
53
|
+
Teneo SDK NestJS Dashboard
|
|
54
|
+
</h1>
|
|
55
|
+
<p class="text-gray-400">NestJS integration example showcasing all SDK features</p>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<!-- Status Grid -->
|
|
59
|
+
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
|
|
60
|
+
<!-- Connection Status -->
|
|
61
|
+
<div class="bg-gray-800 rounded-lg p-4 border border-gray-700">
|
|
62
|
+
<div class="flex items-center justify-between mb-2">
|
|
63
|
+
<span class="text-gray-400 text-sm">Connection</span>
|
|
64
|
+
<div id="connection-dot" class="status-dot w-3 h-3 rounded-full bg-gray-500"></div>
|
|
65
|
+
</div>
|
|
66
|
+
<div id="connection-status" class="text-2xl font-bold text-gray-500">Loading...</div>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<!-- Auth Status -->
|
|
70
|
+
<div class="bg-gray-800 rounded-lg p-4 border border-gray-700">
|
|
71
|
+
<div class="flex items-center justify-between mb-2">
|
|
72
|
+
<span class="text-gray-400 text-sm">Authentication</span>
|
|
73
|
+
<div id="auth-dot" class="status-dot w-3 h-3 rounded-full bg-gray-500"></div>
|
|
74
|
+
</div>
|
|
75
|
+
<div id="auth-status" class="text-2xl font-bold text-gray-500">Loading...</div>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<!-- Agents Count -->
|
|
79
|
+
<div class="bg-gray-800 rounded-lg p-4 border border-gray-700">
|
|
80
|
+
<div class="flex items-center justify-between mb-2">
|
|
81
|
+
<span class="text-gray-400 text-sm">Agents</span>
|
|
82
|
+
<svg
|
|
83
|
+
class="w-5 h-5 text-blue-400"
|
|
84
|
+
fill="none"
|
|
85
|
+
stroke="currentColor"
|
|
86
|
+
viewBox="0 0 24 24"
|
|
87
|
+
>
|
|
88
|
+
<path
|
|
89
|
+
stroke-linecap="round"
|
|
90
|
+
stroke-linejoin="round"
|
|
91
|
+
stroke-width="2"
|
|
92
|
+
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
|
|
93
|
+
></path>
|
|
94
|
+
</svg>
|
|
95
|
+
</div>
|
|
96
|
+
<div id="agents-count" class="text-2xl font-bold">0</div>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<!-- Messages Count -->
|
|
100
|
+
<div class="bg-gray-800 rounded-lg p-4 border border-gray-700">
|
|
101
|
+
<div class="flex items-center justify-between mb-2">
|
|
102
|
+
<span class="text-gray-400 text-sm">Messages</span>
|
|
103
|
+
<svg
|
|
104
|
+
class="w-5 h-5 text-green-400"
|
|
105
|
+
fill="none"
|
|
106
|
+
stroke="currentColor"
|
|
107
|
+
viewBox="0 0 24 24"
|
|
108
|
+
>
|
|
109
|
+
<path
|
|
110
|
+
stroke-linecap="round"
|
|
111
|
+
stroke-linejoin="round"
|
|
112
|
+
stroke-width="2"
|
|
113
|
+
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
|
|
114
|
+
></path>
|
|
115
|
+
</svg>
|
|
116
|
+
</div>
|
|
117
|
+
<div id="messages-count" class="text-2xl font-bold">0</div>
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<!-- Main Content Grid -->
|
|
122
|
+
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
|
123
|
+
<!-- Send Message Panel -->
|
|
124
|
+
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700">
|
|
125
|
+
<h2 class="text-xl font-bold mb-4 flex items-center">
|
|
126
|
+
<svg
|
|
127
|
+
class="w-6 h-6 mr-2 text-blue-400"
|
|
128
|
+
fill="none"
|
|
129
|
+
stroke="currentColor"
|
|
130
|
+
viewBox="0 0 24 24"
|
|
131
|
+
>
|
|
132
|
+
<path
|
|
133
|
+
stroke-linecap="round"
|
|
134
|
+
stroke-linejoin="round"
|
|
135
|
+
stroke-width="2"
|
|
136
|
+
d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"
|
|
137
|
+
></path>
|
|
138
|
+
</svg>
|
|
139
|
+
Send Message
|
|
140
|
+
</h2>
|
|
141
|
+
<div class="mb-3">
|
|
142
|
+
<label for="room-select" class="block text-sm text-gray-400 mb-2">Select Room:</label>
|
|
143
|
+
<select
|
|
144
|
+
id="room-select"
|
|
145
|
+
class="w-full bg-gray-700 rounded-lg p-2 text-gray-100 border border-gray-600 focus:border-blue-500 focus:outline-none"
|
|
146
|
+
>
|
|
147
|
+
<option value="">Loading rooms...</option>
|
|
148
|
+
</select>
|
|
149
|
+
</div>
|
|
150
|
+
<textarea
|
|
151
|
+
id="message-input"
|
|
152
|
+
class="w-full bg-gray-700 rounded-lg p-3 mb-3 text-gray-100 border border-gray-600 focus:border-blue-500 focus:outline-none resize-none"
|
|
153
|
+
rows="3"
|
|
154
|
+
placeholder="Enter your message to agents..."
|
|
155
|
+
></textarea>
|
|
156
|
+
<div class="flex gap-3">
|
|
157
|
+
<button
|
|
158
|
+
id="send-message-btn"
|
|
159
|
+
class="flex-1 bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-lg transition disabled:opacity-50 disabled:cursor-not-allowed"
|
|
160
|
+
disabled
|
|
161
|
+
>
|
|
162
|
+
Send Message
|
|
163
|
+
</button>
|
|
164
|
+
<button
|
|
165
|
+
id="send-wait-btn"
|
|
166
|
+
class="flex-1 bg-purple-600 hover:bg-purple-700 text-white font-semibold py-2 px-4 rounded-lg transition disabled:opacity-50 disabled:cursor-not-allowed"
|
|
167
|
+
disabled
|
|
168
|
+
>
|
|
169
|
+
Send & Wait
|
|
170
|
+
</button>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
<!-- Health Status -->
|
|
175
|
+
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700">
|
|
176
|
+
<h2 class="text-xl font-bold mb-4 flex items-center">
|
|
177
|
+
<svg
|
|
178
|
+
class="w-6 h-6 mr-2 text-green-400"
|
|
179
|
+
fill="none"
|
|
180
|
+
stroke="currentColor"
|
|
181
|
+
viewBox="0 0 24 24"
|
|
182
|
+
>
|
|
183
|
+
<path
|
|
184
|
+
stroke-linecap="round"
|
|
185
|
+
stroke-linejoin="round"
|
|
186
|
+
stroke-width="2"
|
|
187
|
+
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
188
|
+
></path>
|
|
189
|
+
</svg>
|
|
190
|
+
System Health
|
|
191
|
+
</h2>
|
|
192
|
+
<div id="health-status" class="space-y-2">
|
|
193
|
+
<div class="flex justify-between items-center">
|
|
194
|
+
<span class="text-gray-400">Overall Status</span>
|
|
195
|
+
<span id="health-overall" class="text-gray-500">Loading...</span>
|
|
196
|
+
</div>
|
|
197
|
+
<div class="flex justify-between items-center">
|
|
198
|
+
<span class="text-gray-400">Connected</span>
|
|
199
|
+
<span id="health-connected" class="text-gray-500">-</span>
|
|
200
|
+
</div>
|
|
201
|
+
<div class="flex justify-between items-center">
|
|
202
|
+
<span class="text-gray-400">Authenticated</span>
|
|
203
|
+
<span id="health-auth" class="text-gray-500">-</span>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
</div>
|
|
208
|
+
|
|
209
|
+
<!-- Tabs -->
|
|
210
|
+
<div class="bg-gray-800 rounded-lg border border-gray-700 overflow-hidden">
|
|
211
|
+
<div class="flex border-b border-gray-700 overflow-x-auto">
|
|
212
|
+
<button
|
|
213
|
+
class="tab-btn active px-6 py-3 font-semibold whitespace-nowrap"
|
|
214
|
+
data-tab="agents"
|
|
215
|
+
>
|
|
216
|
+
Agents
|
|
217
|
+
</button>
|
|
218
|
+
<button class="tab-btn px-6 py-3 font-semibold whitespace-nowrap" data-tab="rooms">
|
|
219
|
+
Rooms
|
|
220
|
+
</button>
|
|
221
|
+
<button class="tab-btn px-6 py-3 font-semibold whitespace-nowrap" data-tab="room-mgmt">
|
|
222
|
+
Room Management
|
|
223
|
+
</button>
|
|
224
|
+
<button class="tab-btn px-6 py-3 font-semibold whitespace-nowrap" data-tab="agent-room">
|
|
225
|
+
Agent-Room
|
|
226
|
+
</button>
|
|
227
|
+
<button class="tab-btn px-6 py-3 font-semibold whitespace-nowrap" data-tab="messages">
|
|
228
|
+
Messages
|
|
229
|
+
</button>
|
|
230
|
+
<button class="tab-btn px-6 py-3 font-semibold whitespace-nowrap" data-tab="webhooks">
|
|
231
|
+
Webhooks
|
|
232
|
+
</button>
|
|
233
|
+
<button class="tab-btn px-6 py-3 font-semibold whitespace-nowrap" data-tab="events">
|
|
234
|
+
Events
|
|
235
|
+
</button>
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
<div class="p-6">
|
|
239
|
+
<!-- Agents Tab -->
|
|
240
|
+
<div id="agents-tab" class="tab-content">
|
|
241
|
+
<div id="agents-list" class="space-y-3 max-h-96 overflow-y-auto scrollbar-thin">
|
|
242
|
+
<p class="text-gray-500">Loading agents...</p>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
<!-- Rooms Tab -->
|
|
247
|
+
<div id="rooms-tab" class="tab-content hidden">
|
|
248
|
+
<div class="mb-4">
|
|
249
|
+
<input
|
|
250
|
+
id="room-id-input"
|
|
251
|
+
type="text"
|
|
252
|
+
class="bg-gray-700 rounded-lg p-2 text-gray-100 border border-gray-600 focus:border-blue-500 focus:outline-none"
|
|
253
|
+
placeholder="Room ID"
|
|
254
|
+
/>
|
|
255
|
+
<button
|
|
256
|
+
id="subscribe-room-btn"
|
|
257
|
+
class="ml-2 bg-green-600 hover:bg-green-700 text-white font-semibold py-2 px-4 rounded-lg transition"
|
|
258
|
+
>
|
|
259
|
+
Subscribe
|
|
260
|
+
</button>
|
|
261
|
+
</div>
|
|
262
|
+
<div id="rooms-list" class="space-y-3 max-h-80 overflow-y-auto scrollbar-thin">
|
|
263
|
+
<p class="text-gray-500">Loading rooms...</p>
|
|
264
|
+
</div>
|
|
265
|
+
</div>
|
|
266
|
+
|
|
267
|
+
<!-- Room Management Tab -->
|
|
268
|
+
<div id="room-mgmt-tab" class="tab-content hidden">
|
|
269
|
+
<!-- Room Limit Info -->
|
|
270
|
+
<div class="bg-gray-700 rounded-lg p-4 mb-4 border border-gray-600">
|
|
271
|
+
<div class="flex justify-between items-center">
|
|
272
|
+
<span class="text-gray-400">Room Capacity:</span>
|
|
273
|
+
<span id="room-limit-text" class="font-semibold">Loading...</span>
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
|
|
277
|
+
<!-- Create Room Form -->
|
|
278
|
+
<div class="bg-gray-700 rounded-lg p-4 mb-4 border border-gray-600">
|
|
279
|
+
<h3 class="font-semibold mb-3">Create New Room</h3>
|
|
280
|
+
<div class="space-y-2">
|
|
281
|
+
<input
|
|
282
|
+
id="new-room-name"
|
|
283
|
+
type="text"
|
|
284
|
+
placeholder="Room Name"
|
|
285
|
+
class="w-full bg-gray-800 rounded p-2 text-gray-100 border border-gray-600 focus:border-blue-500 focus:outline-none"
|
|
286
|
+
/>
|
|
287
|
+
<input
|
|
288
|
+
id="new-room-desc"
|
|
289
|
+
type="text"
|
|
290
|
+
placeholder="Description (optional)"
|
|
291
|
+
class="w-full bg-gray-800 rounded p-2 text-gray-100 border border-gray-600 focus:border-blue-500 focus:outline-none"
|
|
292
|
+
/>
|
|
293
|
+
<button
|
|
294
|
+
id="create-room-btn"
|
|
295
|
+
class="w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-lg transition"
|
|
296
|
+
>
|
|
297
|
+
Create Room
|
|
298
|
+
</button>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
<!-- Owned/Shared Rooms -->
|
|
303
|
+
<div>
|
|
304
|
+
<h3 class="font-semibold mb-2">Your Rooms</h3>
|
|
305
|
+
<div
|
|
306
|
+
id="managed-rooms-list"
|
|
307
|
+
class="space-y-2 max-h-96 overflow-y-auto scrollbar-thin"
|
|
308
|
+
>
|
|
309
|
+
<p class="text-gray-500">Loading...</p>
|
|
310
|
+
</div>
|
|
311
|
+
</div>
|
|
312
|
+
</div>
|
|
313
|
+
|
|
314
|
+
<!-- Agent-Room Management Tab -->
|
|
315
|
+
<div id="agent-room-tab" class="tab-content hidden">
|
|
316
|
+
<!-- Room Selector -->
|
|
317
|
+
<div class="bg-gray-700 rounded-lg p-4 mb-4 border border-gray-600">
|
|
318
|
+
<label class="block text-sm text-gray-400 mb-2">Select Room:</label>
|
|
319
|
+
<select
|
|
320
|
+
id="agent-room-select"
|
|
321
|
+
class="w-full bg-gray-800 rounded-lg p-2 text-gray-100 border border-gray-600 focus:border-blue-500 focus:outline-none"
|
|
322
|
+
>
|
|
323
|
+
<option value="">Select a room...</option>
|
|
324
|
+
</select>
|
|
325
|
+
</div>
|
|
326
|
+
|
|
327
|
+
<!-- Agents in Room -->
|
|
328
|
+
<div class="mb-4">
|
|
329
|
+
<div class="flex justify-between items-center mb-2">
|
|
330
|
+
<h3 class="font-semibold">Agents in Room</h3>
|
|
331
|
+
<span id="room-agents-count" class="text-sm text-gray-400">-</span>
|
|
332
|
+
</div>
|
|
333
|
+
<div id="room-agents-list" class="space-y-2 max-h-60 overflow-y-auto scrollbar-thin">
|
|
334
|
+
<p class="text-gray-500">Select a room first</p>
|
|
335
|
+
</div>
|
|
336
|
+
</div>
|
|
337
|
+
|
|
338
|
+
<!-- Available Agents -->
|
|
339
|
+
<div>
|
|
340
|
+
<div class="flex justify-between items-center mb-2">
|
|
341
|
+
<h3 class="font-semibold">Available to Add</h3>
|
|
342
|
+
<span id="available-agents-count" class="text-sm text-gray-400">-</span>
|
|
343
|
+
</div>
|
|
344
|
+
<div
|
|
345
|
+
id="available-agents-list"
|
|
346
|
+
class="space-y-2 max-h-60 overflow-y-auto scrollbar-thin"
|
|
347
|
+
>
|
|
348
|
+
<p class="text-gray-500">Select a room first</p>
|
|
349
|
+
</div>
|
|
350
|
+
</div>
|
|
351
|
+
</div>
|
|
352
|
+
|
|
353
|
+
<!-- Messages Tab -->
|
|
354
|
+
<div id="messages-tab" class="tab-content hidden">
|
|
355
|
+
<div id="messages-list" class="space-y-4 max-h-96 overflow-y-auto scrollbar-thin">
|
|
356
|
+
<p class="text-gray-500">No messages yet. Send a message to see it here!</p>
|
|
357
|
+
</div>
|
|
358
|
+
</div>
|
|
359
|
+
|
|
360
|
+
<!-- Webhooks Tab -->
|
|
361
|
+
<div id="webhooks-tab" class="tab-content hidden">
|
|
362
|
+
<div id="webhooks-list" class="space-y-3 max-h-96 overflow-y-auto scrollbar-thin">
|
|
363
|
+
<p class="text-gray-500">No webhooks received yet.</p>
|
|
364
|
+
</div>
|
|
365
|
+
</div>
|
|
366
|
+
|
|
367
|
+
<!-- Events Tab -->
|
|
368
|
+
<div id="events-tab" class="tab-content hidden">
|
|
369
|
+
<div id="events-list" class="space-y-2 max-h-96 overflow-y-auto scrollbar-thin">
|
|
370
|
+
<p class="text-gray-500">Waiting for events...</p>
|
|
371
|
+
</div>
|
|
372
|
+
</div>
|
|
373
|
+
</div>
|
|
374
|
+
</div>
|
|
375
|
+
</div>
|
|
376
|
+
|
|
377
|
+
<script>
|
|
378
|
+
// State
|
|
379
|
+
let connectionStatus = "disconnected";
|
|
380
|
+
let authStatus = "pending";
|
|
381
|
+
|
|
382
|
+
// Initialize
|
|
383
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
384
|
+
setupTabs();
|
|
385
|
+
setupEventSource();
|
|
386
|
+
loadInitialData();
|
|
387
|
+
setupMessageSending();
|
|
388
|
+
setupRoomManagement();
|
|
389
|
+
setupRoomManagementUI();
|
|
390
|
+
setupAgentRoomManagement();
|
|
391
|
+
startHealthCheck();
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// Tab management
|
|
395
|
+
function setupTabs() {
|
|
396
|
+
document.querySelectorAll(".tab-btn").forEach((btn) => {
|
|
397
|
+
btn.addEventListener("click", () => {
|
|
398
|
+
const tab = btn.dataset.tab;
|
|
399
|
+
document
|
|
400
|
+
.querySelectorAll(".tab-btn")
|
|
401
|
+
.forEach((b) => b.classList.remove("active", "bg-gray-700", "text-blue-400"));
|
|
402
|
+
document.querySelectorAll(".tab-content").forEach((c) => c.classList.add("hidden"));
|
|
403
|
+
btn.classList.add("active", "bg-gray-700", "text-blue-400");
|
|
404
|
+
document.getElementById(`${tab}-tab`).classList.remove("hidden");
|
|
405
|
+
|
|
406
|
+
// Load data when switching tabs
|
|
407
|
+
if (tab === "room-mgmt") {
|
|
408
|
+
loadRoomLimit();
|
|
409
|
+
loadManagedRooms();
|
|
410
|
+
}
|
|
411
|
+
if (tab === "agent-room") {
|
|
412
|
+
loadOwnedRooms().then((rooms) => {
|
|
413
|
+
populateAgentRoomSelector(rooms);
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Server-Sent Events
|
|
421
|
+
function setupEventSource() {
|
|
422
|
+
const eventSource = new EventSource("/api/sse");
|
|
423
|
+
|
|
424
|
+
eventSource.addEventListener("message", (e) => {
|
|
425
|
+
try {
|
|
426
|
+
const data = JSON.parse(e.data);
|
|
427
|
+
handleSSEEvent(data);
|
|
428
|
+
} catch (error) {
|
|
429
|
+
console.error("SSE parse error:", error);
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
eventSource.addEventListener("error", () => {
|
|
434
|
+
console.error("SSE connection error");
|
|
435
|
+
setTimeout(setupEventSource, 5000);
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function handleSSEEvent(data) {
|
|
440
|
+
switch (data.type) {
|
|
441
|
+
case "connection":
|
|
442
|
+
updateConnectionStatus(data.status);
|
|
443
|
+
break;
|
|
444
|
+
case "auth":
|
|
445
|
+
updateAuthStatus(data.status);
|
|
446
|
+
if (data.status === "success") {
|
|
447
|
+
setTimeout(loadAvailableRooms, 500);
|
|
448
|
+
}
|
|
449
|
+
break;
|
|
450
|
+
case "agent:selected":
|
|
451
|
+
addEventItem(`Agent Selected: ${data.data.agentName}`, "blue");
|
|
452
|
+
break;
|
|
453
|
+
case "agent:response":
|
|
454
|
+
addEventItem(`Agent Response from ${data.response.agentName}`, "green");
|
|
455
|
+
loadMessages();
|
|
456
|
+
break;
|
|
457
|
+
case "room:created":
|
|
458
|
+
addEventItem(`Room created: ${data.room.name}`, "green");
|
|
459
|
+
loadRoomLimit();
|
|
460
|
+
loadManagedRooms();
|
|
461
|
+
loadAvailableRooms();
|
|
462
|
+
break;
|
|
463
|
+
case "room:updated":
|
|
464
|
+
addEventItem(`Room updated: ${data.room.name}`, "blue");
|
|
465
|
+
loadManagedRooms();
|
|
466
|
+
break;
|
|
467
|
+
case "room:deleted":
|
|
468
|
+
addEventItem(`Room deleted`, "yellow");
|
|
469
|
+
loadRoomLimit();
|
|
470
|
+
loadManagedRooms();
|
|
471
|
+
break;
|
|
472
|
+
case "webhook:received":
|
|
473
|
+
addEventItem(`Webhook: ${data.payload.event}`, "purple");
|
|
474
|
+
loadWebhooks();
|
|
475
|
+
break;
|
|
476
|
+
case "error":
|
|
477
|
+
addEventItem(`Error: ${data.error.message}`, "red");
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function addEventItem(message, color) {
|
|
483
|
+
const list = document.getElementById("events-list");
|
|
484
|
+
const colorClass =
|
|
485
|
+
{
|
|
486
|
+
blue: "border-blue-500",
|
|
487
|
+
green: "border-green-500",
|
|
488
|
+
red: "border-red-500",
|
|
489
|
+
yellow: "border-yellow-500",
|
|
490
|
+
purple: "border-purple-500"
|
|
491
|
+
}[color] || "border-gray-500";
|
|
492
|
+
|
|
493
|
+
const item = document.createElement("div");
|
|
494
|
+
item.className = `event-item bg-gray-700 rounded p-2 border-l-4 ${colorClass}`;
|
|
495
|
+
item.innerHTML = `
|
|
496
|
+
<div class="flex items-center justify-between">
|
|
497
|
+
<span class="text-sm">${message}</span>
|
|
498
|
+
<span class="text-xs text-gray-400">${new Date().toLocaleTimeString()}</span>
|
|
499
|
+
</div>
|
|
500
|
+
`;
|
|
501
|
+
|
|
502
|
+
if (list.firstChild && list.firstChild.textContent.includes("Waiting for events")) {
|
|
503
|
+
list.innerHTML = "";
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
list.insertBefore(item, list.firstChild);
|
|
507
|
+
|
|
508
|
+
if (list.children.length > 50) {
|
|
509
|
+
list.removeChild(list.lastChild);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Load initial data
|
|
514
|
+
async function loadInitialData() {
|
|
515
|
+
await Promise.all([
|
|
516
|
+
loadAgents(),
|
|
517
|
+
loadRooms(),
|
|
518
|
+
loadAvailableRooms(),
|
|
519
|
+
loadRoomLimit(),
|
|
520
|
+
loadManagedRooms(),
|
|
521
|
+
loadEvents(),
|
|
522
|
+
loadWebhooks(),
|
|
523
|
+
loadMessages()
|
|
524
|
+
]);
|
|
525
|
+
updateHealthFromMetrics();
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Load agents
|
|
529
|
+
async function loadAgents() {
|
|
530
|
+
try {
|
|
531
|
+
const response = await fetch("/api/agents");
|
|
532
|
+
const agents = await response.json();
|
|
533
|
+
document.getElementById("agents-count").textContent = agents.length;
|
|
534
|
+
|
|
535
|
+
const list = document.getElementById("agents-list");
|
|
536
|
+
if (agents.length === 0) {
|
|
537
|
+
list.innerHTML = '<p class="text-gray-500">No agents available</p>';
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
list.innerHTML = agents
|
|
542
|
+
.map(
|
|
543
|
+
(agent) => `
|
|
544
|
+
<div class="bg-gray-700 rounded-lg p-4 border border-gray-600">
|
|
545
|
+
<div class="flex items-center justify-between mb-2">
|
|
546
|
+
<span class="font-semibold">${agent.name}</span>
|
|
547
|
+
<span class="text-xs px-2 py-1 rounded ${agent.status === "online" ? "bg-green-600" : "bg-gray-600"}">${agent.status || "unknown"}</span>
|
|
548
|
+
</div>
|
|
549
|
+
<p class="text-sm text-gray-400">${agent.description || "No description"}</p>
|
|
550
|
+
${
|
|
551
|
+
agent.capabilities
|
|
552
|
+
? `
|
|
553
|
+
<div class="mt-2 flex flex-wrap gap-1">
|
|
554
|
+
${agent.capabilities.map((cap) => `<span class="text-xs px-2 py-1 bg-blue-900 rounded">${cap.name}</span>`).join("")}
|
|
555
|
+
</div>
|
|
556
|
+
`
|
|
557
|
+
: ""
|
|
558
|
+
}
|
|
559
|
+
</div>
|
|
560
|
+
`
|
|
561
|
+
)
|
|
562
|
+
.join("");
|
|
563
|
+
} catch (error) {
|
|
564
|
+
console.error("Failed to load agents:", error);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Load rooms
|
|
569
|
+
async function loadRooms() {
|
|
570
|
+
try {
|
|
571
|
+
const response = await fetch("/api/rooms");
|
|
572
|
+
const rooms = await response.json();
|
|
573
|
+
|
|
574
|
+
const list = document.getElementById("rooms-list");
|
|
575
|
+
if (rooms.length === 0) {
|
|
576
|
+
list.innerHTML = '<p class="text-gray-500">No rooms available</p>';
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
list.innerHTML = rooms
|
|
581
|
+
.map(
|
|
582
|
+
(room) => `
|
|
583
|
+
<div class="bg-gray-700 rounded-lg p-4 border border-gray-600">
|
|
584
|
+
<div class="flex items-center justify-between">
|
|
585
|
+
<div>
|
|
586
|
+
<span class="font-semibold">${room.name || room.id}</span>
|
|
587
|
+
<p class="text-sm text-gray-400">${room.id}</p>
|
|
588
|
+
</div>
|
|
589
|
+
<button onclick="unsubscribeRoom('${room.id}')" class="bg-red-600 hover:bg-red-700 text-white text-sm py-1 px-3 rounded transition">
|
|
590
|
+
Unsubscribe
|
|
591
|
+
</button>
|
|
592
|
+
</div>
|
|
593
|
+
</div>
|
|
594
|
+
`
|
|
595
|
+
)
|
|
596
|
+
.join("");
|
|
597
|
+
} catch (error) {
|
|
598
|
+
console.error("Failed to load rooms:", error);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Load available rooms for sending messages
|
|
603
|
+
async function loadAvailableRooms() {
|
|
604
|
+
try {
|
|
605
|
+
const response = await fetch("/api/rooms/available");
|
|
606
|
+
const rooms = await response.json();
|
|
607
|
+
|
|
608
|
+
const select = document.getElementById("room-select");
|
|
609
|
+
const sendBtn = document.getElementById("send-message-btn");
|
|
610
|
+
const sendWaitBtn = document.getElementById("send-wait-btn");
|
|
611
|
+
|
|
612
|
+
if (rooms.length === 0) {
|
|
613
|
+
select.innerHTML =
|
|
614
|
+
'<option value="">No rooms available - Subscribe to a room first</option>';
|
|
615
|
+
sendBtn.disabled = true;
|
|
616
|
+
sendWaitBtn.disabled = true;
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const options = rooms
|
|
621
|
+
.map((room) => {
|
|
622
|
+
const typeLabel =
|
|
623
|
+
room.type === "private" ? "🔒" : room.type === "subscribed" ? "📌" : "🌐";
|
|
624
|
+
const displayName = room.name || room.id;
|
|
625
|
+
return `<option value="${room.id}">${typeLabel} ${displayName}</option>`;
|
|
626
|
+
})
|
|
627
|
+
.join("");
|
|
628
|
+
|
|
629
|
+
select.innerHTML = options;
|
|
630
|
+
sendBtn.disabled = false;
|
|
631
|
+
sendWaitBtn.disabled = false;
|
|
632
|
+
} catch (error) {
|
|
633
|
+
console.error("Failed to load available rooms:", error);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// Message sending
|
|
638
|
+
function setupMessageSending() {
|
|
639
|
+
document
|
|
640
|
+
.getElementById("send-message-btn")
|
|
641
|
+
.addEventListener("click", () => sendMessage(false));
|
|
642
|
+
document.getElementById("send-wait-btn").addEventListener("click", () => sendMessage(true));
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
async function sendMessage(waitForResponse) {
|
|
646
|
+
const input = document.getElementById("message-input");
|
|
647
|
+
const roomSelect = document.getElementById("room-select");
|
|
648
|
+
const content = input.value.trim();
|
|
649
|
+
const room = roomSelect.value;
|
|
650
|
+
|
|
651
|
+
if (!content || !room) return;
|
|
652
|
+
|
|
653
|
+
try {
|
|
654
|
+
const response = await fetch("/api/messages", {
|
|
655
|
+
method: "POST",
|
|
656
|
+
headers: { "Content-Type": "application/json" },
|
|
657
|
+
body: JSON.stringify({ content, room, waitForResponse })
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
const result = await response.json();
|
|
661
|
+
|
|
662
|
+
if (response.ok) {
|
|
663
|
+
input.value = "";
|
|
664
|
+
alert("Message sent successfully!");
|
|
665
|
+
} else {
|
|
666
|
+
alert(`Failed: ${result.error}`);
|
|
667
|
+
}
|
|
668
|
+
} catch (error) {
|
|
669
|
+
console.error("Send error:", error);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// Room management
|
|
674
|
+
function setupRoomManagement() {
|
|
675
|
+
document.getElementById("subscribe-room-btn").addEventListener("click", async () => {
|
|
676
|
+
const input = document.getElementById("room-id-input");
|
|
677
|
+
const roomId = input.value.trim();
|
|
678
|
+
|
|
679
|
+
if (!roomId) return;
|
|
680
|
+
|
|
681
|
+
try {
|
|
682
|
+
const response = await fetch("/api/rooms/join", {
|
|
683
|
+
method: "POST",
|
|
684
|
+
headers: { "Content-Type": "application/json" },
|
|
685
|
+
body: JSON.stringify({ roomId })
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
if (response.ok) {
|
|
689
|
+
input.value = "";
|
|
690
|
+
setTimeout(() => {
|
|
691
|
+
loadRooms();
|
|
692
|
+
loadAvailableRooms();
|
|
693
|
+
}, 500);
|
|
694
|
+
}
|
|
695
|
+
} catch (error) {
|
|
696
|
+
console.error("Subscribe room error:", error);
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
async function unsubscribeRoom(roomId) {
|
|
702
|
+
try {
|
|
703
|
+
const response = await fetch("/api/rooms/leave", {
|
|
704
|
+
method: "POST",
|
|
705
|
+
headers: { "Content-Type": "application/json" },
|
|
706
|
+
body: JSON.stringify({ roomId })
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
if (response.ok) {
|
|
710
|
+
setTimeout(() => {
|
|
711
|
+
loadRooms();
|
|
712
|
+
loadAvailableRooms();
|
|
713
|
+
}, 500);
|
|
714
|
+
}
|
|
715
|
+
} catch (error) {
|
|
716
|
+
console.error("Unsubscribe room error:", error);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// Room Management UI
|
|
721
|
+
async function loadRoomLimit() {
|
|
722
|
+
try {
|
|
723
|
+
const response = await fetch("/api/rooms/limit");
|
|
724
|
+
const data = await response.json();
|
|
725
|
+
|
|
726
|
+
const limitText = `${data.count}/${data.limit} ${data.canCreate ? "✅" : "⚠️"}`;
|
|
727
|
+
document.getElementById("room-limit-text").textContent = limitText;
|
|
728
|
+
} catch (error) {
|
|
729
|
+
console.error("Failed to load room limit:", error);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
async function loadManagedRooms() {
|
|
734
|
+
try {
|
|
735
|
+
const [ownedResponse, sharedResponse] = await Promise.all([
|
|
736
|
+
fetch("/api/rooms/owned"),
|
|
737
|
+
fetch("/api/rooms/shared")
|
|
738
|
+
]);
|
|
739
|
+
|
|
740
|
+
const ownedRooms = await ownedResponse.json();
|
|
741
|
+
const sharedRooms = await sharedResponse.json();
|
|
742
|
+
|
|
743
|
+
const allRooms = [...ownedRooms, ...sharedRooms];
|
|
744
|
+
|
|
745
|
+
const list = document.getElementById("managed-rooms-list");
|
|
746
|
+
if (allRooms.length === 0) {
|
|
747
|
+
list.innerHTML = '<p class="text-gray-500">No rooms yet</p>';
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
list.innerHTML = allRooms
|
|
752
|
+
.map(
|
|
753
|
+
(room) => `
|
|
754
|
+
<div class="bg-gray-800 rounded p-3 border border-gray-600">
|
|
755
|
+
<div class="flex justify-between items-start">
|
|
756
|
+
<div class="flex-1">
|
|
757
|
+
<div class="font-semibold">${room.name}</div>
|
|
758
|
+
<div class="text-xs text-gray-400">${room.id}</div>
|
|
759
|
+
${room.description ? `<div class="text-sm text-gray-400 mt-1">${room.description}</div>` : ""}
|
|
760
|
+
<div class="text-xs mt-1">
|
|
761
|
+
${room.is_public ? '<span class="px-2 py-1 rounded bg-blue-900">🌐 Public</span>' : '<span class="px-2 py-1 rounded bg-purple-900">🔒 Private</span>'}
|
|
762
|
+
</div>
|
|
763
|
+
</div>
|
|
764
|
+
<button onclick="deleteRoom('${room.id}')" class="bg-red-600 hover:bg-red-700 text-white text-xs py-1 px-2 rounded transition">
|
|
765
|
+
Delete
|
|
766
|
+
</button>
|
|
767
|
+
</div>
|
|
768
|
+
</div>
|
|
769
|
+
`
|
|
770
|
+
)
|
|
771
|
+
.join("");
|
|
772
|
+
} catch (error) {
|
|
773
|
+
console.error("Failed to load managed rooms:", error);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
function setupRoomManagementUI() {
|
|
778
|
+
document.getElementById("create-room-btn").addEventListener("click", async () => {
|
|
779
|
+
const name = document.getElementById("new-room-name").value.trim();
|
|
780
|
+
const description = document.getElementById("new-room-desc").value.trim();
|
|
781
|
+
|
|
782
|
+
if (!name) return;
|
|
783
|
+
|
|
784
|
+
try {
|
|
785
|
+
const response = await fetch("/api/rooms", {
|
|
786
|
+
method: "POST",
|
|
787
|
+
headers: { "Content-Type": "application/json" },
|
|
788
|
+
body: JSON.stringify({ name, description: description || undefined })
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
if (response.ok) {
|
|
792
|
+
document.getElementById("new-room-name").value = "";
|
|
793
|
+
document.getElementById("new-room-desc").value = "";
|
|
794
|
+
|
|
795
|
+
setTimeout(() => {
|
|
796
|
+
loadRoomLimit();
|
|
797
|
+
loadManagedRooms();
|
|
798
|
+
loadAvailableRooms();
|
|
799
|
+
}, 500);
|
|
800
|
+
}
|
|
801
|
+
} catch (error) {
|
|
802
|
+
console.error("Create room error:", error);
|
|
803
|
+
}
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
async function deleteRoom(roomId) {
|
|
808
|
+
if (!confirm("Are you sure you want to delete this room?")) return;
|
|
809
|
+
|
|
810
|
+
try {
|
|
811
|
+
const response = await fetch(`/api/rooms/${roomId}`, {
|
|
812
|
+
method: "DELETE"
|
|
813
|
+
});
|
|
814
|
+
|
|
815
|
+
if (response.ok) {
|
|
816
|
+
setTimeout(() => {
|
|
817
|
+
loadRoomLimit();
|
|
818
|
+
loadManagedRooms();
|
|
819
|
+
loadAvailableRooms();
|
|
820
|
+
}, 500);
|
|
821
|
+
}
|
|
822
|
+
} catch (error) {
|
|
823
|
+
console.error("Delete room error:", error);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
// Agent-Room Management
|
|
828
|
+
async function loadOwnedRooms() {
|
|
829
|
+
const response = await fetch("/api/rooms/owned");
|
|
830
|
+
return await response.json();
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
function populateAgentRoomSelector(ownedRooms) {
|
|
834
|
+
const select = document.getElementById("agent-room-select");
|
|
835
|
+
if (ownedRooms.length === 0) {
|
|
836
|
+
select.innerHTML = '<option value="">No owned rooms - create one first</option>';
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
select.innerHTML =
|
|
841
|
+
'<option value="">Select a room...</option>' +
|
|
842
|
+
ownedRooms.map((room) => `<option value="${room.id}">${room.name}</option>`).join("");
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
function setupAgentRoomManagement() {
|
|
846
|
+
document.getElementById("agent-room-select").addEventListener("change", async (e) => {
|
|
847
|
+
const roomId = e.target.value;
|
|
848
|
+
if (!roomId) {
|
|
849
|
+
document.getElementById("room-agents-list").innerHTML =
|
|
850
|
+
'<p class="text-gray-500">Select a room first</p>';
|
|
851
|
+
document.getElementById("available-agents-list").innerHTML =
|
|
852
|
+
'<p class="text-gray-500">Select a room first</p>';
|
|
853
|
+
document.getElementById("room-agents-count").textContent = "-";
|
|
854
|
+
document.getElementById("available-agents-count").textContent = "-";
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
await Promise.all([loadRoomAgents(roomId), loadAvailableAgents(roomId)]);
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
async function loadRoomAgents(roomId) {
|
|
863
|
+
try {
|
|
864
|
+
const response = await fetch(`/api/rooms/${roomId}/agents`);
|
|
865
|
+
const data = await response.json();
|
|
866
|
+
|
|
867
|
+
document.getElementById("room-agents-count").textContent = `${data.count} agents`;
|
|
868
|
+
|
|
869
|
+
const list = document.getElementById("room-agents-list");
|
|
870
|
+
if (data.agents.length === 0) {
|
|
871
|
+
list.innerHTML = '<p class="text-gray-500">No agents in this room</p>';
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
list.innerHTML = data.agents
|
|
876
|
+
.map(
|
|
877
|
+
(agent) => `
|
|
878
|
+
<div class="bg-gray-800 rounded p-3 border border-gray-600 flex justify-between items-center">
|
|
879
|
+
<div>
|
|
880
|
+
<div class="font-semibold">${agent.agent_name || "Unnamed"}</div>
|
|
881
|
+
<div class="text-xs text-gray-400">${agent.agent_id}</div>
|
|
882
|
+
</div>
|
|
883
|
+
<button onclick="removeAgentFromRoom('${roomId}', '${agent.agent_id}')"
|
|
884
|
+
class="bg-red-600 hover:bg-red-700 text-white text-xs py-1 px-3 rounded transition">
|
|
885
|
+
Remove
|
|
886
|
+
</button>
|
|
887
|
+
</div>
|
|
888
|
+
`
|
|
889
|
+
)
|
|
890
|
+
.join("");
|
|
891
|
+
} catch (error) {
|
|
892
|
+
console.error("Failed to load room agents:", error);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
async function loadAvailableAgents(roomId) {
|
|
897
|
+
try {
|
|
898
|
+
const response = await fetch(`/api/rooms/${roomId}/available-agents`);
|
|
899
|
+
const data = await response.json();
|
|
900
|
+
|
|
901
|
+
document.getElementById("available-agents-count").textContent = `${data.count} available`;
|
|
902
|
+
|
|
903
|
+
const list = document.getElementById("available-agents-list");
|
|
904
|
+
if (data.agents.length === 0) {
|
|
905
|
+
list.innerHTML = '<p class="text-gray-500">No more agents available</p>';
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
list.innerHTML = data.agents
|
|
910
|
+
.map(
|
|
911
|
+
(agent) => `
|
|
912
|
+
<div class="bg-gray-800 rounded p-3 border border-gray-600 flex justify-between items-center">
|
|
913
|
+
<div>
|
|
914
|
+
<div class="font-semibold">${agent.agent_name || "Unnamed"}</div>
|
|
915
|
+
<div class="text-xs text-gray-400">${agent.agent_id}</div>
|
|
916
|
+
</div>
|
|
917
|
+
<button onclick="addAgentToRoom('${roomId}', '${agent.agent_id}')"
|
|
918
|
+
class="bg-green-600 hover:bg-green-700 text-white text-xs py-1 px-3 rounded transition">
|
|
919
|
+
Add
|
|
920
|
+
</button>
|
|
921
|
+
</div>
|
|
922
|
+
`
|
|
923
|
+
)
|
|
924
|
+
.join("");
|
|
925
|
+
} catch (error) {
|
|
926
|
+
console.error("Failed to load available agents:", error);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
async function addAgentToRoom(roomId, agentId) {
|
|
931
|
+
try {
|
|
932
|
+
const response = await fetch(`/api/rooms/${roomId}/agents/${agentId}`, {
|
|
933
|
+
method: "POST"
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
if (response.ok) {
|
|
937
|
+
setTimeout(() => {
|
|
938
|
+
loadRoomAgents(roomId);
|
|
939
|
+
loadAvailableAgents(roomId);
|
|
940
|
+
}, 500);
|
|
941
|
+
}
|
|
942
|
+
} catch (error) {
|
|
943
|
+
console.error("Add agent error:", error);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
async function removeAgentFromRoom(roomId, agentId) {
|
|
948
|
+
try {
|
|
949
|
+
const response = await fetch(`/api/rooms/${roomId}/agents/${agentId}`, {
|
|
950
|
+
method: "DELETE"
|
|
951
|
+
});
|
|
952
|
+
|
|
953
|
+
if (response.ok) {
|
|
954
|
+
setTimeout(() => {
|
|
955
|
+
loadRoomAgents(roomId);
|
|
956
|
+
loadAvailableAgents(roomId);
|
|
957
|
+
}, 500);
|
|
958
|
+
}
|
|
959
|
+
} catch (error) {
|
|
960
|
+
console.error("Remove agent error:", error);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
// Health check
|
|
965
|
+
function startHealthCheck() {
|
|
966
|
+
updateHealthFromMetrics();
|
|
967
|
+
setInterval(updateHealthFromMetrics, 5000);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
async function updateHealthFromMetrics() {
|
|
971
|
+
try {
|
|
972
|
+
const [healthResponse, metricsResponse] = await Promise.all([
|
|
973
|
+
fetch("/health"),
|
|
974
|
+
fetch("/metrics")
|
|
975
|
+
]);
|
|
976
|
+
|
|
977
|
+
const health = await healthResponse.json();
|
|
978
|
+
const metrics = await metricsResponse.json();
|
|
979
|
+
|
|
980
|
+
// Update status
|
|
981
|
+
document.getElementById("health-overall").textContent = health.status;
|
|
982
|
+
document.getElementById("health-overall").className =
|
|
983
|
+
health.status === "healthy" ? "text-green-500" : "text-yellow-500";
|
|
984
|
+
|
|
985
|
+
// Update connection/auth status
|
|
986
|
+
const connected = metrics.connection?.connected || false;
|
|
987
|
+
const authenticated = metrics.connection?.authenticated || false;
|
|
988
|
+
|
|
989
|
+
updateConnectionStatus(connected ? "connected" : "disconnected");
|
|
990
|
+
updateAuthStatus(authenticated ? "success" : "pending");
|
|
991
|
+
|
|
992
|
+
document.getElementById("health-connected").textContent = connected ? "✅ Yes" : "❌ No";
|
|
993
|
+
document.getElementById("health-connected").className = connected
|
|
994
|
+
? "text-green-500"
|
|
995
|
+
: "text-red-500";
|
|
996
|
+
|
|
997
|
+
document.getElementById("health-auth").textContent = authenticated ? "✅ Yes" : "❌ No";
|
|
998
|
+
document.getElementById("health-auth").className = authenticated
|
|
999
|
+
? "text-green-500"
|
|
1000
|
+
: "text-red-500";
|
|
1001
|
+
|
|
1002
|
+
// Update message count
|
|
1003
|
+
document.getElementById("messages-count").textContent = metrics.messages?.sent || 0;
|
|
1004
|
+
} catch (error) {
|
|
1005
|
+
console.error("Health check failed:", error);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
function updateConnectionStatus(status) {
|
|
1010
|
+
connectionStatus = status;
|
|
1011
|
+
const dot = document.getElementById("connection-dot");
|
|
1012
|
+
const text = document.getElementById("connection-status");
|
|
1013
|
+
|
|
1014
|
+
if (status === "connected") {
|
|
1015
|
+
dot.className = "status-dot w-3 h-3 rounded-full bg-green-500";
|
|
1016
|
+
text.textContent = "Connected";
|
|
1017
|
+
text.className = "text-2xl font-bold text-green-500";
|
|
1018
|
+
} else {
|
|
1019
|
+
dot.className = "status-dot w-3 h-3 rounded-full bg-red-500";
|
|
1020
|
+
text.textContent = "Disconnected";
|
|
1021
|
+
text.className = "text-2xl font-bold text-red-500";
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
function updateAuthStatus(status) {
|
|
1026
|
+
authStatus = status;
|
|
1027
|
+
const dot = document.getElementById("auth-dot");
|
|
1028
|
+
const text = document.getElementById("auth-status");
|
|
1029
|
+
|
|
1030
|
+
if (status === "success") {
|
|
1031
|
+
dot.className = "status-dot w-3 h-3 rounded-full bg-green-500";
|
|
1032
|
+
text.textContent = "Authenticated";
|
|
1033
|
+
text.className = "text-2xl font-bold text-green-500";
|
|
1034
|
+
} else {
|
|
1035
|
+
dot.className = "status-dot w-3 h-3 rounded-full bg-yellow-500";
|
|
1036
|
+
text.textContent = "Pending";
|
|
1037
|
+
text.className = "text-2xl font-bold text-yellow-500";
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
// Load events
|
|
1042
|
+
async function loadEvents() {
|
|
1043
|
+
try {
|
|
1044
|
+
const response = await fetch("/api/events");
|
|
1045
|
+
const events = await response.json();
|
|
1046
|
+
|
|
1047
|
+
const list = document.getElementById("events-list");
|
|
1048
|
+
if (events.length === 0) {
|
|
1049
|
+
list.innerHTML = '<p class="text-gray-500">No events yet</p>';
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
list.innerHTML = events
|
|
1054
|
+
.map(
|
|
1055
|
+
(evt) => `
|
|
1056
|
+
<div class="event-item bg-gray-700 rounded p-2 border border-gray-600">
|
|
1057
|
+
<div class="flex items-center justify-between">
|
|
1058
|
+
<span class="font-mono text-xs text-blue-400">${evt.type}</span>
|
|
1059
|
+
<span class="text-xs text-gray-400">${new Date(evt.timestamp).toLocaleTimeString()}</span>
|
|
1060
|
+
</div>
|
|
1061
|
+
<p class="text-xs text-gray-400 mt-1">${JSON.stringify(evt.data)}</p>
|
|
1062
|
+
</div>
|
|
1063
|
+
`
|
|
1064
|
+
)
|
|
1065
|
+
.join("");
|
|
1066
|
+
} catch (error) {
|
|
1067
|
+
console.error("Failed to load events:", error);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
// Load webhooks
|
|
1072
|
+
async function loadWebhooks() {
|
|
1073
|
+
try {
|
|
1074
|
+
const response = await fetch("/api/webhooks");
|
|
1075
|
+
const webhooks = await response.json();
|
|
1076
|
+
|
|
1077
|
+
const list = document.getElementById("webhooks-list");
|
|
1078
|
+
if (webhooks.length === 0) {
|
|
1079
|
+
list.innerHTML = '<p class="text-gray-500">No webhooks received yet</p>';
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
list.innerHTML = webhooks
|
|
1084
|
+
.map(
|
|
1085
|
+
(wh) => `
|
|
1086
|
+
<div class="bg-gray-700 rounded-lg p-3 border border-gray-600">
|
|
1087
|
+
<div class="flex items-center justify-between mb-1">
|
|
1088
|
+
<span class="font-mono text-sm text-purple-400">${wh.event}</span>
|
|
1089
|
+
<span class="text-xs text-gray-400">${new Date(wh.receivedAt).toLocaleTimeString()}</span>
|
|
1090
|
+
</div>
|
|
1091
|
+
<pre class="text-xs text-gray-400 overflow-x-auto">${JSON.stringify(wh.data || wh, null, 2)}</pre>
|
|
1092
|
+
</div>
|
|
1093
|
+
`
|
|
1094
|
+
)
|
|
1095
|
+
.join("");
|
|
1096
|
+
} catch (error) {
|
|
1097
|
+
console.error("Failed to load webhooks:", error);
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
// Load messages
|
|
1102
|
+
async function loadMessages() {
|
|
1103
|
+
try {
|
|
1104
|
+
const response = await fetch("/api/messages");
|
|
1105
|
+
const messages = await response.json();
|
|
1106
|
+
|
|
1107
|
+
const list = document.getElementById("messages-list");
|
|
1108
|
+
if (messages.length === 0) {
|
|
1109
|
+
list.innerHTML = '<p class="text-gray-500">No messages yet</p>';
|
|
1110
|
+
return;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
list.innerHTML = messages
|
|
1114
|
+
.map(
|
|
1115
|
+
(msg) => `
|
|
1116
|
+
<div class="bg-gray-700 rounded-lg p-4 border border-gray-600">
|
|
1117
|
+
<div class="flex items-center justify-between mb-2">
|
|
1118
|
+
<span class="text-sm text-gray-400">${new Date(msg.timestamp).toLocaleTimeString()}</span>
|
|
1119
|
+
<span class="text-xs px-2 py-1 rounded ${msg.response ? "bg-green-600" : "bg-yellow-600"}">
|
|
1120
|
+
${msg.response ? "Responded" : "Pending"}
|
|
1121
|
+
</span>
|
|
1122
|
+
</div>
|
|
1123
|
+
<p class="text-sm mb-2">${msg.content}</p>
|
|
1124
|
+
${
|
|
1125
|
+
msg.response
|
|
1126
|
+
? `
|
|
1127
|
+
<div class="mt-3 p-3 bg-gray-800 rounded border-l-4 border-green-500">
|
|
1128
|
+
<p class="text-xs text-gray-400 mb-1">Response from ${msg.response.agentName}:</p>
|
|
1129
|
+
<p class="text-sm">${msg.response.humanized || msg.response.content}</p>
|
|
1130
|
+
</div>
|
|
1131
|
+
`
|
|
1132
|
+
: ""
|
|
1133
|
+
}
|
|
1134
|
+
</div>
|
|
1135
|
+
`
|
|
1136
|
+
)
|
|
1137
|
+
.join("");
|
|
1138
|
+
} catch (error) {
|
|
1139
|
+
console.error("Failed to load messages:", error);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
</script>
|
|
1143
|
+
</body>
|
|
1144
|
+
</html>
|