privateboard 0.1.37 → 0.1.40

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.
Files changed (76) hide show
  1. package/dist/boot.js +1415 -91
  2. package/dist/boot.js.map +1 -1
  3. package/dist/cli.js +1415 -91
  4. package/dist/cli.js.map +1 -1
  5. package/dist/server.js +1271 -81
  6. package/dist/server.js.map +1 -1
  7. package/dist/version.d.ts +1 -1
  8. package/dist/version.js +1 -1
  9. package/dist/version.js.map +1 -1
  10. package/package.json +1 -1
  11. package/public/__avatar3d_test.html +156 -0
  12. package/public/adjourn-overlay.css +2 -2
  13. package/public/agent-overlay.css +27 -15
  14. package/public/agent-overlay.js +3 -1
  15. package/public/agent-profile.css +331 -41
  16. package/public/agent-profile.js +499 -75
  17. package/public/app-updater.css +1 -1
  18. package/public/app.js +2090 -547
  19. package/public/avatar-3d-snap.js +205 -0
  20. package/public/avatar-3d.js +792 -0
  21. package/public/avatar-customizer.html +274 -0
  22. package/public/avatar3d-editor.css +240 -0
  23. package/public/avatar3d-editor.js +481 -0
  24. package/public/avatars/3d/chair.png +0 -0
  25. package/public/avatars/3d/first-principles.png +0 -0
  26. package/public/avatars/3d/historian.png +0 -0
  27. package/public/avatars/3d/long-horizon.png +0 -0
  28. package/public/avatars/3d/phenomenologist.png +0 -0
  29. package/public/avatars/3d/socrates.png +0 -0
  30. package/public/avatars/3d/user-empathy.png +0 -0
  31. package/public/avatars/3d/value-investor.png +0 -0
  32. package/public/core-avatars.js +86 -0
  33. package/public/home-3d-loader.js +15 -4
  34. package/public/home-3d-mock.js +18 -7
  35. package/public/home.html +80 -18
  36. package/public/i18n.js +279 -4
  37. package/public/icons/avatar_1779855104027.glb +0 -0
  38. package/public/icons/logo.png +0 -0
  39. package/public/icons/new-style.glb +0 -0
  40. package/public/icons/new-style2.glb +0 -0
  41. package/public/icons/new-style3.glb +0 -0
  42. package/public/icons/new-style4.glb +0 -0
  43. package/public/icons/new-style5.glb +0 -0
  44. package/public/icons/office.glb +0 -0
  45. package/public/icons/stuff.glb +0 -0
  46. package/public/index.html +203 -182
  47. package/public/mention-picker.js +1 -1
  48. package/public/new-agent.css +7 -7
  49. package/public/new-agent.js +46 -20
  50. package/public/office-viewer.html +340 -0
  51. package/public/onboarding.css +5 -5
  52. package/public/quote-cta.css +5 -4
  53. package/public/quote-cta.js +50 -5
  54. package/public/room-settings.css +24 -9
  55. package/public/stuff-viewer.html +330 -0
  56. package/public/thread.css +1211 -0
  57. package/public/user-settings.css +16 -19
  58. package/public/user-settings.js +86 -78
  59. package/public/vendor/BufferGeometryUtils.js +1434 -0
  60. package/public/vendor/DRACOLoader.js +739 -0
  61. package/public/vendor/GLTFLoader.js +4860 -0
  62. package/public/vendor/RoomEnvironment.js +185 -0
  63. package/public/vendor/SkeletonUtils.js +496 -0
  64. package/public/vendor/draco/draco_decoder.js +34 -0
  65. package/public/vendor/draco/draco_decoder.wasm +0 -0
  66. package/public/vendor/draco/draco_encoder.js +33 -0
  67. package/public/vendor/draco/draco_wasm_wrapper.js +117 -0
  68. package/public/vendor/meshopt_decoder.module.js +196 -0
  69. package/public/voice-3d-banner.js +12 -0
  70. package/public/voice-3d.js +1407 -432
  71. package/public/voice-clone.css +875 -0
  72. package/public/voice-clone.js +1351 -0
  73. package/public/voice-replay.css +3 -3
  74. package/public/voice-replay.js +21 -0
  75. package/public/avatar-skill.js +0 -629
  76. package/public/icons/folded-sidebar.png +0 -0
package/dist/version.d.ts CHANGED
@@ -12,6 +12,6 @@
12
12
  * number ends up surfaced in the user-facing footer or banner. Keep
