primitive-admin 1.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.
Files changed (38) hide show
  1. package/README.md +495 -0
  2. package/dist/bin/primitive.js +72 -0
  3. package/dist/bin/primitive.js.map +1 -0
  4. package/dist/src/commands/admins.js +268 -0
  5. package/dist/src/commands/admins.js.map +1 -0
  6. package/dist/src/commands/analytics.js +195 -0
  7. package/dist/src/commands/analytics.js.map +1 -0
  8. package/dist/src/commands/apps.js +238 -0
  9. package/dist/src/commands/apps.js.map +1 -0
  10. package/dist/src/commands/auth.js +178 -0
  11. package/dist/src/commands/auth.js.map +1 -0
  12. package/dist/src/commands/catalog.js +460 -0
  13. package/dist/src/commands/catalog.js.map +1 -0
  14. package/dist/src/commands/integrations.js +438 -0
  15. package/dist/src/commands/integrations.js.map +1 -0
  16. package/dist/src/commands/prompts.js +999 -0
  17. package/dist/src/commands/prompts.js.map +1 -0
  18. package/dist/src/commands/sync.js +598 -0
  19. package/dist/src/commands/sync.js.map +1 -0
  20. package/dist/src/commands/users.js +293 -0
  21. package/dist/src/commands/users.js.map +1 -0
  22. package/dist/src/commands/waitlist.js +176 -0
  23. package/dist/src/commands/waitlist.js.map +1 -0
  24. package/dist/src/commands/workflows.js +876 -0
  25. package/dist/src/commands/workflows.js.map +1 -0
  26. package/dist/src/lib/api-client.js +522 -0
  27. package/dist/src/lib/api-client.js.map +1 -0
  28. package/dist/src/lib/auth-flow.js +306 -0
  29. package/dist/src/lib/auth-flow.js.map +1 -0
  30. package/dist/src/lib/config.js +90 -0
  31. package/dist/src/lib/config.js.map +1 -0
  32. package/dist/src/lib/fetch.js +43 -0
  33. package/dist/src/lib/fetch.js.map +1 -0
  34. package/dist/src/lib/output.js +143 -0
  35. package/dist/src/lib/output.js.map +1 -0
  36. package/dist/src/types/index.js +2 -0
  37. package/dist/src/types/index.js.map +1 -0
  38. package/package.json +47 -0
