cyrus-gemini-runner 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +411 -0
  3. package/dist/GeminiRunner.d.ts +136 -0
  4. package/dist/GeminiRunner.d.ts.map +1 -0
  5. package/dist/GeminiRunner.js +683 -0
  6. package/dist/GeminiRunner.js.map +1 -0
  7. package/dist/SimpleGeminiRunner.d.ts +27 -0
  8. package/dist/SimpleGeminiRunner.d.ts.map +1 -0
  9. package/dist/SimpleGeminiRunner.js +149 -0
  10. package/dist/SimpleGeminiRunner.js.map +1 -0
  11. package/dist/adapters.d.ts +37 -0
  12. package/dist/adapters.d.ts.map +1 -0
  13. package/dist/adapters.js +317 -0
  14. package/dist/adapters.js.map +1 -0
  15. package/dist/formatter.d.ts +40 -0
  16. package/dist/formatter.d.ts.map +1 -0
  17. package/dist/formatter.js +363 -0
  18. package/dist/formatter.js.map +1 -0
  19. package/dist/index.d.ts +36 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +56 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/prompts/system.md +108 -0
  24. package/dist/schemas.d.ts +1472 -0
  25. package/dist/schemas.d.ts.map +1 -0
  26. package/dist/schemas.js +678 -0
  27. package/dist/schemas.js.map +1 -0
  28. package/dist/settingsGenerator.d.ts +72 -0
  29. package/dist/settingsGenerator.d.ts.map +1 -0
  30. package/dist/settingsGenerator.js +255 -0
  31. package/dist/settingsGenerator.js.map +1 -0
  32. package/dist/systemPromptManager.d.ts +27 -0
  33. package/dist/systemPromptManager.d.ts.map +1 -0
  34. package/dist/systemPromptManager.js +65 -0
  35. package/dist/systemPromptManager.js.map +1 -0
  36. package/dist/types.d.ts +113 -0
  37. package/dist/types.d.ts.map +1 -0
  38. package/dist/types.js +23 -0
  39. package/dist/types.js.map +1 -0
  40. package/package.json +37 -0