13
13
  * this file as the canonical source — every callsite reads from here.
14
14
  */
15
- declare const VERSION = "0.1.37";
15
+ declare const VERSION = "0.1.40";
16
16
 
17
17
  export { VERSION };
package/dist/version.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/version.ts
4
- var VERSION = "0.1.37";
4
+ var VERSION = "0.1.40";
5
5
  export {
6
6
  VERSION
7
7
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts"],"sourcesContent":["/**\n * Single source of truth for the app version.\n *\n * Imported by `cli.ts` (CLI banner / `--version`), `server.ts` (the\n * `/health` payload + the `/api/version` endpoint), and bundled into\n * the frontend via the version endpoint. Bump alongside `package.json`\n * on every release — the existing `npm version <patch|minor|major>`\n * + commit pattern updates package.json automatically; this file\n * needs the matching manual bump.\n *\n * If two strings drift (bumped one but not the other), the wrong\n * number ends up surfaced in the user-facing footer or banner. Keep\n * this file as the canonical source — every callsite reads from here.\n */\nexport const VERSION = \"0.1.37\";\n"],"mappings":";;;AAcO,IAAM,UAAU;","names":[]}
1
+ {"version":3,"sources":["../src/version.ts"],"sourcesContent":["/**\n * Single source of truth for the app version.\n *\n * Imported by `cli.ts` (CLI banner / `--version`), `server.ts` (the\n * `/health` payload + the `/api/version` endpoint), and bundled into\n * the frontend via the version endpoint. Bump alongside `package.json`\n * on every release — the existing `npm version <patch|minor|major>`\n * + commit pattern updates package.json automatically; this file\n * needs the matching manual bump.\n *\n * If two strings drift (bumped one but not the other), the wrong\n * number ends up surfaced in the user-facing footer or banner. Keep\n * this file as the canonical source — every callsite reads from here.\n */\nexport const VERSION = \"0.1.40\";\n"],"mappings":";;;AAcO,IAAM,UAAU;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "privateboard",
3
- "version": "0.1.37",
3
+ "version": "0.1.40",
4
4
  "description": "PrivateBoard · your private board meeting, on call. Local-first, multi-agent thinking amplifier.",
5
5
  "type": "module",
6
6
  "main": "electron-entry.cjs",
@@ -0,0 +1,156 @@
1
+ <!DOCTYPE html>
2
+ <html><head><meta charset="utf-8"><title>avatar3d test</title>
3
+ <style>
4
+ html,body{margin:0;height:100%;background:#1a1a1a;overflow:hidden}
5
+ #status{position:fixed;top:8px;left:10px;color:#9fe;font:12px/1.5 monospace;z-index:9;white-space:pre-wrap;max-width:92vw}
6
+ #panel{position:fixed;top:8px;right:10px;z-index:9;background:rgba(0,0,0,.55);border:1px solid #444;border-radius:8px;padding:10px 12px;color:#cde;font:11px/1.6 monospace;width:230px}
7
+ #panel label{display:block;margin:6px 0 2px}
8
+ #panel input[type=range]{width:100%}
9
+ #panel b{color:#9fe}
10
+ #copy{margin-top:8px;width:100%;padding:5px;background:#2a3340;color:#cde;border:1px solid #556;border-radius:5px;cursor:pointer;font:11px monospace}
11
+ </style>
12
+ </head><body>
13
+ <div id="status">booting…</div>
14
+ <!-- Live brightness controls · drag to taste, then read the values off
15
+ the readout (or click "复制参数") and tell me — I'll bake them into
16
+ the room. -->
17
+ <div id="panel">
18
+ <label>曝光 exposure · <b id="vExp">0.70</b></label>
19
+ <input type="range" id="exp" min="0.2" max="1.4" step="0.01" value="0.70">
20
+ <label>环境强度 envIntensity · <b id="vEnv">0.35</b></label>
21
+ <input type="range" id="env" min="0" max="1.5" step="0.01" value="0.35">
22
+ <label>主光 key · <b id="vKey">0.70</b></label>
23
+ <input type="range" id="key" min="0" max="3" step="0.01" value="0.70">
24
+ <button id="copy">复制参数</button>
25
+ </div>
26
+
27
+ <!-- Classic script FIRST · catches module/import/protocol failures that a
28
+ top-level `import` would otherwise swallow into the console only. -->
29
+ <script>
30
+ window.__setStatus = function (msg, isErr) {
31
+ var el = document.getElementById("status");
32
+ if (!el) return;
33
+ el.textContent = msg;
34
+ el.style.color = isErr ? "#f88" : "#9fe";
35
+ };
36
+ if (location.protocol === "file:") {
37
+ window.__setStatus("⚠ 你是用 file:// 打开的 — 模块和 GLB 都加载不了。\n请在【运行中的 app】里访问 http://localhost:<端口>/__avatar3d_test.html", true);
38
+ }
39
+ window.addEventListener("error", function (e) {
40
+ // Resource (script/module) load failures arrive here as ErrorEvents.
41
+ var what = e.message || (e.target && (e.target.src || e.target.href)) || "unknown";
42
+ window.__setStatus("JS/资源错误: " + what, true);
43
+ }, true);
44
+ window.addEventListener("unhandledrejection", function (e) {
45
+ var r = e.reason; window.__setStatus("未处理的 Promise 拒绝: " + ((r && r.message) || r), true);
46
+ });
47
+ setTimeout(function () {
48
+ var el = document.getElementById("status");
49
+ if (el && /booting|importing|loading|building/i.test(el.textContent)) {
50
+ window.__setStatus(el.textContent + "\n(>6s 仍未完成 — 打开 DevTools Console 看具体报错)", true);
51
+ }
52
+ }, 6000);
53
+ </script>
54
+
55
+ <script type="module">
56
+ const S = window.__setStatus;
57
+ (async () => {
58
+ try {
59
+ // Step 0 · is the GLB even reachable on this server? (isolates
60
+ // "asset not served" from "module failed to load".)
61
+ S("检查 GLB 可达性…");
62
+ const GLB = "/icons/avatar_1779855104027.glb";
63
+ const head = await fetch(GLB, { method: "GET", headers: { Range: "bytes=0-0" } }).catch((e) => ({ ok: false, status: "fetch失败 " + e.message }));
64
+ if (!head.ok && head.status !== 206 && head.status !== 200) {
65
+ S("GLB 拿不到: " + GLB + " → " + head.status + "(文件没被服务?)", true);
66
+ return;
67
+ }
68
+
69
+ S("加载 three…");
70
+ const THREE = await import("/vendor/three.module.min.js");
71
+ S("加载 OrbitControls…");
72
+ const { OrbitControls } = await import("/vendor/OrbitControls.js");
73
+ const { RoomEnvironment } = await import("/vendor/RoomEnvironment.js");
74
+ S("加载 avatar-3d skill…");
75
+ const av = await import("/avatar-3d.js");
76
+
77
+ const renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true });
78
+ renderer.setSize(innerWidth, innerHeight);
79
+ renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
80
+ renderer.shadowMap.enabled = true;
81
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
82
+ // ACES tone mapping + sRGB output · the standard "make PBR look
83
+ // good" pair. Without tone mapping the env reflections clip / look
84
+ // flat; with it skin + hair get that soft filmic sheen.
85
+ renderer.toneMapping = THREE.ACESFilmicToneMapping;
86
+ renderer.toneMappingExposure = 0.7;
87
+ document.body.appendChild(renderer.domElement);
88
+
89
+ const scene = new THREE.Scene();
90
+ scene.background = new THREE.Color(0x222428);
91
+ const camera = new THREE.PerspectiveCamera(35, innerWidth / innerHeight, 0.1, 100);
92
+ camera.position.set(1.6, 1.7, 3.0);
93
+ const controls = new OrbitControls(camera, renderer.domElement);
94
+ controls.target.set(0, 0.9, 0);
95
+ controls.update();
96
+
97
+ // Image-based lighting · a PMREM-filtered procedural RoomEnvironment
98
+ // is what gives the materials real reflections / gloss (no HDRI
99
+ // file needed). This is the single biggest lever for "光泽 / 质感".
100
+ const pmrem = new THREE.PMREMGenerator(renderer);
101
+ scene.environment = pmrem.fromScene(new RoomEnvironment(), 0.04).texture;
102
+ // RoomEnvironment is studio-bright · dim its contribution so it
103
+ // lights + reflects without washing the skin out. Keeps the gloss
104
+ // shape (reflections) while pulling overall exposure down.
105
+ scene.environmentIntensity = 0.35;
106
+
107
+ // The env map already provides ambient fill, so direct lights stay
108
+ // modest · a strong key + rim on top of IBL blew the faces out to
109
+ // pure white. One soft key for shape + a faint rim for separation.
110
+ scene.add(new THREE.HemisphereLight(0xffffff, 0x33384a, 0.18));
111
+ const dir = new THREE.DirectionalLight(0xffffff, 0.7);
112
+ dir.position.set(3, 6, 4); dir.castShadow = true; scene.add(dir);
113
+ const rim = new THREE.DirectionalLight(0xbfd4ff, 0.3);
114
+ rim.position.set(-4, 3, -3); scene.add(rim);
115
+ const ground = new THREE.Mesh(
116
+ new THREE.CircleGeometry(2.4, 48),
117
+ new THREE.MeshStandardMaterial({ color: 0x33363c, roughness: 1 }),
118
+ );
119
+ ground.rotation.x = -Math.PI / 2; ground.receiveShadow = true; scene.add(ground);
120
+
121
+ renderer.setAnimationLoop(() => { controls.update(); renderer.render(scene, camera); });
122
+
123
+ // Live brightness sliders → renderer / scene / key-light.
124
+ const $ = (id) => document.getElementById(id);
125
+ const wire = (id, vid, fn, fmt) => {
126
+ const el = $(id); const lab = $(vid);
127
+ const upd = () => { const v = parseFloat(el.value); fn(v); lab.textContent = fmt(v); };
128
+ el.addEventListener("input", upd); upd();
129
+ };
130
+ wire("exp", "vExp", (v) => { renderer.toneMappingExposure = v; }, (v) => v.toFixed(2));
131
+ wire("env", "vEnv", (v) => { scene.environmentIntensity = v; }, (v) => v.toFixed(2));
132
+ wire("key", "vKey", (v) => { dir.intensity = v; }, (v) => v.toFixed(2));
133
+ $("copy").addEventListener("click", () => {
134
+ const t = `exposure=${$("exp").value} envIntensity=${$("env").value} key=${$("key").value}`;
135
+ navigator.clipboard && navigator.clipboard.writeText(t);
136
+ $("copy").textContent = "已复制: " + t;
137
+ });
138
+
139
+ S("下载 + 解析 GLB…");
140
+ await av.loadAvatar3D(GLB);
141
+
142
+ S("生成 avatar 实例…");
143
+ const seeds = ["yang-tianzhen", "socrates", "first-principles"];
144
+ seeds.forEach((seed, i) => {
145
+ const a = av.buildAvatar3D(seed, { height: 1.7 });
146
+ a.position.x = (i - 1) * 1.1;
147
+ a.rotation.y = 0;
148
+ scene.add(a);
149
+ });
150
+ S("✓ 加载完成 · " + seeds.length + " 个 avatar(拖动可旋转)");
151
+ } catch (e) {
152
+ S("ERROR: " + (e && e.stack ? e.stack : (e && e.message) || e), true);
153
+ }
154
+ })();
155
+ </script>
156
+ </body></html>
@@ -166,7 +166,7 @@
166
166
  }
