@a-t-h-i/bot-lobby 0.6.44 → 0.6.46

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 (38) hide show
  1. package/README.md +15 -4
  2. package/package.json +1 -6
  3. package/src/execution/agent-runner.ts +0 -2
  4. package/src/execution/delegation.ts +1 -2
  5. package/src/execution/pi-runner.ts +2 -6
  6. package/src/execution/task-cancellation.ts +27 -0
  7. package/src/index.ts +0 -3
  8. package/src/lobby/host.ts +5 -12
  9. package/src/lobby/planner.ts +1 -6
  10. package/src/lobby/prompts.ts +4 -7
  11. package/src/lobby/quickfix.ts +0 -2
  12. package/src/lobby/runtime.ts +1 -5
  13. package/src/lobby/service.ts +77 -7
  14. package/src/lobby/topics.ts +0 -1
  15. package/src/pi/tools.ts +2 -2
  16. package/src/state/persistence.ts +26 -1
  17. package/src/webui/api/index.ts +13 -45
  18. package/src/webui/api/tasks.ts +39 -2
  19. package/src/webui/dev/fake-service.ts +0 -57
  20. package/src/webui/dev/fixtures.ts +0 -6
  21. package/src/webui/palette-core.ts +233 -2
  22. package/src/webui/protocol.ts +6 -103
  23. package/src/workflow/workflow.ts +16 -20
  24. package/webui/dist/assets/index-BJ1fEle9.js +110 -0
  25. package/webui/dist/assets/index-BdtiIB9L.css +2 -0
  26. package/webui/dist/build.json +39 -107
  27. package/webui/dist/index.html +2 -2
  28. package/src/excalidraw/check.ts +0 -31
  29. package/src/excalidraw/client.ts +0 -334
  30. package/src/excalidraw/room.ts +0 -118
  31. package/src/excalidraw/scene.ts +0 -746
  32. package/src/excalidraw/sessions.ts +0 -302
  33. package/src/excalidraw/tools.ts +0 -223
  34. package/src/lobby/models/metrics.ts +0 -14
  35. package/src/webui/api/excalidraw.ts +0 -105
  36. package/src/webui/api/metrics.ts +0 -96
  37. package/webui/dist/assets/index-C0T8aK16.js +0 -110
  38. package/webui/dist/assets/index-XtSiJAAR.css +0 -2
