@schlessera/brain-ui-server 0.18.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.
- package/dist/activity/digest.d.ts +29 -0
- package/dist/activity/digest.d.ts.map +1 -0
- package/dist/activity/digest.js +61 -0
- package/dist/activity/digest.js.map +1 -0
- package/dist/activity/notify.d.ts +62 -0
- package/dist/activity/notify.d.ts.map +1 -0
- package/dist/activity/notify.js +171 -0
- package/dist/activity/notify.js.map +1 -0
- package/dist/activity/push-sender.d.ts +63 -0
- package/dist/activity/push-sender.d.ts.map +1 -0
- package/dist/activity/push-sender.js +131 -0
- package/dist/activity/push-sender.js.map +1 -0
- package/dist/activity/query.d.ts +16 -0
- package/dist/activity/query.d.ts.map +1 -0
- package/dist/activity/query.js +128 -0
- package/dist/activity/query.js.map +1 -0
- package/dist/activity/recorder.d.ts +48 -0
- package/dist/activity/recorder.d.ts.map +1 -0
- package/dist/activity/recorder.js +205 -0
- package/dist/activity/recorder.js.map +1 -0
- package/dist/activity/runtime.d.ts +31 -0
- package/dist/activity/runtime.d.ts.map +1 -0
- package/dist/activity/runtime.js +109 -0
- package/dist/activity/runtime.js.map +1 -0
- package/dist/activity/span-sink.d.ts +22 -0
- package/dist/activity/span-sink.d.ts.map +1 -0
- package/dist/activity/span-sink.js +138 -0
- package/dist/activity/span-sink.js.map +1 -0
- package/dist/activity/store.d.ts +207 -0
- package/dist/activity/store.d.ts.map +1 -0
- package/dist/activity/store.js +440 -0
- package/dist/activity/store.js.map +1 -0
- package/dist/activity/stream.d.ts +45 -0
- package/dist/activity/stream.d.ts.map +1 -0
- package/dist/activity/stream.js +312 -0
- package/dist/activity/stream.js.map +1 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +16 -0
- package/dist/app.js.map +1 -1
- package/dist/cron/scheduler.d.ts.map +1 -1
- package/dist/cron/scheduler.js +20 -5
- package/dist/cron/scheduler.js.map +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +32 -6
- package/dist/db/client.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/routes/activity.d.ts +20 -0
- package/dist/routes/activity.d.ts.map +1 -0
- package/dist/routes/activity.js +300 -0
- package/dist/routes/activity.js.map +1 -0
- package/dist/routes/push.d.ts +6 -0
- package/dist/routes/push.d.ts.map +1 -0
- package/dist/routes/push.js +73 -0
- package/dist/routes/push.js.map +1 -0
- package/dist/routes/sessions.d.ts.map +1 -1
- package/dist/routes/sessions.js +20 -4
- package/dist/routes/sessions.js.map +1 -1
- package/dist/ws/bridge.d.ts +2 -1
- package/dist/ws/bridge.d.ts.map +1 -1
- package/dist/ws/bridge.js +27 -2
- package/dist/ws/bridge.js.map +1 -1
- package/dist/ws/connection.d.ts.map +1 -1
- package/dist/ws/connection.js +9 -1
- package/dist/ws/connection.js.map +1 -1
- package/dist/ws/dispatch.d.ts.map +1 -1
- package/dist/ws/dispatch.js +11 -0
- package/dist/ws/dispatch.js.map +1 -1
- package/dist/ws/host.d.ts +16 -0
- package/dist/ws/host.d.ts.map +1 -1
- package/dist/ws/host.js +2 -0
- package/dist/ws/host.js.map +1 -1
- package/dist/ws/run-session.d.ts.map +1 -1
- package/dist/ws/run-session.js +21 -1
- package/dist/ws/run-session.js.map +1 -1
- package/migrations/007_activity.sql +114 -0
- package/migrations/008_push_subscriptions.sql +24 -0
- package/package.json +5 -3
- package/src/activity/digest.ts +92 -0
- package/src/activity/notify.ts +285 -0
- package/src/activity/push-sender.ts +215 -0
- package/src/activity/query.ts +160 -0
- package/src/activity/recorder.ts +261 -0
- package/src/activity/runtime.ts +141 -0
- package/src/activity/span-sink.ts +152 -0
- package/src/activity/store.ts +774 -0
- package/src/activity/stream.ts +366 -0
- package/src/app.ts +17 -0
- package/src/cron/scheduler.ts +28 -8
- package/src/db/client.ts +31 -6
- package/src/index.ts +22 -0
- package/src/routes/activity.ts +363 -0
- package/src/routes/push.ts +90 -0
- package/src/routes/sessions.ts +24 -4
- package/src/ws/bridge.ts +29 -2
- package/src/ws/connection.ts +9 -1
- package/src/ws/dispatch.ts +13 -0
- package/src/ws/host.ts +18 -0
- package/src/ws/run-session.ts +28 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import type { Database } from "bun:sqlite";
|
|
3
|
+
import { type ActivityStore } from "../activity/store.js";
|
|
4
|
+
import type { ActivityNotifier } from "../activity/notify.js";
|
|
5
|
+
/**
|
|
6
|
+
* The activity record's read API. Auth-guarded like every /api route (the
|
|
7
|
+
* record leaks strictly more than /api/status, which is itself deliberately
|
|
8
|
+
* behind the guard).
|
|
9
|
+
*
|
|
10
|
+
* Resolution rules (origin R26): a run id that ever existed resolves — to
|
|
11
|
+
* the full span tree while detail is retained, to its rollup ("detail
|
|
12
|
+
* pruned") afterwards; only never-existed ids 404. Cost/token aggregates
|
|
13
|
+
* read per-run rollups, which carry ROOT-span accounting only.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createActivityRoutes(deps: {
|
|
16
|
+
db: Database;
|
|
17
|
+
store: ActivityStore;
|
|
18
|
+
notifier?: ActivityNotifier;
|
|
19
|
+
}): Hono;
|
|
20
|
+
//# sourceMappingURL=activity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../src/routes/activity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAU3C,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAS9D;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,EAAE,EAAE,QAAQ,CAAC;IACb,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC7B,GAAG,IAAI,CAqQP"}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { isFailureOutcome, } from "@schlessera/brain-ui-sdk/protocol";
|
|
3
|
+
import { rowToRunRollup } from "../activity/store.js";
|
|
4
|
+
import { toWireEvent, toWireSpan } from "../activity/stream.js";
|
|
5
|
+
import { dismissActivityDigest, digestDismissedAt, generateActivityDigest, latestActivityDigest, } from "../activity/digest.js";
|
|
6
|
+
import { getSetting, setSetting } from "../db/settings.js";
|
|
7
|
+
/**
|
|
8
|
+
* The activity record's read API. Auth-guarded like every /api route (the
|
|
9
|
+
* record leaks strictly more than /api/status, which is itself deliberately
|
|
10
|
+
* behind the guard).
|
|
11
|
+
*
|
|
12
|
+
* Resolution rules (origin R26): a run id that ever existed resolves — to
|
|
13
|
+
* the full span tree while detail is retained, to its rollup ("detail
|
|
14
|
+
* pruned") afterwards; only never-existed ids 404. Cost/token aggregates
|
|
15
|
+
* read per-run rollups, which carry ROOT-span accounting only.
|
|
16
|
+
*/
|
|
17
|
+
export function createActivityRoutes(deps) {
|
|
18
|
+
const { db, store, notifier } = deps;
|
|
19
|
+
return new Hono()
|
|
20
|
+
.get("/activity/digest", (c) => {
|
|
21
|
+
try {
|
|
22
|
+
// An authenticated fetch IS the app opening — the marker the next
|
|
23
|
+
// digest window's framing leans on.
|
|
24
|
+
setSetting(db, "activity.lastVisitAt", Date.now());
|
|
25
|
+
return c.json({
|
|
26
|
+
digest: latestActivityDigest(db),
|
|
27
|
+
dismissedAt: digestDismissedAt(db),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to load digest" }, 500);
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
.post("/activity/digest/dismiss", (c) => {
|
|
35
|
+
try {
|
|
36
|
+
dismissActivityDigest(db);
|
|
37
|
+
return c.json({ ok: true });
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to dismiss" }, 500);
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
.post("/activity/digest/generate", (c) => {
|
|
44
|
+
// Manual trigger (the cron job calls generateActivityDigest directly
|
|
45
|
+
// through the script; this exists for dev and for a pull-to-refresh).
|
|
46
|
+
try {
|
|
47
|
+
return c.json({ digest: generateActivityDigest(db) });
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to generate" }, 500);
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
.get("/activity/inbox", (c) => {
|
|
54
|
+
try {
|
|
55
|
+
return c.json({ intents: notifier?.inbox() ?? [] });
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to list inbox" }, 500);
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
.post("/activity/inbox/ack-all", (c) => {
|
|
62
|
+
try {
|
|
63
|
+
return c.json({ acknowledged: notifier?.acknowledgeAll() ?? 0 });
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to acknowledge" }, 500);
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
.post("/activity/inbox/:id/ack", (c) => {
|
|
70
|
+
const id = Number(c.req.param("id"));
|
|
71
|
+
if (!Number.isInteger(id) || id < 1)
|
|
72
|
+
return c.json({ error: "Bad intent id" }, 400);
|
|
73
|
+
try {
|
|
74
|
+
const ok = notifier?.acknowledge(id) ?? false;
|
|
75
|
+
return ok ? c.json({ ok: true }) : c.json({ error: "Unknown intent" }, 404);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to acknowledge" }, 500);
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
.get("/activity/runs", (c) => {
|
|
82
|
+
try {
|
|
83
|
+
const limit = Math.min(Math.max(Number(c.req.query("limit") ?? 50) || 50, 1), 200);
|
|
84
|
+
const before = Number(c.req.query("before")) || Date.now() + 1;
|
|
85
|
+
const origin = c.req.query("origin");
|
|
86
|
+
const job = c.req.query("job");
|
|
87
|
+
const session = c.req.query("session");
|
|
88
|
+
const status = c.req.query("status");
|
|
89
|
+
// Live first (open roots), then history from rollups. Rollups exist
|
|
90
|
+
// for every finished run (terminal writes upsert them), so one table
|
|
91
|
+
// serves the history list regardless of pruning state.
|
|
92
|
+
const live = store
|
|
93
|
+
.openRootSpans()
|
|
94
|
+
.filter((s) => !origin || s.origin === origin)
|
|
95
|
+
.filter((s) => !job || s.jobName === job)
|
|
96
|
+
.filter((s) => !session || s.sessionId === session)
|
|
97
|
+
.map((s) => ({
|
|
98
|
+
runId: s.runId,
|
|
99
|
+
origin: s.origin,
|
|
100
|
+
name: s.name,
|
|
101
|
+
sessionId: s.sessionId,
|
|
102
|
+
jobName: s.jobName,
|
|
103
|
+
startedAt: s.startedAt,
|
|
104
|
+
endedAt: null,
|
|
105
|
+
outcome: null,
|
|
106
|
+
running: true,
|
|
107
|
+
durationMs: null,
|
|
108
|
+
costUsd: s.usage.costUsd ?? null,
|
|
109
|
+
failureReason: null,
|
|
110
|
+
detailPruned: false,
|
|
111
|
+
}));
|
|
112
|
+
const filters = ["started_at < ?"];
|
|
113
|
+
const params = [before];
|
|
114
|
+
if (origin) {
|
|
115
|
+
filters.push("origin = ?");
|
|
116
|
+
params.push(origin);
|
|
117
|
+
}
|
|
118
|
+
if (job) {
|
|
119
|
+
filters.push("job_name = ?");
|
|
120
|
+
params.push(job);
|
|
121
|
+
}
|
|
122
|
+
if (session) {
|
|
123
|
+
filters.push("session_id = ?");
|
|
124
|
+
params.push(session);
|
|
125
|
+
}
|
|
126
|
+
if (status) {
|
|
127
|
+
filters.push("outcome = ?");
|
|
128
|
+
params.push(status);
|
|
129
|
+
}
|
|
130
|
+
if (live.length > 0) {
|
|
131
|
+
filters.push(`run_id NOT IN (${live.map(() => "?").join(", ")})`);
|
|
132
|
+
params.push(...live.map((r) => r.runId));
|
|
133
|
+
}
|
|
134
|
+
const history = db
|
|
135
|
+
.query(`SELECT * FROM activity_run_rollups WHERE ${filters.join(" AND ")}
|
|
136
|
+
ORDER BY started_at DESC LIMIT ?`)
|
|
137
|
+
.all(...params, limit)
|
|
138
|
+
.map(rowToRunRollup)
|
|
139
|
+
.map((r) => ({
|
|
140
|
+
runId: r.runId,
|
|
141
|
+
origin: r.origin,
|
|
142
|
+
name: r.name,
|
|
143
|
+
sessionId: r.sessionId,
|
|
144
|
+
jobName: r.jobName,
|
|
145
|
+
startedAt: r.startedAt,
|
|
146
|
+
endedAt: r.endedAt,
|
|
147
|
+
outcome: r.outcome,
|
|
148
|
+
running: false,
|
|
149
|
+
durationMs: r.durationMs,
|
|
150
|
+
costUsd: r.costUsd,
|
|
151
|
+
failureReason: r.failureReason,
|
|
152
|
+
detailPruned: r.detailPruned,
|
|
153
|
+
}));
|
|
154
|
+
return c.json({ live, history });
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to list activity" }, 500);
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
.get("/activity/runs/:runId", (c) => {
|
|
161
|
+
const runId = c.req.param("runId");
|
|
162
|
+
try {
|
|
163
|
+
const snapshot = store.snapshotRun(runId);
|
|
164
|
+
if (snapshot) {
|
|
165
|
+
// Through the SAME wire mappers the live stream uses: a raw
|
|
166
|
+
// SpanRow serializes null fields where the wire contract omits
|
|
167
|
+
// them, which broke the client's `outcome === undefined`
|
|
168
|
+
// liveness test on REST-loaded runs.
|
|
169
|
+
const detail = {
|
|
170
|
+
runId,
|
|
171
|
+
detailPruned: false,
|
|
172
|
+
spans: snapshot.spans.map(toWireSpan),
|
|
173
|
+
events: snapshot.events.map(toWireEvent),
|
|
174
|
+
highWaterSeq: snapshot.highWaterSeq,
|
|
175
|
+
};
|
|
176
|
+
return c.json(detail);
|
|
177
|
+
}
|
|
178
|
+
const row = db
|
|
179
|
+
.query("SELECT * FROM activity_run_rollups WHERE run_id = ?")
|
|
180
|
+
.get(runId);
|
|
181
|
+
if (!row)
|
|
182
|
+
return c.json({ error: "Unknown run" }, 404);
|
|
183
|
+
const r = rowToRunRollup(row);
|
|
184
|
+
const rollup = {
|
|
185
|
+
origin: r.origin,
|
|
186
|
+
name: r.name,
|
|
187
|
+
sessionId: r.sessionId,
|
|
188
|
+
jobName: r.jobName,
|
|
189
|
+
startedAt: r.startedAt,
|
|
190
|
+
endedAt: r.endedAt,
|
|
191
|
+
outcome: r.outcome,
|
|
192
|
+
durationMs: r.durationMs,
|
|
193
|
+
spanCount: r.spanCount,
|
|
194
|
+
costUsd: r.costUsd,
|
|
195
|
+
failureReason: r.failureReason,
|
|
196
|
+
};
|
|
197
|
+
const detail = { runId, detailPruned: true, rollup };
|
|
198
|
+
return c.json(detail);
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to load run" }, 500);
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
.get("/activity/rollups", (c) => {
|
|
205
|
+
try {
|
|
206
|
+
const days = Math.min(Number(c.req.query("days") ?? 7) || 7, 90);
|
|
207
|
+
const since = Date.now() - days * 24 * 60 * 60 * 1000;
|
|
208
|
+
// The day boundary is the USER'S day, not UTC's — cron runs in UTC
|
|
209
|
+
// but nobody reviews spend in it. Configurable server-side.
|
|
210
|
+
const timeZone = getSetting(db, "activity.timezone", "UTC");
|
|
211
|
+
const dayOf = makeDayFormatter(timeZone);
|
|
212
|
+
// Job/session aggregates group SQL-side; the per-day fold stays in
|
|
213
|
+
// JS because only Intl knows the configured timezone's day boundary.
|
|
214
|
+
const rows = db
|
|
215
|
+
.query(`SELECT started_at, outcome, duration_ms, cost_usd, input_tokens,
|
|
216
|
+
output_tokens, cache_read_tokens, cache_creation_tokens
|
|
217
|
+
FROM activity_run_rollups WHERE started_at >= ?`)
|
|
218
|
+
.all(since);
|
|
219
|
+
const byDay = new Map();
|
|
220
|
+
for (const r of rows) {
|
|
221
|
+
add(byDay, dayOf(r.started_at), r);
|
|
222
|
+
}
|
|
223
|
+
const rollups = {
|
|
224
|
+
timeZone,
|
|
225
|
+
days: [...byDay.entries()]
|
|
226
|
+
.map(([key, a]) => ({ day: key, ...a }))
|
|
227
|
+
.sort((a, b) => (a.day < b.day ? 1 : -1)),
|
|
228
|
+
jobs: groupedAggregates(db, since, "job_name").map(({ key, ...a }) => ({
|
|
229
|
+
jobName: key,
|
|
230
|
+
...a,
|
|
231
|
+
})),
|
|
232
|
+
sessions: groupedAggregates(db, since, "session_id").map(({ key, ...a }) => ({
|
|
233
|
+
sessionId: key,
|
|
234
|
+
...a,
|
|
235
|
+
})),
|
|
236
|
+
};
|
|
237
|
+
return c.json(rollups);
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to aggregate" }, 500);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* SQL-side aggregation per group key. The failure predicate mirrors the
|
|
246
|
+
* SDK's `isFailureOutcome` — it cannot be shared into SQL, so keep the two
|
|
247
|
+
* in sync.
|
|
248
|
+
*/
|
|
249
|
+
function groupedAggregates(db, since, column) {
|
|
250
|
+
return db
|
|
251
|
+
.query(`SELECT ${column} AS key,
|
|
252
|
+
COUNT(*) AS runs,
|
|
253
|
+
SUM(CASE WHEN outcome IN ('error', 'timeout', 'interrupted') THEN 1 ELSE 0 END) AS failures,
|
|
254
|
+
SUM(COALESCE(cost_usd, 0)) AS costUsd,
|
|
255
|
+
SUM(COALESCE(input_tokens, 0)) AS inputTokens,
|
|
256
|
+
SUM(COALESCE(output_tokens, 0)) AS outputTokens,
|
|
257
|
+
SUM(COALESCE(cache_read_tokens, 0)) AS cacheReadTokens,
|
|
258
|
+
SUM(COALESCE(cache_creation_tokens, 0)) AS cacheCreationTokens,
|
|
259
|
+
SUM(COALESCE(duration_ms, 0)) AS durationMs
|
|
260
|
+
FROM activity_run_rollups
|
|
261
|
+
WHERE started_at >= ? AND ${column} IS NOT NULL
|
|
262
|
+
GROUP BY ${column}`)
|
|
263
|
+
.all(since);
|
|
264
|
+
}
|
|
265
|
+
function add(map, key, r) {
|
|
266
|
+
const a = map.get(key) ??
|
|
267
|
+
{
|
|
268
|
+
runs: 0,
|
|
269
|
+
failures: 0,
|
|
270
|
+
costUsd: 0,
|
|
271
|
+
inputTokens: 0,
|
|
272
|
+
outputTokens: 0,
|
|
273
|
+
cacheReadTokens: 0,
|
|
274
|
+
cacheCreationTokens: 0,
|
|
275
|
+
durationMs: 0,
|
|
276
|
+
};
|
|
277
|
+
a.runs += 1;
|
|
278
|
+
if (isFailureOutcome(r.outcome)) {
|
|
279
|
+
a.failures += 1;
|
|
280
|
+
}
|
|
281
|
+
a.costUsd += r.cost_usd ?? 0;
|
|
282
|
+
a.inputTokens += r.input_tokens ?? 0;
|
|
283
|
+
a.outputTokens += r.output_tokens ?? 0;
|
|
284
|
+
a.cacheReadTokens += r.cache_read_tokens ?? 0;
|
|
285
|
+
a.cacheCreationTokens += r.cache_creation_tokens ?? 0;
|
|
286
|
+
a.durationMs += r.duration_ms ?? 0;
|
|
287
|
+
map.set(key, a);
|
|
288
|
+
}
|
|
289
|
+
/** YYYY-MM-DD in the given zone; a bad zone degrades loudly to UTC once. */
|
|
290
|
+
function makeDayFormatter(timeZone) {
|
|
291
|
+
let fmt;
|
|
292
|
+
try {
|
|
293
|
+
fmt = new Intl.DateTimeFormat("en-CA", { timeZone, dateStyle: "short" });
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
fmt = new Intl.DateTimeFormat("en-CA", { timeZone: "UTC", dateStyle: "short" });
|
|
297
|
+
}
|
|
298
|
+
return (ms) => fmt.format(new Date(ms));
|
|
299
|
+
}
|
|
300
|
+
//# sourceMappingURL=activity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity.js","sourceRoot":"","sources":["../../src/routes/activity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EACL,gBAAgB,GAMjB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAE,cAAc,EAAsB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEhE,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE3D;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAIpC;IACC,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAErC,OAAO,IAAI,IAAI,EAAE;SACd,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,kEAAkE;YAClE,oCAAoC;YACpC,UAAU,CAAC,EAAE,EAAE,sBAAsB,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YACnD,OAAO,CAAC,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,oBAAoB,CAAC,EAAE,CAAC;gBAChC,WAAW,EAAE,iBAAiB,CAAC,EAAE,CAAC;aACnC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,EAAE,EACvE,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;SAED,IAAI,CAAC,0BAA0B,EAAE,CAAC,CAAC,EAAE,EAAE;QACtC,IAAI,CAAC;YACH,qBAAqB,CAAC,EAAE,CAAC,CAAC;YAC1B,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,EAAE,EACnE,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;SAED,IAAI,CAAC,2BAA2B,EAAE,CAAC,CAAC,EAAE,EAAE;QACvC,qEAAqE;QACrE,sEAAsE;QACtE,IAAI,CAAC;YACH,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,sBAAsB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,oBAAoB,EAAE,EACpE,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;SAED,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE;QAC5B,IAAI,CAAC;YACH,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QACtD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,sBAAsB,EAAE,EACtE,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;SAED,IAAI,CAAC,yBAAyB,EAAE,CAAC,CAAC,EAAE,EAAE;QACrC,IAAI,CAAC;YACH,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,EAAE,EACvE,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;SAED,IAAI,CAAC,yBAAyB,EAAE,CAAC,CAAC,EAAE,EAAE;QACrC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,GAAG,CAAC,CAAC;QACpF,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,QAAQ,EAAE,WAAW,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC;YAC9C,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,GAAG,CAAC,CAAC;QAC9E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,EAAE,EACvE,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;SACD,GAAG,CAAC,gBAAgB,EAAE,CAAC,CAAC,EAAE,EAAE;QAC3B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YACnF,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC/D,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACrC,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC/B,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACvC,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAErC,oEAAoE;YACpE,qEAAqE;YACrE,uDAAuD;YACvD,MAAM,IAAI,GAAyB,KAAK;iBACrC,aAAa,EAAE;iBACf,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;iBAC7C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,KAAK,GAAG,CAAC;iBACxC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,SAAS,KAAK,OAAO,CAAC;iBAClD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACX,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,IAAI;gBACb,UAAU,EAAE,IAAI;gBAChB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI;gBAChC,aAAa,EAAE,IAAI;gBACnB,YAAY,EAAE,KAAK;aACpB,CAAC,CAAC,CAAC;YAEN,MAAM,OAAO,GAAa,CAAC,gBAAgB,CAAC,CAAC;YAC7C,MAAM,MAAM,GAAc,CAAC,MAAM,CAAC,CAAC;YACnC,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACtB,CAAC;YACD,IAAI,GAAG,EAAE,CAAC;gBACR,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC7B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC;YACD,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC;YACD,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAC5B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACtB,CAAC;YACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,OAAO,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAClE,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3C,CAAC;YACD,MAAM,OAAO,GACX,EAAE;iBACC,KAAK,CACJ,4CAA4C,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;gDAC/B,CACnC;iBACA,GAAG,CAAC,GAAI,MAAkB,EAAE,KAAK,CACrC;iBACE,GAAG,CAAC,cAAc,CAAC;iBACnB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACX,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,OAAO,EAAE,KAAK;gBACd,UAAU,EAAE,CAAC,CAAC,UAAU;gBACxB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,aAAa,EAAE,CAAC,CAAC,aAAa;gBAC9B,YAAY,EAAE,CAAC,CAAC,YAAY;aAC7B,CAAC,CAAC,CAAC;YAEN,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,yBAAyB,EAAE,EACzE,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;SAED,GAAG,CAAC,uBAAuB,EAAE,CAAC,CAAC,EAAE,EAAE;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC1C,IAAI,QAAQ,EAAE,CAAC;gBACb,4DAA4D;gBAC5D,+DAA+D;gBAC/D,yDAAyD;gBACzD,qCAAqC;gBACrC,MAAM,MAAM,GAAsB;oBAChC,KAAK;oBACL,YAAY,EAAE,KAAK;oBACnB,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;oBACrC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;oBACxC,YAAY,EAAE,QAAQ,CAAC,YAAY;iBACpC,CAAC;gBACF,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACxB,CAAC;YACD,MAAM,GAAG,GAAG,EAAE;iBACX,KAAK,CAAC,qDAAqD,CAAC;iBAC5D,GAAG,CAAC,KAAK,CAAQ,CAAC;YACrB,IAAI,CAAC,GAAG;gBAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,GAAG,CAAC,CAAC;YACvD,MAAM,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;YAC9B,MAAM,MAAM,GAAsB;gBAChC,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,UAAU,EAAE,CAAC,CAAC,UAAU;gBACxB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,aAAa,EAAE,CAAC,CAAC,aAAa;aAC/B,CAAC;YACF,MAAM,MAAM,GAAsB,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YACxE,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,oBAAoB,EAAE,EACpE,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;SAED,GAAG,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE;QAC9B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YACjE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;YACtD,mEAAmE;YACnE,4DAA4D;YAC5D,MAAM,QAAQ,GAAG,UAAU,CAAS,EAAE,EAAE,mBAAmB,EAAE,KAAK,CAAC,CAAC;YACpE,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAEzC,mEAAmE;YACnE,qEAAqE;YACrE,MAAM,IAAI,GAAG,EAAE;iBACZ,KAAK,CACJ;;6DAEiD,CAClD;iBACA,GAAG,CAAC,KAAK,CAAU,CAAC;YACvB,MAAM,KAAK,GAAG,IAAI,GAAG,EAA6B,CAAC;YACnD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBACrB,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;YACrC,CAAC;YAED,MAAM,OAAO,GAAoB;gBAC/B,QAAQ;gBACR,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;qBACvB,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;qBACvC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC3C,IAAI,EAAE,iBAAiB,CAAC,EAAE,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;oBACrE,OAAO,EAAE,GAAG;oBACZ,GAAG,CAAC;iBACL,CAAC,CAAC;gBACH,QAAQ,EAAE,iBAAiB,CAAC,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;oBAC3E,SAAS,EAAE,GAAG;oBACd,GAAG,CAAC;iBACL,CAAC,CAAC;aACJ,CAAC;YACF,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,EAAE,EACrE,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CACxB,EAAY,EACZ,KAAa,EACb,MAAiC;IAEjC,OAAO,EAAE;SACN,KAAK,CACJ,UAAU,MAAM;;;;;;;;;;mCAUa,MAAM;kBACvB,MAAM,EAAE,CACrB;SACA,GAAG,CAAC,KAAK,CAA+C,CAAC;AAC9D,CAAC;AAED,SAAS,GAAG,CAAC,GAAmC,EAAE,GAAW,EAAE,CAAM;IACnE,MAAM,CAAC,GACL,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;QACX;YACC,IAAI,EAAE,CAAC;YACP,QAAQ,EAAE,CAAC;YACX,OAAO,EAAE,CAAC;YACV,WAAW,EAAE,CAAC;YACd,YAAY,EAAE,CAAC;YACf,eAAe,EAAE,CAAC;YAClB,mBAAmB,EAAE,CAAC;YACtB,UAAU,EAAE,CAAC;SACe,CAAC;IACjC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;IACZ,IAAI,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC;IAClB,CAAC;IACD,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC7B,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC;IACrC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC;IACvC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,iBAAiB,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,mBAAmB,IAAI,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC;IACtD,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC;IACnC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,4EAA4E;AAC5E,SAAS,gBAAgB,CAAC,QAAgB;IACxC,IAAI,GAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/routes/push.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAuB7D,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GAAG,IAAI,CA2DnE"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
/**
|
|
4
|
+
* Push subscription lifecycle. Behind the auth guard by mount position —
|
|
5
|
+
* the public key is per-deployment (not build-time), and subscribing is a
|
|
6
|
+
* write into the notification fan-out, which only the authenticated user
|
|
7
|
+
* may do. The VAPID PRIVATE key has no route, here or anywhere.
|
|
8
|
+
*/
|
|
9
|
+
const subscribeSchema = z.object({
|
|
10
|
+
subscription: z.object({
|
|
11
|
+
endpoint: z.url().max(2048),
|
|
12
|
+
keys: z.object({
|
|
13
|
+
p256dh: z.string().min(1).max(512),
|
|
14
|
+
auth: z.string().min(1).max(512),
|
|
15
|
+
}),
|
|
16
|
+
}),
|
|
17
|
+
label: z.string().max(120).optional(),
|
|
18
|
+
});
|
|
19
|
+
const unsubscribeSchema = z.object({
|
|
20
|
+
endpoint: z.url().max(2048),
|
|
21
|
+
});
|
|
22
|
+
export function createPushRoutes(deps) {
|
|
23
|
+
const { sender } = deps;
|
|
24
|
+
return new Hono()
|
|
25
|
+
.get("/push/public-key", (c) => {
|
|
26
|
+
try {
|
|
27
|
+
return c.json({ publicKey: sender.publicKey() });
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
return c.json({ error: err instanceof Error ? err.message : "Push unavailable" }, 500);
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
.get("/push/subscriptions", (c) => {
|
|
34
|
+
try {
|
|
35
|
+
// Endpoints are capability URLs — list only metadata.
|
|
36
|
+
return c.json({
|
|
37
|
+
subscriptions: sender.subscriptions().map((s) => ({
|
|
38
|
+
label: s.label,
|
|
39
|
+
createdAt: s.createdAt,
|
|
40
|
+
lastUsedAt: s.lastUsedAt,
|
|
41
|
+
// Enough for the client to recognize its own registration.
|
|
42
|
+
endpointHash: hashEndpoint(s.endpoint),
|
|
43
|
+
})),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to list" }, 500);
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
.post("/push/subscribe", async (c) => {
|
|
51
|
+
try {
|
|
52
|
+
const body = subscribeSchema.parse(await c.req.json());
|
|
53
|
+
sender.subscribe(body.subscription, body.label);
|
|
54
|
+
return c.json({ ok: true });
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
return c.json({ error: err instanceof Error ? err.message : "Bad subscription" }, 400);
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
.post("/push/unsubscribe", async (c) => {
|
|
61
|
+
try {
|
|
62
|
+
const body = unsubscribeSchema.parse(await c.req.json());
|
|
63
|
+
return c.json({ removed: sender.unsubscribe(body.endpoint) });
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
return c.json({ error: err instanceof Error ? err.message : "Bad request" }, 400);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function hashEndpoint(endpoint) {
|
|
71
|
+
return new Bun.CryptoHasher("sha256").update(endpoint).digest("hex").slice(0, 16);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=push.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/routes/push.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,QAAQ,EAAE,eAAe,CAAC;IAC1B,EAAE,EAAE,QAAQ,CAAC;CACd,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,QAAQ,EAAE,eAAe,CAAC;IAC1B,EAAE,EAAE,QAAQ,CAAC;CACd,GAAG,IAAI,CAoEP"}
|
package/dist/routes/sessions.js
CHANGED
|
@@ -11,10 +11,26 @@ export function createSessionRoutes(deps) {
|
|
|
11
11
|
.get("/sessions", async (c) => {
|
|
12
12
|
try {
|
|
13
13
|
const backends = await registry.getBackends();
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
// The catalog's accounting (total_cost_usd, num_turns) was write-only
|
|
15
|
+
// for years on the default backend, whose listSessions hardcodes
|
|
16
|
+
// zeros — merge the stored numbers in so the drawer's cost renders
|
|
17
|
+
// from what the server actually recorded.
|
|
18
|
+
const accounting = new Map(db
|
|
19
|
+
.query("SELECT id, total_cost_usd AS cost, num_turns AS turns FROM sessions")
|
|
20
|
+
.all().map((r) => [r.id, r]));
|
|
21
|
+
const sessions = (await Promise.all(backends.map(async (backend) => (await backend.listSessions()).map((session) => {
|
|
22
|
+
const stored = accounting.get(session.id);
|
|
23
|
+
return {
|
|
24
|
+
...session,
|
|
25
|
+
...(stored?.cost && session.totalCostUsd === 0
|
|
26
|
+
? { totalCostUsd: stored.cost }
|
|
27
|
+
: {}),
|
|
28
|
+
...(stored?.turns && session.numTurns === 0
|
|
29
|
+
? { numTurns: stored.turns }
|
|
30
|
+
: {}),
|
|
31
|
+
backendId: backend.id,
|
|
32
|
+
};
|
|
33
|
+
}))))
|
|
18
34
|
.flat()
|
|
19
35
|
.sort((a, b) => b.lastActiveAt - a.lastActiveAt);
|
|
20
36
|
return c.json({ sessions });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,MAAM,UAAU,mBAAmB,CAAC,IAGnC;IACC,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;IAE9B,SAAS,kBAAkB,CAAC,SAAiB;QAC3C,MAAM,GAAG,GAAG,EAAE;aACX,KAAK,CAAC,2DAA2D,CAAC;aAClE,GAAG,CAAC,SAAS,CAAwC,CAAC;QACzD,OAAO,GAAG,EAAE,SAAS,IAAI,IAAI,CAAC;IAChC,CAAC;IAED,OAAO,IAAI,IAAI,EAAE;SAChB,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC5B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;YAC9C,MAAM,QAAQ,GAAG,CACf,MAAM,OAAO,CAAC,GAAG,CACf,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAC7B,CAAC,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"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"}
|
package/dist/ws/bridge.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { BackendBridge } from "@schlessera/brain-ui-sdk/server";
|
|
2
2
|
import type { RunningTurn } from "./turns.js";
|
|
3
3
|
import type { WsHost } from "./host.js";
|
|
4
|
+
import type { TurnRecorder } from "../activity/recorder.js";
|
|
4
5
|
/** Build the per-turn bridge the backend drives. */
|
|
5
|
-
export declare function makeBridge(host: WsHost, turn: RunningTurn, promptText: string, backendId: string): BackendBridge;
|
|
6
|
+
export declare function makeBridge(host: WsHost, turn: RunningTurn, promptText: string, backendId: string, recorder?: TurnRecorder): BackendBridge;
|
|
6
7
|
export declare function emitTurnError(host: WsHost, turn: RunningTurn, err: unknown): void;
|
|
7
8
|
//# sourceMappingURL=bridge.d.ts.map
|
package/dist/ws/bridge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/ws/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/ws/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EAId,MAAM,iCAAiC,CAAC;AAGzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D,oDAAoD;AACpD,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,WAAW,EACjB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,YAAY,GACtB,aAAa,CAgLf;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,OAAO,GAAG,IAAI,CAwBjF"}
|
package/dist/ws/bridge.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { BackendBusyError, BackendRequestError } from "@schlessera/brain-ui-sdk/server";
|
|
2
2
|
import { withTurnScope } from "./frames.js";
|
|
3
3
|
/** Build the per-turn bridge the backend drives. */
|
|
4
|
-
export function makeBridge(host, turn, promptText, backendId) {
|
|
4
|
+
export function makeBridge(host, turn, promptText, backendId, recorder) {
|
|
5
5
|
const { coordinator, catalog } = host;
|
|
6
6
|
// Capture the turn identity at construction: the slot's turnId is re-minted
|
|
7
7
|
// for each queued follow-up, and a backend can still emit late frames
|
|
8
8
|
// through this bridge after its startTurn resolved. Stamping from the live
|
|
9
9
|
// field would attribute those to the NEXT turn.
|
|
10
10
|
const turnId = turn.turnId;
|
|
11
|
+
const queryActivity = host.activity?.query;
|
|
11
12
|
return {
|
|
12
13
|
emit: (message) => {
|
|
13
14
|
let msg = message;
|
|
@@ -24,6 +25,12 @@ export function makeBridge(host, turn, promptText, backendId) {
|
|
|
24
25
|
// later fails or is cancelled must not leave an unowned transcript.
|
|
25
26
|
catalog.persistSessionStub(msg.sessionId, promptText, turn.providerId, backendId);
|
|
26
27
|
}
|
|
28
|
+
// Persist-then-emit: the span write commits before the frame goes out,
|
|
29
|
+
// so a subscriber's snapshot can never be behind what it just saw live.
|
|
30
|
+
// Late frames through a previous turn's bridge stay un-recorded — the
|
|
31
|
+
// recorder belongs to ONE turn identity.
|
|
32
|
+
if (turn.turnId === turnId)
|
|
33
|
+
recorder?.observeFrame(msg);
|
|
27
34
|
host.sendToClients(withTurnScope(msg, turn, turnId));
|
|
28
35
|
if (msg.type === "result") {
|
|
29
36
|
// Only the live turn's own result may set its disposition — a late
|
|
@@ -63,9 +70,27 @@ export function makeBridge(host, turn, promptText, backendId) {
|
|
|
63
70
|
resolve({ behavior: "deny", message: "Duplicate tool-approval id" });
|
|
64
71
|
return;
|
|
65
72
|
}
|
|
66
|
-
|
|
73
|
+
// The decision stamps the wait/execution boundary on the tool span
|
|
74
|
+
// (grant) or lands the denied outcome (deny) before the backend's
|
|
75
|
+
// own error tool_result can mislabel it — write-once protects it.
|
|
76
|
+
const recorded = (decision) => {
|
|
77
|
+
recorder?.onApprovalDecision(req.toolUseId, decision.behavior === "allow");
|
|
78
|
+
resolve(decision);
|
|
79
|
+
};
|
|
80
|
+
coordinator.pendingApprovals.set(req.toolUseId, {
|
|
81
|
+
turn,
|
|
82
|
+
turnId,
|
|
83
|
+
request: req,
|
|
84
|
+
resolve: recorded,
|
|
85
|
+
});
|
|
67
86
|
});
|
|
68
87
|
},
|
|
88
|
+
...(recorder
|
|
89
|
+
? { activity: (event) => recorder.observeActivity(event) }
|
|
90
|
+
: {}),
|
|
91
|
+
...(queryActivity
|
|
92
|
+
? { queryActivity: async (query) => queryActivity(query) }
|
|
93
|
+
: {}),
|
|
69
94
|
askUser: (requestId, questions) => {
|
|
70
95
|
host.sendToClients(withTurnScope({ type: "ask_user_request", requestId, questions }, turn, turnId));
|
|
71
96
|
host.sendToClients(withTurnScope({ type: "status", status: "tool_executing", detail: "Waiting for your input" }, turn, turnId));
|
package/dist/ws/bridge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/ws/bridge.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/ws/bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/ws/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,SAAS,EAAE,MAAM,UAAU,CAAC;AA6CvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM;iBAStB,KAAK,MAAM,SAAS;
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/ws/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,SAAS,EAAE,MAAM,UAAU,CAAC;AA6CvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM;iBAStB,KAAK,MAAM,SAAS;mBAkFxB,YAAY,MAAM,SAAS;iBA6D7B,UAAU,MAAM,SAAS;EAyBzC;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM;;GAE3C"}
|
package/dist/ws/connection.js
CHANGED
|
@@ -53,7 +53,14 @@ export function createWsHandlers(host) {
|
|
|
53
53
|
host.sendMessage(ws, {
|
|
54
54
|
type: "server_hello",
|
|
55
55
|
protocolRev: PROTOCOL_REV,
|
|
56
|
-
capabilities: {
|
|
56
|
+
capabilities: {
|
|
57
|
+
multiSession: true,
|
|
58
|
+
askUser: true,
|
|
59
|
+
location: true,
|
|
60
|
+
// Advertised only when this host records activity — a client on an
|
|
61
|
+
// activity-less host knows subscribing would be pointless.
|
|
62
|
+
...(host.activity ? { activity: true } : {}),
|
|
63
|
+
},
|
|
57
64
|
});
|
|
58
65
|
// Snapshot-on-connect only for the single-running-session case (backward
|
|
59
66
|
// compatible). With zero or several running sessions the client rehydrates
|
|
@@ -177,6 +184,7 @@ export function createWsHandlers(host) {
|
|
|
177
184
|
host.reportAbnormalClose(code);
|
|
178
185
|
}
|
|
179
186
|
host.clients.remove(ws);
|
|
187
|
+
host.activity?.stream.dropConnection(ws);
|
|
180
188
|
// Turns keep running in the background. Once the LAST client leaves,
|
|
181
189
|
// reject only the requests that need a live client RIGHT NOW (location,
|
|
182
190
|
// mask). Approvals and ask-user cards survive the disconnect and are
|