167
167
  .adjourn-summary-val {
168
168
  font-family: var(--font-human);
169
- font-size: 13px;
169
+ font-size: 14px;
170
170
  color: var(--text);
171
171
  line-height: 1.4;
172
172
  word-break: break-word;
@@ -356,7 +356,7 @@
356
356
  }
357
357
  .adjourn-mode-title {
358
358
  font-family: var(--font-human);
359
- font-size: 13px;
359
+ font-size: 14px;
360
360
  font-weight: 600;
361
361
  color: var(--text);
362
362
  letter-spacing: -0.005em;
@@ -36,33 +36,45 @@ img[data-agent]:hover { filter: brightness(1.15); }
36
36
  width: 100%;
37
37
  max-width: 560px;
38
38
  max-height: calc(100vh - 60px);
39
- overflow-y: auto;
40
39
  background: var(--panel);
41
40
  border: 0.5px solid var(--line-strong);
42
41
  color: var(--text);
43
42
  animation: agent-rise 0.18s ease-out;
44
- /* Auto-hide scrollbar: thumb is transparent until the pointer is
45
- over the card OR the card is actively being scrolled (the
46
- .is-scrolling class is toggled by agent-overlay.js on each scroll
47
- event with a short trailing timeout). Reserved gutter avoids
48
- layout shift when the thumb fades in. */
43
+ /* Frame only · the scroll lives in the inner `.agent-card-scroll`
44
+ below. Keeping `.agent-card` a non-scrolling frame means the
45
+ decorative corner brackets (::before / ::after) stay pinned to the
46
+ card's corners instead of anchoring to the scrolled content and
47
+ drifting away. Flex column lets the inner scroller fill the frame
48
+ up to max-height. */
49
+ display: flex;
50
+ flex-direction: column;
51
+ }
52
+ /* Inner scroll region · owns the overflow + the auto-hide scrollbar
53
+ that used to live on `.agent-card`. Thumb stays transparent until the
54
+ pointer is over the region OR it's actively being scrolled (the
55
+ `.is-scrolling` class is toggled by agent-overlay.js with a short
56
+ trailing timeout). Reserved gutter avoids layout shift on fade-in. */
57
+ .agent-card-scroll {
58
+ flex: 1;
59
+ min-height: 0;
60
+ overflow-y: auto;
49
61
  scrollbar-width: thin;
50
62
  scrollbar-color: transparent transparent;
51
63
  scrollbar-gutter: stable;
52
64
  transition: scrollbar-color 0.18s;
53
65
  }