package/README.md ADDED
@@ -0,0 +1,495 @@
1
+ # primitive-admin CLI
2
+
3
+ Command-line interface for administering Primitive applications. This CLI provides full control over your Primitive apps, including user management, integrations, prompts, workflows, and configuration sync.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g primitive-admin
9
+ ```
10
+
11
+ ### Development Setup
12
+
13
+ From the **worklet root directory**:
14
+
15
+ ```bash
16
+ # Install dependencies
17
+ pnpm install
18
+
19
+ # Build the CLI
20
+ pnpm run cli:build
21
+
22
+ # Link globally for system-wide access
23
+ npm link
24
+ ```
25
+
26
+ Or from the **cli directory** directly:
27
+
28
+ ```bash
29
+ cd cli
30
+
31
+ # Build
32
+ npx tsc
33
+
34
+ # Link globally
35
+ npm link
36
+ ```
37
+
38
+ ### Rebuilding After Changes
39
+
40
+ If you modify CLI source files, rebuild before testing:
41
+
42
+ ```bash
43
+ # From cli directory
44
+ cd cli && npx tsc
45
+
46
+ # Or from worklet root
47
+ pnpm run cli:build
48
+ ```
49
+
50
+ The globally linked `primitive` command uses the compiled files in `cli/dist/`, so changes to source files in `cli/src/` won't take effect until you rebuild.
51
+
52
+ ## Quick Start
53
+
54
+ ```bash
55
+ # Login via browser OAuth
56
+ primitive login
57
+
58
+ # Set your working app context
59
+ primitive use "My App"
60
+
61
+ # List users in the current app
62
+ primitive users list
63
+
64
+ # View help for any command
65
+ primitive --help
66
+ primitive apps --help
67
+ ```
68
+
69
+ ## Authentication
70
+
71
+ The CLI uses browser-based OAuth for authentication. When you run `primitive login`, it opens your browser to authenticate via Google OAuth and stores credentials locally.
72
+
73
+ ```bash
74
+ # Login to the default server
75
+ primitive login
76
+
77
+ # Login to a custom server
78
+ primitive login --server https://api.example.com
79
+
80
+ # View current session
81
+ primitive whoami
82
+
83
+ # Get access token for scripting
84
+ primitive token
85
+
86
+ # Logout
87
+ primitive logout
88
+ ```
89
+
90
+ Credentials are stored in `~/.primitive/credentials.json` with mode 0600.
91
+
92
+ ## App Context
93
+
94
+ Most commands require an app ID. You can specify it in two ways:
95
+
96
+ 1. **Flag**: `primitive users list --app 01HXYZ...`
97
+ 2. **Context**: Set once with `primitive use`, then omit from commands
98
+
99
+ Commands that only need an app ID (like `list`) also accept it as a positional argument:
100
+ ```bash
101
+ primitive users list 01HXYZ...
102
+ ```
103
+
104
+ Commands with other required arguments use only `--app` for the app ID:
105
+ ```bash
106
+ primitive workflows get <workflow-id> --app 01HXYZ...
107
+ ```
108
+
109
+ ```bash
110
+ # Interactive app selection
111
+ primitive use
112
+
113
+ # Set by name or ID
114
+ primitive use "My App"
115
+ primitive use 01HXYZ...
116
+
117
+ # View current context
118
+ primitive context
119
+
120
+ # Clear context
121
+ primitive context clear
122
+ ```
123
+
124
+ ## Commands
125
+
126
+ ### Apps
127
+
128
+ Manage applications (requires admin access).
129
+
130
+ ```bash
131
+ primitive apps list # List all accessible apps
132
+ primitive apps create "My App" # Create a new app
133
+ primitive apps get <app-id> # Get app details
134
+ primitive apps update <app-id> [opts] # Update app settings
135
+ primitive apps delete <app-id> # Delete an app
136
+ ```
137
+
138
+ **Update options:**
139
+ - `--name <name>` - App display name
140
+ - `--mode <mode>` - Access mode: public, invite-only, waitlist
141
+ - `--base-url <url>` - Application base URL
142
+ - `--waitlist` / `--no-waitlist` - Enable/disable waitlist
143
+ - `--google-oauth` / `--no-google-oauth` - Enable/disable Google OAuth
144
+ - `--passkey` / `--no-passkey` - Enable/disable passkey auth
145
+ - `--magic-link` / `--no-magic-link` - Enable/disable magic link auth
146
+
147
+ ### Users
148
+
149
+ Manage users within an app.
150
+
151
+ ```bash
152
+ primitive users list [app-id] # List users
153
+ primitive users invite [app-id] <email> [--role admin] # Invite user
154
+ primitive users remove [app-id] <user-id> # Remove user
155
+ primitive users set-role [app-id] <user-id> <role> # Change role
156
+ primitive users transfer-owner [app-id] <new-owner-id> # Transfer ownership
157
+ primitive users invitations list [app-id] # List pending invitations
158
+ primitive users invitations delete [app-id] <inv-id> # Delete invitation
159
+ ```
160
+
161
+ ### Waitlist
162
+
163
+ Manage waitlist entries for apps in waitlist mode.
164
+
165
+ ```bash
166
+ primitive waitlist list [app-id] # List waitlist entries
167
+ primitive waitlist invite [app-id] <waitlist-id> # Invite from waitlist
168
+ primitive waitlist bulk-invite [app-id] -n 10 # Bulk invite
169
+ primitive waitlist remove [app-id] <waitlist-id> # Remove from waitlist
170
+ ```
171
+
172
+ ### Integrations
173
+
174
+ Manage HTTP integrations (external API connections).
175
+
176
+ ```bash
177
+ primitive integrations list [app-id] # List integrations
178
+ primitive integrations create [app-id] [options] # Create integration
179
+ primitive integrations get <integration-id> # Get details
180
+ primitive integrations update <id> [options] # Update integration
181
+ primitive integrations delete <id> # Soft delete
182
+ primitive integrations test <id> # Test connection
183
+ primitive integrations logs <id> # View invocation logs
184
+ ```
185
+
186
+ **Create options:**
187
+ - `--from-file <path>` - Load from TOML file
188
+ - `--key <key>` - Integration key (identifier)
189
+ - `--name <name>` - Display name
190
+ - `--base-url <url>` - Base URL for API calls
191
+ - `--timeout <ms>` - Request timeout in milliseconds
192
+
193
+ **Secrets management:**
194
+ ```bash
195
+ primitive integrations secrets list <integration-id>
196
+ primitive integrations secrets add <id> --data '{"apiKey":"..."}'
197
+ primitive integrations secrets archive <id> <secret-id>
198
+ ```
199
+
200
+ ### Prompts
201
+
202
+ Manage LLM prompt configurations.
203
+
204
+ ```bash
205
+ primitive prompts list [app-id] # List prompts
206
+ primitive prompts create [app-id] [options] # Create prompt
207
+ primitive prompts get <prompt-id> # Get details
208
+ primitive prompts update <id> [options] # Update prompt
209
+ primitive prompts delete <id> # Soft delete
210
+ primitive prompts execute <id> --vars '{}' # Execute prompt
211
+ primitive prompts preview <id> --vars '{}' # Preview rendered template
212
+ ```
213
+
214
+ **Create options:**
215
+ - `--from-file <path>` - Load from TOML file
216
+ - `--key <key>` - Prompt key (identifier)
217
+ - `--name <name>` - Display name
218
+ - `--provider <provider>` - LLM provider (openrouter, gemini)
219
+ - `--model <model>` - Model name
220
+ - `--system-prompt <text>` - System prompt
221
+ - `--user-template <text>` - User prompt template
222
+
223
+ **Configs (prompt variations):**
224
+ ```bash
225
+ primitive prompts configs list <prompt-id>
226
+ primitive prompts configs create <prompt-id> [options]
227
+ primitive prompts configs activate <prompt-id> <config-id>
228
+ primitive prompts configs duplicate <prompt-id> <config-id>
229
+ ```
230
+
231
+ ### Workflows
232
+
233
+ Manage multi-step workflow definitions.
234
+
235
+ ```bash
236
+ primitive workflows list [app-id] # List workflows
237
+ primitive workflows create [app-id] --from-file wf.toml # Create workflow
238
+ primitive workflows get <workflow-id> # Get details
239
+ primitive workflows update <id> [options] # Update metadata
240
+ primitive workflows draft update <id> --from-file wf.toml # Update draft
241
+ primitive workflows publish <id> # Publish draft
242
+ primitive workflows preview <id> --input '{}' # Preview execution
243
+ ```
244
+
245
+ **Run management:**
246
+ ```bash
247
+ primitive workflows runs list <workflow-id>
248
+ primitive workflows runs status <workflow-id> <run-id>
249
+ ```
250
+
251
+ ### Analytics
252
+
253
+ View usage analytics for an app.
254
+
255
+ ```bash
256
+ primitive analytics overview [app-id] # Activity overview
257
+ primitive analytics top-users [app-id] # Most active users
258
+ primitive analytics user [app-id] <user-ulid> # User activity details
259
+ primitive analytics integrations [app-id] # Integration metrics
260
+ ```
261
+
262
+ **Options:**
263
+ - `--window-days <n>` - Time window (default: 30)
264
+ - `--limit <n>` - Result limit for top-users
265
+
266
+ ### Admins (Super-Admin Only)
267
+
268
+ Manage the admin directory.
269
+
270
+ ```bash
271
+ primitive admins list # List all admins
272
+ primitive admins search <email> # Search by email
273
+ primitive admins invite <email> # Create invitation
274
+ primitive admins update <admin-id> [options] # Update settings
275
+ primitive admins disable <admin-id> # Disable account
276
+ primitive admins enable <admin-id> # Enable account
277
+ primitive admins invitations list # List invitations
278
+ primitive admins invitations delete <invitation-id>
279
+ ```
280
+
281
+ ### Catalog (Super-Admin Only)
282
+
283
+ Manage the global prompt and integration catalog.
284
+
285
+ ```bash
286
+ # Prompt catalog
287
+ primitive catalog prompts list
288
+ primitive catalog prompts create --from-file prompt.toml
289
+ primitive catalog prompts get <catalog-id>
290
+ primitive catalog prompts update <catalog-id> [options]
291
+ primitive catalog prompts delete <catalog-id>
292
+
293
+ # Integration catalog
294
+ primitive catalog integrations list
295
+ primitive catalog integrations create --from-file integration.toml
296
+ primitive catalog integrations get <catalog-id>
297
+ primitive catalog integrations update <catalog-id> [options]
298
+ primitive catalog integrations delete <catalog-id>
299
+ ```
300
+
301
+ ### Sync (TOML Configuration)
302
+
303
+ Sync app configuration to/from TOML files for version control.
304
+
305
+ ```bash
306
+ primitive sync init [app-id] --dir ./config # Initialize config directory
307
+ primitive sync pull [app-id] --dir ./config # Pull remote config to local
308
+ primitive sync push [app-id] --dir ./config # Push local config to remote
309
+ primitive sync diff [app-id] --dir ./config # Show differences
310
+ ```
311
+
312
+ **Options:**
313
+ - `--dir <path>` - Config directory (default: ./config)
314
+ - `--dry-run` - Show changes without applying (push only)
315
+ - `--force` - Overwrite remote changes (push only)
316
+
317
+ ## TOML Configuration Format
318
+
319
+ The sync commands use TOML files for configuration. Here's the directory structure:
320
+
321
+ ```
322
+ config/
323
+ .primitive-sync.json # Sync state (auto-generated)
324
+ app.toml # App settings
325
+ integrations/
326
+ weather-api.toml # Integration configs
327
+ prompts/
328
+ summarizer.toml # Prompt configs with all variations
329
+ workflows/
330
+ process-doc.toml # Workflow definitions
331
+ ```
332
+
333
+ ### Example: app.toml
334
+
335
+ ```toml
336
+ [app]
337
+ name = "My Application"
338
+ mode = "invite-only"
339
+ waitlistEnabled = false
340
+ baseUrl = "https://myapp.com"
341
+
342
+ [auth]
343
+ googleOAuthEnabled = true
344
+ passkeyEnabled = true
345
+ magicLinkEnabled = false
346
+
347
+ [cors]
348
+ mode = "custom"
349
+ allowedOrigins = ["https://myapp.com"]
350
+ allowCredentials = true
351
+ ```
352
+
353
+ ### Example: integrations/weather-api.toml
354
+
355
+ ```toml
356
+ [integration]
357
+ key = "weather-api"
358
+ displayName = "Weather API"
359
+ description = "OpenWeatherMap integration"
360
+ status = "active"
361
+ timeoutMs = 30000
362
+
363
+ [requestConfig]
364
+ baseUrl = "https://api.openweathermap.org/data/2.5"
365
+ allowedMethods = ["GET"]
366
+ allowedPaths = ["/weather", "/forecast"]
367
+ ```
368
+
369
+ ### Example: prompts/summarizer.toml
370
+
371
+ ```toml
372
+ [prompt]
373
+ key = "summarizer"
374
+ displayName = "Text Summarizer"
375
+ description = "Summarizes input text"
376
+ status = "active"
377
+
378
+ [[configs]]
379
+ name = "default"
380
+ provider = "openrouter"
381
+ model = "google/gemini-2.0-flash-001"
382
+ temperature = "0.7"
383
+ maxTokens = 500
384
+ systemPrompt = "You are a helpful assistant."
385
+ userPromptTemplate = "Summarize: {{ input.text }}"
386
+
387
+ [[configs]]
388
+ name = "concise"
389
+ provider = "openrouter"
390
+ model = "google/gemini-2.0-flash-001"
391
+ temperature = "0.3"
392
+ maxTokens = 200
393
+ systemPrompt = "You create very brief summaries."
394
+ userPromptTemplate = "Brief summary:\n{{ input.text }}"
395
+ ```
396
+
397
+ ## Output Formats
398
+
399
+ All list/get commands support `--json` for machine-readable output:
400
+
401
+ ```bash
402
+ # Human-readable table
403
+ primitive apps list
404
+
405
+ # JSON output for scripting
406
+ primitive apps list --json | jq '.[0].appId'
407
+ ```
408
+
409
+ ## Exit Codes
410
+
411
+ - `0` - Success
412
+ - `1` - General error
413
+ - `2` - Authentication error (try `primitive login`)
414
+
415
+ ## Environment Variables
416
+
417
+ - `PRIMITIVE_SERVER_URL` - Server URL for login (defaults to `https://primitiveapi.com`)
418
+
419
+ **Server URL priority:**
420
+ 1. `--server` flag (highest priority)
421
+ 2. `PRIMITIVE_SERVER_URL` environment variable
422
+ 3. Default: `https://primitiveapi.com`
423
+
424
+ ## Development
425
+
426
+ ```bash
427
+ # Run without building (uses tsx)
428
+ pnpm run cli:dev -- login
429
+
430
+ # Type check
431
+ pnpm run cli:typecheck
432
+
433
+ # Build
434
+ pnpm run cli:build
435
+ ```
436
+
437
+ ## Testing
438
+
439
+ The CLI includes both unit tests and integration tests.
440
+
441
+ ### Unit Tests
442
+
443
+ Unit tests run without requiring a server connection:
444
+
445
+ ```bash
446
+ # Run all unit tests
447
+ pnpm run cli:test:unit
448
+ ```
449
+
450
+ ### Integration Tests
451
+
452
+ Integration tests require a running server and valid admin credentials:
453
+
454
+ ```bash
455
+ # Set required environment variables
456
+ export TEST_HTTP_URL=https://localhost:8787
457
+ export TEST_ADMIN_JWT=your-admin-jwt-token
458
+ export TEST_APP_ID=01HXYZ... # Optional: for app-scoped tests
459
+
460
+ # Run integration tests
461
+ pnpm run cli:test:integration
462
+ ```
463
+
464
+ ### All Tests
465
+
466
+ ```bash
467
+ # Run all CLI tests
468
+ pnpm run cli:test
469
+ ```
470
+
471
+ ### Test Structure
472
+
473
+ ```
474
+ cli/tests/
475
+ unit/
476
+ config.test.ts # Credentials and config management
477
+ output.test.ts # Output formatting functions
478
+ integration/
479
+ api-client.test.ts # API client HTTP tests
480
+ commands.test.ts # CLI command tests
481
+ ```
482
+
483
+ ## Troubleshooting
484
+
485
+ ### "Not logged in" error
486
+ Run `primitive login` to authenticate.
487
+
488
+ ### "No app specified" error
489
+ Either pass an app ID as an argument, use `--app <id>`, or set context with `primitive use`.
490
+
491
+ ### Token expired
492
+ The CLI automatically refreshes tokens. If issues persist, try `primitive logout` then `primitive login`.
493
+
494
+ ### Connection errors
495
+ Verify your server URL with `primitive whoami` and check network connectivity.
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { registerAuthCommands } from "../src/commands/auth.js";
4
+ import { registerAppsCommands } from "../src/commands/apps.js";
5
+ import { registerUsersCommands } from "../src/commands/users.js";
6
+ import { registerWaitlistCommands } from "../src/commands/waitlist.js";
7
+ import { registerIntegrationsCommands } from "../src/commands/integrations.js";
8
+ import { registerPromptsCommands } from "../src/commands/prompts.js";
9
+ import { registerWorkflowsCommands } from "../src/commands/workflows.js";
10
+ import { registerAdminsCommands } from "../src/commands/admins.js";
11
+ import { registerCatalogCommands } from "../src/commands/catalog.js";
12
+ import { registerAnalyticsCommands } from "../src/commands/analytics.js";
13
+ import { registerSyncCommands } from "../src/commands/sync.js";
14
+ import { error } from "../src/lib/output.js";
15
+ import { ApiError } from "../src/lib/api-client.js";
16
+ const program = new Command();
17
+ program
18
+ .name("primitive")
19
+ .description(`CLI for administering Primitive applications.
20
+
21
+ Manage apps, users, integrations, prompts, workflows, and more from the command line.
22
+ Supports TOML-based configuration sync for version-controlled app settings.`)
23
+ .version("1.0.0")
24
+ .addHelpText("after", `
25
+ Examples:
26
+ $ primitive login # Authenticate via browser OAuth
27
+ $ primitive use "My App" # Set working app context
28
+ $ primitive users list # List users (uses current app)
29
+ $ primitive integrations list --json # JSON output for scripting
30
+ $ primitive sync pull --dir ./config # Export config to TOML files
31
+
32
+ Authentication:
33
+ Credentials are stored in ~/.primitive/credentials.json
34
+
35
+ App Context:
36
+ Set with 'primitive use <app>' to avoid passing --app to every command.
37
+ Most commands accept --app flag to override the current context.
38
+
39
+ Documentation:
40
+ See https://github.com/anthropics/primitive for full documentation.
41
+ `);
42
+ // Register all command groups
43
+ registerAuthCommands(program);
44
+ registerAppsCommands(program);
45
+ registerUsersCommands(program);
46
+ registerWaitlistCommands(program);
47
+ registerIntegrationsCommands(program);
48
+ registerPromptsCommands(program);
49
+ registerWorkflowsCommands(program);
50
+ registerAdminsCommands(program);
51
+ registerCatalogCommands(program);
52
+ registerAnalyticsCommands(program);
53
+ registerSyncCommands(program);
54
+ // Global error handler
55
+ program.hook("preAction", () => {
56
+ // Reset API client state before each command
57
+ });
58
+ // Parse and execute
59
+ program.parseAsync(process.argv).catch((err) => {
60
+ if (err instanceof ApiError) {
61
+ error(err.message);
62
+ if (err.statusCode === 401) {
63
+ error("Try running 'primitive login' to authenticate.");
64
+ }
65
+ process.exit(err.statusCode === 401 ? 2 : 1);
66
+ }
67
+ else {
68
+ error(err.message || "An unexpected error occurred");
69
+ process.exit(1);
70
+ }
71
+ });
72
+ //# sourceMappingURL=primitive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitive.js","sourceRoot":"","sources":["../../bin/primitive.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC;;;4EAG6D,CAAC;KAC1E,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,OAAO,EAAE;;;;;;;;;;;;;;;;;CAiBvB,CAAC,CAAC;AAEH,8BAA8B;AAC9B,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,4BAA4B,CAAC,OAAO,CAAC,CAAC;AACtC,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,yBAAyB,CAAC,OAAO,CAAC,CAAC;AACnC,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,yBAAyB,CAAC,OAAO,CAAC,CAAC;AACnC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAE9B,uBAAuB;AACvB,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;IAC7B,6CAA6C;AAC/C,CAAC,CAAC,CAAC;AAEH,oBAAoB;AACpB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;QAC5B,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACnB,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;YAC3B,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,8BAA8B,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}