cyrus-edge-worker 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +293 -0
- package/dist/EdgeWorker.d.ts +142 -0
- package/dist/EdgeWorker.d.ts.map +1 -0
- package/dist/EdgeWorker.js +965 -0
- package/dist/EdgeWorker.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +39 -0
- package/prompt-template.md +116 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Ceedar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# @cyrus/edge-worker
|
|
2
|
+
|
|
3
|
+
Unified edge worker for processing Linear issues with Claude. Handles webhook events, manages Claude sessions, and posts comments back to Linear.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @cyrus/edge-worker
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
The EdgeWorker supports multiple repository/Linear workspace pairs. Each repository configuration includes:
|
|
14
|
+
- Git repository path and branch
|
|
15
|
+
- Linear workspace ID and OAuth token
|
|
16
|
+
- Workspace directory for issue processing
|
|
17
|
+
|
|
18
|
+
### Single Repository Example (CLI)
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { EdgeWorker } from '@cyrus/edge-worker'
|
|
22
|
+
|
|
23
|
+
const edgeWorker = new EdgeWorker({
|
|
24
|
+
// Connection
|
|
25
|
+
proxyUrl: 'https://edge-proxy.example.com',
|
|
26
|
+
|
|
27
|
+
// Claude
|
|
28
|
+
claudePath: '/usr/local/bin/claude',
|
|
29
|
+
defaultAllowedTools: ['bash', 'edit', 'read'],
|
|
30
|
+
|
|
31
|
+
// Single repository configuration
|
|
32
|
+
repositories: [{
|
|
33
|
+
id: 'main-repo',
|
|
34
|
+
name: 'Main Repository',
|
|
35
|
+
repositoryPath: '/home/user/projects/main',
|
|
36
|
+
baseBranch: 'main',
|
|
37
|
+
linearWorkspaceId: 'workspace-123',
|
|
38
|
+
linearToken: await oauthHelper.getAccessToken(),
|
|
39
|
+
workspaceBaseDir: '/home/user/.cyrus/workspaces/main'
|
|
40
|
+
}],
|
|
41
|
+
|
|
42
|
+
// Optional handlers
|
|
43
|
+
handlers: {
|
|
44
|
+
// Custom workspace creation (e.g., git worktrees)
|
|
45
|
+
createWorkspace: async (issue, repository) => {
|
|
46
|
+
const path = await createGitWorktree(
|
|
47
|
+
repository.repositoryPath,
|
|
48
|
+
issue.identifier,
|
|
49
|
+
repository.baseBranch
|
|
50
|
+
)
|
|
51
|
+
return { path, isGitWorktree: true }
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// Log errors
|
|
55
|
+
onError: (error) => {
|
|
56
|
+
console.error('EdgeWorker error:', error)
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
// Features
|
|
61
|
+
features: {
|
|
62
|
+
enableContinuation: true,
|
|
63
|
+
enableTokenLimitHandling: true
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
// Start processing
|
|
68
|
+
await edgeWorker.start()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Multi-Repository Example (Electron)
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { EdgeWorker } from '@cyrus/edge-worker'
|
|
75
|
+
|
|
76
|
+
// Load repository configurations from user settings
|
|
77
|
+
const repositories = userSettings.repositories.map(repo => ({
|
|
78
|
+
id: repo.id,
|
|
79
|
+
name: repo.name,
|
|
80
|
+
repositoryPath: repo.path,
|
|
81
|
+
baseBranch: repo.branch || 'main',
|
|
82
|
+
linearWorkspaceId: repo.linearWorkspaceId,
|
|
83
|
+
linearToken: repo.linearToken, // Each repo can have its own token
|
|
84
|
+
workspaceBaseDir: path.join(app.getPath('userData'), 'workspaces', repo.id),
|
|
85
|
+
isActive: repo.enabled
|
|
86
|
+
}))
|
|
87
|
+
|
|
88
|
+
const edgeWorker = new EdgeWorker({
|
|
89
|
+
proxyUrl: config.proxyUrl,
|
|
90
|
+
claudePath: getClaudePath(),
|
|
91
|
+
|
|
92
|
+
// Multiple repositories
|
|
93
|
+
repositories,
|
|
94
|
+
|
|
95
|
+
// UI updates with repository context
|
|
96
|
+
handlers: {
|
|
97
|
+
onClaudeEvent: (issueId, event, repositoryId) => {
|
|
98
|
+
// Update UI with Claude's progress
|
|
99
|
+
mainWindow.webContents.send('claude-event', {
|
|
100
|
+
issueId,
|
|
101
|
+
event,
|
|
102
|
+
repository: repositories.find(r => r.id === repositoryId)
|
|
103
|
+
})
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
onSessionStart: (issueId, issue, repositoryId) => {
|
|
107
|
+
const repo = repositories.find(r => r.id === repositoryId)
|
|
108
|
+
// Show notification
|
|
109
|
+
new Notification({
|
|
110
|
+
title: `Processing Issue in ${repo.name}`,
|
|
111
|
+
body: `Working on ${issue.identifier}: ${issue.title}`
|
|
112
|
+
}).show()
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
createWorkspace: async (issue, repository) => {
|
|
116
|
+
// Create git worktree for the specific repository
|
|
117
|
+
const worktreePath = await createWorktree(
|
|
118
|
+
repository.repositoryPath,
|
|
119
|
+
issue.identifier,
|
|
120
|
+
repository.baseBranch
|
|
121
|
+
)
|
|
122
|
+
return { path: worktreePath, isGitWorktree: true }
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
await edgeWorker.start()
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Configuration
|
|
131
|
+
|
|
132
|
+
### Required Config
|
|
133
|
+
|
|
134
|
+
- `proxyUrl`: URL of the edge proxy server
|
|
135
|
+
- `claudePath`: Path to Claude CLI executable
|
|
136
|
+
- `repositories`: Array of repository configurations
|
|
137
|
+
|
|
138
|
+
### Repository Configuration
|
|
139
|
+
|
|
140
|
+
Each repository in the `repositories` array requires:
|
|
141
|
+
|
|
142
|
+
- `id`: Unique identifier for the repository
|
|
143
|
+
- `name`: Display name for the repository
|
|
144
|
+
- `repositoryPath`: Local git repository path
|
|
145
|
+
- `baseBranch`: Branch to create worktrees from (e.g., 'main')
|
|
146
|
+
- `linearWorkspaceId`: Linear workspace/team ID
|
|
147
|
+
- `linearToken`: OAuth token for this Linear workspace
|
|
148
|
+
- `workspaceBaseDir`: Where to create issue workspaces
|
|
149
|
+
|
|
150
|
+
Optional per-repository settings:
|
|
151
|
+
- `isActive`: Whether to process webhooks (default: true)
|
|
152
|
+
- `promptTemplatePath`: Custom prompt template for this repo
|
|
153
|
+
|
|
154
|
+
### Optional Handlers
|
|
155
|
+
|
|
156
|
+
All handlers are optional and now include repository context:
|
|
157
|
+
|
|
158
|
+
- `createWorkspace(issue, repository)`: Custom workspace creation
|
|
159
|
+
- `onClaudeEvent(issueId, event, repositoryId)`: Claude event updates
|
|
160
|
+
- `onSessionStart(issueId, issue, repositoryId)`: Session started
|
|
161
|
+
- `onSessionEnd(issueId, exitCode, repositoryId)`: Session ended
|
|
162
|
+
- `onError(error, context)`: Error handling
|
|
163
|
+
|
|
164
|
+
### Features
|
|
165
|
+
|
|
166
|
+
- `enableContinuation`: Use `--continue` flag for follow-up comments (default: true)
|
|
167
|
+
- `enableTokenLimitHandling`: Auto-restart on token limits (default: true)
|
|
168
|
+
- `enableAttachmentDownload`: Download issue attachments (default: false)
|
|
169
|
+
|
|
170
|
+
## Events
|
|
171
|
+
|
|
172
|
+
The EdgeWorker extends EventEmitter and emits:
|
|
173
|
+
|
|
174
|
+
- `connected`: Connected to proxy (token)
|
|
175
|
+
- `disconnected`: Disconnected from proxy (token, reason)
|
|
176
|
+
- `session:started`: Claude session started (issueId, issue, repositoryId)
|
|
177
|
+
- `session:ended`: Claude session ended (issueId, exitCode, repositoryId)
|
|
178
|
+
- `claude:event`: Any Claude event (issueId, event, repositoryId)
|
|
179
|
+
- `claude:response`: Claude text response (issueId, text, repositoryId)
|
|
180
|
+
- `claude:tool-use`: Claude used a tool (issueId, tool, input, repositoryId)
|
|
181
|
+
- `error`: Error occurred (error, context)
|
|
182
|
+
|
|
183
|
+
## Architecture
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
Your App (CLI/Electron)
|
|
187
|
+
↓ provides repository configs
|
|
188
|
+
EdgeWorker
|
|
189
|
+
↓ manages multiple repositories
|
|
190
|
+
├─→ Repository 1 (token A) ─→ Linear Workspace 1
|
|
191
|
+
├─→ Repository 2 (token A) ─→ Linear Workspace 1
|
|
192
|
+
└─→ Repository 3 (token B) ─→ Linear Workspace 2
|
|
193
|
+
↓ connects to proxy (grouped by token)
|
|
194
|
+
Edge Proxy
|
|
195
|
+
↓ webhooks from all workspaces
|
|
196
|
+
Linear
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Key features:
|
|
200
|
+
- Multiple repositories can share the same Linear workspace/token
|
|
201
|
+
- Repositories with different tokens connect separately to minimize connections
|
|
202
|
+
- Each repository has its own workspace directory and configuration
|
|
203
|
+
- OAuth tokens serve dual purpose: proxy auth and Linear API calls
|
|
204
|
+
|
|
205
|
+
## Prompt Templates
|
|
206
|
+
|
|
207
|
+
The EdgeWorker supports customizable prompt templates to tailor Claude's behavior for different repositories or workflows.
|
|
208
|
+
|
|
209
|
+
### Default Template
|
|
210
|
+
|
|
211
|
+
If no custom template is specified, EdgeWorker uses a built-in template that helps Claude determine whether to:
|
|
212
|
+
1. **Execute** - When requirements are clear, implement the solution
|
|
213
|
+
2. **Clarify** - When requirements are vague, ask clarifying questions
|
|
214
|
+
|
|
215
|
+
### Custom Templates
|
|
216
|
+
|
|
217
|
+
You can provide custom templates at two levels:
|
|
218
|
+
- **Global**: Via `config.features.promptTemplatePath`
|
|
219
|
+
- **Per-repository**: Via `repository.promptTemplatePath` (takes precedence)
|
|
220
|
+
|
|
221
|
+
### Template Variables
|
|
222
|
+
|
|
223
|
+
Templates use Handlebars-style variables that are automatically replaced:
|
|
224
|
+
|
|
225
|
+
- `{{repository_name}}` - Name of the repository
|
|
226
|
+
- `{{issue_id}}` - Linear issue ID
|
|
227
|
+
- `{{issue_title}}` - Issue title
|
|
228
|
+
- `{{issue_description}}` - Full issue description
|
|
229
|
+
- `{{issue_state}}` - Current issue state
|
|
230
|
+
- `{{issue_priority}}` - Priority level (0-4)
|
|
231
|
+
- `{{issue_url}}` - Direct link to Linear issue
|
|
232
|
+
- `{{comment_history}}` - All previous comments formatted
|
|
233
|
+
- `{{latest_comment}}` - Most recent comment text
|
|
234
|
+
- `{{working_directory}}` - Current working directory
|
|
235
|
+
- `{{base_branch}}` - Base git branch (e.g., 'main')
|
|
236
|
+
- `{{branch_name}}` - Issue branch name
|
|
237
|
+
|
|
238
|
+
### Example Custom Template
|
|
239
|
+
|
|
240
|
+
```markdown
|
|
241
|
+
You are an expert {{repository_name}} developer.
|
|
242
|
+
|
|
243
|
+
## Current Task
|
|
244
|
+
**Issue**: {{issue_title}} (#{{issue_id}})
|
|
245
|
+
**Priority**: {{issue_priority}}
|
|
246
|
+
**Status**: {{issue_state}}
|
|
247
|
+
|
|
248
|
+
## Description
|
|
249
|
+
{{issue_description}}
|
|
250
|
+
|
|
251
|
+
## Previous Discussion
|
|
252
|
+
{{comment_history}}
|
|
253
|
+
|
|
254
|
+
## Technical Context
|
|
255
|
+
- Repository: {{repository_name}}
|
|
256
|
+
- Working Directory: {{working_directory}}
|
|
257
|
+
- Branch: {{branch_name}} (from {{base_branch}})
|
|
258
|
+
|
|
259
|
+
## Instructions
|
|
260
|
+
1. Review the issue requirements carefully
|
|
261
|
+
2. Check existing code patterns in the repository
|
|
262
|
+
3. Implement a solution following project conventions
|
|
263
|
+
4. Ensure all tests pass
|
|
264
|
+
5. Create a descriptive pull request
|
|
265
|
+
|
|
266
|
+
Remember to ask clarifying questions if requirements are unclear.
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Using Custom Templates
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
// Global template for all repositories
|
|
273
|
+
const edgeWorker = new EdgeWorker({
|
|
274
|
+
// ... other config
|
|
275
|
+
features: {
|
|
276
|
+
promptTemplatePath: './prompts/default.md'
|
|
277
|
+
}
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
// Per-repository templates
|
|
281
|
+
const edgeWorker = new EdgeWorker({
|
|
282
|
+
repositories: [{
|
|
283
|
+
id: 'frontend',
|
|
284
|
+
name: 'Frontend App',
|
|
285
|
+
// ... other config
|
|
286
|
+
promptTemplatePath: './prompts/frontend-specific.md'
|
|
287
|
+
}, {
|
|
288
|
+
id: 'backend',
|
|
289
|
+
name: 'Backend API',
|
|
290
|
+
// ... other config
|
|
291
|
+
promptTemplatePath: './prompts/backend-specific.md'
|
|
292
|
+
}]
|
|
293
|
+
})
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import type { EdgeWorkerConfig, EdgeWorkerEvents } from './types.js';
|
|
3
|
+
export declare interface EdgeWorker {
|
|
4
|
+
on<K extends keyof EdgeWorkerEvents>(event: K, listener: EdgeWorkerEvents[K]): this;
|
|
5
|
+
emit<K extends keyof EdgeWorkerEvents>(event: K, ...args: Parameters<EdgeWorkerEvents[K]>): boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Unified edge worker that orchestrates NDJSON streaming, Claude processing, and Linear integration
|
|
9
|
+
*/
|
|
10
|
+
export declare class EdgeWorker extends EventEmitter {
|
|
11
|
+
private config;
|
|
12
|
+
private repositories;
|
|
13
|
+
private linearClients;
|
|
14
|
+
private ndjsonClients;
|
|
15
|
+
private sessionManager;
|
|
16
|
+
private claudeRunners;
|
|
17
|
+
private sessionToRepo;
|
|
18
|
+
private issueToCommentId;
|
|
19
|
+
private issueToReplyContext;
|
|
20
|
+
constructor(config: EdgeWorkerConfig);
|
|
21
|
+
/**
|
|
22
|
+
* Start the edge worker
|
|
23
|
+
*/
|
|
24
|
+
start(): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Stop the edge worker
|
|
27
|
+
*/
|
|
28
|
+
stop(): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Handle connection established
|
|
31
|
+
*/
|
|
32
|
+
private handleConnect;
|
|
33
|
+
/**
|
|
34
|
+
* Handle disconnection
|
|
35
|
+
*/
|
|
36
|
+
private handleDisconnect;
|
|
37
|
+
/**
|
|
38
|
+
* Handle errors
|
|
39
|
+
*/
|
|
40
|
+
private handleError;
|
|
41
|
+
/**
|
|
42
|
+
* Check if Claude logs exist for a workspace
|
|
43
|
+
*/
|
|
44
|
+
private hasExistingLogs;
|
|
45
|
+
/**
|
|
46
|
+
* Handle webhook events from proxy
|
|
47
|
+
*/
|
|
48
|
+
private handleWebhook;
|
|
49
|
+
/**
|
|
50
|
+
* Handle Agent API notifications
|
|
51
|
+
*/
|
|
52
|
+
private handleAgentNotification;
|
|
53
|
+
/**
|
|
54
|
+
* Handle legacy webhook format
|
|
55
|
+
*/
|
|
56
|
+
private handleLegacyWebhook;
|
|
57
|
+
/**
|
|
58
|
+
* Find the repository configuration for a webhook
|
|
59
|
+
*/
|
|
60
|
+
private findRepositoryForWebhook;
|
|
61
|
+
/**
|
|
62
|
+
* Extract workspace ID from webhook data
|
|
63
|
+
*/
|
|
64
|
+
private extractWorkspaceId;
|
|
65
|
+
/**
|
|
66
|
+
* Handle issue assignment
|
|
67
|
+
*/
|
|
68
|
+
private handleIssueAssigned;
|
|
69
|
+
/**
|
|
70
|
+
* Handle new comment on issue
|
|
71
|
+
*/
|
|
72
|
+
private handleNewComment;
|
|
73
|
+
/**
|
|
74
|
+
* Handle issue unassignment
|
|
75
|
+
*/
|
|
76
|
+
private handleIssueUnassigned;
|
|
77
|
+
/**
|
|
78
|
+
* Handle Claude events
|
|
79
|
+
*/
|
|
80
|
+
private handleClaudeEvent;
|
|
81
|
+
/**
|
|
82
|
+
* Handle Claude process exit
|
|
83
|
+
*/
|
|
84
|
+
private handleClaudeExit;
|
|
85
|
+
/**
|
|
86
|
+
* Handle token limit by restarting session
|
|
87
|
+
*/
|
|
88
|
+
private handleTokenLimit;
|
|
89
|
+
/**
|
|
90
|
+
* Build initial prompt for issue
|
|
91
|
+
*/
|
|
92
|
+
private buildInitialPrompt;
|
|
93
|
+
/**
|
|
94
|
+
* Extract text content from Claude event
|
|
95
|
+
*/
|
|
96
|
+
private extractTextContent;
|
|
97
|
+
/**
|
|
98
|
+
* Report status back to proxy
|
|
99
|
+
*/
|
|
100
|
+
private reportStatus;
|
|
101
|
+
/**
|
|
102
|
+
* Get connection status
|
|
103
|
+
*/
|
|
104
|
+
getConnectionStatus(): Map<string, boolean>;
|
|
105
|
+
/**
|
|
106
|
+
* Get active sessions
|
|
107
|
+
*/
|
|
108
|
+
getActiveSessions(): string[];
|
|
109
|
+
/**
|
|
110
|
+
* Post initial comment when assigned to issue
|
|
111
|
+
*/
|
|
112
|
+
private postInitialComment;
|
|
113
|
+
/**
|
|
114
|
+
* Post a comment to Linear
|
|
115
|
+
*/
|
|
116
|
+
private postComment;
|
|
117
|
+
/**
|
|
118
|
+
* Update initial comment with TODO checklist
|
|
119
|
+
*/
|
|
120
|
+
private updateCommentWithTodos;
|
|
121
|
+
/**
|
|
122
|
+
* Format todos as Linear checklist markdown
|
|
123
|
+
*/
|
|
124
|
+
private formatTodosAsChecklist;
|
|
125
|
+
/**
|
|
126
|
+
* Extract attachment URLs from text (issue description or comment)
|
|
127
|
+
*/
|
|
128
|
+
private extractAttachmentUrls;
|
|
129
|
+
/**
|
|
130
|
+
* Download attachments from Linear issue
|
|
131
|
+
*/
|
|
132
|
+
private downloadIssueAttachments;
|
|
133
|
+
/**
|
|
134
|
+
* Download a single attachment from Linear
|
|
135
|
+
*/
|
|
136
|
+
private downloadAttachment;
|
|
137
|
+
/**
|
|
138
|
+
* Generate a markdown section describing downloaded attachments
|
|
139
|
+
*/
|
|
140
|
+
private generateAttachmentManifest;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=EdgeWorker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EdgeWorker.d.ts","sourceRoot":"","sources":["../src/EdgeWorker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAKrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAoB,MAAM,YAAY,CAAA;AAUtF,MAAM,CAAC,OAAO,WAAW,UAAU;IACjC,EAAE,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IACnF,IAAI,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAA;CACpG;AAED;;GAEG;AACH,qBAAa,UAAW,SAAQ,YAAY;IAC1C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,YAAY,CAA2C;IAC/D,OAAO,CAAC,aAAa,CAAuC;IAC5D,OAAO,CAAC,aAAa,CAAuC;IAC5D,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,aAAa,CAAuC;IAC5D,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,mBAAmB,CAAmE;gBAElF,MAAM,EAAE,gBAAgB;IAiDpC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB3B;;OAEG;IACH,OAAO,CAAC,aAAa;IAKrB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAKxB;;OAEG;IACH,OAAO,CAAC,WAAW;IAKnB;;OAEG;YACW,eAAe;IAkB7B;;OAEG;YACW,aAAa;IAoC3B;;OAEG;YACW,uBAAuB;IAuBrC;;OAEG;YACW,mBAAmB;IAUjC;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAOhC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAS1B;;OAEG;YACW,mBAAmB;IA4EjC;;OAEG;YACW,gBAAgB;IAmJ9B;;OAEG;YACW,qBAAqB;IAmCnC;;OAEG;YACW,iBAAiB;IAuD/B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAOxB;;OAEG;YACW,gBAAgB;IAkB9B;;OAEG;YACW,kBAAkB;IAsFhC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAoB1B;;OAEG;YACW,YAAY;IAW1B;;OAEG;IACH,mBAAmB,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAQ3C;;OAEG;IACH,iBAAiB,IAAI,MAAM,EAAE;IAI7B;;OAEG;YACW,kBAAkB;IA+BhC;;OAEG;YACW,WAAW;IAwCzB;;OAEG;YACW,sBAAsB;IA6BpC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAS9B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAW7B;;OAEG;YACW,wBAAwB;IAmHtC;;OAEG;YACW,kBAAkB;IAmDhC;;OAEG;IACH,OAAO,CAAC,0BAA0B;CA4DnC"}
|