@ginkoai/cli 2.0.6 → 2.1.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.
Files changed (149) hide show
  1. package/dist/commands/epic/index.d.ts +29 -0
  2. package/dist/commands/epic/index.d.ts.map +1 -0
  3. package/dist/commands/epic/index.js +94 -0
  4. package/dist/commands/epic/index.js.map +1 -0
  5. package/dist/commands/epic/status.d.ts +40 -0
  6. package/dist/commands/epic/status.d.ts.map +1 -0
  7. package/dist/commands/epic/status.js +244 -0
  8. package/dist/commands/epic/status.js.map +1 -0
  9. package/dist/commands/graph/api-client.d.ts +221 -1
  10. package/dist/commands/graph/api-client.d.ts.map +1 -1
  11. package/dist/commands/graph/api-client.js +141 -2
  12. package/dist/commands/graph/api-client.js.map +1 -1
  13. package/dist/commands/graph/load.d.ts.map +1 -1
  14. package/dist/commands/graph/load.js +40 -2
  15. package/dist/commands/graph/load.js.map +1 -1
  16. package/dist/commands/handoff.d.ts +3 -3
  17. package/dist/commands/handoff.d.ts.map +1 -1
  18. package/dist/commands/handoff.js +32 -3
  19. package/dist/commands/handoff.js.map +1 -1
  20. package/dist/commands/migrate/index.d.ts +27 -0
  21. package/dist/commands/migrate/index.d.ts.map +1 -0
  22. package/dist/commands/migrate/index.js +76 -0
  23. package/dist/commands/migrate/index.js.map +1 -0
  24. package/dist/commands/migrate/status-migration.d.ts +58 -0
  25. package/dist/commands/migrate/status-migration.d.ts.map +1 -0
  26. package/dist/commands/migrate/status-migration.js +323 -0
  27. package/dist/commands/migrate/status-migration.js.map +1 -0
  28. package/dist/commands/nudging/index.d.ts +24 -0
  29. package/dist/commands/nudging/index.d.ts.map +1 -0
  30. package/dist/commands/nudging/index.js +175 -0
  31. package/dist/commands/nudging/index.js.map +1 -0
  32. package/dist/commands/sprint/create.d.ts +26 -0
  33. package/dist/commands/sprint/create.d.ts.map +1 -0
  34. package/dist/commands/sprint/create.js +269 -0
  35. package/dist/commands/sprint/create.js.map +1 -0
  36. package/dist/commands/sprint/index.d.ts.map +1 -1
  37. package/dist/commands/sprint/index.js +28 -0
  38. package/dist/commands/sprint/index.js.map +1 -1
  39. package/dist/commands/sprint/quick-fix.d.ts +25 -0
  40. package/dist/commands/sprint/quick-fix.d.ts.map +1 -0
  41. package/dist/commands/sprint/quick-fix.js +151 -0
  42. package/dist/commands/sprint/quick-fix.js.map +1 -0
  43. package/dist/commands/sprint/sprint-pipeline-enhanced.d.ts.map +1 -1
  44. package/dist/commands/sprint/sprint-pipeline-enhanced.js +37 -0
  45. package/dist/commands/sprint/sprint-pipeline-enhanced.js.map +1 -1
  46. package/dist/commands/sprint/status.d.ts +42 -0
  47. package/dist/commands/sprint/status.d.ts.map +1 -0
  48. package/dist/commands/sprint/status.js +298 -0
  49. package/dist/commands/sprint/status.js.map +1 -0
  50. package/dist/commands/start/start-reflection.d.ts +53 -0
  51. package/dist/commands/start/start-reflection.d.ts.map +1 -1
  52. package/dist/commands/start/start-reflection.js +464 -71
  53. package/dist/commands/start/start-reflection.js.map +1 -1
  54. package/dist/commands/sync/sprint-syncer.d.ts +19 -12
  55. package/dist/commands/sync/sprint-syncer.d.ts.map +1 -1
  56. package/dist/commands/sync/sprint-syncer.js +58 -140
  57. package/dist/commands/sync/sprint-syncer.js.map +1 -1
  58. package/dist/commands/sync/sync-command.d.ts.map +1 -1
  59. package/dist/commands/sync/sync-command.js +6 -18
  60. package/dist/commands/sync/sync-command.js.map +1 -1
  61. package/dist/commands/task/index.d.ts +25 -0
  62. package/dist/commands/task/index.d.ts.map +1 -0
  63. package/dist/commands/task/index.js +100 -0
  64. package/dist/commands/task/index.js.map +1 -0
  65. package/dist/commands/task/status.d.ts +46 -0
  66. package/dist/commands/task/status.d.ts.map +1 -0
  67. package/dist/commands/task/status.js +348 -0
  68. package/dist/commands/task/status.js.map +1 -0
  69. package/dist/commands/team/index.d.ts +5 -0
  70. package/dist/commands/team/index.d.ts.map +1 -1
  71. package/dist/commands/team/index.js +28 -0
  72. package/dist/commands/team/index.js.map +1 -1
  73. package/dist/commands/team/status.d.ts +16 -0
  74. package/dist/commands/team/status.d.ts.map +1 -0
  75. package/dist/commands/team/status.js +180 -0
  76. package/dist/commands/team/status.js.map +1 -0
  77. package/dist/index.js +21 -32
  78. package/dist/index.js.map +1 -1
  79. package/dist/lib/adoption-score.d.ts +69 -0
  80. package/dist/lib/adoption-score.d.ts.map +1 -0
  81. package/dist/lib/adoption-score.js +206 -0
  82. package/dist/lib/adoption-score.js.map +1 -0
  83. package/dist/lib/coaching-level.d.ts +127 -0
  84. package/dist/lib/coaching-level.d.ts.map +1 -0
  85. package/dist/lib/coaching-level.js +406 -0
  86. package/dist/lib/coaching-level.js.map +1 -0
  87. package/dist/lib/context-loader-events.d.ts.map +1 -1
  88. package/dist/lib/context-loader-events.js +7 -26
  89. package/dist/lib/context-loader-events.js.map +1 -1
  90. package/dist/lib/event-logger.d.ts +42 -0
  91. package/dist/lib/event-logger.d.ts.map +1 -1
  92. package/dist/lib/event-logger.js +77 -0
  93. package/dist/lib/event-logger.js.map +1 -1
  94. package/dist/lib/output-formatter.d.ts +8 -2
  95. package/dist/lib/output-formatter.d.ts.map +1 -1
  96. package/dist/lib/output-formatter.js +98 -18
  97. package/dist/lib/output-formatter.js.map +1 -1
  98. package/dist/lib/pending-updates.d.ts +148 -0
  99. package/dist/lib/pending-updates.d.ts.map +1 -0
  100. package/dist/lib/pending-updates.js +301 -0
  101. package/dist/lib/pending-updates.js.map +1 -0
  102. package/dist/lib/planning-menu.d.ts +69 -0
  103. package/dist/lib/planning-menu.d.ts.map +1 -0
  104. package/dist/lib/planning-menu.js +342 -0
  105. package/dist/lib/planning-menu.js.map +1 -0
  106. package/dist/lib/sprint-loader.d.ts +86 -14
  107. package/dist/lib/sprint-loader.d.ts.map +1 -1
  108. package/dist/lib/sprint-loader.js +293 -98
  109. package/dist/lib/sprint-loader.js.map +1 -1
  110. package/dist/lib/state-cache.d.ts +142 -0
  111. package/dist/lib/state-cache.d.ts.map +1 -0
  112. package/dist/lib/state-cache.js +259 -0
  113. package/dist/lib/state-cache.js.map +1 -0
  114. package/dist/lib/targeted-coaching.d.ts +71 -0
  115. package/dist/lib/targeted-coaching.d.ts.map +1 -0
  116. package/dist/lib/targeted-coaching.js +318 -0
  117. package/dist/lib/targeted-coaching.js.map +1 -0
  118. package/dist/lib/task-graph-sync.d.ts +105 -0
  119. package/dist/lib/task-graph-sync.d.ts.map +1 -0
  120. package/dist/lib/task-graph-sync.js +178 -0
  121. package/dist/lib/task-graph-sync.js.map +1 -0
  122. package/dist/lib/task-parser.d.ts +109 -0
  123. package/dist/lib/task-parser.d.ts.map +1 -0
  124. package/dist/lib/task-parser.js +407 -0
  125. package/dist/lib/task-parser.js.map +1 -0
  126. package/dist/lib/user-sprint.d.ts +53 -0
  127. package/dist/lib/user-sprint.d.ts.map +1 -1
  128. package/dist/lib/user-sprint.js +137 -2
  129. package/dist/lib/user-sprint.js.map +1 -1
  130. package/dist/lib/work-reconciliation.d.ts +59 -0
  131. package/dist/lib/work-reconciliation.d.ts.map +1 -0
  132. package/dist/lib/work-reconciliation.js +267 -0
  133. package/dist/lib/work-reconciliation.js.map +1 -0
  134. package/dist/templates/ai-instructions-template.d.ts.map +1 -1
  135. package/dist/templates/ai-instructions-template.js +7 -5
  136. package/dist/templates/ai-instructions-template.js.map +1 -1
  137. package/dist/templates/epic-template.md +0 -2
  138. package/dist/types/config.d.ts.map +1 -1
  139. package/dist/types/config.js +7 -5
  140. package/dist/types/config.js.map +1 -1
  141. package/dist/utils/synthesis.d.ts +4 -0
  142. package/dist/utils/synthesis.d.ts.map +1 -1
  143. package/dist/utils/synthesis.js +12 -18
  144. package/dist/utils/synthesis.js.map +1 -1
  145. package/dist/utils/version-check.d.ts +26 -0
  146. package/dist/utils/version-check.d.ts.map +1 -0
  147. package/dist/utils/version-check.js +186 -0
  148. package/dist/utils/version-check.js.map +1 -0
  149. package/package.json +2 -2
