@vertaaux/cli 0.3.3 → 0.5.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 (227) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/MIGRATION.md +239 -0
  3. package/README.md +34 -16
  4. package/dist/app/interactive-app.d.ts +101 -0
  5. package/dist/app/interactive-app.d.ts.map +1 -0
  6. package/dist/app/interactive-app.js +309 -0
  7. package/dist/app/layout/canvas.d.ts +23 -0
  8. package/dist/app/layout/canvas.d.ts.map +1 -0
  9. package/dist/app/layout/canvas.js +36 -0
  10. package/dist/app/layout/footer.d.ts +31 -0
  11. package/dist/app/layout/footer.d.ts.map +1 -0
  12. package/dist/app/layout/footer.js +41 -0
  13. package/dist/app/layout/header.d.ts +20 -0
  14. package/dist/app/layout/header.d.ts.map +1 -0
  15. package/dist/app/layout/header.js +27 -0
  16. package/dist/app/menu/categories.d.ts +20 -0
  17. package/dist/app/menu/categories.d.ts.map +1 -0
  18. package/dist/app/menu/categories.js +181 -0
  19. package/dist/app/menu/filter.d.ts +17 -0
  20. package/dist/app/menu/filter.d.ts.map +1 -0
  21. package/dist/app/menu/filter.js +33 -0
  22. package/dist/app/menu/menu-view.d.ts +35 -0
  23. package/dist/app/menu/menu-view.d.ts.map +1 -0
  24. package/dist/app/menu/menu-view.js +230 -0
  25. package/dist/app/menu/recent.d.ts +24 -0
  26. package/dist/app/menu/recent.d.ts.map +1 -0
  27. package/dist/app/menu/recent.js +49 -0
  28. package/dist/app/types.d.ts +43 -0
  29. package/dist/app/types.d.ts.map +1 -0
  30. package/dist/app/types.js +7 -0
  31. package/dist/app/views/command-runner.d.ts +36 -0
  32. package/dist/app/views/command-runner.d.ts.map +1 -0
  33. package/dist/app/views/command-runner.js +372 -0
  34. package/dist/app/views/help-overlay.d.ts +21 -0
  35. package/dist/app/views/help-overlay.d.ts.map +1 -0
  36. package/dist/app/views/help-overlay.js +45 -0
  37. package/dist/auth/ci-token.d.ts +14 -2
  38. package/dist/auth/ci-token.d.ts.map +1 -1
  39. package/dist/auth/ci-token.js +15 -30
  40. package/dist/auth/device-flow.d.ts +2 -1
  41. package/dist/auth/device-flow.d.ts.map +1 -1
  42. package/dist/auth/device-flow.js +13 -10
  43. package/dist/auth/token-store.d.ts.map +1 -1
  44. package/dist/auth/token-store.js +12 -2
  45. package/dist/baseline/diff.d.ts +2 -2
  46. package/dist/baseline/diff.d.ts.map +1 -1
  47. package/dist/baseline/diff.js +15 -34
  48. package/dist/commands/a11y.d.ts +9 -0
  49. package/dist/commands/a11y.d.ts.map +1 -0
  50. package/dist/commands/a11y.js +76 -0
  51. package/dist/commands/audit/artifacts.d.ts +27 -0
  52. package/dist/commands/audit/artifacts.d.ts.map +1 -0
  53. package/dist/commands/audit/artifacts.js +158 -0
  54. package/dist/commands/audit/ci-detection.d.ts +18 -0
  55. package/dist/commands/audit/ci-detection.d.ts.map +1 -0
  56. package/dist/commands/audit/ci-detection.js +71 -0
  57. package/dist/commands/audit/explain.d.ts +11 -0
  58. package/dist/commands/audit/explain.d.ts.map +1 -0
  59. package/dist/commands/audit/explain.js +45 -0
  60. package/dist/commands/audit/filters.d.ts +17 -0
  61. package/dist/commands/audit/filters.d.ts.map +1 -0
  62. package/dist/commands/audit/filters.js +40 -0
  63. package/dist/commands/audit/index.d.ts +18 -0
  64. package/dist/commands/audit/index.d.ts.map +1 -0
  65. package/dist/commands/audit/index.js +564 -0
  66. package/dist/commands/audit/output.d.ts +32 -0
  67. package/dist/commands/audit/output.d.ts.map +1 -0
  68. package/dist/commands/audit/output.js +130 -0
  69. package/dist/commands/audit/policy.d.ts +19 -0
  70. package/dist/commands/audit/policy.d.ts.map +1 -0
  71. package/dist/commands/audit/policy.js +102 -0
  72. package/dist/commands/audit/scoring.d.ts +23 -0
  73. package/dist/commands/audit/scoring.d.ts.map +1 -0
  74. package/dist/commands/audit/scoring.js +70 -0
  75. package/dist/commands/audit/types.d.ts +88 -0
  76. package/dist/commands/audit/types.d.ts.map +1 -0
  77. package/dist/commands/audit/types.js +8 -0
  78. package/dist/commands/audit.d.ts +2 -60
  79. package/dist/commands/audit.d.ts.map +1 -1
  80. package/dist/commands/audit.js +2 -1038
  81. package/dist/commands/baseline.d.ts +1 -0
  82. package/dist/commands/baseline.d.ts.map +1 -1
  83. package/dist/commands/baseline.js +205 -121
  84. package/dist/commands/comment.d.ts +22 -0
  85. package/dist/commands/comment.d.ts.map +1 -1
  86. package/dist/commands/comment.js +122 -58
  87. package/dist/commands/compare.d.ts +17 -0
  88. package/dist/commands/compare.d.ts.map +1 -1
  89. package/dist/commands/compare.js +287 -180
  90. package/dist/commands/diff.d.ts +5 -0
  91. package/dist/commands/diff.d.ts.map +1 -1
  92. package/dist/commands/diff.js +168 -141
  93. package/dist/commands/doc.d.ts +10 -0
  94. package/dist/commands/doc.d.ts.map +1 -1
  95. package/dist/commands/doc.js +134 -76
  96. package/dist/commands/doctor.d.ts +2 -0
  97. package/dist/commands/doctor.d.ts.map +1 -1
  98. package/dist/commands/doctor.js +164 -17
  99. package/dist/commands/download.d.ts +10 -0
  100. package/dist/commands/download.d.ts.map +1 -1
  101. package/dist/commands/download.js +169 -112
  102. package/dist/commands/explain.d.ts +5 -0
  103. package/dist/commands/explain.d.ts.map +1 -1
  104. package/dist/commands/explain.js +241 -155
  105. package/dist/commands/fix-all.d.ts +25 -0
  106. package/dist/commands/fix-all.d.ts.map +1 -0
  107. package/dist/commands/fix-all.js +206 -0
  108. package/dist/commands/fix-plan.d.ts +9 -0
  109. package/dist/commands/fix-plan.d.ts.map +1 -1
  110. package/dist/commands/fix-plan.js +152 -89
  111. package/dist/commands/fix.d.ts +17 -0
  112. package/dist/commands/fix.d.ts.map +1 -0
  113. package/dist/commands/fix.js +111 -0
  114. package/dist/commands/init.d.ts +11 -0
  115. package/dist/commands/init.d.ts.map +1 -1
  116. package/dist/commands/init.js +94 -42
  117. package/dist/commands/login.d.ts +18 -0
  118. package/dist/commands/login.d.ts.map +1 -1
  119. package/dist/commands/login.js +268 -95
  120. package/dist/commands/patch-review.d.ts +11 -0
  121. package/dist/commands/patch-review.d.ts.map +1 -1
  122. package/dist/commands/patch-review.js +159 -97
  123. package/dist/commands/policy.d.ts +31 -0
  124. package/dist/commands/policy.d.ts.map +1 -1
  125. package/dist/commands/policy.js +269 -124
  126. package/dist/commands/release-notes.d.ts +10 -0
  127. package/dist/commands/release-notes.d.ts.map +1 -1
  128. package/dist/commands/release-notes.js +127 -73
  129. package/dist/commands/scan.d.ts +13 -0
  130. package/dist/commands/scan.d.ts.map +1 -0
  131. package/dist/commands/scan.js +133 -0
  132. package/dist/commands/status.d.ts +9 -0
  133. package/dist/commands/status.d.ts.map +1 -0
  134. package/dist/commands/status.js +81 -0
  135. package/dist/commands/suggest.d.ts +10 -0
  136. package/dist/commands/suggest.d.ts.map +1 -1
  137. package/dist/commands/suggest.js +153 -82
  138. package/dist/commands/triage.d.ts +35 -0
  139. package/dist/commands/triage.d.ts.map +1 -1
  140. package/dist/commands/triage.js +206 -81
  141. package/dist/commands/upload.d.ts +9 -0
  142. package/dist/commands/upload.d.ts.map +1 -1
  143. package/dist/commands/upload.js +140 -101
  144. package/dist/commands/verify.d.ts +13 -0
  145. package/dist/commands/verify.d.ts.map +1 -0
  146. package/dist/commands/verify.js +118 -0
  147. package/dist/index.d.ts +3 -2
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +125 -990
  150. package/dist/interactive/fix-wizard.d.ts +3 -0
  151. package/dist/interactive/fix-wizard.d.ts.map +1 -1
  152. package/dist/interactive/fix-wizard.js +130 -112
  153. package/dist/interactive/init-wizard.d.ts +3 -1
  154. package/dist/interactive/init-wizard.d.ts.map +1 -1
  155. package/dist/interactive/init-wizard.js +207 -138
  156. package/dist/interactive/prompts.d.ts +7 -3
  157. package/dist/interactive/prompts.d.ts.map +1 -1
  158. package/dist/interactive/prompts.js +44 -23
  159. package/dist/output/envelope.d.ts +2 -0
  160. package/dist/output/envelope.d.ts.map +1 -1
  161. package/dist/output/envelope.js +18 -2
  162. package/dist/output/factory.d.ts +9 -1
  163. package/dist/output/factory.d.ts.map +1 -1
  164. package/dist/output/html.d.ts +2 -1
  165. package/dist/output/html.d.ts.map +1 -1
  166. package/dist/output/html.js +3 -2
  167. package/dist/output/human.d.ts +9 -1
  168. package/dist/output/human.d.ts.map +1 -1
  169. package/dist/output/human.js +17 -2
  170. package/dist/output/json.d.ts +2 -1
  171. package/dist/output/json.d.ts.map +1 -1
  172. package/dist/output/junit.d.ts +2 -1
  173. package/dist/output/junit.d.ts.map +1 -1
  174. package/dist/output/sarif.d.ts +2 -1
  175. package/dist/output/sarif.d.ts.map +1 -1
  176. package/dist/types.d.ts +74 -0
  177. package/dist/types.d.ts.map +1 -0
  178. package/dist/types.js +5 -0
  179. package/dist/ui/banner.d.ts +34 -0
  180. package/dist/ui/banner.d.ts.map +1 -1
  181. package/dist/ui/banner.js +97 -5
  182. package/dist/ui/diagnostics.d.ts +9 -4
  183. package/dist/ui/diagnostics.d.ts.map +1 -1
  184. package/dist/ui/diagnostics.js +32 -82
  185. package/dist/ui/strings.d.ts +373 -0
  186. package/dist/ui/strings.d.ts.map +1 -0
  187. package/dist/ui/strings.js +499 -0
  188. package/dist/ui/table.d.ts +0 -2
  189. package/dist/ui/table.d.ts.map +1 -1
  190. package/dist/ui/table.js +3 -4
  191. package/dist/utils/api-client.d.ts +46 -0
  192. package/dist/utils/api-client.d.ts.map +1 -0
  193. package/dist/utils/api-client.js +170 -0
  194. package/dist/utils/client.d.ts +29 -18
  195. package/dist/utils/client.d.ts.map +1 -1
  196. package/dist/utils/client.js +102 -12
  197. package/dist/utils/formatters.d.ts +38 -0
  198. package/dist/utils/formatters.d.ts.map +1 -0
  199. package/dist/utils/formatters.js +277 -0
  200. package/dist/utils/local-capture.d.ts +25 -0
  201. package/dist/utils/local-capture.d.ts.map +1 -0
  202. package/dist/utils/local-capture.js +57 -0
  203. package/dist/utils/url-classify.d.ts +18 -0
  204. package/dist/utils/url-classify.d.ts.map +1 -0
  205. package/dist/utils/url-classify.js +106 -0
  206. package/node_modules/@vertaaux/tui/dist/index.cjs +713 -20
  207. package/node_modules/@vertaaux/tui/dist/index.cjs.map +1 -1
  208. package/node_modules/@vertaaux/tui/dist/index.d.cts +361 -4
  209. package/node_modules/@vertaaux/tui/dist/index.d.ts +361 -4
  210. package/node_modules/@vertaaux/tui/dist/index.js +689 -21
  211. package/node_modules/@vertaaux/tui/dist/index.js.map +1 -1
  212. package/package.json +13 -5
  213. package/dist/commands/client.d.ts +0 -14
  214. package/dist/commands/client.d.ts.map +0 -1
  215. package/dist/commands/client.js +0 -362
  216. package/dist/commands/drift.d.ts +0 -15
  217. package/dist/commands/drift.d.ts.map +0 -1
  218. package/dist/commands/drift.js +0 -309
  219. package/dist/commands/protect.d.ts +0 -16
  220. package/dist/commands/protect.d.ts.map +0 -1
  221. package/dist/commands/protect.js +0 -323
  222. package/dist/commands/report.d.ts +0 -15
  223. package/dist/commands/report.d.ts.map +0 -1
  224. package/dist/commands/report.js +0 -214
  225. package/dist/policy/sync.d.ts +0 -67
  226. package/dist/policy/sync.d.ts.map +0 -1
  227. package/dist/policy/sync.js +0 -147
