@schlessera/brain-ui-react 0.18.0 → 0.20.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.
- package/dist/components/activity/activity-page.d.ts +11 -0
- package/dist/components/activity/activity-page.d.ts.map +1 -0
- package/dist/components/activity/activity-page.js +243 -0
- package/dist/components/activity/activity-page.js.map +1 -0
- package/dist/components/activity/digest-card.d.ts +10 -0
- package/dist/components/activity/digest-card.d.ts.map +1 -0
- package/dist/components/activity/digest-card.js +55 -0
- package/dist/components/activity/digest-card.js.map +1 -0
- package/dist/components/activity/push-toggle.d.ts +2 -0
- package/dist/components/activity/push-toggle.d.ts.map +1 -0
- package/dist/components/activity/push-toggle.js +121 -0
- package/dist/components/activity/push-toggle.js.map +1 -0
- package/dist/components/activity/span-bits.d.ts +76 -0
- package/dist/components/activity/span-bits.d.ts.map +1 -0
- package/dist/components/activity/span-bits.js +127 -0
- package/dist/components/activity/span-bits.js.map +1 -0
- package/dist/components/chat/chat-page.d.ts.map +1 -1
- package/dist/components/chat/chat-page.js +4 -1
- package/dist/components/chat/chat-page.js.map +1 -1
- package/dist/components/chat/session-drawer.d.ts.map +1 -1
- package/dist/components/chat/session-drawer.js +1 -15
- package/dist/components/chat/session-drawer.js.map +1 -1
- package/dist/components/chat/subagent-view.d.ts +18 -0
- package/dist/components/chat/subagent-view.d.ts.map +1 -0
- package/dist/components/chat/subagent-view.js +83 -0
- package/dist/components/chat/subagent-view.js.map +1 -0
- package/dist/components/chat/tool-call-timeline.d.ts.map +1 -1
- package/dist/components/chat/tool-call-timeline.js +40 -4
- package/dist/components/chat/tool-call-timeline.js.map +1 -1
- package/dist/components/chat/tool-views.d.ts +4 -0
- package/dist/components/chat/tool-views.d.ts.map +1 -1
- package/dist/components/chat/tool-views.js +26 -0
- package/dist/components/chat/tool-views.js.map +1 -1
- package/dist/components/layout/mobile-tab-bar.d.ts.map +1 -1
- package/dist/components/layout/mobile-tab-bar.js +10 -4
- package/dist/components/layout/mobile-tab-bar.js.map +1 -1
- package/dist/components/layout/side-rail.d.ts.map +1 -1
- package/dist/components/layout/side-rail.js +7 -4
- package/dist/components/layout/side-rail.js.map +1 -1
- package/dist/components/settings/models-tab.d.ts +15 -0
- package/dist/components/settings/models-tab.d.ts.map +1 -1
- package/dist/components/settings/models-tab.js +100 -21
- package/dist/components/settings/models-tab.js.map +1 -1
- package/dist/hooks/use-now.d.ts +8 -0
- package/dist/hooks/use-now.d.ts.map +1 -0
- package/dist/hooks/use-now.js +32 -0
- package/dist/hooks/use-now.js.map +1 -0
- package/dist/hooks/use-websocket.d.ts.map +1 -1
- package/dist/hooks/use-websocket.js +46 -0
- package/dist/hooks/use-websocket.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/api-client.d.ts +67 -1
- package/dist/lib/api-client.d.ts.map +1 -1
- package/dist/lib/api-client.js +41 -0
- package/dist/lib/api-client.js.map +1 -1
- package/dist/stores/activity-store.d.ts +108 -0
- package/dist/stores/activity-store.d.ts.map +1 -0
- package/dist/stores/activity-store.js +359 -0
- package/dist/stores/activity-store.js.map +1 -0
- package/dist/stores/ui-store.d.ts +9 -1
- package/dist/stores/ui-store.d.ts.map +1 -1
- package/dist/stores/ui-store.js +3 -0
- package/dist/stores/ui-store.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
- package/src/components/activity/activity-page.tsx +623 -0
- package/src/components/activity/digest-card.tsx +105 -0
- package/src/components/activity/push-toggle.tsx +157 -0
- package/src/components/activity/span-bits.tsx +194 -0
- package/src/components/chat/chat-page.tsx +17 -0
- package/src/components/chat/session-drawer.tsx +1 -12
- package/src/components/chat/subagent-view.tsx +239 -0
- package/src/components/chat/tool-call-timeline.tsx +61 -3
- package/src/components/chat/tool-views.tsx +22 -0
- package/src/components/layout/mobile-tab-bar.tsx +25 -5
- package/src/components/layout/side-rail.tsx +17 -0
- package/src/components/settings/models-tab.tsx +135 -21
- package/src/hooks/use-now.ts +32 -0
- package/src/hooks/use-websocket.ts +44 -0
- package/src/index.ts +1 -0
- package/src/lib/api-client.ts +111 -0
- package/src/stores/activity-store.ts +451 -0
- 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":"AA4CA;;;;;;;;GAQG;AACH,wBAAgB,YAAY,gCAsQ3B"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useState } from "react";
|
|
3
|
+
import { Activity as ActivityIcon, AlertTriangle, ArrowLeft, Bot, ChevronRight, 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 { SpanPayload, SpanStatusDot, formatAggregateCost, formatEffectiveCost, runCostText, spanToolLabel, } from "./span-bits.js";
|
|
15
|
+
import { PushToggle } from "./push-toggle.js";
|
|
16
|
+
import { SettingsPanel } from "../settings/settings-panel.js";
|
|
17
|
+
/**
|
|
18
|
+
* The Activity surface: an INDEX of all agent activity — live runs first,
|
|
19
|
+
* then history — with cost/token rollups. Deliberately not a residence:
|
|
20
|
+
* a session run deep-links back into its chat, a subagent into the drill-in
|
|
21
|
+
* stack; only a cron run (which has no chat around it) details here.
|
|
22
|
+
*
|
|
23
|
+
* Live rows ride the index-view activity subscription while this surface is
|
|
24
|
+
* open; history and rollups come from the REST activity API.
|
|
25
|
+
*/
|
|
26
|
+
export function ActivityPage() {
|
|
27
|
+
const supported = useActivityStore((s) => s.supported);
|
|
28
|
+
const connectionEpoch = useActivityStore((s) => s.connectionEpoch);
|
|
29
|
+
const liveSpans = useActivityStore((s) => s.spans);
|
|
30
|
+
const setActiveView = useUIStore((s) => s.setActiveView);
|
|
31
|
+
const openSettings = useUIStore((s) => s.openSettings);
|
|
32
|
+
const settingsPanelOpen = useUIStore((s) => s.settingsPanelOpen);
|
|
33
|
+
const setSettingsPanelOpen = useUIStore((s) => s.setSettingsPanelOpen);
|
|
34
|
+
const setActiveSession = useChatStore((s) => s.setActiveSession);
|
|
35
|
+
const [runs, setRuns] = useState(null);
|
|
36
|
+
const [rollups, setRollups] = useState(null);
|
|
37
|
+
const [error, setError] = useState(null);
|
|
38
|
+
const [detailRunId, setDetailRunId] = useState(null);
|
|
39
|
+
const [pricingStale, setPricingStale] = useState(false);
|
|
40
|
+
const inbox = useActivityStore((s) => s.inbox);
|
|
41
|
+
const loadInbox = useActivityStore((s) => s.loadInbox);
|
|
42
|
+
const acknowledgeIntent = useActivityStore((s) => s.acknowledgeIntent);
|
|
43
|
+
const acknowledgeAllIntents = useActivityStore((s) => s.acknowledgeAllIntents);
|
|
44
|
+
const refresh = () => {
|
|
45
|
+
api
|
|
46
|
+
.activityRuns({ limit: 100 })
|
|
47
|
+
.then(setRuns)
|
|
48
|
+
.catch((err) => setError(err instanceof Error ? err.message : String(err)));
|
|
49
|
+
api.activityRollups(7).then(setRollups).catch(() => { });
|
|
50
|
+
// Surface the pricing warning only when the table is stale AND refreshes
|
|
51
|
+
// are failing — a merely-aging table heals itself. A rejection (including
|
|
52
|
+
// 404 from a server that predates the route) means no signal: stay quiet.
|
|
53
|
+
api
|
|
54
|
+
.pricingState()
|
|
55
|
+
.then((s) => setPricingStale(Boolean(s.stale && s.error)))
|
|
56
|
+
.catch(() => setPricingStale(false));
|
|
57
|
+
void loadInbox();
|
|
58
|
+
};
|
|
59
|
+
// Re-runs on every reconnect (connectionEpoch): the new socket has no
|
|
60
|
+
// server-side subscriptions, and the REST refresh heals whatever finished
|
|
61
|
+
// while disconnected.
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
refresh();
|
|
64
|
+
if (supported) {
|
|
65
|
+
sendClientMessage({ type: "activity_subscribe", view: "index" });
|
|
66
|
+
return () => {
|
|
67
|
+
sendClientMessage({ type: "activity_unsubscribe", view: "index" });
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}, [supported, connectionEpoch]);
|
|
72
|
+
// Deep-link consumer: `#/activity/<runId>` (the push notification landing
|
|
73
|
+
// spot — the shell routes it here but leaves the hash intact) opens that
|
|
74
|
+
// run's detail. Opening/closing detail writes the hash back via
|
|
75
|
+
// history.replaceState so the link stays shareable without history spam.
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
const applyHash = () => {
|
|
78
|
+
const match = /^#\/activity\/(.+)$/.exec(window.location.hash);
|
|
79
|
+
if (match)
|
|
80
|
+
setDetailRunId(decodeURIComponent(match[1]));
|
|
81
|
+
};
|
|
82
|
+
applyHash();
|
|
83
|
+
window.addEventListener("hashchange", applyHash);
|
|
84
|
+
return () => window.removeEventListener("hashchange", applyHash);
|
|
85
|
+
}, []);
|
|
86
|
+
function showDetail(runId) {
|
|
87
|
+
setDetailRunId(runId);
|
|
88
|
+
const target = runId ? `#/activity/${encodeURIComponent(runId)}` : "#/activity";
|
|
89
|
+
if (window.location.hash !== target) {
|
|
90
|
+
// window-qualified: `history` is the run list in this scope.
|
|
91
|
+
window.history.replaceState(null, "", target);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Live open roots from the stream override/extend the REST snapshot.
|
|
95
|
+
const liveRoots = useMemo(() => {
|
|
96
|
+
const roots = [];
|
|
97
|
+
for (const byId of Object.values(liveSpans)) {
|
|
98
|
+
for (const span of Object.values(byId)) {
|
|
99
|
+
if (!span.parentSpanId && span.outcome === undefined)
|
|
100
|
+
roots.push(span);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return roots.sort((a, b) => b.startedAt - a.startedAt);
|
|
104
|
+
}, [liveSpans]);
|
|
105
|
+
const liveRunIds = new Set(liveRoots.map((r) => r.runId));
|
|
106
|
+
const restLive = (runs?.live ?? []).filter((r) => !liveRunIds.has(r.runId));
|
|
107
|
+
const history = (runs?.history ?? []).filter((r) => !liveRunIds.has(r.runId));
|
|
108
|
+
function openRun(row) {
|
|
109
|
+
if (row.origin === "session" && row.sessionId) {
|
|
110
|
+
// Chat is the residence — a session run opens its session.
|
|
111
|
+
setActiveSession(row.sessionId);
|
|
112
|
+
setActiveView("chat");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
showDetail(row.runId);
|
|
116
|
+
}
|
|
117
|
+
/** An inbox tap routes like any run row: chat for session runs, detail otherwise. */
|
|
118
|
+
function openIntent(intent) {
|
|
119
|
+
const liveRoot = liveRoots.find((r) => r.runId === intent.runId);
|
|
120
|
+
if (liveRoot) {
|
|
121
|
+
openRun({ runId: liveRoot.runId, origin: liveRoot.origin, sessionId: liveRoot.sessionId });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const known = [...(runs?.live ?? []), ...(runs?.history ?? [])].find((r) => r.runId === intent.runId);
|
|
125
|
+
if (known) {
|
|
126
|
+
openRun(known);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
showDetail(intent.runId);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (detailRunId) {
|
|
133
|
+
return _jsx(RunDetail, { runId: detailRunId, onBack: () => showDetail(null) });
|
|
134
|
+
}
|
|
135
|
+
return (_jsxs("div", { className: "flex h-full flex-col overflow-y-auto", children: [_jsx(SettingsPanel, { open: settingsPanelOpen, onClose: () => setSettingsPanelOpen(false) }), _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" }), _jsxs("div", { className: "ml-auto flex items-center gap-2", children: [pricingStale && (_jsxs("button", { type: "button", onClick: () => openSettings("models"), className: "flex items-center gap-1 rounded-md p-1.5 text-amber-500 transition-colors hover:bg-surface-raised hover:text-amber-400", "aria-label": "Pricing refresh is failing \u2014 costs may use stale rates. Open Settings", title: "Pricing refresh is failing \u2014 costs may use stale rates. Open Settings", children: [_jsx(AlertTriangle, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "hidden text-[10px] sm:inline", children: "Pricing stale" })] })), _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"
|
|
136
|
+
? "border-destructive/30 bg-destructive/5"
|
|
137
|
+
: "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: () => {
|
|
138
|
+
void acknowledgeIntent(intent.id);
|
|
139
|
+
openIntent(intent);
|
|
140
|
+
}, 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))) }))] })] })] }));
|
|
141
|
+
}
|
|
142
|
+
/** Today's key in the server's configured zone (mirrors its day formatter). */
|
|
143
|
+
function todayKey(timeZone) {
|
|
144
|
+
let fmt;
|
|
145
|
+
try {
|
|
146
|
+
fmt = new Intl.DateTimeFormat("en-CA", { timeZone, dateStyle: "short" });
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
fmt = new Intl.DateTimeFormat("en-CA", { timeZone: "UTC", dateStyle: "short" });
|
|
150
|
+
}
|
|
151
|
+
return fmt.format(new Date());
|
|
152
|
+
}
|
|
153
|
+
function RollupCards({ rollups }) {
|
|
154
|
+
// days[0] is merely the newest day WITH runs — on a quiet day that is
|
|
155
|
+
// yesterday, so look today up by its actual key (0 when absent).
|
|
156
|
+
const today = rollups.days.find((d) => d.day === todayKey(rollups.timeZone));
|
|
157
|
+
const week = rollups.days.reduce((acc, d) => ({
|
|
158
|
+
runs: acc.runs + d.runs,
|
|
159
|
+
failures: acc.failures + d.failures,
|
|
160
|
+
costUsd: acc.costUsd + d.costUsd,
|
|
161
|
+
effectiveCostUsd: acc.effectiveCostUsd + (d.effectiveCostUsd ?? 0),
|
|
162
|
+
unpricedRuns: acc.unpricedRuns + (d.unpricedRuns ?? 0),
|
|
163
|
+
tokens: acc.tokens + d.inputTokens + d.outputTokens,
|
|
164
|
+
}), { runs: 0, failures: 0, costUsd: 0, effectiveCostUsd: 0, unpricedRuns: 0, tokens: 0 });
|
|
165
|
+
// A server that predates pricing omits the effective fields entirely; the
|
|
166
|
+
// card then keeps its single list-price number instead of claiming an
|
|
167
|
+
// effective $0.00 it never computed.
|
|
168
|
+
const hasEffective = rollups.days.some((d) => d.effectiveCostUsd !== undefined);
|
|
169
|
+
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: hasEffective
|
|
170
|
+
? formatAggregateCost(week.effectiveCostUsd, week.unpricedRuns)
|
|
171
|
+
: `$${week.costUsd.toFixed(2)}`, secondary: hasEffective && (_jsxs(_Fragment, { children: ["list $", week.costUsd.toFixed(2), week.unpricedRuns > 0 && (_jsxs(_Fragment, { children: [_jsxs("span", { className: "hidden sm:inline", children: [" \u00B7 ", week.unpricedRuns, " unpriced"] }), _jsxs("span", { className: "sm:hidden", children: [" \u00B7 ", week.unpricedRuns, "?"] })] }))] })) }), _jsx(StatCard, { label: "Tokens (7d)", value: formatTokenCount(week.tokens) })] }));
|
|
172
|
+
}
|
|
173
|
+
function StatCard({ label, value, secondary, alert, }) {
|
|
174
|
+
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 }), secondary && (_jsx("div", { className: "truncate text-[10px] text-muted-foreground/70", children: secondary })), _jsx("div", { className: "text-[11px] text-muted-foreground", children: label })] }));
|
|
175
|
+
}
|
|
176
|
+
function LiveRow({ span, onOpen, }) {
|
|
177
|
+
const children = useActivityStore(useShallow((s) => Object.values(s.spans[span.runId] ?? {}).filter((x) => x.parentSpanId)));
|
|
178
|
+
const now = useNow();
|
|
179
|
+
const current = children.filter((c) => c.outcome === undefined).at(-1);
|
|
180
|
+
const currentLabel = current ? spanToolLabel(current) : null;
|
|
181
|
+
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) })] }));
|
|
182
|
+
}
|
|
183
|
+
function RunRow({ run, onOpen, }) {
|
|
184
|
+
const failed = isFailureOutcome(run.outcome);
|
|
185
|
+
// Effective cost only — list price lives on the Spend card and the detail
|
|
186
|
+
// view. "—" is unknown, never $0.00 (AE3); a pre-pricing server that never
|
|
187
|
+
// sent the field keeps the original list-cost span instead (see runCostText).
|
|
188
|
+
const cost = runCostText(run);
|
|
189
|
+
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: [cost !== null && _jsx("span", { children: cost }), 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) })] })] }));
|
|
190
|
+
}
|
|
191
|
+
/** Chat-less run detail (cron runs; pruned runs show their rollup). */
|
|
192
|
+
function RunDetail({ runId, onBack }) {
|
|
193
|
+
const streamed = useActivityStore(useShallow((s) => runSpans(s, runId)));
|
|
194
|
+
const applySnapshot = useActivityStore((s) => s.applySnapshot);
|
|
195
|
+
const [pruned, setPruned] = useState(null);
|
|
196
|
+
const [rollup, setRollup] = useState(null);
|
|
197
|
+
const [missing, setMissing] = useState(false);
|
|
198
|
+
useEffect(() => {
|
|
199
|
+
api
|
|
200
|
+
// Payload bodies are excluded from run detail by default; this view's
|
|
201
|
+
// rows expand to them, so opt in.
|
|
202
|
+
.activityRun(runId, { includePayloads: true })
|
|
203
|
+
.then((detail) => {
|
|
204
|
+
if (detail.rollup)
|
|
205
|
+
setRollup(detail.rollup);
|
|
206
|
+
if (detail.detailPruned) {
|
|
207
|
+
setPruned(detail.rollup ?? {});
|
|
208
|
+
}
|
|
209
|
+
else if (detail.spans) {
|
|
210
|
+
applySnapshot({
|
|
211
|
+
type: "activity_snapshot",
|
|
212
|
+
view: "run",
|
|
213
|
+
runId,
|
|
214
|
+
spans: detail.spans,
|
|
215
|
+
events: detail.events ?? [],
|
|
216
|
+
highWaterSeq: { [runId]: detail.highWaterSeq ?? 0 },
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
.catch(() => setMissing(true));
|
|
221
|
+
}, [runId, applySnapshot]);
|
|
222
|
+
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." }), rollup && (_jsxs("div", { className: "mb-2 flex flex-wrap items-center gap-x-3 gap-y-0.5 rounded-lg border border-border-subtle bg-surface px-3 py-2 text-[11px] text-muted-foreground", children: [_jsxs("span", { children: ["list", " ", _jsx("span", { className: "font-[family-name:var(--font-mono)] text-foreground/80", children: formatEffectiveCost(rollup.costUsd) })] }), _jsxs("span", { children: ["effective", " ", _jsx("span", { className: "font-[family-name:var(--font-mono)] text-foreground/80", children: formatEffectiveCost(rollup.effectiveCostUsd, rollup.pricingEstimate) })] }), rollup.billingMode && (_jsx("span", { children: rollup.billingMode === "api" ? "API billed" : "subscription billed" })), rollup.pricingEstimate && _jsx("span", { children: "~ estimated rates" })] })), 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) => (_jsx(DetailSpanRow, { span: span, depth: depthOf(span, streamed) }, span.spanId)))] })] }));
|
|
223
|
+
}
|
|
224
|
+
/** One span tree row; tool spans expand to their recorded payload (AE7). */
|
|
225
|
+
function DetailSpanRow({ span, depth }) {
|
|
226
|
+
const [expanded, setExpanded] = useState(false);
|
|
227
|
+
const expandable = span.kind === "tool";
|
|
228
|
+
return (_jsxs("div", { style: { paddingLeft: `${depth * 16}px` }, children: [_jsxs("div", { className: cn("flex items-center gap-2 text-xs text-muted-foreground", expandable && "cursor-pointer hover:text-foreground"), onClick: expandable ? () => setExpanded((v) => !v) : undefined, 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
|
|
229
|
+
? formatDuration(span.endedAt - span.startedAt)
|
|
230
|
+
: "…" }), expandable && (_jsx(ChevronRight, { className: cn("h-3 w-3 shrink-0 transition-transform", expanded && "rotate-90") }))] }), expanded && _jsx(SpanPayload, { spanId: span.spanId })] }));
|
|
231
|
+
}
|
|
232
|
+
function depthOf(span, all) {
|
|
233
|
+
let depth = 0;
|
|
234
|
+
let current = span;
|
|
235
|
+
while (current?.parentSpanId) {
|
|
236
|
+
depth += 1;
|
|
237
|
+
current = all.find((s) => s.spanId === current.parentSpanId);
|
|
238
|
+
if (depth > 6)
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
return depth;
|
|
242
|
+
}
|
|
243
|
+
//# 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":"AAQA;;;;;;;GAOG;AACH,wBAAgB,UAAU,uCAoFzB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
import { digestCostClause } from "./span-bits.js";
|
|
8
|
+
/**
|
|
9
|
+
* The while-you-were-away card: presented PROACTIVELY on app open when a
|
|
10
|
+
* fresh digest exists (planning decision — built passively, the flow
|
|
11
|
+
* collapses back into asking the agent what happened). Once per digest:
|
|
12
|
+
* dismissing persists server-side, so a phone and a laptop don't each nag.
|
|
13
|
+
* An empty window stays quiet — no card for "nothing happened". The window
|
|
14
|
+
* is labeled: the card says what period it covers, never implies "now".
|
|
15
|
+
*/
|
|
16
|
+
export function DigestCard() {
|
|
17
|
+
const [digest, setDigest] = useState(null);
|
|
18
|
+
const [visible, setVisible] = useState(false);
|
|
19
|
+
const setActiveView = useUIStore((s) => s.setActiveView);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
void api
|
|
22
|
+
.activityDigest()
|
|
23
|
+
.then(({ digest, dismissedAt }) => {
|
|
24
|
+
if (!digest || digest.runs === 0)
|
|
25
|
+
return;
|
|
26
|
+
if (digest.generatedAt <= dismissedAt)
|
|
27
|
+
return;
|
|
28
|
+
setDigest(digest);
|
|
29
|
+
setVisible(true);
|
|
30
|
+
})
|
|
31
|
+
.catch(() => {
|
|
32
|
+
// No digest is a quiet state, never an error surface.
|
|
33
|
+
});
|
|
34
|
+
}, []);
|
|
35
|
+
if (!visible || !digest)
|
|
36
|
+
return null;
|
|
37
|
+
function dismiss() {
|
|
38
|
+
setVisible(false);
|
|
39
|
+
void api.activityDigestDismiss().catch(() => { });
|
|
40
|
+
}
|
|
41
|
+
const windowLabel = `${formatDay(digest.windowStart)} – ${formatDay(digest.windowEnd)}`;
|
|
42
|
+
// Effective-only spend clause; a digest persisted before pricing shipped
|
|
43
|
+
// falls back to its old list-cost clause inside the helper.
|
|
44
|
+
const costClause = digestCostClause(digest);
|
|
45
|
+
return (_jsxs("div", { className: cn("mx-auto mb-3 w-full max-w-2xl rounded-xl border p-3 text-xs", digest.failures > 0
|
|
46
|
+
? "border-destructive/30 bg-destructive/5"
|
|
47
|
+
: "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"] })), costClause && ` · ${costClause}`] }), 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: () => {
|
|
48
|
+
dismiss();
|
|
49
|
+
setActiveView("activity");
|
|
50
|
+
}, className: "mt-2 text-[11px] font-medium text-primary hover:underline", children: "Open Activity" })] }));
|
|
51
|
+
}
|
|
52
|
+
function formatDay(ms) {
|
|
53
|
+
return new Date(ms).toLocaleDateString(undefined, { month: "short", day: "numeric" });
|
|
54
|
+
}
|
|
55
|
+
//# 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":";AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAE3D,OAAO,EAAE,GAAG,EAAuB,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAwB,IAAI,CAAC,CAAC;IAClE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;IAEzD,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,GAAG;aACL,cAAc,EAAE;aAChB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE;YAChC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;gBAAE,OAAO;YACzC,IAAI,MAAM,CAAC,WAAW,IAAI,WAAW;gBAAE,OAAO;YAC9C,SAAS,CAAC,MAAM,CAAC,CAAC;YAClB,UAAU,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,sDAAsD;QACxD,CAAC,CAAC,CAAC;IACP,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAErC,SAAS,OAAO;QACd,UAAU,CAAC,KAAK,CAAC,CAAC;QAClB,KAAK,GAAG,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,WAAW,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;IACxF,yEAAyE;IACzE,4DAA4D;IAC5D,MAAM,UAAU,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAE5C,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,6DAA6D,EAC7D,MAAM,CAAC,QAAQ,GAAG,CAAC;YACjB,CAAC,CAAC,wCAAwC;YAC1C,CAAC,CAAC,iCAAiC,CACtC,aAED,eAAK,SAAS,EAAC,yBAAyB,aACtC,KAAC,SAAS,IAAC,SAAS,EAAC,wCAAwC,GAAG,EAChE,eAAM,SAAS,EAAC,aAAa,oCAA2B,EACxD,eAAM,SAAS,EAAC,sCAAsC,YAAE,WAAW,GAAQ,EAC3E,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,OAAO,EAChB,SAAS,EAAC,mFAAmF,gBAClF,SAAS,YAEpB,KAAC,CAAC,IAAC,SAAS,EAAC,aAAa,GAAG,GACtB,IACL,EACN,eAAK,SAAS,EAAC,8BAA8B,aAC1C,MAAM,CAAC,IAAI,UAAM,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAC7C,MAAM,CAAC,QAAQ,GAAG,CAAC,IAAI,CACtB,gBAAM,SAAS,EAAC,kBAAkB,yBAAK,MAAM,CAAC,QAAQ,eAAe,CACtE,EACA,UAAU,IAAI,MAAM,UAAU,EAAE,IAC7B,EACL,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAC5B,cAAK,SAAS,EAAC,oBAAoB,YAChC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACrC,eAAmB,SAAS,EAAC,uCAAuC,aAClE,KAAC,aAAa,IAAC,SAAS,EAAC,mCAAmC,GAAG,EAC/D,gBAAM,SAAS,EAAC,UAAU,aACvB,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,cAAK,CAAC,CAAC,OAAO,IAC7B,KAJC,CAAC,CAAC,KAAK,CAKX,CACP,CAAC,GACE,CACP,EACD,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE;oBACZ,OAAO,EAAE,CAAC;oBACV,aAAa,CAAC,UAAU,CAAC,CAAC;gBAC5B,CAAC,EACD,SAAS,EAAC,2DAA2D,8BAG9D,IACL,CACP,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,EAAU;IAC3B,OAAO,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,kBAAkB,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;AACxF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-toggle.d.ts","sourceRoot":"","sources":["../../../src/components/activity/push-toggle.tsx"],"names":[],"mappings":"AA8BA,wBAAgB,UAAU,gCA8HzB"}
|
|
@@ -0,0 +1,121 @@
|
|
|
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
|
+
/**
|
|
7
|
+
* The push enable/disable control, living on the Activity surface (where the
|
|
8
|
+
* alerts it governs land). The permission model is THREE-state, not a bare
|
|
9
|
+
* toggle: once the browser prompt is denied, Chrome silently ignores every
|
|
10
|
+
* further in-page request — so the blocked state must say where the real
|
|
11
|
+
* switch lives (site settings) instead of offering a button that does
|
|
12
|
+
* nothing. Where the platform has no push at all (iOS Safari in-browser,
|
|
13
|
+
* pre-16.4), the control renders disabled-with-explanation, not hidden.
|
|
14
|
+
*/
|
|
15
|
+
/** The subscription's bound applicationServerKey, in the base64url form the
|
|
16
|
+
* server hands out — comparable against `pushPublicKey()` directly. */
|
|
17
|
+
function keyToBase64Url(key) {
|
|
18
|
+
let bin = "";
|
|
19
|
+
for (const b of new Uint8Array(key))
|
|
20
|
+
bin += String.fromCharCode(b);
|
|
21
|
+
return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
22
|
+
}
|
|
23
|
+
export function PushToggle() {
|
|
24
|
+
const [state, setState] = useState("unsupported");
|
|
25
|
+
const [busy, setBusy] = useState(false);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
void (async () => {
|
|
28
|
+
if (!("Notification" in window) || !("serviceWorker" in navigator) || !("PushManager" in window)) {
|
|
29
|
+
setState("unsupported");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (Notification.permission === "denied") {
|
|
33
|
+
setState("blocked");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (Notification.permission === "default") {
|
|
37
|
+
setState("not-asked");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const registration = await navigator.serviceWorker.ready;
|
|
41
|
+
const subscription = await registration.pushManager.getSubscription();
|
|
42
|
+
if (subscription) {
|
|
43
|
+
// The browser having a subscription doesn't mean the SERVER can
|
|
44
|
+
// still use it. Two disagreement cases: the server pruned/lost the
|
|
45
|
+
// row (a dead-endpoint send, a DB restore) — healed by re-asserting,
|
|
46
|
+
// an idempotent upsert; or the server's VAPID keypair changed, which
|
|
47
|
+
// makes this subscription permanently unsendable — its
|
|
48
|
+
// applicationServerKey no longer matches, so drop it and surface the
|
|
49
|
+
// re-enable button. Offline, trust the browser's own state.
|
|
50
|
+
try {
|
|
51
|
+
const { publicKey } = await api.pushPublicKey();
|
|
52
|
+
const boundKey = subscription.options.applicationServerKey;
|
|
53
|
+
if (boundKey && keyToBase64Url(boundKey) !== publicKey) {
|
|
54
|
+
await subscription.unsubscribe().catch(() => { });
|
|
55
|
+
setState("unsubscribed");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
await api.pushSubscribe(subscription.toJSON(), navigator.userAgent.slice(0, 100));
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// Server unreachable — keep the browser's answer.
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
setState(subscription ? "subscribed" : "unsubscribed");
|
|
65
|
+
})();
|
|
66
|
+
}, []);
|
|
67
|
+
async function enable() {
|
|
68
|
+
setBusy(true);
|
|
69
|
+
try {
|
|
70
|
+
const permission = await Notification.requestPermission();
|
|
71
|
+
if (permission === "denied") {
|
|
72
|
+
setState("blocked");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (permission !== "granted") {
|
|
76
|
+
setState("not-asked");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const { publicKey } = await api.pushPublicKey();
|
|
80
|
+
const registration = await navigator.serviceWorker.ready;
|
|
81
|
+
const subscription = await registration.pushManager.subscribe({
|
|
82
|
+
userVisibleOnly: true,
|
|
83
|
+
applicationServerKey: publicKey,
|
|
84
|
+
});
|
|
85
|
+
await api.pushSubscribe(subscription.toJSON(), navigator.userAgent.slice(0, 100));
|
|
86
|
+
setState("subscribed");
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
setState("unsubscribed");
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
setBusy(false);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function disable() {
|
|
96
|
+
setBusy(true);
|
|
97
|
+
try {
|
|
98
|
+
const registration = await navigator.serviceWorker.ready;
|
|
99
|
+
const subscription = await registration.pushManager.getSubscription();
|
|
100
|
+
if (subscription) {
|
|
101
|
+
await api.pushUnsubscribe(subscription.endpoint).catch(() => { });
|
|
102
|
+
await subscription.unsubscribe();
|
|
103
|
+
}
|
|
104
|
+
setState("unsubscribed");
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
setBusy(false);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (state === "unsupported") {
|
|
111
|
+
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"] }));
|
|
112
|
+
}
|
|
113
|
+
if (state === "blocked") {
|
|
114
|
+
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"] }));
|
|
115
|
+
}
|
|
116
|
+
const on = state === "subscribed";
|
|
117
|
+
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
|
|
118
|
+
? "text-primary hover:bg-surface-raised"
|
|
119
|
+
: "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"] }));
|
|
120
|
+
}
|
|
121
|
+
//# 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,76 @@
|
|
|
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
|
+
/**
|
|
24
|
+
* The recorded input/output of one tool span, expanded under its row — the
|
|
25
|
+
* ONE payload renderer shared by the subagent drill-in and the run detail.
|
|
26
|
+
* Mounted only while expanded (collapsed rows never subscribe). A span with
|
|
27
|
+
* no payload events (recorded before capture shipped) states so instead of
|
|
28
|
+
* offering an empty block (AE7); a payload clipped at persist time carries
|
|
29
|
+
* the wire `truncated` flag, rendered as a hint line under the block.
|
|
30
|
+
*/
|
|
31
|
+
export declare function SpanPayload({ spanId }: {
|
|
32
|
+
spanId: string;
|
|
33
|
+
}): import("react").JSX.Element;
|
|
34
|
+
/**
|
|
35
|
+
* THE effective-cost glyph — one three-state rule so no surface ever renders
|
|
36
|
+
* an unknown cost as $0.00 (AE3): absent/NULL is "—" (we don't know), 0 is
|
|
37
|
+
* "free" (we know — subscription-billed or genuinely zero), positive is
|
|
38
|
+
* dollars, "~"-prefixed when computed from estimated rates. Sub-cent costs
|
|
39
|
+
* floor at "<$0.01" rather than rounding down to a zero look-alike.
|
|
40
|
+
*/
|
|
41
|
+
export declare function formatEffectiveCost(costUsd: number | null | undefined, estimate?: boolean): string;
|
|
42
|
+
/**
|
|
43
|
+
* An aggregate's effective-cost sum. Sums exclude unknown-cost runs, so a
|
|
44
|
+
* nonzero `unpricedRuns` makes the number a floor ("≥ $X"), never a total.
|
|
45
|
+
* A known sub-cent sum floors at "<$0.01" like the per-run glyph — only an
|
|
46
|
+
* exact 0 (genuinely nothing to add up) renders "$0.00" (AE3).
|
|
47
|
+
*/
|
|
48
|
+
export declare function formatAggregateCost(effectiveUsd: number, unpricedRuns: number): string;
|
|
49
|
+
/**
|
|
50
|
+
* A run row's cost text, three-way on `effectiveCostUsd`: ABSENT means a
|
|
51
|
+
* pre-pricing server never sent the field — fall back to the original
|
|
52
|
+
* list-cost rendering (a positive `costUsd`, else nothing) instead of
|
|
53
|
+
* claiming unknown; explicit null means THIS server computed "unknown" and
|
|
54
|
+
* renders the em dash; a number goes through `formatEffectiveCost` (AE3).
|
|
55
|
+
*/
|
|
56
|
+
export declare function runCostText(run: {
|
|
57
|
+
costUsd: number | null;
|
|
58
|
+
effectiveCostUsd?: number | null;
|
|
59
|
+
pricingEstimate?: boolean;
|
|
60
|
+
}): string | null;
|
|
61
|
+
/**
|
|
62
|
+
* The digest card's cost clause (no leading separator), effective-only, or
|
|
63
|
+
* null for "say nothing". A digest persisted before pricing shipped carries
|
|
64
|
+
* neither new field and keeps its old list-cost clause.
|
|
65
|
+
*/
|
|
66
|
+
export declare function digestCostClause(digest: {
|
|
67
|
+
costUsd: number;
|
|
68
|
+
effectiveCostUsd?: number;
|
|
69
|
+
unpricedRuns?: number;
|
|
70
|
+
}): string | null;
|
|
71
|
+
/** The "9+" unread-count bubble shared by the rail and the tab bar. Hidden at 0. */
|
|
72
|
+
export declare function CountBadge({ count, className }: {
|
|
73
|
+
count: number;
|
|
74
|
+
className?: string;
|
|
75
|
+
}): import("react").JSX.Element | null;
|
|
76
|
+
//# 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":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAU3F;;;;;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,CASxD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,+BAgCzD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,QAAQ,CAAC,EAAE,OAAO,GACjB,MAAM,CAKR;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAItF;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,GAAG,MAAM,GAAG,IAAI,CAKhB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,MAAM,GAAG,IAAI,CAYhB;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"}
|