@volter/teams 0.1.27 → 0.1.29
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/package.json +1 -1
- package/viewer/index.html +35 -0
- package/viewer/session-view-entry.mjs +15 -3
- package/viewer/session-view.css +2 -1
- package/viewer/session-view.mjs +14 -14
- package/viewer/viewer.mjs +36 -1
package/viewer/viewer.mjs
CHANGED
|
@@ -25,17 +25,50 @@ function applyTheme(properties) {
|
|
|
25
25
|
if (!/^--(volter|scui)-[a-z0-9-]+$/.test(name) || typeof value !== 'string' || value.length > 400) continue;
|
|
26
26
|
// on the page (its background) and on the session root (which sets its own scheme default)
|
|
27
27
|
for (const element of [document.documentElement, $('session')]) element.style.setProperty(name, value);
|
|
28
|
+
if (name === '--scui-color-scheme') themed = true;
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
// The session header is the host's to show: framed, it is hidden unless the host asks for it (the host's own header
|
|
31
32
|
// carries the session's details, which this page posts to it as `viewer-session`).
|
|
32
33
|
function showHeader(shown) { $('session').classList.toggle('header-hidden', !shown); }
|
|
33
|
-
|
|
34
|
+
// The host's presentation of the transcript: supercode-ui's own (the default), or `rows`, a chat's rows (every
|
|
35
|
+
// message left-aligned under its author's avatar and name, one author's run grouped) in the brand's type.
|
|
36
|
+
let themed = false;
|
|
37
|
+
// The host's words for the composer (its placeholder and the hint under it), e.g. "Message #Work".
|
|
38
|
+
let labels = {};
|
|
39
|
+
let applyLabels = () => {};
|
|
40
|
+
function useLabels(value) {
|
|
41
|
+
if (!value || typeof value !== 'object') return;
|
|
42
|
+
for (const key of ['composerPlaceholder', 'composerHint']) if (typeof value[key] === 'string' && value[key].length <= 200) labels[key] = value[key];
|
|
43
|
+
applyLabels();
|
|
44
|
+
}
|
|
45
|
+
function useLayout(layout) {
|
|
46
|
+
const rows = layout === 'rows';
|
|
47
|
+
$('session').classList.toggle('layout-rows', rows);
|
|
48
|
+
if (rows && !document.getElementById('brand-tokens')) {
|
|
49
|
+
const link = Object.assign(document.createElement('link'), { id: 'brand-tokens', rel: 'stylesheet', href: 'https://brand.volter.ai/tokens.css' });
|
|
50
|
+
document.head.append(link);
|
|
51
|
+
// A chat's rows are light unless the host's theme names a scheme.
|
|
52
|
+
if (!themed) document.documentElement.style.setProperty('--scui-color-scheme', 'light');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// A fragment value that is base64url JSON (UTF-8), or null.
|
|
56
|
+
function fragmentJson(name) {
|
|
57
|
+
try {
|
|
58
|
+
const bytes = Uint8Array.from(atob((fragment.get(name) ?? '').replaceAll('-', '+').replaceAll('_', '/')), (c) => c.charCodeAt(0));
|
|
59
|
+
return bytes.length ? JSON.parse(decoder.decode(bytes)) : null;
|
|
60
|
+
} catch { return null; }
|
|
61
|
+
}
|
|
62
|
+
applyTheme(fragmentJson('theme'));
|
|
34
63
|
showHeader(fragment.has('header') ? fragment.get('header') !== 'hidden' : !embedded);
|
|
64
|
+
useLayout(fragment.get('layout'));
|
|
65
|
+
useLabels(fragmentJson('labels'));
|
|
35
66
|
|
|
36
67
|
window.addEventListener('message', (event) => {
|
|
37
68
|
if (event.data?.type === 'viewer-theme') { applyTheme(event.data.properties); return; }
|
|
38
69
|
if (event.data?.type === 'viewer-header') { showHeader(!event.data.hidden); return; }
|
|
70
|
+
if (event.data?.type === 'viewer-layout') { useLayout(event.data.layout); return; }
|
|
71
|
+
if (event.data?.type === 'viewer-labels') { useLabels(event.data); return; }
|
|
39
72
|
if (event.data?.type !== 'delegated-token' || typeof event.data.token !== 'string') return;
|
|
40
73
|
token = event.data.token;
|
|
41
74
|
if (waiting) { const resume = waiting; waiting = null; resume(); }
|
|
@@ -108,6 +141,8 @@ async function showSession(session, control) {
|
|
|
108
141
|
},
|
|
109
142
|
});
|
|
110
143
|
const headers = async () => ({ Authorization: `Bearer ${await freshToken()}` });
|
|
144
|
+
applyLabels = () => view.update({ ...labels });
|
|
145
|
+
applyLabels();
|
|
111
146
|
const HARNESSES = { 'claude-code': 'Claude Code', codex: 'Codex', gemini: 'Gemini CLI', goose: 'Goose', opencode: 'OpenCode', pi: 'Pi', grok: 'Grok' };
|
|
112
147
|
const apply = (body) => {
|
|
113
148
|
view.update({ descriptor: body.descriptor, messages: body.messages.map((message) => message.value), members: body.names?.members ?? [], machines: body.names?.machines ?? [], status: 'ready', error: null });
|