@polpo-ai/core 0.2.4 → 0.3.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/LICENSE +21 -0
- package/dist/assessment-orchestrator.d.ts +124 -0
- package/dist/assessment-orchestrator.d.ts.map +1 -0
- package/dist/assessment-orchestrator.js +790 -0
- package/dist/assessment-orchestrator.js.map +1 -0
- package/dist/assessment-prompts.d.ts +45 -0
- package/dist/assessment-prompts.d.ts.map +1 -0
- package/dist/assessment-prompts.js +205 -0
- package/dist/assessment-prompts.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/mission-executor.d.ts +253 -0
- package/dist/mission-executor.d.ts.map +1 -0
- package/dist/mission-executor.js +1053 -0
- package/dist/mission-executor.js.map +1 -0
- package/dist/orchestrator-context.d.ts +11 -5
- package/dist/orchestrator-context.d.ts.map +1 -1
- package/dist/orchestrator-engine.d.ts +500 -0
- package/dist/orchestrator-engine.d.ts.map +1 -0
- package/dist/orchestrator-engine.js +454 -0
- package/dist/orchestrator-engine.js.map +1 -0
- package/dist/question-detector.d.ts +31 -0
- package/dist/question-detector.d.ts.map +1 -0
- package/dist/question-detector.js +65 -0
- package/dist/question-detector.js.map +1 -0
- package/dist/spawner.d.ts +43 -0
- package/dist/spawner.d.ts.map +1 -0
- package/dist/spawner.js +2 -0
- package/dist/spawner.js.map +1 -0
- package/dist/task-runner.d.ts +43 -0
- package/dist/task-runner.d.ts.map +1 -0
- package/dist/task-runner.js +487 -0
- package/dist/task-runner.js.map +1 -0
- package/package.json +34 -8
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spawner — abstraction for launching agent runner processes.
|
|
3
|
+
*
|
|
4
|
+
* Node.js uses NodeSpawner (child_process.spawn).
|
|
5
|
+
* Cloud uses SandboxSpawner (Daytona sandbox).
|
|
6
|
+
*
|
|
7
|
+
* Same pattern as FileSystem and Shell — pure interface in core,
|
|
8
|
+
* runtime implementations in the shell layer.
|
|
9
|
+
*/
|
|
10
|
+
import type { RunnerConfig } from "./types.js";
|
|
11
|
+
/**
|
|
12
|
+
* Result of spawning a runner process.
|
|
13
|
+
*/
|
|
14
|
+
export interface SpawnResult {
|
|
15
|
+
/** OS process ID (0 for sandbox-based spawners with no local PID). */
|
|
16
|
+
pid: number;
|
|
17
|
+
/** Where the config was persisted ("file:///path" or "db://runId"). */
|
|
18
|
+
configPath: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Interface for spawning agent runner processes.
|
|
22
|
+
*/
|
|
23
|
+
export interface Spawner {
|
|
24
|
+
/**
|
|
25
|
+
* Spawn a runner process for the given config.
|
|
26
|
+
* The spawner is responsible for:
|
|
27
|
+
* - Persisting the RunnerConfig (to file or DB)
|
|
28
|
+
* - Starting the runner process
|
|
29
|
+
* - Returning the PID and config location
|
|
30
|
+
*/
|
|
31
|
+
spawn(config: RunnerConfig): Promise<SpawnResult>;
|
|
32
|
+
/**
|
|
33
|
+
* Check if a process is still alive.
|
|
34
|
+
* Returns false for spawners that don't track OS processes (e.g. sandbox).
|
|
35
|
+
*/
|
|
36
|
+
isAlive(pid: number): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Kill a runner process by PID.
|
|
39
|
+
* No-op for spawners that don't track OS processes (e.g. sandbox).
|
|
40
|
+
*/
|
|
41
|
+
kill(pid: number): void;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=spawner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawner.d.ts","sourceRoot":"","sources":["../src/spawner.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,GAAG,EAAE,MAAM,CAAC;IACZ,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAElD;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAE9B;;;OAGG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB"}
|
package/dist/spawner.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawner.js","sourceRoot":"","sources":["../src/spawner.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { OrchestratorContext } from "./orchestrator-context.js";
|
|
2
|
+
import type { Task, TaskResult } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Spawns, monitors, and collects results from agent runner subprocesses.
|
|
5
|
+
*/
|
|
6
|
+
export declare class TaskRunner {
|
|
7
|
+
private ctx;
|
|
8
|
+
private staleWarned;
|
|
9
|
+
/** Last known activity snapshot per taskId, used to diff and emit SSE events */
|
|
10
|
+
private lastActivity;
|
|
11
|
+
/** Tracks files already seen per task to emit incremental file:changed events */
|
|
12
|
+
private knownFiles;
|
|
13
|
+
constructor(ctx: OrchestratorContext);
|
|
14
|
+
/**
|
|
15
|
+
* Collect results from terminal runs and pass them to the callback.
|
|
16
|
+
* The callback is typically the assessment pipeline (handleResult).
|
|
17
|
+
*/
|
|
18
|
+
collectResults(onResult: (taskId: string, result: TaskResult) => void): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Read the JSONL activity log for a killed run and produce a human-readable
|
|
21
|
+
* diagnosis of what the agent was doing when it timed out.
|
|
22
|
+
* This gets appended to stderr so buildRetryPrompt includes it automatically.
|
|
23
|
+
*/
|
|
24
|
+
private buildTimeoutDiagnosis;
|
|
25
|
+
/**
|
|
26
|
+
* Enforce task timeouts and detect stale agents via RunStore active runs.
|
|
27
|
+
* - Hard kill at maxDuration (or default taskTimeout)
|
|
28
|
+
* - Warn at staleThreshold, kill at 2x staleThreshold
|
|
29
|
+
*/
|
|
30
|
+
enforceHealthChecks(): Promise<void>;
|
|
31
|
+
/** Sync process list from RunStore into the old processes table for backward compat.
|
|
32
|
+
* Also emits `agent:activity` SSE events when activity changes (diff-based). */
|
|
33
|
+
syncProcessesFromRunStore(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Recover tasks left in limbo from a previous crash.
|
|
36
|
+
* Resets orphaned tasks to pending WITHOUT burning retry count.
|
|
37
|
+
*/
|
|
38
|
+
recoverOrphanedTasks(): Promise<number>;
|
|
39
|
+
isProcessAlive(pid: number): boolean;
|
|
40
|
+
spawnForTask(task: Task): Promise<void>;
|
|
41
|
+
private killOrphanProcess;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=task-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-runner.d.ts","sourceRoot":"","sources":["../src/task-runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAgB,MAAM,YAAY,CAAC;AAqBjE;;GAEG;AACH,qBAAa,UAAU;IAOT,OAAO,CAAC,GAAG;IANvB,OAAO,CAAC,WAAW,CAAqB;IACxC,gFAAgF;IAChF,OAAO,CAAC,YAAY,CAA6B;IACjD,iFAAiF;IACjF,OAAO,CAAC,UAAU,CAAkC;gBAEhC,GAAG,EAAE,mBAAmB;IAE5C;;;OAGG;IACG,cAAc,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAuC3F;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAyF7B;;;;OAIG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAkD1C;qFACiF;IAC3E,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC;IAyDhD;;;OAGG;IACG,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;IAsD7C,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI9B,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAwK7C,OAAO,CAAC,iBAAiB;CAK1B"}
|
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
import { nanoid } from "nanoid";
|
|
2
|
+
import { agentMemoryScope } from "./memory-store.js";
|
|
3
|
+
// ── Pure path helpers (no node:path dependency) ─────────────────────────
|
|
4
|
+
/** Join path segments with '/'. */
|
|
5
|
+
function pathJoin(...parts) {
|
|
6
|
+
return parts
|
|
7
|
+
.map((p, i) => (i === 0 ? p.replace(/\/+$/, "") : p.replace(/^\/+|\/+$/g, "")))
|
|
8
|
+
.filter(Boolean)
|
|
9
|
+
.join("/");
|
|
10
|
+
}
|
|
11
|
+
/** Return the directory portion of a path. */
|
|
12
|
+
function pathDirname(p) {
|
|
13
|
+
const idx = p.lastIndexOf("/");
|
|
14
|
+
if (idx <= 0)
|
|
15
|
+
return idx === 0 ? "/" : ".";
|
|
16
|
+
return p.slice(0, idx);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Spawns, monitors, and collects results from agent runner subprocesses.
|
|
20
|
+
*/
|
|
21
|
+
export class TaskRunner {
|
|
22
|
+
ctx;
|
|
23
|
+
staleWarned = new Set();
|
|
24
|
+
/** Last known activity snapshot per taskId, used to diff and emit SSE events */
|
|
25
|
+
lastActivity = new Map();
|
|
26
|
+
/** Tracks files already seen per task to emit incremental file:changed events */
|
|
27
|
+
knownFiles = new Map();
|
|
28
|
+
constructor(ctx) {
|
|
29
|
+
this.ctx = ctx;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Collect results from terminal runs and pass them to the callback.
|
|
33
|
+
* The callback is typically the assessment pipeline (handleResult).
|
|
34
|
+
*/
|
|
35
|
+
async collectResults(onResult) {
|
|
36
|
+
const terminalRuns = await this.ctx.runStore.getTerminalRuns();
|
|
37
|
+
for (const run of terminalRuns) {
|
|
38
|
+
// Persist sessionId on the task before deleting the run
|
|
39
|
+
const sid = run.sessionId ?? run.activity.sessionId;
|
|
40
|
+
if (sid) {
|
|
41
|
+
try {
|
|
42
|
+
await this.ctx.registry.updateTask(run.taskId, { sessionId: sid });
|
|
43
|
+
}
|
|
44
|
+
catch { /* task may already be gone */ }
|
|
45
|
+
}
|
|
46
|
+
// Persist auto-collected outcomes on the task.
|
|
47
|
+
// REPLACE (not append) — each execution produces its own definitive outcomes.
|
|
48
|
+
// Appending caused "exponential outcome" accumulation across retries/fix cycles.
|
|
49
|
+
if (run.outcomes && run.outcomes.length > 0) {
|
|
50
|
+
try {
|
|
51
|
+
await this.ctx.registry.updateTask(run.taskId, { outcomes: run.outcomes });
|
|
52
|
+
}
|
|
53
|
+
catch { /* task may already be gone */ }
|
|
54
|
+
}
|
|
55
|
+
if (run.result) {
|
|
56
|
+
// A killed run must never be treated as successful — force exitCode=1
|
|
57
|
+
// even if the adapter resolved cleanly before the kill took effect.
|
|
58
|
+
if (run.status === "killed" && run.result.exitCode === 0) {
|
|
59
|
+
run.result.exitCode = 1;
|
|
60
|
+
run.result.stderr = (run.result.stderr ? run.result.stderr + "\n" : "") + "Run was killed (timeout or shutdown)";
|
|
61
|
+
}
|
|
62
|
+
// For killed runs, build a diagnosis from the activity log so the retry
|
|
63
|
+
// prompt tells the agent exactly what went wrong (e.g. "you got stuck
|
|
64
|
+
// running `python3 server.py &` for 120s").
|
|
65
|
+
if (run.status === "killed") {
|
|
66
|
+
const diagnosis = this.buildTimeoutDiagnosis(run);
|
|
67
|
+
if (diagnosis) {
|
|
68
|
+
run.result.stderr = (run.result.stderr ? run.result.stderr + "\n" : "") + diagnosis;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
onResult(run.taskId, run.result);
|
|
72
|
+
}
|
|
73
|
+
await this.ctx.runStore.deleteRun(run.id);
|
|
74
|
+
this.staleWarned.delete(run.taskId);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Read the JSONL activity log for a killed run and produce a human-readable
|
|
79
|
+
* diagnosis of what the agent was doing when it timed out.
|
|
80
|
+
* This gets appended to stderr so buildRetryPrompt includes it automatically.
|
|
81
|
+
*/
|
|
82
|
+
buildTimeoutDiagnosis(run) {
|
|
83
|
+
try {
|
|
84
|
+
// Use the context port to read log content (shell provides the implementation)
|
|
85
|
+
const content = this.ctx.readRunLog?.(run.id);
|
|
86
|
+
if (!content)
|
|
87
|
+
return null;
|
|
88
|
+
const lines = content.trim().split("\n");
|
|
89
|
+
// Parse last N entries (skip header)
|
|
90
|
+
const entries = [];
|
|
91
|
+
for (const line of lines) {
|
|
92
|
+
try {
|
|
93
|
+
entries.push(JSON.parse(line));
|
|
94
|
+
}
|
|
95
|
+
catch { /* skip malformed */ }
|
|
96
|
+
}
|
|
97
|
+
if (entries.length === 0)
|
|
98
|
+
return null;
|
|
99
|
+
// Gather stats
|
|
100
|
+
const toolUses = entries.filter(e => e.type === "tool_use");
|
|
101
|
+
const toolResults = entries.filter(e => e.type === "tool_result");
|
|
102
|
+
const assistantMsgs = entries.filter(e => e.type === "assistant");
|
|
103
|
+
const activitySnaps = entries.filter(e => e.event === "activity");
|
|
104
|
+
// Find the last tool_use (likely the one that blocked)
|
|
105
|
+
const lastToolUse = toolUses[toolUses.length - 1];
|
|
106
|
+
const lastToolResult = toolResults[toolResults.length - 1];
|
|
107
|
+
// Check if last tool_use has no matching result (= it was the blocking call)
|
|
108
|
+
const lastToolId = lastToolUse?.toolId;
|
|
109
|
+
const lastResultId = lastToolResult?.toolId;
|
|
110
|
+
const wasBlocking = lastToolId && lastToolId !== lastResultId;
|
|
111
|
+
// Get activity stats from last snapshot
|
|
112
|
+
const lastSnap = activitySnaps[activitySnaps.length - 1];
|
|
113
|
+
const snapData = lastSnap?.data;
|
|
114
|
+
const parts = [
|
|
115
|
+
``,
|
|
116
|
+
`TIMEOUT DIAGNOSIS:`,
|
|
117
|
+
`- Total tool calls attempted: ${toolUses.length}`,
|
|
118
|
+
`- Total tool results received: ${toolResults.length}`,
|
|
119
|
+
`- Files created: ${snapData?.filesCreated?.length ?? 0}`,
|
|
120
|
+
`- Files edited: ${snapData?.filesEdited?.length ?? 0}`,
|
|
121
|
+
];
|
|
122
|
+
if (wasBlocking && lastToolUse) {
|
|
123
|
+
const tool = lastToolUse.tool;
|
|
124
|
+
const input = lastToolUse.input;
|
|
125
|
+
parts.push(``, `BLOCKED ON: tool="${tool}"`);
|
|
126
|
+
if (tool === "bash" && input?.command) {
|
|
127
|
+
const cmd = String(input.command);
|
|
128
|
+
parts.push(`Command that hung: ${cmd.slice(0, 500)}`, ``, `DO NOT repeat this command. It blocks forever.`, `If you need to start a server, use: nohup <cmd> > /tmp/server.log 2>&1 & echo "PID=$!"`, `Then verify with a SEPARATE bash call: curl --max-time 5 http://127.0.0.1:<port>/`, `NEVER combine server start + verification in one command.`, `NEVER use lsof or netstat to check servers — use curl.`);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
parts.push(`Input: ${JSON.stringify(input ?? {}).slice(0, 500)}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
// Last tool completed — agent might have been in a loop or LLM was slow
|
|
136
|
+
const lastAssistant = assistantMsgs[assistantMsgs.length - 1];
|
|
137
|
+
if (lastAssistant?.text) {
|
|
138
|
+
parts.push(`Last agent message: ${String(lastAssistant.text).slice(0, 300)}`);
|
|
139
|
+
}
|
|
140
|
+
if (lastToolUse) {
|
|
141
|
+
parts.push(`Last completed tool: ${lastToolUse.tool}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// List files created so agent knows what's already done
|
|
145
|
+
const filesCreated = snapData?.filesCreated ?? [];
|
|
146
|
+
const filesEdited = snapData?.filesEdited ?? [];
|
|
147
|
+
if (filesCreated.length > 0 || filesEdited.length > 0) {
|
|
148
|
+
parts.push(``, `WORK ALREADY DONE (do not redo):`);
|
|
149
|
+
if (filesCreated.length > 0)
|
|
150
|
+
parts.push(`Created: ${filesCreated.join(", ")}`);
|
|
151
|
+
if (filesEdited.length > 0)
|
|
152
|
+
parts.push(`Edited: ${filesEdited.join(", ")}`);
|
|
153
|
+
}
|
|
154
|
+
return parts.join("\n");
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Enforce task timeouts and detect stale agents via RunStore active runs.
|
|
162
|
+
* - Hard kill at maxDuration (or default taskTimeout)
|
|
163
|
+
* - Warn at staleThreshold, kill at 2x staleThreshold
|
|
164
|
+
*/
|
|
165
|
+
async enforceHealthChecks() {
|
|
166
|
+
const defaultTimeout = this.ctx.config.settings.taskTimeout ?? 30 * 60 * 1000;
|
|
167
|
+
const staleThreshold = this.ctx.config.settings.staleThreshold ?? 5 * 60 * 1000;
|
|
168
|
+
const activeRuns = await this.ctx.runStore.getActiveRuns();
|
|
169
|
+
for (const run of activeRuns) {
|
|
170
|
+
// 1. Task timeout (hard kill)
|
|
171
|
+
const task = await this.ctx.registry.getTask(run.taskId);
|
|
172
|
+
const timeout = task?.maxDuration ?? defaultTimeout;
|
|
173
|
+
if (timeout > 0) {
|
|
174
|
+
const elapsed = Date.now() - new Date(run.startedAt).getTime();
|
|
175
|
+
if (elapsed > timeout) {
|
|
176
|
+
this.ctx.emitter.emit("log", { level: "warn", message: `[${run.taskId}] Timed out (${Math.round(elapsed / 1000)}s)` });
|
|
177
|
+
this.ctx.emitter.emit("task:timeout", { taskId: run.taskId, elapsed, timeout });
|
|
178
|
+
if (run.pid > 0) {
|
|
179
|
+
try {
|
|
180
|
+
this.ctx.spawner.kill(run.pid);
|
|
181
|
+
}
|
|
182
|
+
catch { /* already dead */ }
|
|
183
|
+
}
|
|
184
|
+
// Mark run as killed so we don't retry every tick
|
|
185
|
+
await this.ctx.runStore.completeRun(run.id, "killed", {
|
|
186
|
+
exitCode: 1, stdout: "", stderr: `Timed out after ${Math.round(elapsed / 1000)}s`, duration: elapsed,
|
|
187
|
+
});
|
|
188
|
+
this.staleWarned.delete(run.taskId);
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// 2. Stale detection (warning at 1x, kill at 2x)
|
|
193
|
+
if (staleThreshold > 0 && run.activity.lastUpdate) {
|
|
194
|
+
const idle = Date.now() - new Date(run.activity.lastUpdate).getTime();
|
|
195
|
+
if (idle > staleThreshold * 2) {
|
|
196
|
+
this.ctx.emitter.emit("log", { level: "error", message: `[${run.taskId}] Agent unresponsive for ${Math.round(idle / 1000)}s — killing` });
|
|
197
|
+
this.ctx.emitter.emit("agent:stale", { taskId: run.taskId, agentName: run.agentName, idleMs: idle, action: "killed" });
|
|
198
|
+
if (run.pid > 0) {
|
|
199
|
+
try {
|
|
200
|
+
this.ctx.spawner.kill(run.pid);
|
|
201
|
+
}
|
|
202
|
+
catch { /* already dead */ }
|
|
203
|
+
}
|
|
204
|
+
// Mark run as killed so we don't retry every tick
|
|
205
|
+
await this.ctx.runStore.completeRun(run.id, "killed", {
|
|
206
|
+
exitCode: 1, stdout: "", stderr: `Agent unresponsive for ${Math.round(idle / 1000)}s`, duration: idle,
|
|
207
|
+
});
|
|
208
|
+
this.staleWarned.delete(run.taskId);
|
|
209
|
+
}
|
|
210
|
+
else if (idle > staleThreshold && !this.staleWarned.has(run.taskId)) {
|
|
211
|
+
this.ctx.emitter.emit("agent:stale", { taskId: run.taskId, agentName: run.agentName, idleMs: idle, action: "warning" });
|
|
212
|
+
this.ctx.emitter.emit("log", { level: "warn", message: `[${run.taskId}] Agent idle for ${Math.round(idle / 1000)}s — may be stuck` });
|
|
213
|
+
this.staleWarned.add(run.taskId);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/** Sync process list from RunStore into the old processes table for backward compat.
|
|
219
|
+
* Also emits `agent:activity` SSE events when activity changes (diff-based). */
|
|
220
|
+
async syncProcessesFromRunStore() {
|
|
221
|
+
const active = await this.ctx.runStore.getActiveRuns();
|
|
222
|
+
// Emit agent:activity for each run whose activity snapshot changed
|
|
223
|
+
const seenTaskIds = new Set();
|
|
224
|
+
for (const r of active) {
|
|
225
|
+
seenTaskIds.add(r.taskId);
|
|
226
|
+
const snapshot = JSON.stringify(r.activity);
|
|
227
|
+
const prev = this.lastActivity.get(r.taskId);
|
|
228
|
+
if (prev !== snapshot) {
|
|
229
|
+
this.lastActivity.set(r.taskId, snapshot);
|
|
230
|
+
this.ctx.emitter.emit("agent:activity", {
|
|
231
|
+
taskId: r.taskId,
|
|
232
|
+
agentName: r.agentName,
|
|
233
|
+
tool: r.activity.lastTool,
|
|
234
|
+
file: r.activity.lastFile,
|
|
235
|
+
summary: r.activity.summary,
|
|
236
|
+
});
|
|
237
|
+
// Emit file:changed for newly created/edited files
|
|
238
|
+
let known = this.knownFiles.get(r.taskId);
|
|
239
|
+
if (!known) {
|
|
240
|
+
known = new Set();
|
|
241
|
+
this.knownFiles.set(r.taskId, known);
|
|
242
|
+
}
|
|
243
|
+
for (const f of r.activity.filesCreated ?? []) {
|
|
244
|
+
if (!known.has(f)) {
|
|
245
|
+
known.add(f);
|
|
246
|
+
this.ctx.emitter.emit("file:changed", { path: f, dir: pathDirname(f), action: "created", source: "agent" });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
for (const f of r.activity.filesEdited ?? []) {
|
|
250
|
+
if (!known.has(f)) {
|
|
251
|
+
known.add(f);
|
|
252
|
+
this.ctx.emitter.emit("file:changed", { path: f, dir: pathDirname(f), action: "modified", source: "agent" });
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// Cleanup stale entries for tasks no longer active
|
|
258
|
+
for (const taskId of this.lastActivity.keys()) {
|
|
259
|
+
if (!seenTaskIds.has(taskId)) {
|
|
260
|
+
this.lastActivity.delete(taskId);
|
|
261
|
+
this.knownFiles.delete(taskId);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
await this.ctx.registry.setState({
|
|
265
|
+
processes: active.map(r => ({
|
|
266
|
+
agentName: r.agentName,
|
|
267
|
+
pid: r.pid,
|
|
268
|
+
taskId: r.taskId,
|
|
269
|
+
startedAt: r.startedAt,
|
|
270
|
+
alive: true,
|
|
271
|
+
activity: r.activity,
|
|
272
|
+
})),
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Recover tasks left in limbo from a previous crash.
|
|
277
|
+
* Resets orphaned tasks to pending WITHOUT burning retry count.
|
|
278
|
+
*/
|
|
279
|
+
async recoverOrphanedTasks() {
|
|
280
|
+
// Check RunStore active runs first
|
|
281
|
+
const activeRuns = await this.ctx.runStore.getActiveRuns();
|
|
282
|
+
for (const run of activeRuns) {
|
|
283
|
+
if (this.isProcessAlive(run.pid)) {
|
|
284
|
+
// Runner still alive — leave it running, work is NOT lost!
|
|
285
|
+
this.ctx.emitter.emit("log", { level: "info", message: `Runner PID ${run.pid} still alive for task ${run.taskId} — reconnecting` });
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
// Runner died — clean up the run record
|
|
289
|
+
await this.ctx.runStore.completeRun(run.id, "failed", {
|
|
290
|
+
exitCode: 1, stdout: "", stderr: "Runner process died", duration: 0,
|
|
291
|
+
});
|
|
292
|
+
await this.ctx.runStore.deleteRun(run.id);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// Backward compat: kill orphan OS processes from old processes table
|
|
296
|
+
const state = await this.ctx.registry.getState();
|
|
297
|
+
for (const proc of state.processes) {
|
|
298
|
+
if (proc.pid > 0 && proc.alive) {
|
|
299
|
+
this.killOrphanProcess(proc.pid, proc.agentName);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
const tasks = await this.ctx.registry.getAllTasks();
|
|
303
|
+
const orphanStates = new Set(["assigned", "in_progress", "review"]);
|
|
304
|
+
let recovered = 0;
|
|
305
|
+
for (const task of tasks) {
|
|
306
|
+
if (!orphanStates.has(task.status))
|
|
307
|
+
continue;
|
|
308
|
+
// Check if there's a live runner for this task
|
|
309
|
+
const run = await this.ctx.runStore.getRunByTaskId(task.id);
|
|
310
|
+
if (run && run.status === "running" && this.isProcessAlive(run.pid)) {
|
|
311
|
+
// Runner still working — skip recovery for this task
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
// Recover: reset to pending WITHOUT incrementing retries.
|
|
315
|
+
// Shutdown interrupts are not real failures — unsafeSetStatus bypasses
|
|
316
|
+
// transition(failed → pending) which would burn a retry.
|
|
317
|
+
this.ctx.emitter.emit("task:recovered", { taskId: task.id, title: task.title, previousStatus: task.status });
|
|
318
|
+
await this.ctx.registry.unsafeSetStatus(task.id, "pending", "orphan recovery — shutdown interrupt");
|
|
319
|
+
recovered++;
|
|
320
|
+
}
|
|
321
|
+
// Clear stale process list
|
|
322
|
+
if (recovered > 0 || tasks.some(t => orphanStates.has(t.status))) {
|
|
323
|
+
await this.ctx.registry.setState({ processes: [] });
|
|
324
|
+
}
|
|
325
|
+
return recovered;
|
|
326
|
+
}
|
|
327
|
+
isProcessAlive(pid) {
|
|
328
|
+
return this.ctx.spawner.isAlive(pid);
|
|
329
|
+
}
|
|
330
|
+
async spawnForTask(task) {
|
|
331
|
+
const agent = await this.ctx.agentStore.getAgent(task.assignTo);
|
|
332
|
+
if (!agent) {
|
|
333
|
+
this.ctx.emitter.emit("log", { level: "error", message: `No agent "${task.assignTo}" for task "${task.title}"` });
|
|
334
|
+
await this.ctx.registry.transition(task.id, "assigned");
|
|
335
|
+
await this.ctx.registry.transition(task.id, "in_progress");
|
|
336
|
+
await this.ctx.registry.transition(task.id, "failed");
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
// Fail fast if the agent's model provider has no API key
|
|
340
|
+
if (agent.model && this.ctx.validateProviderKeys) {
|
|
341
|
+
const missing = this.ctx.validateProviderKeys([agent.model]);
|
|
342
|
+
if (missing.length > 0) {
|
|
343
|
+
const detail = missing.map(m => `${m.provider} (${m.modelSpec})`).join(", ");
|
|
344
|
+
this.ctx.emitter.emit("log", {
|
|
345
|
+
level: "error",
|
|
346
|
+
message: `[${task.id}] Missing API key for ${detail} — cannot spawn agent "${agent.name}"`,
|
|
347
|
+
});
|
|
348
|
+
await this.ctx.registry.transition(task.id, "assigned");
|
|
349
|
+
await this.ctx.registry.transition(task.id, "in_progress");
|
|
350
|
+
await this.ctx.registry.transition(task.id, "failed");
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// Run before:task:spawn hook (sync — tick loop is synchronous)
|
|
355
|
+
const hookResult = this.ctx.hooks.runBeforeSync("task:spawn", { task, agent });
|
|
356
|
+
if (hookResult.cancelled) {
|
|
357
|
+
this.ctx.emitter.emit("log", {
|
|
358
|
+
level: "info",
|
|
359
|
+
message: `[${task.id}] Spawn blocked by hook: ${hookResult.cancelReason ?? "no reason"}`,
|
|
360
|
+
});
|
|
361
|
+
return; // task stays pending — will be re-evaluated next tick
|
|
362
|
+
}
|
|
363
|
+
await this.ctx.registry.transition(task.id, "assigned");
|
|
364
|
+
await this.ctx.registry.transition(task.id, "in_progress");
|
|
365
|
+
// Set phase if not already set (new tasks start in execution phase)
|
|
366
|
+
if (!task.phase) {
|
|
367
|
+
await this.ctx.registry.updateTask(task.id, { phase: "execution" });
|
|
368
|
+
}
|
|
369
|
+
const runId = nanoid();
|
|
370
|
+
// Create per-task output directory for deliverables
|
|
371
|
+
const outputDir = pathJoin(this.ctx.polpoDir, "output", task.id);
|
|
372
|
+
// Inject context into task description for agent awareness.
|
|
373
|
+
// Context is prepended using XML-like tags that the agent prompt can reference.
|
|
374
|
+
const taskWithContext = { ...task };
|
|
375
|
+
const contextParts = [];
|
|
376
|
+
// 1. Shared memory (persistent cross-session knowledge, visible to all agents)
|
|
377
|
+
const sharedMemory = (await this.ctx.memoryStore?.get()) ?? "";
|
|
378
|
+
if (sharedMemory) {
|
|
379
|
+
contextParts.push(`<shared-memory>\n${sharedMemory}\n</shared-memory>`);
|
|
380
|
+
}
|
|
381
|
+
// 1b. Agent-specific memory (private knowledge for the assigned agent)
|
|
382
|
+
if (task.assignTo) {
|
|
383
|
+
const agentMem = (await this.ctx.memoryStore?.get(agentMemoryScope(task.assignTo))) ?? "";
|
|
384
|
+
if (agentMem) {
|
|
385
|
+
contextParts.push(`<agent-memory agent="${task.assignTo}">\n${agentMem}\n</agent-memory>`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// 2. Mission context — if this task belongs to a mission, include the mission goal and sibling tasks
|
|
389
|
+
if (task.group) {
|
|
390
|
+
try {
|
|
391
|
+
// Resolve mission via direct ID (preferred) or group name (legacy fallback)
|
|
392
|
+
const mission = task.missionId
|
|
393
|
+
? await this.ctx.registry.getMission?.(task.missionId)
|
|
394
|
+
: await this.ctx.registry.getMissionByName?.(task.group);
|
|
395
|
+
const missionParts = [];
|
|
396
|
+
// Original user prompt that generated this mission (the "why")
|
|
397
|
+
if (mission?.prompt) {
|
|
398
|
+
missionParts.push(`Mission goal: ${mission.prompt}`);
|
|
399
|
+
}
|
|
400
|
+
// Sibling tasks — just titles and statuses for awareness, not full descriptions
|
|
401
|
+
const allTasks = await this.ctx.registry.getAllTasks();
|
|
402
|
+
const siblings = allTasks.filter(t => t.group === task.group && t.id !== task.id);
|
|
403
|
+
if (siblings.length > 0) {
|
|
404
|
+
missionParts.push(`Other tasks in this mission:`);
|
|
405
|
+
for (const s of siblings) {
|
|
406
|
+
const marker = s.status === "done" ? "[done]"
|
|
407
|
+
: s.status === "in_progress" ? "[in progress]"
|
|
408
|
+
: s.status === "failed" ? "[failed]"
|
|
409
|
+
: "[pending]";
|
|
410
|
+
missionParts.push(` ${marker} "${s.title}" → ${s.assignTo}`);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
if (missionParts.length > 0) {
|
|
414
|
+
contextParts.push(`<mission-context>\n${missionParts.join("\n")}\n</mission-context>`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
catch { /* best effort — mission may have been deleted */ }
|
|
418
|
+
}
|
|
419
|
+
if (contextParts.length > 0) {
|
|
420
|
+
taskWithContext.description = contextParts.join("\n\n") + "\n\n" + task.description;
|
|
421
|
+
}
|
|
422
|
+
// WhatsApp tools: if agent has whatsapp_* in allowedTools and a WhatsApp channel is configured,
|
|
423
|
+
// pass the DB path and profile path so the runner can create its own store + connection
|
|
424
|
+
let whatsappDbPath;
|
|
425
|
+
let whatsappProfilePath;
|
|
426
|
+
if (agent.allowedTools?.some(t => t.toLowerCase().startsWith("whatsapp_"))) {
|
|
427
|
+
const channels = this.ctx.config.settings.notifications?.channels;
|
|
428
|
+
if (channels) {
|
|
429
|
+
const waKey = Object.keys(channels).find(k => channels[k]?.type === "whatsapp");
|
|
430
|
+
if (waKey) {
|
|
431
|
+
whatsappDbPath = pathJoin(this.ctx.polpoDir, "whatsapp.db");
|
|
432
|
+
const profileName = channels[waKey].profileDir ?? "default";
|
|
433
|
+
whatsappProfilePath = pathJoin(this.ctx.polpoDir, "whatsapp-profiles", profileName);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
const runnerConfig = {
|
|
438
|
+
runId,
|
|
439
|
+
taskId: task.id,
|
|
440
|
+
agent,
|
|
441
|
+
task: taskWithContext,
|
|
442
|
+
polpoDir: this.ctx.polpoDir,
|
|
443
|
+
cwd: this.ctx.agentWorkDir,
|
|
444
|
+
outputDir,
|
|
445
|
+
storage: this.ctx.config.settings.storage,
|
|
446
|
+
databaseUrl: this.ctx.config.settings.databaseUrl,
|
|
447
|
+
notifySocket: this.ctx.notifySocketPath,
|
|
448
|
+
emailAllowedDomains: agent.emailAllowedDomains ?? this.ctx.config.settings.emailAllowedDomains,
|
|
449
|
+
reasoning: this.ctx.config.settings.reasoning,
|
|
450
|
+
whatsappDbPath,
|
|
451
|
+
whatsappProfilePath,
|
|
452
|
+
};
|
|
453
|
+
try {
|
|
454
|
+
const spawnResult = await this.ctx.spawner.spawn(runnerConfig);
|
|
455
|
+
const now = new Date().toISOString();
|
|
456
|
+
const runRecord = {
|
|
457
|
+
id: runId,
|
|
458
|
+
taskId: task.id,
|
|
459
|
+
pid: spawnResult.pid,
|
|
460
|
+
agentName: agent.name,
|
|
461
|
+
status: "running",
|
|
462
|
+
startedAt: now,
|
|
463
|
+
updatedAt: now,
|
|
464
|
+
activity: { filesCreated: [], filesEdited: [], toolCalls: 0, totalTokens: 0, lastUpdate: now },
|
|
465
|
+
configPath: spawnResult.configPath,
|
|
466
|
+
};
|
|
467
|
+
await this.ctx.runStore.upsertRun(runRecord);
|
|
468
|
+
this.ctx.emitter.emit("agent:spawned", {
|
|
469
|
+
taskId: task.id,
|
|
470
|
+
agentName: agent.name,
|
|
471
|
+
taskTitle: task.title,
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
catch (err) {
|
|
475
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
476
|
+
this.ctx.emitter.emit("log", { level: "error", message: `[${task.id}] Failed to spawn runner: ${message}` });
|
|
477
|
+
await this.ctx.registry.transition(task.id, "failed");
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
killOrphanProcess(pid, agentName) {
|
|
481
|
+
if (!this.ctx.spawner.isAlive(pid))
|
|
482
|
+
return;
|
|
483
|
+
this.ctx.emitter.emit("log", { level: "warn", message: `Killing orphan process PID ${pid} (${agentName})` });
|
|
484
|
+
this.ctx.spawner.kill(pid);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
//# sourceMappingURL=task-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-runner.js","sourceRoot":"","sources":["../src/task-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD,2EAA2E;AAE3E,mCAAmC;AACnC,SAAS,QAAQ,CAAC,GAAG,KAAe;IAClC,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC;SAC9E,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,8CAA8C;AAC9C,SAAS,WAAW,CAAC,CAAS;IAC5B,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3C,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,UAAU;IAOD;IANZ,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,gFAAgF;IACxE,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IACjD,iFAAiF;IACzE,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAC;IAEpD,YAAoB,GAAwB;QAAxB,QAAG,GAAH,GAAG,CAAqB;IAAG,CAAC;IAEhD;;;OAGG;IACH,KAAK,CAAC,cAAc,CAAC,QAAsD;QACzE,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC;QAC/D,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAC/B,wDAAwD;YACxD,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;YACpD,IAAI,GAAG,EAAE,CAAC;gBACR,IAAI,CAAC;oBAAC,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,8BAA8B,CAAC,CAAC;YACtH,CAAC;YACD,+CAA+C;YAC/C,8EAA8E;YAC9E,iFAAiF;YACjF,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC7E,CAAC;gBAAC,MAAM,CAAC,CAAC,8BAA8B,CAAC,CAAC;YAC5C,CAAC;YACD,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;gBACf,sEAAsE;gBACtE,oEAAoE;gBACpE,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;oBACzD,GAAG,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC;oBACxB,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,sCAAsC,CAAC;gBACnH,CAAC;gBACD,wEAAwE;gBACxE,sEAAsE;gBACtE,4CAA4C;gBAC5C,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;oBAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;oBAClD,IAAI,SAAS,EAAE,CAAC;wBACd,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;oBACtF,CAAC;gBACH,CAAC;gBACD,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;YACD,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1C,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,qBAAqB,CAAC,GAAc;QAC1C,IAAI,CAAC;YACH,+EAA+E;YAC/E,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC9C,IAAI,CAAC,OAAO;gBAAE,OAAO,IAAI,CAAC;YAE1B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzC,qCAAqC;YACrC,MAAM,OAAO,GAAmC,EAAE,CAAC;YACnD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC;oBAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC,CAAC;YACxE,CAAC;YACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YAEtC,eAAe;YACf,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;YAC5D,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC;YAClE,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;YAClE,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC;YAElE,uDAAuD;YACvD,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAClD,MAAM,cAAc,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAE3D,6EAA6E;YAC7E,MAAM,UAAU,GAAG,WAAW,EAAE,MAA4B,CAAC;YAC7D,MAAM,YAAY,GAAG,cAAc,EAAE,MAA4B,CAAC;YAClE,MAAM,WAAW,GAAG,UAAU,IAAI,UAAU,KAAK,YAAY,CAAC;YAE9D,wCAAwC;YACxC,MAAM,QAAQ,GAAG,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACzD,MAAM,QAAQ,GAAG,QAAQ,EAAE,IAA2C,CAAC;YAEvE,MAAM,KAAK,GAAG;gBACZ,EAAE;gBACF,oBAAoB;gBACpB,iCAAiC,QAAQ,CAAC,MAAM,EAAE;gBAClD,kCAAkC,WAAW,CAAC,MAAM,EAAE;gBACtD,oBAAqB,QAAQ,EAAE,YAAqC,EAAE,MAAM,IAAI,CAAC,EAAE;gBACnF,mBAAoB,QAAQ,EAAE,WAAoC,EAAE,MAAM,IAAI,CAAC,EAAE;aAClF,CAAC;YAEF,IAAI,WAAW,IAAI,WAAW,EAAE,CAAC;gBAC/B,MAAM,IAAI,GAAG,WAAW,CAAC,IAAc,CAAC;gBACxC,MAAM,KAAK,GAAG,WAAW,CAAC,KAA4C,CAAC;gBACvE,KAAK,CAAC,IAAI,CACR,EAAE,EACF,qBAAqB,IAAI,GAAG,CAC7B,CAAC;gBACF,IAAI,IAAI,KAAK,MAAM,IAAI,KAAK,EAAE,OAAO,EAAE,CAAC;oBACtC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;oBAClC,KAAK,CAAC,IAAI,CACR,sBAAsB,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EACzC,EAAE,EACF,gDAAgD,EAChD,wFAAwF,EACxF,mFAAmF,EACnF,2DAA2D,EAC3D,wDAAwD,CACzD,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBACpE,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,wEAAwE;gBACxE,MAAM,aAAa,GAAG,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAC9D,IAAI,aAAa,EAAE,IAAI,EAAE,CAAC;oBACxB,KAAK,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBAChF,CAAC;gBACD,IAAI,WAAW,EAAE,CAAC;oBAChB,KAAK,CAAC,IAAI,CAAC,wBAAwB,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;gBACzD,CAAC;YACH,CAAC;YAED,wDAAwD;YACxD,MAAM,YAAY,GAAI,QAAQ,EAAE,YAAqC,IAAI,EAAE,CAAC;YAC5E,MAAM,WAAW,GAAI,QAAQ,EAAE,WAAoC,IAAI,EAAE,CAAC;YAC1E,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,kCAAkC,CAAC,CAAC;gBACnD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,YAAY,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC/E,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,WAAW,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9E,CAAC;YAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,mBAAmB;QACvB,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAC9E,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAEhF,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC3D,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,8BAA8B;YAC9B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACzD,MAAM,OAAO,GAAG,IAAI,EAAE,WAAW,IAAI,cAAc,CAAC;YACpD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBAChB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC/D,IAAI,OAAO,GAAG,OAAO,EAAE,CAAC;oBACtB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC,MAAM,gBAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;oBACvH,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;oBAChF,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;wBAChB,IAAI,CAAC;4BAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;wBAAC,CAAC;wBAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;oBACtE,CAAC;oBACD,kDAAkD;oBAClD,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE;wBACpD,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,mBAAmB,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO;qBACrG,CAAC,CAAC;oBACH,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBACpC,SAAS;gBACX,CAAC;YACH,CAAC;YAED,iDAAiD;YACjD,IAAI,cAAc,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAClD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;gBAEtE,IAAI,IAAI,GAAG,cAAc,GAAG,CAAC,EAAE,CAAC;oBAC9B,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC,MAAM,4BAA4B,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;oBAC1I,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;oBACvH,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;wBAChB,IAAI,CAAC;4BAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;wBAAC,CAAC;wBAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;oBACtE,CAAC;oBACD,kDAAkD;oBAClD,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE;wBACpD,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,0BAA0B,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI;qBACtG,CAAC,CAAC;oBACH,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACtC,CAAC;qBAAM,IAAI,IAAI,GAAG,cAAc,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;oBACtE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;oBACxH,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC,MAAM,oBAAoB,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC;oBACtI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACnC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;qFACiF;IACjF,KAAK,CAAC,yBAAyB;QAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAEvD,mEAAmE;QACnE,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC7C,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;gBAC1C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE;oBACtC,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,SAAS,EAAE,CAAC,CAAC,SAAS;oBACtB,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ;oBACzB,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ;oBACzB,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO;iBAC5B,CAAC,CAAC;gBAEH,mDAAmD;gBACnD,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;oBAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;oBAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;gBAAC,CAAC;gBACxE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;oBAC9C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;wBAClB,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;wBACb,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;oBAC9G,CAAC;gBACH,CAAC;gBACD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;oBAC7C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;wBAClB,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;wBACb,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;oBAC/G,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,mDAAmD;QACnD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;YAC9C,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7B,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACjC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QAED,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC/B,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC1B,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,GAAG,EAAE,CAAC,CAAC,GAAG;gBACV,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,KAAK,EAAE,IAAI;gBACX,QAAQ,EAAE,CAAC,CAAC,QAAQ;aACrB,CAAC,CAAC;SACJ,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,oBAAoB;QACxB,mCAAmC;QACnC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC3D,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjC,2DAA2D;gBAC3D,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,CAAC,GAAG,yBAAyB,GAAG,CAAC,MAAM,iBAAiB,EAAE,CAAC,CAAC;YACtI,CAAC;iBAAM,CAAC;gBACN,wCAAwC;gBACxC,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE;oBACpD,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,qBAAqB,EAAE,QAAQ,EAAE,CAAC;iBACpE,CAAC,CAAC;gBACH,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QAED,qEAAqE;QACrE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACjD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACnC,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC/B,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QACpD,MAAM,YAAY,GAAgB,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC;QACjF,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;gBAAE,SAAS;YAE7C,+CAA+C;YAC/C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC5D,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpE,qDAAqD;gBACrD,SAAS;YACX,CAAC;YAED,0DAA0D;YAC1D,uEAAuE;YACvE,yDAAyD;YACzD,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7G,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,sCAAsC,CAAC,CAAC;YACpG,SAAS,EAAE,CAAC;QACd,CAAC;QAED,2BAA2B;QAC3B,IAAI,SAAS,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACjE,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,cAAc,CAAC,GAAW;QACxB,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAU;QAC3B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,IAAI,CAAC,QAAQ,eAAe,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;YAClH,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACxD,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;YAC3D,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;YACtD,OAAO;QACT,CAAC;QAED,yDAAyD;QACzD,IAAI,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;YACjD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YAC7D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC7E,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE;oBAC3B,KAAK,EAAE,OAAO;oBACd,OAAO,EAAE,IAAI,IAAI,CAAC,EAAE,yBAAyB,MAAM,0BAA0B,KAAK,CAAC,IAAI,GAAG;iBAC3F,CAAC,CAAC;gBACH,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;gBACxD,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;gBAC3D,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;gBACtD,OAAO;YACT,CAAC;QACH,CAAC;QAED,+DAA+D;QAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE;gBAC3B,KAAK,EAAE,MAAM;gBACb,OAAO,EAAE,IAAI,IAAI,CAAC,EAAE,4BAA4B,UAAU,CAAC,YAAY,IAAI,WAAW,EAAE;aACzF,CAAC,CAAC;YACH,OAAO,CAAE,sDAAsD;QACjE,CAAC;QAED,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QACxD,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;QAE3D,oEAAoE;QACpE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QACtE,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC;QAEvB,oDAAoD;QACpD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QAEjE,4DAA4D;QAC5D,gFAAgF;QAChF,MAAM,eAAe,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;QACpC,MAAM,YAAY,GAAa,EAAE,CAAC;QAElC,+EAA+E;QAC/E,MAAM,YAAY,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;QAC/D,IAAI,YAAY,EAAE,CAAC;YACjB,YAAY,CAAC,IAAI,CAAC,oBAAoB,YAAY,oBAAoB,CAAC,CAAC;QAC1E,CAAC;QAED,uEAAuE;QACvE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1F,IAAI,QAAQ,EAAE,CAAC;gBACb,YAAY,CAAC,IAAI,CAAC,wBAAwB,IAAI,CAAC,QAAQ,OAAO,QAAQ,mBAAmB,CAAC,CAAC;YAC7F,CAAC;QACH,CAAC;QAED,qGAAqG;QACrG,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC;gBACH,4EAA4E;gBAC5E,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS;oBAC5B,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;oBACtD,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC3D,MAAM,YAAY,GAAa,EAAE,CAAC;gBAElC,+DAA+D;gBAC/D,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;oBACpB,YAAY,CAAC,IAAI,CAAC,iBAAiB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;gBACvD,CAAC;gBAED,gFAAgF;gBAChF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;gBACvD,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;gBAClF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACxB,YAAY,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;oBAClD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;wBACzB,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ;4BAC3C,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,eAAe;gCAC9C,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU;oCACpC,CAAC,CAAC,WAAW,CAAC;wBAChB,YAAY,CAAC,IAAI,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;oBAChE,CAAC;gBACH,CAAC;gBAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC5B,YAAY,CAAC,IAAI,CAAC,sBAAsB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;gBACzF,CAAC;YACH,CAAC;YAAC,MAAM,CAAC,CAAC,iDAAiD,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,eAAe,CAAC,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC;QACtF,CAAC;QAED,gGAAgG;QAChG,wFAAwF;QACxF,IAAI,cAAkC,CAAC;QACvC,IAAI,mBAAuC,CAAC;QAC5C,IAAI,KAAK,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;YAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC;YAClE,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,UAAU,CAAC,CAAC;gBAChF,IAAI,KAAK,EAAE,CAAC;oBACV,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;oBAC5D,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,UAAU,IAAI,SAAS,CAAC;oBAC5D,mBAAmB,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,mBAAmB,EAAE,WAAW,CAAC,CAAC;gBACtF,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,YAAY,GAAiB;YACjC,KAAK;YACL,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,KAAK;YACL,IAAI,EAAE,eAAe;YACrB,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ;YAC3B,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY;YAC1B,SAAS;YACT,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO;YACzC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW;YACjD,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,gBAAgB;YACvC,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB;YAC9F,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS;YAC7C,cAAc;YACd,mBAAmB;SACpB,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAE/D,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,SAAS,GAAc;gBAC3B,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,GAAG,EAAE,WAAW,CAAC,GAAG;gBACpB,SAAS,EAAE,KAAK,CAAC,IAAI;gBACrB,MAAM,EAAE,SAAS;gBACjB,SAAS,EAAE,GAAG;gBACd,SAAS,EAAE,GAAG;gBACd,QAAQ,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE;gBAC9F,UAAU,EAAE,WAAW,CAAC,UAAU;aACnC,CAAC;YACF,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YAE7C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE;gBACrC,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,SAAS,EAAE,KAAK,CAAC,IAAI;gBACrB,SAAS,EAAE,IAAI,CAAC,KAAK;aACtB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,IAAI,CAAC,EAAE,6BAA6B,OAAO,EAAE,EAAE,CAAC,CAAC;YAC7G,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAEO,iBAAiB,CAAC,GAAW,EAAE,SAAiB;QACtD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO;QAC3C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,8BAA8B,GAAG,KAAK,SAAS,GAAG,EAAE,CAAC,CAAC;QAC7G,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;CACF"}
|