@@ -1,96 +0,0 @@
1
- /**
2
- * The Metrics tab over HTTP: the KPI tiles, the per-model groups, where the
3
- * time goes, and what the classifier did — the same figures the terminal
4
- * tab draws, as data. Search narrows runs exactly like the tab's `/`.
5
- */
6
- import { aggregateMetrics, collectMetrics, sortGroups, summarizeClassifier, taskStats, taskTimesByModel, type MetricRecord } from "../../state/metrics.ts";
7
- import { filterRecords } from "../../lobby/models/metrics.ts";
8
- import type { Api, MetricsData } from "../protocol.ts";
9
- import { fail, type ApiContext } from "./index.ts";
10
-
11
- function timed(records: readonly MetricRecord[]): MetricRecord[] {
12
- return records.filter((record) => record.status !== "cancelled" && record.durationMs > 0);
13
- }
14
-
15
- /** The KPI row as data: runs, success, average run, cost, tasks. */
16
- function tilesOf(records: readonly MetricRecord[], stats: ReturnType<typeof taskStats>): MetricsData["tiles"] {
17
- const done = timed(records);
18
- const ok = records.filter((record) => record.status === "success").length;
19
- const cost = records.reduce((sum, record) => sum + (record.cost ?? 0), 0);
20
- const avg = done.length > 0 ? done.reduce((sum, record) => sum + record.durationMs, 0) / done.length : 0;
21
- const sorted = done.map((record) => record.durationMs).sort((a, b) => a - b);
22
- const p90 = sorted.length > 0 ? sorted[Math.min(sorted.length - 1, Math.ceil(0.9 * sorted.length) - 1)]! : 0;
23
- return {
24
- runs: records.length,
25
- successes: ok,
26
- stalls: records.filter((record) => record.stalled || record.status === "timeout").length,
27
- avgMs: avg,
28
- p90Ms: p90,
29
- cost,
30
- completed: stats.completed,
31
- active: stats.active,
32
- avgCompleteMs: stats.avgCompleteMs,
33
- };
34
- }
35
-
36
- /** Each agent's share of all run time, longest first. */
37
- function shareOf(records: readonly MetricRecord[]): MetricsData["timeShare"]["byAgent"] {
38
- const byAgent = new Map<string, { runs: number; ms: number }>();
39
- for (const record of timed(records)) {
40
- const entry = byAgent.get(record.agent) ?? { runs: 0, ms: 0 };
41
- entry.runs += 1;
42
- entry.ms += record.durationMs;
43
- byAgent.set(record.agent, entry);
44
- }
45
- const total = [...byAgent.values()].reduce((sum, entry) => sum + entry.ms, 0);
46
- return [...byAgent.entries()]
47
- .sort((a, b) => b[1].ms - a[1].ms)
48
- .map(([agent, entry]) => ({ agent, runs: entry.runs, ms: entry.ms, share: total > 0 ? entry.ms / total : 0 }));
49
- }
50
-
51
- /** The dashboard figures for one grouping and search. */
52
- export function metricsGet(body: Api["metrics.get"]["request"], ctx: ApiContext): MetricsData {
53
- const { from, to } = body;
54
- const validDate = (value: string) => /^\d{4}-\d{2}-\d{2}$/.test(value) && Number.isFinite(Date.parse(value)) && new Date(value).toISOString().slice(0, 10) === value;
55
- if ((from === undefined) !== (to === undefined) || (from !== undefined && (!validDate(from) || !validDate(to!) || from > to!))) {
56
- fail(400, "bad_request", "Choose a valid start and end date, with the start on or before the end.");
57
- }
58
- let formatter: Intl.DateTimeFormat;
59
- try {
60
- formatter = new Intl.DateTimeFormat("en", { timeZone: body.timeZone ?? "UTC", year: "numeric", month: "2-digit", day: "2-digit" });
61
- } catch {
62
- fail(400, "bad_request", "Choose a valid time zone.");
63
- }
64
- const dayOf = (timestamp: string) => {
65
- const date = new Date(timestamp);
66
- if (!Number.isFinite(date.getTime())) return "";
67
- const parts = formatter.formatToParts(date);
68
- return ["year", "month", "day"].map((part) => parts.find((item) => item.type === part)!.value).join("-");
69
- };
70
- const inRange = (timestamp: string) => !from || (dayOf(timestamp) >= from && dayOf(timestamp) <= to!);
71
- const allTasks = ctx.service.tasks();
72
- const tasks = allTasks.filter((task) => inRange(task.state === "completed" ? task.updatedAt : task.createdAt));
73
- const allRecords = filterRecords(collectMetrics(ctx.service.metrics(), allTasks), body.query);
74
- const records = allRecords.filter((record) => inRange(record.startedAt));
75
- const stats = taskStats(tasks);
76
- const classifier = summarizeClassifier((ctx.service.classifierMetrics?.() ?? []).filter((record) => inRange(record.startedAt)), records);
77
- const daily = new Map<string, MetricsData["daily"][number]>();
78
- for (const record of records) {
79
- const date = dayOf(record.startedAt);
80
- if (!date) continue;
81
- const entry = daily.get(date) ?? { date, runs: 0, successes: 0, cost: 0 };
82
- entry.runs += 1;
83
- entry.successes += Number(record.status === "success");
84
- entry.cost += record.cost ?? 0;
85
- daily.set(date, entry);
86
- }
87
- // Include range edges without allocating an entry for every empty day.
88
- for (const date of [from, to]) if (date && !daily.has(date)) daily.set(date, { date, runs: 0, successes: 0, cost: 0 });
89
- return {
90
- tiles: tilesOf(records, stats),
91
- daily: [...daily.values()].sort((a, b) => a.date.localeCompare(b.date)),
92
- groups: sortGroups(aggregateMetrics(records, body.groupBy), "runs"),
93
- timeShare: { byAgent: shareOf(records), taskTimes: taskTimesByModel(tasks, allRecords) },
94
- ...(classifier ? { classifier } : {}),
95
- };
96
- }