@vertaaux/cli 0.4.0 → 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.
- package/CHANGELOG.md +97 -0
- package/MIGRATION.md +239 -0
- package/README.md +34 -16
- package/dist/app/interactive-app.d.ts +101 -0
- package/dist/app/interactive-app.d.ts.map +1 -0
- package/dist/app/interactive-app.js +309 -0
- package/dist/app/layout/canvas.d.ts +23 -0
- package/dist/app/layout/canvas.d.ts.map +1 -0
- package/dist/app/layout/canvas.js +36 -0
- package/dist/app/layout/footer.d.ts +31 -0
- package/dist/app/layout/footer.d.ts.map +1 -0
- package/dist/app/layout/footer.js +41 -0
- package/dist/app/layout/header.d.ts +20 -0
- package/dist/app/layout/header.d.ts.map +1 -0
- package/dist/app/layout/header.js +27 -0
- package/dist/app/menu/categories.d.ts +20 -0
- package/dist/app/menu/categories.d.ts.map +1 -0
- package/dist/app/menu/categories.js +181 -0
- package/dist/app/menu/filter.d.ts +17 -0
- package/dist/app/menu/filter.d.ts.map +1 -0
- package/dist/app/menu/filter.js +33 -0
- package/dist/app/menu/menu-view.d.ts +35 -0
- package/dist/app/menu/menu-view.d.ts.map +1 -0
- package/dist/app/menu/menu-view.js +230 -0
- package/dist/app/menu/recent.d.ts +24 -0
- package/dist/app/menu/recent.d.ts.map +1 -0
- package/dist/app/menu/recent.js +49 -0
- package/dist/app/types.d.ts +43 -0
- package/dist/app/types.d.ts.map +1 -0
- package/dist/app/types.js +7 -0
- package/dist/app/views/command-runner.d.ts +36 -0
- package/dist/app/views/command-runner.d.ts.map +1 -0
- package/dist/app/views/command-runner.js +372 -0
- package/dist/app/views/help-overlay.d.ts +21 -0
- package/dist/app/views/help-overlay.d.ts.map +1 -0
- package/dist/app/views/help-overlay.js +45 -0
- package/dist/auth/ci-token.d.ts +8 -2
- package/dist/auth/ci-token.d.ts.map +1 -1
- package/dist/auth/ci-token.js +15 -30
- package/dist/auth/device-flow.d.ts +2 -1
- package/dist/auth/device-flow.d.ts.map +1 -1
- package/dist/auth/device-flow.js +13 -10
- package/dist/auth/token-store.d.ts.map +1 -1
- package/dist/auth/token-store.js +12 -2
- package/dist/baseline/diff.d.ts +2 -2
- package/dist/baseline/diff.d.ts.map +1 -1
- package/dist/baseline/diff.js +15 -34
- package/dist/commands/a11y.d.ts +9 -0
- package/dist/commands/a11y.d.ts.map +1 -0
- package/dist/commands/a11y.js +76 -0
- package/dist/commands/audit/artifacts.d.ts +27 -0
- package/dist/commands/audit/artifacts.d.ts.map +1 -0
- package/dist/commands/audit/artifacts.js +158 -0
- package/dist/commands/audit/ci-detection.d.ts +18 -0
- package/dist/commands/audit/ci-detection.d.ts.map +1 -0
- package/dist/commands/audit/ci-detection.js +71 -0
- package/dist/commands/audit/explain.d.ts +11 -0
- package/dist/commands/audit/explain.d.ts.map +1 -0
- package/dist/commands/audit/explain.js +45 -0
- package/dist/commands/audit/filters.d.ts +17 -0
- package/dist/commands/audit/filters.d.ts.map +1 -0
- package/dist/commands/audit/filters.js +40 -0
- package/dist/commands/audit/index.d.ts +18 -0
- package/dist/commands/audit/index.d.ts.map +1 -0
- package/dist/commands/audit/index.js +564 -0
- package/dist/commands/audit/output.d.ts +32 -0
- package/dist/commands/audit/output.d.ts.map +1 -0
- package/dist/commands/audit/output.js +130 -0
- package/dist/commands/audit/policy.d.ts +19 -0
- package/dist/commands/audit/policy.d.ts.map +1 -0
- package/dist/commands/audit/policy.js +102 -0
- package/dist/commands/audit/scoring.d.ts +23 -0
- package/dist/commands/audit/scoring.d.ts.map +1 -0
- package/dist/commands/audit/scoring.js +70 -0
- package/dist/commands/audit/types.d.ts +88 -0
- package/dist/commands/audit/types.d.ts.map +1 -0
- package/dist/commands/audit/types.js +8 -0
- package/dist/commands/audit.d.ts +2 -60
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +2 -1097
- package/dist/commands/baseline.d.ts +1 -0
- package/dist/commands/baseline.d.ts.map +1 -1
- package/dist/commands/baseline.js +205 -121
- package/dist/commands/comment.d.ts +22 -0
- package/dist/commands/comment.d.ts.map +1 -1
- package/dist/commands/comment.js +122 -58
- package/dist/commands/compare.d.ts +17 -0
- package/dist/commands/compare.d.ts.map +1 -1
- package/dist/commands/compare.js +287 -180
- package/dist/commands/diff.d.ts +5 -0
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +168 -141
- package/dist/commands/doc.d.ts +10 -0
- package/dist/commands/doc.d.ts.map +1 -1
- package/dist/commands/doc.js +134 -76
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +164 -17
- package/dist/commands/download.d.ts +10 -0
- package/dist/commands/download.d.ts.map +1 -1
- package/dist/commands/download.js +169 -112
- package/dist/commands/explain.d.ts +5 -0
- package/dist/commands/explain.d.ts.map +1 -1
- package/dist/commands/explain.js +241 -155
- package/dist/commands/fix-all.d.ts +25 -0
- package/dist/commands/fix-all.d.ts.map +1 -0
- package/dist/commands/fix-all.js +206 -0
- package/dist/commands/fix-plan.d.ts +9 -0
- package/dist/commands/fix-plan.d.ts.map +1 -1
- package/dist/commands/fix-plan.js +152 -89
- package/dist/commands/fix.d.ts +17 -0
- package/dist/commands/fix.d.ts.map +1 -0
- package/dist/commands/fix.js +111 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +94 -42
- package/dist/commands/login.d.ts +18 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +263 -92
- package/dist/commands/patch-review.d.ts +11 -0
- package/dist/commands/patch-review.d.ts.map +1 -1
- package/dist/commands/patch-review.js +159 -97
- package/dist/commands/policy.d.ts +31 -0
- package/dist/commands/policy.d.ts.map +1 -1
- package/dist/commands/policy.js +269 -124
- package/dist/commands/release-notes.d.ts +10 -0
- package/dist/commands/release-notes.d.ts.map +1 -1
- package/dist/commands/release-notes.js +127 -73
- package/dist/commands/scan.d.ts +13 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +133 -0
- package/dist/commands/status.d.ts +9 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +81 -0
- package/dist/commands/suggest.d.ts +10 -0
- package/dist/commands/suggest.d.ts.map +1 -1
- package/dist/commands/suggest.js +153 -82
- package/dist/commands/triage.d.ts +35 -0
- package/dist/commands/triage.d.ts.map +1 -1
- package/dist/commands/triage.js +206 -81
- package/dist/commands/upload.d.ts +9 -0
- package/dist/commands/upload.d.ts.map +1 -1
- package/dist/commands/upload.js +140 -101
- package/dist/commands/verify.d.ts +13 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +118 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +125 -990
- package/dist/interactive/fix-wizard.d.ts +3 -0
- package/dist/interactive/fix-wizard.d.ts.map +1 -1
- package/dist/interactive/fix-wizard.js +130 -112
- package/dist/interactive/init-wizard.d.ts +3 -1
- package/dist/interactive/init-wizard.d.ts.map +1 -1
- package/dist/interactive/init-wizard.js +207 -138
- package/dist/interactive/prompts.d.ts +7 -3
- package/dist/interactive/prompts.d.ts.map +1 -1
- package/dist/interactive/prompts.js +44 -23
- package/dist/output/envelope.d.ts +2 -0
- package/dist/output/envelope.d.ts.map +1 -1
- package/dist/output/envelope.js +18 -2
- package/dist/output/factory.d.ts +2 -1
- package/dist/output/factory.d.ts.map +1 -1
- package/dist/output/html.d.ts +2 -1
- package/dist/output/html.d.ts.map +1 -1
- package/dist/output/html.js +3 -2
- package/dist/output/human.d.ts +2 -1
- package/dist/output/human.d.ts.map +1 -1
- package/dist/output/human.js +3 -2
- package/dist/output/json.d.ts +2 -1
- package/dist/output/json.d.ts.map +1 -1
- package/dist/output/junit.d.ts +2 -1
- package/dist/output/junit.d.ts.map +1 -1
- package/dist/output/sarif.d.ts +2 -1
- package/dist/output/sarif.d.ts.map +1 -1
- package/dist/types.d.ts +74 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/ui/banner.d.ts +34 -0
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +97 -5
- package/dist/ui/diagnostics.d.ts +9 -4
- package/dist/ui/diagnostics.d.ts.map +1 -1
- package/dist/ui/diagnostics.js +32 -82
- package/dist/ui/strings.d.ts +373 -0
- package/dist/ui/strings.d.ts.map +1 -0
- package/dist/ui/strings.js +499 -0
- package/dist/ui/table.d.ts +0 -2
- package/dist/ui/table.d.ts.map +1 -1
- package/dist/ui/table.js +3 -4
- package/dist/utils/api-client.d.ts +46 -0
- package/dist/utils/api-client.d.ts.map +1 -0
- package/dist/utils/api-client.js +170 -0
- package/dist/utils/client.d.ts +29 -18
- package/dist/utils/client.d.ts.map +1 -1
- package/dist/utils/client.js +102 -12
- package/dist/utils/formatters.d.ts +38 -0
- package/dist/utils/formatters.d.ts.map +1 -0
- package/dist/utils/formatters.js +277 -0
- package/dist/utils/url-classify.d.ts.map +1 -1
- package/dist/utils/url-classify.js +24 -3
- package/node_modules/@vertaaux/tui/dist/index.cjs +713 -20
- package/node_modules/@vertaaux/tui/dist/index.cjs.map +1 -1
- package/node_modules/@vertaaux/tui/dist/index.d.cts +361 -4
- package/node_modules/@vertaaux/tui/dist/index.d.ts +361 -4
- package/node_modules/@vertaaux/tui/dist/index.js +689 -21
- package/node_modules/@vertaaux/tui/dist/index.js.map +1 -1
- package/package.json +13 -5
- package/dist/commands/client.d.ts +0 -14
- package/dist/commands/client.d.ts.map +0 -1
- package/dist/commands/client.js +0 -362
- package/dist/commands/drift.d.ts +0 -15
- package/dist/commands/drift.d.ts.map +0 -1
- package/dist/commands/drift.js +0 -309
- package/dist/commands/protect.d.ts +0 -16
- package/dist/commands/protect.d.ts.map +0 -1
- package/dist/commands/protect.js +0 -323
- package/dist/commands/report.d.ts +0 -15
- package/dist/commands/report.d.ts.map +0 -1
- package/dist/commands/report.js +0 -214
- package/dist/policy/sync.d.ts +0 -67
- package/dist/policy/sync.d.ts.map +0 -1
- package/dist/policy/sync.js +0 -147
package/dist/commands/init.js
CHANGED
|
@@ -6,13 +6,15 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import fs from "fs";
|
|
8
8
|
import path from "path";
|
|
9
|
-
import
|
|
9
|
+
import { colorize, brand, renderError, renderWarning, runSteps, createRenderer } from "@vertaaux/tui";
|
|
10
10
|
import yaml from "yaml";
|
|
11
11
|
import { runInitWizard } from "../interactive/init-wizard.js";
|
|
12
12
|
import { isInteractive } from "../interactive/prompts.js";
|
|
13
13
|
import { ExitCode } from "../utils/exit-codes.js";
|
|
14
14
|
import { parseThreshold, parseFailOn } from "../utils/validators.js";
|
|
15
15
|
import { generateTemplate } from "../templates/index.js";
|
|
16
|
+
import { writeOutput } from "../output/envelope.js";
|
|
17
|
+
import { strings } from "../ui/strings.js";
|
|
16
18
|
/**
|
|
17
19
|
* Config file path.
|
|
18
20
|
*/
|
|
@@ -109,17 +111,35 @@ function checkExisting(filePath) {
|
|
|
109
111
|
/**
|
|
110
112
|
* Handle the init command.
|
|
111
113
|
*/
|
|
112
|
-
async function handleInit(options) {
|
|
114
|
+
export async function handleInit(options) {
|
|
113
115
|
// Check for existing config
|
|
114
116
|
if (checkExisting(CONFIG_FILE) && !options.force) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
process.stderr.write(renderWarning({
|
|
118
|
+
message: strings.init.configExists(CONFIG_FILE),
|
|
119
|
+
suggestion: "vertaa init --force",
|
|
120
|
+
}) + "\n");
|
|
117
121
|
process.exit(ExitCode.ERROR);
|
|
118
122
|
}
|
|
119
|
-
|
|
123
|
+
const renderer = createRenderer("auto");
|
|
124
|
+
const baseState = {
|
|
125
|
+
phase: "init",
|
|
126
|
+
phaseIndex: 1,
|
|
127
|
+
phaseTotal: 1,
|
|
128
|
+
url: "",
|
|
129
|
+
mode: "init",
|
|
130
|
+
progress: {},
|
|
131
|
+
totals: {},
|
|
132
|
+
issueCount: 0,
|
|
133
|
+
scorePreview: null,
|
|
134
|
+
verbose: false,
|
|
135
|
+
elapsed: 0,
|
|
136
|
+
};
|
|
137
|
+
const startTime = Date.now();
|
|
138
|
+
let config = null;
|
|
139
|
+
const outputLines = [];
|
|
120
140
|
// Determine configuration source
|
|
121
141
|
if (options.yes || !isInteractive()) {
|
|
122
|
-
// Use defaults
|
|
142
|
+
// Use defaults — skip interactive wizard
|
|
123
143
|
config = {
|
|
124
144
|
mode: "standard",
|
|
125
145
|
failOn: options.failOn || "error",
|
|
@@ -129,17 +149,20 @@ async function handleInit(options) {
|
|
|
129
149
|
};
|
|
130
150
|
}
|
|
131
151
|
else {
|
|
132
|
-
// Run interactive wizard
|
|
152
|
+
// Run interactive wizard (suspend/resume renderer around prompts)
|
|
153
|
+
renderer.suspend?.();
|
|
133
154
|
try {
|
|
134
155
|
config = await runInitWizard();
|
|
135
156
|
}
|
|
136
157
|
catch (error) {
|
|
158
|
+
renderer.resume?.();
|
|
137
159
|
if (error instanceof Error && error.message.includes("cancelled")) {
|
|
138
|
-
|
|
160
|
+
writeOutput(strings.init.cancelled);
|
|
139
161
|
process.exit(0);
|
|
140
162
|
}
|
|
141
163
|
throw error;
|
|
142
164
|
}
|
|
165
|
+
renderer.resume?.();
|
|
143
166
|
}
|
|
144
167
|
// Override with explicit flags
|
|
145
168
|
if (options.ci) {
|
|
@@ -151,42 +174,67 @@ async function handleInit(options) {
|
|
|
151
174
|
if (options.threshold !== undefined) {
|
|
152
175
|
config.threshold = options.threshold;
|
|
153
176
|
}
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
177
|
+
const resolvedConfig = config;
|
|
178
|
+
const steps = [
|
|
179
|
+
{
|
|
180
|
+
id: "detect",
|
|
181
|
+
actionText: "Detecting project configuration...",
|
|
182
|
+
summaryText: "Configuration detected",
|
|
183
|
+
run: async () => {
|
|
184
|
+
// Create .vertaaux directory
|
|
185
|
+
const baselineDir = path.resolve(process.cwd(), BASELINE_DIR);
|
|
186
|
+
if (!fs.existsSync(baselineDir)) {
|
|
187
|
+
fs.mkdirSync(baselineDir, { recursive: true });
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
id: "write",
|
|
193
|
+
actionText: "Writing configuration file...",
|
|
194
|
+
summaryText: "Configuration saved",
|
|
195
|
+
run: async () => {
|
|
196
|
+
// Write config file
|
|
197
|
+
const yamlContent = configToYaml(resolvedConfig);
|
|
198
|
+
writeFile(CONFIG_FILE, yamlContent);
|
|
199
|
+
outputLines.push(colorize(strings.init.configCreated(CONFIG_FILE), brand.lime));
|
|
200
|
+
// Generate CI template if selected
|
|
201
|
+
if (resolvedConfig.ciProvider !== "none") {
|
|
202
|
+
const template = getCITemplate(resolvedConfig.ciProvider, resolvedConfig);
|
|
203
|
+
if (template) {
|
|
204
|
+
writeFile(template.path, template.content);
|
|
205
|
+
outputLines.push(colorize(strings.init.templateCreated(template.path), brand.lime));
|
|
206
|
+
// Show instructions if provided by template generator
|
|
207
|
+
if (template.instructions) {
|
|
208
|
+
outputLines.push("");
|
|
209
|
+
outputLines.push(colorize(strings.init.templateNote(template.instructions), brand.cyan));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
];
|
|
216
|
+
await runSteps(steps, {
|
|
217
|
+
failFast: true,
|
|
218
|
+
onStateChange: (stepStates) => {
|
|
219
|
+
renderer.update({ ...baseState, stepStates, elapsed: Date.now() - startTime });
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
renderer.finish({ url: "", mode: "init", overallScore: 0, scores: {}, issueCount: 0, passed: true, elapsed: Date.now() - startTime });
|
|
176
223
|
// Success message
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (
|
|
183
|
-
|
|
224
|
+
outputLines.push("");
|
|
225
|
+
outputLines.push(colorize(strings.init.success, brand.lime));
|
|
226
|
+
outputLines.push("");
|
|
227
|
+
outputLines.push(strings.init.nextStepsHeader);
|
|
228
|
+
outputLines.push(` 1. ${colorize(strings.init.nextSteps.runAudit, brand.cyan)}`);
|
|
229
|
+
if (resolvedConfig.ciProvider === "github") {
|
|
230
|
+
outputLines.push(` 2. ${colorize(strings.init.nextSteps.addGithubSecret, brand.cyan)}`);
|
|
184
231
|
}
|
|
185
|
-
else if (
|
|
186
|
-
|
|
232
|
+
else if (resolvedConfig.ciProvider !== "none") {
|
|
233
|
+
outputLines.push(` 2. ${colorize(strings.init.nextSteps.addCISecret, brand.cyan)}`);
|
|
187
234
|
}
|
|
188
|
-
|
|
189
|
-
|
|
235
|
+
outputLines.push(` 3. ${colorize(strings.init.nextSteps.createBaseline, brand.cyan)}`);
|
|
236
|
+
outputLines.push("");
|
|
237
|
+
writeOutput(outputLines.join("\n"));
|
|
190
238
|
}
|
|
191
239
|
/**
|
|
192
240
|
* Register the init command with the Commander program.
|
|
@@ -205,7 +253,11 @@ export function registerInitCommand(program) {
|
|
|
205
253
|
await handleInit(options);
|
|
206
254
|
}
|
|
207
255
|
catch (error) {
|
|
208
|
-
|
|
256
|
+
process.stderr.write(renderError({
|
|
257
|
+
message: error instanceof Error ? error.message : String(error),
|
|
258
|
+
suggestion: "vertaa init --force",
|
|
259
|
+
exitCode: ExitCode.ERROR,
|
|
260
|
+
}) + "\n");
|
|
209
261
|
process.exit(ExitCode.ERROR);
|
|
210
262
|
}
|
|
211
263
|
});
|
package/dist/commands/login.d.ts
CHANGED
|
@@ -7,6 +7,24 @@
|
|
|
7
7
|
* - vertaa whoami: Show current authentication status
|
|
8
8
|
*/
|
|
9
9
|
import type { Command } from "commander";
|
|
10
|
+
/**
|
|
11
|
+
* Handle the login command.
|
|
12
|
+
*/
|
|
13
|
+
export declare function handleLogin(options: {
|
|
14
|
+
token?: string;
|
|
15
|
+
sso?: boolean;
|
|
16
|
+
base?: string;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Handle the logout command.
|
|
20
|
+
*/
|
|
21
|
+
export declare function handleLogout(): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Handle the whoami command.
|
|
24
|
+
*/
|
|
25
|
+
export declare function handleWhoami(options: {
|
|
26
|
+
base?: string;
|
|
27
|
+
}): Promise<void>;
|
|
10
28
|
/**
|
|
11
29
|
* Register authentication commands with the Commander program.
|
|
12
30
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgDzC;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,IAAI,CAAC,CAgKhB;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAiDlD;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkI5E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgE3D"}
|