privateboard 0.1.19 → 0.1.21
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/boot.js +239 -34
- package/dist/boot.js.map +1 -1
- package/dist/cli.js +239 -34
- package/dist/cli.js.map +1 -1
- package/dist/server.js +239 -34
- package/dist/server.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +14 -3
- package/public/adjourn-overlay.css +19 -19
- package/public/agent-overlay.css +71 -71
- package/public/agent-profile.css +66 -66
- package/public/agent-profile.js +32 -31
- package/public/app.js +80 -22
- package/public/home.html +4 -136
- package/public/i18n.js +20 -16
- package/public/icons/fold.png +0 -0
- package/public/index.html +198 -94
- package/public/new-agent.css +111 -110
- package/public/new-agent.js +4 -1
- package/public/onboarding.css +96 -96
- package/public/onboarding.js +53 -24
- package/public/quote-cta.css +38 -38
- package/public/room-settings.css +145 -144
- package/public/themes.css +43 -64
- package/public/user-settings.css +257 -215
- package/public/user-settings.js +94 -13
- package/public/voice-onboarding.css +33 -33
- package/public/voice-replay.css +34 -34
package/public/app.js
CHANGED
|
@@ -308,6 +308,31 @@
|
|
|
308
308
|
: (btn.getAttribute("data-more") || this._t("convene_show_more"));
|
|
309
309
|
btn.textContent = label;
|
|
310
310
|
});
|
|
311
|
+
// Live-subtitle minimize / restore · attached in CAPTURE phase
|
|
312
|
+
// so it wins ahead of any outside-click handlers (picker dismiss
|
|
313
|
+
// / overlay close) that might `stopPropagation` and swallow the
|
|
314
|
+
// first click. Without capture, a click on the minimize button
|
|
315
|
+
// takes two presses to register — the first one gets eaten by an
|
|
316
|
+
// unrelated bubble-phase listener.
|
|
317
|
+
const onSubBtn = (e) => {
|
|
318
|
+
if (e.target.closest("[data-rt-sub-min]")) {
|
|
319
|
+
e.preventDefault();
|
|
320
|
+
e.stopPropagation();
|
|
321
|
+
document.body.classList.add("is-subtitle-min");
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (e.target.closest("[data-rt-sub-restore]")) {
|
|
325
|
+
e.preventDefault();
|
|
326
|
+
e.stopPropagation();
|
|
327
|
+
document.body.classList.remove("is-subtitle-min");
|
|
328
|
+
// Re-render so the subtitle re-populates with the latest
|
|
329
|
+
// streaming / replay state (it was hidden via CSS, not via
|
|
330
|
+
// `slot.hidden`, so its innerHTML is preserved — but a
|
|
331
|
+
// fresh paint guarantees the cursor / kicker is current).
|
|
332
|
+
this.renderRtSubtitle();
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
document.addEventListener("click", onSubBtn, true);
|
|
311
336
|
document.addEventListener("boardroom:locale", () => {
|
|
312
337
|
this.renderSidebarRooms();
|
|
313
338
|
this.renderSidebarAgents();
|
|
@@ -1471,6 +1496,16 @@
|
|
|
1471
1496
|
this.currentMessages = this.currentMessages.filter((m) => m.id !== data.messageId);
|
|
1472
1497
|
const article = document.querySelector(`[data-message-id="${data.messageId}"]`);
|
|
1473
1498
|
if (article) article.remove();
|
|
1499
|
+
// Round-table stage · the just-removed message was the in-flight
|
|
1500
|
+
// streaming placeholder. Without repainting, `renderRoundTable`'s
|
|
1501
|
+
// speaker-detection path (which scans `currentMessages` for the
|
|
1502
|
+
// most recent `meta.streaming === true` entry) keeps reporting
|
|
1503
|
+
// the removed director as still speaking — the "thinking / speaking"
|
|
1504
|
+
// bubble stays glued to their seat after a hard-pause "stop
|
|
1505
|
+
// immediately" tore the message out. Mirrors `message-final`'s
|
|
1506
|
+
// repaint at line ~1440.
|
|
1507
|
+
this.renderRoundTable();
|
|
1508
|
+
this.renderRtSubtitle();
|
|
1474
1509
|
});
|
|
1475
1510
|
|
|
1476
1511
|
this.sse.addEventListener("voice-chunk", (e) => {
|
|
@@ -1527,7 +1562,17 @@
|
|
|
1527
1562
|
|
|
1528
1563
|
this.sse.addEventListener("voice-final", (e) => {
|
|
1529
1564
|
const data = JSON.parse(e.data);
|
|
1530
|
-
|
|
1565
|
+
// Do NOT auto-create a queue entry on voice-final · this event
|
|
1566
|
+
// can arrive AFTER a hard-pause `room-paused` already cleared
|
|
1567
|
+
// `voiceQueues` (the speakerTurn finalizer runs on its own
|
|
1568
|
+
// async tick, separate from the route handler that emitted
|
|
1569
|
+
// room-paused — so the SSE ordering is voice-final-after-pause
|
|
1570
|
+
// even though emission was earlier in source code). Re-creating
|
|
1571
|
+
// the queue here re-arms renderRoundTable's voiceQueues path
|
|
1572
|
+
// and the speaking bubble glues itself to the seat forever.
|
|
1573
|
+
// If the queue is already gone, there's nothing to finalize.
|
|
1574
|
+
const q = this.voiceQueues[data.messageId];
|
|
1575
|
+
if (!q) return;
|
|
1531
1576
|
q.final = true;
|
|
1532
1577
|
q.messageId = data.messageId;
|
|
1533
1578
|
q.roomId = roomId;
|
|
@@ -2634,8 +2679,8 @@
|
|
|
2634
2679
|
},
|
|
2635
2680
|
|
|
2636
2681
|
/** Pre-flight gate · returns true when at least one MODEL provider
|
|
2637
|
-
* (anthropic / openai / google / xai / deepseek / openrouter)
|
|
2638
|
-
* configured. When none are, opens a modal asking the user to
|
|
2682
|
+
* (anthropic / openai / google / xai / deepseek / openrouter / bai)
|
|
2683
|
+
* is configured. When none are, opens a modal asking the user to
|
|
2639
2684
|
* configure a key + returns false. Brave is search, not a model
|
|
2640
2685
|
* provider, so it's intentionally excluded.
|
|
2641
2686
|
*
|
|
@@ -2853,9 +2898,15 @@
|
|
|
2853
2898
|
/** Pure cache read · returns true when the local app.keys map
|
|
2854
2899
|
* reports any model provider as configured. Used by the gate
|
|
2855
2900
|
* and (via wrappers) anywhere downstream UI needs the answer
|
|
2856
|
-
* cheaply.
|
|
2901
|
+
* cheaply.
|
|
2902
|
+
*
|
|
2903
|
+
* Mirror the server-side LLM_PROVIDERS set (`routes/keys.ts:47`).
|
|
2904
|
+
* Without B.AI in this list, a user who configured ONLY a B.AI
|
|
2905
|
+
* key gets bounced to "configure an API key first" on every
|
|
2906
|
+
* pre-flight gate (topic-recs trigger, convene a room, etc.)
|
|
2907
|
+
* even though every model with a baiId is fully reachable. */
|
|
2857
2908
|
hasAnyModelKey() {
|
|
2858
|
-
const MODEL_PROVIDERS = ["anthropic", "openai", "google", "xai", "deepseek", "openrouter"];
|
|
2909
|
+
const MODEL_PROVIDERS = ["anthropic", "openai", "google", "xai", "deepseek", "openrouter", "bai"];
|
|
2859
2910
|
const keys = this.keys || {};
|
|
2860
2911
|
return MODEL_PROVIDERS.some((p) => keys[p] && keys[p].configured);
|
|
2861
2912
|
},
|
|
@@ -9261,10 +9312,14 @@
|
|
|
9261
9312
|
// quote dots never collide with the title text · the deco
|
|
9262
9313
|
// stays visible only at the periphery + along the top band.
|
|
9263
9314
|
// Same hygiene pass as the agent composer's motif.
|
|
9315
|
+
// All motif fills below pull from theme tokens (`--accent-line`
|
|
9316
|
+
// is the brand-tinted hairline = very subtle in both themes)
|
|
9317
|
+
// so the backdrop adopts the page's palette instead of staying
|
|
9318
|
+
// a fixed wood-brown patch that looks "dirty" on a light bg.
|
|
9264
9319
|
const chairs = [
|
|
9265
|
-
{ x: 108, y: 138
|
|
9266
|
-
{ x: 372, y: 46
|
|
9267
|
-
{ x: 678, y: 148
|
|
9320
|
+
{ x: 108, y: 138 },
|
|
9321
|
+
{ x: 372, y: 46 },
|
|
9322
|
+
{ x: 678, y: 148 },
|
|
9268
9323
|
];
|
|
9269
9324
|
const sparks = [
|
|
9270
9325
|
[98, 78], [640, 62], [588, 156],
|
|
@@ -9274,20 +9329,16 @@
|
|
|
9274
9329
|
];
|
|
9275
9330
|
motif = `
|
|
9276
9331
|
<g shape-rendering="crispEdges">
|
|
9277
|
-
<!-- Mini chair silhouettes
|
|
9332
|
+
<!-- Mini chair silhouettes — fill pulled from theme token -->
|
|
9278
9333
|
${chairs.map((c, i) => `
|
|
9279
|
-
<g class="deco-bob" ${_delay(i + 3, 3.2)} fill="
|
|
9334
|
+
<g class="deco-bob" ${_delay(i + 3, 3.2)} fill="var(--accent-line)">
|
|
9280
9335
|
<rect x="${c.x}" y="${c.y + 10}" width="6" height="2"/>
|
|
9281
9336
|
<rect x="${c.x}" y="${c.y}" width="2" height="10"/>
|
|
9282
9337
|
<rect x="${c.x + 6}" y="${c.y}" width="2" height="10"/>
|
|
9283
9338
|
</g>
|
|
9284
9339
|
`).join("")}
|
|
9285
|
-
<!-- Tiny microphones · static (small, would feel busy).
|
|
9286
|
-
|
|
9287
|
-
(244, 216) cyan moderator chair — both sat in the
|
|
9288
|
-
title's footprint and read as typos behind the
|
|
9289
|
-
prompt. -->
|
|
9290
|
-
<g fill="#8E8B83">
|
|
9340
|
+
<!-- Tiny microphones · static (small, would feel busy). -->
|
|
9341
|
+
<g fill="var(--accent-line)">
|
|
9291
9342
|
<rect x="226" y="46" width="3" height="2"/>
|
|
9292
9343
|
<rect x="227" y="42" width="1" height="4"/>
|
|
9293
9344
|
<rect x="514" y="100" width="3" height="2"/>
|
|
@@ -9328,11 +9379,13 @@
|
|
|
9328
9379
|
];
|
|
9329
9380
|
motif = `
|
|
9330
9381
|
<g shape-rendering="crispEdges">
|
|
9331
|
-
<!-- Mini character heads ·
|
|
9382
|
+
<!-- Mini character heads · fills pulled from theme tokens
|
|
9383
|
+
so the heads stop reading as out-of-place skin-tan +
|
|
9384
|
+
dark-brown patches against a white bg. -->
|
|
9332
9385
|
${heads.map(([x, y], i) => `
|
|
9333
9386
|
<g class="deco-bob" ${_delay(i + 21, 3.0)}>
|
|
9334
|
-
<rect x="${x}" y="${y}" width="4" height="4" fill="
|
|
9335
|
-
<rect x="${x}" y="${y}" width="4" height="1" fill="
|
|
9387
|
+
<rect x="${x}" y="${y}" width="4" height="4" fill="var(--accent-line)"/>
|
|
9388
|
+
<rect x="${x}" y="${y}" width="4" height="1" fill="var(--lime-dim)"/>
|
|
9336
9389
|
</g>
|
|
9337
9390
|
`).join("")}
|
|
9338
9391
|
<!-- Tiny speech bubbles · 10×6 pill with 1-pixel tail · blink -->
|
|
@@ -16184,6 +16237,11 @@
|
|
|
16184
16237
|
renderRtSubtitle() {
|
|
16185
16238
|
const slot = document.querySelector("[data-rt-subtitle]");
|
|
16186
16239
|
if (!slot) return;
|
|
16240
|
+
// Minimize-affordance template · prepended to every populated
|
|
16241
|
+
// innerHTML branch below so the corner button is present on the
|
|
16242
|
+
// thinking / streaming / replay variants without being a sibling
|
|
16243
|
+
// of the slot (which would survive the slot.hidden = true reset).
|
|
16244
|
+
const minBtn = `<button type="button" class="rt-sub-min" data-rt-sub-min title="Minimize" aria-label="Minimize subtitle"></button>`;
|
|
16187
16245
|
const msgs = this.currentMessages || [];
|
|
16188
16246
|
let speakerId = null;
|
|
16189
16247
|
let body = "";
|
|
@@ -16264,7 +16322,7 @@
|
|
|
16264
16322
|
})[stage];
|
|
16265
16323
|
if (titleKey && deckKey) {
|
|
16266
16324
|
slot.hidden = false;
|
|
16267
|
-
slot.innerHTML =
|
|
16325
|
+
slot.innerHTML = minBtn +
|
|
16268
16326
|
`<span class="rt-sub-kicker">${this.escape(this.currentChair.name || "")} · ${this.escape(this._t(titleKey))}</span>` +
|
|
16269
16327
|
`<p class="rt-sub-text rt-sub-thinking">` +
|
|
16270
16328
|
`<span class="rt-sub-dots" aria-hidden="true"><i></i><i></i><i></i></span>` +
|
|
@@ -16304,7 +16362,7 @@
|
|
|
16304
16362
|
// to the normal caption render below.
|
|
16305
16363
|
if (isStreaming) {
|
|
16306
16364
|
slot.hidden = false;
|
|
16307
|
-
slot.innerHTML =
|
|
16365
|
+
slot.innerHTML = minBtn +
|
|
16308
16366
|
`<span class="rt-sub-kicker">${this.escape(speaker.name || "")}</span>` +
|
|
16309
16367
|
`<p class="rt-sub-text rt-sub-thinking">` +
|
|
16310
16368
|
`<span class="rt-sub-dots" aria-hidden="true"><i></i><i></i><i></i></span>` +
|
|
@@ -16395,7 +16453,7 @@
|
|
|
16395
16453
|
visible = parts.length ? parts[parts.length - 1] : text;
|
|
16396
16454
|
}
|
|
16397
16455
|
slot.hidden = false;
|
|
16398
|
-
slot.innerHTML =
|
|
16456
|
+
slot.innerHTML = minBtn +
|
|
16399
16457
|
`<span class="rt-sub-kicker">${this.escape(speaker.name || "")}</span>` +
|
|
16400
16458
|
`<p class="rt-sub-text">${this.escape(visible.trim())}</p>`;
|
|
16401
16459
|
},
|
package/public/home.html
CHANGED
|
@@ -370,114 +370,6 @@
|
|
|
370
370
|
}
|
|
371
371
|
@media (max-width: 700px) { .section { padding: 24px 18px; } }
|
|
372
372
|
|
|
373
|
-
/* ─── Mac download card · sits at the top of `#install` as the
|
|
374
|
-
primary install path for macOS users. Spans both grid columns
|
|
375
|
-
so the lime download button reads as the section's hero CTA.
|
|
376
|
-
Brutalist register · hairline border + bracketed corner marks
|
|
377
|
-
(lime ones, same vocabulary as `.install` / `.hero-right` /
|
|
378
|
-
`.final-cta`), mono kicker + meta, generous click target. */
|
|
379
|
-
.install-mac {
|
|
380
|
-
grid-column: 1 / -1;
|
|
381
|
-
display: flex;
|
|
382
|
-
align-items: center;
|
|
383
|
-
gap: 24px;
|
|
384
|
-
padding: 22px 26px;
|
|
385
|
-
background: var(--bg);
|
|
386
|
-
border: 1px solid var(--line-bright);
|
|
387
|
-
position: relative;
|
|
388
|
-
flex-wrap: wrap;
|
|
389
|
-
}
|
|
390
|
-
.install-mac::before,
|
|
391
|
-
.install-mac::after {
|
|
392
|
-
content: "";
|
|
393
|
-
position: absolute;
|
|
394
|
-
width: 10px; height: 10px;
|
|
395
|
-
border: 1px solid var(--lime);
|
|
396
|
-
}
|
|
397
|
-
.install-mac::before {
|
|
398
|
-
top: -1px; left: -1px;
|
|
399
|
-
border-right: none; border-bottom: none;
|
|
400
|
-
}
|
|
401
|
-
.install-mac::after {
|
|
402
|
-
bottom: -1px; right: -1px;
|
|
403
|
-
border-left: none; border-top: none;
|
|
404
|
-
}
|
|
405
|
-
.install-mac-meta {
|
|
406
|
-
flex: 1 1 320px;
|
|
407
|
-
min-width: 0;
|
|
408
|
-
}
|
|
409
|
-
.install-mac-kicker {
|
|
410
|
-
font-family: var(--mono);
|
|
411
|
-
font-size: 10px;
|
|
412
|
-
letter-spacing: 0.22em;
|
|
413
|
-
color: var(--lime);
|
|
414
|
-
text-transform: uppercase;
|
|
415
|
-
font-weight: 700;
|
|
416
|
-
margin-bottom: 8px;
|
|
417
|
-
}
|
|
418
|
-
.install-mac-kicker::before { content: "▸ "; }
|
|
419
|
-
.install-mac-title {
|
|
420
|
-
font-size: 22px;
|
|
421
|
-
font-weight: 700;
|
|
422
|
-
color: var(--text);
|
|
423
|
-
letter-spacing: -0.005em;
|
|
424
|
-
margin-bottom: 6px;
|
|
425
|
-
line-height: 1.2;
|
|
426
|
-
}
|
|
427
|
-
.install-mac-sub {
|
|
428
|
-
font-family: var(--mono);
|
|
429
|
-
font-size: 11px;
|
|
430
|
-
color: var(--text-soft);
|
|
431
|
-
letter-spacing: 0.06em;
|
|
432
|
-
display: flex;
|
|
433
|
-
flex-wrap: wrap;
|
|
434
|
-
gap: 6px 8px;
|
|
435
|
-
align-items: center;
|
|
436
|
-
}
|
|
437
|
-
.install-mac-sub .im-sep { color: var(--text-faint); }
|
|
438
|
-
.install-mac-sub .im-ok {
|
|
439
|
-
color: var(--lime);
|
|
440
|
-
/* Bracketed `[ ✓ ]` mark reused from `.install-bullet` vocabulary
|
|
441
|
-
— same visual cue for "verified / passes". */
|
|
442
|
-
}
|
|
443
|
-
.install-mac-btn {
|
|
444
|
-
display: inline-flex;
|
|
445
|
-
align-items: center;
|
|
446
|
-
gap: 10px;
|
|
447
|
-
padding: 14px 22px;
|
|
448
|
-
background: var(--lime);
|
|
449
|
-
color: var(--bg);
|
|
450
|
-
border: 1px solid var(--lime);
|
|
451
|
-
font-family: var(--mono);
|
|
452
|
-
font-size: 13px;
|
|
453
|
-
font-weight: 700;
|
|
454
|
-
letter-spacing: 0.14em;
|
|
455
|
-
text-transform: uppercase;
|
|
456
|
-
text-decoration: none;
|
|
457
|
-
transition: background 0.12s, color 0.12s, border-color 0.12s, transform 0.12s;
|
|
458
|
-
white-space: nowrap;
|
|
459
|
-
flex-shrink: 0;
|
|
460
|
-
}
|
|
461
|
-
.install-mac-btn:hover {
|
|
462
|
-
background: var(--bg);
|
|
463
|
-
color: var(--lime);
|
|
464
|
-
}
|
|
465
|
-
.install-mac-btn:active { transform: translateY(1px); }
|
|
466
|
-
.install-mac-btn .im-btn-mark {
|
|
467
|
-
font-size: 16px;
|
|
468
|
-
line-height: 1;
|
|
469
|
-
}
|
|
470
|
-
/* Mobile: stack meta above button, full-width button so it remains
|
|
471
|
-
a clear primary CTA on narrow screens. */
|
|
472
|
-
@media (max-width: 700px) {
|
|
473
|
-
.install-mac { padding: 18px 18px; gap: 16px; }
|
|
474
|
-
.install-mac-btn {
|
|
475
|
-
width: 100%;
|
|
476
|
-
justify-content: center;
|
|
477
|
-
padding: 14px 18px;
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
373
|
/* ─── Install module · terminal-flavored ─── */
|
|
482
374
|
.install {
|
|
483
375
|
background: var(--panel);
|
|
@@ -1910,7 +1802,10 @@
|
|
|
1910
1802
|
|
|
1911
1803
|
<div class="hero-actions">
|
|
1912
1804
|
<a href="#install" class="big-btn primary">[ ◆ Convene a Room ]</a>
|
|
1913
|
-
<a href="
|
|
1805
|
+
<a href="https://github.com/kaysaith1900/privateboard/releases/download/v0.1.18/PrivateBoard-0.1.18-arm64.dmg"
|
|
1806
|
+
class="big-btn secondary"
|
|
1807
|
+
download
|
|
1808
|
+
aria-label="Download PrivateBoard for macOS (Apple Silicon)"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M12 3v12"/><polyline points="6 11 12 17 18 11"/><path d="M5 21h14"/></svg> Download for Mac</a>
|
|
1914
1809
|
</div>
|
|
1915
1810
|
</div>
|
|
1916
1811
|
|
|
@@ -1976,33 +1871,6 @@
|
|
|
1976
1871
|
|
|
1977
1872
|
<!-- ─────────── INSTALL · LOCAL-FIRST ─────────── -->
|
|
1978
1873
|
<section class="install bracketed" id="install">
|
|
1979
|
-
<!-- Mac download card · primary install path for macOS users.
|
|
1980
|
-
Sits above the terminal install card so it's the first thing
|
|
1981
|
-
the eye lands on inside the install section. CLI install
|
|
1982
|
-
(npx / npm) lives in the existing 2-col grid below for users
|
|
1983
|
-
who'd rather run from the terminal. -->
|
|
1984
|
-
<div class="install-mac">
|
|
1985
|
-
<div class="install-mac-meta">
|
|
1986
|
-
<div class="install-mac-kicker">macOS · desktop app</div>
|
|
1987
|
-
<div class="install-mac-title">PrivateBoard.app</div>
|
|
1988
|
-
<div class="install-mac-sub">
|
|
1989
|
-
<span>v0.1.18</span>
|
|
1990
|
-
<span class="im-sep">·</span>
|
|
1991
|
-
<span>Apple Silicon</span>
|
|
1992
|
-
<span class="im-sep">·</span>
|
|
1993
|
-
<span>123 MB</span>
|
|
1994
|
-
<span class="im-sep">·</span>
|
|
1995
|
-
<span class="im-ok">[ ✓ ] signed & notarized</span>
|
|
1996
|
-
</div>
|
|
1997
|
-
</div>
|
|
1998
|
-
<a href="https://github.com/kaysaith1900/privateboard/releases/download/v0.1.18/PrivateBoard-0.1.18-arm64.dmg"
|
|
1999
|
-
class="install-mac-btn"
|
|
2000
|
-
download>
|
|
2001
|
-
<span class="im-btn-mark">↓</span>
|
|
2002
|
-
<span class="im-btn-text">Download .dmg</span>
|
|
2003
|
-
</a>
|
|
2004
|
-
</div>
|
|
2005
|
-
|
|
2006
1874
|
<div class="install-head">
|
|
2007
1875
|
<div class="install-tag">▸ install · runs locally</div>
|
|
2008
1876
|
<h2 class="install-title">Bring PrivateBoard to your terminal.</h2>
|
package/public/i18n.js
CHANGED
|
@@ -383,7 +383,6 @@
|
|
|
383
383
|
ao_tenure_meta: "tenure ·",
|
|
384
384
|
ao_first_room_meta: "first room ·",
|
|
385
385
|
ao_free: "free",
|
|
386
|
-
ao_convene_cta: "[ ◆ Convene with them ]",
|
|
387
386
|
ao_signin_cta: "[ → Sign in to convene ]",
|
|
388
387
|
ao_room_notes_empty: "no live room. open a room to see this director's in-room notes.",
|
|
389
388
|
ao_room_notes_waiting: "no turns yet — once they speak, claims and stance shifts land here.",
|
|
@@ -551,8 +550,10 @@
|
|
|
551
550
|
onb_v2_key_title: "Pick one brain — or pick many.",
|
|
552
551
|
onb_v2_key_body: "Your key stays on this machine. We never upload it.",
|
|
553
552
|
onb_v2_key_recommend_badge: "// recommended",
|
|
554
|
-
|
|
555
|
-
|
|
553
|
+
onb_v2_key_recommend_openrouter_name: "OpenRouter · one key, every model",
|
|
554
|
+
onb_v2_key_recommend_openrouter_body: "Each director can run on a different model — Claude as the skeptic, GPT as the pattern hunter, Gemini as the long-horizon strategist. The chair routes each turn to the right brain.",
|
|
555
|
+
onb_v2_key_recommend_bai_name: "B.AI · one key, every model",
|
|
556
|
+
onb_v2_key_recommend_bai_body: "A second universal aggregator with its own pricing and access channels. Pick whichever has the credits or regional pricing that suits you, or use it as a fallback when an OpenRouter route is throttled.",
|
|
556
557
|
onb_v2_key_or: "or — a direct provider",
|
|
557
558
|
onb_v2_key_or_body: "Same model for every director. Personas stay distinct, but they all share one brain underneath.",
|
|
558
559
|
onb_v2_voice_kicker: "03 — Give them a voice · optional",
|
|
@@ -960,7 +961,7 @@ When the room ___, raise an objection.`,
|
|
|
960
961
|
us_modal_kicker_right: "// local",
|
|
961
962
|
us_close: "Close",
|
|
962
963
|
us_nav_api_key: "API Key",
|
|
963
|
-
us_nav_other_settings: "
|
|
964
|
+
us_nav_other_settings: "General",
|
|
964
965
|
us_locale_label: "Interface language",
|
|
965
966
|
us_locale_deck:
|
|
966
967
|
"Sidebar labels, dialogs, and app chrome follow this locale. Room messages and briefs still mirror the language you write in.",
|
|
@@ -1371,7 +1372,6 @@ When the room ___, raise an objection.`,
|
|
|
1371
1372
|
ao_tenure_meta: "任期 ·",
|
|
1372
1373
|
ao_first_room_meta: "首场 ·",
|
|
1373
1374
|
ao_free: "免费",
|
|
1374
|
-
ao_convene_cta: "[ ◆ 与其开会 ]",
|
|
1375
1375
|
ao_signin_cta: "[ → 登录后召开 ]",
|
|
1376
1376
|
ao_room_notes_empty: "当前无进行中的会议 · 打开会议室后可查看该董事的场内笔记。",
|
|
1377
1377
|
ao_room_notes_waiting: "尚未发言 · 发言后关键论断与立场变化会出现在此。",
|
|
@@ -1526,8 +1526,10 @@ When the room ___, raise an objection.`,
|
|
|
1526
1526
|
onb_v2_key_title: "选一个脑袋,或者一群脑袋。",
|
|
1527
1527
|
onb_v2_key_body: "Key 只留在这台机器上,我们不会上传。",
|
|
1528
1528
|
onb_v2_key_recommend_badge: "// 推荐",
|
|
1529
|
-
|
|
1530
|
-
|
|
1529
|
+
onb_v2_key_recommend_openrouter_name: "OpenRouter · 一把钥匙,所有模型",
|
|
1530
|
+
onb_v2_key_recommend_openrouter_body: "每位 director 可以跑在不同的模型上——Claude 当怀疑论者,GPT 当模式猎手,Gemini 当长期主义者。主席每一轮都会把发言派给最合适的脑袋。",
|
|
1531
|
+
onb_v2_key_recommend_bai_name: "B.AI · 一把钥匙,所有模型",
|
|
1532
|
+
onb_v2_key_recommend_bai_body: "另一家通用聚合器——和 OpenRouter 一样一把钥匙跑全部模型,自带定价与渠道。挑一个对你区域更顺手的,或在 OpenRouter 限流时作为备用线路。",
|
|
1531
1533
|
onb_v2_key_or: "或者,用一家直连厂商",
|
|
1532
1534
|
onb_v2_key_or_body: "所有 director 共用一个模型。人格仍然各异,但底下是同一颗脑袋。",
|
|
1533
1535
|
onb_v2_voice_kicker: "03 — 让他们开口说话 · 可跳过",
|
|
@@ -1929,7 +1931,7 @@ When the room ___, raise an objection.`,
|
|
|
1929
1931
|
us_modal_kicker_right: "// 本地",
|
|
1930
1932
|
us_close: "关闭",
|
|
1931
1933
|
us_nav_api_key: "API 密钥",
|
|
1932
|
-
us_nav_other_settings: "
|
|
1934
|
+
us_nav_other_settings: "通用",
|
|
1933
1935
|
us_locale_label: "界面语言",
|
|
1934
1936
|
us_locale_deck: "侧边栏、对话框和应用外壳使用该语言;房间消息与简报仍会以你书写的内容为准。",
|
|
1935
1937
|
us_replay_onb_label: "回放 Onboarding",
|
|
@@ -2326,7 +2328,6 @@ When the room ___, raise an objection.`,
|
|
|
2326
2328
|
ao_tenure_meta: "在任 ·",
|
|
2327
2329
|
ao_first_room_meta: "最初の会議室 ·",
|
|
2328
2330
|
ao_free: "空き",
|
|
2329
|
-
ao_convene_cta: "[ ◆ 一緒に開催 ]",
|
|
2330
2331
|
ao_signin_cta: "[ → サインインして開催 ]",
|
|
2331
2332
|
ao_room_notes_empty: "進行中の会議室なし。会議室を開いてこのディレクターのノートを表示。",
|
|
2332
2333
|
ao_room_notes_waiting: "まだターンなし — 発言があれば主張と立場の変化がここに表示されます。",
|
|
@@ -2477,8 +2478,10 @@ When the room ___, raise an objection.`,
|
|
|
2477
2478
|
onb_v2_key_title: "一つの脳を選ぶ——あるいは、たくさん選ぶ。",
|
|
2478
2479
|
onb_v2_key_body: "key はこの端末にのみ保存され、サーバへ送られることはありません。",
|
|
2479
2480
|
onb_v2_key_recommend_badge: "// おすすめ",
|
|
2480
|
-
|
|
2481
|
-
|
|
2481
|
+
onb_v2_key_recommend_openrouter_name: "OpenRouter · 一つの鍵で、すべてのモデル",
|
|
2482
|
+
onb_v2_key_recommend_openrouter_body: "各 director がそれぞれ違うモデルで動けます——Claude は懐疑家、GPT はパターン捜索、Gemini は長期戦略家。議長が毎ターン、最適な脳に発言を振り分けます。",
|
|
2483
|
+
onb_v2_key_recommend_bai_name: "B.AI · 一つの鍵で、すべてのモデル",
|
|
2484
|
+
onb_v2_key_recommend_bai_body: "もう一つの統合アグリゲーター。OpenRouter と同じ「一鍵で全モデル」、独自の価格・経路。地域や残高に合うほうを選ぶか、OpenRouter のスロットリング時のバックアップとして併用できます。",
|
|
2482
2485
|
onb_v2_key_or: "あるいは、直接プロバイダ",
|
|
2483
2486
|
onb_v2_key_or_body: "全 director が同じモデルを共有します。ペルソナは別々ですが、土台は一つの脳です。",
|
|
2484
2487
|
onb_v2_voice_kicker: "03 — 声を与える · オプション",
|
|
@@ -2710,7 +2713,7 @@ When the room ___, raise an objection.`,
|
|
|
2710
2713
|
us_modal_kicker_right: "// ローカル",
|
|
2711
2714
|
us_close: "閉じる",
|
|
2712
2715
|
us_nav_api_key: "API キー",
|
|
2713
|
-
us_nav_other_settings: "
|
|
2716
|
+
us_nav_other_settings: "一般",
|
|
2714
2717
|
us_locale_label: "インターフェース言語",
|
|
2715
2718
|
us_locale_deck: "サイドバー、ダイアログ、アプリ全体のクロームがこの言語に従います。会議室のメッセージとブリーフはあなたが書いた言語のままです。",
|
|
2716
2719
|
us_replay_onb_label: "オンボーディングを再生",
|
|
@@ -3097,7 +3100,6 @@ When the room ___, raise an objection.`,
|
|
|
3097
3100
|
ao_tenure_meta: "antigüedad ·",
|
|
3098
3101
|
ao_first_room_meta: "primera sala ·",
|
|
3099
3102
|
ao_free: "libre",
|
|
3100
|
-
ao_convene_cta: "[ ◆ Convocar con ellos ]",
|
|
3101
3103
|
ao_signin_cta: "[ → Inicia sesión para convocar ]",
|
|
3102
3104
|
ao_room_notes_empty: "ninguna sala en vivo. abre una sala para ver las notas de este director.",
|
|
3103
3105
|
ao_room_notes_waiting: "aún no hay turnos — cuando hablen, las afirmaciones y los cambios de postura aparecerán aquí.",
|
|
@@ -3248,8 +3250,10 @@ When the room ___, raise an objection.`,
|
|
|
3248
3250
|
onb_v2_key_title: "Elige un cerebro — o elige varios.",
|
|
3249
3251
|
onb_v2_key_body: "Tu key se queda en esta máquina. Nunca la subimos.",
|
|
3250
3252
|
onb_v2_key_recommend_badge: "// recomendado",
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
+
onb_v2_key_recommend_openrouter_name: "OpenRouter · una key, todos los modelos",
|
|
3254
|
+
onb_v2_key_recommend_openrouter_body: "Cada director puede correr en un modelo distinto — Claude como escéptico, GPT como cazador de patrones, Gemini como estratega de largo plazo. El chair enruta cada turno al cerebro adecuado.",
|
|
3255
|
+
onb_v2_key_recommend_bai_name: "B.AI · una key, todos los modelos",
|
|
3256
|
+
onb_v2_key_recommend_bai_body: "Un segundo agregador universal con sus propios precios y rutas de acceso. Elige el que tenga mejores créditos o precios regionales para ti, o úsalo como respaldo cuando una ruta de OpenRouter esté limitada.",
|
|
3253
3257
|
onb_v2_key_or: "o — un proveedor directo",
|
|
3254
3258
|
onb_v2_key_or_body: "Mismo modelo para todos los directores. Las personas siguen siendo distintas, pero comparten un solo cerebro.",
|
|
3255
3259
|
onb_v2_voice_kicker: "03 — Dales una voz · opcional",
|
|
@@ -3482,7 +3486,7 @@ When the room ___, raise an objection.`,
|
|
|
3482
3486
|
us_modal_kicker_right: "// local",
|
|
3483
3487
|
us_close: "Cerrar",
|
|
3484
3488
|
us_nav_api_key: "Clave API",
|
|
3485
|
-
us_nav_other_settings: "
|
|
3489
|
+
us_nav_other_settings: "General",
|
|
3486
3490
|
us_locale_label: "Idioma de interfaz",
|
|
3487
3491
|
us_locale_deck: "Las etiquetas de la barra lateral, los diálogos y la interfaz siguen este idioma. Los mensajes de sala y los informes mantienen el idioma en que escribes.",
|
|
3488
3492
|
us_replay_onb_label: "Repetir onboarding",
|
|
Binary file
|