crewly 1.20.305 → 1.20.307
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/config/hooks/agent-status/report.sh +39 -1
- package/dist/backend/backend/src/constants.d.ts +54 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +54 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.d.ts +2 -1
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.js +18 -1
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/board/board.controller.d.ts +23 -0
- package/dist/backend/backend/src/controllers/board/board.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/board/board.controller.js +48 -0
- package/dist/backend/backend/src/controllers/board/board.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/board/board.routes.d.ts +15 -0
- package/dist/backend/backend/src/controllers/board/board.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/board/board.routes.js +21 -0
- package/dist/backend/backend/src/controllers/board/board.routes.js.map +1 -0
- package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.js +2 -0
- package/dist/backend/backend/src/controllers/browser/browser.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.js +5 -0
- package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.js +3 -0
- package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts +9 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +46 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +3 -0
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/board/board-activity.normalizer.d.ts +85 -0
- package/dist/backend/backend/src/services/board/board-activity.normalizer.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/board-activity.normalizer.js +241 -0
- package/dist/backend/backend/src/services/board/board-activity.normalizer.js.map +1 -0
- package/dist/backend/backend/src/services/board/board-activity.tracker.d.ts +154 -0
- package/dist/backend/backend/src/services/board/board-activity.tracker.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/board-activity.tracker.js +322 -0
- package/dist/backend/backend/src/services/board/board-activity.tracker.js.map +1 -0
- package/dist/backend/backend/src/services/board/board-outcome-phrases.d.ts +43 -0
- package/dist/backend/backend/src/services/board/board-outcome-phrases.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/board-outcome-phrases.js +76 -0
- package/dist/backend/backend/src/services/board/board-outcome-phrases.js.map +1 -0
- package/dist/backend/backend/src/services/board/board-push.service.d.ts +114 -0
- package/dist/backend/backend/src/services/board/board-push.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/board-push.service.js +312 -0
- package/dist/backend/backend/src/services/board/board-push.service.js.map +1 -0
- package/dist/backend/backend/src/services/board/board-redact.d.ts +90 -0
- package/dist/backend/backend/src/services/board/board-redact.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/board-redact.js +359 -0
- package/dist/backend/backend/src/services/board/board-redact.js.map +1 -0
- package/dist/backend/backend/src/services/board/board-snapshot.builder.d.ts +176 -0
- package/dist/backend/backend/src/services/board/board-snapshot.builder.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/board-snapshot.builder.js +342 -0
- package/dist/backend/backend/src/services/board/board-snapshot.builder.js.map +1 -0
- package/dist/backend/backend/src/services/board/board-usage.d.ts +20 -0
- package/dist/backend/backend/src/services/board/board-usage.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/board-usage.js +82 -0
- package/dist/backend/backend/src/services/board/board-usage.js.map +1 -0
- package/dist/backend/backend/src/services/board/board.service.d.ts +60 -0
- package/dist/backend/backend/src/services/board/board.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/board.service.js +82 -0
- package/dist/backend/backend/src/services/board/board.service.js.map +1 -0
- package/dist/backend/backend/src/services/board/board.sources.d.ts +25 -0
- package/dist/backend/backend/src/services/board/board.sources.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/board.sources.js +293 -0
- package/dist/backend/backend/src/services/board/board.sources.js.map +1 -0
- package/dist/backend/backend/src/services/board/board.types.d.ts +117 -0
- package/dist/backend/backend/src/services/board/board.types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/board.types.js +8 -0
- package/dist/backend/backend/src/services/board/board.types.js.map +1 -0
- package/dist/backend/backend/src/services/google/google-reauth-notifier.service.d.ts +13 -0
- package/dist/backend/backend/src/services/google/google-reauth-notifier.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/google-reauth-notifier.service.js +15 -0
- package/dist/backend/backend/src/services/google/google-reauth-notifier.service.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.js +2 -2
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.d.ts +9 -0
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.js +61 -5
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts +2 -0
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.js.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-cloud.client.d.ts +6 -0
- package/dist/backend/backend/src/services/team-move/team-move-cloud.client.d.ts.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-cloud.client.js +22 -1
- package/dist/backend/backend/src/services/team-move/team-move-cloud.client.js.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-driver.service.js +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-driver.service.js.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-importer.d.ts +15 -1
- package/dist/backend/backend/src/services/team-move/team-move-importer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-importer.js +38 -4
- package/dist/backend/backend/src/services/team-move/team-move-importer.js.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-runtime.d.ts.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-runtime.js +22 -1
- package/dist/backend/backend/src/services/team-move/team-move-runtime.js.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move.types.d.ts +19 -5
- package/dist/backend/backend/src/services/team-move/team-move.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move.types.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +54 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +54 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts +2 -0
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts.map +1 -1
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Board snapshot builder (crewly#1247): turns what the machine knows (teams,
|
|
3
|
+
* runtime turn state, WorkItems, tickets, decisions, the usage ledger and the
|
|
4
|
+
* live activity tracker) into the {@link BoardSnapshot} Cloud and the local
|
|
5
|
+
* dashboard show.
|
|
6
|
+
*
|
|
7
|
+
* Everything is read through {@link BoardSources}, so the builder is a pure
|
|
8
|
+
* function of its inputs and is tested with fixtures. A full build refreshes
|
|
9
|
+
* a cache (roster, usage, tasks, owner waits); the per-agent delta rows are
|
|
10
|
+
* built from that cache plus the live activity, so a delta never rescans the
|
|
11
|
+
* disk.
|
|
12
|
+
*
|
|
13
|
+
* Every text in the result went through {@link scrubText}.
|
|
14
|
+
*
|
|
15
|
+
* @module services/board/board-snapshot.builder
|
|
16
|
+
*/
|
|
17
|
+
import { BOARD_CONSTANTS } from '../../constants.js';
|
|
18
|
+
import { scrubText } from './board-redact.js';
|
|
19
|
+
import { resultOf, summarizeResults } from './board-outcome-phrases.js';
|
|
20
|
+
const C = BOARD_CONSTANTS;
|
|
21
|
+
/** Local midnight of `now`. */
|
|
22
|
+
export function startOfLocalDay(now) {
|
|
23
|
+
const d = new Date(now);
|
|
24
|
+
d.setHours(0, 0, 0, 0);
|
|
25
|
+
return d.getTime();
|
|
26
|
+
}
|
|
27
|
+
const iso = (ms) => new Date(ms).toISOString();
|
|
28
|
+
const msOf = (s) => (s ? Date.parse(s) : NaN);
|
|
29
|
+
/** Hours/minutes in words for stuck reasons. */
|
|
30
|
+
function age(ms) {
|
|
31
|
+
const m = Math.max(1, Math.round(ms / 60_000));
|
|
32
|
+
if (m < 60)
|
|
33
|
+
return `${m} min`;
|
|
34
|
+
const h = Math.round(m / 60);
|
|
35
|
+
return h < 48 ? `${h} h` : `${Math.round(h / 24)} days`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Builds board snapshots and per-agent rows.
|
|
39
|
+
*/
|
|
40
|
+
export class BoardSnapshotBuilder {
|
|
41
|
+
sources;
|
|
42
|
+
tracker;
|
|
43
|
+
clock;
|
|
44
|
+
cache = { roster: new Map(), usage: null, tasks: new Map(), waits: new Map() };
|
|
45
|
+
/**
|
|
46
|
+
* @param sources - Everything the board reads
|
|
47
|
+
* @param tracker - Live activity
|
|
48
|
+
* @param clock - Clock (tests)
|
|
49
|
+
*/
|
|
50
|
+
constructor(sources, tracker, clock = Date.now) {
|
|
51
|
+
this.sources = sources;
|
|
52
|
+
this.tracker = tracker;
|
|
53
|
+
this.clock = clock;
|
|
54
|
+
}
|
|
55
|
+
/** Whether a full build has filled the cache. */
|
|
56
|
+
get primed() {
|
|
57
|
+
return this.cache.roster.size > 0;
|
|
58
|
+
}
|
|
59
|
+
/** This machine's identity. */
|
|
60
|
+
identity() {
|
|
61
|
+
return this.sources.identity();
|
|
62
|
+
}
|
|
63
|
+
/** Sessions known from the last full build. */
|
|
64
|
+
knownSessions() {
|
|
65
|
+
return [...this.cache.roster.keys()];
|
|
66
|
+
}
|
|
67
|
+
async safe(read, fallback) {
|
|
68
|
+
try {
|
|
69
|
+
return await read();
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return fallback;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build the full snapshot and refresh the cache.
|
|
77
|
+
*
|
|
78
|
+
* @returns The snapshot
|
|
79
|
+
*/
|
|
80
|
+
async build() {
|
|
81
|
+
const now = this.clock();
|
|
82
|
+
const dayStart = startOfLocalDay(now);
|
|
83
|
+
const [identity, version, teams, workItems, tickets, decisions, holds, usage, active] = await Promise.all([
|
|
84
|
+
this.sources.identity(),
|
|
85
|
+
this.safe(() => this.sources.version(), 'unknown'),
|
|
86
|
+
this.safe(() => this.sources.teams(), []),
|
|
87
|
+
this.safe(() => this.sources.workItems(), []),
|
|
88
|
+
this.safe(() => this.sources.tickets(), []),
|
|
89
|
+
this.safe(() => this.sources.decisions(), []),
|
|
90
|
+
this.safe(() => this.sources.holds(), []),
|
|
91
|
+
this.safe(() => this.sources.usage(now), null),
|
|
92
|
+
this.safe(() => this.sources.activeWork(), new Map()),
|
|
93
|
+
]);
|
|
94
|
+
const roster = new Map();
|
|
95
|
+
for (const team of teams)
|
|
96
|
+
for (const member of team.members)
|
|
97
|
+
roster.set(member.session, { team, member });
|
|
98
|
+
const waits = new Map();
|
|
99
|
+
for (const d of decisions)
|
|
100
|
+
if (d.asker && !waits.has(d.asker))
|
|
101
|
+
waits.set(d.asker, d);
|
|
102
|
+
const tasks = new Map(usage?.taskOf ?? []);
|
|
103
|
+
for (const [session, task] of active)
|
|
104
|
+
tasks.set(session, task);
|
|
105
|
+
this.cache = { roster, usage, tasks, waits };
|
|
106
|
+
const teamName = (id, agent) => {
|
|
107
|
+
const byId = id ? teams.find((t) => t.teamId === id)?.name : undefined;
|
|
108
|
+
return byId ?? (agent ? roster.get(agent)?.team.name : undefined);
|
|
109
|
+
};
|
|
110
|
+
const agentName = (session) => (session ? (roster.get(session)?.member.name ?? undefined) : undefined);
|
|
111
|
+
return {
|
|
112
|
+
v: 1,
|
|
113
|
+
instanceId: identity.instanceId,
|
|
114
|
+
machineName: scrubText(identity.machineName, 60) || 'This machine',
|
|
115
|
+
crewlyVersion: scrubText(version, 30) || 'unknown',
|
|
116
|
+
generatedAt: iso(now),
|
|
117
|
+
outcomes: {
|
|
118
|
+
...this.doneToday(tickets, workItems, dayStart, teamName, agentName),
|
|
119
|
+
waitingOnOwner: this.waiting(decisions, holds, tickets, teamName, agentName),
|
|
120
|
+
stuck: this.stuck(workItems, tickets, roster, now, teamName, agentName),
|
|
121
|
+
spend: usage?.spend ?? { todayUsd: 0, weekUsd: 0, todayTokens: 0, weekTokens: 0 },
|
|
122
|
+
},
|
|
123
|
+
teams: teams.map((t) => ({
|
|
124
|
+
teamId: t.teamId,
|
|
125
|
+
name: scrubText(t.name, 60) || t.teamId,
|
|
126
|
+
...(t.paused ? { paused: true } : {}),
|
|
127
|
+
agents: t.members.map((m) => this.row(m, now)),
|
|
128
|
+
})),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Rows for some agents, from the cache and the live activity. No disk or
|
|
133
|
+
* network reads.
|
|
134
|
+
*
|
|
135
|
+
* @param sessions - Sessions to build
|
|
136
|
+
* @returns Rows of the known sessions
|
|
137
|
+
*/
|
|
138
|
+
rows(sessions) {
|
|
139
|
+
const now = this.clock();
|
|
140
|
+
const out = [];
|
|
141
|
+
for (const session of new Set(sessions)) {
|
|
142
|
+
const entry = this.cache.roster.get(session);
|
|
143
|
+
if (!entry)
|
|
144
|
+
continue;
|
|
145
|
+
out.push({ ...this.row(entry.member, now), teamId: entry.team.teamId });
|
|
146
|
+
}
|
|
147
|
+
return out;
|
|
148
|
+
}
|
|
149
|
+
// -------------------------------------------------------------------------
|
|
150
|
+
// Agent rows
|
|
151
|
+
// -------------------------------------------------------------------------
|
|
152
|
+
row(m, now) {
|
|
153
|
+
const turn = this.safeSync(() => this.sources.turnState(m.session, now), 'unknown');
|
|
154
|
+
const working = turn === 'working' || (turn === 'unknown' && m.workingStatus === 'in_progress' && m.agentStatus !== 'inactive');
|
|
155
|
+
const decision = this.cache.waits.get(m.session);
|
|
156
|
+
const hookWaiting = this.safeSync(() => this.sources.waitingOnHuman(m.session), false);
|
|
157
|
+
const error = this.safeSync(() => this.sources.errorOf?.(m.session) ?? null, null);
|
|
158
|
+
const queued = this.safeSync(() => this.sources.queuedFor(m.session), 0);
|
|
159
|
+
const stopped = m.agentStatus === 'inactive' || m.agentStatus === 'suspended';
|
|
160
|
+
const live = this.tracker.live(m.session, working && !stopped, now);
|
|
161
|
+
const trackerWaiting = live.activity?.type === 'waiting_owner';
|
|
162
|
+
let state;
|
|
163
|
+
if (stopped)
|
|
164
|
+
state = 'stopped';
|
|
165
|
+
else if (error)
|
|
166
|
+
state = 'error';
|
|
167
|
+
else if (hookWaiting || trackerWaiting || (decision && !working))
|
|
168
|
+
state = 'waiting';
|
|
169
|
+
else if (working)
|
|
170
|
+
state = 'working';
|
|
171
|
+
else if (queued > 0)
|
|
172
|
+
state = 'queued';
|
|
173
|
+
else
|
|
174
|
+
state = 'idle';
|
|
175
|
+
let activity = live.activity ?? undefined;
|
|
176
|
+
if (state === 'waiting' && activity?.type !== 'waiting_owner') {
|
|
177
|
+
const what = decision ? scrubText(decision.title, 100) : 'a reply to its prompt';
|
|
178
|
+
activity = { type: 'waiting_owner', detail: `Waiting for the owner: ${what}`.slice(0, C.MAX_TEXT), since: decision?.createdAt ?? iso(now) };
|
|
179
|
+
}
|
|
180
|
+
if (stopped || state === 'idle' || state === 'queued')
|
|
181
|
+
activity = undefined;
|
|
182
|
+
if (state === 'error' && error)
|
|
183
|
+
activity = { type: 'other', detail: scrubText(error), since: iso(now) };
|
|
184
|
+
const task = this.cache.tasks.get(m.session);
|
|
185
|
+
const usage = this.cache.usage?.perAgent.get(m.session);
|
|
186
|
+
const row = {
|
|
187
|
+
session: m.session,
|
|
188
|
+
name: scrubText(m.name, 60) || m.session,
|
|
189
|
+
role: scrubText(m.role, 40),
|
|
190
|
+
runtime: scrubText(m.runtime, 30),
|
|
191
|
+
...(m.model ? { model: scrubText(m.model, 60) } : {}),
|
|
192
|
+
state,
|
|
193
|
+
...(activity ? { activity } : {}),
|
|
194
|
+
...(task && !stopped ? { task: { ...(task.id ? { id: task.id } : {}), title: scrubText(task.title), since: task.since } } : {}),
|
|
195
|
+
...(live.lastAction ? { lastAction: live.lastAction } : {}),
|
|
196
|
+
...(usage ? { todayUsd: round4(usage.todayUsd), todayTokens: Math.round(usage.todayTokens) } : {}),
|
|
197
|
+
};
|
|
198
|
+
return row;
|
|
199
|
+
}
|
|
200
|
+
safeSync(read, fallback) {
|
|
201
|
+
try {
|
|
202
|
+
return read();
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return fallback;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// -------------------------------------------------------------------------
|
|
209
|
+
// Outcomes
|
|
210
|
+
// -------------------------------------------------------------------------
|
|
211
|
+
doneToday(tickets, workItems, dayStart, teamName, agentName) {
|
|
212
|
+
const items = [];
|
|
213
|
+
for (const t of tickets) {
|
|
214
|
+
if (t.column !== 'done')
|
|
215
|
+
continue;
|
|
216
|
+
const at = msOf(t.completedAt ?? t.updatedAt);
|
|
217
|
+
if (!Number.isFinite(at) || at < dayStart)
|
|
218
|
+
continue;
|
|
219
|
+
const title = scrubText(t.title);
|
|
220
|
+
items.push({
|
|
221
|
+
ticketId: t.label ?? t.id,
|
|
222
|
+
title,
|
|
223
|
+
result: resultOf(title, t.kind),
|
|
224
|
+
team: teamName(t.teamId, t.assignee) ?? 'Crewly',
|
|
225
|
+
...(agentName(t.assignee) ? { agent: agentName(t.assignee) } : {}),
|
|
226
|
+
at: iso(at),
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
// WorkItems that belong to no ticket (a ticket carries its own result, and the
|
|
230
|
+
// harness's own verify / follow-through / retry items are bookkeeping, not results)
|
|
231
|
+
const OWNER_FACING_TYPES = new Set(['delegate', 'project_task', 'review']);
|
|
232
|
+
const BOOKKEEPING_TITLE = /^(?:verify|follow[- ]through|retry\b|refresh standing|tl fallback|re-?verify|\[?auto|[A-Z][A-Z0-9]{1,6}-\d+\b)/i;
|
|
233
|
+
for (const w of workItems) {
|
|
234
|
+
if (w.status !== 'verified' && w.status !== 'done')
|
|
235
|
+
continue;
|
|
236
|
+
if (!OWNER_FACING_TYPES.has(w.type))
|
|
237
|
+
continue;
|
|
238
|
+
if (w.requestId || w.projectTaskId)
|
|
239
|
+
continue;
|
|
240
|
+
if (BOOKKEEPING_TITLE.test(w.title.trim()))
|
|
241
|
+
continue;
|
|
242
|
+
const at = msOf(w.completedAt ?? w.statusChangedAt);
|
|
243
|
+
if (!Number.isFinite(at) || at < dayStart)
|
|
244
|
+
continue;
|
|
245
|
+
const title = scrubText(w.title);
|
|
246
|
+
items.push({
|
|
247
|
+
title,
|
|
248
|
+
result: resultOf(title),
|
|
249
|
+
team: teamName(undefined, w.target) ?? 'Crewly',
|
|
250
|
+
...(agentName(w.target) ? { agent: agentName(w.target) } : {}),
|
|
251
|
+
at: iso(at),
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
items.sort((a, b) => Date.parse(b.at) - Date.parse(a.at));
|
|
255
|
+
return { doneTodaySummary: summarizeResults(items.map((i) => i.result)), doneToday: items.slice(0, C.MAX_DONE) };
|
|
256
|
+
}
|
|
257
|
+
waiting(decisions, holds, tickets, teamName, agentName) {
|
|
258
|
+
const out = [];
|
|
259
|
+
for (const d of decisions) {
|
|
260
|
+
out.push({
|
|
261
|
+
id: `decision:${d.id}`,
|
|
262
|
+
kind: d.kind,
|
|
263
|
+
title: scrubText(d.title) || 'A decision is waiting',
|
|
264
|
+
...(teamName(d.teamId, d.asker) ? { team: teamName(d.teamId, d.asker) } : {}),
|
|
265
|
+
...(agentName(d.asker) ? { agent: agentName(d.asker) } : {}),
|
|
266
|
+
since: d.createdAt,
|
|
267
|
+
action: { label: d.kind === 'approval' ? 'Approve' : 'Answer' },
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
for (const t of tickets) {
|
|
271
|
+
if (t.column !== 'to_review')
|
|
272
|
+
continue;
|
|
273
|
+
out.push({
|
|
274
|
+
id: `review:${t.id}`,
|
|
275
|
+
kind: 'review',
|
|
276
|
+
title: scrubText(t.label ? `${t.label} ${t.title}` : t.title),
|
|
277
|
+
...(teamName(t.teamId, t.assignee) ? { team: teamName(t.teamId, t.assignee) } : {}),
|
|
278
|
+
...(agentName(t.assignee) ? { agent: agentName(t.assignee) } : {}),
|
|
279
|
+
since: t.submittedAt ?? t.updatedAt,
|
|
280
|
+
action: { label: 'Review' },
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
for (const h of holds)
|
|
284
|
+
out.push({ ...h, title: scrubText(h.title) });
|
|
285
|
+
return out.sort((a, b) => Date.parse(a.since) - Date.parse(b.since)).slice(0, C.MAX_WAITING);
|
|
286
|
+
}
|
|
287
|
+
stuck(workItems, tickets, roster, now, teamName, agentName) {
|
|
288
|
+
const out = [];
|
|
289
|
+
const ownerWords = /owner|approv|sign[- ]?in|log ?in|credential|password|permission|reconnect|authori[sz]/i;
|
|
290
|
+
const add = (id, title, target, since, on, reason, teamId) => {
|
|
291
|
+
out.push({
|
|
292
|
+
id,
|
|
293
|
+
title: scrubText(title),
|
|
294
|
+
...(teamName(teamId, target) ? { team: teamName(teamId, target) } : {}),
|
|
295
|
+
...(agentName(target) ? { agent: agentName(target) } : {}),
|
|
296
|
+
since: iso(Number.isFinite(since) ? since : now),
|
|
297
|
+
on,
|
|
298
|
+
reason: scrubText(reason),
|
|
299
|
+
});
|
|
300
|
+
};
|
|
301
|
+
for (const w of workItems) {
|
|
302
|
+
const changed = msOf(w.statusChangedAt) || msOf(w.createdAt);
|
|
303
|
+
if (w.status === 'blocked') {
|
|
304
|
+
const reason = w.blockedReason ?? 'Blocked';
|
|
305
|
+
const on = w.blockSource === 'explicit' ? (ownerWords.test(reason) ? 'owner' : 'agent') : 'system';
|
|
306
|
+
add(`wi:${w.id}`, w.title, w.target, changed, on, reason);
|
|
307
|
+
}
|
|
308
|
+
else if (w.status === 'escalated') {
|
|
309
|
+
add(`wi:${w.id}`, w.title, w.target, changed, 'agent', 'Escalated and not resolved yet');
|
|
310
|
+
}
|
|
311
|
+
else if (w.status === 'failed') {
|
|
312
|
+
const at = msOf(w.completedAt) || changed;
|
|
313
|
+
if (now - at <= C.STUCK_FAILED_MAX_AGE_MS)
|
|
314
|
+
add(`wi:${w.id}`, w.title, w.target, at, 'agent', `Failed${w.error ? `: ${w.error}` : ''}`);
|
|
315
|
+
}
|
|
316
|
+
else if (w.status === 'queued') {
|
|
317
|
+
const waited = now - msOf(w.createdAt);
|
|
318
|
+
const scheduledLater = msOf(w.scheduledAt) > now;
|
|
319
|
+
if (waited >= C.STUCK_QUEUED_MS && !scheduledLater) {
|
|
320
|
+
add(`wi:${w.id}`, w.title, w.target, msOf(w.createdAt), w.target ? 'agent' : 'system', `Waiting in the queue for ${age(waited)}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
else if (w.status === 'running') {
|
|
324
|
+
const ran = now - (msOf(w.startedAt) || changed);
|
|
325
|
+
if (ran >= C.STUCK_RUNNING_MS)
|
|
326
|
+
add(`wi:${w.id}`, w.title, w.target, msOf(w.startedAt) || changed, 'agent', `Running for ${age(ran)}`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
for (const t of tickets) {
|
|
330
|
+
if (t.column === 'blocked')
|
|
331
|
+
add(`ticket:${t.id}`, t.label ? `${t.label} ${t.title}` : t.title, t.assignee, msOf(t.updatedAt), 'agent', 'Ticket is blocked', t.teamId);
|
|
332
|
+
}
|
|
333
|
+
for (const session of roster.keys()) {
|
|
334
|
+
const stalled = this.safeSync(() => this.sources.stalledBackground(session, now), null);
|
|
335
|
+
if (stalled)
|
|
336
|
+
add(`bg:${session}`, stalled.description ?? 'Background task', session, stalled.since, 'agent', `Background task stopped making progress ${age(now - stalled.since)} ago`);
|
|
337
|
+
}
|
|
338
|
+
return out.sort((a, b) => Date.parse(a.since) - Date.parse(b.since)).slice(0, C.MAX_STUCK);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
const round4 = (n) => Math.round(n * 10_000) / 10_000;
|
|
342
|
+
//# sourceMappingURL=board-snapshot.builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board-snapshot.builder.js","sourceRoot":"","sources":["../../../../../../backend/src/services/board/board-snapshot.builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spend and "what is each agent on" from the usage ledger (crewly#1247).
|
|
3
|
+
* A pure fold over the ledger's in-memory rollup: per-agent and total cost
|
|
4
|
+
* for today (local midnight) and the last 7 days, the owner's minutes, and the
|
|
5
|
+
* open ticket each agent used tokens on most recently (the ledger's
|
|
6
|
+
* attribution, #1250).
|
|
7
|
+
*
|
|
8
|
+
* @module services/board/board-usage
|
|
9
|
+
*/
|
|
10
|
+
import type { UnitRollup } from '../usage-ledger/ledger-rollup.js';
|
|
11
|
+
import type { BoardUsage } from './board-snapshot.builder.js';
|
|
12
|
+
/**
|
|
13
|
+
* Fold the ledger rollup into board usage.
|
|
14
|
+
*
|
|
15
|
+
* @param units - The rollup's units
|
|
16
|
+
* @param now - Epoch ms
|
|
17
|
+
* @returns Usage for the board
|
|
18
|
+
*/
|
|
19
|
+
export declare function computeBoardUsage(units: Iterable<UnitRollup>, now: number): BoardUsage;
|
|
20
|
+
//# sourceMappingURL=board-usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board-usage.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/board/board-usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAGnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAM9D;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAuDtF"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spend and "what is each agent on" from the usage ledger (crewly#1247).
|
|
3
|
+
* A pure fold over the ledger's in-memory rollup: per-agent and total cost
|
|
4
|
+
* for today (local midnight) and the last 7 days, the owner's minutes, and the
|
|
5
|
+
* open ticket each agent used tokens on most recently (the ledger's
|
|
6
|
+
* attribution, #1250).
|
|
7
|
+
*
|
|
8
|
+
* @module services/board/board-usage
|
|
9
|
+
*/
|
|
10
|
+
import { BOARD_CONSTANTS } from '../../constants.js';
|
|
11
|
+
import { buildOwnerSpans, ownerMinutesByUnit } from '../usage-ledger/owner-spans.js';
|
|
12
|
+
import { scrubText } from './board-redact.js';
|
|
13
|
+
import { startOfLocalDay } from './board-snapshot.builder.js';
|
|
14
|
+
const HOUR_MS = 3_600_000;
|
|
15
|
+
const WEEK_MS = 7 * 24 * HOUR_MS;
|
|
16
|
+
/**
|
|
17
|
+
* Fold the ledger rollup into board usage.
|
|
18
|
+
*
|
|
19
|
+
* @param units - The rollup's units
|
|
20
|
+
* @param now - Epoch ms
|
|
21
|
+
* @returns Usage for the board
|
|
22
|
+
*/
|
|
23
|
+
export function computeBoardUsage(units, now) {
|
|
24
|
+
const dayStart = startOfLocalDay(now);
|
|
25
|
+
const weekStart = now - WEEK_MS;
|
|
26
|
+
const perAgent = new Map();
|
|
27
|
+
const spend = { todayUsd: 0, weekUsd: 0, todayTokens: 0, weekTokens: 0 };
|
|
28
|
+
const recent = new Map();
|
|
29
|
+
const spans = [];
|
|
30
|
+
for (const unit of units) {
|
|
31
|
+
if (unit.ownerMessages.length > 0)
|
|
32
|
+
spans.push(...buildOwnerSpans(unit.unitId, unit.ownerMessages));
|
|
33
|
+
for (const e of unit.usage) {
|
|
34
|
+
const end = e.hourMs + HOUR_MS;
|
|
35
|
+
if (end <= weekStart || e.hourMs > now)
|
|
36
|
+
continue;
|
|
37
|
+
const tokens = e.budget * e.share;
|
|
38
|
+
const usd = e.costUsd * e.share;
|
|
39
|
+
spend.weekUsd += usd;
|
|
40
|
+
spend.weekTokens += tokens;
|
|
41
|
+
if (e.hourMs + HOUR_MS > dayStart) {
|
|
42
|
+
spend.todayUsd += usd;
|
|
43
|
+
spend.todayTokens += tokens;
|
|
44
|
+
const a = perAgent.get(e.agent) ?? { todayUsd: 0, todayTokens: 0 };
|
|
45
|
+
a.todayUsd += usd;
|
|
46
|
+
a.todayTokens += tokens;
|
|
47
|
+
perAgent.set(e.agent, a);
|
|
48
|
+
}
|
|
49
|
+
if (!unit.synthetic && !unit.closedAt) {
|
|
50
|
+
const at = Math.min(now, e.hourMs + HOUR_MS);
|
|
51
|
+
const prev = recent.get(e.agent);
|
|
52
|
+
if (!prev || at > prev.at)
|
|
53
|
+
recent.set(e.agent, { unit, at });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const taskOf = new Map();
|
|
58
|
+
for (const [agent, { unit, at }] of recent) {
|
|
59
|
+
if (now - at > BOARD_CONSTANTS.LEDGER_TASK_MAX_AGE_MS)
|
|
60
|
+
continue;
|
|
61
|
+
const title = scrubText(unit.title || unit.ticketId || '');
|
|
62
|
+
if (!title)
|
|
63
|
+
continue;
|
|
64
|
+
taskOf.set(agent, { ...(unit.ticketId ? { id: unit.ticketId } : {}), title, since: new Date(unit.firstMs || at).toISOString() });
|
|
65
|
+
}
|
|
66
|
+
const sum = (m) => [...m.values()].reduce((a, b) => a + b, 0);
|
|
67
|
+
const minutes = (from) => Math.round(sum(ownerMinutesByUnit(spans, from, now)));
|
|
68
|
+
return {
|
|
69
|
+
perAgent,
|
|
70
|
+
taskOf,
|
|
71
|
+
spend: {
|
|
72
|
+
todayUsd: round2(spend.todayUsd),
|
|
73
|
+
weekUsd: round2(spend.weekUsd),
|
|
74
|
+
todayTokens: Math.round(spend.todayTokens),
|
|
75
|
+
weekTokens: Math.round(spend.weekTokens),
|
|
76
|
+
ownerMinutesToday: minutes(dayStart),
|
|
77
|
+
ownerMinutesWeek: minutes(weekStart),
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const round2 = (n) => Math.round(n * 100) / 100;
|
|
82
|
+
//# sourceMappingURL=board-usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board-usage.js","sourceRoot":"","sources":["../../../../../../backend/src/services/board/board-usage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Owner Board on this machine (crewly#1247): the snapshot builder, the
|
|
3
|
+
* live activity tracker and the Cloud push, behind one handle. The local
|
|
4
|
+
* `GET /api/board` and the push share one builder, so the dashboard and the
|
|
5
|
+
* phone show the same board.
|
|
6
|
+
*
|
|
7
|
+
* @module services/board/board.service
|
|
8
|
+
*/
|
|
9
|
+
import { BoardActivityTracker } from './board-activity.tracker.js';
|
|
10
|
+
import { BoardPushService, type BoardCloudSession } from './board-push.service.js';
|
|
11
|
+
import { BoardSnapshotBuilder, type BoardSources } from './board-snapshot.builder.js';
|
|
12
|
+
import type { BoardSnapshot, BoardTimelineEvent } from './board.types.js';
|
|
13
|
+
/** Constructor options. */
|
|
14
|
+
export interface BoardServiceOptions {
|
|
15
|
+
sources: BoardSources;
|
|
16
|
+
cloud: BoardCloudSession;
|
|
17
|
+
tracker?: BoardActivityTracker;
|
|
18
|
+
env?: NodeJS.ProcessEnv;
|
|
19
|
+
}
|
|
20
|
+
/** Owner board for this machine. */
|
|
21
|
+
export declare class BoardService {
|
|
22
|
+
readonly builder: BoardSnapshotBuilder;
|
|
23
|
+
readonly push: BoardPushService;
|
|
24
|
+
readonly tracker: BoardActivityTracker;
|
|
25
|
+
private last;
|
|
26
|
+
private inflight;
|
|
27
|
+
constructor(options: BoardServiceOptions);
|
|
28
|
+
/** Start the Cloud push (a no-op when switched off). */
|
|
29
|
+
start(): void;
|
|
30
|
+
/** Stop the Cloud push. */
|
|
31
|
+
stop(): void;
|
|
32
|
+
/**
|
|
33
|
+
* The current snapshot; one built within `maxAgeMs` is reused, and
|
|
34
|
+
* concurrent callers share one build.
|
|
35
|
+
*
|
|
36
|
+
* @param maxAgeMs - Oldest acceptable snapshot (ms)
|
|
37
|
+
* @returns The snapshot
|
|
38
|
+
*/
|
|
39
|
+
getSnapshot(maxAgeMs?: number): Promise<BoardSnapshot>;
|
|
40
|
+
/**
|
|
41
|
+
* An agent's recent timeline.
|
|
42
|
+
*
|
|
43
|
+
* @param session - Agent session
|
|
44
|
+
* @returns Events, oldest first
|
|
45
|
+
*/
|
|
46
|
+
timeline(session: string): BoardTimelineEvent[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Install the process-wide board (composition root).
|
|
50
|
+
*
|
|
51
|
+
* @param service - The board, or null
|
|
52
|
+
*/
|
|
53
|
+
export declare function setBoardService(service: BoardService | null): void;
|
|
54
|
+
/**
|
|
55
|
+
* The process-wide board, or null before boot wired it.
|
|
56
|
+
*
|
|
57
|
+
* @returns The board or null
|
|
58
|
+
*/
|
|
59
|
+
export declare function getBoardService(): BoardService | null;
|
|
60
|
+
//# sourceMappingURL=board.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/board/board.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,KAAK,YAAY,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE1E,2BAA2B;AAC3B,MAAM,WAAW,mBAAmB;IACnC,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,iBAAiB,CAAC;IACzB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED,oCAAoC;AACpC,qBAAa,YAAY;IACxB,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;IACvC,OAAO,CAAC,IAAI,CAAwD;IACpE,OAAO,CAAC,QAAQ,CAAuC;gBAE3C,OAAO,EAAE,mBAAmB;IAMxC,wDAAwD;IACxD,KAAK,IAAI,IAAI;IAIb,2BAA2B;IAC3B,IAAI,IAAI,IAAI;IAIZ;;;;;;OAMG;IACG,WAAW,CAAC,QAAQ,SAAQ,GAAG,OAAO,CAAC,aAAa,CAAC;IAgB3D;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,EAAE;CAG/C;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAElE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,YAAY,GAAG,IAAI,CAErD"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Owner Board on this machine (crewly#1247): the snapshot builder, the
|
|
3
|
+
* live activity tracker and the Cloud push, behind one handle. The local
|
|
4
|
+
* `GET /api/board` and the push share one builder, so the dashboard and the
|
|
5
|
+
* phone show the same board.
|
|
6
|
+
*
|
|
7
|
+
* @module services/board/board.service
|
|
8
|
+
*/
|
|
9
|
+
import { BoardActivityTracker } from './board-activity.tracker.js';
|
|
10
|
+
import { BoardPushService } from './board-push.service.js';
|
|
11
|
+
import { BoardSnapshotBuilder } from './board-snapshot.builder.js';
|
|
12
|
+
/** Owner board for this machine. */
|
|
13
|
+
export class BoardService {
|
|
14
|
+
builder;
|
|
15
|
+
push;
|
|
16
|
+
tracker;
|
|
17
|
+
last = null;
|
|
18
|
+
inflight = null;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
this.tracker = options.tracker ?? BoardActivityTracker.getInstance();
|
|
21
|
+
this.builder = new BoardSnapshotBuilder(options.sources, this.tracker);
|
|
22
|
+
this.push = new BoardPushService({ builder: this.builder, tracker: this.tracker, cloud: options.cloud, ...(options.env ? { env: options.env } : {}) });
|
|
23
|
+
}
|
|
24
|
+
/** Start the Cloud push (a no-op when switched off). */
|
|
25
|
+
start() {
|
|
26
|
+
this.push.start();
|
|
27
|
+
}
|
|
28
|
+
/** Stop the Cloud push. */
|
|
29
|
+
stop() {
|
|
30
|
+
this.push.stop();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The current snapshot; one built within `maxAgeMs` is reused, and
|
|
34
|
+
* concurrent callers share one build.
|
|
35
|
+
*
|
|
36
|
+
* @param maxAgeMs - Oldest acceptable snapshot (ms)
|
|
37
|
+
* @returns The snapshot
|
|
38
|
+
*/
|
|
39
|
+
async getSnapshot(maxAgeMs = 5_000) {
|
|
40
|
+
if (this.last && Date.now() - this.last.at < maxAgeMs)
|
|
41
|
+
return this.last.snapshot;
|
|
42
|
+
if (!this.inflight) {
|
|
43
|
+
this.inflight = this.builder
|
|
44
|
+
.build()
|
|
45
|
+
.then((snapshot) => {
|
|
46
|
+
this.last = { at: Date.now(), snapshot };
|
|
47
|
+
return snapshot;
|
|
48
|
+
})
|
|
49
|
+
.finally(() => {
|
|
50
|
+
this.inflight = null;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return this.inflight;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* An agent's recent timeline.
|
|
57
|
+
*
|
|
58
|
+
* @param session - Agent session
|
|
59
|
+
* @returns Events, oldest first
|
|
60
|
+
*/
|
|
61
|
+
timeline(session) {
|
|
62
|
+
return this.tracker.timeline(session);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
let instance = null;
|
|
66
|
+
/**
|
|
67
|
+
* Install the process-wide board (composition root).
|
|
68
|
+
*
|
|
69
|
+
* @param service - The board, or null
|
|
70
|
+
*/
|
|
71
|
+
export function setBoardService(service) {
|
|
72
|
+
instance = service;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The process-wide board, or null before boot wired it.
|
|
76
|
+
*
|
|
77
|
+
* @returns The board or null
|
|
78
|
+
*/
|
|
79
|
+
export function getBoardService() {
|
|
80
|
+
return instance;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=board.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/board/board.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAA0B,MAAM,yBAAyB,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAqB,MAAM,6BAA6B,CAAC;AAWtF,oCAAoC;AACpC,MAAM,OAAO,YAAY;IACf,OAAO,CAAuB;IAC9B,IAAI,CAAmB;IACvB,OAAO,CAAuB;IAC/B,IAAI,GAAmD,IAAI,CAAC;IAC5D,QAAQ,GAAkC,IAAI,CAAC;IAEvD,YAAY,OAA4B;QACvC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,oBAAoB,CAAC,WAAW,EAAE,CAAC;QACrE,IAAI,CAAC,OAAO,GAAG,IAAI,oBAAoB,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,GAAG,IAAI,gBAAgB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACxJ,CAAC;IAED,wDAAwD;IACxD,KAAK;QACJ,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,2BAA2B;IAC3B,IAAI;QACH,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAClB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,WAAW,CAAC,QAAQ,GAAG,KAAK;QACjC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;QACjF,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO;iBAC1B,KAAK,EAAE;iBACP,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;gBAClB,IAAI,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,CAAC;gBACzC,OAAO,QAAQ,CAAC;YACjB,CAAC,CAAC;iBACD,OAAO,CAAC,GAAG,EAAE;gBACb,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACtB,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,OAAe;QACvB,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;CACD;AAED,IAAI,QAAQ,GAAwB,IAAI,CAAC;AAEzC;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAA4B;IAC3D,QAAQ,GAAG,OAAO,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC9B,OAAO,QAAQ,CAAC;AACjB,CAAC"}
|