@@ -0,0 +1,372 @@
1
+ /**
2
+ * CommandRunnerView — Executes a CLI command within the InteractiveApp canvas.
3
+ *
4
+ * Lifecycle:
5
+ * 1. "collecting" — prompts for required args ON the alt screen using raw-mode
6
+ * keyboard input (same system as MenuView). No stdin mode transitions.
7
+ * 2. "running" — command runs INSIDE the app layout. A renderer override
8
+ * captures step states so this view can render them in the canvas.
9
+ * Header and footer stay visible throughout.
10
+ * 3. "done"/"error" — shows result summary in canvas, M returns to menu.
11
+ *
12
+ * Each command's handler is called directly (no program.parse()).
13
+ */
14
+ import { dim, bold, colorize, brand, renderError, setRendererOverride, setKeyboardOverrideActive, renderStepList, getTerminalWidth, getTerminalHeight, } from "@vertaaux/tui";
15
+ import { setOutputBuffer } from "../../output/envelope.js";
16
+ // Command handler imports
17
+ import { handleAudit } from "../../commands/audit/index.js";
18
+ import { handleScan } from "../../commands/scan.js";
19
+ import { handleA11y } from "../../commands/a11y.js";
20
+ import { handleStatus } from "../../commands/status.js";
21
+ import { handleDiff } from "../../commands/diff.js";
22
+ import { handleCompare } from "../../commands/compare.js";
23
+ import { handleTriage } from "../../commands/triage.js";
24
+ import { handleExplain } from "../../commands/explain.js";
25
+ import { handleSuggest } from "../../commands/suggest.js";
26
+ import { handleFix } from "../../commands/fix.js";
27
+ import { handleFixAll } from "../../commands/fix-all.js";
28
+ import { handleFixPlan } from "../../commands/fix-plan.js";
29
+ import { handlePatchReview } from "../../commands/patch-review.js";
30
+ import { handleDoc } from "../../commands/doc.js";
31
+ import { handleComment } from "../../commands/comment.js";
32
+ import { handleReleaseNotes } from "../../commands/release-notes.js";
33
+ import { handleInit } from "../../commands/init.js";
34
+ import { handleBaseline } from "../../commands/baseline.js";
35
+ import { handleUpload } from "../../commands/upload.js";
36
+ import { handleDownload } from "../../commands/download.js";
37
+ import { handleVerify } from "../../commands/verify.js";
38
+ import { handleLogin, handleLogout, handleWhoami } from "../../commands/login.js";
39
+ import { handleDoctor } from "../../commands/doctor.js";
40
+ import { handlePolicy } from "../../commands/policy.js";
41
+ /**
42
+ * Get the argument definitions for a command.
43
+ */
44
+ function getArgDefs(cmd) {
45
+ switch (cmd) {
46
+ case "audit":
47
+ case "scan":
48
+ case "a11y":
49
+ return [{ label: "Target URL", key: "url" }];
50
+ case "status":
51
+ return [{ label: "Job ID", key: "jobId" }];
52
+ case "fix":
53
+ return [{ label: "Job ID to fix", key: "jobId" }];
54
+ case "suggest":
55
+ return [{ label: "Describe the fix you need", key: "intent" }];
56
+ case "fix-all":
57
+ return [
58
+ { label: "Job ID", key: "jobId" },
59
+ { label: "File path or content", key: "fileContent" },
60
+ ];
61
+ case "download":
62
+ return [{ label: "Job ID to download", key: "jobId" }];
63
+ default:
64
+ return [];
65
+ }
66
+ }
67
+ /**
68
+ * A renderer that captures state instead of writing to the terminal.
69
+ * The CommandRunnerView reads from it in render().
70
+ */
71
+ class CanvasRenderer {
72
+ stepStates = [];
73
+ result = null;
74
+ finished = false;
75
+ update(state) {
76
+ if (state.stepStates) {
77
+ this.stepStates = [...state.stepStates];
78
+ }
79
+ }
80
+ finish(result) {
81
+ this.result = result;
82
+ this.finished = true;
83
+ }
84
+ dispose() { }
85
+ suspend() { }
86
+ resume() { }
87
+ }
88
+ export class CommandRunnerView {
89
+ status;
90
+ statusText = "";
91
+ commandValue;
92
+ app;
93
+ onReturn;
94
+ // Arg collection state
95
+ argDefs;
96
+ collectedArgs = {};
97
+ currentArgIndex = 0;
98
+ inputBuffer = "";
99
+ // Resolve function for the arg collection promise
100
+ resolveArgCollection = null;
101
+ // Canvas renderer for capturing step states
102
+ canvasRenderer = new CanvasRenderer();
103
+ // Captured command output (from writeOutput during execution)
104
+ outputBuffer = [];
105
+ // Scroll position for viewing results
106
+ scrollOffset = 0;
107
+ constructor(commandValue, app, onReturn) {
108
+ this.commandValue = commandValue;
109
+ this.app = app;
110
+ this.onReturn = onReturn;
111
+ this.argDefs = getArgDefs(commandValue);
112
+ this.status = this.argDefs.length > 0 ? "collecting" : "running";
113
+ }
114
+ render() {
115
+ const lines = [];
116
+ switch (this.status) {
117
+ case "collecting": {
118
+ lines.push(bold(this.commandValue));
119
+ lines.push("");
120
+ for (let i = 0; i < this.currentArgIndex; i++) {
121
+ const def = this.argDefs[i];
122
+ lines.push(dim(` ${def.label}: `) + this.collectedArgs[def.key]);
123
+ }
124
+ const currentDef = this.argDefs[this.currentArgIndex];
125
+ if (currentDef) {
126
+ lines.push(colorize(` ${currentDef.label}: `, brand.lime) +
127
+ this.inputBuffer +
128
+ colorize("█", brand.lime));
129
+ }
130
+ lines.push("");
131
+ lines.push(dim("Type your input, then press Enter to confirm"));
132
+ lines.push(dim("Press Escape to cancel"));
133
+ break;
134
+ }
135
+ case "running": {
136
+ // Show step-list from the canvas renderer
137
+ if (this.canvasRenderer.stepStates.length > 0) {
138
+ const stepList = renderStepList(this.canvasRenderer.stepStates, this.app.getFrameIndex(), getTerminalWidth());
139
+ lines.push(stepList);
140
+ }
141
+ else {
142
+ lines.push(dim(`Running ${bold(this.commandValue)}...`));
143
+ }
144
+ break;
145
+ }
146
+ case "done":
147
+ case "error": {
148
+ const content = this.status === "error" && this.outputBuffer.length === 0
149
+ ? [renderError({ message: this.statusText || "Command failed", suggestion: "vertaa doctor" })]
150
+ : this.outputBuffer.length > 0
151
+ ? [...this.outputBuffer]
152
+ : [colorize("Command completed.", brand.lime)];
153
+ // Scrollable view: show a window of lines based on scrollOffset
154
+ // Reserve 2 lines for footer hint
155
+ const availableHeight = Math.max(3, getTerminalHeight() - 12);
156
+ const totalLines = content.length;
157
+ const maxScroll = Math.max(0, totalLines - availableHeight);
158
+ this.scrollOffset = Math.min(this.scrollOffset, maxScroll);
159
+ const visible = content.slice(this.scrollOffset, this.scrollOffset + availableHeight);
160
+ lines.push(...visible);
161
+ // Scroll indicator
162
+ if (totalLines > availableHeight) {
163
+ const pct = maxScroll > 0 ? Math.round((this.scrollOffset / maxScroll) * 100) : 100;
164
+ lines.push("");
165
+ lines.push(dim(`↑↓ scroll (${pct}%) | M menu | Q quit`));
166
+ }
167
+ else {
168
+ lines.push("");
169
+ lines.push(dim("M menu | Q quit"));
170
+ }
171
+ break;
172
+ }
173
+ }
174
+ return lines.join("\n");
175
+ }
176
+ handleKey(key, ctrl, _meta) {
177
+ if (this.status === "collecting") {
178
+ if (ctrl && key === "\x03")
179
+ return false;
180
+ if (key === "\x1b") {
181
+ this.onReturn();
182
+ return true;
183
+ }
184
+ if (key === "\r" || key === "\n") {
185
+ const currentDef = this.argDefs[this.currentArgIndex];
186
+ if (currentDef && this.inputBuffer.trim().length > 0) {
187
+ this.collectedArgs[currentDef.key] = this.inputBuffer.trim();
188
+ this.inputBuffer = "";
189
+ this.currentArgIndex++;
190
+ if (this.currentArgIndex >= this.argDefs.length) {
191
+ if (this.resolveArgCollection) {
192
+ this.resolveArgCollection();
193
+ }
194
+ }
195
+ }
196
+ return true;
197
+ }
198
+ if (key === "\x7f" || key === "\b") {
199
+ this.inputBuffer = this.inputBuffer.slice(0, -1);
200
+ return true;
201
+ }
202
+ if (key.length === 1 && key >= " ") {
203
+ this.inputBuffer += key;
204
+ return true;
205
+ }
206
+ return false;
207
+ }
208
+ // Done/error state — handle navigation and scroll keys
209
+ if (this.status === "done" || this.status === "error") {
210
+ if (key === "m" || key === "M" || key === "\r") {
211
+ this.onReturn();
212
+ return true;
213
+ }
214
+ if (key === "\x1b") {
215
+ // Escape — but not arrow key sequences
216
+ this.onReturn();
217
+ return true;
218
+ }
219
+ if (key === "q" || key === "Q") {
220
+ process.exit(0);
221
+ }
222
+ // Arrow up / k
223
+ if (key === "\x1b[A" || key === "k") {
224
+ this.scrollOffset = Math.max(0, this.scrollOffset - 1);
225
+ return true;
226
+ }
227
+ // Arrow down / j
228
+ if (key === "\x1b[B" || key === "j") {
229
+ this.scrollOffset++;
230
+ return true;
231
+ }
232
+ // Page up
233
+ if (key === "\x1b[5~") {
234
+ this.scrollOffset = Math.max(0, this.scrollOffset - 10);
235
+ return true;
236
+ }
237
+ // Page down
238
+ if (key === "\x1b[6~") {
239
+ this.scrollOffset += 10;
240
+ return true;
241
+ }
242
+ // Home
243
+ if (key === "\x1b[H" || key === "g") {
244
+ this.scrollOffset = 0;
245
+ return true;
246
+ }
247
+ // End
248
+ if (key === "\x1b[F" || key === "G") {
249
+ this.scrollOffset = Infinity; // clamped in render()
250
+ return true;
251
+ }
252
+ return true;
253
+ }
254
+ return false;
255
+ }
256
+ async onMount() {
257
+ // If command needs args, wait for collection
258
+ if (this.argDefs.length > 0) {
259
+ await new Promise((resolve) => {
260
+ this.resolveArgCollection = resolve;
261
+ });
262
+ }
263
+ // Set overrides so command handlers use our canvas renderer,
264
+ // don't steal stdin, and buffer their output instead of writing to stderr.
265
+ this.status = "running";
266
+ setRendererOverride(this.canvasRenderer);
267
+ setKeyboardOverrideActive(true);
268
+ setOutputBuffer(this.outputBuffer);
269
+ try {
270
+ await this.executeCommand();
271
+ this.status = "done";
272
+ }
273
+ catch (err) {
274
+ this.status = "error";
275
+ this.statusText = err instanceof Error ? err.message : String(err);
276
+ }
277
+ // Restore all overrides
278
+ setOutputBuffer(null);
279
+ setRendererOverride(null);
280
+ setKeyboardOverrideActive(false);
281
+ }
282
+ // ── Private ──────────────────────────────────────────────────
283
+ async executeCommand() {
284
+ const cmd = this.commandValue;
285
+ const args = this.collectedArgs;
286
+ switch (cmd) {
287
+ case "audit":
288
+ await handleAudit(args.url, {}, {});
289
+ break;
290
+ case "scan":
291
+ await handleScan(args.url, {});
292
+ break;
293
+ case "a11y":
294
+ await handleA11y(args.url, {});
295
+ break;
296
+ case "status":
297
+ await handleStatus(args.jobId, {});
298
+ break;
299
+ case "fix":
300
+ await handleFix(args.jobId, {});
301
+ break;
302
+ case "download":
303
+ await handleDownload(args.jobId, {});
304
+ break;
305
+ case "suggest":
306
+ await handleSuggest({ intent: args.intent });
307
+ break;
308
+ case "fix-all":
309
+ await handleFixAll({
310
+ jobId: args.jobId,
311
+ fileContent: args.fileContent,
312
+ });
313
+ break;
314
+ case "diff":
315
+ await handleDiff({});
316
+ break;
317
+ case "compare":
318
+ await handleCompare({});
319
+ break;
320
+ case "triage":
321
+ await handleTriage({});
322
+ break;
323
+ case "explain":
324
+ await handleExplain({});
325
+ break;
326
+ case "fix-plan":
327
+ await handleFixPlan({});
328
+ break;
329
+ case "patch-review":
330
+ await handlePatchReview({});
331
+ break;
332
+ case "doc":
333
+ await handleDoc({});
334
+ break;
335
+ case "comment":
336
+ await handleComment({});
337
+ break;
338
+ case "release-notes":
339
+ await handleReleaseNotes({});
340
+ break;
341
+ case "init":
342
+ await handleInit({});
343
+ break;
344
+ case "baseline":
345
+ await handleBaseline(undefined, {});
346
+ break;
347
+ case "upload":
348
+ await handleUpload(undefined, {});
349
+ break;
350
+ case "verify":
351
+ await handleVerify({});
352
+ break;
353
+ case "login":
354
+ await handleLogin({});
355
+ break;
356
+ case "logout":
357
+ await handleLogout();
358
+ break;
359
+ case "whoami":
360
+ await handleWhoami({});
361
+ break;
362
+ case "doctor":
363
+ await handleDoctor({});
364
+ break;
365
+ case "policy":
366
+ await handlePolicy("show", {});
367
+ break;
368
+ default:
369
+ throw new Error(`Unknown command: ${cmd}`);
370
+ }
371
+ }
372
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * HelpOverlayView — Keyboard shortcuts overlay implementing CommandView.
3
+ *
4
+ * Renders a box with context-specific keyboard shortcuts. Pressing H or Esc
5
+ * dismisses the overlay via the onDismiss callback.
6
+ */
7
+ import type { CommandView } from "../types.js";
8
+ /**
9
+ * HelpOverlayView implements CommandView for the keyboard shortcuts overlay.
10
+ *
11
+ * @param onDismiss - Callback invoked when user dismisses the overlay (H or Esc)
12
+ */
13
+ export declare class HelpOverlayView implements CommandView {
14
+ private readonly onDismiss;
15
+ constructor(onDismiss: () => void);
16
+ /** Render the help overlay as a box */
17
+ render(): string;
18
+ /** Handle H and Esc to dismiss the overlay */
19
+ handleKey(key: string, _ctrl: boolean, _meta: boolean): boolean;
20
+ }
21
+ //# sourceMappingURL=help-overlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help-overlay.d.ts","sourceRoot":"","sources":["../../../src/app/views/help-overlay.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY/C;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,WAAW;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;gBAE3B,SAAS,EAAE,MAAM,IAAI;IAIjC,uCAAuC;IACvC,MAAM,IAAI,MAAM;IAehB,8CAA8C;IAC9C,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO;CAOhE"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * HelpOverlayView — Keyboard shortcuts overlay implementing CommandView.
3
+ *
4
+ * Renders a box with context-specific keyboard shortcuts. Pressing H or Esc
5
+ * dismisses the overlay via the onDismiss callback.
6
+ */
7
+ import { box, bold, dim } from "@vertaaux/tui";
8
+ /** Default shortcuts shown in any context */
9
+ const DEFAULT_SHORTCUTS = [
10
+ ["↑ / ↓", "Navigate menu items"],
11
+ ["Enter", "Select / confirm"],
12
+ ["/", "Start search (or type any character)"],
13
+ ["Esc", "Clear search / go back"],
14
+ ["H", "Toggle this help overlay"],
15
+ ["Ctrl+C", "Exit vertaa"],
16
+ ];
17
+ /**
18
+ * HelpOverlayView implements CommandView for the keyboard shortcuts overlay.
19
+ *
20
+ * @param onDismiss - Callback invoked when user dismisses the overlay (H or Esc)
21
+ */
22
+ export class HelpOverlayView {
23
+ onDismiss;
24
+ constructor(onDismiss) {
25
+ this.onDismiss = onDismiss;
26
+ }
27
+ /** Render the help overlay as a box */
28
+ render() {
29
+ const rows = DEFAULT_SHORTCUTS.map(([key, description]) => ` ${bold(key.padEnd(12))} ${dim(description)}`);
30
+ const content = [
31
+ bold("Keyboard Shortcuts"),
32
+ dim("─".repeat(36)),
33
+ ...rows,
34
+ ].join("\n");
35
+ return box(content, { padding: 1 });
36
+ }
37
+ /** Handle H and Esc to dismiss the overlay */
38
+ handleKey(key, _ctrl, _meta) {
39
+ if (key === "h" || key === "H" || key === "\x1b") {
40
+ this.onDismiss();
41
+ return true;
42
+ }
43
+ return false;
44
+ }
45
+ }
@@ -20,6 +20,12 @@ interface TokenValidationResponse {
20
20
  valid: boolean;
21
21
  /** User or organization ID */
22
22
  user_id?: string;
23
+ /** User display name */
24
+ name?: string;
25
+ /** User email */
26
+ email?: string;
27
+ /** Subscription tier */
28
+ tier?: string;
23
29
  /** Organization name */
24
30
  organization?: string;
25
31
  /** Scopes granted to token */
@@ -32,16 +38,22 @@ interface TokenValidationResponse {
32
38
  /**
33
39
  * Validate a CI token against the API.
34
40
  *
41
+ * Uses apiRequest() from client.ts with the token as explicit API key,
42
+ * so that auth header construction stays centralized in client.ts.
43
+ *
35
44
  * @param token - Token to validate
36
- * @param apiBase - API base URL (optional)
45
+ * @param apiBase - API base URL (optional, resolved via resolveApiBase)
37
46
  * @returns true if token is valid
38
47
  */
39
48
  export declare function validateCIToken(token: string, apiBase?: string): Promise<boolean>;
40
49
  /**
41
50
  * Get token info from the API.
42
51
  *
52
+ * Uses apiRequest() from client.ts with the token as explicit API key,
53
+ * so that auth header construction stays centralized in client.ts.
54
+ *
43
55
  * @param token - Token to check
44
- * @param apiBase - API base URL (optional)
56
+ * @param apiBase - API base URL (optional, resolved via resolveApiBase)
45
57
  * @returns Token info or null if invalid/error
46
58
  */
47
59
  export declare function getTokenInfo(token: string, apiBase?: string): Promise<TokenValidationResponse | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"ci-token.d.ts","sourceRoot":"","sources":["../../src/auth/ci-token.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;;;;;GAMG;AACH,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAQ1C;AAED;;GAEG;AACH,UAAU,uBAAuB;IAC/B,6BAA6B;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,MAAyB,GACjC,OAAO,CAAC,OAAO,CAAC,CAoBlB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,MAAyB,GACjC,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAkBzC"}
1
+ {"version":3,"file":"ci-token.d.ts","sourceRoot":"","sources":["../../src/auth/ci-token.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH;;;;;;GAMG;AACH,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAQ1C;AAED;;GAEG;AACH,UAAU,uBAAuB;IAC/B,6BAA6B;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAclB;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAYzC"}
@@ -4,6 +4,7 @@
4
4
  * CI tokens are long-lived API keys used in CI/CD pipelines.
5
5
  * They can be passed via environment variables or --token flag.
6
6
  */
7
+ import { apiRequest, resolveApiBase } from "../utils/client.js";
7
8
  /**
8
9
  * Environment variable names for CI tokens.
9
10
  * Checked in order of preference.
@@ -25,30 +26,20 @@ export function getCIToken() {
25
26
  }
26
27
  return null;
27
28
  }
28
- /**
29
- * Default API base URL.
30
- */
31
- const DEFAULT_API_BASE = "https://vertaaux.ai/v1";
32
29
  /**
33
30
  * Validate a CI token against the API.
34
31
  *
32
+ * Uses apiRequest() from client.ts with the token as explicit API key,
33
+ * so that auth header construction stays centralized in client.ts.
34
+ *
35
35
  * @param token - Token to validate
36
- * @param apiBase - API base URL (optional)
36
+ * @param apiBase - API base URL (optional, resolved via resolveApiBase)
37
37
  * @returns true if token is valid
38
38
  */
39
- export async function validateCIToken(token, apiBase = DEFAULT_API_BASE) {
39
+ export async function validateCIToken(token, apiBase) {
40
40
  try {
41
- const response = await fetch(`${apiBase}/auth/validate`, {
42
- method: "GET",
43
- headers: {
44
- "X-API-Key": token,
45
- "Content-Type": "application/json",
46
- },
47
- });
48
- if (!response.ok) {
49
- return false;
50
- }
51
- const data = (await response.json());
41
+ const base = resolveApiBase(apiBase);
42
+ const data = await apiRequest(base, "/auth/validate", { method: "GET" }, token);
52
43
  return data.valid === true;
53
44
  }
54
45
  catch {
@@ -59,23 +50,17 @@ export async function validateCIToken(token, apiBase = DEFAULT_API_BASE) {
59
50
  /**
60
51
  * Get token info from the API.
61
52
  *
53
+ * Uses apiRequest() from client.ts with the token as explicit API key,
54
+ * so that auth header construction stays centralized in client.ts.
55
+ *
62
56
  * @param token - Token to check
63
- * @param apiBase - API base URL (optional)
57
+ * @param apiBase - API base URL (optional, resolved via resolveApiBase)
64
58
  * @returns Token info or null if invalid/error
65
59
  */
66
- export async function getTokenInfo(token, apiBase = DEFAULT_API_BASE) {
60
+ export async function getTokenInfo(token, apiBase) {
67
61
  try {
68
- const response = await fetch(`${apiBase}/auth/validate`, {
69
- method: "GET",
70
- headers: {
71
- "X-API-Key": token,
72
- "Content-Type": "application/json",
73
- },
74
- });
75
- if (!response.ok) {
76
- return null;
77
- }
78
- return response.json();
62
+ const base = resolveApiBase(apiBase);
63
+ return await apiRequest(base, "/auth/validate", { method: "GET" }, token);
79
64
  }
80
65
  catch {
81
66
  return null;
@@ -59,8 +59,9 @@ export interface DeviceFlowResult {
59
59
  *
60
60
  * @param clientId - OAuth client ID for the CLI
61
61
  * @param authBase - Base URL for auth endpoints (default: https://vertaaux.ai)
62
+ * @param onMessage - Optional callback for displaying messages (defaults to writeOutput)
62
63
  * @returns Device flow result with tokens
63
64
  * @throws Error if authorization fails or times out
64
65
  */
65
- export declare function startDeviceFlow(clientId: string, authBase?: string): Promise<DeviceFlowResult>;
66
+ export declare function startDeviceFlow(clientId: string, authBase?: string, onMessage?: (msg: string) => void): Promise<DeviceFlowResult>;
66
67
  //# sourceMappingURL=device-flow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"device-flow.d.ts","sourceRoot":"","sources":["../../src/auth/device-flow.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,gBAAgB,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mBAAmB;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;CACnB;AAmCD;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,MAA0B,GACnC,OAAO,CAAC,gBAAgB,CAAC,CA6B3B"}
1
+ {"version":3,"file":"device-flow.d.ts","sourceRoot":"","sources":["../../src/auth/device-flow.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,gBAAgB,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mBAAmB;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;CACnB;AAmCD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,MAA0B,EACpC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAChC,OAAO,CAAC,gBAAgB,CAAC,CA+B3B"}
@@ -7,6 +7,7 @@
7
7
  * @see https://datatracker.ietf.org/doc/html/rfc8628
8
8
  */
9
9
  import { createSpinner, succeedSpinner } from "../ui/spinner.js";
10
+ import { writeOutput } from "../output/envelope.js";
10
11
  /**
11
12
  * Format remaining time as MM:SS.
12
13
  */
@@ -33,24 +34,26 @@ const DEFAULT_TIMEOUT_SECONDS = 300;
33
34
  *
34
35
  * @param clientId - OAuth client ID for the CLI
35
36
  * @param authBase - Base URL for auth endpoints (default: https://vertaaux.ai)
37
+ * @param onMessage - Optional callback for displaying messages (defaults to writeOutput)
36
38
  * @returns Device flow result with tokens
37
39
  * @throws Error if authorization fails or times out
38
40
  */
39
- export async function startDeviceFlow(clientId, authBase = DEFAULT_AUTH_BASE) {
41
+ export async function startDeviceFlow(clientId, authBase = DEFAULT_AUTH_BASE, onMessage) {
42
+ const emit = onMessage ?? ((msg) => writeOutput(msg));
40
43
  // Step 1: Request device code
41
44
  const deviceCodeResponse = await requestDeviceCode(clientId, authBase);
42
45
  // Step 2: Display instructions
43
- console.log("\n");
44
- console.log(" To authenticate, visit:");
45
- console.log(` ${deviceCodeResponse.verification_uri}`);
46
- console.log("\n");
47
- console.log(` Enter code: ${deviceCodeResponse.user_code}`);
48
- console.log("\n");
46
+ emit("\n\n");
47
+ emit(" To authenticate, visit:\n");
48
+ emit(` ${deviceCodeResponse.verification_uri}\n`);
49
+ emit("\n");
50
+ emit(` Enter code: ${deviceCodeResponse.user_code}\n`);
51
+ emit("\n");
49
52
  if (deviceCodeResponse.verification_uri_complete) {
50
- console.log(` Or open: ${deviceCodeResponse.verification_uri_complete}`);
51
- console.log("\n");
53
+ emit(` Or open: ${deviceCodeResponse.verification_uri_complete}\n`);
54
+ emit("\n");
52
55
  }
53
- console.log(" Press Ctrl+C to cancel.\n");
56
+ emit(" Press Ctrl+C to cancel.\n\n");
54
57
  // Step 3: Poll for token with countdown
55
58
  const tokens = await pollForToken(clientId, deviceCodeResponse.device_code, deviceCodeResponse.interval, deviceCodeResponse.expires_in, authBase);
56
59
  return tokens;
@@ -1 +1 @@
1
- {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAY/D;AAED;;;;GAIG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAa3D;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAMhD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAUxD"}
1
+ {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB/D;AAED;;;;GAIG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAkB3D;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAMhD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAUxD"}