54
- .agent-card:hover,
55
- .agent-card.is-scrolling { scrollbar-color: var(--text-faint) transparent; }
56
- .agent-card::-webkit-scrollbar { width: 8px; }
57
- .agent-card::-webkit-scrollbar-track { background: transparent; }
58
- .agent-card::-webkit-scrollbar-thumb {
66
+ .agent-card-scroll:hover,
67
+ .agent-card-scroll.is-scrolling { scrollbar-color: var(--text-faint) transparent; }
68
+ .agent-card-scroll::-webkit-scrollbar { width: 8px; }
69
+ .agent-card-scroll::-webkit-scrollbar-track { background: transparent; }
70
+ .agent-card-scroll::-webkit-scrollbar-thumb {
59
71
  background: transparent;
60
72
  border-radius: 4px;
61
73
  transition: background 0.18s;
62
74
  }
63
- .agent-card:hover::-webkit-scrollbar-thumb,
64
- .agent-card.is-scrolling::-webkit-scrollbar-thumb { background: var(--text-faint); }
65
- .agent-card::-webkit-scrollbar-thumb:hover { background: var(--text-soft); }
75
+ .agent-card-scroll:hover::-webkit-scrollbar-thumb,
76
+ .agent-card-scroll.is-scrolling::-webkit-scrollbar-thumb { background: var(--text-faint); }
77
+ .agent-card-scroll::-webkit-scrollbar-thumb:hover { background: var(--text-soft); }
66
78
  @keyframes agent-rise {
67
79
  from { transform: translateY(8px); opacity: 0; }
68
80
  to { transform: translateY(0); opacity: 1; }
@@ -180,7 +192,7 @@ img[data-agent]:hover { filter: brightness(1.15); }
180
192
 
181
193
  .agent-lens {
182
194
  font-family: var(--sans);
183
- font-size: 13px;
195
+ font-size: 14px;
184
196
  line-height: 1.55;
185
197
  color: var(--text-soft);
186
198
  letter-spacing: -0.003em;
@@ -201,6 +201,7 @@
201
201
  const OVERLAY_HTML = `
202
202
  <div class="agent-overlay" id="agent-overlay" role="dialog" aria-modal="true" aria-hidden="true">
203
203
  <div class="agent-card" role="document">
204
+ <div class="agent-card-scroll">
204
205
  <div class="agent-classification">
205
206
  <span><span class="dot">●</span> <span data-i18n="ao_personnel_kicker">agent · personnel file</span></span>
206
207
  <span class="right" data-i18n="ao_classified_mark">// classified</span>
@@ -303,6 +304,7 @@
303
304
  <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>
304
305
  <a href="/#convene" class="agent-card-cta public-only" data-i18n="ao_signin_cta">[ → Sign in to convene ]</a>
305
306
  </footer>
307
+ </div>
306
308
  </div>
307
309
  </div>
308
310
  `;
@@ -366,7 +368,7 @@
366
368
  timer = setTimeout(() => node.classList.remove("is-scrolling"), 700);
367
369
  }, { passive: true });
368
370
  }
369
- bindScrollAutoHide(card);
371
+ bindScrollAutoHide(card.querySelector(".agent-card-scroll"));
370
372
  bindScrollAutoHide(card.querySelector(".agent-memory-list"));
371
373
 
372
374
  /** Build a card from a live /api/agents record (custom directors).