nightshift-mcp 1.1.1 → 2.0.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.
@@ -331,91 +331,91 @@ function stripAnsiEscapes(str) {
331
331
  function createWrapperScript(agent, cmd, args, promptFile, outputFile, promptDelivery, promptFlag) {
332
332
  const argsJson = JSON.stringify(args);
333
333
  const promptFlagJson = promptFlag ? JSON.stringify(promptFlag) : "null";
334
- return `
335
- import { spawn } from "child_process";
336
- import * as fs from "fs";
337
-
338
- const agent = ${JSON.stringify(agent)};
339
- const cmd = ${JSON.stringify(cmd)};
340
- const args = ${argsJson};
341
- const promptFile = ${JSON.stringify(promptFile)};
342
- const outputFile = ${JSON.stringify(outputFile)};
343
- const promptDelivery = ${JSON.stringify(promptDelivery)};
344
- const promptFlag = ${promptFlagJson};
345
-
346
- // Read the prompt
347
- const prompt = fs.readFileSync(promptFile, "utf-8");
348
-
349
- // Build final args
350
- const finalArgs = [...args];
351
- if (promptDelivery === "flag" && promptFlag) {
352
- finalArgs.push(promptFlag, prompt);
353
- }
354
-
355
- // Write header to output file
356
- fs.writeFileSync(outputFile, \`Agent: \${agent}\\nStarted: \${new Date().toISOString()}\\n---\\n\`);
357
-
358
- // Spawn the agent (use shell on Windows to resolve .cmd/.bat shims)
359
- const proc = spawn(cmd, finalArgs, {
360
- cwd: process.cwd(),
361
- env: process.env,
362
- stdio: ["pipe", "pipe", "pipe"],
363
- shell: process.platform === "win32",
364
- windowsHide: true,
365
- });
366
-
367
- let output = "";
368
-
369
- proc.stdout.on("data", (data) => {
370
- const text = data.toString();
371
- output += text;
372
- fs.appendFileSync(outputFile, text);
373
- });
374
-
375
- proc.stderr.on("data", (data) => {
376
- const text = data.toString();
377
- output += text;
378
- fs.appendFileSync(outputFile, text);
379
- });
380
-
381
- // Send prompt via stdin if required, with backpressure handling
382
- if (promptDelivery === "stdin") {
383
- const CHUNK_SIZE = 16 * 1024;
384
- let offset = 0;
385
- function writeNext() {
386
- let ok = true;
387
- while (offset < prompt.length && ok) {
388
- const chunk = prompt.slice(offset, offset + CHUNK_SIZE);
389
- offset += chunk.length;
390
- if (offset >= prompt.length) {
391
- proc.stdin.end(chunk);
392
- return;
393
- }
394
- ok = proc.stdin.write(chunk);
395
- }
396
- if (offset < prompt.length) {
397
- proc.stdin.once("drain", writeNext);
398
- }
399
- }
400
- writeNext();
401
- }
402
-
403
- proc.on("close", (code) => {
404
- fs.appendFileSync(outputFile, \`\\n---\\nFinished: \${new Date().toISOString()}\\nExit Code: \${code}\\n\`);
405
- // Clean up prompt file
406
- try {
407
- fs.unlinkSync(promptFile);
408
- } catch {}
409
- process.exit(code ?? 0);
410
- });
411
-
412
- proc.on("error", (err) => {
413
- fs.appendFileSync(outputFile, \`\\n---\\nError: \${err.message}\\nFinished: \${new Date().toISOString()}\\nExit Code: 1\\n\`);
414
- try {
415
- fs.unlinkSync(promptFile);
416
- } catch {}
417
- process.exit(1);
418
- });
334
+ return `
335
+ import { spawn } from "child_process";
336
+ import * as fs from "fs";
337
+
338
+ const agent = ${JSON.stringify(agent)};
339
+ const cmd = ${JSON.stringify(cmd)};
340
+ const args = ${argsJson};
341
+ const promptFile = ${JSON.stringify(promptFile)};
342
+ const outputFile = ${JSON.stringify(outputFile)};
343
+ const promptDelivery = ${JSON.stringify(promptDelivery)};
344
+ const promptFlag = ${promptFlagJson};
345
+
346
+ // Read the prompt
347
+ const prompt = fs.readFileSync(promptFile, "utf-8");
348
+
349
+ // Build final args
350
+ const finalArgs = [...args];
351
+ if (promptDelivery === "flag" && promptFlag) {
352
+ finalArgs.push(promptFlag, prompt);
353
+ }
354
+
355
+ // Write header to output file
356
+ fs.writeFileSync(outputFile, \`Agent: \${agent}\\nStarted: \${new Date().toISOString()}\\n---\\n\`);
357
+
358
+ // Spawn the agent (use shell on Windows to resolve .cmd/.bat shims)
359
+ const proc = spawn(cmd, finalArgs, {
360
+ cwd: process.cwd(),
361
+ env: process.env,
362
+ stdio: ["pipe", "pipe", "pipe"],
363
+ shell: process.platform === "win32",
364
+ windowsHide: true,
365
+ });
366
+
367
+ let output = "";
368
+
369
+ proc.stdout.on("data", (data) => {
370
+ const text = data.toString();
371
+ output += text;
372
+ fs.appendFileSync(outputFile, text);
373
+ });
374
+
375
+ proc.stderr.on("data", (data) => {
376
+ const text = data.toString();
377
+ output += text;
378
+ fs.appendFileSync(outputFile, text);
379
+ });
380
+
381
+ // Send prompt via stdin if required, with backpressure handling
382
+ if (promptDelivery === "stdin") {
383
+ const CHUNK_SIZE = 16 * 1024;
384
+ let offset = 0;
385
+ function writeNext() {
386
+ let ok = true;
387
+ while (offset < prompt.length && ok) {
388
+ const chunk = prompt.slice(offset, offset + CHUNK_SIZE);
389
+ offset += chunk.length;
390
+ if (offset >= prompt.length) {
391
+ proc.stdin.end(chunk);
392
+ return;
393
+ }
394
+ ok = proc.stdin.write(chunk);
395
+ }
396
+ if (offset < prompt.length) {
397
+ proc.stdin.once("drain", writeNext);
398
+ }
399
+ }
400
+ writeNext();
401
+ }
402
+
403
+ proc.on("close", (code) => {
404
+ fs.appendFileSync(outputFile, \`\\n---\\nFinished: \${new Date().toISOString()}\\nExit Code: \${code}\\n\`);
405
+ // Clean up prompt file
406
+ try {
407
+ fs.unlinkSync(promptFile);
408
+ } catch {}
409
+ process.exit(code ?? 0);
410
+ });
411
+
412
+ proc.on("error", (err) => {
413
+ fs.appendFileSync(outputFile, \`\\n---\\nError: \${err.message}\\nFinished: \${new Date().toISOString()}\\nExit Code: 1\\n\`);
414
+ try {
415
+ fs.unlinkSync(promptFile);
416
+ } catch {}
417
+ process.exit(1);
418
+ });
419
419
  `;
420
420
  }
421
421
  /**
@@ -19,10 +19,10 @@ export class ChatManager {
19
19
  fs.mkdirSync(this.chatDir, { recursive: true });
20
20
  }
21
21
  if (!fs.existsSync(this.chatFile)) {
22
- const header = `# Robot Chat - Multi-Agent Communication
23
- # Format: [AgentName @ HH:MM] MESSAGE_TYPE
24
- # ========================================
25
-
22
+ const header = `# Robot Chat - Multi-Agent Communication
23
+ # Format: [AgentName @ HH:MM] MESSAGE_TYPE
24
+ # ========================================
25
+
26
26
  `;
27
27
  fs.writeFileSync(this.chatFile, header, "utf-8");
28
28
  }
@@ -314,10 +314,10 @@ export class ChatManager {
314
314
  }
315
315
  fs.appendFileSync(archiveFile, archiveContent, "utf-8");
316
316
  // Rewrite main chat file with only recent messages
317
- const mainHeader = `# Robot Chat - Multi-Agent Communication
318
- # Format: [AgentName @ HH:MM] MESSAGE_TYPE
319
- # ========================================
320
-
317
+ const mainHeader = `# Robot Chat - Multi-Agent Communication
318
+ # Format: [AgentName @ HH:MM] MESSAGE_TYPE
319
+ # ========================================
320
+
321
321
  `;
322
322
  let mainContent = mainHeader;
323
323
  for (const msg of toKeep) {
package/dist/cli.js CHANGED
@@ -277,38 +277,38 @@ async function cmdFailover(chat, flags) {
277
277
  output({ status: "posted", agent, type: "FAILOVER_NEEDED", task });
278
278
  }
279
279
  function cmdHelp() {
280
- console.log(`
281
- NightShift CLI - Multi-agent coordination without MCP
282
-
283
- Usage: nightshift <command> [options]
284
-
285
- Commands:
286
- status Show PRD progress, bugs, active agents
287
- next Get the next unclaimed story
288
- claim [storyId] --agent <name> Claim a story (or next available)
289
- complete <storyId> --agent <name> --summary "..." [--files "a,b"] [--learnings "..."]
290
- Mark story complete, create savepoint
291
- chat --read [--limit N] Read recent chat messages
292
- chat --agent <name> --type <TYPE> --message "..."
293
- Post a chat message
294
- bug-claim [bugId] --agent <name> Claim a bug (or next available)
295
- bug-fix <bugId> --agent <name> --summary "..." [--files "a,b"]
296
- Mark bug fixed, create savepoint
297
- failover --agent <name> --message "..." [--task "US-001"]
298
- Post a failover request
299
- help Show this help
300
-
301
- Message Types: STATUS_UPDATE, INFO, QUESTION, ANSWER, ERROR, FAILOVER_NEEDED
302
-
303
- Environment:
304
- ROBOT_CHAT_PROJECT_PATH Project directory (default: cwd)
305
-
306
- Examples:
307
- nightshift status
308
- nightshift claim US-001 --agent Codex
309
- nightshift chat --agent Codex --type STATUS_UPDATE --message "Working on auth module"
310
- nightshift complete US-001 --agent Codex --summary "Added JWT auth" --files "src/auth.ts,src/middleware.ts"
311
- nightshift failover --agent Codex --task US-001 --message "Hit rate limit at 80%"
280
+ console.log(`
281
+ NightShift CLI - Multi-agent coordination without MCP
282
+
283
+ Usage: nightshift <command> [options]
284
+
285
+ Commands:
286
+ status Show PRD progress, bugs, active agents
287
+ next Get the next unclaimed story
288
+ claim [storyId] --agent <name> Claim a story (or next available)
289
+ complete <storyId> --agent <name> --summary "..." [--files "a,b"] [--learnings "..."]
290
+ Mark story complete, create savepoint
291
+ chat --read [--limit N] Read recent chat messages
292
+ chat --agent <name> --type <TYPE> --message "..."
293
+ Post a chat message
294
+ bug-claim [bugId] --agent <name> Claim a bug (or next available)
295
+ bug-fix <bugId> --agent <name> --summary "..." [--files "a,b"]
296
+ Mark bug fixed, create savepoint
297
+ failover --agent <name> --message "..." [--task "US-001"]
298
+ Post a failover request
299
+ help Show this help
300
+
301
+ Message Types: STATUS_UPDATE, INFO, QUESTION, ANSWER, ERROR, FAILOVER_NEEDED
302
+
303
+ Environment:
304
+ ROBOT_CHAT_PROJECT_PATH Project directory (default: cwd)
305
+
306
+ Examples:
307
+ nightshift status
308
+ nightshift claim US-001 --agent Codex
309
+ nightshift chat --agent Codex --type STATUS_UPDATE --message "Working on auth module"
310
+ nightshift complete US-001 --agent Codex --summary "Added JWT auth" --files "src/auth.ts,src/middleware.ts"
311
+ nightshift failover --agent Codex --task US-001 --message "Hit rate limit at 80%"
312
312
  `);
313
313
  }
314
314
  // ============================================
@@ -117,75 +117,75 @@ export async function startDaemon(options) {
117
117
  const wrapperFile = path.join(robotChatDir, `daemon-starter-${timestamp}.mjs`);
118
118
  // Find the daemon entry point
119
119
  // It could be installed globally or locally
120
- const daemonScript = `
121
- import { spawn } from "child_process";
122
- import * as fs from "fs";
123
- import * as path from "path";
124
-
125
- const projectPath = ${JSON.stringify(projectPath)};
126
- const logFile = ${JSON.stringify(logFile)};
127
- const args = ${JSON.stringify(args)};
128
-
129
- // Try to find the daemon module
130
- // First check if nightshift-mcp is installed globally or locally
131
- const possiblePaths = [
132
- // Local node_modules
133
- path.join(projectPath, "node_modules", "nightshift-mcp", "dist", "daemon.js"),
134
- // If we're running from within the nightshift-mcp package itself
135
- path.join(process.cwd(), "dist", "daemon.js"),
136
- // Global npm installation (will use npx)
137
- null,
138
- ];
139
-
140
- let daemonPath = null;
141
- for (const p of possiblePaths) {
142
- if (p && fs.existsSync(p)) {
143
- daemonPath = p;
144
- break;
145
- }
146
- }
147
-
148
- // Write startup info to log
149
- fs.writeFileSync(logFile, \`Daemon starting at \${new Date().toISOString()}\\n\`);
150
- fs.appendFileSync(logFile, \`Project: \${projectPath}\\n\`);
151
- fs.appendFileSync(logFile, \`Args: \${args.join(" ")}\\n---\\n\`);
152
-
153
- const isWin = process.platform === "win32";
154
- let proc;
155
- if (daemonPath) {
156
- fs.appendFileSync(logFile, \`Using daemon at: \${daemonPath}\\n\`);
157
- // node is a real executable, NOT a .cmd shim — don't use shell (breaks paths with spaces)
158
- proc = spawn("node", [daemonPath, ...args], {
159
- cwd: projectPath,
160
- env: {
161
- ...process.env,
162
- ROBOT_CHAT_PROJECT_PATH: projectPath,
163
- },
164
- detached: true,
165
- stdio: ["ignore", fs.openSync(logFile, "a"), fs.openSync(logFile, "a")],
166
- windowsHide: true,
167
- });
168
- } else {
169
- // Try npx as fallback — npx IS a .cmd shim on Windows, needs shell: true
170
- fs.appendFileSync(logFile, "Using npx nightshift-daemon\\n");
171
- proc = spawn("npx", ["nightshift-daemon", ...args], {
172
- cwd: projectPath,
173
- env: {
174
- ...process.env,
175
- ROBOT_CHAT_PROJECT_PATH: projectPath,
176
- },
177
- detached: true,
178
- stdio: ["ignore", fs.openSync(logFile, "a"), fs.openSync(logFile, "a")],
179
- shell: isWin,
180
- windowsHide: true,
181
- });
182
- }
183
-
184
- proc.unref();
185
-
186
- // Write PID for reference
187
- fs.appendFileSync(logFile, \`Daemon PID: \${proc.pid}\\n\`);
188
- console.log(JSON.stringify({ success: true, pid: proc.pid }));
120
+ const daemonScript = `
121
+ import { spawn } from "child_process";
122
+ import * as fs from "fs";
123
+ import * as path from "path";
124
+
125
+ const projectPath = ${JSON.stringify(projectPath)};
126
+ const logFile = ${JSON.stringify(logFile)};
127
+ const args = ${JSON.stringify(args)};
128
+
129
+ // Try to find the daemon module
130
+ // First check if nightshift-mcp is installed globally or locally
131
+ const possiblePaths = [
132
+ // Local node_modules
133
+ path.join(projectPath, "node_modules", "nightshift-mcp", "dist", "daemon.js"),
134
+ // If we're running from within the nightshift-mcp package itself
135
+ path.join(process.cwd(), "dist", "daemon.js"),
136
+ // Global npm installation (will use npx)
137
+ null,
138
+ ];
139
+
140
+ let daemonPath = null;
141
+ for (const p of possiblePaths) {
142
+ if (p && fs.existsSync(p)) {
143
+ daemonPath = p;
144
+ break;
145
+ }
146
+ }
147
+
148
+ // Write startup info to log
149
+ fs.writeFileSync(logFile, \`Daemon starting at \${new Date().toISOString()}\\n\`);
150
+ fs.appendFileSync(logFile, \`Project: \${projectPath}\\n\`);
151
+ fs.appendFileSync(logFile, \`Args: \${args.join(" ")}\\n---\\n\`);
152
+
153
+ const isWin = process.platform === "win32";
154
+ let proc;
155
+ if (daemonPath) {
156
+ fs.appendFileSync(logFile, \`Using daemon at: \${daemonPath}\\n\`);
157
+ // node is a real executable, NOT a .cmd shim — don't use shell (breaks paths with spaces)
158
+ proc = spawn("node", [daemonPath, ...args], {
159
+ cwd: projectPath,
160
+ env: {
161
+ ...process.env,
162
+ ROBOT_CHAT_PROJECT_PATH: projectPath,
163
+ },
164
+ detached: true,
165
+ stdio: ["ignore", fs.openSync(logFile, "a"), fs.openSync(logFile, "a")],
166
+ windowsHide: true,
167
+ });
168
+ } else {
169
+ // Try npx as fallback — npx IS a .cmd shim on Windows, needs shell: true
170
+ fs.appendFileSync(logFile, "Using npx nightshift-daemon\\n");
171
+ proc = spawn("npx", ["nightshift-daemon", ...args], {
172
+ cwd: projectPath,
173
+ env: {
174
+ ...process.env,
175
+ ROBOT_CHAT_PROJECT_PATH: projectPath,
176
+ },
177
+ detached: true,
178
+ stdio: ["ignore", fs.openSync(logFile, "a"), fs.openSync(logFile, "a")],
179
+ shell: isWin,
180
+ windowsHide: true,
181
+ });
182
+ }
183
+
184
+ proc.unref();
185
+
186
+ // Write PID for reference
187
+ fs.appendFileSync(logFile, \`Daemon PID: \${proc.pid}\\n\`);
188
+ console.log(JSON.stringify({ success: true, pid: proc.pid }));
189
189
  `;
190
190
  try {
191
191
  // Write the wrapper script
package/dist/daemon.d.ts CHANGED
@@ -16,15 +16,20 @@ interface DaemonConfig {
16
16
  agents: AgentType[];
17
17
  verbose: boolean;
18
18
  dryRun: boolean;
19
+ circuitBreakerThreshold: number;
20
+ circuitBreakerCooldownMs: number;
19
21
  }
22
+ type CircuitState = "CLOSED" | "OPEN" | "HALF_OPEN";
20
23
  export declare class NightShiftDaemon {
21
24
  private config;
22
25
  private ralph;
23
26
  private chat;
24
27
  private workflow;
28
+ private db;
25
29
  private running;
26
30
  private activeAgents;
27
31
  private storyStates;
32
+ private agentCircuits;
28
33
  private availableAgents;
29
34
  private agentIndex;
30
35
  private prdWatcher;
@@ -47,6 +52,22 @@ export declare class NightShiftDaemon {
47
52
  private onPrdChanged;
48
53
  private onChatChanged;
49
54
  private handleFailover;
55
+ private initializeCircuits;
56
+ private recordAgentFailure;
57
+ private recordAgentSuccess;
58
+ /**
59
+ * Try to reserve an agent for work. Returns true if the agent is available.
60
+ * For HALF_OPEN state, only one probe is allowed at a time.
61
+ */
62
+ private tryReserveAgent;
63
+ private releaseProbe;
64
+ private getHealthyAgents;
65
+ getCircuitStatus(): Record<string, {
66
+ state: CircuitState;
67
+ failures: number;
68
+ successes: number;
69
+ consecutiveFailures: number;
70
+ }>;
50
71
  private reconcile;
51
72
  private getNextAgent;
52
73
  private spawnAgentForStory;
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAQH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,oBAAoB,CAAC;AAO5B,UAAU,YAAY;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;AAuBD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,QAAQ,CAAkB;IAGlC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,eAAe,CAAmB;IAC1C,OAAO,CAAC,UAAU,CAAK;IAGvB,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,eAAe,CAAQ;IAG/B,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,cAAc,CAA0C;IAGhE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAuB;gBAEzB,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE;IAuBnE,OAAO,CAAC,GAAG;IAwBX,OAAO,CAAC,WAAW;IAmCnB,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,aAAa;IAgCrB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,QAAQ;YAkBF,YAAY;YAKZ,aAAa;YAwBb,cAAc;YA2Bd,SAAS;IA6CvB,OAAO,CAAC,YAAY;YAQN,kBAAkB;IA4DhC,OAAO,CAAC,gBAAgB;IAgCxB,OAAO,CAAC,YAAY;YAaN,WAAW;IA4BzB,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,eAAe;YAOT,WAAW;IA0CnB,KAAK;IAuCL,QAAQ;CAoBf"}
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAQH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,oBAAoB,CAAC;AAQ5B,UAAU,YAAY;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,uBAAuB,EAAE,MAAM,CAAC;IAChC,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAmBD,KAAK,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAiBpD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,EAAE,CAAe;IAGzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,aAAa,CAAgD;IACrE,OAAO,CAAC,eAAe,CAAmB;IAC1C,OAAO,CAAC,UAAU,CAAK;IAGvB,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,eAAe,CAAQ;IAG/B,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,cAAc,CAA0C;IAGhE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAuB;gBAEzB,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE;IA0BnE,OAAO,CAAC,GAAG;IAwBX,OAAO,CAAC,WAAW;IAmCnB,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,aAAa;IAgCrB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,QAAQ;YAkBF,YAAY;YAKZ,aAAa;YAwBb,cAAc;IA2B5B,OAAO,CAAC,kBAAkB;IAuB1B,OAAO,CAAC,kBAAkB;IAsC1B,OAAO,CAAC,kBAAkB;IAyB1B;;;OAGG;IACH,OAAO,CAAC,eAAe;IA0CvB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,gBAAgB;IAexB,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,YAAY,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAA;KAAE,CAAC;YAiB/G,SAAS;IA6CvB,OAAO,CAAC,YAAY;YAQN,kBAAkB;IAgFhC,OAAO,CAAC,gBAAgB;IAgCxB,OAAO,CAAC,YAAY;YAaN,WAAW;IA2CzB,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,eAAe;YAOT,WAAW;IAgDnB,KAAK;IA0CL,QAAQ;CAuBf"}