@schlessera/brain-ui-react 0.17.0 → 0.19.0

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 (81) hide show
  1. package/dist/components/activity/activity-page.d.ts +11 -0
  2. package/dist/components/activity/activity-page.d.ts.map +1 -0
  3. package/dist/components/activity/activity-page.js +208 -0
  4. package/dist/components/activity/activity-page.js.map +1 -0
  5. package/dist/components/activity/digest-card.d.ts +10 -0
  6. package/dist/components/activity/digest-card.d.ts.map +1 -0
  7. package/dist/components/activity/digest-card.js +51 -0
  8. package/dist/components/activity/digest-card.js.map +1 -0
  9. package/dist/components/activity/push-toggle.d.ts +2 -0
  10. package/dist/components/activity/push-toggle.d.ts.map +1 -0
  11. package/dist/components/activity/push-toggle.js +82 -0
  12. package/dist/components/activity/push-toggle.js.map +1 -0
  13. package/dist/components/activity/span-bits.d.ts +28 -0
  14. package/dist/components/activity/span-bits.d.ts.map +1 -0
  15. package/dist/components/activity/span-bits.js +43 -0
  16. package/dist/components/activity/span-bits.js.map +1 -0
  17. package/dist/components/chat/chat-page.d.ts.map +1 -1
  18. package/dist/components/chat/chat-page.js +4 -1
  19. package/dist/components/chat/chat-page.js.map +1 -1
  20. package/dist/components/chat/session-drawer.d.ts.map +1 -1
  21. package/dist/components/chat/session-drawer.js +1 -15
  22. package/dist/components/chat/session-drawer.js.map +1 -1
  23. package/dist/components/chat/subagent-view.d.ts +18 -0
  24. package/dist/components/chat/subagent-view.d.ts.map +1 -0
  25. package/dist/components/chat/subagent-view.js +79 -0
  26. package/dist/components/chat/subagent-view.js.map +1 -0
  27. package/dist/components/chat/tool-call-timeline.d.ts.map +1 -1
  28. package/dist/components/chat/tool-call-timeline.js +40 -4
  29. package/dist/components/chat/tool-call-timeline.js.map +1 -1
  30. package/dist/components/chat/tool-views.d.ts +4 -0
  31. package/dist/components/chat/tool-views.d.ts.map +1 -1
  32. package/dist/components/chat/tool-views.js +26 -0
  33. package/dist/components/chat/tool-views.js.map +1 -1
  34. package/dist/components/layout/mobile-tab-bar.d.ts.map +1 -1
  35. package/dist/components/layout/mobile-tab-bar.js +10 -4
  36. package/dist/components/layout/mobile-tab-bar.js.map +1 -1
  37. package/dist/components/layout/side-rail.d.ts.map +1 -1
  38. package/dist/components/layout/side-rail.js +7 -4
  39. package/dist/components/layout/side-rail.js.map +1 -1
  40. package/dist/hooks/use-now.d.ts +8 -0
  41. package/dist/hooks/use-now.d.ts.map +1 -0
  42. package/dist/hooks/use-now.js +32 -0
  43. package/dist/hooks/use-now.js.map +1 -0
  44. package/dist/hooks/use-websocket.d.ts.map +1 -1
  45. package/dist/hooks/use-websocket.js +46 -0
  46. package/dist/hooks/use-websocket.js.map +1 -1
  47. package/dist/index.d.ts +1 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +1 -0
  50. package/dist/index.js.map +1 -1
  51. package/dist/lib/api-client.d.ts +40 -1
  52. package/dist/lib/api-client.d.ts.map +1 -1
  53. package/dist/lib/api-client.js +28 -0
  54. package/dist/lib/api-client.js.map +1 -1
  55. package/dist/stores/activity-store.d.ts +93 -0
  56. package/dist/stores/activity-store.d.ts.map +1 -0
  57. package/dist/stores/activity-store.js +310 -0
  58. package/dist/stores/activity-store.js.map +1 -0
  59. package/dist/stores/ui-store.d.ts +9 -1
  60. package/dist/stores/ui-store.d.ts.map +1 -1
  61. package/dist/stores/ui-store.js +3 -0
  62. package/dist/stores/ui-store.js.map +1 -1
  63. package/dist/styles.css +1 -1
  64. package/package.json +2 -2
  65. package/src/components/activity/activity-page.tsx +495 -0
  66. package/src/components/activity/digest-card.tsx +101 -0
  67. package/src/components/activity/push-toggle.tsx +128 -0
  68. package/src/components/activity/span-bits.tsx +71 -0
  69. package/src/components/chat/chat-page.tsx +17 -0
  70. package/src/components/chat/session-drawer.tsx +1 -12
  71. package/src/components/chat/subagent-view.tsx +229 -0
  72. package/src/components/chat/tool-call-timeline.tsx +61 -3
  73. package/src/components/chat/tool-views.tsx +22 -0
  74. package/src/components/layout/mobile-tab-bar.tsx +25 -5
  75. package/src/components/layout/side-rail.tsx +17 -0
  76. package/src/hooks/use-now.ts +32 -0
  77. package/src/hooks/use-websocket.ts +44 -0
  78. package/src/index.ts +1 -0
  79. package/src/lib/api-client.ts +75 -0
  80. package/src/stores/activity-store.ts +402 -0
  81. package/src/stores/ui-store.ts +13 -1
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The Activity surface: an INDEX of all agent activity — live runs first,
3
+ * then history — with cost/token rollups. Deliberately not a residence:
4
+ * a session run deep-links back into its chat, a subagent into the drill-in
5
+ * stack; only a cron run (which has no chat around it) details here.
6
+ *
7
+ * Live rows ride the index-view activity subscription while this surface is
8
+ * open; history and rollups come from the REST activity API.
9
+ */
10
+ export declare function ActivityPage(): import("react").JSX.Element;
11
+ //# sourceMappingURL=activity-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-page.d.ts","sourceRoot":"","sources":["../../../src/components/activity/activity-page.tsx"],"names":[],"mappings":"AAkCA;;;;;;;;GAQG;AACH,wBAAgB,YAAY,gCAwO3B"}
@@ -0,0 +1,208 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useState } from "react";
3
+ import { Activity as ActivityIcon, AlertTriangle, ArrowLeft, Bot, Clock, RefreshCw, Timer, } from "lucide-react";
4
+ import { useShallow } from "zustand/react/shallow";
5
+ import { isFailureOutcome } from "@schlessera/brain-ui-sdk/protocol";
6
+ import { api, } from "../../lib/api-client.js";
7
+ import { sendClientMessage } from "../../hooks/use-websocket.js";
8
+ import { useNow } from "../../hooks/use-now.js";
9
+ import { useActivityStore, runSpans } from "../../stores/activity-store.js";
10
+ import { useChatStore } from "../../stores/chat-store.js";
11
+ import { useUIStore } from "../../stores/ui-store.js";
12
+ import { cn } from "../../lib/utils.js";
13
+ import { formatDuration, formatRelativeTime, formatTokenCount, } from "../chat/tool-views.js";
14
+ import { SpanStatusDot, spanToolLabel } from "./span-bits.js";
15
+ import { PushToggle } from "./push-toggle.js";
16
+ /**
17
+ * The Activity surface: an INDEX of all agent activity — live runs first,
18
+ * then history — with cost/token rollups. Deliberately not a residence:
19
+ * a session run deep-links back into its chat, a subagent into the drill-in
20
+ * stack; only a cron run (which has no chat around it) details here.
21
+ *
22
+ * Live rows ride the index-view activity subscription while this surface is
23
+ * open; history and rollups come from the REST activity API.
24
+ */
25
+ export function ActivityPage() {
26
+ const supported = useActivityStore((s) => s.supported);
27
+ const connectionEpoch = useActivityStore((s) => s.connectionEpoch);
28
+ const liveSpans = useActivityStore((s) => s.spans);
29
+ const setActiveView = useUIStore((s) => s.setActiveView);
30
+ const setActiveSession = useChatStore((s) => s.setActiveSession);
31
+ const [runs, setRuns] = useState(null);
32
+ const [rollups, setRollups] = useState(null);
33
+ const [error, setError] = useState(null);
34
+ const [detailRunId, setDetailRunId] = useState(null);
35
+ const inbox = useActivityStore((s) => s.inbox);
36
+ const loadInbox = useActivityStore((s) => s.loadInbox);
37
+ const acknowledgeIntent = useActivityStore((s) => s.acknowledgeIntent);
38
+ const acknowledgeAllIntents = useActivityStore((s) => s.acknowledgeAllIntents);
39
+ const refresh = () => {
40
+ api
41
+ .activityRuns({ limit: 100 })
42
+ .then(setRuns)
43
+ .catch((err) => setError(err instanceof Error ? err.message : String(err)));
44
+ api.activityRollups(7).then(setRollups).catch(() => { });
45
+ void loadInbox();
46
+ };
47
+ // Re-runs on every reconnect (connectionEpoch): the new socket has no
48
+ // server-side subscriptions, and the REST refresh heals whatever finished
49
+ // while disconnected.
50
+ useEffect(() => {
51
+ refresh();
52
+ if (supported) {
53
+ sendClientMessage({ type: "activity_subscribe", view: "index" });
54
+ return () => {
55
+ sendClientMessage({ type: "activity_unsubscribe", view: "index" });
56
+ };
57
+ }
58
+ return undefined;
59
+ }, [supported, connectionEpoch]);
60
+ // Deep-link consumer: `#/activity/<runId>` (the push notification landing
61
+ // spot — the shell routes it here but leaves the hash intact) opens that
62
+ // run's detail. Opening/closing detail writes the hash back via
63
+ // history.replaceState so the link stays shareable without history spam.
64
+ useEffect(() => {
65
+ const applyHash = () => {
66
+ const match = /^#\/activity\/(.+)$/.exec(window.location.hash);
67
+ if (match)
68
+ setDetailRunId(decodeURIComponent(match[1]));
69
+ };
70
+ applyHash();
71
+ window.addEventListener("hashchange", applyHash);
72
+ return () => window.removeEventListener("hashchange", applyHash);
73
+ }, []);
74
+ function showDetail(runId) {
75
+ setDetailRunId(runId);
76
+ const target = runId ? `#/activity/${encodeURIComponent(runId)}` : "#/activity";
77
+ if (window.location.hash !== target) {
78
+ // window-qualified: `history` is the run list in this scope.
79
+ window.history.replaceState(null, "", target);
80
+ }
81
+ }
82
+ // Live open roots from the stream override/extend the REST snapshot.
83
+ const liveRoots = useMemo(() => {
84
+ const roots = [];
85
+ for (const byId of Object.values(liveSpans)) {
86
+ for (const span of Object.values(byId)) {
87
+ if (!span.parentSpanId && span.outcome === undefined)
88
+ roots.push(span);
89
+ }
90
+ }
91
+ return roots.sort((a, b) => b.startedAt - a.startedAt);
92
+ }, [liveSpans]);
93
+ const liveRunIds = new Set(liveRoots.map((r) => r.runId));
94
+ const restLive = (runs?.live ?? []).filter((r) => !liveRunIds.has(r.runId));
95
+ const history = (runs?.history ?? []).filter((r) => !liveRunIds.has(r.runId));
96
+ function openRun(row) {
97
+ if (row.origin === "session" && row.sessionId) {
98
+ // Chat is the residence — a session run opens its session.
99
+ setActiveSession(row.sessionId);
100
+ setActiveView("chat");
101
+ return;
102
+ }
103
+ showDetail(row.runId);
104
+ }
105
+ /** An inbox tap routes like any run row: chat for session runs, detail otherwise. */
106
+ function openIntent(intent) {
107
+ const liveRoot = liveRoots.find((r) => r.runId === intent.runId);
108
+ if (liveRoot) {
109
+ openRun({ runId: liveRoot.runId, origin: liveRoot.origin, sessionId: liveRoot.sessionId });
110
+ return;
111
+ }
112
+ const known = [...(runs?.live ?? []), ...(runs?.history ?? [])].find((r) => r.runId === intent.runId);
113
+ if (known) {
114
+ openRun(known);
115
+ }
116
+ else {
117
+ showDetail(intent.runId);
118
+ }
119
+ }
120
+ if (detailRunId) {
121
+ return _jsx(RunDetail, { runId: detailRunId, onBack: () => showDetail(null) });
122
+ }
123
+ return (_jsxs("div", { className: "flex h-full flex-col overflow-y-auto", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-border-subtle px-4 py-3", children: [_jsx(ActivityIcon, { className: "h-4 w-4 text-muted-foreground" }), _jsx("h1", { className: "text-sm font-medium", children: "Activity" }), _jsx("div", { className: "ml-auto flex items-center gap-2", children: _jsx(PushToggle, {}) }), _jsx("button", { type: "button", onClick: refresh, className: "rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-surface-raised hover:text-foreground", "aria-label": "Refresh", children: _jsx(RefreshCw, { className: "h-3.5 w-3.5" }) })] }), _jsxs("div", { className: "mx-auto w-full max-w-3xl space-y-6 p-4", children: [error && (_jsxs("p", { className: "text-xs text-destructive", children: ["Could not load activity: ", error] })), inbox.length > 0 && (_jsxs("section", { children: [_jsxs("div", { className: "mb-2 flex items-center", children: [_jsx("h2", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "Needs attention" }), _jsx("button", { type: "button", onClick: () => void acknowledgeAllIntents(), className: "ml-auto text-[11px] text-muted-foreground transition-colors hover:text-foreground", children: "Dismiss all" })] }), _jsx("div", { className: "space-y-1", children: inbox.map((intent) => (_jsxs("div", { className: cn("flex items-center gap-2 rounded-lg border px-3 py-2 text-xs", intent.kind === "failure"
124
+ ? "border-destructive/30 bg-destructive/5"
125
+ : "border-border-subtle bg-surface"), children: [intent.kind === "failure" ? (_jsx(AlertTriangle, { className: "h-3.5 w-3.5 shrink-0 text-destructive" })) : intent.kind === "stuck" ? (_jsx(Timer, { className: "h-3.5 w-3.5 shrink-0 text-amber-500" })) : (_jsx(ActivityIcon, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })), _jsx("button", { type: "button", className: "min-w-0 flex-1 truncate text-left hover:underline", onClick: () => {
126
+ void acknowledgeIntent(intent.id);
127
+ openIntent(intent);
128
+ }, children: intent.title }), _jsx("span", { className: "shrink-0 text-[10px] text-muted-foreground/60", children: formatRelativeTime(intent.createdAt) }), _jsx("button", { type: "button", onClick: () => void acknowledgeIntent(intent.id), className: "shrink-0 rounded p-1 text-muted-foreground transition-colors hover:text-foreground", "aria-label": "Dismiss", children: "\u00D7" })] }, intent.id))) })] })), rollups && _jsx(RollupCards, { rollups: rollups }), _jsxs("section", { children: [_jsx("h2", { className: "mb-2 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "Running now" }), liveRoots.length === 0 && restLive.length === 0 ? (_jsx("p", { className: "text-xs text-muted-foreground/70", children: "Nothing is running." })) : (_jsxs("div", { className: "space-y-1", children: [liveRoots.map((span) => (_jsx(LiveRow, { span: span, onOpen: openRun }, span.runId))), restLive.map((run) => (_jsx(RunRow, { run: run, onOpen: openRun }, run.runId)))] }))] }), _jsxs("section", { children: [_jsx("h2", { className: "mb-2 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "History" }), history.length === 0 ? (_jsx("p", { className: "text-xs text-muted-foreground/70", children: "No recorded runs yet." })) : (_jsx("div", { className: "space-y-1", children: history.map((run) => (_jsx(RunRow, { run: run, onOpen: openRun }, run.runId))) }))] })] })] }));
129
+ }
130
+ /** Today's key in the server's configured zone (mirrors its day formatter). */
131
+ function todayKey(timeZone) {
132
+ let fmt;
133
+ try {
134
+ fmt = new Intl.DateTimeFormat("en-CA", { timeZone, dateStyle: "short" });
135
+ }
136
+ catch {
137
+ fmt = new Intl.DateTimeFormat("en-CA", { timeZone: "UTC", dateStyle: "short" });
138
+ }
139
+ return fmt.format(new Date());
140
+ }
141
+ function RollupCards({ rollups }) {
142
+ // days[0] is merely the newest day WITH runs — on a quiet day that is
143
+ // yesterday, so look today up by its actual key (0 when absent).
144
+ const today = rollups.days.find((d) => d.day === todayKey(rollups.timeZone));
145
+ const week = rollups.days.reduce((acc, d) => ({
146
+ runs: acc.runs + d.runs,
147
+ failures: acc.failures + d.failures,
148
+ costUsd: acc.costUsd + d.costUsd,
149
+ tokens: acc.tokens + d.inputTokens + d.outputTokens,
150
+ }), { runs: 0, failures: 0, costUsd: 0, tokens: 0 });
151
+ return (_jsxs("div", { className: "grid grid-cols-2 gap-2 sm:grid-cols-4", children: [_jsx(StatCard, { label: "Runs today", value: String(today?.runs ?? 0) }), _jsx(StatCard, { label: "Failures (7d)", value: String(week.failures), alert: week.failures > 0 }), _jsx(StatCard, { label: "Spend (7d)", value: `$${week.costUsd.toFixed(2)}` }), _jsx(StatCard, { label: "Tokens (7d)", value: formatTokenCount(week.tokens) })] }));
152
+ }
153
+ function StatCard({ label, value, alert }) {
154
+ return (_jsxs("div", { className: "rounded-lg border border-border-subtle bg-surface p-3", children: [_jsx("div", { className: cn("text-lg font-semibold", alert && "text-destructive"), children: value }), _jsx("div", { className: "text-[11px] text-muted-foreground", children: label })] }));
155
+ }
156
+ function LiveRow({ span, onOpen, }) {
157
+ const children = useActivityStore(useShallow((s) => Object.values(s.spans[span.runId] ?? {}).filter((x) => x.parentSpanId)));
158
+ const now = useNow();
159
+ const current = children.filter((c) => c.outcome === undefined).at(-1);
160
+ const currentLabel = current ? spanToolLabel(current) : null;
161
+ return (_jsxs("button", { type: "button", onClick: () => onOpen({ runId: span.runId, origin: span.origin, sessionId: span.sessionId }), className: "flex w-full items-center gap-2 rounded-lg border border-border-subtle bg-surface px-3 py-2 text-left text-xs transition-colors hover:bg-surface-raised", children: [_jsx("span", { className: "h-2 w-2 shrink-0 animate-pulse rounded-full bg-primary" }), span.origin === "cron" ? (_jsx(Clock, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })) : (_jsx(Bot, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })), _jsx("span", { className: "truncate font-medium", children: span.jobName ?? span.name }), currentLabel && (_jsxs("span", { className: "truncate text-muted-foreground", children: ["\u00B7 ", currentLabel] })), _jsx("span", { className: "ml-auto shrink-0 font-[family-name:var(--font-mono)] text-[10px] text-muted-foreground/60", children: formatDuration(now - span.startedAt) })] }));
162
+ }
163
+ function RunRow({ run, onOpen, }) {
164
+ const failed = isFailureOutcome(run.outcome);
165
+ return (_jsxs("button", { type: "button", onClick: () => onOpen(run), className: cn("flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-xs transition-colors hover:bg-surface-raised", failed && "border border-destructive/30 bg-destructive/5"), children: [run.origin === "cron" ? (_jsx(Clock, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })) : (_jsx(Bot, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })), _jsx("span", { className: "truncate", children: run.jobName ?? run.name }), failed && _jsx(AlertTriangle, { className: "h-3 w-3 shrink-0 text-destructive" }), run.outcome && run.outcome !== "success" && (_jsx("span", { className: cn("text-[10px] uppercase", failed ? "text-destructive" : "text-muted-foreground"), children: run.outcome })), _jsxs("span", { className: "ml-auto flex shrink-0 items-center gap-2 font-[family-name:var(--font-mono)] text-[10px] text-muted-foreground/60", children: [run.costUsd !== null && run.costUsd > 0 && _jsxs("span", { children: ["$", run.costUsd.toFixed(2)] }), run.durationMs !== null && (_jsxs("span", { className: "flex items-center gap-0.5", children: [_jsx(Timer, { className: "h-3 w-3" }), formatDuration(run.durationMs)] })), _jsx("span", { children: formatRelativeTime(run.startedAt) })] })] }));
166
+ }
167
+ /** Chat-less run detail (cron runs; pruned runs show their rollup). */
168
+ function RunDetail({ runId, onBack }) {
169
+ const streamed = useActivityStore(useShallow((s) => runSpans(s, runId)));
170
+ const applySnapshot = useActivityStore((s) => s.applySnapshot);
171
+ const [pruned, setPruned] = useState(null);
172
+ const [missing, setMissing] = useState(false);
173
+ useEffect(() => {
174
+ api
175
+ .activityRun(runId)
176
+ .then((detail) => {
177
+ if (detail.detailPruned) {
178
+ setPruned(detail.rollup ?? {});
179
+ }
180
+ else if (detail.spans) {
181
+ applySnapshot({
182
+ type: "activity_snapshot",
183
+ view: "run",
184
+ runId,
185
+ spans: detail.spans,
186
+ events: detail.events ?? [],
187
+ highWaterSeq: { [runId]: detail.highWaterSeq ?? 0 },
188
+ });
189
+ }
190
+ })
191
+ .catch(() => setMissing(true));
192
+ }, [runId, applySnapshot]);
193
+ return (_jsxs("div", { className: "flex h-full flex-col overflow-y-auto", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-border-subtle px-4 py-3", children: [_jsx("button", { type: "button", onClick: onBack, className: "rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-surface-raised hover:text-foreground", "aria-label": "Back", children: _jsx(ArrowLeft, { className: "h-4 w-4" }) }), _jsx("h1", { className: "truncate text-sm font-medium", children: runId })] }), _jsxs("div", { className: "mx-auto w-full max-w-3xl space-y-1 p-4", children: [missing && _jsx("p", { className: "text-xs text-muted-foreground", children: "Unknown run." }), pruned && (_jsxs("div", { className: "rounded-lg border border-border-subtle bg-surface p-3 text-xs text-muted-foreground", children: ["Detail pruned \u2014 only the rollup remains.", _jsx("pre", { className: "mt-2 overflow-x-auto text-[11px]", children: JSON.stringify(pruned, null, 2) })] })), streamed.map((span) => (_jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", style: { paddingLeft: `${depthOf(span, streamed) * 16}px` }, children: [_jsx(SpanStatusDot, { span: span }), _jsx("span", { className: "truncate font-[family-name:var(--font-mono)]", children: spanToolLabel(span) }), span.outcome && span.outcome !== "success" && (_jsx("span", { className: "text-[10px] uppercase", children: span.outcome })), span.outcomeReason && (_jsx("span", { className: "truncate text-[10px] text-muted-foreground/60", children: span.outcomeReason })), _jsx("span", { className: "ml-auto shrink-0 font-[family-name:var(--font-mono)] text-[10px] text-muted-foreground/50", children: span.endedAt !== undefined
194
+ ? formatDuration(span.endedAt - span.startedAt)
195
+ : "…" })] }, span.spanId)))] })] }));
196
+ }
197
+ function depthOf(span, all) {
198
+ let depth = 0;
199
+ let current = span;
200
+ while (current?.parentSpanId) {
201
+ depth += 1;
202
+ current = all.find((s) => s.spanId === current.parentSpanId);
203
+ if (depth > 6)
204
+ break;
205
+ }
206
+ return depth;
207
+ }
208
+ //# sourceMappingURL=activity-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-page.js","sourceRoot":"","sources":["../../../src/components/activity/activity-page.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The while-you-were-away card: presented PROACTIVELY on app open when a
3
+ * fresh digest exists (planning decision — built passively, the flow
4
+ * collapses back into asking the agent what happened). Once per digest:
5
+ * dismissing persists server-side, so a phone and a laptop don't each nag.
6
+ * An empty window stays quiet — no card for "nothing happened". The window
7
+ * is labeled: the card says what period it covers, never implies "now".
8
+ */
9
+ export declare function DigestCard(): import("react").JSX.Element | null;
10
+ //# sourceMappingURL=digest-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest-card.d.ts","sourceRoot":"","sources":["../../../src/components/activity/digest-card.tsx"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AACH,wBAAgB,UAAU,uCAiFzB"}
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { AlertTriangle, Newspaper, X } from "lucide-react";
4
+ import { api } from "../../lib/api-client.js";
5
+ import { useUIStore } from "../../stores/ui-store.js";
6
+ import { cn } from "../../lib/utils.js";
7
+ /**
8
+ * The while-you-were-away card: presented PROACTIVELY on app open when a
9
+ * fresh digest exists (planning decision — built passively, the flow
10
+ * collapses back into asking the agent what happened). Once per digest:
11
+ * dismissing persists server-side, so a phone and a laptop don't each nag.
12
+ * An empty window stays quiet — no card for "nothing happened". The window
13
+ * is labeled: the card says what period it covers, never implies "now".
14
+ */
15
+ export function DigestCard() {
16
+ const [digest, setDigest] = useState(null);
17
+ const [visible, setVisible] = useState(false);
18
+ const setActiveView = useUIStore((s) => s.setActiveView);
19
+ useEffect(() => {
20
+ void api
21
+ .activityDigest()
22
+ .then(({ digest, dismissedAt }) => {
23
+ if (!digest || digest.runs === 0)
24
+ return;
25
+ if (digest.generatedAt <= dismissedAt)
26
+ return;
27
+ setDigest(digest);
28
+ setVisible(true);
29
+ })
30
+ .catch(() => {
31
+ // No digest is a quiet state, never an error surface.
32
+ });
33
+ }, []);
34
+ if (!visible || !digest)
35
+ return null;
36
+ function dismiss() {
37
+ setVisible(false);
38
+ void api.activityDigestDismiss().catch(() => { });
39
+ }
40
+ const windowLabel = `${formatDay(digest.windowStart)} – ${formatDay(digest.windowEnd)}`;
41
+ return (_jsxs("div", { className: cn("mx-auto mb-3 w-full max-w-2xl rounded-xl border p-3 text-xs", digest.failures > 0
42
+ ? "border-destructive/30 bg-destructive/5"
43
+ : "border-border-subtle bg-surface"), children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Newspaper, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsx("span", { className: "font-medium", children: "While you were away" }), _jsx("span", { className: "text-[10px] text-muted-foreground/60", children: windowLabel }), _jsx("button", { type: "button", onClick: dismiss, className: "ml-auto rounded p-1 text-muted-foreground transition-colors hover:text-foreground", "aria-label": "Dismiss", children: _jsx(X, { className: "h-3.5 w-3.5" }) })] }), _jsxs("div", { className: "mt-1.5 text-muted-foreground", children: [digest.runs, " run", digest.runs === 1 ? "" : "s", digest.failures > 0 && (_jsxs("span", { className: "text-destructive", children: [" \u00B7 ", digest.failures, " failed"] })), digest.costUsd > 0 && ` · $${digest.costUsd.toFixed(2)} spent`] }), digest.notable.length > 0 && (_jsx("div", { className: "mt-1.5 space-y-0.5", children: digest.notable.slice(0, 3).map((n) => (_jsxs("div", { className: "flex items-center gap-1.5 text-[11px]", children: [_jsx(AlertTriangle, { className: "h-3 w-3 shrink-0 text-destructive" }), _jsxs("span", { className: "truncate", children: [n.jobName ?? n.name, " \u2014 ", n.outcome] })] }, n.runId))) })), _jsx("button", { type: "button", onClick: () => {
44
+ dismiss();
45
+ setActiveView("activity");
46
+ }, className: "mt-2 text-[11px] font-medium text-primary hover:underline", children: "Open Activity" })] }));
47
+ }
48
+ function formatDay(ms) {
49
+ return new Date(ms).toLocaleDateString(undefined, { month: "short", day: "numeric" });
50
+ }
51
+ //# sourceMappingURL=digest-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest-card.js","sourceRoot":"","sources":["../../../src/components/activity/digest-card.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function PushToggle(): import("react").JSX.Element;
2
+ //# sourceMappingURL=push-toggle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-toggle.d.ts","sourceRoot":"","sources":["../../../src/components/activity/push-toggle.tsx"],"names":[],"mappings":"AAsBA,wBAAgB,UAAU,gCAyGzB"}
@@ -0,0 +1,82 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { Bell, BellOff } from "lucide-react";
4
+ import { api } from "../../lib/api-client.js";
5
+ import { cn } from "../../lib/utils.js";
6
+ export function PushToggle() {
7
+ const [state, setState] = useState("unsupported");
8
+ const [busy, setBusy] = useState(false);
9
+ useEffect(() => {
10
+ void (async () => {
11
+ if (!("Notification" in window) || !("serviceWorker" in navigator) || !("PushManager" in window)) {
12
+ setState("unsupported");
13
+ return;
14
+ }
15
+ if (Notification.permission === "denied") {
16
+ setState("blocked");
17
+ return;
18
+ }
19
+ if (Notification.permission === "default") {
20
+ setState("not-asked");
21
+ return;
22
+ }
23
+ const registration = await navigator.serviceWorker.ready;
24
+ const subscription = await registration.pushManager.getSubscription();
25
+ setState(subscription ? "subscribed" : "unsubscribed");
26
+ })();
27
+ }, []);
28
+ async function enable() {
29
+ setBusy(true);
30
+ try {
31
+ const permission = await Notification.requestPermission();
32
+ if (permission === "denied") {
33
+ setState("blocked");
34
+ return;
35
+ }
36
+ if (permission !== "granted") {
37
+ setState("not-asked");
38
+ return;
39
+ }
40
+ const { publicKey } = await api.pushPublicKey();
41
+ const registration = await navigator.serviceWorker.ready;
42
+ const subscription = await registration.pushManager.subscribe({
43
+ userVisibleOnly: true,
44
+ applicationServerKey: publicKey,
45
+ });
46
+ await api.pushSubscribe(subscription.toJSON(), navigator.userAgent.slice(0, 100));
47
+ setState("subscribed");
48
+ }
49
+ catch {
50
+ setState("unsubscribed");
51
+ }
52
+ finally {
53
+ setBusy(false);
54
+ }
55
+ }
56
+ async function disable() {
57
+ setBusy(true);
58
+ try {
59
+ const registration = await navigator.serviceWorker.ready;
60
+ const subscription = await registration.pushManager.getSubscription();
61
+ if (subscription) {
62
+ await api.pushUnsubscribe(subscription.endpoint).catch(() => { });
63
+ await subscription.unsubscribe();
64
+ }
65
+ setState("unsubscribed");
66
+ }
67
+ finally {
68
+ setBusy(false);
69
+ }
70
+ }
71
+ if (state === "unsupported") {
72
+ return (_jsxs("div", { className: "flex items-center gap-1.5 text-[11px] text-muted-foreground/60", title: "This browser has no web push. On iOS, install the app to the home screen (iOS 16.4+).", children: [_jsx(BellOff, { className: "h-3.5 w-3.5" }), "No push here"] }));
73
+ }
74
+ if (state === "blocked") {
75
+ return (_jsxs("div", { className: "flex items-center gap-1.5 text-[11px] text-muted-foreground", title: "Notifications are blocked at the browser level. Allow them in this site's browser settings, then reload.", children: [_jsx(BellOff, { className: "h-3.5 w-3.5 text-destructive" }), "Blocked in browser settings"] }));
76
+ }
77
+ const on = state === "subscribed";
78
+ return (_jsxs("button", { type: "button", disabled: busy, onClick: () => void (on ? disable() : enable()), className: cn("flex items-center gap-1.5 rounded-md px-2 py-1 text-[11px] transition-colors disabled:opacity-50", on
79
+ ? "text-primary hover:bg-surface-raised"
80
+ : "text-muted-foreground hover:bg-surface-raised hover:text-foreground"), title: on ? "Push notifications are on for this device" : "Get a push notification when background work fails", children: [on ? _jsx(Bell, { className: "h-3.5 w-3.5" }) : _jsx(BellOff, { className: "h-3.5 w-3.5" }), on ? "Push on" : "Enable push"] }));
81
+ }
82
+ //# sourceMappingURL=push-toggle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-toggle.js","sourceRoot":"","sources":["../../../src/components/activity/push-toggle.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { ActivitySpan, ActivitySpanOutcome } from "@schlessera/brain-ui-sdk/protocol";
2
+ /**
3
+ * THE status dot for activity spans — one outcome→color mapping so every
4
+ * surface (timeline rows, drill-in, activity index) agrees on what a color
5
+ * means: running pulses primary, success is accent, failures (per
6
+ * `isFailureOutcome`) and denied are destructive, cancelled is muted.
7
+ */
8
+ export declare function SpanStatusDot({ span, outcome, running, className, }: {
9
+ span?: ActivitySpan;
10
+ /** Alternative to `span` when only the outcome is at hand. */
11
+ outcome?: ActivitySpanOutcome | string | null;
12
+ running?: boolean;
13
+ /** Size/position overrides; defaults to h-1.5 w-1.5. */
14
+ className?: string;
15
+ }): import("react").JSX.Element;
16
+ /**
17
+ * Display label for a span. Prefers the server-lifted `toolName`; root spans
18
+ * label by kind (a turn or cron root is not a tool call); the last resort
19
+ * un-parses the `execute_tool` naming convention for spans recorded before
20
+ * the field existed.
21
+ */
22
+ export declare function spanToolLabel(span: ActivitySpan): string;
23
+ /** The "9+" unread-count bubble shared by the rail and the tab bar. Hidden at 0. */
24
+ export declare function CountBadge({ count, className }: {
25
+ count: number;
26
+ className?: string;
27
+ }): import("react").JSX.Element | null;
28
+ //# sourceMappingURL=span-bits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span-bits.d.ts","sourceRoot":"","sources":["../../../src/components/activity/span-bits.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAK3F;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,OAAO,EACP,OAAO,EACP,SAAS,GACV,EAAE;IACD,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAkBA;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAKxD;AAED,oFAAoF;AACpF,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,sCAYrF"}
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { isFailureOutcome } from "@schlessera/brain-ui-sdk/protocol";
3
+ import { cn } from "../../lib/utils.js";
4
+ import { getToolLabel } from "../chat/tool-views.js";
5
+ /**
6
+ * THE status dot for activity spans — one outcome→color mapping so every
7
+ * surface (timeline rows, drill-in, activity index) agrees on what a color
8
+ * means: running pulses primary, success is accent, failures (per
9
+ * `isFailureOutcome`) and denied are destructive, cancelled is muted.
10
+ */
11
+ export function SpanStatusDot({ span, outcome, running, className, }) {
12
+ const resolved = span ? span.outcome : outcome;
13
+ const isRunning = running ?? (span !== undefined && span.outcome === undefined);
14
+ return (_jsx("span", { className: cn("h-1.5 w-1.5 shrink-0 rounded-full", isRunning
15
+ ? "animate-pulse bg-primary"
16
+ : resolved === "success"
17
+ ? "bg-accent"
18
+ : isFailureOutcome(resolved) || resolved === "denied"
19
+ ? "bg-destructive"
20
+ : "bg-muted-foreground", className) }));
21
+ }
22
+ /**
23
+ * Display label for a span. Prefers the server-lifted `toolName`; root spans
24
+ * label by kind (a turn or cron root is not a tool call); the last resort
25
+ * un-parses the `execute_tool` naming convention for spans recorded before
26
+ * the field existed.
27
+ */
28
+ export function spanToolLabel(span) {
29
+ if (span.toolName)
30
+ return getToolLabel(span.toolName);
31
+ if (span.kind === "turn")
32
+ return "Turn";
33
+ if (span.kind === "cron")
34
+ return span.jobName ?? span.name;
35
+ return getToolLabel(span.name.replace(/^execute_tool /, ""));
36
+ }
37
+ /** The "9+" unread-count bubble shared by the rail and the tab bar. Hidden at 0. */
38
+ export function CountBadge({ count, className }) {
39
+ if (count <= 0)
40
+ return null;
41
+ return (_jsx("span", { className: cn("absolute flex h-4 min-w-4 items-center justify-center rounded-full bg-destructive px-1 text-[9px] font-semibold text-white", className), children: count > 9 ? "9+" : count }));
42
+ }
43
+ //# sourceMappingURL=span-bits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span-bits.js","sourceRoot":"","sources":["../../../src/components/activity/span-bits.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAGrE,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,IAAI,EACJ,OAAO,EACP,OAAO,EACP,SAAS,GAQV;IACC,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IAC/C,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC;IAChF,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,mCAAmC,EACnC,SAAS;YACP,CAAC,CAAC,0BAA0B;YAC5B,CAAC,CAAC,QAAQ,KAAK,SAAS;gBACtB,CAAC,CAAC,WAAW;gBACb,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,QAAQ,KAAK,QAAQ;oBACnD,CAAC,CAAC,gBAAgB;oBAClB,CAAC,CAAC,qBAAqB,EAC7B,SAAS,CACV,GACD,CACH,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAAkB;IAC9C,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtD,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC;IACxC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC;IAC3D,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,SAAS,EAAyC;IACpF,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5B,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,4HAA4H,EAC5H,SAAS,CACV,YAEA,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GACpB,CACR,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-page.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-page.tsx"],"names":[],"mappings":"AAuDA,wBAAgB,QAAQ,gCAyzBvB"}
1
+ {"version":3,"file":"chat-page.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-page.tsx"],"names":[],"mappings":"AAyDA,wBAAgB,QAAQ,gCAw0BvB"}
@@ -14,6 +14,8 @@ import { WelcomeState } from "./welcome-state.js";
14
14
  import { ShareIntake } from "./share-card.js";
