leedab 0.1.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/LICENSE +6 -0
- package/README.md +85 -0
- package/bin/leedab.js +626 -0
- package/dist/analytics.d.ts +20 -0
- package/dist/analytics.js +57 -0
- package/dist/audit.d.ts +15 -0
- package/dist/audit.js +46 -0
- package/dist/brand.d.ts +9 -0
- package/dist/brand.js +57 -0
- package/dist/channels/index.d.ts +5 -0
- package/dist/channels/index.js +47 -0
- package/dist/config/index.d.ts +10 -0
- package/dist/config/index.js +49 -0
- package/dist/config/schema.d.ts +58 -0
- package/dist/config/schema.js +21 -0
- package/dist/dashboard/routes.d.ts +5 -0
- package/dist/dashboard/routes.js +410 -0
- package/dist/dashboard/server.d.ts +2 -0
- package/dist/dashboard/server.js +80 -0
- package/dist/dashboard/static/app.js +351 -0
- package/dist/dashboard/static/console.html +252 -0
- package/dist/dashboard/static/favicon.png +0 -0
- package/dist/dashboard/static/index.html +815 -0
- package/dist/dashboard/static/logo-dark.png +0 -0
- package/dist/dashboard/static/logo-light.png +0 -0
- package/dist/dashboard/static/sessions.html +182 -0
- package/dist/dashboard/static/settings.html +274 -0
- package/dist/dashboard/static/style.css +493 -0
- package/dist/dashboard/static/team.html +215 -0
- package/dist/gateway.d.ts +8 -0
- package/dist/gateway.js +213 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/license.d.ts +27 -0
- package/dist/license.js +92 -0
- package/dist/memory/index.d.ts +9 -0
- package/dist/memory/index.js +41 -0
- package/dist/onboard/index.d.ts +4 -0
- package/dist/onboard/index.js +263 -0
- package/dist/onboard/oauth-server.d.ts +13 -0
- package/dist/onboard/oauth-server.js +73 -0
- package/dist/onboard/steps/google.d.ts +12 -0
- package/dist/onboard/steps/google.js +178 -0
- package/dist/onboard/steps/provider.d.ts +10 -0
- package/dist/onboard/steps/provider.js +292 -0
- package/dist/onboard/steps/teams.d.ts +5 -0
- package/dist/onboard/steps/teams.js +51 -0
- package/dist/onboard/steps/telegram.d.ts +6 -0
- package/dist/onboard/steps/telegram.js +88 -0
- package/dist/onboard/steps/welcome.d.ts +1 -0
- package/dist/onboard/steps/welcome.js +10 -0
- package/dist/onboard/steps/whatsapp.d.ts +2 -0
- package/dist/onboard/steps/whatsapp.js +76 -0
- package/dist/openclaw.d.ts +9 -0
- package/dist/openclaw.js +20 -0
- package/dist/team.d.ts +13 -0
- package/dist/team.js +49 -0
- package/dist/templates/verticals/supply-chain/HEARTBEAT.md +12 -0
- package/dist/templates/verticals/supply-chain/SOUL.md +49 -0
- package/dist/templates/verticals/supply-chain/WORKFLOWS.md +148 -0
- package/dist/templates/verticals/supply-chain/vault-template.json +18 -0
- package/dist/templates/workspace/AGENTS.md +181 -0
- package/dist/templates/workspace/BOOTSTRAP.md +32 -0
- package/dist/templates/workspace/HEARTBEAT.md +9 -0
- package/dist/templates/workspace/IDENTITY.md +14 -0
- package/dist/templates/workspace/SOUL.md +32 -0
- package/dist/templates/workspace/TOOLS.md +40 -0
- package/dist/templates/workspace/USER.md +26 -0
- package/dist/vault.d.ts +24 -0
- package/dist/vault.js +123 -0
- package/package.json +58 -0
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,182 @@
|
|
|
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
|
+
<link rel="icon" type="image/png" href="/favicon.png">
|
|
7
|
+
<title>LeedAB — Sessions</title>
|
|
8
|
+
<link rel="stylesheet" href="/style.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<style>
|
|
12
|
+
.page-header { display:flex; align-items:center; justify-content:space-between; padding:0 20px; height:52px; border-bottom:1px solid var(--border); background:var(--bg); }
|
|
13
|
+
.page-header-left { display:flex; align-items:center; gap:10px; }
|
|
14
|
+
.page-header-title { font-size:14px; font-weight:600; letter-spacing:-0.01em; }
|
|
15
|
+
.page-nav { display:flex; align-items:center; gap:2px; }
|
|
16
|
+
.page-nav a, .page-nav button { color:var(--text-dim); text-decoration:none; display:flex; align-items:center; gap:5px; padding:6px 12px; border-radius:8px; font-size:13px; font-weight:450; transition:all 0.15s; background:none; border:none; cursor:pointer; font-family:inherit; }
|
|
17
|
+
.page-nav a:hover, .page-nav button:hover { color:var(--text-secondary); background:var(--surface-raised); }
|
|
18
|
+
.page-nav .theme-btn { border:1px solid var(--border); padding:5px 8px; }
|
|
19
|
+
</style>
|
|
20
|
+
|
|
21
|
+
<div class="page-header">
|
|
22
|
+
<div class="page-header-left">
|
|
23
|
+
<span class="page-header-title">Sessions</span>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="page-nav">
|
|
26
|
+
<a href="/">
|
|
27
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m22 2-7 20-4-9-9-4 20-7Z"/><path d="M22 2 11 13"/></svg>
|
|
28
|
+
Chat
|
|
29
|
+
</a>
|
|
30
|
+
<a href="/console.html">
|
|
31
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
|
|
32
|
+
Console
|
|
33
|
+
</a>
|
|
34
|
+
<button class="theme-btn" onclick="toggleTheme()" title="Toggle theme">
|
|
35
|
+
<svg id="theme-icon-sun" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
|
|
36
|
+
<svg id="theme-icon-moon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:none"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div class="container">
|
|
42
|
+
<main>
|
|
43
|
+
<p class="section-desc">Conversation history across all channels. Read-only log.</p>
|
|
44
|
+
|
|
45
|
+
<div class="session-list" id="session-list">
|
|
46
|
+
<div style="color:var(--text-dim);font-size:14px;padding:24px 0">Loading sessions...</div>
|
|
47
|
+
</div>
|
|
48
|
+
</main>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<style>
|
|
52
|
+
.session-list {
|
|
53
|
+
display: flex;
|
|
54
|
+
flex-direction: column;
|
|
55
|
+
gap: 8px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.session-item {
|
|
59
|
+
display: flex;
|
|
60
|
+
align-items: center;
|
|
61
|
+
justify-content: space-between;
|
|
62
|
+
padding: 16px 20px;
|
|
63
|
+
background: var(--surface);
|
|
64
|
+
border: 1px solid var(--border);
|
|
65
|
+
border-radius: 12px;
|
|
66
|
+
text-decoration: none;
|
|
67
|
+
color: inherit;
|
|
68
|
+
transition: border-color 0.15s;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.session-item:hover {
|
|
72
|
+
border-color: var(--border-hover);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.session-info h3 {
|
|
76
|
+
font-size: 14px;
|
|
77
|
+
font-weight: 500;
|
|
78
|
+
margin-bottom: 2px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.session-info p {
|
|
82
|
+
font-size: 12px;
|
|
83
|
+
color: var(--text-dim);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.session-meta {
|
|
87
|
+
font-size: 12px;
|
|
88
|
+
color: var(--text-faint);
|
|
89
|
+
text-align: right;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.session-meta .channel {
|
|
93
|
+
display: inline-block;
|
|
94
|
+
padding: 2px 8px;
|
|
95
|
+
background: var(--accent-soft);
|
|
96
|
+
color: var(--accent);
|
|
97
|
+
border-radius: 6px;
|
|
98
|
+
font-size: 11px;
|
|
99
|
+
margin-bottom: 4px;
|
|
100
|
+
}
|
|
101
|
+
</style>
|
|
102
|
+
|
|
103
|
+
<script>
|
|
104
|
+
function initTheme() {
|
|
105
|
+
const saved = localStorage.getItem("leedab-theme") || "dark";
|
|
106
|
+
document.documentElement.setAttribute("data-theme", saved);
|
|
107
|
+
updateThemeIcon(saved);
|
|
108
|
+
}
|
|
109
|
+
function toggleTheme() {
|
|
110
|
+
const current = document.documentElement.getAttribute("data-theme") || "dark";
|
|
111
|
+
const next = current === "dark" ? "light" : "dark";
|
|
112
|
+
document.documentElement.setAttribute("data-theme", next);
|
|
113
|
+
localStorage.setItem("leedab-theme", next);
|
|
114
|
+
updateThemeIcon(next);
|
|
115
|
+
}
|
|
116
|
+
function updateThemeIcon(theme) {
|
|
117
|
+
const sun = document.getElementById("theme-icon-sun");
|
|
118
|
+
const moon = document.getElementById("theme-icon-moon");
|
|
119
|
+
if (sun && moon) {
|
|
120
|
+
sun.style.display = theme === "dark" ? "block" : "none";
|
|
121
|
+
moon.style.display = theme === "light" ? "block" : "none";
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
initTheme();
|
|
125
|
+
|
|
126
|
+
document.addEventListener("DOMContentLoaded", loadSessions);
|
|
127
|
+
|
|
128
|
+
async function loadSessions() {
|
|
129
|
+
const list = document.getElementById("session-list");
|
|
130
|
+
try {
|
|
131
|
+
const res = await fetch("/api/sessions");
|
|
132
|
+
const sessions = await res.json();
|
|
133
|
+
|
|
134
|
+
if (!sessions.length) {
|
|
135
|
+
list.innerHTML = '<div style="text-align:center;padding:48px 0;color:var(--text-dim);font-size:14px">No conversations yet.</div>';
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
list.innerHTML = sessions.map(s => {
|
|
140
|
+
const date = s.updatedAt ? new Date(s.updatedAt).toLocaleDateString("en-US", {
|
|
141
|
+
month: "short", day: "numeric", hour: "numeric", minute: "2-digit"
|
|
142
|
+
}) : "";
|
|
143
|
+
// Derive channel and label from key like "agent:main:telegram:direct:123"
|
|
144
|
+
const parts = (s.key || "").split(":");
|
|
145
|
+
let channel = "console";
|
|
146
|
+
let label = s.key || s.sessionId || "unknown";
|
|
147
|
+
if (parts[2] === "telegram") {
|
|
148
|
+
channel = "telegram";
|
|
149
|
+
label = parts.slice(2).join(":");
|
|
150
|
+
} else if (parts[2] === "cron") {
|
|
151
|
+
channel = "cron";
|
|
152
|
+
label = parts.slice(2).join(":");
|
|
153
|
+
} else if (parts[2] === "subagent") {
|
|
154
|
+
channel = "subagent";
|
|
155
|
+
label = parts.slice(2).join(":");
|
|
156
|
+
} else if (parts.length >= 3) {
|
|
157
|
+
label = parts.slice(2).join(":");
|
|
158
|
+
}
|
|
159
|
+
const tokens = s.totalTokens != null ? `${(s.totalTokens / 1000).toFixed(1)}k tokens` : "";
|
|
160
|
+
return `
|
|
161
|
+
<div class="session-item">
|
|
162
|
+
<div class="session-info">
|
|
163
|
+
<h3>${escapeHtml(label)}</h3>
|
|
164
|
+
<p>${escapeHtml(s.model || "")} ${tokens ? "· " + tokens : ""}</p>
|
|
165
|
+
</div>
|
|
166
|
+
<div class="session-meta">
|
|
167
|
+
<div class="channel">${channel}</div>
|
|
168
|
+
<div>${date}</div>
|
|
169
|
+
</div>
|
|
170
|
+
</div>`;
|
|
171
|
+
}).join("");
|
|
172
|
+
} catch {
|
|
173
|
+
list.innerHTML = '<div style="text-align:center;padding:48px 0;color:var(--text-dim);font-size:14px">Could not load sessions. Is the gateway running?</div>';
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function escapeHtml(str) {
|
|
178
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
179
|
+
}
|
|
180
|
+
</script>
|
|
181
|
+
</body>
|
|
182
|
+
</html>
|
|
@@ -0,0 +1,274 @@
|
|
|
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
|
+
<link rel="icon" type="image/png" href="/favicon.png">
|
|
7
|
+
<title>LeedAB — Setup</title>
|
|
8
|
+
<link rel="stylesheet" href="/style.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<style>
|
|
12
|
+
.page-header {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: space-between;
|
|
16
|
+
padding: 0 20px;
|
|
17
|
+
height: 52px;
|
|
18
|
+
border-bottom: 1px solid var(--border);
|
|
19
|
+
background: var(--bg);
|
|
20
|
+
}
|
|
21
|
+
.page-header-left {
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
gap: 10px;
|
|
25
|
+
}
|
|
26
|
+
.page-header-title {
|
|
27
|
+
font-size: 14px;
|
|
28
|
+
font-weight: 600;
|
|
29
|
+
letter-spacing: -0.01em;
|
|
30
|
+
}
|
|
31
|
+
.page-nav {
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
gap: 2px;
|
|
35
|
+
}
|
|
36
|
+
.page-nav a, .page-nav button {
|
|
37
|
+
color: var(--text-dim);
|
|
38
|
+
text-decoration: none;
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
gap: 5px;
|
|
42
|
+
padding: 6px 12px;
|
|
43
|
+
border-radius: 8px;
|
|
44
|
+
font-size: 13px;
|
|
45
|
+
font-weight: 450;
|
|
46
|
+
transition: all 0.15s;
|
|
47
|
+
background: none;
|
|
48
|
+
border: none;
|
|
49
|
+
cursor: pointer;
|
|
50
|
+
font-family: inherit;
|
|
51
|
+
}
|
|
52
|
+
.page-nav a:hover, .page-nav button:hover {
|
|
53
|
+
color: var(--text-secondary);
|
|
54
|
+
background: var(--surface-raised);
|
|
55
|
+
}
|
|
56
|
+
.page-nav .theme-btn {
|
|
57
|
+
border: 1px solid var(--border);
|
|
58
|
+
padding: 5px 8px;
|
|
59
|
+
}
|
|
60
|
+
</style>
|
|
61
|
+
|
|
62
|
+
<div class="page-header">
|
|
63
|
+
<div class="page-header-left">
|
|
64
|
+
<span class="page-header-title">Settings</span>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="page-nav">
|
|
67
|
+
<a href="/">
|
|
68
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m22 2-7 20-4-9-9-4 20-7Z"/><path d="M22 2 11 13"/></svg>
|
|
69
|
+
Chat
|
|
70
|
+
</a>
|
|
71
|
+
<a href="/console.html">
|
|
72
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
73
|
+
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/>
|
|
74
|
+
</svg>
|
|
75
|
+
Console
|
|
76
|
+
</a>
|
|
77
|
+
<button class="theme-btn" onclick="toggleTheme()" title="Toggle theme">
|
|
78
|
+
<svg id="theme-icon-sun" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
|
|
79
|
+
<svg id="theme-icon-moon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:none"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
|
|
80
|
+
</button>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<div class="container">
|
|
85
|
+
<main>
|
|
86
|
+
<div id="toast" class="toast hidden"></div>
|
|
87
|
+
|
|
88
|
+
<!-- Channels -->
|
|
89
|
+
<section class="section">
|
|
90
|
+
<h2 class="section-title">Channels</h2>
|
|
91
|
+
<p class="section-desc">How your team reaches the agent.</p>
|
|
92
|
+
|
|
93
|
+
<div class="cards">
|
|
94
|
+
<!-- Telegram -->
|
|
95
|
+
<div class="card" id="card-telegram">
|
|
96
|
+
<div class="card-icon">
|
|
97
|
+
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
98
|
+
<path d="m22 2-7 20-4-9-9-4 20-7Z"/><path d="M22 2 11 13"/>
|
|
99
|
+
</svg>
|
|
100
|
+
</div>
|
|
101
|
+
<div class="card-body">
|
|
102
|
+
<h3>Telegram</h3>
|
|
103
|
+
<div class="card-status" id="status-telegram">
|
|
104
|
+
<span class="dot"></span> Not connected
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
<button class="btn" onclick="showTelegramForm()">Connect</button>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<!-- WhatsApp -->
|
|
111
|
+
<div class="card" id="card-whatsapp">
|
|
112
|
+
<div class="card-icon">
|
|
113
|
+
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
114
|
+
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/>
|
|
115
|
+
</svg>
|
|
116
|
+
</div>
|
|
117
|
+
<div class="card-body">
|
|
118
|
+
<h3>WhatsApp</h3>
|
|
119
|
+
<div class="card-status" id="status-whatsapp">
|
|
120
|
+
<span class="dot"></span> Not connected
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
<button class="btn" onclick="connectWhatsApp()">Connect</button>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
<!-- Teams -->
|
|
127
|
+
<div class="card" id="card-teams">
|
|
128
|
+
<div class="card-icon">
|
|
129
|
+
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
130
|
+
<rect x="2" y="7" width="20" height="14" rx="2" ry="2"/>
|
|
131
|
+
<path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"/>
|
|
132
|
+
</svg>
|
|
133
|
+
</div>
|
|
134
|
+
<div class="card-body">
|
|
135
|
+
<h3>Microsoft Teams</h3>
|
|
136
|
+
<div class="card-status" id="status-teams">
|
|
137
|
+
<span class="dot"></span> Not connected
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
<button class="btn" onclick="showTeamsForm()">Connect</button>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
</section>
|
|
144
|
+
|
|
145
|
+
<!-- Telegram inline form -->
|
|
146
|
+
<div id="telegram-form" class="form-panel hidden">
|
|
147
|
+
<h3>Connect Telegram</h3>
|
|
148
|
+
<p class="form-help">Get a bot token from <a href="https://t.me/BotFather" target="_blank">@BotFather</a> on Telegram.</p>
|
|
149
|
+
<label>Bot Token
|
|
150
|
+
<input type="password" id="telegram-token" placeholder="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11">
|
|
151
|
+
</label>
|
|
152
|
+
<div class="form-actions">
|
|
153
|
+
<button class="btn" onclick="connectTelegram()">Connect</button>
|
|
154
|
+
<button class="btn btn-ghost" onclick="hideTelegramForm()">Cancel</button>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<!-- Teams inline form -->
|
|
159
|
+
<div id="teams-form" class="form-panel hidden">
|
|
160
|
+
<h3>Connect Microsoft Teams</h3>
|
|
161
|
+
<p class="form-help">Enter your Azure AD app credentials. <a href="https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps" target="_blank">Create one here</a></p>
|
|
162
|
+
<label>App (Client) ID
|
|
163
|
+
<input type="text" id="teams-app-id" placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
|
|
164
|
+
</label>
|
|
165
|
+
<label>Tenant ID
|
|
166
|
+
<input type="text" id="teams-tenant-id" placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
|
|
167
|
+
</label>
|
|
168
|
+
<div class="form-actions">
|
|
169
|
+
<button class="btn" onclick="connectTeams()">Connect</button>
|
|
170
|
+
<button class="btn btn-ghost" onclick="hideTeamsForm()">Cancel</button>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
<!-- WhatsApp QR panel -->
|
|
175
|
+
<div id="whatsapp-panel" class="form-panel hidden">
|
|
176
|
+
<h3>WhatsApp Pairing</h3>
|
|
177
|
+
<p class="form-help">Open WhatsApp on your phone → Settings → Linked Devices → Link a Device</p>
|
|
178
|
+
<div id="whatsapp-qr" class="qr-area">
|
|
179
|
+
<p>Starting pairing...</p>
|
|
180
|
+
</div>
|
|
181
|
+
<p class="form-help" style="margin-top:12px">Once paired, this page will update automatically.</p>
|
|
182
|
+
<button class="btn btn-ghost" onclick="hideWhatsAppPanel()">Cancel</button>
|
|
183
|
+
</div>
|
|
184
|
+
|
|
185
|
+
<!-- Channel Access / Allowlist -->
|
|
186
|
+
<section class="section" style="margin-top:48px">
|
|
187
|
+
<h2 class="section-title">Channel Access</h2>
|
|
188
|
+
<p class="section-desc">Only users on the allowlist can message the agent. Add their user ID to grant access.</p>
|
|
189
|
+
|
|
190
|
+
<div class="form-panel">
|
|
191
|
+
<h3>Allowlist</h3>
|
|
192
|
+
<label>Channel
|
|
193
|
+
<select id="allowlist-channel" onchange="loadAllowlist()" style="display:block;width:100%;margin-top:4px;padding:10px 12px;background:var(--bg);border:1px solid var(--border);border-radius:8px;color:var(--text);font-size:0.9rem;font-family:inherit">
|
|
194
|
+
<option value="telegram">Telegram</option>
|
|
195
|
+
<option value="whatsapp">WhatsApp</option>
|
|
196
|
+
<option value="teams">Teams</option>
|
|
197
|
+
</select>
|
|
198
|
+
</label>
|
|
199
|
+
<div id="allowlist-entries" style="margin:16px 0"></div>
|
|
200
|
+
<label>Add user ID
|
|
201
|
+
<input type="text" id="allowlist-userid" placeholder="e.g. 6549960466">
|
|
202
|
+
</label>
|
|
203
|
+
<p style="margin:4px 0 12px;font-size:0.8rem;color:var(--text-faint)">
|
|
204
|
+
Telegram: message <a href="https://t.me/userinfobot" target="_blank" style="color:var(--accent)">@userinfobot</a> to get your numeric user ID.
|
|
205
|
+
WhatsApp: use the phone number. Teams: use the Azure AD object ID.
|
|
206
|
+
</p>
|
|
207
|
+
<div class="form-actions">
|
|
208
|
+
<button class="btn" onclick="addAllowlistEntry()">Add to allowlist</button>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
</section>
|
|
212
|
+
|
|
213
|
+
<!-- Credential Vault -->
|
|
214
|
+
<section class="section" style="margin-top:48px">
|
|
215
|
+
<h2 class="section-title">Credential Vault</h2>
|
|
216
|
+
<p class="section-desc">Stored logins for services the agent accesses via browser (Gmail, Drive, CRM, etc.)</p>
|
|
217
|
+
|
|
218
|
+
<div id="vault-list"></div>
|
|
219
|
+
|
|
220
|
+
<div class="form-panel" style="margin-top:16px">
|
|
221
|
+
<h3>Add credential</h3>
|
|
222
|
+
<label>Service name
|
|
223
|
+
<input type="text" id="vault-service" placeholder="e.g. gmail, salesforce, shipstation">
|
|
224
|
+
</label>
|
|
225
|
+
<label>Login URL
|
|
226
|
+
<input type="text" id="vault-url" placeholder="https://...">
|
|
227
|
+
</label>
|
|
228
|
+
<label>Username / email
|
|
229
|
+
<input type="text" id="vault-username">
|
|
230
|
+
</label>
|
|
231
|
+
<label>Password
|
|
232
|
+
<input type="password" id="vault-password">
|
|
233
|
+
</label>
|
|
234
|
+
<label>Notes for agent
|
|
235
|
+
<textarea id="vault-notes" placeholder="e.g. Use the shipping dashboard, not the admin panel"></textarea>
|
|
236
|
+
</label>
|
|
237
|
+
<div class="form-actions">
|
|
238
|
+
<button class="btn" onclick="addVaultEntry()">Add to vault</button>
|
|
239
|
+
</div>
|
|
240
|
+
</div>
|
|
241
|
+
</section>
|
|
242
|
+
</main>
|
|
243
|
+
|
|
244
|
+
<footer>
|
|
245
|
+
<p>Your files, credentials, and memory stay on this device.</p>
|
|
246
|
+
</footer>
|
|
247
|
+
</div>
|
|
248
|
+
|
|
249
|
+
<script>
|
|
250
|
+
function initTheme() {
|
|
251
|
+
const saved = localStorage.getItem("leedab-theme") || "dark";
|
|
252
|
+
document.documentElement.setAttribute("data-theme", saved);
|
|
253
|
+
updateThemeIcon(saved);
|
|
254
|
+
}
|
|
255
|
+
function toggleTheme() {
|
|
256
|
+
const current = document.documentElement.getAttribute("data-theme") || "dark";
|
|
257
|
+
const next = current === "dark" ? "light" : "dark";
|
|
258
|
+
document.documentElement.setAttribute("data-theme", next);
|
|
259
|
+
localStorage.setItem("leedab-theme", next);
|
|
260
|
+
updateThemeIcon(next);
|
|
261
|
+
}
|
|
262
|
+
function updateThemeIcon(theme) {
|
|
263
|
+
const sun = document.getElementById("theme-icon-sun");
|
|
264
|
+
const moon = document.getElementById("theme-icon-moon");
|
|
265
|
+
if (sun && moon) {
|
|
266
|
+
sun.style.display = theme === "dark" ? "block" : "none";
|
|
267
|
+
moon.style.display = theme === "light" ? "block" : "none";
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
initTheme();
|
|
271
|
+
</script>
|
|
272
|
+
<script src="/app.js"></script>
|
|
273
|
+
</body>
|
|
274
|
+
</html>
|