@nahisaho/musubix-codegraph 2.3.2 → 2.3.3

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.
@@ -0,0 +1,441 @@
1
+ /**
2
+ * @nahisaho/musubix-codegraph - Git Operations
3
+ *
4
+ * Git operations wrapper using simple-git
5
+ *
6
+ * @packageDocumentation
7
+ * @module @nahisaho/musubix-codegraph/pr
8
+ *
9
+ * @see REQ-CG-PR-003 - Git Branch Creation
10
+ * @see REQ-CG-PR-004 - Auto Commit
11
+ * @see DES-CG-PR-004 - Class Design
12
+ */
13
+ import { execSync } from 'node:child_process';
14
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
15
+ import { join } from 'node:path';
16
+ /**
17
+ * Git operations wrapper
18
+ *
19
+ * Provides a safe interface for Git operations needed for PR creation.
20
+ * Uses child_process to interact with Git directly.
21
+ *
22
+ * @see DES-CG-PR-004
23
+ * @example
24
+ * ```typescript
25
+ * const git = new GitOperations('/path/to/repo');
26
+ * await git.createBranch('refactor/extract-interface');
27
+ * await git.commit('refactor(auth): extract IAuthService interface');
28
+ * await git.push();
29
+ * ```
30
+ */
31
+ export class GitOperations {
32
+ repoPath;
33
+ remote;
34
+ /**
35
+ * Create a new GitOperations instance
36
+ * @param options - Git operation options
37
+ */
38
+ constructor(options) {
39
+ this.repoPath = options.repoPath;
40
+ this.remote = options.remote ?? 'origin';
41
+ // Validate repository
42
+ if (!this.isGitRepository()) {
43
+ throw new Error(`Not a git repository: ${this.repoPath}`);
44
+ }
45
+ }
46
+ // ============================================================================
47
+ // Repository Information
48
+ // ============================================================================
49
+ /**
50
+ * Check if path is a Git repository
51
+ */
52
+ isGitRepository() {
53
+ try {
54
+ this.git(['rev-parse', '--git-dir']);
55
+ return true;
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
61
+ /**
62
+ * Get repository root path
63
+ */
64
+ getRepoRoot() {
65
+ return this.git(['rev-parse', '--show-toplevel']).trim();
66
+ }
67
+ /**
68
+ * Get current branch name
69
+ * @see REQ-CG-PR-003
70
+ */
71
+ getCurrentBranch() {
72
+ return this.git(['rev-parse', '--abbrev-ref', 'HEAD']).trim();
73
+ }
74
+ /**
75
+ * Get default branch name (main or master)
76
+ */
77
+ getDefaultBranch() {
78
+ try {
79
+ // Try to get from remote HEAD
80
+ const remoteHead = this.git(['symbolic-ref', `refs/remotes/${this.remote}/HEAD`]);
81
+ return remoteHead.replace(`refs/remotes/${this.remote}/`, '').trim();
82
+ }
83
+ catch {
84
+ // Fallback: check if main exists, otherwise master
85
+ try {
86
+ this.git(['rev-parse', '--verify', 'main']);
87
+ return 'main';
88
+ }
89
+ catch {
90
+ return 'master';
91
+ }
92
+ }
93
+ }
94
+ /**
95
+ * List all branches
96
+ */
97
+ listBranches() {
98
+ const output = this.git([
99
+ 'for-each-ref',
100
+ '--format=%(refname:short)|%(HEAD)|%(upstream:short)|%(objectname:short)',
101
+ 'refs/heads',
102
+ ]);
103
+ return output
104
+ .trim()
105
+ .split('\n')
106
+ .filter((line) => line.length > 0)
107
+ .map((line) => {
108
+ const [name, head, tracking, commit] = line.split('|');
109
+ return {
110
+ name,
111
+ current: head === '*',
112
+ tracking: tracking || undefined,
113
+ commit,
114
+ };
115
+ });
116
+ }
117
+ /**
118
+ * Check if branch exists
119
+ */
120
+ branchExists(branchName) {
121
+ try {
122
+ this.git(['rev-parse', '--verify', branchName]);
123
+ return true;
124
+ }
125
+ catch {
126
+ return false;
127
+ }
128
+ }
129
+ // ============================================================================
130
+ // Branch Operations
131
+ // ============================================================================
132
+ /**
133
+ * Create a new branch
134
+ * @see REQ-CG-PR-003
135
+ */
136
+ createBranch(branchName, baseBranch) {
137
+ const base = baseBranch ?? this.getCurrentBranch();
138
+ if (this.branchExists(branchName)) {
139
+ throw new Error(`Branch already exists: ${branchName}`);
140
+ }
141
+ this.git(['checkout', '-b', branchName, base]);
142
+ }
143
+ /**
144
+ * Checkout an existing branch
145
+ */
146
+ checkout(branchName) {
147
+ if (!this.branchExists(branchName)) {
148
+ throw new Error(`Branch does not exist: ${branchName}`);
149
+ }
150
+ this.git(['checkout', branchName]);
151
+ }
152
+ /**
153
+ * Delete a branch
154
+ */
155
+ deleteBranch(branchName, force = false) {
156
+ const flag = force ? '-D' : '-d';
157
+ this.git(['branch', flag, branchName]);
158
+ }
159
+ // ============================================================================
160
+ // Working Tree Operations
161
+ // ============================================================================
162
+ /**
163
+ * Check for uncommitted changes
164
+ */
165
+ hasUncommittedChanges() {
166
+ const status = this.git(['status', '--porcelain']);
167
+ return status.trim().length > 0;
168
+ }
169
+ /**
170
+ * Get list of modified files
171
+ */
172
+ getModifiedFiles() {
173
+ const status = this.git(['status', '--porcelain']);
174
+ return status
175
+ .trim()
176
+ .split('\n')
177
+ .filter((line) => line.length > 0)
178
+ .map((line) => line.slice(3).trim());
179
+ }
180
+ /**
181
+ * Stage files for commit
182
+ */
183
+ stageFiles(files) {
184
+ if (files.length === 0)
185
+ return;
186
+ this.git(['add', ...files]);
187
+ }
188
+ /**
189
+ * Stage all changes
190
+ */
191
+ stageAll() {
192
+ this.git(['add', '-A']);
193
+ }
194
+ /**
195
+ * Unstage files
196
+ */
197
+ unstageFiles(files) {
198
+ if (files.length === 0)
199
+ return;
200
+ this.git(['reset', 'HEAD', ...files]);
201
+ }
202
+ /**
203
+ * Discard changes in working tree
204
+ */
205
+ discardChanges(files) {
206
+ if (files.length === 0)
207
+ return;
208
+ this.git(['checkout', '--', ...files]);
209
+ }
210
+ /**
211
+ * Stash changes
212
+ */
213
+ stash(message) {
214
+ const args = ['stash', 'push'];
215
+ if (message) {
216
+ args.push('-m', message);
217
+ }
218
+ this.git(args);
219
+ }
220
+ /**
221
+ * Pop stash
222
+ */
223
+ stashPop() {
224
+ this.git(['stash', 'pop']);
225
+ }
226
+ // ============================================================================
227
+ // Commit Operations
228
+ // ============================================================================
229
+ /**
230
+ * Create a commit
231
+ * @see REQ-CG-PR-004
232
+ */
233
+ commit(message, options) {
234
+ const args = ['commit', '-m', message];
235
+ if (options?.allowEmpty) {
236
+ args.push('--allow-empty');
237
+ }
238
+ this.git(args);
239
+ // Get commit info
240
+ return this.getLastCommit();
241
+ }
242
+ /**
243
+ * Get last commit info
244
+ */
245
+ getLastCommit() {
246
+ const format = '%H|%s|%an|%ae|%aI';
247
+ const output = this.git(['log', '-1', `--format=${format}`]).trim();
248
+ const [hash, message, author, email, dateStr] = output.split('|');
249
+ return {
250
+ hash,
251
+ message,
252
+ author,
253
+ email,
254
+ date: new Date(dateStr),
255
+ };
256
+ }
257
+ /**
258
+ * Get commit history
259
+ */
260
+ getCommitHistory(count = 10) {
261
+ const format = '%H|%s|%an|%ae|%aI';
262
+ const output = this.git(['log', `-${count}`, `--format=${format}`]).trim();
263
+ return output
264
+ .split('\n')
265
+ .filter((line) => line.length > 0)
266
+ .map((line) => {
267
+ const [hash, message, author, email, dateStr] = line.split('|');
268
+ return {
269
+ hash,
270
+ message,
271
+ author,
272
+ email,
273
+ date: new Date(dateStr),
274
+ };
275
+ });
276
+ }
277
+ // ============================================================================
278
+ // Remote Operations
279
+ // ============================================================================
280
+ /**
281
+ * Push branch to remote
282
+ */
283
+ push(options) {
284
+ const args = ['push'];
285
+ if (options?.setUpstream) {
286
+ args.push('-u', this.remote, this.getCurrentBranch());
287
+ }
288
+ if (options?.force) {
289
+ args.push('--force');
290
+ }
291
+ this.git(args);
292
+ }
293
+ /**
294
+ * Fetch from remote
295
+ */
296
+ fetch(prune = false) {
297
+ const args = ['fetch', this.remote];
298
+ if (prune) {
299
+ args.push('--prune');
300
+ }
301
+ this.git(args);
302
+ }
303
+ /**
304
+ * Pull from remote
305
+ */
306
+ pull(rebase = false) {
307
+ const args = ['pull', this.remote, this.getCurrentBranch()];
308
+ if (rebase) {
309
+ args.push('--rebase');
310
+ }
311
+ this.git(args);
312
+ }
313
+ /**
314
+ * Get remote URL
315
+ */
316
+ getRemoteUrl() {
317
+ return this.git(['remote', 'get-url', this.remote]).trim();
318
+ }
319
+ /**
320
+ * Parse GitHub owner/repo from remote URL
321
+ */
322
+ parseRemoteUrl() {
323
+ const url = this.getRemoteUrl();
324
+ // SSH format: git@github.com:owner/repo.git
325
+ const sshMatch = url.match(/git@github\.com:([^/]+)\/([^/.]+)(\.git)?$/);
326
+ if (sshMatch) {
327
+ return { owner: sshMatch[1], repo: sshMatch[2] };
328
+ }
329
+ // HTTPS format: https://github.com/owner/repo.git
330
+ const httpsMatch = url.match(/https:\/\/github\.com\/([^/]+)\/([^/.]+)(\.git)?$/);
331
+ if (httpsMatch) {
332
+ return { owner: httpsMatch[1], repo: httpsMatch[2] };
333
+ }
334
+ return null;
335
+ }
336
+ // ============================================================================
337
+ // Diff Operations
338
+ // ============================================================================
339
+ /**
340
+ * Get diff for staged changes
341
+ */
342
+ getStagedDiff() {
343
+ return this.git(['diff', '--cached']);
344
+ }
345
+ /**
346
+ * Get diff for unstaged changes
347
+ */
348
+ getUnstagedDiff() {
349
+ return this.git(['diff']);
350
+ }
351
+ /**
352
+ * Get diff between branches
353
+ */
354
+ getDiffBetweenBranches(baseBranch, headBranch) {
355
+ const head = headBranch ?? this.getCurrentBranch();
356
+ return this.git(['diff', `${baseBranch}...${head}`]);
357
+ }
358
+ /**
359
+ * Get diff stats
360
+ */
361
+ getDiffStats(baseBranch) {
362
+ const base = baseBranch ?? this.getDefaultBranch();
363
+ const output = this.git(['diff', '--stat', `${base}...HEAD`]);
364
+ const match = output.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/);
365
+ if (!match) {
366
+ return { additions: 0, deletions: 0, files: 0 };
367
+ }
368
+ return {
369
+ files: parseInt(match[1], 10) || 0,
370
+ additions: parseInt(match[2], 10) || 0,
371
+ deletions: parseInt(match[3], 10) || 0,
372
+ };
373
+ }
374
+ // ============================================================================
375
+ // File Operations for Refactoring
376
+ // ============================================================================
377
+ /**
378
+ * Apply code changes to files
379
+ * @see REQ-CG-PR-002
380
+ */
381
+ applyCodeChanges(changes) {
382
+ const modifiedFiles = [];
383
+ for (const change of changes) {
384
+ const filePath = join(this.repoPath, change.filePath);
385
+ // Ensure file exists
386
+ if (!existsSync(filePath)) {
387
+ throw new Error(`File not found: ${change.filePath}`);
388
+ }
389
+ // Read file content
390
+ const content = readFileSync(filePath, 'utf-8');
391
+ const lines = content.split('\n');
392
+ // Validate line numbers
393
+ if (change.startLine < 1 || change.endLine > lines.length) {
394
+ throw new Error(`Invalid line range ${change.startLine}-${change.endLine} for file ${change.filePath} (has ${lines.length} lines)`);
395
+ }
396
+ // Apply change
397
+ const beforeLines = lines.slice(0, change.startLine - 1);
398
+ const afterLines = lines.slice(change.endLine);
399
+ const newLines = change.newCode.split('\n');
400
+ const newContent = [...beforeLines, ...newLines, ...afterLines].join('\n');
401
+ // Write back
402
+ writeFileSync(filePath, newContent, 'utf-8');
403
+ modifiedFiles.push(change.filePath);
404
+ }
405
+ return [...new Set(modifiedFiles)];
406
+ }
407
+ /**
408
+ * Revert changes to a file
409
+ */
410
+ revertFile(filePath) {
411
+ this.git(['checkout', 'HEAD', '--', filePath]);
412
+ }
413
+ // ============================================================================
414
+ // Private Helpers
415
+ // ============================================================================
416
+ /**
417
+ * Execute a git command synchronously
418
+ */
419
+ git(args) {
420
+ try {
421
+ return execSync(`git ${args.join(' ')}`, {
422
+ cwd: this.repoPath,
423
+ encoding: 'utf-8',
424
+ stdio: ['pipe', 'pipe', 'pipe'],
425
+ });
426
+ }
427
+ catch (error) {
428
+ if (error instanceof Error && 'stderr' in error) {
429
+ throw new Error(`Git command failed: git ${args.join(' ')}\n${error.stderr}`);
430
+ }
431
+ throw error;
432
+ }
433
+ }
434
+ }
435
+ /**
436
+ * Create a GitOperations instance
437
+ */
438
+ export function createGitOperations(repoPath, remote) {
439
+ return new GitOperations({ repoPath, remote });
440
+ }
441
+ //# sourceMappingURL=git-operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-operations.js","sourceRoot":"","sources":["../../src/pr/git-operations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * @nahisaho/musubix-codegraph - GitHub Adapter
3
+ *
4
+ * GitHub API integration using Octokit or gh CLI fallback
5
+ *
6
+ * @packageDocumentation
7
+ * @module @nahisaho/musubix-codegraph/pr
8
+ *
9
+ * @see REQ-CG-PR-001 - GitHub Authentication
10
+ * @see REQ-CG-PR-005 - GitHub PR Creation
11
+ * @see DES-CG-PR-004 - Class Design
12
+ */
13
+ import type { GitHubConfig, GitHubAuthMethod, GitHubAuthResult, PRInfo } from './types.js';
14
+ /**
15
+ * Pull Request creation options for GitHub API
16
+ */
17
+ export interface CreatePROptions {
18
+ /** PR title */
19
+ title: string;
20
+ /** PR body (Markdown) */
21
+ body: string;
22
+ /** Head branch (the branch with changes) */
23
+ head: string;
24
+ /** Base branch (the branch to merge into) */
25
+ base: string;
26
+ /** Create as draft PR */
27
+ draft?: boolean;
28
+ /** Maintainer can modify */
29
+ maintainerCanModify?: boolean;
30
+ }
31
+ /**
32
+ * Options for updating a PR
33
+ */
34
+ export interface UpdatePROptions {
35
+ /** PR number */
36
+ number: number;
37
+ /** New title */
38
+ title?: string;
39
+ /** New body */
40
+ body?: string;
41
+ /** New state */
42
+ state?: 'open' | 'closed';
43
+ }
44
+ /**
45
+ * PR label
46
+ */
47
+ export interface PRLabel {
48
+ name: string;
49
+ color?: string;
50
+ description?: string;
51
+ }
52
+ /**
53
+ * GitHub Adapter
54
+ *
55
+ * Provides a unified interface for GitHub operations.
56
+ * Supports both direct API access (via GITHUB_TOKEN) and gh CLI fallback.
57
+ *
58
+ * @see DES-CG-PR-004
59
+ * @example
60
+ * ```typescript
61
+ * const github = new GitHubAdapter({ owner: 'user', repo: 'project' });
62
+ * await github.authenticate();
63
+ * const pr = await github.createPullRequest({
64
+ * title: 'refactor: extract interface',
65
+ * body: '...',
66
+ * head: 'refactor/extract-interface',
67
+ * base: 'main'
68
+ * });
69
+ * ```
70
+ */
71
+ export declare class GitHubAdapter {
72
+ private readonly config;
73
+ private authMethod;
74
+ private authenticated;
75
+ private username?;
76
+ /**
77
+ * Create a new GitHubAdapter
78
+ * @param config - GitHub configuration
79
+ */
80
+ constructor(config: GitHubConfig);
81
+ /**
82
+ * Authenticate with GitHub
83
+ * @see REQ-CG-PR-001
84
+ */
85
+ authenticate(): Promise<GitHubAuthResult>;
86
+ /**
87
+ * Check if authenticated
88
+ */
89
+ isAuthenticated(): boolean;
90
+ /**
91
+ * Get authentication method
92
+ */
93
+ getAuthMethod(): GitHubAuthMethod;
94
+ /**
95
+ * Get authenticated username
96
+ */
97
+ getUsername(): string | undefined;
98
+ /**
99
+ * Validate a GitHub token
100
+ */
101
+ private validateToken;
102
+ /**
103
+ * Check if gh CLI is available
104
+ */
105
+ private isGhCliAvailable;
106
+ /**
107
+ * Authenticate using gh CLI
108
+ */
109
+ private authenticateWithGhCli;
110
+ /**
111
+ * Create a pull request
112
+ * @see REQ-CG-PR-005
113
+ */
114
+ createPullRequest(options: CreatePROptions): Promise<PRInfo>;
115
+ /**
116
+ * Create PR using GitHub API
117
+ */
118
+ private createPRWithApi;
119
+ /**
120
+ * Create PR using gh CLI
121
+ */
122
+ private createPRWithGhCli;
123
+ /**
124
+ * Get PR information
125
+ */
126
+ getPullRequest(prNumber: number): Promise<PRInfo>;
127
+ /**
128
+ * Get PR using API
129
+ */
130
+ private getPRWithApi;
131
+ /**
132
+ * Get PR using gh CLI
133
+ */
134
+ private getPRWithGhCli;
135
+ /**
136
+ * Add labels to PR
137
+ */
138
+ addLabels(prNumber: number, labels: string[]): Promise<void>;
139
+ /**
140
+ * Add reviewers to PR
141
+ */
142
+ addReviewers(prNumber: number, reviewers: string[]): Promise<void>;
143
+ /**
144
+ * Add assignees to PR
145
+ */
146
+ addAssignees(prNumber: number, assignees: string[]): Promise<void>;
147
+ /**
148
+ * Get repository information
149
+ */
150
+ getRepository(): Promise<{
151
+ defaultBranch: string;
152
+ private: boolean;
153
+ }>;
154
+ /**
155
+ * Ensure authenticated before operations
156
+ */
157
+ private ensureAuthenticated;
158
+ }
159
+ /**
160
+ * Create a GitHubAdapter instance
161
+ */
162
+ export declare function createGitHubAdapter(owner: string, repo: string, token?: string): GitHubAdapter;
163
+ //# sourceMappingURL=github-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-adapter.d.ts","sourceRoot":"","sources":["../../src/pr/github-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,EACP,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,eAAe;IACf,KAAK,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4BAA4B;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,gBAAgB;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,CAAS;IAE1B;;;OAGG;gBACS,MAAM,EAAE,YAAY;IAWhC;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAwC/C;;OAEG;IACH,eAAe,IAAI,OAAO;IAI1B;;OAEG;IACH,aAAa,IAAI,gBAAgB;IAIjC;;OAEG;IACH,WAAW,IAAI,MAAM,GAAG,SAAS;IAIjC;;OAEG;YACW,aAAa;IAiC3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;YACW,qBAAqB;IAgCnC;;;OAGG;IACG,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAUlE;;OAEG;YACW,eAAe;IAqD7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA4CzB;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUvD;;OAEG;YACW,YAAY;IA2C1B;;OAEG;IACH,OAAO,CAAC,cAAc;IAiCtB;;OAEG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BlE;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BxE;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCxE;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAqD3E;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAK5B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,GACb,aAAa,CAEf"}