@tokenfactory/acc-runner 0.40.0 → 0.40.1
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/cli.js +60 -0
- package/dist/cli.js.map +1 -1
- package/dist/companion-autostart.d.ts +71 -0
- package/dist/companion-autostart.d.ts.map +1 -0
- package/dist/companion-autostart.js +191 -0
- package/dist/companion-autostart.js.map +1 -0
- package/dist/companion-mirror-socket.d.ts +126 -0
- package/dist/companion-mirror-socket.d.ts.map +1 -0
- package/dist/companion-mirror-socket.js +196 -0
- package/dist/companion-mirror-socket.js.map +1 -0
- package/dist/companion-run.d.ts +19 -0
- package/dist/companion-run.d.ts.map +1 -0
- package/dist/companion-run.js +132 -0
- package/dist/companion-run.js.map +1 -0
- package/dist/companion.d.ts +181 -0
- package/dist/companion.d.ts.map +1 -0
- package/dist/companion.js +343 -0
- package/dist/companion.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CC-3C (COMPANION): companion-mode runtime for the acc-runner CLI.
|
|
3
|
+
*
|
|
4
|
+
* A COMPANION is a runner attached to its owner's operator chats. It is a
|
|
5
|
+
* distinct execution shape from the fleet `watch` runner:
|
|
6
|
+
*
|
|
7
|
+
* - OWNER-AFFINITY LANE — a companion serves ONLY its bound owner's chat
|
|
8
|
+
* turns. `OwnerConversationSource` is the runner-side guarantee: a
|
|
9
|
+
* conversation is only served when its owner is the bound user, so a
|
|
10
|
+
* companion never claims another operator's turn even if the queue is
|
|
11
|
+
* shared. Cross-runner contention is still resolved by the per-conversation
|
|
12
|
+
* advisory lock in `acc.claim_chat_turn` (migration 0254) — a fleet runner
|
|
13
|
+
* and a companion can race the SAME conversation and exactly one wins; the
|
|
14
|
+
* companion just never races a conversation that isn't its owner's.
|
|
15
|
+
*
|
|
16
|
+
* - NO CODE LANE BY DEFAULT — the `companion` command drives the chat lane
|
|
17
|
+
* only (`activeCodeTasks` is always 0 and no task/review pump runs). A
|
|
18
|
+
* companion claims interactive turns, not build tasks. (The `watch` command
|
|
19
|
+
* remains the code/review fleet runner; the same machine may run both.)
|
|
20
|
+
*
|
|
21
|
+
* - FAIL-OVER TO FLEET — when the companion stops (operator quit, laptop
|
|
22
|
+
* sleep, crash), its in-flight turns are REQUEUED (via the driver's
|
|
23
|
+
* abort→requeue path) and an `companion_lost` identity event flips the
|
|
24
|
+
* identity offline immediately, so an Auto-routed turn fails over to a
|
|
25
|
+
* fleet runner with no duplicate side effects (the driver emits exactly one
|
|
26
|
+
* terminal transport call per turn).
|
|
27
|
+
*
|
|
28
|
+
* - LOCALHOST MIRROR — the companion's turn stream is teed to a loopback
|
|
29
|
+
* mirror socket (companion-mirror-socket.ts) so the same-machine browser
|
|
30
|
+
* paints replies with sub-round-trip latency. The DB (via the chat topic)
|
|
31
|
+
* stays the single source of truth; the mirror is a read-only latency shim.
|
|
32
|
+
*
|
|
33
|
+
* Everything side-effecting (transport, engine, identity broadcaster, heartbeat,
|
|
34
|
+
* clock, mirror socket) is injected so the orchestrator is exercised
|
|
35
|
+
* deterministically without a network or a `claude` binary.
|
|
36
|
+
*/
|
|
37
|
+
import { createHash } from "node:crypto";
|
|
38
|
+
import { ChatCompanion } from "./chat-companion.js";
|
|
39
|
+
import { resolveChatLaneConfig, } from "./chat-lane.js";
|
|
40
|
+
/** Build the per-identity capacity Realtime topic (mirror of the web builder). */
|
|
41
|
+
export function identityTopic(userId) {
|
|
42
|
+
return `identity:${userId}`;
|
|
43
|
+
}
|
|
44
|
+
/* ------------------------------------------------------------------ *
|
|
45
|
+
* 2. Companion config (env resolution)
|
|
46
|
+
* ------------------------------------------------------------------ */
|
|
47
|
+
/** Opt the runner's chat lane into serving code tasks too (default: chat only). */
|
|
48
|
+
export const COMPANION_CODE_TASKS_ENV = "ACC_RUNNER_COMPANION_CODE_TASKS";
|
|
49
|
+
/** Disable the localhost mirror socket (default: enabled). */
|
|
50
|
+
export const COMPANION_MIRROR_ENV = "ACC_RUNNER_COMPANION_MIRROR";
|
|
51
|
+
/** Loopback port the mirror socket binds to. */
|
|
52
|
+
export const COMPANION_MIRROR_PORT_ENV = "ACC_RUNNER_COMPANION_MIRROR_PORT";
|
|
53
|
+
/** Explicit mirror handshake token override (else derived from the session). */
|
|
54
|
+
export const COMPANION_MIRROR_TOKEN_ENV = "ACC_RUNNER_COMPANION_MIRROR_TOKEN";
|
|
55
|
+
/** Default loopback port for the mirror socket. */
|
|
56
|
+
export const DEFAULT_COMPANION_MIRROR_PORT = 7717;
|
|
57
|
+
function isTruthyFlag(raw) {
|
|
58
|
+
const v = (raw ?? "").trim().toLowerCase();
|
|
59
|
+
return v === "1" || v === "true" || v === "yes" || v === "on";
|
|
60
|
+
}
|
|
61
|
+
function isFalsyFlag(raw) {
|
|
62
|
+
const v = (raw ?? "").trim().toLowerCase();
|
|
63
|
+
return v === "0" || v === "false" || v === "no" || v === "off";
|
|
64
|
+
}
|
|
65
|
+
/** Resolve companion knobs from the environment in one place. */
|
|
66
|
+
export function resolveCompanionConfig(env = process.env) {
|
|
67
|
+
const portRaw = Number.parseInt((env[COMPANION_MIRROR_PORT_ENV] ?? "").trim(), 10);
|
|
68
|
+
const mirrorPort = Number.isFinite(portRaw) && portRaw > 0 && portRaw < 65_536 ? portRaw : DEFAULT_COMPANION_MIRROR_PORT;
|
|
69
|
+
const tokenRaw = (env[COMPANION_MIRROR_TOKEN_ENV] ?? "").trim();
|
|
70
|
+
return {
|
|
71
|
+
codeTasksEnabled: isTruthyFlag(env[COMPANION_CODE_TASKS_ENV]),
|
|
72
|
+
// Mirror is on unless explicitly disabled.
|
|
73
|
+
mirrorEnabled: !isFalsyFlag(env[COMPANION_MIRROR_ENV]),
|
|
74
|
+
mirrorPort,
|
|
75
|
+
mirrorToken: tokenRaw || null,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Derive the loopback mirror handshake token from the session. Bound to the
|
|
80
|
+
* refresh token (stable across hourly access-token refreshes, rotated on
|
|
81
|
+
* re-login / logout) + the runner id, one-way hashed so the token never leaks
|
|
82
|
+
* either. The same-machine browser obtains the matching token through the
|
|
83
|
+
* authenticated control plane; this keeps the mirror strictly session-bound —
|
|
84
|
+
* it cannot outlive the session it reflects.
|
|
85
|
+
*/
|
|
86
|
+
export function deriveMirrorToken(session) {
|
|
87
|
+
return createHash("sha256")
|
|
88
|
+
.update(`${session.refresh_token}:${session.runner_id}:acc-companion-mirror`)
|
|
89
|
+
.digest("hex")
|
|
90
|
+
.slice(0, 32);
|
|
91
|
+
}
|
|
92
|
+
/* ------------------------------------------------------------------ *
|
|
93
|
+
* 3. Owner-affinity conversation source
|
|
94
|
+
* ------------------------------------------------------------------ */
|
|
95
|
+
/**
|
|
96
|
+
* The set of conversations a companion is allowed to serve — the OWNER-AFFINITY
|
|
97
|
+
* guarantee. A conversation enters the set only when its owner is the bound
|
|
98
|
+
* user; `add` returns false and no-ops for any other owner, so the companion's
|
|
99
|
+
* claim loop can never present a foreign operator's conversation to the claim
|
|
100
|
+
* RPC. Fed by the control plane (the browser announces which conversation the
|
|
101
|
+
* operator is active in over the authenticated `identity:<user>` topic); an
|
|
102
|
+
* optional seed lists conversations known at boot.
|
|
103
|
+
*/
|
|
104
|
+
export class OwnerConversationSource {
|
|
105
|
+
boundUserId;
|
|
106
|
+
ids = new Set();
|
|
107
|
+
constructor(boundUserId, seed = []) {
|
|
108
|
+
this.boundUserId = boundUserId;
|
|
109
|
+
for (const s of seed)
|
|
110
|
+
this.add(s.conversationId, s.ownerUserId);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Register a conversation IF and only if its owner is the bound user. Returns
|
|
114
|
+
* true when it was added (owner match), false when rejected (foreign owner or
|
|
115
|
+
* blank id). This is the single enforcement point for owner-affinity.
|
|
116
|
+
*/
|
|
117
|
+
add(conversationId, ownerUserId) {
|
|
118
|
+
const id = (conversationId ?? "").trim();
|
|
119
|
+
if (!id)
|
|
120
|
+
return false;
|
|
121
|
+
if (ownerUserId !== this.boundUserId)
|
|
122
|
+
return false;
|
|
123
|
+
this.ids.add(id);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
/** Drop a conversation (operator closed it / it moved to another owner). */
|
|
127
|
+
remove(conversationId) {
|
|
128
|
+
this.ids.delete((conversationId ?? "").trim());
|
|
129
|
+
}
|
|
130
|
+
/** True when the conversation is currently served by this companion. */
|
|
131
|
+
has(conversationId) {
|
|
132
|
+
return this.ids.has((conversationId ?? "").trim());
|
|
133
|
+
}
|
|
134
|
+
/** Stable snapshot of the served conversations (for the claim loop). */
|
|
135
|
+
snapshot() {
|
|
136
|
+
return [...this.ids];
|
|
137
|
+
}
|
|
138
|
+
/** Count of served conversations. */
|
|
139
|
+
size() {
|
|
140
|
+
return this.ids.size;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/* ------------------------------------------------------------------ *
|
|
144
|
+
* 4. Mirror tee — teeing the outbound turn stream onto the loopback socket
|
|
145
|
+
* ------------------------------------------------------------------ */
|
|
146
|
+
/**
|
|
147
|
+
* Wrap a `ChatLaneTransport` so every OUTBOUND lifecycle message (stream /
|
|
148
|
+
* complete / requeue) is ALSO pushed to the loopback mirror socket after the
|
|
149
|
+
* authoritative transport call succeeds. This is a strict tee: the wrapper only
|
|
150
|
+
* reads the payloads the driver already sends to the DB path — it introduces no
|
|
151
|
+
* new mutation and no inbound path. With no mirror socket it is the identity
|
|
152
|
+
* wrapper. `claim` / `markStreaming` pass straight through (nothing to mirror).
|
|
153
|
+
*/
|
|
154
|
+
export function mirrorTee(transport, mirror) {
|
|
155
|
+
if (!mirror)
|
|
156
|
+
return transport;
|
|
157
|
+
return {
|
|
158
|
+
claim: (args) => transport.claim(args),
|
|
159
|
+
...(transport.markStreaming
|
|
160
|
+
? { markStreaming: (turn) => transport.markStreaming(turn) }
|
|
161
|
+
: {}),
|
|
162
|
+
async stream(turn, payload) {
|
|
163
|
+
await transport.stream(turn, payload);
|
|
164
|
+
mirror.mirror("turn_stream", turn.conversation_id, turn.id, payload);
|
|
165
|
+
},
|
|
166
|
+
async complete(turn, payload) {
|
|
167
|
+
await transport.complete(turn, payload);
|
|
168
|
+
mirror.mirror("turn_complete", turn.conversation_id, turn.id, payload);
|
|
169
|
+
},
|
|
170
|
+
async requeue(turn, payload) {
|
|
171
|
+
await transport.requeue(turn, payload);
|
|
172
|
+
mirror.mirror("turn_requeued", turn.conversation_id, turn.id, payload);
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Drive companion mode: register the owner-bound identity, serve the owner's
|
|
178
|
+
* chat turns through a `ChatCompanion` (chat lane only — `activeCodeTasks` is
|
|
179
|
+
* always 0), tee the stream to the loopback mirror, heartbeat the identity
|
|
180
|
+
* online, and on stop requeue in-flight turns + flip the identity offline so an
|
|
181
|
+
* Auto turn fails over to the fleet.
|
|
182
|
+
*/
|
|
183
|
+
export class CompanionRunner {
|
|
184
|
+
deps;
|
|
185
|
+
companion = null;
|
|
186
|
+
heartbeatTimer = null;
|
|
187
|
+
lastCapacity = null;
|
|
188
|
+
stopped = false;
|
|
189
|
+
now;
|
|
190
|
+
constructor(deps) {
|
|
191
|
+
this.deps = deps;
|
|
192
|
+
this.now = deps.now ?? Date.now;
|
|
193
|
+
}
|
|
194
|
+
/** Chat turns currently in flight on this companion. */
|
|
195
|
+
activeChatTurns() {
|
|
196
|
+
return this.companion?.activeChatTurns() ?? 0;
|
|
197
|
+
}
|
|
198
|
+
/** Register the owner-bound identity, start the pump + mirror + heartbeat. */
|
|
199
|
+
async start() {
|
|
200
|
+
if (this.companion || this.stopped)
|
|
201
|
+
return;
|
|
202
|
+
const probe = await this.deps.engine.credentialProbe().catch(() => null);
|
|
203
|
+
const capacity = await this.deps.engine.classifyCapacity().catch(() => "light");
|
|
204
|
+
this.lastCapacity = capacity;
|
|
205
|
+
const capabilities = {
|
|
206
|
+
...this.deps.engine.capabilities,
|
|
207
|
+
// Report the tier the resolved credential actually authorises (probe wins
|
|
208
|
+
// over the static declaration; an unavailable probe drops to unavailable).
|
|
209
|
+
...(probe ? { tier: probe.tier } : {}),
|
|
210
|
+
};
|
|
211
|
+
const register = {
|
|
212
|
+
mode: "companion",
|
|
213
|
+
bound_user_id: this.deps.boundUserId,
|
|
214
|
+
engine_ids: [this.deps.engine.id],
|
|
215
|
+
capability_matrix: capabilities,
|
|
216
|
+
capacity,
|
|
217
|
+
};
|
|
218
|
+
await this.deps.announce("companion_registered", register);
|
|
219
|
+
if (this.deps.mirror)
|
|
220
|
+
await this.deps.mirror.start();
|
|
221
|
+
this.companion = new ChatCompanion({
|
|
222
|
+
runnerId: this.deps.runnerId,
|
|
223
|
+
engine: this.deps.engine,
|
|
224
|
+
transport: mirrorTee(this.deps.transport, this.deps.mirror),
|
|
225
|
+
breaker: this.deps.breaker,
|
|
226
|
+
concurrencyLimit: this.deps.concurrencyLimit,
|
|
227
|
+
maxShare: this.deps.maxShare,
|
|
228
|
+
leaseMs: this.deps.leaseMs,
|
|
229
|
+
conversations: () => this.deps.conversations.snapshot(),
|
|
230
|
+
// Companion is a chat-only lane: no code/review tasks contend for slots.
|
|
231
|
+
activeCodeTasks: () => 0,
|
|
232
|
+
...(this.deps.cwd !== undefined ? { cwd: this.deps.cwd } : {}),
|
|
233
|
+
...(this.deps.mintDelegation ? { mintDelegation: this.deps.mintDelegation } : {}),
|
|
234
|
+
...(this.deps.now ? { now: this.deps.now } : {}),
|
|
235
|
+
...(this.deps.onLog ? { onLog: this.deps.onLog } : {}),
|
|
236
|
+
});
|
|
237
|
+
this.companion.start(this.deps.pumpMs ?? 1_000);
|
|
238
|
+
// Heartbeat keeps the identity online; a lapse (sleep/crash) is what flips
|
|
239
|
+
// it offline server-side and fails Auto over to the fleet.
|
|
240
|
+
await this.beat();
|
|
241
|
+
const beatMs = this.deps.heartbeatMs ?? 4_000;
|
|
242
|
+
this.heartbeatTimer = setInterval(() => void this.beat(), beatMs);
|
|
243
|
+
this.heartbeatTimer.unref?.();
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Stop the companion: requeue in-flight turns (clean fail-over — the driver
|
|
247
|
+
* emits exactly one requeue, no duplicate completion), flip the identity
|
|
248
|
+
* offline so Auto routes to the fleet, and tear the mirror down.
|
|
249
|
+
*/
|
|
250
|
+
async stop() {
|
|
251
|
+
if (this.stopped)
|
|
252
|
+
return;
|
|
253
|
+
this.stopped = true;
|
|
254
|
+
if (this.heartbeatTimer) {
|
|
255
|
+
clearInterval(this.heartbeatTimer);
|
|
256
|
+
this.heartbeatTimer = null;
|
|
257
|
+
}
|
|
258
|
+
// Requeue every in-flight turn so a fleet runner can finish it.
|
|
259
|
+
if (this.companion)
|
|
260
|
+
await this.companion.stop().catch(() => []);
|
|
261
|
+
// Flip the identity offline immediately (don't wait for the heartbeat lapse).
|
|
262
|
+
await this.deps
|
|
263
|
+
.announce("companion_lost", {
|
|
264
|
+
runner_id: this.deps.runnerId,
|
|
265
|
+
capacity: "overloaded",
|
|
266
|
+
available_engine_ids: [],
|
|
267
|
+
ts: new Date(this.now()).toISOString(),
|
|
268
|
+
})
|
|
269
|
+
.catch(() => undefined);
|
|
270
|
+
if (this.deps.mirror)
|
|
271
|
+
await this.deps.mirror.close().catch(() => undefined);
|
|
272
|
+
}
|
|
273
|
+
/** One heartbeat: keep the identity online + announce a capacity change. */
|
|
274
|
+
async beat() {
|
|
275
|
+
if (this.stopped)
|
|
276
|
+
return;
|
|
277
|
+
await this.deps.heartbeat().catch((err) => {
|
|
278
|
+
this.deps.onLog?.(`[acc-runner] companion heartbeat failed: ${err.message}`);
|
|
279
|
+
});
|
|
280
|
+
const capacity = await this.deps.engine.classifyCapacity().catch(() => this.lastCapacity);
|
|
281
|
+
if (capacity && capacity !== this.lastCapacity) {
|
|
282
|
+
this.lastCapacity = capacity;
|
|
283
|
+
await this.deps
|
|
284
|
+
.announce("capacity_changed", {
|
|
285
|
+
runner_id: this.deps.runnerId,
|
|
286
|
+
capacity,
|
|
287
|
+
available_engine_ids: [this.deps.engine.id],
|
|
288
|
+
ts: new Date(this.now()).toISOString(),
|
|
289
|
+
})
|
|
290
|
+
.catch(() => undefined);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Build the identity-topic broadcaster for a companion. Broadcasts on
|
|
296
|
+
* `identity:<userId>` via the runner's Supabase realtime client. Kept separate
|
|
297
|
+
* from the orchestrator so tests inject a recording fake instead.
|
|
298
|
+
*/
|
|
299
|
+
export function createIdentityBroadcaster(
|
|
300
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
301
|
+
client, userId, opts = {}) {
|
|
302
|
+
const topic = identityTopic(userId);
|
|
303
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
304
|
+
let channel = null;
|
|
305
|
+
async function ensure() {
|
|
306
|
+
if (channel)
|
|
307
|
+
return channel;
|
|
308
|
+
channel = client.channel(topic);
|
|
309
|
+
await new Promise((resolve) => {
|
|
310
|
+
channel.subscribe((status) => {
|
|
311
|
+
if (status === "SUBSCRIBED")
|
|
312
|
+
resolve();
|
|
313
|
+
});
|
|
314
|
+
setTimeout(resolve, 2_000).unref?.();
|
|
315
|
+
});
|
|
316
|
+
return channel;
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
async announce(event, payload) {
|
|
320
|
+
try {
|
|
321
|
+
const ch = await ensure();
|
|
322
|
+
await ch.send({ type: "broadcast", event, payload });
|
|
323
|
+
}
|
|
324
|
+
catch (err) {
|
|
325
|
+
opts.onLog?.(`[acc-runner] identity broadcast(${event}) failed: ${err.message}`);
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
async close() {
|
|
329
|
+
if (channel) {
|
|
330
|
+
try {
|
|
331
|
+
await client.removeChannel(channel);
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
/* best-effort */
|
|
335
|
+
}
|
|
336
|
+
channel = null;
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/** Re-export for callers that resolve chat-lane knobs alongside companion knobs. */
|
|
342
|
+
export { resolveChatLaneConfig };
|
|
343
|
+
//# sourceMappingURL=companion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"companion.js","sourceRoot":"","sources":["../src/companion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,qBAAqB,GAMtB,MAAM,gBAAgB,CAAC;AAuCxB,kFAAkF;AAClF,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,YAAY,MAAM,EAAE,CAAC;AAC9B,CAAC;AAED;;wEAEwE;AAExE,mFAAmF;AACnF,MAAM,CAAC,MAAM,wBAAwB,GAAG,iCAAiC,CAAC;AAC1E,8DAA8D;AAC9D,MAAM,CAAC,MAAM,oBAAoB,GAAG,6BAA6B,CAAC;AAClE,gDAAgD;AAChD,MAAM,CAAC,MAAM,yBAAyB,GAAG,kCAAkC,CAAC;AAC5E,gFAAgF;AAChF,MAAM,CAAC,MAAM,0BAA0B,GAAG,mCAAmC,CAAC;AAC9E,mDAAmD;AACnD,MAAM,CAAC,MAAM,6BAA6B,GAAG,IAAI,CAAC;AAElD,SAAS,YAAY,CAAC,GAA8B;IAClD,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC;AAChE,CAAC;AAED,SAAS,WAAW,CAAC,GAA8B;IACjD,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC;AACjE,CAAC;AAcD,iEAAiE;AACjE,MAAM,UAAU,sBAAsB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACzE,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,yBAAyB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACnF,MAAM,UAAU,GACd,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC;IACxG,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,0BAA0B,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAChE,OAAO;QACL,gBAAgB,EAAE,YAAY,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QAC7D,2CAA2C;QAC3C,aAAa,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QACtD,UAAU;QACV,WAAW,EAAE,QAAQ,IAAI,IAAI;KAC9B,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA2D;IAC3F,OAAO,UAAU,CAAC,QAAQ,CAAC;SACxB,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,SAAS,uBAAuB,CAAC;SAC5E,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;wEAEwE;AAExE;;;;;;;;GAQG;AACH,MAAM,OAAO,uBAAuB;IAIf;IAHF,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAEzC,YACmB,WAAmB,EACpC,OAA+D,EAAE;QADhD,gBAAW,GAAX,WAAW,CAAQ;QAGpC,KAAK,MAAM,CAAC,IAAI,IAAI;YAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;IAClE,CAAC;IAED;;;;OAIG;IACH,GAAG,CAAC,cAAsB,EAAE,WAAmB;QAC7C,MAAM,EAAE,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACzC,IAAI,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;QACtB,IAAI,WAAW,KAAK,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,CAAC;QACnD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4EAA4E;IAC5E,MAAM,CAAC,cAAsB;QAC3B,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,wEAAwE;IACxE,GAAG,CAAC,cAAsB;QACxB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,wEAAwE;IACxE,QAAQ;QACN,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAED,qCAAqC;IACrC,IAAI;QACF,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACvB,CAAC;CACF;AAED;;wEAEwE;AAExE;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CACvB,SAA4B,EAC5B,MAAgD;IAEhD,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,OAAO;QACL,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;QACtC,GAAG,CAAC,SAAS,CAAC,aAAa;YACzB,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,IAAqB,EAAE,EAAE,CAAC,SAAS,CAAC,aAAc,CAAC,IAAI,CAAC,EAAE;YAC9E,CAAC,CAAC,EAAE,CAAC;QACP,KAAK,CAAC,MAAM,CAAC,IAAqB,EAAE,OAA8B;YAChE,MAAM,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACtC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACvE,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,IAAqB,EAAE,OAAgC;YACpE,MAAM,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACxC,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACzE,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,IAAqB,EAAE,OAA+B;YAClE,MAAM,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACzE,CAAC;KACF,CAAC;AACJ,CAAC;AA6CD;;;;;;GAMG;AACH,MAAM,OAAO,eAAe;IAOG;IANrB,SAAS,GAAyB,IAAI,CAAC;IACvC,cAAc,GAA0C,IAAI,CAAC;IAC7D,YAAY,GAA+B,IAAI,CAAC;IAChD,OAAO,GAAG,KAAK,CAAC;IACP,GAAG,CAAe;IAEnC,YAA6B,IAAyB;QAAzB,SAAI,GAAJ,IAAI,CAAqB;QACpD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IAClC,CAAC;IAED,wDAAwD;IACxD,eAAe;QACb,OAAO,IAAI,CAAC,SAAS,EAAE,eAAe,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QAE3C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QACzE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAA8B,CAAC,CAAC;QACvG,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC;QAE7B,MAAM,YAAY,GAA2B;YAC3C,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY;YAChC,0EAA0E;YAC1E,2EAA2E;YAC3E,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvC,CAAC;QACF,MAAM,QAAQ,GAA6B;YACzC,IAAI,EAAE,WAAW;YACjB,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW;YACpC,UAAU,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACjC,iBAAiB,EAAE,YAAY;YAC/B,QAAQ;SACT,CAAC;QACF,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,sBAAsB,EAAE,QAAQ,CAAC,CAAC;QAE3D,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAErD,IAAI,CAAC,SAAS,GAAG,IAAI,aAAa,CAAC;YACjC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ;YAC5B,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;YACxB,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YAC3D,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO;YAC1B,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAC5C,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ;YAC5B,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO;YAC1B,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE;YACvD,yEAAyE;YACzE,eAAe,EAAE,GAAG,EAAE,CAAC,CAAC;YACxB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjF,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvD,CAAC,CAAC;QACH,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC;QAEhD,2EAA2E;QAC3E,2DAA2D;QAC3D,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC;QAC9C,IAAI,CAAC,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;QAClE,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,CAAC;IAChC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACnC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;QACD,gEAAgE;QAChE,IAAI,IAAI,CAAC,SAAS;YAAE,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAChE,8EAA8E;QAC9E,MAAM,IAAI,CAAC,IAAI;aACZ,QAAQ,CAAC,gBAAgB,EAAE;YAC1B,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ;YAC7B,QAAQ,EAAE,YAAmC;YAC7C,oBAAoB,EAAE,EAAE;YACxB,EAAE,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE;SACP,CAAC;aACjC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1B,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC9E,CAAC;IAED,4EAA4E;IACpE,KAAK,CAAC,IAAI;QAChB,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACxC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,4CAA6C,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1F,CAAC,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1F,IAAI,QAAQ,IAAI,QAAQ,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/C,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC;YAC7B,MAAM,IAAI,CAAC,IAAI;iBACZ,QAAQ,CAAC,kBAAkB,EAAE;gBAC5B,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ;gBAC7B,QAAQ;gBACR,oBAAoB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3C,EAAE,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE;aACP,CAAC;iBACjC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB;AACvC,8DAA8D;AAC9D,MAAyF,EACzF,MAAc,EACd,OAA2C,EAAE;IAE7C,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,8DAA8D;IAC9D,IAAI,OAAO,GAAQ,IAAI,CAAC;IACxB,KAAK,UAAU,MAAM;QACnB,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,OAAO,CAAC,SAAS,CAAC,CAAC,MAAc,EAAE,EAAE;gBACnC,IAAI,MAAM,KAAK,YAAY;oBAAE,OAAO,EAAE,CAAC;YACzC,CAAC,CAAC,CAAC;YACH,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QACvC,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO;QACL,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO;YAC3B,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,MAAM,MAAM,EAAE,CAAC;gBAC1B,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YACvD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,KAAK,EAAE,CAAC,mCAAmC,KAAK,aAAc,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9F,CAAC;QACH,CAAC;QACD,KAAK,CAAC,KAAK;YACT,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;gBACtC,CAAC;gBAAC,MAAM,CAAC;oBACP,iBAAiB;gBACnB,CAAC;gBACD,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|