@@ -0,0 +1,301 @@
1
+ /**
2
+ * @fileType: utility
3
+ * @status: current
4
+ * @updated: 2026-01-19
5
+ * @tags: [offline, queue, sync, EPIC-015]
6
+ * @related: [state-cache.ts, api-client.ts]
7
+ * @priority: medium
8
+ * @complexity: medium
9
+ * @dependencies: [fs-extra, path]
10
+ */
11
+ /**
12
+ * Pending Updates Queue (EPIC-015 Sprint 2 Task 6)
13
+ *
14
+ * Provides offline queueing for status updates when API is unavailable:
15
+ * - Queue status updates when offline
16
+ * - Process queued updates when back online
17
+ * - "Local wins" conflict resolution (queued update takes precedence)
18
+ * - Max 3 retry attempts before permanent failure
19
+ *
20
+ * Queue location: .ginko/pending-updates.json
21
+ * Uses atomic writes (temp file + rename) to prevent partial writes.
22
+ */
23
+ import fs from 'fs-extra';
24
+ import path from 'path';
25
+ import { randomUUID } from 'crypto';
26
+ import { getGinkoDir } from '../utils/helpers.js';
27
+ // =============================================================================
28
+ // Constants
29
+ // =============================================================================
30
+ const QUEUE_FILE = 'pending-updates.json';
31
+ const QUEUE_VERSION = 1;
32
+ const MAX_ATTEMPTS = 3;
33
+ // =============================================================================
34
+ // Queue Management
35
+ // =============================================================================
36
+ /**
37
+ * Load pending updates from disk
38
+ *
39
+ * @returns Array of pending updates, empty array if no queue file exists
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const updates = await loadPendingUpdates();
44
+ * console.log(`${updates.length} updates pending`);
45
+ * ```
46
+ */
47
+ export async function loadPendingUpdates() {
48
+ try {
49
+ const queuePath = await getQueuePath();
50
+ if (!await fs.pathExists(queuePath)) {
51
+ return [];
52
+ }
53
+ const data = await fs.readJSON(queuePath);
54
+ // Validate queue structure
55
+ if (!isValidQueue(data)) {
56
+ return [];
57
+ }
58
+ return data.updates || [];
59
+ }
60
+ catch (error) {
61
+ // File doesn't exist, is invalid JSON, or other read error
62
+ return [];
63
+ }
64
+ }
65
+ /**
66
+ * Queue a status update for later sync
67
+ * Used when API call fails due to network error
68
+ *
69
+ * @param update - Update to queue (id, queued_at, attempts added automatically)
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * await queueUpdate({
74
+ * type: 'task_status',
75
+ * entity_id: 'e015_s02_t01',
76
+ * new_status: 'complete'
77
+ * });
78
+ * ```
79
+ */
80
+ export async function queueUpdate(update) {
81
+ const updates = await loadPendingUpdates();
82
+ // Check if there's already a pending update for this entity
83
+ // If so, replace it (latest update wins)
84
+ const existingIndex = updates.findIndex(u => u.entity_id === update.entity_id && u.type === update.type);
85
+ const newUpdate = {
86
+ id: randomUUID(),
87
+ ...update,
88
+ queued_at: new Date().toISOString(),
89
+ attempts: 0,
90
+ };
91
+ if (existingIndex >= 0) {
92
+ // Replace existing update for same entity
93
+ updates[existingIndex] = newUpdate;
94
+ }
95
+ else {
96
+ // Add new update
97
+ updates.push(newUpdate);
98
+ }
99
+ await saveQueue(updates);
100
+ }
101
+ /**
102
+ * Remove a specific update from the queue
103
+ *
104
+ * @param updateId - UUID of the update to remove
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * await removeUpdate('abc-123-def');
109
+ * ```
110
+ */
111
+ export async function removeUpdate(updateId) {
112
+ const updates = await loadPendingUpdates();
113
+ const filtered = updates.filter(u => u.id !== updateId);
114
+ if (filtered.length !== updates.length) {
115
+ await saveQueue(filtered);
116
+ }
117
+ }
118
+ /**
119
+ * Clear all pending updates from the queue
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * await clearPendingUpdates();
124
+ * ```
125
+ */
126
+ export async function clearPendingUpdates() {
127
+ try {
128
+ const queuePath = await getQueuePath();
129
+ if (await fs.pathExists(queuePath)) {
130
+ await fs.remove(queuePath);
131
+ }
132
+ }
133
+ catch (error) {
134
+ // Ignore errors when clearing queue
135
+ }
136
+ }
137
+ /**
138
+ * Check if there are pending updates
139
+ *
140
+ * @returns true if queue has at least one update
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * if (await hasPendingUpdates()) {
145
+ * console.log('Pending updates need to sync');
146
+ * }
147
+ * ```
148
+ */
149
+ export async function hasPendingUpdates() {
150
+ const updates = await loadPendingUpdates();
151
+ return updates.length > 0;
152
+ }
153
+ // =============================================================================
154
+ // Sync Processing
155
+ // =============================================================================
156
+ /**
157
+ * Process all pending updates, syncing them to the API
158
+ *
159
+ * Processing logic:
160
+ * - Iterates oldest-first (FIFO order)
161
+ * - On success: removes update from queue
162
+ * - On failure: increments attempts, keeps in queue (max 3 attempts)
163
+ * - Conflict resolution: "local wins" (queued update takes precedence)
164
+ *
165
+ * @param client - Authenticated GraphApiClient instance
166
+ * @returns Counts of succeeded and failed updates
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * const client = new GraphApiClient();
171
+ * const result = await processPendingUpdates(client);
172
+ * console.log(`Synced ${result.succeeded}, failed ${result.failed}`);
173
+ * ```
174
+ */
175
+ export async function processPendingUpdates(client) {
176
+ const updates = await loadPendingUpdates();
177
+ if (updates.length === 0) {
178
+ return { succeeded: 0, failed: 0 };
179
+ }
180
+ let succeeded = 0;
181
+ let failed = 0;
182
+ const remaining = [];
183
+ // Get graph ID from environment
184
+ const graphId = process.env.GINKO_GRAPH_ID || '';
185
+ if (!graphId) {
186
+ // Can't process without graph ID, keep all updates
187
+ return { succeeded: 0, failed: updates.length };
188
+ }
189
+ // Sort by queued_at to process oldest first
190
+ const sortedUpdates = [...updates].sort((a, b) => new Date(a.queued_at).getTime() - new Date(b.queued_at).getTime());
191
+ for (const update of sortedUpdates) {
192
+ try {
193
+ await processUpdate(client, graphId, update);
194
+ succeeded++;
195
+ // Don't add to remaining - it was successful
196
+ }
197
+ catch (error) {
198
+ // Increment attempts
199
+ update.attempts++;
200
+ if (update.attempts >= MAX_ATTEMPTS) {
201
+ // Max attempts reached, count as failed and don't keep
202
+ failed++;
203
+ }
204
+ else {
205
+ // Keep in queue for retry
206
+ remaining.push(update);
207
+ failed++;
208
+ }
209
+ }
210
+ }
211
+ // Save remaining updates (excluding succeeded and permanently failed)
212
+ await saveQueue(remaining);
213
+ return { succeeded, failed };
214
+ }
215
+ /**
216
+ * Process a single update by calling the appropriate API method
217
+ */
218
+ async function processUpdate(client, graphId, update) {
219
+ switch (update.type) {
220
+ case 'task_status':
221
+ await client.updateTaskStatus(graphId, update.entity_id, update.new_status, update.reason);
222
+ break;
223
+ case 'sprint_status':
224
+ await client.updateSprintStatus(graphId, update.entity_id, update.new_status);
225
+ break;
226
+ case 'epic_status':
227
+ await client.updateEpicStatus(graphId, update.entity_id, update.new_status);
228
+ break;
229
+ default:
230
+ throw new Error(`Unknown update type: ${update.type}`);
231
+ }
232
+ }
233
+ // =============================================================================
234
+ // Helper Functions
235
+ // =============================================================================
236
+ /**
237
+ * Get the full path to the queue file
238
+ */
239
+ async function getQueuePath() {
240
+ const ginkoDir = await getGinkoDir();
241
+ return path.join(ginkoDir, QUEUE_FILE);
242
+ }
243
+ /**
244
+ * Save updates to queue file using atomic write
245
+ */
246
+ async function saveQueue(updates) {
247
+ const queuePath = await getQueuePath();
248
+ const queueDir = path.dirname(queuePath);
249
+ const tempPath = `${queuePath}.tmp.${Date.now()}`;
250
+ // Ensure .ginko directory exists
251
+ await fs.ensureDir(queueDir);
252
+ const queue = {
253
+ version: QUEUE_VERSION,
254
+ updates,
255
+ };
256
+ // Atomic write: write to temp file, then rename
257
+ try {
258
+ await fs.writeJSON(tempPath, queue, { spaces: 2 });
259
+ await fs.rename(tempPath, queuePath);
260
+ }
261
+ catch (error) {
262
+ // Clean up temp file if rename failed
263
+ try {
264
+ await fs.remove(tempPath);
265
+ }
266
+ catch {
267
+ // Ignore cleanup errors
268
+ }
269
+ throw error;
270
+ }
271
+ }
272
+ /**
273
+ * Validate that queue data has correct structure and version
274
+ */
275
+ function isValidQueue(data) {
276
+ if (!data || typeof data !== 'object') {
277
+ return false;
278
+ }
279
+ const queue = data;
280
+ // Check version
281
+ if (queue.version !== QUEUE_VERSION) {
282
+ return false;
283
+ }
284
+ // Check updates array exists
285
+ if (!Array.isArray(queue.updates)) {
286
+ return false;
287
+ }
288
+ return true;
289
+ }
290
+ // =============================================================================
291
+ // Exports for Testing
292
+ // =============================================================================
293
+ export const _internal = {
294
+ getQueuePath,
295
+ saveQueue,
296
+ isValidQueue,
297
+ processUpdate,
298
+ QUEUE_VERSION,
299
+ MAX_ATTEMPTS,
300
+ };
301
+ //# sourceMappingURL=pending-updates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-updates.js","sourceRoot":"","sources":["../../src/lib/pending-updates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @fileType: utility
3
+ * @status: current
4
+ * @updated: 2026-01-26
5
+ * @tags: [planning, menu, coaching, structure-detection, epic-016-s04]
6
+ * @related: [start-reflection.ts, user-sprint.ts, event-logger.ts]
7
+ * @priority: high
8
+ * @complexity: medium
9
+ * @dependencies: [prompts, chalk, event-logger]
10
+ */
11
+ import { WorkStructureStatus } from './user-sprint.js';
12
+ import { CoachingLevel } from './coaching-level.js';
13
+ export type PlanningChoice = 'epic' | 'sprint' | 'quick-fix' | 'adhoc';
14
+ export interface PlanningMenuResult {
15
+ choice: PlanningChoice | null;
16
+ cancelled: boolean;
17
+ }
18
+ export interface PlanningRouteResult {
19
+ success: boolean;
20
+ sprintId?: string;
21
+ taskId?: string;
22
+ message?: string;
23
+ shouldContinueStart?: boolean;
24
+ }
25
+ /**
26
+ * Display the guided planning menu and get user selection
27
+ *
28
+ * Called when ginko start detects no structured work.
29
+ * Logs selection for coaching insights analysis (t05).
30
+ * Uses adoption-based quieting to adjust verbosity.
31
+ *
32
+ * @param status - Work structure status from checkWorkStructure()
33
+ * @returns Menu selection result
34
+ */
35
+ export declare function showPlanningMenu(status?: WorkStructureStatus): Promise<PlanningMenuResult>;
36
+ /**
37
+ * Log the planning menu selection for coaching analysis (t05)
38
+ *
39
+ * Enables the insights system to:
40
+ * - Track pattern adoption over time
41
+ * - Identify users who frequently choose ad-hoc
42
+ * - Measure effectiveness of planning prompts
43
+ *
44
+ * Also records adoption signals for quieting behavior.
45
+ */
46
+ declare function logPlanningChoice(choice: PlanningChoice, coachingLevel?: CoachingLevel, overallScore?: number): Promise<void>;
47
+ /**
48
+ * Route the planning menu choice to appropriate handler
49
+ *
50
+ * Routes:
51
+ * - epic → launches ginko epic command
52
+ * - sprint → launches sprint creation flow (t03)
53
+ * - quick-fix → launches quick-fix flow (t04)
54
+ * - adhoc → marks session as ad-hoc, continues to normal start
55
+ *
56
+ * @param choice - User's menu selection
57
+ * @returns Route result with success status and metadata
58
+ */
59
+ export declare function routePlanningChoice(choice: PlanningChoice): Promise<PlanningRouteResult>;
60
+ export declare const __testing: {
61
+ PLANNING_MENU_CHOICES: {
62
+ title: string;
63
+ description: string;
64
+ value: PlanningChoice;
65
+ }[];
66
+ logPlanningChoice: typeof logPlanningChoice;
67
+ };
68
+ export {};
69
+ //# sourceMappingURL=planning-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planning-menu.d.ts","sourceRoot":"","sources":["../../src/lib/planning-menu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAkBH,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAWvD,OAAO,EAEL,aAAa,EAId,MAAM,qBAAqB,CAAC;AAO7B,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC;AAEvE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAiCD;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CA0E7B;AAED;;;;;;;;;GASG;AACH,iBAAe,iBAAiB,CAC9B,MAAM,EAAE,cAAc,EACtB,aAAa,CAAC,EAAE,aAAa,EAC7B,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAsCf;AAMD;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,mBAAmB,CAAC,CAiB9B;AAkJD,eAAO,MAAM,SAAS;;;;eA1VD,cAAc;;;CA6VlC,CAAC"}