@coralai/sps-cli 0.6.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 (145) hide show
  1. package/dist/commands/cardAdd.d.ts +2 -0
  2. package/dist/commands/cardAdd.d.ts.map +1 -0
  3. package/dist/commands/cardAdd.js +65 -0
  4. package/dist/commands/cardAdd.js.map +1 -0
  5. package/dist/commands/doctor.d.ts +9 -0
  6. package/dist/commands/doctor.d.ts.map +1 -0
  7. package/dist/commands/doctor.js +264 -0
  8. package/dist/commands/doctor.js.map +1 -0
  9. package/dist/commands/monitorTick.d.ts +2 -0
  10. package/dist/commands/monitorTick.d.ts.map +1 -0
  11. package/dist/commands/monitorTick.js +47 -0
  12. package/dist/commands/monitorTick.js.map +1 -0
  13. package/dist/commands/pipelineTick.d.ts +2 -0
  14. package/dist/commands/pipelineTick.d.ts.map +1 -0
  15. package/dist/commands/pipelineTick.js +44 -0
  16. package/dist/commands/pipelineTick.js.map +1 -0
  17. package/dist/commands/pmCommand.d.ts +2 -0
  18. package/dist/commands/pmCommand.d.ts.map +1 -0
  19. package/dist/commands/pmCommand.js +159 -0
  20. package/dist/commands/pmCommand.js.map +1 -0
  21. package/dist/commands/projectInit.d.ts +2 -0
  22. package/dist/commands/projectInit.d.ts.map +1 -0
  23. package/dist/commands/projectInit.js +75 -0
  24. package/dist/commands/projectInit.js.map +1 -0
  25. package/dist/commands/qaTick.d.ts +2 -0
  26. package/dist/commands/qaTick.d.ts.map +1 -0
  27. package/dist/commands/qaTick.js +43 -0
  28. package/dist/commands/qaTick.js.map +1 -0
  29. package/dist/commands/schedulerTick.d.ts +2 -0
  30. package/dist/commands/schedulerTick.d.ts.map +1 -0
  31. package/dist/commands/schedulerTick.js +45 -0
  32. package/dist/commands/schedulerTick.js.map +1 -0
  33. package/dist/commands/tick.d.ts +14 -0
  34. package/dist/commands/tick.d.ts.map +1 -0
  35. package/dist/commands/tick.js +251 -0
  36. package/dist/commands/tick.js.map +1 -0
  37. package/dist/commands/workerLaunch.d.ts +2 -0
  38. package/dist/commands/workerLaunch.d.ts.map +1 -0
  39. package/dist/commands/workerLaunch.js +56 -0
  40. package/dist/commands/workerLaunch.js.map +1 -0
  41. package/dist/core/config.d.ts +38 -0
  42. package/dist/core/config.d.ts.map +1 -0
  43. package/dist/core/config.js +131 -0
  44. package/dist/core/config.js.map +1 -0
  45. package/dist/core/context.d.ts +23 -0
  46. package/dist/core/context.d.ts.map +1 -0
  47. package/dist/core/context.js +28 -0
  48. package/dist/core/context.js.map +1 -0
  49. package/dist/core/lock.d.ts +14 -0
  50. package/dist/core/lock.d.ts.map +1 -0
  51. package/dist/core/lock.js +65 -0
  52. package/dist/core/lock.js.map +1 -0
  53. package/dist/core/logger.d.ts +24 -0
  54. package/dist/core/logger.d.ts.map +1 -0
  55. package/dist/core/logger.js +62 -0
  56. package/dist/core/logger.js.map +1 -0
  57. package/dist/core/paths.d.ts +27 -0
  58. package/dist/core/paths.d.ts.map +1 -0
  59. package/dist/core/paths.js +29 -0
  60. package/dist/core/paths.js.map +1 -0
  61. package/dist/core/queue.d.ts +14 -0
  62. package/dist/core/queue.d.ts.map +1 -0
  63. package/dist/core/queue.js +38 -0
  64. package/dist/core/queue.js.map +1 -0
  65. package/dist/core/state.d.ts +32 -0
  66. package/dist/core/state.d.ts.map +1 -0
  67. package/dist/core/state.js +52 -0
  68. package/dist/core/state.js.map +1 -0
  69. package/dist/engines/CloseoutEngine.d.ts +60 -0
  70. package/dist/engines/CloseoutEngine.d.ts.map +1 -0
  71. package/dist/engines/CloseoutEngine.js +596 -0
  72. package/dist/engines/CloseoutEngine.js.map +1 -0
  73. package/dist/engines/ExecutionEngine.d.ts +65 -0
  74. package/dist/engines/ExecutionEngine.d.ts.map +1 -0
  75. package/dist/engines/ExecutionEngine.js +603 -0
  76. package/dist/engines/ExecutionEngine.js.map +1 -0
  77. package/dist/engines/MonitorEngine.d.ts +39 -0
  78. package/dist/engines/MonitorEngine.d.ts.map +1 -0
  79. package/dist/engines/MonitorEngine.js +473 -0
  80. package/dist/engines/MonitorEngine.js.map +1 -0
  81. package/dist/engines/SchedulerEngine.d.ts +24 -0
  82. package/dist/engines/SchedulerEngine.d.ts.map +1 -0
  83. package/dist/engines/SchedulerEngine.js +195 -0
  84. package/dist/engines/SchedulerEngine.js.map +1 -0
  85. package/dist/interfaces/HookProvider.d.ts +9 -0
  86. package/dist/interfaces/HookProvider.d.ts.map +1 -0
  87. package/dist/interfaces/HookProvider.js +2 -0
  88. package/dist/interfaces/HookProvider.js.map +1 -0
  89. package/dist/interfaces/Notifier.d.ts +11 -0
  90. package/dist/interfaces/Notifier.d.ts.map +1 -0
  91. package/dist/interfaces/Notifier.js +2 -0
  92. package/dist/interfaces/Notifier.js.map +1 -0
  93. package/dist/interfaces/RepoBackend.d.ts +23 -0
  94. package/dist/interfaces/RepoBackend.d.ts.map +1 -0
  95. package/dist/interfaces/RepoBackend.js +2 -0
  96. package/dist/interfaces/RepoBackend.js.map +1 -0
  97. package/dist/interfaces/TaskBackend.d.ts +24 -0
  98. package/dist/interfaces/TaskBackend.d.ts.map +1 -0
  99. package/dist/interfaces/TaskBackend.js +2 -0
  100. package/dist/interfaces/TaskBackend.js.map +1 -0
  101. package/dist/interfaces/WorkerProvider.d.ts +23 -0
  102. package/dist/interfaces/WorkerProvider.d.ts.map +1 -0
  103. package/dist/interfaces/WorkerProvider.js +2 -0
  104. package/dist/interfaces/WorkerProvider.js.map +1 -0
  105. package/dist/main.d.ts +3 -0
  106. package/dist/main.d.ts.map +1 -0
  107. package/dist/main.js +226 -0
  108. package/dist/main.js.map +1 -0
  109. package/dist/models/types.d.ts +68 -0
  110. package/dist/models/types.d.ts.map +1 -0
  111. package/dist/models/types.js +2 -0
  112. package/dist/models/types.js.map +1 -0
  113. package/dist/providers/ClaudeWorkerProvider.d.ts +84 -0
  114. package/dist/providers/ClaudeWorkerProvider.d.ts.map +1 -0
  115. package/dist/providers/ClaudeWorkerProvider.js +293 -0
  116. package/dist/providers/ClaudeWorkerProvider.js.map +1 -0
  117. package/dist/providers/CodexWorkerProvider.d.ts +50 -0
  118. package/dist/providers/CodexWorkerProvider.d.ts.map +1 -0
  119. package/dist/providers/CodexWorkerProvider.js +275 -0
  120. package/dist/providers/CodexWorkerProvider.js.map +1 -0
  121. package/dist/providers/GitLabRepoBackend.d.ts +42 -0
  122. package/dist/providers/GitLabRepoBackend.d.ts.map +1 -0
  123. package/dist/providers/GitLabRepoBackend.js +280 -0
  124. package/dist/providers/GitLabRepoBackend.js.map +1 -0
  125. package/dist/providers/MarkdownTaskBackend.d.ts +88 -0
  126. package/dist/providers/MarkdownTaskBackend.d.ts.map +1 -0
  127. package/dist/providers/MarkdownTaskBackend.js +414 -0
  128. package/dist/providers/MarkdownTaskBackend.js.map +1 -0
  129. package/dist/providers/MatrixNotifier.d.ts +30 -0
  130. package/dist/providers/MatrixNotifier.d.ts.map +1 -0
  131. package/dist/providers/MatrixNotifier.js +82 -0
  132. package/dist/providers/MatrixNotifier.js.map +1 -0
  133. package/dist/providers/PlaneTaskBackend.d.ts +86 -0
  134. package/dist/providers/PlaneTaskBackend.d.ts.map +1 -0
  135. package/dist/providers/PlaneTaskBackend.js +409 -0
  136. package/dist/providers/PlaneTaskBackend.js.map +1 -0
  137. package/dist/providers/TrelloTaskBackend.d.ts +53 -0
  138. package/dist/providers/TrelloTaskBackend.d.ts.map +1 -0
  139. package/dist/providers/TrelloTaskBackend.js +300 -0
  140. package/dist/providers/TrelloTaskBackend.js.map +1 -0
  141. package/dist/providers/registry.d.ts +10 -0
  142. package/dist/providers/registry.d.ts.map +1 -0
  143. package/dist/providers/registry.js +29 -0
  144. package/dist/providers/registry.js.map +1 -0
  145. package/package.json +36 -0
