privateboard 0.1.13 → 0.1.16
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 +2623 -333
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/public/adjourn-overlay.css +6 -6
- package/public/agent-build-bgm.js +292 -0
- package/public/agent-overlay.css +14 -14
- package/public/agent-profile.css +408 -87
- package/public/agent-profile.js +254 -0
- package/public/app.js +2486 -384
- package/public/home.html +26 -26
- package/public/i18n.js +1890 -21
- package/public/icons/logo2.png +0 -0
- package/public/icons/private-board-vi.html +1716 -0
- package/public/index.html +2954 -1018
- package/public/magazine.html +12 -12
- package/public/new-agent.css +29 -29
- package/public/newspaper.html +20 -20
- package/public/onboarding.css +350 -272
- package/public/onboarding.js +614 -323
- package/public/quote-cta.css +4 -4
- package/public/report.html +2008 -1673
- package/public/room-settings.css +192 -24
- package/public/room-settings.js +5 -0
- package/public/share-cover-svg-creator.js +736 -0
- package/public/themes.css +0 -34
- package/public/typing-sfx.js +176 -3
- package/public/user-settings.css +50 -27
- package/public/user-settings.js +43 -14
- package/public/voice-onboarding.css +425 -0
- package/public/voice-onboarding.js +144 -0
- package/public/voice-replay.css +31 -38
- package/public/voice-replay.js +12 -11
package/public/agent-profile.js
CHANGED
|
@@ -1173,6 +1173,44 @@
|
|
|
1173
1173
|
</button>
|
|
1174
1174
|
</section>`;
|
|
1175
1175
|
}
|
|
1176
|
+
|
|
1177
|
+
/** Build log card · sibling to the persona dossier. Surfaces a 1-line
|
|
1178
|
+
* teaser drawn from the narrator's pitch summary plus a CTA that
|
|
1179
|
+
* opens the build-log modal. Hidden when the agent has no
|
|
1180
|
+
* `personaSpec.buildLog` (older Full-mode builds without the
|
|
1181
|
+
* buildLog field; all Signal-mode agents; all seed directors). */
|
|
1182
|
+
function renderBuildLogSection(slug, p) {
|
|
1183
|
+
const live = window.app && window.app.agentsById ? window.app.agentsById[slug] : null;
|
|
1184
|
+
const spec = live && live.personaSpec ? live.personaSpec : null;
|
|
1185
|
+
const buildLog = spec && spec.buildLog ? spec.buildLog : null;
|
|
1186
|
+
if (!buildLog) return "";
|
|
1187
|
+
const narrative = typeof buildLog.narrative === "string" ? buildLog.narrative : "";
|
|
1188
|
+
// Teaser · first ~160 chars of the narrative or a localised
|
|
1189
|
+
// fallback if the narrator pass came back empty. The narrative is
|
|
1190
|
+
// plain prose so we just trim on the nearest whitespace.
|
|
1191
|
+
let teaser = narrative.trim();
|
|
1192
|
+
if (teaser.length === 0) {
|
|
1193
|
+
teaser = uiT("ap_build_log_teaser_fallback");
|
|
1194
|
+
} else if (teaser.length > 160) {
|
|
1195
|
+
const cut = teaser.slice(0, 160);
|
|
1196
|
+
const lastSpace = cut.lastIndexOf(" ");
|
|
1197
|
+
teaser = (lastSpace > 80 ? cut.slice(0, lastSpace) : cut).trim() + "…";
|
|
1198
|
+
}
|
|
1199
|
+
return `
|
|
1200
|
+
<section class="ap-block ap-buildlog-block">
|
|
1201
|
+
<header class="ap-block-h">
|
|
1202
|
+
<span class="ap-block-h-title">${escape(uiT("ap_build_log"))}</span>
|
|
1203
|
+
<span class="ap-block-h-tag">${escape(uiT("ap_build_log_kicker"))}</span>
|
|
1204
|
+
</header>
|
|
1205
|
+
<button type="button" class="ap-buildlog-card" data-ap-buildlog-open data-slug="${escape(slug)}" aria-label="${escape(uiT("ap_build_log_open"))}">
|
|
1206
|
+
<p class="ap-buildlog-teaser">${escape(teaser)}</p>
|
|
1207
|
+
<div class="ap-buildlog-card-cta">
|
|
1208
|
+
<span class="ap-buildlog-card-cta-label">${escape(uiT("ap_build_log_open_cta"))}</span>
|
|
1209
|
+
</div>
|
|
1210
|
+
</button>
|
|
1211
|
+
</section>`;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1176
1214
|
function renderRulesInner(slug) {
|
|
1177
1215
|
const rules = rulesForAgent(slug);
|
|
1178
1216
|
const list = rules.length === 0
|
|
@@ -1939,6 +1977,199 @@
|
|
|
1939
1977
|
}
|
|
1940
1978
|
}
|
|
1941
1979
|
|
|
1980
|
+
/* ─── Build-log overlay ────────────────────────────────
|
|
1981
|
+
Sibling to the persona dossier overlay. Reads the buildLog from
|
|
1982
|
+
window.app.agentsById[slug].personaSpec.buildLog (already on the
|
|
1983
|
+
client — the spec rides the agent payload). Renders:
|
|
1984
|
+
· the narrator's pitch summary (hero block)
|
|
1985
|
+
· a 7-phase timeline rail with per-phase blurbs
|
|
1986
|
+
· dimension-card grid stitched under phase 2 from the
|
|
1987
|
+
`dimension-plan` event + matching `search` events
|
|
1988
|
+
· footer stats: voice-uniqueness · tokens · duration
|
|
1989
|
+
Closed on backdrop click or Escape. */
|
|
1990
|
+
let _buildLogOverlayEsc = null;
|
|
1991
|
+
function openBuildLogOverlay(slug, agentName) {
|
|
1992
|
+
closeBuildLogOverlay();
|
|
1993
|
+
const live = window.app && window.app.agentsById ? window.app.agentsById[slug] : null;
|
|
1994
|
+
const spec = live && live.personaSpec ? live.personaSpec : null;
|
|
1995
|
+
const buildLog = spec && spec.buildLog ? spec.buildLog : null;
|
|
1996
|
+
if (!buildLog) return; // safety · the entry point is hidden in this case anyway
|
|
1997
|
+
|
|
1998
|
+
const overlay = document.createElement("div");
|
|
1999
|
+
overlay.id = "ap-buildlog-overlay";
|
|
2000
|
+
overlay.className = "ap-buildlog-overlay";
|
|
2001
|
+
overlay.innerHTML = `
|
|
2002
|
+
<div class="ap-buildlog-overlay-backdrop" data-ap-buildlog-close></div>
|
|
2003
|
+
<div class="ap-buildlog-overlay-modal" role="dialog" aria-modal="true" aria-label="${escape(uiT("ap_build_log"))}">
|
|
2004
|
+
<div class="ap-buildlog-overlay-classification">
|
|
2005
|
+
<span><span class="dot">●</span> ${escape(uiT("ap_build_log_kicker"))}</span>
|
|
2006
|
+
<span class="right">${escape(agentName || "")}</span>
|
|
2007
|
+
</div>
|
|
2008
|
+
<div class="ap-buildlog-overlay-head">
|
|
2009
|
+
<div class="ap-buildlog-overlay-title">${escape(uiT("ap_build_log"))}</div>
|
|
2010
|
+
<div class="ap-buildlog-overlay-actions">
|
|
2011
|
+
<button type="button" class="ap-buildlog-overlay-close" data-ap-buildlog-close aria-label="${escape(uiT("ap_build_close"))}">✕</button>
|
|
2012
|
+
</div>
|
|
2013
|
+
</div>
|
|
2014
|
+
<div class="ap-buildlog-overlay-body">
|
|
2015
|
+
${renderBuildLogBody(buildLog)}
|
|
2016
|
+
</div>
|
|
2017
|
+
</div>
|
|
2018
|
+
`;
|
|
2019
|
+
document.body.appendChild(overlay);
|
|
2020
|
+
document.body.classList.add("ap-buildlog-overlay-open");
|
|
2021
|
+
_buildLogOverlayEsc = (ev) => {
|
|
2022
|
+
if (ev.key === "Escape") {
|
|
2023
|
+
ev.stopImmediatePropagation();
|
|
2024
|
+
closeBuildLogOverlay();
|
|
2025
|
+
}
|
|
2026
|
+
};
|
|
2027
|
+
document.addEventListener("keydown", _buildLogOverlayEsc, true);
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
function closeBuildLogOverlay() {
|
|
2031
|
+
const el = document.getElementById("ap-buildlog-overlay");
|
|
2032
|
+
if (el) el.remove();
|
|
2033
|
+
document.body.classList.remove("ap-buildlog-overlay-open");
|
|
2034
|
+
if (_buildLogOverlayEsc) {
|
|
2035
|
+
document.removeEventListener("keydown", _buildLogOverlayEsc, true);
|
|
2036
|
+
_buildLogOverlayEsc = null;
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
/** Render the modal body · narrative hero + 7-phase timeline +
|
|
2041
|
+
* dimension cards under phase 2 + footer stats. Pure HTML string. */
|
|
2042
|
+
function renderBuildLogBody(buildLog) {
|
|
2043
|
+
const events = Array.isArray(buildLog.events) ? buildLog.events : [];
|
|
2044
|
+
const narrative = typeof buildLog.narrative === "string" ? buildLog.narrative.trim() : "";
|
|
2045
|
+
|
|
2046
|
+
// Collect dimensions + searches by walking the event log once.
|
|
2047
|
+
let dimensionPlan = [];
|
|
2048
|
+
const searchesByDim = new Map();
|
|
2049
|
+
const topupSearches = [];
|
|
2050
|
+
const phaseEnd = new Map(); // phase → durationMs
|
|
2051
|
+
let divergenceScore = null;
|
|
2052
|
+
for (const e of events) {
|
|
2053
|
+
if (e.kind === "dimension-plan" && Array.isArray(e.dimensions)) {
|
|
2054
|
+
dimensionPlan = e.dimensions;
|
|
2055
|
+
} else if (e.kind === "search") {
|
|
2056
|
+
if (e.topup) {
|
|
2057
|
+
topupSearches.push(e);
|
|
2058
|
+
} else if (e.dimension) {
|
|
2059
|
+
const cur = searchesByDim.get(e.dimension) || { count: 0, sources: 0, queries: [] };
|
|
2060
|
+
cur.count += 1;
|
|
2061
|
+
cur.sources += (typeof e.pagesRead === "number" ? e.pagesRead : 0);
|
|
2062
|
+
cur.queries.push(e.query);
|
|
2063
|
+
searchesByDim.set(e.dimension, cur);
|
|
2064
|
+
}
|
|
2065
|
+
} else if (e.kind === "phase-end" && typeof e.phase === "number") {
|
|
2066
|
+
phaseEnd.set(e.phase, typeof e.durationMs === "number" ? e.durationMs : 0);
|
|
2067
|
+
} else if (e.kind === "divergence") {
|
|
2068
|
+
divergenceScore = (typeof e.score === "number") ? e.score : null;
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
// Narrative hero. Empty narrative → show a localised fallback line
|
|
2073
|
+
// so the modal doesn't open with an empty top half.
|
|
2074
|
+
const narrativeHTML = narrative.length > 0
|
|
2075
|
+
? `<div class="ap-buildlog-narrative">${narrative.split(/\n\n+/).map((p) => `<p>${escape(p.trim())}</p>`).join("")}</div>`
|
|
2076
|
+
: `<div class="ap-buildlog-narrative ap-buildlog-narrative-empty"><p>${escape(uiT("ap_build_log_no_narrative"))}</p></div>`;
|
|
2077
|
+
|
|
2078
|
+
// Timeline · 7 cards. Phase 2 expands to a dimension grid
|
|
2079
|
+
// beneath the card. We render all 7 even if some events are
|
|
2080
|
+
// missing (e.g. aborted-then-resumed builds) — missing phases
|
|
2081
|
+
// just don't show a duration.
|
|
2082
|
+
const phaseCards = [1, 2, 3, 4, 5, 6, 7].map((n) => {
|
|
2083
|
+
const num = String(n).padStart(2, "0");
|
|
2084
|
+
const label = escape(uiT("ap_build_phase_" + n));
|
|
2085
|
+
const blurb = escape(uiT("ap_build_phase_" + n + "_blurb"));
|
|
2086
|
+
const dur = phaseEnd.get(n);
|
|
2087
|
+
const durText = (typeof dur === "number" && dur > 0)
|
|
2088
|
+
? `<span class="ap-buildlog-phase-dur">${Math.max(1, Math.round(dur / 1000))}s</span>`
|
|
2089
|
+
: "";
|
|
2090
|
+
let extras = "";
|
|
2091
|
+
if (n === 2) {
|
|
2092
|
+
// Dimension grid under the research-phase card.
|
|
2093
|
+
const dimCards = dimensionPlan.map((d) => {
|
|
2094
|
+
const stats = searchesByDim.get(d.dimension) || { sources: 0, count: 0 };
|
|
2095
|
+
const why = d.why ? escape(d.why) : escape(d.query || "");
|
|
2096
|
+
const sources = uiT("ap_build_sources_short", { n: stats.sources });
|
|
2097
|
+
return `
|
|
2098
|
+
<div class="ap-buildlog-dim">
|
|
2099
|
+
<div class="ap-buildlog-dim-name">${escape(d.dimension)}</div>
|
|
2100
|
+
<div class="ap-buildlog-dim-why">${why}</div>
|
|
2101
|
+
<div class="ap-buildlog-dim-stat">${escape(sources)}</div>
|
|
2102
|
+
</div>
|
|
2103
|
+
`;
|
|
2104
|
+
}).join("");
|
|
2105
|
+
const topupBlock = topupSearches.length > 0
|
|
2106
|
+
? `
|
|
2107
|
+
<div class="ap-buildlog-topup">
|
|
2108
|
+
<div class="ap-buildlog-topup-label">${escape(uiT("ap_build_topup_label"))}</div>
|
|
2109
|
+
<ul class="ap-buildlog-topup-list">
|
|
2110
|
+
${topupSearches.map((t) => `<li>“${escape(t.query)}” · ${escape(uiT("ap_build_sources_short", { n: typeof t.pagesRead === "number" ? t.pagesRead : 0 }))}</li>`).join("")}
|
|
2111
|
+
</ul>
|
|
2112
|
+
</div>`
|
|
2113
|
+
: "";
|
|
2114
|
+
if (dimensionPlan.length > 0 || topupSearches.length > 0) {
|
|
2115
|
+
extras = `
|
|
2116
|
+
<div class="ap-buildlog-phase-extras">
|
|
2117
|
+
${dimensionPlan.length > 0 ? `
|
|
2118
|
+
<div class="ap-buildlog-dims-label">${escape(uiT("ap_build_dimensions_label"))}</div>
|
|
2119
|
+
<div class="ap-buildlog-dims-grid">${dimCards}</div>
|
|
2120
|
+
` : ""}
|
|
2121
|
+
${topupBlock}
|
|
2122
|
+
</div>
|
|
2123
|
+
`;
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
return `
|
|
2127
|
+
<li class="ap-buildlog-phase">
|
|
2128
|
+
<div class="ap-buildlog-phase-head">
|
|
2129
|
+
<span class="ap-buildlog-phase-num">${num}</span>
|
|
2130
|
+
<span class="ap-buildlog-phase-label">${label}</span>
|
|
2131
|
+
${durText}
|
|
2132
|
+
</div>
|
|
2133
|
+
<p class="ap-buildlog-phase-blurb">${blurb}</p>
|
|
2134
|
+
${extras}
|
|
2135
|
+
</li>
|
|
2136
|
+
`;
|
|
2137
|
+
}).join("");
|
|
2138
|
+
|
|
2139
|
+
// Footer stats.
|
|
2140
|
+
const totalTokens = typeof buildLog.totalTokens === "number" ? buildLog.totalTokens : 0;
|
|
2141
|
+
const totalDurationMs = Array.from(phaseEnd.values()).reduce((a, b) => a + (typeof b === "number" ? b : 0), 0);
|
|
2142
|
+
const totalDurationSec = Math.round(totalDurationMs / 1000);
|
|
2143
|
+
const divergencePct = (divergenceScore === null || typeof divergenceScore !== "number")
|
|
2144
|
+
? "—"
|
|
2145
|
+
: (Math.round(divergenceScore * 100) + "%");
|
|
2146
|
+
const tokensFmt = totalTokens > 0 ? totalTokens.toLocaleString() : "—";
|
|
2147
|
+
const durFmt = totalDurationSec > 0
|
|
2148
|
+
? (totalDurationSec >= 60
|
|
2149
|
+
? `${Math.floor(totalDurationSec / 60)}m ${totalDurationSec % 60}s`
|
|
2150
|
+
: `${totalDurationSec}s`)
|
|
2151
|
+
: "—";
|
|
2152
|
+
|
|
2153
|
+
return `
|
|
2154
|
+
${narrativeHTML}
|
|
2155
|
+
<ol class="ap-buildlog-timeline">${phaseCards}</ol>
|
|
2156
|
+
<footer class="ap-buildlog-footer">
|
|
2157
|
+
<div class="ap-buildlog-stat">
|
|
2158
|
+
<div class="ap-buildlog-stat-l">${escape(uiT("ap_build_divergence_label"))}</div>
|
|
2159
|
+
<div class="ap-buildlog-stat-v">${escape(divergencePct)}</div>
|
|
2160
|
+
</div>
|
|
2161
|
+
<div class="ap-buildlog-stat">
|
|
2162
|
+
<div class="ap-buildlog-stat-l">${escape(uiT("ap_build_tokens_label"))}</div>
|
|
2163
|
+
<div class="ap-buildlog-stat-v">${escape(tokensFmt)}</div>
|
|
2164
|
+
</div>
|
|
2165
|
+
<div class="ap-buildlog-stat">
|
|
2166
|
+
<div class="ap-buildlog-stat-l">${escape(uiT("ap_build_duration_label"))}</div>
|
|
2167
|
+
<div class="ap-buildlog-stat-v">${escape(durFmt)}</div>
|
|
2168
|
+
</div>
|
|
2169
|
+
</footer>
|
|
2170
|
+
`;
|
|
2171
|
+
}
|
|
2172
|
+
|
|
1942
2173
|
/* ─── Profile · ⋯ menu (top-right of the cover) ─────
|
|
1943
2174
|
Small popover anchored to the menu button with one or more
|
|
1944
2175
|
actions. v1 ships a single "regenerate 8-bit avatar" item. */
|
|
@@ -2889,6 +3120,7 @@
|
|
|
2889
3120
|
</section>
|
|
2890
3121
|
|
|
2891
3122
|
${renderPersonaDossierSection(slug, p)}
|
|
3123
|
+
${renderBuildLogSection(slug, p)}
|
|
2892
3124
|
|
|
2893
3125
|
<section class="ap-block">
|
|
2894
3126
|
<header class="ap-block-h">
|
|
@@ -3367,6 +3599,28 @@
|
|
|
3367
3599
|
return;
|
|
3368
3600
|
}
|
|
3369
3601
|
|
|
3602
|
+
// Build-log card · open the build-log modal. Mirrors the
|
|
3603
|
+
// persona-dossier open/close pattern. The teaser card is a
|
|
3604
|
+
// <button> so the click can land on any child element.
|
|
3605
|
+
const buildLogOpen = e.target.closest("[data-ap-buildlog-open]");
|
|
3606
|
+
if (buildLogOpen) {
|
|
3607
|
+
e.preventDefault();
|
|
3608
|
+
e.stopPropagation();
|
|
3609
|
+
const slug = buildLogOpen.getAttribute("data-slug");
|
|
3610
|
+
if (!slug) return;
|
|
3611
|
+
const live = window.app && window.app.agentsById ? window.app.agentsById[slug] : null;
|
|
3612
|
+
const agentName = live && live.name ? live.name : "";
|
|
3613
|
+
openBuildLogOverlay(slug, agentName);
|
|
3614
|
+
return;
|
|
3615
|
+
}
|
|
3616
|
+
const buildLogClose = e.target.closest("[data-ap-buildlog-close]");
|
|
3617
|
+
if (buildLogClose) {
|
|
3618
|
+
e.preventDefault();
|
|
3619
|
+
e.stopPropagation();
|
|
3620
|
+
closeBuildLogOverlay();
|
|
3621
|
+
return;
|
|
3622
|
+
}
|
|
3623
|
+
|
|
3370
3624
|
// ⋯ menu · open the popover (anchored to the button).
|
|
3371
3625
|
const idMenuBtn = e.target.closest("[data-ap-id-menu]");
|
|
3372
3626
|
if (idMenuBtn) {
|