@volter-ai-dev/supercode-ui 0.1.45 → 0.1.47
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/README.md +4 -1
- package/activity.mjs +6 -2
- package/components.mjs +7 -3
- package/controller.d.ts +2 -0
- package/controller.mjs +6 -4
- package/core.mjs +7 -0
- package/embed.mjs +2 -1
- package/index.d.ts +3 -0
- package/messenger.mjs +2 -1
- package/package.json +1 -1
- package/react/activity.mjs +6 -2
- package/react/components.mjs +7 -3
- package/react/messenger.mjs +2 -1
- package/react/sessions.mjs +1 -1
- package/sessions.mjs +1 -1
- package/styles.css +2 -0
package/README.md
CHANGED
|
@@ -205,7 +205,10 @@ and can overlay a machine-wide session inventory, pagination state, attention, d
|
|
|
205
205
|
errors, and owned/attached identities without reimplementing transcript or capability semantics.
|
|
206
206
|
`projectSessionInventory` performs the corresponding title, latest-preview, activity, path, age,
|
|
207
207
|
sorting, and row projection for raw machine-wide descriptors; the trusted host supplies only its
|
|
208
|
-
opaque-key callback and retains the reversible locator map.
|
|
208
|
+
opaque-key callback and retains the reversible locator map. Its `isWritable` capability callback
|
|
209
|
+
is fail-closed: unread badges remain neutral until the host proves a real send or terminal-control
|
|
210
|
+
path. Runtime activity remains independent, so a read-only channel can still truthfully show that
|
|
211
|
+
its external agent is working or needs input.
|
|
209
212
|
|
|
210
213
|
## Modularity contract
|
|
211
214
|
|
package/activity.mjs
CHANGED
|
@@ -554,6 +554,7 @@ function readSessions(value) {
|
|
|
554
554
|
updatedAt: nullableNumber(row.updatedAt),
|
|
555
555
|
messages: nullableNumber(row.messages),
|
|
556
556
|
active: row.active === true,
|
|
557
|
+
writable: row.writable === true,
|
|
557
558
|
live: row.live === true,
|
|
558
559
|
runtimeStatus: row.runtimeStatus === "running" || row.runtimeStatus === "busy" || row.runtimeStatus === "idle" ? row.runtimeStatus : null
|
|
559
560
|
}];
|
|
@@ -815,7 +816,9 @@ function activityDetail(activity, preview, pill) {
|
|
|
815
816
|
function projectAgentActivity(value) {
|
|
816
817
|
const state = normalizeUiState(value);
|
|
817
818
|
const attentionByKey = new Map(state.attention.map((item) => [item.key, item]));
|
|
819
|
+
const sessionsByKey = new Map(state.sessions.map((row) => [row.key, row]));
|
|
818
820
|
const unreadCount = state.attention.reduce((total, item) => total + (item.unreadCount ?? 1), 0);
|
|
821
|
+
const unreadTone = state.attention.length > 0 && state.attention.every((item) => sessionsByKey.get(item.key)?.writable) ? "attention" : "neutral";
|
|
819
822
|
const ranked = state.sessions.map((row, index) => {
|
|
820
823
|
const activity2 = sessionActivity(state, row);
|
|
821
824
|
return {
|
|
@@ -839,7 +842,8 @@ function projectAgentActivity(value) {
|
|
|
839
842
|
title: selected ? sessionDisplayName(selected.row) : fallback ? sessionDisplayName(fallback) : "Agent chats",
|
|
840
843
|
detail: activityDetail(activity, preview, state.pill.label),
|
|
841
844
|
activity,
|
|
842
|
-
unreadCount
|
|
845
|
+
unreadCount,
|
|
846
|
+
unreadTone
|
|
843
847
|
};
|
|
844
848
|
}
|
|
845
849
|
function toolTarget(argumentsText) {
|
|
@@ -926,7 +930,7 @@ function AgentActivityLauncher({ state, onOpen, class: className = "", showSumma
|
|
|
926
930
|
const Logo = components.HarnessLogo ?? HarnessLogo;
|
|
927
931
|
const badge = value.unreadCount > 99 ? "99+" : String(value.unreadCount);
|
|
928
932
|
const label = [value.title, value.detail, value.unreadCount ? `${value.unreadCount} unread` : ""].filter(Boolean).join(" \xB7 ");
|
|
929
|
-
return /* @__PURE__ */ jsxs2("button", { className: `scui-launcher ${className}`, "data-activity": value.activity, type: "button", "aria-label": `Open ${label}`, onClick: () => onOpen?.(value), children: [
|
|
933
|
+
return /* @__PURE__ */ jsxs2("button", { className: `scui-launcher ${className}`, "data-activity": value.activity, "data-unread-tone": value.unreadTone, type: "button", "aria-label": `Open ${label}`, onClick: () => onOpen?.(value), children: [
|
|
930
934
|
/* @__PURE__ */ jsxs2("span", { className: "scui-launcher-logo", children: [
|
|
931
935
|
/* @__PURE__ */ jsx2(Logo, { id: value.harness || "supercode", activity: value.activity, size: 36 }),
|
|
932
936
|
value.unreadCount ? /* @__PURE__ */ jsx2("b", { "aria-hidden": "true", children: badge }) : null
|
package/components.mjs
CHANGED
|
@@ -566,6 +566,7 @@ function readSessions(value) {
|
|
|
566
566
|
updatedAt: nullableNumber(row.updatedAt),
|
|
567
567
|
messages: nullableNumber(row.messages),
|
|
568
568
|
active: row.active === true,
|
|
569
|
+
writable: row.writable === true,
|
|
569
570
|
live: row.live === true,
|
|
570
571
|
runtimeStatus: row.runtimeStatus === "running" || row.runtimeStatus === "busy" || row.runtimeStatus === "idle" ? row.runtimeStatus : null
|
|
571
572
|
}];
|
|
@@ -827,7 +828,9 @@ function activityDetail(activity, preview, pill) {
|
|
|
827
828
|
function projectAgentActivity(value) {
|
|
828
829
|
const state = normalizeUiState(value);
|
|
829
830
|
const attentionByKey = new Map(state.attention.map((item) => [item.key, item]));
|
|
831
|
+
const sessionsByKey = new Map(state.sessions.map((row) => [row.key, row]));
|
|
830
832
|
const unreadCount = state.attention.reduce((total, item) => total + (item.unreadCount ?? 1), 0);
|
|
833
|
+
const unreadTone = state.attention.length > 0 && state.attention.every((item) => sessionsByKey.get(item.key)?.writable) ? "attention" : "neutral";
|
|
831
834
|
const ranked = state.sessions.map((row, index) => {
|
|
832
835
|
const activity2 = sessionActivity(state, row);
|
|
833
836
|
return {
|
|
@@ -851,7 +854,8 @@ function projectAgentActivity(value) {
|
|
|
851
854
|
title: selected ? sessionDisplayName(selected.row) : fallback ? sessionDisplayName(fallback) : "Agent chats",
|
|
852
855
|
detail: activityDetail(activity, preview, state.pill.label),
|
|
853
856
|
activity,
|
|
854
|
-
unreadCount
|
|
857
|
+
unreadCount,
|
|
858
|
+
unreadTone
|
|
855
859
|
};
|
|
856
860
|
}
|
|
857
861
|
function filterSessions(rows, query) {
|
|
@@ -1639,7 +1643,7 @@ function AgentActivityLauncher({ state, onOpen, class: className = "", showSumma
|
|
|
1639
1643
|
const Logo = components.HarnessLogo ?? HarnessLogo;
|
|
1640
1644
|
const badge = value.unreadCount > 99 ? "99+" : String(value.unreadCount);
|
|
1641
1645
|
const label = [value.title, value.detail, value.unreadCount ? `${value.unreadCount} unread` : ""].filter(Boolean).join(" \xB7 ");
|
|
1642
|
-
return /* @__PURE__ */ jsxs5("button", { className: `scui-launcher ${className}`, "data-activity": value.activity, type: "button", "aria-label": `Open ${label}`, onClick: () => onOpen?.(value), children: [
|
|
1646
|
+
return /* @__PURE__ */ jsxs5("button", { className: `scui-launcher ${className}`, "data-activity": value.activity, "data-unread-tone": value.unreadTone, type: "button", "aria-label": `Open ${label}`, onClick: () => onOpen?.(value), children: [
|
|
1643
1647
|
/* @__PURE__ */ jsxs5("span", { className: "scui-launcher-logo", children: [
|
|
1644
1648
|
/* @__PURE__ */ jsx5(Logo, { id: value.harness || "supercode", activity: value.activity, size: 36 }),
|
|
1645
1649
|
value.unreadCount ? /* @__PURE__ */ jsx5("b", { "aria-hidden": "true", children: badge }) : null
|
|
@@ -2299,7 +2303,7 @@ function SessionRow({ row, state, onOpen, now = Date.now() }) {
|
|
|
2299
2303
|
const unreadCount = attention?.unreadCount ?? 0;
|
|
2300
2304
|
const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
|
|
2301
2305
|
const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
|
|
2302
|
-
return /* @__PURE__ */ jsxs7("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
2306
|
+
return /* @__PURE__ */ jsxs7("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${row.writable ? "" : " \xB7 Read-only"}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
2303
2307
|
/* @__PURE__ */ jsx8(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
2304
2308
|
/* @__PURE__ */ jsxs7("span", { className: "scui-session-copy", children: [
|
|
2305
2309
|
/* @__PURE__ */ jsxs7("span", { className: "scui-session-title", children: [
|
package/controller.d.ts
CHANGED
|
@@ -65,6 +65,8 @@ export interface SessionInventoryProjectionOptions {
|
|
|
65
65
|
maxSessions?: number;
|
|
66
66
|
liveWindowMs?: number;
|
|
67
67
|
preserveOrder?: boolean;
|
|
68
|
+
/** Capability check performed by the trusted host; omitted rows are read-only observations. */
|
|
69
|
+
isWritable?(descriptor: SessionDescriptor): boolean;
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
export function sessionConversationUpdatedAt(descriptor: SessionDescriptor): number | null;
|
package/controller.mjs
CHANGED
|
@@ -72,7 +72,7 @@ function descriptorTitle(descriptor) {
|
|
|
72
72
|
return compactTopic(nativeTitle);
|
|
73
73
|
}
|
|
74
74
|
if (descriptor?.locator?.harness !== 'claude-code' && descriptor?.locator?.harness !== 'codex') {
|
|
75
|
-
return compactTopic(nativeTitle || workspace
|
|
75
|
+
return compactTopic(nativeTitle || workspace) || 'Untitled chat';
|
|
76
76
|
}
|
|
77
77
|
const openingUserMessages = (descriptor?.preview_candidates ?? []).filter(
|
|
78
78
|
(candidate) => candidate?.role === undefined || candidate.role === 'user',
|
|
@@ -125,6 +125,7 @@ export function projectSessionInventory(descriptors, options) {
|
|
|
125
125
|
active: active?.sessionId != null
|
|
126
126
|
&& descriptor.locator.harness === active.harness
|
|
127
127
|
&& descriptor.locator.session_id === active.sessionId,
|
|
128
|
+
writable: options.isWritable?.(descriptor) === true,
|
|
128
129
|
live: updatedAt !== null && now - updatedAt <= liveWindowMs,
|
|
129
130
|
runtimeStatus: sessionDescriptorRuntimeStatus(descriptor),
|
|
130
131
|
});
|
|
@@ -378,14 +379,14 @@ function attached(snapshot) {
|
|
|
378
379
|
harness: snapshot.activeHarness,
|
|
379
380
|
name: workspaceName(snapshot.workspace),
|
|
380
381
|
cwd: snapshot.workspace,
|
|
381
|
-
title:
|
|
382
|
+
title: 'Untitled chat',
|
|
382
383
|
} : null;
|
|
383
384
|
return {
|
|
384
385
|
key: session.key,
|
|
385
386
|
harness: session.harness,
|
|
386
387
|
name: workspaceName(session.cwd),
|
|
387
388
|
cwd: session.cwd ?? '',
|
|
388
|
-
title: session.title ??
|
|
389
|
+
title: session.title ?? 'Untitled chat',
|
|
389
390
|
};
|
|
390
391
|
}
|
|
391
392
|
|
|
@@ -442,11 +443,12 @@ function projectClientSnapshotInternal(snapshot, options, imageRegistry) {
|
|
|
442
443
|
harness: session.harness,
|
|
443
444
|
name: workspaceName(session.cwd),
|
|
444
445
|
cwd: session.cwd ?? '',
|
|
445
|
-
title: session.title ??
|
|
446
|
+
title: session.title ?? 'Untitled chat',
|
|
446
447
|
age: relativeAge(session.updatedAt, now),
|
|
447
448
|
updatedAt: session.updatedAt ?? null,
|
|
448
449
|
messages: session.messageCount ?? null,
|
|
449
450
|
active: session.key === snapshot.activeSessionKey,
|
|
451
|
+
writable: session.key === snapshot.activeSessionKey && actions.send === true,
|
|
450
452
|
live: typeof session.updatedAt === 'number' && now - session.updatedAt <= liveWindowMs,
|
|
451
453
|
runtimeStatus: session.liveStatus ?? null,
|
|
452
454
|
}));
|
package/core.mjs
CHANGED
|
@@ -562,6 +562,7 @@ function readSessions(value) {
|
|
|
562
562
|
updatedAt: nullableNumber(row.updatedAt),
|
|
563
563
|
messages: nullableNumber(row.messages),
|
|
564
564
|
active: row.active === true,
|
|
565
|
+
writable: row.writable === true,
|
|
565
566
|
live: row.live === true,
|
|
566
567
|
runtimeStatus: row.runtimeStatus === 'running' || row.runtimeStatus === 'busy' || row.runtimeStatus === 'idle' ? row.runtimeStatus : null,
|
|
567
568
|
}];
|
|
@@ -896,7 +897,12 @@ function activityDetail(activity, preview, pill) {
|
|
|
896
897
|
export function projectAgentActivity(value) {
|
|
897
898
|
const state = normalizeUiState(value);
|
|
898
899
|
const attentionByKey = new Map(state.attention.map((item) => [item.key, item]));
|
|
900
|
+
const sessionsByKey = new Map(state.sessions.map((row) => [row.key, row]));
|
|
899
901
|
const unreadCount = state.attention.reduce((total, item) => total + (item.unreadCount ?? 1), 0);
|
|
902
|
+
const unreadTone = state.attention.length > 0
|
|
903
|
+
&& state.attention.every((item) => sessionsByKey.get(item.key)?.writable)
|
|
904
|
+
? 'attention'
|
|
905
|
+
: 'neutral';
|
|
900
906
|
const ranked = state.sessions.map((row, index) => {
|
|
901
907
|
const activity = sessionActivity(state, row);
|
|
902
908
|
return {
|
|
@@ -921,6 +927,7 @@ export function projectAgentActivity(value) {
|
|
|
921
927
|
detail: activityDetail(activity, preview, state.pill.label),
|
|
922
928
|
activity,
|
|
923
929
|
unreadCount,
|
|
930
|
+
unreadTone,
|
|
924
931
|
};
|
|
925
932
|
}
|
|
926
933
|
|
package/embed.mjs
CHANGED
|
@@ -569,6 +569,7 @@ function readSessions(value) {
|
|
|
569
569
|
updatedAt: nullableNumber(row.updatedAt),
|
|
570
570
|
messages: nullableNumber(row.messages),
|
|
571
571
|
active: row.active === true,
|
|
572
|
+
writable: row.writable === true,
|
|
572
573
|
live: row.live === true,
|
|
573
574
|
runtimeStatus: row.runtimeStatus === "running" || row.runtimeStatus === "busy" || row.runtimeStatus === "idle" ? row.runtimeStatus : null
|
|
574
575
|
}];
|
|
@@ -2219,7 +2220,7 @@ function SessionRow({ row, state, onOpen, now = Date.now() }) {
|
|
|
2219
2220
|
const unreadCount = attention?.unreadCount ?? 0;
|
|
2220
2221
|
const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
|
|
2221
2222
|
const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
|
|
2222
|
-
return /* @__PURE__ */ jsxs6("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
2223
|
+
return /* @__PURE__ */ jsxs6("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${row.writable ? "" : " \xB7 Read-only"}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
2223
2224
|
/* @__PURE__ */ jsx7(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
2224
2225
|
/* @__PURE__ */ jsxs6("span", { className: "scui-session-copy", children: [
|
|
2225
2226
|
/* @__PURE__ */ jsxs6("span", { className: "scui-session-title", children: [
|
package/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export interface AgentActivityModel {
|
|
|
17
17
|
detail: string;
|
|
18
18
|
activity: SessionActivity;
|
|
19
19
|
unreadCount: number;
|
|
20
|
+
unreadTone: 'attention' | 'neutral';
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export interface HarnessOption {
|
|
@@ -58,6 +59,8 @@ export interface SessionRowModel {
|
|
|
58
59
|
updatedAt: number | null;
|
|
59
60
|
messages: number | null;
|
|
60
61
|
active: boolean;
|
|
62
|
+
/** This surface currently has a real send or terminal-control path for the session. */
|
|
63
|
+
writable: boolean;
|
|
61
64
|
live: boolean;
|
|
62
65
|
runtimeStatus: 'running' | 'busy' | 'idle' | null;
|
|
63
66
|
}
|
package/messenger.mjs
CHANGED
|
@@ -566,6 +566,7 @@ function readSessions(value) {
|
|
|
566
566
|
updatedAt: nullableNumber(row.updatedAt),
|
|
567
567
|
messages: nullableNumber(row.messages),
|
|
568
568
|
active: row.active === true,
|
|
569
|
+
writable: row.writable === true,
|
|
569
570
|
live: row.live === true,
|
|
570
571
|
runtimeStatus: row.runtimeStatus === "running" || row.runtimeStatus === "busy" || row.runtimeStatus === "idle" ? row.runtimeStatus : null
|
|
571
572
|
}];
|
|
@@ -2216,7 +2217,7 @@ function SessionRow({ row, state, onOpen, now = Date.now() }) {
|
|
|
2216
2217
|
const unreadCount = attention?.unreadCount ?? 0;
|
|
2217
2218
|
const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
|
|
2218
2219
|
const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
|
|
2219
|
-
return /* @__PURE__ */ jsxs6("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
2220
|
+
return /* @__PURE__ */ jsxs6("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${row.writable ? "" : " \xB7 Read-only"}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
2220
2221
|
/* @__PURE__ */ jsx7(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
2221
2222
|
/* @__PURE__ */ jsxs6("span", { className: "scui-session-copy", children: [
|
|
2222
2223
|
/* @__PURE__ */ jsxs6("span", { className: "scui-session-title", children: [
|
package/package.json
CHANGED
package/react/activity.mjs
CHANGED
|
@@ -554,6 +554,7 @@ function readSessions(value) {
|
|
|
554
554
|
updatedAt: nullableNumber(row.updatedAt),
|
|
555
555
|
messages: nullableNumber(row.messages),
|
|
556
556
|
active: row.active === true,
|
|
557
|
+
writable: row.writable === true,
|
|
557
558
|
live: row.live === true,
|
|
558
559
|
runtimeStatus: row.runtimeStatus === "running" || row.runtimeStatus === "busy" || row.runtimeStatus === "idle" ? row.runtimeStatus : null
|
|
559
560
|
}];
|
|
@@ -815,7 +816,9 @@ function activityDetail(activity, preview, pill) {
|
|
|
815
816
|
function projectAgentActivity(value) {
|
|
816
817
|
const state = normalizeUiState(value);
|
|
817
818
|
const attentionByKey = new Map(state.attention.map((item) => [item.key, item]));
|
|
819
|
+
const sessionsByKey = new Map(state.sessions.map((row) => [row.key, row]));
|
|
818
820
|
const unreadCount = state.attention.reduce((total, item) => total + (item.unreadCount ?? 1), 0);
|
|
821
|
+
const unreadTone = state.attention.length > 0 && state.attention.every((item) => sessionsByKey.get(item.key)?.writable) ? "attention" : "neutral";
|
|
819
822
|
const ranked = state.sessions.map((row, index) => {
|
|
820
823
|
const activity2 = sessionActivity(state, row);
|
|
821
824
|
return {
|
|
@@ -839,7 +842,8 @@ function projectAgentActivity(value) {
|
|
|
839
842
|
title: selected ? sessionDisplayName(selected.row) : fallback ? sessionDisplayName(fallback) : "Agent chats",
|
|
840
843
|
detail: activityDetail(activity, preview, state.pill.label),
|
|
841
844
|
activity,
|
|
842
|
-
unreadCount
|
|
845
|
+
unreadCount,
|
|
846
|
+
unreadTone
|
|
843
847
|
};
|
|
844
848
|
}
|
|
845
849
|
function toolTarget(argumentsText) {
|
|
@@ -926,7 +930,7 @@ function AgentActivityLauncher({ state, onOpen, class: className = "", showSumma
|
|
|
926
930
|
const Logo = components.HarnessLogo ?? HarnessLogo;
|
|
927
931
|
const badge = value.unreadCount > 99 ? "99+" : String(value.unreadCount);
|
|
928
932
|
const label = [value.title, value.detail, value.unreadCount ? `${value.unreadCount} unread` : ""].filter(Boolean).join(" \xB7 ");
|
|
929
|
-
return /* @__PURE__ */ jsxs2("button", { className: `scui-launcher ${className}`, "data-activity": value.activity, type: "button", "aria-label": `Open ${label}`, onClick: () => onOpen?.(value), children: [
|
|
933
|
+
return /* @__PURE__ */ jsxs2("button", { className: `scui-launcher ${className}`, "data-activity": value.activity, "data-unread-tone": value.unreadTone, type: "button", "aria-label": `Open ${label}`, onClick: () => onOpen?.(value), children: [
|
|
930
934
|
/* @__PURE__ */ jsxs2("span", { className: "scui-launcher-logo", children: [
|
|
931
935
|
/* @__PURE__ */ jsx2(Logo, { id: value.harness || "supercode", activity: value.activity, size: 36 }),
|
|
932
936
|
value.unreadCount ? /* @__PURE__ */ jsx2("b", { "aria-hidden": "true", children: badge }) : null
|
package/react/components.mjs
CHANGED
|
@@ -566,6 +566,7 @@ function readSessions(value) {
|
|
|
566
566
|
updatedAt: nullableNumber(row.updatedAt),
|
|
567
567
|
messages: nullableNumber(row.messages),
|
|
568
568
|
active: row.active === true,
|
|
569
|
+
writable: row.writable === true,
|
|
569
570
|
live: row.live === true,
|
|
570
571
|
runtimeStatus: row.runtimeStatus === "running" || row.runtimeStatus === "busy" || row.runtimeStatus === "idle" ? row.runtimeStatus : null
|
|
571
572
|
}];
|
|
@@ -827,7 +828,9 @@ function activityDetail(activity, preview, pill) {
|
|
|
827
828
|
function projectAgentActivity(value) {
|
|
828
829
|
const state = normalizeUiState(value);
|
|
829
830
|
const attentionByKey = new Map(state.attention.map((item) => [item.key, item]));
|
|
831
|
+
const sessionsByKey = new Map(state.sessions.map((row) => [row.key, row]));
|
|
830
832
|
const unreadCount = state.attention.reduce((total, item) => total + (item.unreadCount ?? 1), 0);
|
|
833
|
+
const unreadTone = state.attention.length > 0 && state.attention.every((item) => sessionsByKey.get(item.key)?.writable) ? "attention" : "neutral";
|
|
831
834
|
const ranked = state.sessions.map((row, index) => {
|
|
832
835
|
const activity2 = sessionActivity(state, row);
|
|
833
836
|
return {
|
|
@@ -851,7 +854,8 @@ function projectAgentActivity(value) {
|
|
|
851
854
|
title: selected ? sessionDisplayName(selected.row) : fallback ? sessionDisplayName(fallback) : "Agent chats",
|
|
852
855
|
detail: activityDetail(activity, preview, state.pill.label),
|
|
853
856
|
activity,
|
|
854
|
-
unreadCount
|
|
857
|
+
unreadCount,
|
|
858
|
+
unreadTone
|
|
855
859
|
};
|
|
856
860
|
}
|
|
857
861
|
function filterSessions(rows, query) {
|
|
@@ -1639,7 +1643,7 @@ function AgentActivityLauncher({ state, onOpen, class: className = "", showSumma
|
|
|
1639
1643
|
const Logo = components.HarnessLogo ?? HarnessLogo;
|
|
1640
1644
|
const badge = value.unreadCount > 99 ? "99+" : String(value.unreadCount);
|
|
1641
1645
|
const label = [value.title, value.detail, value.unreadCount ? `${value.unreadCount} unread` : ""].filter(Boolean).join(" \xB7 ");
|
|
1642
|
-
return /* @__PURE__ */ jsxs5("button", { className: `scui-launcher ${className}`, "data-activity": value.activity, type: "button", "aria-label": `Open ${label}`, onClick: () => onOpen?.(value), children: [
|
|
1646
|
+
return /* @__PURE__ */ jsxs5("button", { className: `scui-launcher ${className}`, "data-activity": value.activity, "data-unread-tone": value.unreadTone, type: "button", "aria-label": `Open ${label}`, onClick: () => onOpen?.(value), children: [
|
|
1643
1647
|
/* @__PURE__ */ jsxs5("span", { className: "scui-launcher-logo", children: [
|
|
1644
1648
|
/* @__PURE__ */ jsx5(Logo, { id: value.harness || "supercode", activity: value.activity, size: 36 }),
|
|
1645
1649
|
value.unreadCount ? /* @__PURE__ */ jsx5("b", { "aria-hidden": "true", children: badge }) : null
|
|
@@ -2299,7 +2303,7 @@ function SessionRow({ row, state, onOpen, now = Date.now() }) {
|
|
|
2299
2303
|
const unreadCount = attention?.unreadCount ?? 0;
|
|
2300
2304
|
const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
|
|
2301
2305
|
const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
|
|
2302
|
-
return /* @__PURE__ */ jsxs7("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
2306
|
+
return /* @__PURE__ */ jsxs7("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${row.writable ? "" : " \xB7 Read-only"}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
2303
2307
|
/* @__PURE__ */ jsx8(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
2304
2308
|
/* @__PURE__ */ jsxs7("span", { className: "scui-session-copy", children: [
|
|
2305
2309
|
/* @__PURE__ */ jsxs7("span", { className: "scui-session-title", children: [
|
package/react/messenger.mjs
CHANGED
|
@@ -566,6 +566,7 @@ function readSessions(value) {
|
|
|
566
566
|
updatedAt: nullableNumber(row.updatedAt),
|
|
567
567
|
messages: nullableNumber(row.messages),
|
|
568
568
|
active: row.active === true,
|
|
569
|
+
writable: row.writable === true,
|
|
569
570
|
live: row.live === true,
|
|
570
571
|
runtimeStatus: row.runtimeStatus === "running" || row.runtimeStatus === "busy" || row.runtimeStatus === "idle" ? row.runtimeStatus : null
|
|
571
572
|
}];
|
|
@@ -2216,7 +2217,7 @@ function SessionRow({ row, state, onOpen, now = Date.now() }) {
|
|
|
2216
2217
|
const unreadCount = attention?.unreadCount ?? 0;
|
|
2217
2218
|
const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
|
|
2218
2219
|
const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
|
|
2219
|
-
return /* @__PURE__ */ jsxs6("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
2220
|
+
return /* @__PURE__ */ jsxs6("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${row.writable ? "" : " \xB7 Read-only"}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
2220
2221
|
/* @__PURE__ */ jsx7(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
2221
2222
|
/* @__PURE__ */ jsxs6("span", { className: "scui-session-copy", children: [
|
|
2222
2223
|
/* @__PURE__ */ jsxs6("span", { className: "scui-session-title", children: [
|
package/react/sessions.mjs
CHANGED
|
@@ -332,7 +332,7 @@ function SessionRow({ row, state, onOpen, now = Date.now() }) {
|
|
|
332
332
|
const unreadCount = attention?.unreadCount ?? 0;
|
|
333
333
|
const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
|
|
334
334
|
const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
|
|
335
|
-
return /* @__PURE__ */ jsxs5("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
335
|
+
return /* @__PURE__ */ jsxs5("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${row.writable ? "" : " \xB7 Read-only"}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
336
336
|
/* @__PURE__ */ jsx6(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
337
337
|
/* @__PURE__ */ jsxs5("span", { className: "scui-session-copy", children: [
|
|
338
338
|
/* @__PURE__ */ jsxs5("span", { className: "scui-session-title", children: [
|
package/sessions.mjs
CHANGED
|
@@ -332,7 +332,7 @@ function SessionRow({ row, state, onOpen, now = Date.now() }) {
|
|
|
332
332
|
const unreadCount = attention?.unreadCount ?? 0;
|
|
333
333
|
const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
|
|
334
334
|
const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
|
|
335
|
-
return /* @__PURE__ */ jsxs5("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
335
|
+
return /* @__PURE__ */ jsxs5("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${row.writable ? "" : " \xB7 Read-only"}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
336
336
|
/* @__PURE__ */ jsx6(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
337
337
|
/* @__PURE__ */ jsxs5("span", { className: "scui-session-copy", children: [
|
|
338
338
|
/* @__PURE__ */ jsxs5("span", { className: "scui-session-title", children: [
|
package/styles.css
CHANGED
|
@@ -80,6 +80,7 @@
|
|
|
80
80
|
|
|
81
81
|
.scui-launcher { --scui-bg:#fff; --scui-fg:#191918; --scui-muted:#5f5f5a; --scui-border:#deded9; --scui-positive:#22863a; --scui-warning:#b26a00; --scui-danger:#b4232e; display:inline-flex; min-width:44px; min-height:44px; align-items:center; gap:8px; padding:4px; overflow:visible; border:1px solid var(--scui-border); border-radius:999px; background:color-mix(in srgb,var(--scui-bg) 88%,transparent); color:var(--scui-fg); box-shadow:0 5px 18px rgba(0,0,0,.14); cursor:pointer; font:12px/1.25 var(--scui-font,Inter,ui-sans-serif,system-ui,sans-serif); backdrop-filter:blur(10px) }
|
|
82
82
|
.scui-launcher-logo { position:relative; display:grid; flex:none; place-items:center }.scui-launcher-logo > b { position:absolute; z-index:1; top:-6px; right:-8px; display:grid; min-width:18px; height:18px; padding:0 4px; place-items:center; border:2px solid var(--scui-bg); border-radius:999px; background:var(--scui-danger); color:#fff; font-size:9px; line-height:1 }
|
|
83
|
+
.scui-launcher[data-unread-tone="neutral"] .scui-launcher-logo > b { background:var(--scui-muted) }
|
|
83
84
|
.scui-launcher-copy { display:grid; min-width:0; max-width:220px; padding-right:8px; text-align:left }.scui-launcher-copy strong,.scui-launcher-copy small { overflow:hidden; text-overflow:ellipsis; white-space:nowrap }.scui-launcher-copy small { color:var(--scui-muted); font-size:10px }
|
|
84
85
|
.scui-launcher:hover { border-color:color-mix(in srgb,var(--scui-fg) 28%,var(--scui-border)); box-shadow:0 7px 22px rgba(0,0,0,.18) }.scui-launcher:focus-visible { outline:2px solid currentColor; outline-offset:2px }
|
|
85
86
|
@media (prefers-color-scheme:dark) { .scui-launcher { --scui-bg:#151515; --scui-fg:#f3f3ef; --scui-muted:#a3a39d; --scui-border:#353532; --scui-positive:#57c26e; --scui-warning:#e8a23a; --scui-danger:#ff747d } }
|
|
@@ -107,6 +108,7 @@
|
|
|
107
108
|
.scui-session-path { display:flex; min-width:0; overflow:hidden; color:var(--scui-muted); font-size:9.5px; white-space:nowrap }
|
|
108
109
|
.scui-session-path-leading { flex:0 1 auto; overflow:hidden; text-overflow:ellipsis }.scui-session-path-separator { flex:none }.scui-session-path-trailing { flex:none; max-width:58%; overflow:hidden; direction:rtl; text-align:left; text-overflow:ellipsis; unicode-bidi:plaintext }
|
|
109
110
|
.scui-session-preview small { flex:1; min-width:0; color:var(--scui-muted); font-size:10.5px }.scui-session-preview b { display:grid; flex:none; min-width:16px; height:16px; padding:0 4px; place-items:center; border-radius:8px; background:var(--scui-accent); color:var(--scui-bg); font-size:9px; line-height:16px }
|
|
111
|
+
.scui-session[data-writable="false"] .scui-session-preview b { background:var(--scui-muted) }
|
|
110
112
|
.scui-session-copy em { overflow:hidden; color:var(--scui-danger); font-size:10px; font-style:normal; text-overflow:ellipsis; white-space:nowrap }
|
|
111
113
|
.scui-load { display:block; margin:7px auto; padding:5px 10px; border:1px solid var(--scui-border); border-radius:8px; background:var(--scui-bg-raised); color:var(--scui-muted); cursor:pointer }.scui-load:disabled { opacity:.65; cursor:default }
|
|
112
114
|
|