@@ -0,0 +1,275 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { existsSync, readFileSync } from 'node:fs';
3
+ /**
4
+ * Codex CLI patterns (differs from Claude):
5
+ *
6
+ * Ready prompt: › <placeholder>
7
+ * gpt-5.3-codex default · ...
8
+ *
9
+ * Completion: returns to › prompt after task
10
+ *
11
+ * Update blocker: ✨ Update available!
12
+ * › 1. Update now
13
+ * 2. Skip
14
+ * 3. Skip until next version
15
+ * Press enter to continue
16
+ *
17
+ * Confirmation: (none with --dangerously-bypass-approvals-and-sandbox)
18
+ *
19
+ * Exit command: /quit (Claude uses /exit)
20
+ */
21
+ /** Completion keywords in codex pane text. */
22
+ const COMPLETION_KEYWORDS = /\b(done|completed|finished|Next step:|committed|pushed|MR created|merge request)\b/i;
23
+ /** Codex ready prompt: › at start of line + model info line */
24
+ const CODEX_READY = /›\s.*$/m;
25
+ const CODEX_MODEL_LINE = /codex.*default.*·/i;
26
+ /** Codex update blocker pattern */
27
+ const CODEX_UPDATE_PROMPT = /Update available|Skip until next version/i;
28
+ /**
29
+ * Run a tmux command. Returns null on failure.
30
+ */
31
+ function tmux(args) {
32
+ try {
33
+ return execFileSync('tmux', args, {
34
+ encoding: 'utf-8',
35
+ timeout: 10_000,
36
+ stdio: ['ignore', 'pipe', 'pipe'],
37
+ });
38
+ }
39
+ catch (err) {
40
+ const stderr = err.stderr ?? '';
41
+ if (stderr.includes('server exited unexpectedly') || stderr.includes('no server running')) {
42
+ try {
43
+ const uid = process.getuid?.() ?? 1000;
44
+ const { rmSync } = require('node:fs');
45
+ rmSync(`/tmp/tmux-${uid}`, { recursive: true, force: true });
46
+ process.stderr.write('[codex-worker] Cleaned stale tmux socket, retrying\n');
47
+ return execFileSync('tmux', args, {
48
+ encoding: 'utf-8',
49
+ timeout: 10_000,
50
+ stdio: ['ignore', 'pipe', 'pipe'],
51
+ });
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ return null;
58
+ }
59
+ }
60
+ function sessionExists(session) {
61
+ return tmux(['has-session', '-t', session]) !== null;
62
+ }
63
+ function capturePaneText(session, lines) {
64
+ return tmux(['capture-pane', '-t', session, '-p', '-S', `-${lines}`]) ?? '';
65
+ }
66
+ export class CodexWorkerProvider {
67
+ config;
68
+ constructor(config) {
69
+ this.config = config;
70
+ }
71
+ async prepareEnv(worktree, _seq) {
72
+ if (!existsSync(worktree)) {
73
+ throw new Error(`Worktree directory does not exist: ${worktree}`);
74
+ }
75
+ try {
76
+ execFileSync('git', ['-C', worktree, 'rev-parse', '--is-inside-work-tree'], {
77
+ encoding: 'utf-8', timeout: 5_000, stdio: ['ignore', 'pipe', 'pipe'],
78
+ });
79
+ }
80
+ catch {
81
+ throw new Error(`Directory is not a git worktree: ${worktree}`);
82
+ }
83
+ }
84
+ /**
85
+ * Launch Codex in a tmux session (interactive mode).
86
+ * Handles session reuse and update prompt auto-skip.
87
+ */
88
+ async launch(session, worktree) {
89
+ const codexCmd = 'codex --sandbox danger-full-access -a never --no-alt-screen';
90
+ if (sessionExists(session)) {
91
+ const pane = capturePaneText(session, 10);
92
+ const codexAlive = CODEX_READY.test(pane) && CODEX_MODEL_LINE.test(pane);
93
+ if (codexAlive) {
94
+ // Codex running — clear conversation + switch worktree
95
+ process.stderr.write(`[codex-worker] Reusing live Codex session ${session}\n`);
96
+ tmux(['send-keys', '-t', session, '/clear', 'Enter']);
97
+ await this.sleep(1_000);
98
+ // Codex doesn't support cd mid-session, but we can try
99
+ tmux(['send-keys', '-t', session, `/cd ${worktree}`, 'Enter']);
100
+ await this.sleep(500);
101
+ return;
102
+ }
103
+ // Session exists but Codex not running
104
+ process.stderr.write(`[codex-worker] Reusing tmux session ${session}\n`);
105
+ tmux(['send-keys', '-t', session, `cd ${worktree}`, 'Enter']);
106
+ await this.sleep(500);
107
+ tmux(['send-keys', '-t', session, codexCmd, 'Enter']);
108
+ return;
109
+ }
110
+ // New session
111
+ const result = tmux(['new-session', '-d', '-s', session, '-c', worktree]);
112
+ if (result === null && !sessionExists(session)) {
113
+ throw new Error(`Failed to create tmux session: ${session}`);
114
+ }
115
+ tmux(['send-keys', '-t', session, codexCmd, 'Enter']);
116
+ }
117
+ /**
118
+ * Wait for Codex to be ready.
119
+ * Must handle the update prompt blocker (auto-skip).
120
+ */
121
+ async waitReady(session, timeoutMs = 90_000) {
122
+ const pollInterval = 3_000;
123
+ const deadline = Date.now() + timeoutMs;
124
+ let updateSkipped = false;
125
+ // Codex is slower to start than Claude — wait longer before first check
126
+ await this.sleep(5_000);
127
+ while (Date.now() < deadline) {
128
+ const text = capturePaneText(session, 30);
129
+ // Handle update prompt — send Enter to dismiss, then skip
130
+ if (!updateSkipped && CODEX_UPDATE_PROMPT.test(text)) {
131
+ process.stderr.write('[codex-worker] Detected update prompt, skipping\n');
132
+ // If showing numbered options (1/2/3), select 3 "Skip until next version"
133
+ if (/1\. Update now/i.test(text)) {
134
+ tmux(['send-keys', '-t', session, 'Down']);
135
+ await this.sleep(300);
136
+ tmux(['send-keys', '-t', session, 'Down']);
137
+ await this.sleep(300);
138
+ }
139
+ tmux(['send-keys', '-t', session, 'Enter']);
140
+ updateSkipped = true;
141
+ await this.sleep(5_000);
142
+ continue;
143
+ }
144
+ // Handle "Press enter to continue" after update banner
145
+ if (/Press enter to continue/i.test(text)) {
146
+ tmux(['send-keys', '-t', session, 'Enter']);
147
+ await this.sleep(3_000);
148
+ continue;
149
+ }
150
+ // Check if Codex is ready: › prompt + model info line
151
+ if (CODEX_MODEL_LINE.test(text) && CODEX_READY.test(text)) {
152
+ process.stderr.write('[codex-worker] Codex ready\n');
153
+ return true;
154
+ }
155
+ // Also match "OpenAI Codex" banner + › prompt
156
+ if (/OpenAI Codex/i.test(text) && /›/m.test(text)) {
157
+ process.stderr.write('[codex-worker] Codex ready (banner match)\n');
158
+ return true;
159
+ }
160
+ await this.sleep(pollInterval);
161
+ }
162
+ process.stderr.write(`[codex-worker] waitReady timed out after ${timeoutMs}ms\n`);
163
+ return false;
164
+ }
165
+ /**
166
+ * Send task prompt to Codex via tmux paste-buffer.
167
+ */
168
+ async sendTask(session, promptFile) {
169
+ if (!existsSync(promptFile)) {
170
+ throw new Error(`Prompt file does not exist: ${promptFile}`);
171
+ }
172
+ const content = readFileSync(promptFile, 'utf-8').trim();
173
+ const bufferFile = `/tmp/sps-task-${Date.now()}.txt`;
174
+ const { writeFileSync: writeTmp, unlinkSync } = await import('node:fs');
175
+ writeTmp(bufferFile, content);
176
+ tmux(['load-buffer', bufferFile]);
177
+ tmux(['paste-buffer', '-t', session]);
178
+ try {
179
+ unlinkSync(bufferFile);
180
+ }
181
+ catch { /* cleanup */ }
182
+ await this.sleep(500);
183
+ tmux(['send-keys', '-t', session, 'Enter']);
184
+ }
185
+ async inspect(session) {
186
+ const alive = sessionExists(session);
187
+ const paneText = alive ? capturePaneText(session, 50) : '';
188
+ return { alive, paneText };
189
+ }
190
+ /**
191
+ * Codex with --dangerously-bypass-approvals-and-sandbox doesn't need confirmation.
192
+ * But if run without that flag, it may show approval prompts.
193
+ * For now, always return not waiting since we use bypass mode.
194
+ */
195
+ async detectWaiting(session) {
196
+ // Codex in bypass mode doesn't have confirmation prompts
197
+ // But check for any "Press enter" or similar blockers
198
+ const pane = capturePaneText(session, 15);
199
+ // Update prompt blocker
200
+ if (CODEX_UPDATE_PROMPT.test(pane)) {
201
+ return { waiting: true, destructive: false, prompt: 'Codex update prompt' };
202
+ }
203
+ return { waiting: false, destructive: false, prompt: '' };
204
+ }
205
+ /**
206
+ * Detect completion by checking if Codex returned to › prompt after working.
207
+ */
208
+ async detectCompleted(session, logDir, _branch) {
209
+ // Priority 1: task_completed marker file (same as Claude)
210
+ const markerPath = `${logDir}/task_completed`;
211
+ if (existsSync(markerPath)) {
212
+ return 'COMPLETED';
213
+ }
214
+ // Priority 2: check for update prompt (needs auto-skip, not completion)
215
+ const pane = capturePaneText(session, 20);
216
+ if (CODEX_UPDATE_PROMPT.test(pane)) {
217
+ return 'NEEDS_INPUT'; // will trigger auto-confirm to skip update
218
+ }
219
+ // Priority 3: completion keywords + back at › prompt
220
+ if (COMPLETION_KEYWORDS.test(pane) && CODEX_READY.test(pane) && CODEX_MODEL_LINE.test(pane)) {
221
+ return 'COMPLETED';
222
+ }
223
+ // Priority 4: session alive
224
+ if (sessionExists(session)) {
225
+ return 'ALIVE';
226
+ }
227
+ return 'DEAD';
228
+ }
229
+ async detectBlocked(session) {
230
+ const pane = capturePaneText(session, 30);
231
+ return /(error|fatal|rate.?limit|quota exceeded)/i.test(pane);
232
+ }
233
+ async sendFix(session, fixPrompt) {
234
+ const escaped = fixPrompt.replace(/'/g, "'\\''");
235
+ tmux(['send-keys', '-t', session, escaped, 'Enter']);
236
+ }
237
+ async resolveConflict(session, worktree, branch) {
238
+ const instruction = [
239
+ `There is a merge conflict on branch ${branch}.`,
240
+ `Working directory: ${worktree}`,
241
+ 'Please resolve the conflict:',
242
+ `1. Run: git fetch origin && git rebase origin/${this.config.GITLAB_MERGE_BRANCH}`,
243
+ '2. Resolve any conflicts in the affected files',
244
+ '3. Run: git add . && git rebase --continue',
245
+ '4. Run: git push --force-with-lease',
246
+ ].join('\n');
247
+ tmux(['send-keys', '-t', session, instruction, 'Enter']);
248
+ }
249
+ /**
250
+ * Stop Codex. Uses /quit (Codex's exit command, not /exit like Claude).
251
+ */
252
+ async stop(session) {
253
+ if (!sessionExists(session))
254
+ return;
255
+ if (this.config.WORKER_SESSION_REUSE) {
256
+ // Keep session, just quit Codex
257
+ tmux(['send-keys', '-t', session, '/quit', 'Enter']);
258
+ return;
259
+ }
260
+ tmux(['send-keys', '-t', session, '/quit', 'Enter']);
261
+ for (let i = 0; i < 5; i++) {
262
+ await this.sleep(1_000);
263
+ if (!sessionExists(session))
264
+ return;
265
+ }
266
+ tmux(['kill-session', '-t', session]);
267
+ }
268
+ async collectSummary(session) {
269
+ return capturePaneText(session, 100);
270
+ }
271
+ sleep(ms) {
272
+ return new Promise((resolve) => setTimeout(resolve, ms));
273
+ }
274
+ }
275
+ //# sourceMappingURL=CodexWorkerProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodexWorkerProvider.js","sourceRoot":"","sources":["../../src/providers/CodexWorkerProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { ProjectConfig } from '../core/config.js';
2
+ import type { RepoBackend } from '../interfaces/RepoBackend.js';
3
+ import type { MrStatus } from '../models/types.js';
4
+ /**
5
+ * GitLab-backed implementation of RepoBackend.
6
+ * Local git operations via execFileSync, remote operations via GitLab REST API.
7
+ */
8
+ export declare class GitLabRepoBackend implements RepoBackend {
9
+ private readonly gitlabUrl;
10
+ private readonly projectId;
11
+ private readonly token;
12
+ private readonly apiBase;
13
+ private readonly mergeBranch;
14
+ constructor(config: ProjectConfig);
15
+ private git;
16
+ private apiGet;
17
+ private apiPost;
18
+ private apiPut;
19
+ ensureCleanBase(repoDir: string, baseBranch: string): Promise<void>;
20
+ ensureBranch(repoDir: string, branchName: string, baseBranch: string): Promise<void>;
21
+ ensureWorktree(repoDir: string, branchName: string, worktreePath: string): Promise<void>;
22
+ commit(worktree: string, message: string): Promise<void>;
23
+ push(worktree: string, branch: string, force?: boolean): Promise<void>;
24
+ rebase(worktree: string, baseBranch: string): Promise<{
25
+ success: boolean;
26
+ conflictFiles?: string[];
27
+ }>;
28
+ createOrUpdateMr(branch: string, title: string, description: string): Promise<{
29
+ url: string;
30
+ iid: number;
31
+ }>;
32
+ getMrStatus(branch: string): Promise<MrStatus>;
33
+ mergeMr(iid: number): Promise<{
34
+ merged: boolean;
35
+ error?: string;
36
+ }>;
37
+ detectMerged(branch: string): Promise<boolean>;
38
+ private mapMrState;
39
+ private mapCiStatus;
40
+ private mapMergeStatus;
41
+ }
42
+ //# sourceMappingURL=GitLabRepoBackend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitLabRepoBackend.d.ts","sourceRoot":"","sources":["../../src/providers/GitLabRepoBackend.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,MAAM,EAAE,aAAa;IAYjC,OAAO,CAAC,GAAG;YAqBG,MAAM;YAiBN,OAAO;YAgBP,MAAM;IAoBd,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnE,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BpF,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASxF,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAaxD,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IA2BrG,gBAAgB,CACpB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAkClC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAoC9C,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAkBlE,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBpD,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,cAAc;CAQvB"}
@@ -0,0 +1,280 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ /**
4
+ * GitLab-backed implementation of RepoBackend.
5
+ * Local git operations via execFileSync, remote operations via GitLab REST API.
6
+ */
7
+ export class GitLabRepoBackend {
8
+ gitlabUrl;
9
+ projectId;
10
+ token;
11
+ apiBase;
12
+ mergeBranch;
13
+ constructor(config) {
14
+ this.gitlabUrl = config.raw.GITLAB_URL || 'https://gitlab.com';
15
+ this.projectId = config.GITLAB_PROJECT_ID;
16
+ this.token = config.raw.GITLAB_TOKEN || '';
17
+ this.apiBase = `${this.gitlabUrl}/api/v4/projects/${encodeURIComponent(this.projectId)}`;
18
+ this.mergeBranch = config.GITLAB_MERGE_BRANCH;
19
+ }
20
+ // ---------------------------------------------------------------------------
21
+ // Git helpers
22
+ // ---------------------------------------------------------------------------
23
+ git(args, cwd) {
24
+ try {
25
+ return execFileSync('git', args, {
26
+ cwd,
27
+ encoding: 'utf-8',
28
+ stdio: ['pipe', 'pipe', 'pipe'],
29
+ }).trim();
30
+ }
31
+ catch (err) {
32
+ const e = err;
33
+ const stderr = typeof e.stderr === 'string' ? e.stderr.trim() : '';
34
+ const code = e.status ?? 1;
35
+ throw new Error(`git ${args.join(' ')} failed (exit ${code}) in ${cwd}: ${stderr}`);
36
+ }
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // API helpers
40
+ // ---------------------------------------------------------------------------
41
+ async apiGet(path, query) {
42
+ const url = new URL(`${this.apiBase}${path}`);
43
+ if (query) {
44
+ for (const [k, v] of Object.entries(query)) {
45
+ url.searchParams.set(k, v);
46
+ }
47
+ }
48
+ const res = await fetch(url.toString(), {
49
+ headers: { 'PRIVATE-TOKEN': this.token },
50
+ });
51
+ if (!res.ok) {
52
+ const body = await res.text();
53
+ throw new Error(`GitLab GET ${path} returned ${res.status}: ${body}`);
54
+ }
55
+ return (await res.json());
56
+ }
57
+ async apiPost(path, body) {
58
+ const res = await fetch(`${this.apiBase}${path}`, {
59
+ method: 'POST',
60
+ headers: {
61
+ 'PRIVATE-TOKEN': this.token,
62
+ 'Content-Type': 'application/json',
63
+ },
64
+ body: JSON.stringify(body),
65
+ });
66
+ if (!res.ok) {
67
+ const text = await res.text();
68
+ throw new Error(`GitLab POST ${path} returned ${res.status}: ${text}`);
69
+ }
70
+ return (await res.json());
71
+ }
72
+ async apiPut(path, body) {
73
+ const res = await fetch(`${this.apiBase}${path}`, {
74
+ method: 'PUT',
75
+ headers: {
76
+ 'PRIVATE-TOKEN': this.token,
77
+ 'Content-Type': 'application/json',
78
+ },
79
+ body: JSON.stringify(body),
80
+ });
81
+ if (!res.ok) {
82
+ const text = await res.text();
83
+ throw new Error(`GitLab PUT ${path} returned ${res.status}: ${text}`);
84
+ }
85
+ return (await res.json());
86
+ }
87
+ // ---------------------------------------------------------------------------
88
+ // Local git operations
89
+ // ---------------------------------------------------------------------------
90
+ async ensureCleanBase(repoDir, baseBranch) {
91
+ this.git(['fetch', 'origin'], repoDir);
92
+ this.git(['checkout', baseBranch], repoDir);
93
+ this.git(['pull', 'origin', baseBranch], repoDir);
94
+ }
95
+ async ensureBranch(repoDir, branchName, baseBranch) {
96
+ // Ensure we're on base branch first (avoid branch-in-use conflicts with worktrees)
97
+ this.git(['fetch', 'origin'], repoDir);
98
+ try {
99
+ this.git(['checkout', baseBranch], repoDir);
100
+ }
101
+ catch {
102
+ // May fail if baseBranch doesn't exist locally yet
103
+ this.git(['checkout', '-b', baseBranch, `origin/${baseBranch}`], repoDir);
104
+ }
105
+ // Check if branch already exists locally or remotely
106
+ try {
107
+ this.git(['rev-parse', '--verify', branchName], repoDir);
108
+ // Branch exists locally — nothing more to do (worktree will check it out)
109
+ }
110
+ catch {
111
+ // Check remote
112
+ try {
113
+ this.git(['rev-parse', '--verify', `origin/${branchName}`], repoDir);
114
+ // Exists on remote — create local tracking branch (don't checkout)
115
+ this.git(['branch', branchName, `origin/${branchName}`], repoDir);
116
+ }
117
+ catch {
118
+ // Does not exist anywhere — create from base (don't checkout)
119
+ this.git(['branch', branchName, `origin/${baseBranch}`], repoDir);
120
+ }
121
+ }
122
+ }
123
+ async ensureWorktree(repoDir, branchName, worktreePath) {
124
+ if (existsSync(worktreePath)) {
125
+ return;
126
+ }
127
+ // Prune stale worktree references before adding new one
128
+ try {
129
+ this.git(['worktree', 'prune'], repoDir);
130
+ }
131
+ catch { /* non-fatal */ }
132
+ this.git(['worktree', 'add', worktreePath, branchName], repoDir);
133
+ }
134
+ async commit(worktree, message) {
135
+ this.git(['add', '-A'], worktree);
136
+ // Check if there is anything to commit
137
+ try {
138
+ this.git(['diff', '--cached', '--quiet'], worktree);
139
+ // No changes staged — nothing to commit
140
+ return;
141
+ }
142
+ catch {
143
+ // There are staged changes — proceed with commit
144
+ }
145
+ this.git(['commit', '-m', message], worktree);
146
+ }
147
+ async push(worktree, branch, force) {
148
+ const args = ['push', 'origin', branch];
149
+ if (force) {
150
+ args.splice(1, 0, '--force-with-lease');
151
+ }
152
+ this.git(args, worktree);
153
+ }
154
+ async rebase(worktree, baseBranch) {
155
+ this.git(['fetch', 'origin'], worktree);
156
+ try {
157
+ this.git(['rebase', `origin/${baseBranch}`], worktree);
158
+ return { success: true };
159
+ }
160
+ catch {
161
+ // Rebase failed — extract conflict files then abort
162
+ let conflictFiles = [];
163
+ try {
164
+ const status = this.git(['diff', '--name-only', '--diff-filter=U'], worktree);
165
+ conflictFiles = status.split('\n').filter(Boolean);
166
+ }
167
+ catch {
168
+ // Could not list conflicts — return empty list
169
+ }
170
+ try {
171
+ this.git(['rebase', '--abort'], worktree);
172
+ }
173
+ catch {
174
+ // Abort may fail if rebase already cleaned up
175
+ }
176
+ return { success: false, conflictFiles };
177
+ }
178
+ }
179
+ // ---------------------------------------------------------------------------
180
+ // GitLab API operations
181
+ // ---------------------------------------------------------------------------
182
+ async createOrUpdateMr(branch, title, description) {
183
+ const existing = await this.apiGet('/merge_requests', {
184
+ source_branch: branch,
185
+ target_branch: this.mergeBranch,
186
+ state: 'opened',
187
+ });
188
+ if (existing.length > 0) {
189
+ // Update existing MR
190
+ const mr = existing[0];
191
+ const updated = await this.apiPut(`/merge_requests/${mr.iid}`, {
192
+ title,
193
+ description,
194
+ });
195
+ return { url: updated.web_url, iid: updated.iid };
196
+ }
197
+ // Create new MR
198
+ const created = await this.apiPost('/merge_requests', {
199
+ source_branch: branch,
200
+ target_branch: this.mergeBranch,
201
+ title,
202
+ description,
203
+ });
204
+ return { url: created.web_url, iid: created.iid };
205
+ }
206
+ async getMrStatus(branch) {
207
+ const mrs = await this.apiGet('/merge_requests', {
208
+ source_branch: branch,
209
+ });
210
+ if (mrs.length === 0) {
211
+ return {
212
+ exists: false,
213
+ state: 'not_found',
214
+ ciStatus: 'unknown',
215
+ mergeStatus: 'unknown',
216
+ url: null,
217
+ iid: null,
218
+ };
219
+ }
220
+ const mr = mrs[0];
221
+ return {
222
+ exists: true,
223
+ state: this.mapMrState(mr.state),
224
+ ciStatus: this.mapCiStatus(mr.head_pipeline?.status ?? null),
225
+ mergeStatus: this.mapMergeStatus(mr.merge_status),
226
+ url: mr.web_url,
227
+ iid: mr.iid,
228
+ };
229
+ }
230
+ async mergeMr(iid) {
231
+ try {
232
+ const result = await this.apiPut(`/merge_requests/${iid}/merge`, {});
233
+ if (result.state === 'merged') {
234
+ return { merged: true };
235
+ }
236
+ return { merged: false, error: result.merge_error || `Unexpected state: ${result.state}` };
237
+ }
238
+ catch (err) {
239
+ const message = err instanceof Error ? err.message : String(err);
240
+ return { merged: false, error: message };
241
+ }
242
+ }
243
+ async detectMerged(branch) {
244
+ const mrs = await this.apiGet('/merge_requests', {
245
+ source_branch: branch,
246
+ state: 'merged',
247
+ });
248
+ return mrs.length > 0;
249
+ }
250
+ // ---------------------------------------------------------------------------
251
+ // Status mapping helpers (doc 12 §13.4)
252
+ // ---------------------------------------------------------------------------
253
+ mapMrState(state) {
254
+ switch (state) {
255
+ case 'opened': return 'opened';
256
+ case 'merged': return 'merged';
257
+ case 'closed': return 'closed';
258
+ default: return 'not_found';
259
+ }
260
+ }
261
+ mapCiStatus(status) {
262
+ switch (status) {
263
+ case 'success': return 'success';
264
+ case 'failed': return 'failed';
265
+ case 'running': return 'running';
266
+ case 'pending': return 'pending';
267
+ case 'created': return 'created';
268
+ default: return 'unknown';
269
+ }
270
+ }
271
+ mapMergeStatus(status) {
272
+ switch (status) {
273
+ case 'can_be_merged': return 'can_be_merged';
274
+ case 'cannot_be_merged': return 'cannot_be_merged';
275
+ case 'checking': return 'checking';
276
+ default: return 'unknown';
277
+ }
278
+ }
279
+ }
280
+ //# sourceMappingURL=GitLabRepoBackend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitLabRepoBackend.js","sourceRoot":"","sources":["../../src/providers/GitLabRepoBackend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAKrC;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IACX,SAAS,CAAS;IAClB,SAAS,CAAS;IAClB,KAAK,CAAS;IACd,OAAO,CAAS;IAChB,WAAW,CAAS;IAErC,YAAY,MAAqB;QAC/B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,IAAI,oBAAoB,CAAC;QAC/D,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,iBAAiB,CAAC;QAC1C,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,GAAG,GAAG,IAAI,CAAC,SAAS,oBAAoB,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACzF,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,mBAAmB,CAAC;IAChD,CAAC;IAED,8EAA8E;IAC9E,cAAc;IACd,8EAA8E;IAEtE,GAAG,CAAC,IAAc,EAAE,GAAW;QACrC,IAAI,CAAC;YACH,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE;gBAC/B,GAAG;gBACH,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;aAChC,CAAC,CAAC,IAAI,EAAE,CAAC;QACZ,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,GAA2C,CAAC;YACtD,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,IAAI,QAAQ,GAAG,KAAK,MAAM,EAAE,CACnE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,cAAc;IACd,8EAA8E;IAEtE,KAAK,CAAC,MAAM,CAAI,IAAY,EAAE,KAA8B;QAClE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC,CAAC;QAC9C,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;YACtC,OAAO,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC,KAAK,EAAE;SACzC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,aAAa,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;IACjC,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,IAAY,EAAE,IAA6B;QAClE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE;YAChD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,eAAe,EAAE,IAAI,CAAC,KAAK;gBAC3B,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,aAAa,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QACzE,CAAC;QACD,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;IACjC,CAAC;IAEO,KAAK,CAAC,MAAM,CAAI,IAAY,EAAE,IAA6B;QACjE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE;YAChD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,eAAe,EAAE,IAAI,CAAC,KAAK;gBAC3B,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,aAAa,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;IACjC,CAAC;IAED,8EAA8E;IAC9E,uBAAuB;IACvB,8EAA8E;IAE9E,KAAK,CAAC,eAAe,CAAC,OAAe,EAAE,UAAkB;QACvD,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAAe,EAAE,UAAkB,EAAE,UAAkB;QACxE,mFAAmF;QACnF,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;YACnD,IAAI,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,UAAU,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5E,CAAC;QAED,qDAAqD;QACrD,IAAI,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;YACzD,0EAA0E;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;YACf,IAAI,CAAC;gBACH,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,UAAU,UAAU,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;gBACrE,mEAAmE;gBACnE,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,UAAU,UAAU,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;YACpE,CAAC;YAAC,MAAM,CAAC;gBACP,8DAA8D;gBAC9D,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,UAAU,UAAU,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAAe,EAAE,UAAkB,EAAE,YAAoB;QAC5E,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,wDAAwD;QACxD,IAAI,CAAC;YAAC,IAAI,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC;QAC3E,IAAI,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAgB,EAAE,OAAe;QAC5C,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;QAClC,uCAAuC;QACvC,IAAI,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC,CAAC;YACpD,wCAAwC;YACxC,OAAO;QACT,CAAC;QAAC,MAAM,CAAC;YACP,iDAAiD;QACnD,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAgB,EAAE,MAAc,EAAE,KAAe;QAC1D,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACxC,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,oBAAoB,CAAC,CAAC;QAC1C,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAgB,EAAE,UAAkB;QAC/C,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,UAAU,UAAU,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;YACvD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,oDAAoD;YACpD,IAAI,aAAa,GAAa,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,iBAAiB,CAAC,EAAE,QAAQ,CAAC,CAAC;gBAC9E,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACrD,CAAC;YAAC,MAAM,CAAC;gBACP,+CAA+C;YACjD,CAAC;YACD,IAAI,CAAC;gBACH,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC,CAAC;YAC5C,CAAC;YAAC,MAAM,CAAC;gBACP,8CAA8C;YAChD,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,wBAAwB;IACxB,8EAA8E;IAE9E,KAAK,CAAC,gBAAgB,CACpB,MAAc,EACd,KAAa,EACb,WAAmB;QASnB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAa,iBAAiB,EAAE;YAChE,aAAa,EAAE,MAAM;YACrB,aAAa,EAAE,IAAI,CAAC,WAAW;YAC/B,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,qBAAqB;YACrB,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACvB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAW,mBAAmB,EAAE,CAAC,GAAG,EAAE,EAAE;gBACvE,KAAK;gBACL,WAAW;aACZ,CAAC,CAAC;YACH,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;QACpD,CAAC;QAED,gBAAgB;QAChB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAW,iBAAiB,EAAE;YAC9D,aAAa,EAAE,MAAM;YACrB,aAAa,EAAE,IAAI,CAAC,WAAW;YAC/B,KAAK;YACL,WAAW;SACZ,CAAC,CAAC;QACH,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc;QAS9B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAmB,iBAAiB,EAAE;YACjE,aAAa,EAAE,MAAM;SACtB,CAAC,CAAC;QAEH,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO;gBACL,MAAM,EAAE,KAAK;gBACb,KAAK,EAAE,WAAW;gBAClB,QAAQ,EAAE,SAAS;gBACnB,WAAW,EAAE,SAAS;gBACtB,GAAG,EAAE,IAAI;gBACT,GAAG,EAAE,IAAI;aACV,CAAC;QACJ,CAAC;QAED,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAElB,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC;YAChC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,IAAI,IAAI,CAAC;YAC5D,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,YAAY,CAAC;YACjD,GAAG,EAAE,EAAE,CAAC,OAAO;YACf,GAAG,EAAE,EAAE,CAAC,GAAG;SACZ,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW;QAMvB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAc,mBAAmB,GAAG,QAAQ,EAAE,EAAE,CAAC,CAAC;YAClF,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YAC1B,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,IAAI,qBAAqB,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;QAC7F,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAc;QAK/B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAkB,iBAAiB,EAAE;YAChE,aAAa,EAAE,MAAM;YACrB,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAC;QAEH,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,8EAA8E;IAC9E,wCAAwC;IACxC,8EAA8E;IAEtE,UAAU,CAAC,KAAa;QAC9B,QAAQ,KAAK,EAAE,CAAC;YACd,KAAK,QAAQ,CAAC,CAAC,OAAO,QAAQ,CAAC;YAC/B,KAAK,QAAQ,CAAC,CAAC,OAAO,QAAQ,CAAC;YAC/B,KAAK,QAAQ,CAAC,CAAC,OAAO,QAAQ,CAAC;YAC/B,OAAO,CAAC,CAAC,OAAO,WAAW,CAAC;QAC9B,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,MAAqB;QACvC,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,SAAS,CAAC,CAAC,OAAO,SAAS,CAAC;YACjC,KAAK,QAAQ,CAAC,CAAC,OAAO,QAAQ,CAAC;YAC/B,KAAK,SAAS,CAAC,CAAC,OAAO,SAAS,CAAC;YACjC,KAAK,SAAS,CAAC,CAAC,OAAO,SAAS,CAAC;YACjC,KAAK,SAAS,CAAC,CAAC,OAAO,SAAS,CAAC;YACjC,OAAO,CAAC,CAAC,OAAO,SAAS,CAAC;QAC5B,CAAC;IACH,CAAC;IAEO,cAAc,CAAC,MAAc;QACnC,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,eAAe,CAAC,CAAC,OAAO,eAAe,CAAC;YAC7C,KAAK,kBAAkB,CAAC,CAAC,OAAO,kBAAkB,CAAC;YACnD,KAAK,UAAU,CAAC,CAAC,OAAO,UAAU,CAAC;YACnC,OAAO,CAAC,CAAC,OAAO,SAAS,CAAC;QAC5B,CAAC;IACH,CAAC;CACF"}