@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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/teams",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.29",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Volter Teams, the neutral team plane: machine identity and daemon core, the local door and server link, admission from machine grants, product doors, and the Teams server's neutral routes (company RFC 0008).",
|
|
6
6
|
"license": "MIT",
|
package/viewer/index.html
CHANGED
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
#session .session-view > section { flex: 1; min-height: 0; overflow: auto; }
|
|
41
41
|
#session .session-composer { border-top: 1px solid var(--line); padding: 8px; --scui-width: 100%; --scui-height: auto; }
|
|
42
42
|
#session .session-composer > * { flex: 1; min-width: 0; }
|
|
43
|
+
#session .session-hint { margin: 4px 16px 10px; font-size: 11px; color: var(--volter-text-faint, var(--scui-muted, var(--muted))); }
|
|
43
44
|
/* The host's header carries the session's details when it hides this one. */
|
|
44
45
|
#session.header-hidden .scui-team-transcript > header { display: none; }
|
|
45
46
|
/* A Room's transcript says who wrote each message: its name and face (a person) or mark (an agent). */
|
|
@@ -49,6 +50,40 @@
|
|
|
49
50
|
/* A peer session's message is an agent's, on the agent's side, never read as a person's own turn. */
|
|
50
51
|
#session .scui-message[data-role="user"][data-actor-kind="agent"] { align-self: flex-start; }
|
|
51
52
|
body:has(#session:not([hidden])) { background: var(--scui-bg, var(--volter-surface-page, var(--bg))); color: var(--scui-fg, var(--text)); }
|
|
53
|
+
/* layout=rows: a chat's rows (the host's own conversations' anatomy), over supercode-ui's message DOM. */
|
|
54
|
+
#session.layout-rows { --scui-message-actor-display: flex; font-family: var(--volter-font-ui, "Geist", system-ui, sans-serif); color: var(--volter-text-primary, var(--scui-fg)); }
|
|
55
|
+
#session.layout-rows .scui-conversation-content { display: flex; flex-direction: column; gap: 0; padding: 0 0 8px; min-height: 100%; }
|
|
56
|
+
#session.layout-rows .scui-conversation-content::before { content: ''; margin-top: auto; }
|
|
57
|
+
#session.layout-rows .scui-message { position: relative; align-self: stretch; max-width: none; margin: 0; padding: 8px 20px 2px 68px; background: transparent; border: 0; border-radius: 0; box-shadow: none; display: block; }
|
|
58
|
+
#session.layout-rows .scui-message:first-child { padding-top: 12px; }
|
|
59
|
+
#session.layout-rows .scui-message:hover { background: var(--volter-surface-subtle, var(--scui-fill)); }
|
|
60
|
+
#session.layout-rows .scui-message-actor { display: flex; align-items: baseline; gap: 8px; margin: 0 0 1px; }
|
|
61
|
+
#session.layout-rows .scui-message-actor-image { position: absolute; left: 20px; top: 10px; width: 36px; height: 36px; }
|
|
62
|
+
#session.layout-rows .scui-message-actor-name { order: 1; font-size: 14.5px; font-weight: 650; color: var(--volter-text-primary, var(--scui-fg)); font-family: var(--volter-font-ui, "Geist", system-ui, sans-serif); letter-spacing: 0; text-transform: none; }
|
|
63
|
+
#session.layout-rows .scui-message-actor-name::before { display: none; }
|
|
64
|
+
#session.layout-rows .scui-message-actor-time { order: 2; font-size: 11.5px; color: var(--volter-text-muted, var(--scui-muted)); font-family: var(--volter-font-ui, inherit); }
|
|
65
|
+
#session.layout-rows .scui-message .scui-markdown { font-size: 14px; line-height: 1.45; font-family: inherit; color: inherit; }
|
|
66
|
+
#session.layout-rows .scui-message .scui-markdown p { margin: 0 0 .5em; }
|
|
67
|
+
#session.layout-rows .scui-message .scui-markdown > :last-child { margin-bottom: 0; }
|
|
68
|
+
#session.layout-rows .scui-message .scui-markdown code { font-size: .92em; padding: 0 .2em; border-radius: 4px; background: var(--volter-overlay-emboss, var(--scui-fill)); }
|
|
69
|
+
#session.layout-rows .scui-message .scui-markdown pre { margin: .25em 0 .5em; padding: .5em .75em; border-radius: 6px; background: var(--volter-overlay-emboss, var(--scui-fill)); font-size: .9em; }
|
|
70
|
+
#session.layout-rows .scui-message .scui-markdown ul, #session.layout-rows .scui-message .scui-markdown ol { margin: .25em 0 .5em 1.25em; padding: 0; }
|
|
71
|
+
#session.layout-rows .scui-message-meta { display: none; }
|
|
72
|
+
#session.layout-rows .scui-message[data-continued] { padding-top: 1px; }
|
|
73
|
+
#session.layout-rows .scui-message[data-continued] .scui-message-actor { display: block; height: 0; margin: 0; }
|
|
74
|
+
#session.layout-rows .scui-message[data-continued] .scui-message-actor-image, #session.layout-rows .scui-message[data-continued] .scui-message-actor-name { display: none; }
|
|
75
|
+
#session.layout-rows .scui-message[data-continued] .scui-message-actor-time { position: absolute; left: 20px; top: 4px; width: 36px; text-align: right; font-size: 10.5px; color: var(--volter-text-faint, var(--scui-muted)); visibility: hidden; }
|
|
76
|
+
#session.layout-rows .scui-message[data-continued]:hover .scui-message-actor-time { visibility: visible; }
|
|
77
|
+
#session.layout-rows .scui-message[data-pending] { opacity: .6; }
|
|
78
|
+
#session.layout-rows .scui-tool { margin: 0 20px 0 62px; border: 0; background: transparent; box-shadow: none; }
|
|
79
|
+
#session.layout-rows .scui-tool-head { display: flex; align-items: center; gap: 6px; padding: 3px 6px; font-size: 12.5px; color: var(--volter-text-muted, var(--scui-muted)); border-radius: 6px; }
|
|
80
|
+
#session.layout-rows .scui-tool-head:hover { background: var(--volter-surface-subtle, var(--scui-fill)); }
|
|
81
|
+
#session.layout-rows .scui-tool-actor { display: none; }
|
|
82
|
+
#session.layout-rows .scui-tool-title { font-weight: 600; color: var(--volter-text-primary, var(--scui-fg)); }
|
|
83
|
+
#session.layout-rows .scui-tool-target { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--volter-font-data, var(--scui-font-mono)); background: none; }
|
|
84
|
+
#session.layout-rows .scui-tool-detail { margin: 2px 0 6px 20px; padding: 6px 10px; border-radius: 6px; background: var(--volter-overlay-emboss, var(--scui-fill)); font-size: 12px; max-height: 320px; overflow: auto; }
|
|
85
|
+
#session.layout-rows .session-composer { border-top: 0; padding: 0 16px 12px; }
|
|
86
|
+
#session.layout-rows .scui-team-coverage { display: none; }
|
|
52
87
|
[hidden] { display: none !important; }
|
|
53
88
|
</style>
|
|
54
89
|
</head>
|
|
@@ -11,7 +11,7 @@ import { projectSubagentTranscript } from '@volter/supercode-ui/controller';
|
|
|
11
11
|
// A person's picture: the brand's person placeholder. An empty seed is its one standard anonymous face.
|
|
12
12
|
const personImage = (seed = '') => `https://brand.volter.ai/runner/svg?seed=${encodeURIComponent(seed)}&size=36&radius=18`;
|
|
13
13
|
// An agent's picture (this session's own, a peer session's): the brand's agent mark, a rounded square, never a face.
|
|
14
|
-
const agentImage = (seed) => `https://brand.volter.ai/agent/svg?seed=${encodeURIComponent(seed)}&size=36&radius=
|
|
14
|
+
const agentImage = (seed) => `https://brand.volter.ai/agent/svg?seed=${encodeURIComponent(seed)}&size=36&radius=7`;
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* A message another session sent this one, as its harness delivers it: an envelope naming the sender (a
|
|
@@ -41,7 +41,7 @@ function withPeople(transcript, messages, { agentName = null, sessionId = '' } =
|
|
|
41
41
|
const at = Date.parse(message.metadata?.timestamp ?? '');
|
|
42
42
|
if (Number.isFinite(at)) byTime.set(at, message.metadata);
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
const people = transcript.map((entry) => {
|
|
45
45
|
// This session's own turns: named as the Room knows its agent, with the agent mark.
|
|
46
46
|
if (entry.role === 'assistant') return { ...entry, actor: { ...(agentName ? { name: agentName } : {}), image: agentImage(sessionId), kind: 'agent' } };
|
|
47
47
|
if (entry.role !== 'user') return entry;
|
|
@@ -53,6 +53,17 @@ function withPeople(transcript, messages, { agentName = null, sessionId = '' } =
|
|
|
53
53
|
const name = metadata.source_name || null;
|
|
54
54
|
return { ...entry, actor: { name: name ?? 'Someone in the session', image: personImage(name ? (metadata.source_principal_id || name) : ''), kind: 'person' } };
|
|
55
55
|
});
|
|
56
|
+
// A row layout groups one author's run: a message by the same author within five minutes of their last is
|
|
57
|
+
// `continued` (no second avatar and name); a tool step does not break the run. Each shows a short local time.
|
|
58
|
+
let last = null;
|
|
59
|
+
return people.map((entry) => {
|
|
60
|
+
if (!entry.actor) return entry;
|
|
61
|
+
const author = `${entry.actor.kind ?? ''}:${entry.actor.name ?? entry.role}`;
|
|
62
|
+
const continued = last !== null && last.author === author && Number.isFinite(entry.ts) && Number.isFinite(last.ts) && entry.ts - last.ts < 5 * 60_000;
|
|
63
|
+
last = { author, ts: entry.ts };
|
|
64
|
+
const timeLabel = Number.isFinite(entry.ts) ? new Date(entry.ts).toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' }) : undefined;
|
|
65
|
+
return { ...entry, actor: { ...entry.actor, ...(continued ? { continued: true } : {}), ...(timeLabel ? { timeLabel } : {}) } };
|
|
66
|
+
});
|
|
56
67
|
}
|
|
57
68
|
|
|
58
69
|
const SOURCES = { 'claude-code': 'claude_code', codex: 'codex', gemini: 'gemini', goose: 'goose', grok: 'grok', opencode: 'opencode', pi: 'pi' };
|
|
@@ -103,7 +114,8 @@ export function mountSessionView(element, { onSend, control = false, agentName =
|
|
|
103
114
|
const composerState = normalizeUiState({ ...EMPTY_UI_STATE, startup: 'ready', harness: descriptor?.harness ?? '', canSend: canSend && !sending, busy: sending, transcript });
|
|
104
115
|
render(h('div', { class: 'session-view' },
|
|
105
116
|
h(TeamTranscript, { session: descriptor, transcript, members, machines, live, status, error, adapter, labels, pending: current.pending }),
|
|
106
|
-
canSend ? h('div', { class: 'session-composer scui-root' }, h(Composer, { state: composerState, adapter })) : null,
|
|
117
|
+
canSend ? h('div', { class: 'session-composer scui-root' }, h(Composer, { state: composerState, adapter, labels: current.composerPlaceholder ? { askAgent: current.composerPlaceholder } : undefined })) : null,
|
|
118
|
+
canSend && current.composerHint ? h('p', { class: 'session-hint' }, current.composerHint) : null,
|
|
107
119
|
), element);
|
|
108
120
|
};
|
|
109
121
|
draw();
|
package/viewer/session-view.css
CHANGED
|
@@ -379,7 +379,8 @@
|
|
|
379
379
|
.scui-message-actor { display:var(--scui-message-actor-display, none); grid-row:1 / span 9; grid-template-columns:var(--scui-message-actor-columns, auto auto); gap:calc(10px * var(--scui-scaling)); align-items:baseline; color:var(--scui-muted); font:var(--scui-text-xs) var(--scui-font-mono) }
|
|
380
380
|
.scui-message-actor-time { white-space:nowrap }
|
|
381
381
|
.scui-message-actor-name { display:inline-flex; align-items:center; gap:calc(8px * var(--scui-scaling)); color:var(--scui-fg); white-space:nowrap }
|
|
382
|
-
|
|
382
|
+
/* A host's picture carries its own shape (a brand face is round, an agent's mark a rounded square): never cropped. */
|
|
383
|
+
.scui-message-actor-image { width:18px; height:18px; flex:none; object-fit:cover }
|
|
383
384
|
.scui-message-actor-name::before { content:''; width:var(--scui-message-actor-dot, 0); height:var(--scui-message-actor-dot, 0); border-radius:50%; background:var(--scui-message-actor-dot-bg, var(--scui-muted)) }
|
|
384
385
|
.scui-message-actor-name[data-role="user"]::before { background:var(--scui-message-actor-user-dot-bg, var(--scui-fg)) }
|
|
385
386
|
/* Muted color, not opacity: opacity crushed the footer text below the 4.5:1 contrast floor (axe color-contrast).
|