package/README.md ADDED
@@ -0,0 +1,411 @@
1
+ # @cyrus-ai/gemini-runner
2
+
3
+ A TypeScript wrapper around the Gemini CLI that provides a provider-agnostic interface for running Gemini AI sessions. This package mirrors the architecture of `@cyrus-ai/claude-runner` while adapting to Gemini CLI's streaming format and session management.
4
+
5
+ ## Overview
6
+
7
+ The `gemini-runner` package provides two main classes:
8
+
9
+ - **GeminiRunner**: Full-featured wrapper around Gemini CLI with streaming support, event handling, and message format conversion
10
+ - **SimpleGeminiRunner**: Simplified interface for enumerated response use cases (yes/no, multiple choice, etc.)
11
+
12
+ Both classes implement standard interfaces from `cyrus-core`, making them interchangeable with other AI runner implementations like `ClaudeRunner`.
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pnpm add @cyrus-ai/gemini-runner
18
+ ```
19
+
20
+ ### Prerequisites
21
+
22
+ 1. **Gemini CLI**: Install the Gemini CLI and ensure it's in your PATH:
23
+ ```bash
24
+ # Installation instructions depend on your platform
25
+ # Verify installation:
26
+ gemini --version
27
+ ```
28
+
29
+ 2. **Gemini API Credentials**: Configure your Gemini API credentials according to the Gemini CLI documentation.
30
+
31
+ ## Quick Start
32
+
33
+ ### Basic Usage with GeminiRunner
34
+
35
+ ```typescript
36
+ import { GeminiRunner } from '@cyrus-ai/gemini-runner';
37
+
38
+ const runner = new GeminiRunner({
39
+ cyrusHome: '/path/to/.cyrus',
40
+ workingDirectory: '/path/to/project',
41
+ model: 'gemini-2.5-flash',
42
+ autoApprove: true // Enable --yolo flag
43
+ });
44
+
45
+ // Listen for events
46
+ runner.on('message', (message) => {
47
+ console.log('New message:', message);
48
+ });
49
+
50
+ runner.on('complete', (messages) => {
51
+ console.log('Session complete! Total messages:', messages.length);
52
+ });
53
+
54
+ // Start a session
55
+ await runner.start("Analyze this codebase and suggest improvements");
56
+
57
+ // Get all messages
58
+ const messages = runner.getMessages();
59
+ ```
60
+
61
+ ### Simple Enumerated Responses with SimpleGeminiRunner
62
+
63
+ ```typescript
64
+ import { SimpleGeminiRunner } from '@cyrus-ai/gemini-runner';
65
+
66
+ const runner = new SimpleGeminiRunner({
67
+ validResponses: ['yes', 'no', 'maybe'],
68
+ cyrusHome: '/path/to/.cyrus',
69
+ workingDirectory: '/path/to/project',
70
+ model: 'gemini-2.5-flash',
71
+ maxTurns: 5,
72
+ onProgress: (event) => {
73
+ console.log(`Progress: ${event.type}`);
74
+ }
75
+ });
76
+
77
+ const result = await runner.query('Is this code correct?');
78
+ console.log(`Response: ${result.response}`); // Guaranteed to be 'yes', 'no', or 'maybe'
79
+ console.log(`Cost: $${result.cost.toFixed(4)}`);
80
+ ```
81
+
82
+ ## Core Concepts
83
+
84
+ ### GeminiRunner
85
+
86
+ `GeminiRunner` is the primary class for interacting with the Gemini CLI. It:
87
+
88
+ - Spawns the Gemini CLI process in headless mode (`--output-format stream-json`)
89
+ - Translates between Gemini CLI's JSON streaming format and Claude SDK message types
90
+ - Manages session lifecycle (start, stop, status)
91
+ - Provides event-based communication
92
+ - Creates detailed logs in both NDJSON and human-readable formats
93
+ - Supports both string prompts and streaming prompts
94
+
95
+ **Key Features**:
96
+ - **Provider-agnostic interface**: Implements `IAgentRunner` for compatibility with other runners
97
+ - **Event system**: Subscribe to `message`, `error`, `complete`, and `streamEvent` events
98
+ - **Streaming support**: Add messages incrementally with `addStreamMessage()`
99
+ - **Session management**: Track session state with `isRunning()` and `getMessages()`
100
+ - **MCP server support**: Configure Model Context Protocol servers (inherited from `IAgentRunner`)
101
+
102
+ ### SimpleGeminiRunner
103
+
104
+ `SimpleGeminiRunner` extends `SimpleAgentRunner` to provide a streamlined interface for enumerated response scenarios:
105
+
106
+ - Validates responses against a predefined set of valid answers
107
+ - Handles timeout management automatically
108
+ - Cleans responses (removes markdown, code blocks, quotes)
109
+ - Emits progress events (thinking, tool-use, validating)
110
+ - Builds system prompts with valid response constraints
111
+ - Extracts cost information from result messages
112
+
113
+ **Use Cases**:
114
+ - Yes/No questions
115
+ - Multiple choice selection
116
+ - Status confirmations
117
+ - Classification tasks
118
+
119
+ ## API Reference
120
+
121
+ ### GeminiRunner
122
+
123
+ #### Constructor Options
124
+
125
+ ```typescript
126
+ interface GeminiRunnerConfig extends IAgentRunnerConfig {
127
+ // Gemini-specific options
128
+ geminiPath?: string; // Path to gemini CLI (default: 'gemini')
129
+ autoApprove?: boolean; // Enable --yolo flag (default: false)
130
+ approvalMode?: 'auto_edit' | 'auto' | 'manual'; // Approval mode
131
+ debug?: boolean; // Enable debug output
132
+
133
+ // Inherited from IAgentRunnerConfig
134
+ model?: string; // Model to use (e.g., 'gemini-2.5-flash')
135
+ cyrusHome: string; // Home directory for logs
136
+ workingDirectory: string; // Working directory for Gemini
137
+ systemPrompt?: string; // System prompt for session
138
+ mcpServers?: MCPServerConfig[]; // MCP server configurations
139
+ env?: Record<string, string>; // Environment variables
140
+ }
141
+ ```
142
+
143
+ #### Methods
144
+
145
+ **start(prompt: string): Promise<void>**
146
+ - Start a new session with a string prompt
147
+ - Throws if a session is already running
148
+
149
+ **startStreaming(initialPrompt?: string): Promise<void>**
150
+ - Start a new session with streaming input capability
151
+ - Optionally provide an initial prompt
152
+ - Use `addStreamMessage()` to add more messages
153
+ - Call `completeStream()` when done
154
+
155
+ **addStreamMessage(content: string): void**
156
+ - Add a message to an active streaming session
157
+ - Must be called after `startStreaming()`
158
+
159
+ **completeStream(): void**
160
+ - Signal the end of streaming input
161
+ - Session will continue processing
162
+
163
+ **stop(): Promise<void>**
164
+ - Terminate the current session
165
+ - Kills the Gemini CLI process
166
+
167
+ **getMessages(): SDKMessage[]**
168
+ - Retrieve all messages from the current session
169
+ - Returns both user and assistant messages
170
+
171
+ **isRunning(): boolean**
172
+ - Check if a session is currently active
173
+
174
+ #### Events
175
+
176
+ **'message'**: `(message: SDKMessage) => void`
177
+ - Emitted when a new message is received from Gemini
178
+
179
+ **'error'**: `(error: Error) => void`
180
+ - Emitted when an error occurs
181
+
182
+ **'complete'**: `(messages: SDKMessage[]) => void`
183
+ - Emitted when the session completes successfully
184
+
185
+ **'streamEvent'**: `(event: GeminiStreamEvent) => void`
186
+ - Emitted for raw Gemini CLI events (for debugging)
187
+
188
+ ### SimpleGeminiRunner
189
+
190
+ #### Constructor Options
191
+
192
+ ```typescript
193
+ interface SimpleGeminiRunnerConfig {
194
+ validResponses: string[]; // REQUIRED: Valid response options
195
+ cyrusHome: string; // REQUIRED: Home directory for logs
196
+ workingDirectory?: string; // Working directory (default: cwd)
197
+ model?: string; // Model to use (default: 'gemini-2.5-flash')
198
+ systemPrompt?: string; // Additional system prompt
199
+ maxTurns?: number; // Max conversation turns (default: 10)
200
+ timeout?: number; // Timeout in ms (default: 300000)
201
+ onProgress?: (event: SimpleAgentProgressEvent) => void;
202
+ mcpServers?: MCPServerConfig[];
203
+ env?: Record<string, string>;
204
+ }
205
+ ```
206
+
207
+ #### Methods
208
+
209
+ **query(prompt: string, options?: SimpleAgentQueryOptions): Promise<SimpleAgentResult>**
210
+ - Execute a query and get a validated response
211
+ - Returns an object with `response`, `cost`, and `messages`
212
+
213
+ ```typescript
214
+ interface SimpleAgentResult {
215
+ response: string; // Validated response (one of validResponses)
216
+ cost: number; // Total cost in dollars
217
+ messages: SDKMessage[]; // All messages from session
218
+ }
219
+ ```
220
+
221
+ ## Adapter Pattern
222
+
223
+ The package uses an adapter pattern to translate between Gemini CLI's JSON streaming format and Claude SDK message types. This allows the runner to integrate seamlessly with other parts of the Cyrus ecosystem.
224
+
225
+ ### Message Format Conversion
226
+
227
+ **Gemini Stream Events → SDK Messages**:
228
+ - `GeminiInitEvent` → Session ID extraction
229
+ - `GeminiMessageEvent` (user) → `SDKUserMessage`
230
+ - `GeminiMessageEvent` (assistant) → `SDKAssistantMessage`
231
+ - `GeminiToolUseEvent` → `SDKAssistantMessage` with `tool_use` content block
232
+ - `GeminiToolResultEvent` → `SDKUserMessage` with `tool_result` content block
233
+ - `GeminiResultEvent` (success) → `SDKAssistantMessage` with final response
234
+
235
+ **Key Differences from Claude**:
236
+ - Gemini uses simple `{type, role, content}` for messages
237
+ - SDK uses `{type, message: {role, content}, session_id, ...}` structure
238
+ - Tool use IDs are generated client-side for Gemini (`${tool_name}_${timestamp}`)
239
+ - Session ID is "pending" until init event is received from Gemini CLI
240
+
241
+ ## Differences from ClaudeRunner
242
+
243
+ While `GeminiRunner` mirrors the architecture of `ClaudeRunner`, there are some key differences:
244
+
245
+ | Aspect | ClaudeRunner | GeminiRunner |
246
+ |--------|--------------|--------------|
247
+ | CLI Command | `claude --output-format ndjson` | `gemini --output-format stream-json` |
248
+ | Session ID | Generated client-side or via `--continue` | Assigned by CLI in init event |
249
+ | Stream Format | NDJSON with SDK-compatible messages | Custom JSON format requiring adapter |
250
+ | Tool Use IDs | Native SDK format | Generated client-side |
251
+ | Auto-Approval | Approval callbacks or flags | `--yolo` flag and `--approval-mode` |
252
+ | System Prompts | Native CLI support | Accepted in config (CLI handling TBD) |
253
+
254
+ ## Supported Models
255
+
256
+ The package supports Gemini 2.5 and later models. Common model identifiers:
257
+
258
+ - `gemini-2.5-flash` - Fast, cost-effective model
259
+ - `gemini-2.5-pro` - Advanced reasoning and complex tasks
260
+ - Additional models as supported by the Gemini CLI
261
+
262
+ Specify the model in the configuration:
263
+
264
+ ```typescript
265
+ const runner = new GeminiRunner({
266
+ model: 'gemini-2.5-flash',
267
+ // ... other options
268
+ });
269
+ ```
270
+
271
+ ## Configuration
272
+
273
+ ### Environment Variables
274
+
275
+ The package respects standard Gemini CLI environment variables for API credentials. Refer to the Gemini CLI documentation for setup instructions.
276
+
277
+ ### Log Files
278
+
279
+ Both runners create detailed logs in the `cyrusHome` directory:
280
+
281
+ - `{cyrusHome}/logs/{workspaceName}/{sessionId}.ndjson` - NDJSON event log
282
+ - `{cyrusHome}/logs/{workspaceName}/{sessionId}.log` - Human-readable log
283
+
284
+ ### MCP Server Configuration
285
+
286
+ Configure Model Context Protocol servers for enhanced capabilities:
287
+
288
+ ```typescript
289
+ const runner = new GeminiRunner({
290
+ cyrusHome: '/path/to/.cyrus',
291
+ workingDirectory: '/path/to/project',
292
+ mcpServers: [
293
+ {
294
+ name: 'linear',
295
+ type: 'http',
296
+ url: 'https://mcp.linear.app',
297
+ headers: {
298
+ 'Authorization': 'Bearer YOUR_TOKEN'
299
+ }
300
+ }
301
+ ]
302
+ });
303
+ ```
304
+
305
+ ## Examples
306
+
307
+ See the `examples/` directory for complete working examples:
308
+
309
+ - `basic-usage.ts` - Basic GeminiRunner usage with event handling
310
+ - `simple-agent-example.ts` - SimpleGeminiRunner for enumerated responses
311
+
312
+ To run the examples:
313
+
314
+ ```bash
315
+ cd packages/gemini-runner
316
+ pnpm build
317
+ node examples/basic-usage.js # Or .ts with ts-node
318
+ ```
319
+
320
+ ## Troubleshooting
321
+
322
+ ### Common Issues
323
+
324
+ **"gemini: command not found"**
325
+ - Ensure the Gemini CLI is installed and in your PATH
326
+ - Or specify the full path in the config: `geminiPath: '/path/to/gemini'`
327
+
328
+ **"Session already running"**
329
+ - You can only have one active session per GeminiRunner instance
330
+ - Call `stop()` before starting a new session, or create a new instance
331
+
332
+ **"Invalid response from Gemini"**
333
+ - Check that your validResponses match the expected output format
334
+ - Use the `onProgress` callback to see raw responses during validation
335
+ - Verify the system prompt is being respected by the model
336
+
337
+ **Empty messages array**
338
+ - The session may have errored before producing any messages
339
+ - Check the `error` event for details
340
+ - Review the log files in `{cyrusHome}/logs/`
341
+
342
+ **Response validation fails with SimpleGeminiRunner**
343
+ - Increase `maxTurns` to allow more attempts
344
+ - Simplify your `validResponses` list
345
+ - Check if the model is producing markdown or code blocks (automatically cleaned)
346
+ - Use `onProgress` to debug what responses are being received
347
+
348
+ **Timeout errors**
349
+ - Increase the `timeout` option (default: 300000ms / 5 minutes)
350
+ - Check if the Gemini CLI is hanging on approval prompts (use `autoApprove: true`)
351
+ - Verify your working directory is accessible and doesn't have permission issues
352
+
353
+ ### Debug Mode
354
+
355
+ Enable debug mode for detailed logging:
356
+
357
+ ```typescript
358
+ const runner = new GeminiRunner({
359
+ debug: true,
360
+ // ... other options
361
+ });
362
+ ```
363
+
364
+ ### Log Analysis
365
+
366
+ Check the NDJSON log files for detailed event information:
367
+
368
+ ```bash
369
+ cat ~/.cyrus/logs/my-workspace/{session-id}.ndjson | jq .
370
+ ```
371
+
372
+ Or the human-readable log:
373
+
374
+ ```bash
375
+ cat ~/.cyrus/logs/my-workspace/{session-id}.log
376
+ ```
377
+
378
+ ## Development
379
+
380
+ ### Building
381
+
382
+ ```bash
383
+ pnpm build
384
+ ```
385
+
386
+ ### Running Tests
387
+
388
+ ```bash
389
+ pnpm test # Watch mode
390
+ pnpm test:run # Run once
391
+ ```
392
+
393
+ ### Type Checking
394
+
395
+ ```bash
396
+ pnpm typecheck
397
+ ```
398
+
399
+ ## Related Packages
400
+
401
+ - `@cyrus-ai/core` - Core types and interfaces
402
+ - `@cyrus-ai/claude-runner` - Claude CLI wrapper (similar architecture)
403
+ - `@cyrus-ai/simple-agent-runner` - Abstract base for simple enumerated responses
404
+
405
+ ## License
406
+
407
+ MIT
408
+
409
+ ## Support
410
+
411
+ For issues and feature requests, please use the project's issue tracker.
@@ -0,0 +1,136 @@
1
+ import { EventEmitter } from "node:events";
2
+ import { type IAgentRunner, type IMessageFormatter, type SDKAssistantMessage, type SDKMessage } from "cyrus-core";
3
+ import type { GeminiRunnerConfig, GeminiRunnerEvents, GeminiSessionInfo } from "./types.js";
4
+ export declare interface GeminiRunner {
5
+ on<K extends keyof GeminiRunnerEvents>(event: K, listener: GeminiRunnerEvents[K]): this;
6
+ emit<K extends keyof GeminiRunnerEvents>(event: K, ...args: Parameters<GeminiRunnerEvents[K]>): boolean;
7
+ }
8
+ /**
9
+ * Manages Gemini CLI sessions and communication
10
+ *
11
+ * GeminiRunner implements the IAgentRunner interface to provide a provider-agnostic
12
+ * wrapper around the Gemini CLI. It spawns the Gemini CLI process in headless mode
13
+ * and translates between the CLI's JSON streaming format and Claude SDK message types.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const runner = new GeminiRunner({
18
+ * cyrusHome: '/home/user/.cyrus',
19
+ * workingDirectory: '/path/to/repo',
20
+ * model: 'gemini-2.5-flash',
21
+ * autoApprove: true
22
+ * });
23
+ *
24
+ * // String mode
25
+ * await runner.start("Analyze this codebase");
26
+ *
27
+ * // Streaming mode
28
+ * await runner.startStreaming("Initial task");
29
+ * runner.addStreamMessage("Additional context");
30
+ * runner.completeStream();
31
+ * ```
32
+ */
33
+ export declare class GeminiRunner extends EventEmitter implements IAgentRunner {
34
+ /**
35
+ * GeminiRunner does not support true streaming input.
36
+ * While startStreaming() exists, it only accepts an initial prompt and does not support
37
+ * addStreamMessage() for adding messages after the session starts.
38
+ */
39
+ readonly supportsStreamingInput = false;
40
+ private config;
41
+ private process;
42
+ private sessionInfo;
43
+ private logStream;
44
+ private readableLogStream;
45
+ private messages;
46
+ private streamingPrompt;
47
+ private cyrusHome;
48
+ private accumulatingMessage;
49
+ private accumulatingRole;
50
+ private lastAssistantMessage;
51
+ private settingsCleanup;
52
+ private systemPromptManager;
53
+ private formatter;
54
+ private readlineInterface;
55
+ private pendingResultMessage;
56
+ constructor(config: GeminiRunnerConfig);
57
+ /**
58
+ * Start a new Gemini session with string prompt (legacy mode)
59
+ */
60
+ start(prompt: string): Promise<GeminiSessionInfo>;
61
+ /**
62
+ * Start a new Gemini session with streaming input
63
+ */
64
+ startStreaming(initialPrompt?: string): Promise<GeminiSessionInfo>;
65
+ /**
66
+ * Add a message to the streaming prompt (only works when in streaming mode)
67
+ */
68
+ addStreamMessage(content: string): void;
69
+ /**
70
+ * Complete the streaming prompt (no more messages will be added)
71
+ */
72
+ completeStream(): void;
73
+ /**
74
+ * Get the last assistant message (used for result coercion)
75
+ */
76
+ getLastAssistantMessage(): SDKAssistantMessage | null;
77
+ /**
78
+ * Internal method to start a Gemini session with either string or streaming prompt
79
+ */
80
+ private startWithPrompt;
81
+ /**
82
+ * Process a Gemini stream event and convert to SDK message
83
+ */
84
+ private processStreamEvent;
85
+ /**
86
+ * Accumulate a delta message (message with delta: true)
87
+ */
88
+ private accumulateDeltaMessage;
89
+ /**
90
+ * Flush the accumulated delta message
91
+ */
92
+ private flushAccumulatedMessage;
93
+ /**
94
+ * Emit a message (add to messages array, log, and emit event)
95
+ */
96
+ private emitMessage;
97
+ /**
98
+ * Stop the current Gemini session
99
+ */
100
+ stop(): void;
101
+ /**
102
+ * Check if the session is currently running
103
+ */
104
+ isRunning(): boolean;
105
+ /**
106
+ * Get all messages from the current session
107
+ */
108
+ getMessages(): SDKMessage[];
109
+ /**
110
+ * Get the message formatter for this runner
111
+ */
112
+ getFormatter(): IMessageFormatter;
113
+ /**
114
+ * Build MCP servers configuration from config paths and inline config
115
+ *
116
+ * MCP configuration loading follows a layered approach:
117
+ * 1. Auto-detect .mcp.json in working directory (base config)
118
+ * 2. Load from explicitly configured paths via mcpConfigPath (extends/overrides)
119
+ * 3. Merge inline mcpConfig (highest priority, overrides file configs)
120
+ *
121
+ * HTTP-based MCP servers (like Linear's https://mcp.linear.app/mcp) are filtered out
122
+ * since Gemini CLI only supports stdio (command-based) MCP servers.
123
+ *
124
+ * @returns Record of MCP server name to GeminiMcpServerConfig
125
+ */
126
+ private buildMcpServers;
127
+ /**
128
+ * Set up logging streams for this session
129
+ */
130
+ private setupLogging;
131
+ /**
132
+ * Write a human-readable log entry for a message
133
+ */
134
+ private writeReadableLogEntry;
135
+ }
136
+ //# sourceMappingURL=GeminiRunner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GeminiRunner.d.ts","sourceRoot":"","sources":["../src/GeminiRunner.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,UAAU,EAIf,MAAM,YAAY,CAAC;AAepB,OAAO,KAAK,EAEX,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,OAAO,WAAW,YAAY;IACpC,EAAE,CAAC,CAAC,SAAS,MAAM,kBAAkB,EACpC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC7B,IAAI,CAAC;IACR,IAAI,CAAC,CAAC,SAAS,MAAM,kBAAkB,EACtC,KAAK,EAAE,CAAC,EACR,GAAG,IAAI,EAAE,UAAU,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,GACxC,OAAO,CAAC;CACX;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,YAAa,SAAQ,YAAa,YAAW,YAAY;IACrE;;;;OAIG;IACH,QAAQ,CAAC,sBAAsB,SAAS;IAExC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO,CAAC,mBAAmB,CAA2B;IACtD,OAAO,CAAC,gBAAgB,CAAqC;IAE7D,OAAO,CAAC,oBAAoB,CAAoC;IAEhE,OAAO,CAAC,eAAe,CAA6B;IAEpD,OAAO,CAAC,mBAAmB,CAAsB;IAEjD,OAAO,CAAC,SAAS,CAAoB;IAErC,OAAO,CAAC,iBAAiB,CAAmD;IAE5E,OAAO,CAAC,oBAAoB,CAA2B;gBAE3C,MAAM,EAAE,kBAAkB;IAmBtC;;OAEG;IACG,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIvD;;OAEG;IACG,cAAc,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIxE;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAmBvC;;OAEG;IACH,cAAc,IAAI,IAAI;IAWtB;;OAEG;IACH,uBAAuB,IAAI,mBAAmB,GAAG,IAAI;IAIrD;;OAEG;YACW,eAAe;IAsU7B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAgE1B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAoD9B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAiB/B;;OAEG;IACH,OAAO,CAAC,WAAW;IAsBnB;;OAEG;IACH,IAAI,IAAI,IAAI;IAqCZ;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,WAAW,IAAI,UAAU,EAAE;IAI3B;;OAEG;IACH,YAAY,IAAI,iBAAiB;IAIjC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,eAAe;IA+CvB;;OAEG;IACH,OAAO,CAAC,YAAY;IAgDpB;;OAEG;IACH,OAAO,CAAC,qBAAqB;CAiB7B"}