15
15
  import { CommandPalette } from "./command-palette.js";
16
16
  import { SessionDrawer } from "./session-drawer.js";
17
+ import { SubagentView } from "./subagent-view.js";
18
+ import { DigestCard } from "../activity/digest-card.js";
17
19
  import { SettingsPanel } from "../settings/settings-panel.js";
18
20
  import { StreamingPanel } from "../quick-actions/streaming-modal.js";
19
21
  import { WhatsupPanel } from "../quick-actions/whatsup-modal.js";
@@ -80,6 +82,7 @@ export function ChatPage() {
80
82
  const backends = useProviderStore((s) => s.backends);
81
83
  const sessionPanelOpen = useUIStore((s) => s.sessionPanelOpen);
82
84
  const setSessionPanelOpen = useUIStore((s) => s.setSessionPanelOpen);
85
+ const subagentStack = useUIStore((s) => s.subagentStack);
83
86
  const syncPanelOpen = useUIStore((s) => s.syncPanelOpen);
84
87
  const setSyncPanelOpen = useUIStore((s) => s.setSyncPanelOpen);
85
88
  const whatsupPanelOpen = useUIStore((s) => s.whatsupPanelOpen);
@@ -428,7 +431,7 @@ export function ChatPage() {
428
431
  ? "Follows up live"
429
432
  : "Will queue"
430
433
  : null;
431
- return (_jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [_jsx(MaskEditor, { onSubmit: (requestId, maskPng) => send({ type: "mask_response", requestId, maskPng }), onCancel: (requestId, message) => send({ type: "mask_error", requestId, code: "cancelled", message }) }), _jsx(SessionDrawer, { open: sessionPanelOpen, onClose: () => setSessionPanelOpen(false), onResume: handleSessionResume }), _jsx(SettingsPanel, { open: settingsPanelOpen, onClose: () => setSettingsPanelOpen(false) }), _jsx(StreamingPanel, { open: syncPanelOpen, onClose: () => setSyncPanelOpen(false), title: "Brain Sync", endpoint: getBackendUrl("/api/brain/sync") }), _jsx(WhatsupPanel, { open: whatsupPanelOpen, onClose: () => setWhatsupPanelOpen(false) }), _jsx(SearchPanel, { open: searchPanelOpen, onClose: () => setSearchPanelOpen(false) }), _jsx(AddPanel, { open: addPanelOpen, onClose: () => setAddPanelOpen(false) }), _jsx(FilePanel, { open: filePanelOpen, onClose: () => setFilePanelOpen(false) }), _jsxs("div", { className: "relative flex-1 overflow-hidden", children: [messages.length === 0 ? (_jsx("div", { className: "h-full overflow-y-auto", children: _jsx(WelcomeState, { onAction: handleWelcomeAction }) })) : (_jsx("div", { ref: scrollRef, className: "h-full overflow-y-auto px-4 md:px-6", children: _jsx("div", { [READING_COLUMN_ATTR]: "", className: "mx-auto max-w-3xl divide-y divide-border/20", children: messages.map((msg) => (_jsx(MessageBubble, { message: msg, onToolApproval: handleToolApproval, onAskUserSubmit: handleAskUserSubmit, onAskUserCancel: handleAskUserCancel }, msg.id))) }) })), showScrollButton && (_jsx("button", { type: "button", onClick: scrollToBottom, title: "Scroll to bottom", className: "absolute bottom-4 left-1/2 -translate-x-1/2 flex h-8 w-8 items-center justify-center rounded-full border border-border bg-surface shadow-md text-muted-foreground transition-all duration-150 hover:text-foreground", children: _jsx(ArrowDown, { className: "h-4 w-4" }) }))] }), _jsx(DictationSheet, { open: voiceMode === "dictate", onStop: () => dictation.stop(true), onCancel: () => dictation.cancel() }), _jsx("div", { className: "px-4 pt-2 pb-4 md:px-6 md:pb-6", children: _jsxs("div", { className: "mx-auto max-w-3xl", children: [_jsx(ShareIntake, {}), _jsx(ReviewCard, { text: reviewText, onSend: handleVoiceSend, onEdit: handleVoiceEdit, onDiscard: clearReview, onAppend: handleVoiceAppend }), attachErrors.length > 0 && (_jsxs("div", { className: "mb-2 flex items-start gap-2 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-[11px] text-destructive", children: [_jsx("div", { className: "flex-1 space-y-0.5", children: attachErrors.map((e, i) => (_jsx("div", { children: e }, i))) }), _jsx("button", { type: "button", onClick: () => setAttachErrors([]), title: "Dismiss", className: "shrink-0 rounded p-0.5 transition-colors hover:text-foreground", children: _jsx(X, { className: "h-3.5 w-3.5" }) })] })), attachments.length > 0 && (_jsx("div", { className: "mb-2 flex flex-wrap gap-2", children: attachments.map((a, i) => (_jsxs("div", { className: "relative h-16 w-16 shrink-0", children: [_jsx("img", { src: a.previewUrl, alt: a.name, className: "h-16 w-16 rounded-lg border border-border object-cover" }), _jsx("button", { type: "button", onClick: () => removeAttachment(i), title: "Remove", className: "absolute -right-1.5 -top-1.5 flex h-5 w-5 items-center justify-center rounded-full border border-border bg-surface text-muted-foreground shadow transition-colors hover:text-destructive", children: _jsx(X, { className: "h-3 w-3" }) })] }, i))) })), _jsxs("div", { className: cn("relative rounded-2xl border border-border bg-surface shadow-lg transition-all duration-200", "focus-within:border-primary/40 focus-within:shadow-[0_0_20px_rgba(224,159,62,0.05)]"), children: [showCommandPalette && (_jsx(CommandPalette, { filter: input.slice(1), onSelect: handleCommand })), _jsx("input", { ref: libraryInputRef, type: "file", accept: "image/*", multiple: true, hidden: true, onChange: onFilePick }), _jsx("input", { ref: cameraInputRef, type: "file", accept: "image/*", capture: "environment", hidden: true, onChange: onFilePick }), _jsx("textarea", { ref: textareaRef, value: input, onChange: (e) => setInput(e.target.value), onPaste: (e) => {
434
+ return (_jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [_jsx(MaskEditor, { onSubmit: (requestId, maskPng) => send({ type: "mask_response", requestId, maskPng }), onCancel: (requestId, message) => send({ type: "mask_error", requestId, code: "cancelled", message }) }), subagentStack.length > 0 && (_jsx("div", { className: "fixed inset-0 z-40 bg-background", children: _jsx(SubagentView, { spanId: subagentStack[subagentStack.length - 1], onApproval: handleToolApproval }) })), _jsx(SessionDrawer, { open: sessionPanelOpen, onClose: () => setSessionPanelOpen(false), onResume: handleSessionResume }), _jsx(SettingsPanel, { open: settingsPanelOpen, onClose: () => setSettingsPanelOpen(false) }), _jsx(StreamingPanel, { open: syncPanelOpen, onClose: () => setSyncPanelOpen(false), title: "Brain Sync", endpoint: getBackendUrl("/api/brain/sync") }), _jsx(WhatsupPanel, { open: whatsupPanelOpen, onClose: () => setWhatsupPanelOpen(false) }), _jsx(SearchPanel, { open: searchPanelOpen, onClose: () => setSearchPanelOpen(false) }), _jsx(AddPanel, { open: addPanelOpen, onClose: () => setAddPanelOpen(false) }), _jsx(FilePanel, { open: filePanelOpen, onClose: () => setFilePanelOpen(false) }), _jsxs("div", { className: "relative flex-1 overflow-hidden", children: [messages.length === 0 ? (_jsxs("div", { className: "h-full overflow-y-auto", children: [_jsx("div", { className: "px-4 pt-3 md:px-6", children: _jsx(DigestCard, {}) }), _jsx(WelcomeState, { onAction: handleWelcomeAction })] })) : (_jsx("div", { ref: scrollRef, className: "h-full overflow-y-auto px-4 md:px-6", children: _jsx("div", { [READING_COLUMN_ATTR]: "", className: "mx-auto max-w-3xl divide-y divide-border/20", children: messages.map((msg) => (_jsx(MessageBubble, { message: msg, onToolApproval: handleToolApproval, onAskUserSubmit: handleAskUserSubmit, onAskUserCancel: handleAskUserCancel }, msg.id))) }) })), showScrollButton && (_jsx("button", { type: "button", onClick: scrollToBottom, title: "Scroll to bottom", className: "absolute bottom-4 left-1/2 -translate-x-1/2 flex h-8 w-8 items-center justify-center rounded-full border border-border bg-surface shadow-md text-muted-foreground transition-all duration-150 hover:text-foreground", children: _jsx(ArrowDown, { className: "h-4 w-4" }) }))] }), _jsx(DictationSheet, { open: voiceMode === "dictate", onStop: () => dictation.stop(true), onCancel: () => dictation.cancel() }), _jsx("div", { className: "px-4 pt-2 pb-4 md:px-6 md:pb-6", children: _jsxs("div", { className: "mx-auto max-w-3xl", children: [_jsx(ShareIntake, {}), _jsx(ReviewCard, { text: reviewText, onSend: handleVoiceSend, onEdit: handleVoiceEdit, onDiscard: clearReview, onAppend: handleVoiceAppend }), attachErrors.length > 0 && (_jsxs("div", { className: "mb-2 flex items-start gap-2 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-[11px] text-destructive", children: [_jsx("div", { className: "flex-1 space-y-0.5", children: attachErrors.map((e, i) => (_jsx("div", { children: e }, i))) }), _jsx("button", { type: "button", onClick: () => setAttachErrors([]), title: "Dismiss", className: "shrink-0 rounded p-0.5 transition-colors hover:text-foreground", children: _jsx(X, { className: "h-3.5 w-3.5" }) })] })), attachments.length > 0 && (_jsx("div", { className: "mb-2 flex flex-wrap gap-2", children: attachments.map((a, i) => (_jsxs("div", { className: "relative h-16 w-16 shrink-0", children: [_jsx("img", { src: a.previewUrl, alt: a.name, className: "h-16 w-16 rounded-lg border border-border object-cover" }), _jsx("button", { type: "button", onClick: () => removeAttachment(i), title: "Remove", className: "absolute -right-1.5 -top-1.5 flex h-5 w-5 items-center justify-center rounded-full border border-border bg-surface text-muted-foreground shadow transition-colors hover:text-destructive", children: _jsx(X, { className: "h-3 w-3" }) })] }, i))) })), _jsxs("div", { className: cn("relative rounded-2xl border border-border bg-surface shadow-lg transition-all duration-200", "focus-within:border-primary/40 focus-within:shadow-[0_0_20px_rgba(224,159,62,0.05)]"), children: [showCommandPalette && (_jsx(CommandPalette, { filter: input.slice(1), onSelect: handleCommand })), _jsx("input", { ref: libraryInputRef, type: "file", accept: "image/*", multiple: true, hidden: true, onChange: onFilePick }), _jsx("input", { ref: cameraInputRef, type: "file", accept: "image/*", capture: "environment", hidden: true, onChange: onFilePick }), _jsx("textarea", { ref: textareaRef, value: input, onChange: (e) => setInput(e.target.value), onPaste: (e) => {
432
435
  const files = e.clipboardData?.files;
433
436
  if (files && files.length > 0) {
434
437
  const images = Array.from(files).filter((f) => f.type.startsWith("image/"));