@volter/teams 0.1.28 → 0.1.30
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/server/core.mjs +9 -3
- package/viewer/index.html +1 -2
- package/viewer/session-view-entry.mjs +3 -2
- package/viewer/session-view.css +2 -1
- package/viewer/session-view.mjs +14 -14
- package/viewer/viewer.mjs +20 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/teams",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
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/server/core.mjs
CHANGED
|
@@ -77,7 +77,13 @@ export async function maintain(api){const now=api.clock.nowMs();await api.store.
|
|
|
77
77
|
AND NOT EXISTS (SELECT 1 FROM cursors c, json_each(c.snapshot_json) j WHERE c.team_id=v.team_id AND c.kind IN ('list','search') AND c.expires_at>? AND json_extract(j.value,'$[0]')=v.session_id AND json_extract(j.value,'$[1]')=v.revision)
|
|
78
78
|
AND NOT EXISTS (SELECT 1 FROM cursors c WHERE c.team_id=v.team_id AND c.kind='history' AND c.expires_at>? AND json_extract(c.snapshot_json,'$.session_id')=v.session_id AND json_extract(c.snapshot_json,'$.revision')=v.revision)
|
|
79
79
|
LIMIT ${VERSION_PRUNE_BATCH}`,[now,now]);
|
|
80
|
+
// A committed capture's parts are its messages in transit; once committed, the session's version holds them, so
|
|
81
|
+
// they go (a backlog of them filled the database).
|
|
82
|
+
const parts=await api.store.query(`SELECT p.team_id,p.capture_id,p.part_index FROM capture_parts p JOIN captures c ON c.team_id=p.team_id AND c.id=p.capture_id WHERE c.state='committed' LIMIT ${PART_PRUNE_BATCH}`,[]);
|
|
83
|
+
if(parts.length)await api.store.transaction(parts.map(({team_id,capture_id,part_index})=>({sql:'DELETE FROM capture_parts WHERE team_id=? AND capture_id=? AND part_index=?',params:[team_id,capture_id,part_index]})));
|
|
80
84
|
if(stale.length)await api.store.transaction(stale.flatMap(({team_id,session_id,revision})=>['messages','session_artifacts','session_versions'].map(table=>({sql:`DELETE FROM ${table} WHERE team_id=? AND session_id=? AND revision=?`,params:[team_id,session_id,revision]}))));
|
|
81
|
-
return {pruned_versions:stale.length};}
|
|
82
|
-
/** Session versions `maintain` removes per run: small enough for one Durable Object alarm
|
|
83
|
-
const VERSION_PRUNE_BATCH=
|
|
85
|
+
return {pruned_versions:stale.length,pruned_parts:parts.length,backlog:stale.length>=VERSION_PRUNE_BATCH||parts.length>=PART_PRUNE_BATCH};}
|
|
86
|
+
/** Session versions `maintain` removes per run: small enough for one Durable Object alarm; a backlog runs again in seconds. */
|
|
87
|
+
const VERSION_PRUNE_BATCH=200;
|
|
88
|
+
/** Committed capture parts `maintain` removes per run. */
|
|
89
|
+
const PART_PRUNE_BATCH=500;
|
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). */
|
|
@@ -58,8 +59,6 @@
|
|
|
58
59
|
#session.layout-rows .scui-message:hover { background: var(--volter-surface-subtle, var(--scui-fill)); }
|
|
59
60
|
#session.layout-rows .scui-message-actor { display: flex; align-items: baseline; gap: 8px; margin: 0 0 1px; }
|
|
60
61
|
#session.layout-rows .scui-message-actor-image { position: absolute; left: 20px; top: 10px; width: 36px; height: 36px; }
|
|
61
|
-
/* A person's face is round; an agent's mark is a rounded square, so an agent never reads as a person. */
|
|
62
|
-
#session.layout-rows .scui-message[data-actor-kind="agent"] .scui-message-actor-image { border-radius: 8px; }
|
|
63
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; }
|
|
64
63
|
#session.layout-rows .scui-message-actor-name::before { display: none; }
|
|
65
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); }
|
|
@@ -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
|
|
@@ -114,7 +114,8 @@ export function mountSessionView(element, { onSend, control = false, agentName =
|
|
|
114
114
|
const composerState = normalizeUiState({ ...EMPTY_UI_STATE, startup: 'ready', harness: descriptor?.harness ?? '', canSend: canSend && !sending, busy: sending, transcript });
|
|
115
115
|
render(h('div', { class: 'session-view' },
|
|
116
116
|
h(TeamTranscript, { session: descriptor, transcript, members, machines, live, status, error, adapter, labels, pending: current.pending }),
|
|
117
|
-
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,
|
|
118
119
|
), element);
|
|
119
120
|
};
|
|
120
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).
|