privateboard 0.1.9 → 0.1.11
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/dist/cli.js +3732 -2160
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/public/agent-overlay.js +59 -36
- package/public/agent-profile.css +392 -100
- package/public/agent-profile.js +551 -59
- package/public/app.js +1341 -681
- package/public/i18n.js +1990 -0
- package/public/index.html +251 -94
- package/public/keys-store.js +63 -0
- package/public/new-agent.css +60 -0
- package/public/new-agent.js +121 -53
- package/public/room-settings.js +2 -1
- package/public/user-settings.css +68 -0
- package/public/user-settings.js +241 -87
- package/public/voice-replay.css +607 -0
- package/public/voice-replay.js +533 -0
package/package.json
CHANGED
package/public/agent-overlay.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* a key isn't in the table (registry updates lag this map). */
|
|
17
17
|
const MODEL_LABELS = {
|
|
18
18
|
"opus-4-7": { name: "Claude Opus 4.7", provider: "Anthropic" },
|
|
19
|
+
"opus-4-6": { name: "Claude Opus 4.6", provider: "Anthropic" },
|
|
19
20
|
"sonnet-4-6": { name: "Claude Sonnet 4.6", provider: "Anthropic" },
|
|
20
21
|
"opus-4-6": { name: "Claude Opus 4.6", provider: "Anthropic" },
|
|
21
22
|
"opus-4-6-fast": { name: "Claude Opus 4.6 Fast", provider: "Anthropic" },
|
|
@@ -30,9 +31,9 @@
|
|
|
30
31
|
"gemini-3-1-flash": { name: "Gemini 3.1 Flash Lite", provider: "Google" },
|
|
31
32
|
"grok-4-3": { name: "Grok 4.3", provider: "xAI" },
|
|
32
33
|
"grok-4-1-fast": { name: "Grok 4.1 Fast", provider: "xAI" },
|
|
33
|
-
"grok-4-3": { name: "Grok 4.3", provider: "xAI" },
|
|
34
34
|
"grok-4-20": { name: "Grok 4.20", provider: "xAI" },
|
|
35
35
|
"deepseek-v4-pro": { name: "DeepSeek V4 Pro", provider: "DeepSeek" },
|
|
36
|
+
"deepseek-v4-flash": { name: "DeepSeek Lite", provider: "DeepSeek" },
|
|
36
37
|
};
|
|
37
38
|
|
|
38
39
|
const AGENT_CATALOG = {
|
|
@@ -182,12 +183,22 @@
|
|
|
182
183
|
}
|
|
183
184
|
};
|
|
184
185
|
|
|
186
|
+
function escapeHtml(s) {
|
|
187
|
+
return String(s).replace(/[&<>"']/g, (c) => ({
|
|
188
|
+
"&": "&", "<": "<", ">": ">", '"': """, "'": "'"
|
|
189
|
+
}[c]));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function ovT(key, vars) {
|
|
193
|
+
return (window.I18n && window.I18n.t(key, vars)) || key;
|
|
194
|
+
}
|
|
195
|
+
|
|
185
196
|
const OVERLAY_HTML = `
|
|
186
197
|
<div class="agent-overlay" id="agent-overlay" role="dialog" aria-modal="true" aria-hidden="true">
|
|
187
198
|
<div class="agent-card" role="document">
|
|
188
199
|
<div class="agent-classification">
|
|
189
|
-
<span><span class="dot">●</span> agent · personnel file</span>
|
|
190
|
-
<span class="right">// classified</span>
|
|
200
|
+
<span><span class="dot">●</span> <span data-i18n="ao_personnel_kicker">agent · personnel file</span></span>
|
|
201
|
+
<span class="right" data-i18n="ao_classified_mark">// classified</span>
|
|
191
202
|
</div>
|
|
192
203
|
<header class="agent-card-head">
|
|
193
204
|
<img class="agent-card-avatar" src="" alt="">
|
|
@@ -196,17 +207,17 @@
|
|
|
196
207
|
<div class="role"></div>
|
|
197
208
|
<div class="handle"></div>
|
|
198
209
|
</div>
|
|
199
|
-
<button type="button" class="agent-card-close" aria-label="Close">✕</button>
|
|
210
|
+
<button type="button" class="agent-card-close" data-i18n-aria="us_close" aria-label="Close">✕</button>
|
|
200
211
|
</header>
|
|
201
212
|
<div class="agent-card-body">
|
|
202
213
|
|
|
203
214
|
<div class="agent-block">
|
|
204
|
-
<div class="agent-block-label">Lens</div>
|
|
215
|
+
<div class="agent-block-label" data-i18n="ao_lens">Lens</div>
|
|
205
216
|
<p class="agent-lens"></p>
|
|
206
217
|
</div>
|
|
207
218
|
|
|
208
219
|
<div class="agent-block agent-model-block">
|
|
209
|
-
<div class="agent-block-label">Model</div>
|
|
220
|
+
<div class="agent-block-label" data-i18n="ao_model">Model</div>
|
|
210
221
|
<div class="agent-model-display">
|
|
211
222
|
<span class="agent-model-name"></span>
|
|
212
223
|
<span class="agent-model-provider"></span>
|
|
@@ -214,32 +225,31 @@
|
|
|
214
225
|
</div>
|
|
215
226
|
|
|
216
227
|
<div class="agent-block">
|
|
217
|
-
<div class="agent-block-label">Style</div>
|
|
228
|
+
<div class="agent-block-label" data-i18n="ao_style">Style</div>
|
|
218
229
|
<div class="agent-traits"></div>
|
|
219
230
|
</div>
|
|
220
231
|
|
|
221
232
|
<div class="agent-block private-only">
|
|
222
233
|
<div class="agent-block-label">
|
|
223
|
-
In-Room Memory
|
|
224
|
-
<span class="badge">this room</span>
|
|
234
|
+
<span data-i18n="ao_memory_room">In-Room Memory</span>
|
|
235
|
+
<span class="badge" data-i18n="ao_badge_this_room">this room</span>
|
|
225
236
|
</div>
|
|
226
237
|
<div class="agent-memory-list" data-agent-room-notes></div>
|
|
227
238
|
</div>
|
|
228
239
|
|
|
229
240
|
<div class="agent-block private-only">
|
|
230
|
-
<div class="agent-block-label">Track Record</div>
|
|
241
|
+
<div class="agent-block-label" data-i18n="ap_track_record">Track Record</div>
|
|
231
242
|
<div class="agent-stats"></div>
|
|
232
243
|
</div>
|
|
233
244
|
|
|
234
245
|
<div class="agent-block public-only">
|
|
235
246
|
<div class="agent-block-label">
|
|
236
|
-
In-Room Memory
|
|
237
|
-
<span class="badge locked-badge">⊘ classified</span>
|
|
247
|
+
<span data-i18n="ao_memory_room">In-Room Memory</span>
|
|
248
|
+
<span class="badge locked-badge" data-i18n="ao_badge_classified">⊘ classified</span>
|
|
238
249
|
</div>
|
|
239
250
|
<div class="agent-locked">
|
|
240
251
|
<div class="lock-icon">▰</div>
|
|
241
|
-
<div class="lock-text">
|
|
242
|
-
in-room notes are private to each thinker.
|
|
252
|
+
<div class="lock-text" data-i18n-html="ao_lock_blurb_html">in-room notes are private to each thinker.
|
|
243
253
|
<a href="/" class="lock-link">sign in →</a>
|
|
244
254
|
to see what they have said and where their stance shifted.
|
|
245
255
|
</div>
|
|
@@ -248,10 +258,10 @@
|
|
|
248
258
|
|
|
249
259
|
</div>
|
|
250
260
|
<footer class="agent-card-foot">
|
|
251
|
-
<div class="meta private-only">tenure
|
|
252
|
-
<div class="meta public-only">first room
|
|
253
|
-
<a href="/#convene" class="agent-card-cta private-only">[ ◆ Convene with them ]</a>
|
|
254
|
-
<a href="/#convene" class="agent-card-cta public-only">[ → Sign in to convene ]</a>
|
|
261
|
+
<div class="meta private-only"><span data-i18n="ao_tenure_meta">tenure ·</span> <span class="lime agent-tenure"></span></div>
|
|
262
|
+
<div class="meta public-only"><span data-i18n="ao_first_room_meta">first room ·</span> <span class="lime" data-i18n="ao_free">free</span></div>
|
|
263
|
+
<a href="/#convene" class="agent-card-cta private-only" data-i18n="ao_convene_cta">[ ◆ Convene with them ]</a>
|
|
264
|
+
<a href="/#convene" class="agent-card-cta public-only" data-i18n="ao_signin_cta">[ → Sign in to convene ]</a>
|
|
255
265
|
</footer>
|
|
256
266
|
</div>
|
|
257
267
|
</div>
|
|
@@ -285,17 +295,21 @@
|
|
|
285
295
|
// Privacy mode: pages can opt-in via <body data-agent-mode="public">,
|
|
286
296
|
// which hides personal memory/stats and swaps the CTA to a sign-in.
|
|
287
297
|
const isPublic = document.body.dataset.agentMode === "public";
|
|
288
|
-
const
|
|
289
|
-
if (isPublic)
|
|
298
|
+
const overlay = document.getElementById("agent-overlay");
|
|
299
|
+
if (isPublic) overlay.classList.add("public");
|
|
300
|
+
if (window.I18n && typeof window.I18n.applyDom === "function") {
|
|
301
|
+
window.I18n.applyDom(overlay);
|
|
302
|
+
}
|
|
290
303
|
|
|
291
304
|
autoTagAvatars();
|
|
292
305
|
// Re-run after short delay in case other scripts mutate the DOM
|
|
293
306
|
setTimeout(autoTagAvatars, 50);
|
|
294
307
|
|
|
295
|
-
const overlay = document.getElementById("agent-overlay");
|
|
296
308
|
const card = overlay.querySelector(".agent-card");
|
|
297
309
|
const closeBtn = overlay.querySelector(".agent-card-close");
|
|
298
310
|
|
|
311
|
+
let overlayOpenSlug = null;
|
|
312
|
+
|
|
299
313
|
/** Auto-hide scrollbar · adds `.is-scrolling` to a scroll container
|
|
300
314
|
* for ~700ms after each scroll event. The CSS uses that class
|
|
301
315
|
* alongside :hover to show the thumb only while the user is
|
|
@@ -322,7 +336,7 @@
|
|
|
322
336
|
function buildLiveAgentCard(live) {
|
|
323
337
|
return {
|
|
324
338
|
name: live.name,
|
|
325
|
-
role: live.roleTag || "
|
|
339
|
+
role: live.roleTag || ovT("ap_live_agent_director"),
|
|
326
340
|
handle: live.handle || ("/" + live.id),
|
|
327
341
|
avatar: live.avatarPath || "",
|
|
328
342
|
lens: live.bio || "",
|
|
@@ -345,6 +359,7 @@
|
|
|
345
359
|
if (live) a = buildLiveAgentCard(live);
|
|
346
360
|
}
|
|
347
361
|
if (!a) return;
|
|
362
|
+
overlayOpenSlug = slug;
|
|
348
363
|
// Avatar source-of-truth · the live agent record's avatarPath
|
|
349
364
|
// (same field the agent profile renders). For seeds this is an
|
|
350
365
|
// absolute path "/avatars/<slug>.svg"; for customs it's a data:
|
|
@@ -356,7 +371,11 @@
|
|
|
356
371
|
av.src = (live && live.avatarPath) ? live.avatarPath : a.avatar;
|
|
357
372
|
av.alt = a.name;
|
|
358
373
|
card.querySelector(".agent-card-id .name").textContent = a.name;
|
|
359
|
-
|
|
374
|
+
let roleDisp = a.role;
|
|
375
|
+
if (live && live.roleKind === "moderator" && String(roleDisp).toLowerCase() === "moderator") {
|
|
376
|
+
roleDisp = ovT("agent_role_tag_moderator");
|
|
377
|
+
}
|
|
378
|
+
card.querySelector(".agent-card-id .role").textContent = roleDisp;
|
|
360
379
|
card.querySelector(".agent-card-id .handle").textContent = a.handle;
|
|
361
380
|
card.querySelector(".agent-lens").textContent = a.lens;
|
|
362
381
|
|
|
@@ -473,7 +492,7 @@
|
|
|
473
492
|
list.innerHTML = `
|
|
474
493
|
<div class="agent-memory-empty">
|
|
475
494
|
<div class="lock-icon">○</div>
|
|
476
|
-
<div class="lock-text"
|
|
495
|
+
<div class="lock-text">${escapeHtml(ovT("ao_room_notes_empty"))}</div>
|
|
477
496
|
</div>
|
|
478
497
|
`;
|
|
479
498
|
return;
|
|
@@ -482,7 +501,7 @@
|
|
|
482
501
|
list.innerHTML = `
|
|
483
502
|
<div class="agent-memory-empty">
|
|
484
503
|
<div class="lock-icon">○</div>
|
|
485
|
-
<div class="lock-text"
|
|
504
|
+
<div class="lock-text">${escapeHtml(ovT("ao_room_notes_waiting"))}</div>
|
|
486
505
|
</div>
|
|
487
506
|
`;
|
|
488
507
|
return;
|
|
@@ -494,10 +513,10 @@
|
|
|
494
513
|
: n.tag;
|
|
495
514
|
return `
|
|
496
515
|
<div class="agent-note-entry ${cls}">
|
|
497
|
-
<div class="agent-note-time">${
|
|
516
|
+
<div class="agent-note-time">${escapeHtml(formatTime(n.ts))}</div>
|
|
498
517
|
<div class="agent-note-body">
|
|
499
|
-
<span class="agent-note-tag t-${
|
|
500
|
-
${
|
|
518
|
+
<span class="agent-note-tag t-${escapeHtml(n.tag)}">${escapeHtml(tagLabel)}</span>
|
|
519
|
+
${escapeHtml(n.body)}
|
|
501
520
|
</div>
|
|
502
521
|
</div>
|
|
503
522
|
`;
|
|
@@ -510,9 +529,9 @@
|
|
|
510
529
|
// Render placeholders immediately, then patch in real values
|
|
511
530
|
// once the fetch resolves. Keeps the overlay snappy on open.
|
|
512
531
|
stats.innerHTML = `
|
|
513
|
-
<div class="agent-stat"><div class="v" data-stat-v="rooms">—</div><div class="l"
|
|
514
|
-
<div class="agent-stat"><div class="v" data-stat-v="rounds">—</div><div class="l"
|
|
515
|
-
<div class="agent-stat"><div class="v" data-stat-v="tokens">—</div><div class="l"
|
|
532
|
+
<div class="agent-stat"><div class="v" data-stat-v="rooms">—</div><div class="l">${escapeHtml(ovT("ap_stat_rooms"))}</div></div>
|
|
533
|
+
<div class="agent-stat"><div class="v" data-stat-v="rounds">—</div><div class="l">${escapeHtml(ovT("ap_stat_rounds"))}</div></div>
|
|
534
|
+
<div class="agent-stat"><div class="v" data-stat-v="tokens">—</div><div class="l">${escapeHtml(ovT("ap_stat_tokens"))}</div></div>
|
|
516
535
|
`;
|
|
517
536
|
fetch("/api/agents/" + encodeURIComponent(slug) + "/stats")
|
|
518
537
|
.then((r) => (r.ok ? r.json() : Promise.reject(new Error("HTTP " + r.status))))
|
|
@@ -544,16 +563,20 @@
|
|
|
544
563
|
}
|
|
545
564
|
|
|
546
565
|
function close() {
|
|
566
|
+
overlayOpenSlug = null;
|
|
547
567
|
overlay.classList.remove("open");
|
|
548
568
|
overlay.setAttribute("aria-hidden", "true");
|
|
549
569
|
document.body.style.overflow = "";
|
|
550
570
|
}
|
|
551
571
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
572
|
+
document.addEventListener("boardroom:locale", () => {
|
|
573
|
+
if (!overlay.classList.contains("open") || !overlayOpenSlug) return;
|
|
574
|
+
if (window.I18n && typeof window.I18n.applyDom === "function") {
|
|
575
|
+
window.I18n.applyDom(overlay);
|
|
576
|
+
}
|
|
577
|
+
renderTrackRecord(overlayOpenSlug);
|
|
578
|
+
renderRoomNotes(overlayOpenSlug);
|
|
579
|
+
});
|
|
557
580
|
|
|
558
581
|
document.addEventListener("click", (e) => {
|
|
559
582
|
const trigger = e.target.closest("[data-agent]");
|