appsec-agent 2.4.5 → 2.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.
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Codebase-graph context input (v2.6.0 / parent-app plan §8.18 Phase 2) —
3
+ * per-changed-file structural-graph summary passed to `pr_reviewer` so the LLM
4
+ * can factor symbol-level callers/callees and downstream blast-radius into its
5
+ * severity + confidence calls.
6
+ *
7
+ * Distinct from `--import-graph-context` (file-level inbound import counts via
8
+ * SCIP). This context is *symbol-level* (cbm tree-sitter graph; 155 languages):
9
+ * - `callers` — qualified symbol names whose body invokes a symbol
10
+ * defined in the changed file.
11
+ * - `callees` — qualified symbol names invoked from a symbol defined
12
+ * in the changed file.
13
+ * - `blast_radius_files_count` — number of unique files reachable via
14
+ * outbound CALLS edges within the configured depth.
15
+ *
16
+ * The parent app's `composeCodebaseGraphContextPayload`
17
+ * (`<parent-app>/backend/src/services/codebaseGraph/`) does the cbm MCP queries
18
+ * (`search_graph` to find symbols defined in each changed file →
19
+ * `trace_path(direction=both, mode=calls, depth=2)` per symbol) and writes the
20
+ * JSON file. The agent here only parses + formats it for the prompt — no MCP
21
+ * query at agent runtime (Phase 3 is the live-MCP variant).
22
+ *
23
+ * Shape mirrors the v5.4.0 import-graph and v2.3.0 runtime-enrichment patterns
24
+ * exactly so that `prScanProcessor` can reuse the same fail-open + size-cap +
25
+ * coverage tagging conventions across all three structural-context families.
26
+ *
27
+ * **§8.5 PHI gate**: cbm sees only source-code text from CapsuleHealth-owned
28
+ * repos (no PHI). The schema accepts only structural-edge fields; any extras
29
+ * on per-file entries are silently dropped (mirrors runtime-enrichment's PHI
30
+ * minimization invariant defensively, even though cbm's input surface
31
+ * cannot contain PHI by construction).
32
+ */
33
+ export interface CodebaseGraphFileEntry {
34
+ /** Repository-relative file path. Must be non-empty after trimming. */
35
+ file: string;
36
+ /**
37
+ * Optional list of qualified symbol names defined in this file that the PR
38
+ * actually changes. When present, the parent app scoped the
39
+ * callers/callees query to these symbols only (instead of every symbol
40
+ * defined in the file). Truncated at 20 to bound the prompt budget.
41
+ */
42
+ symbols_changed?: string[];
43
+ /**
44
+ * Inbound callers — qualified symbol names whose body invokes a symbol
45
+ * defined in this file. Truncated at 20 (most-popular first per the
46
+ * parent app's ranking) so the most structurally-important callers
47
+ * survive the prompt-budget cap.
48
+ */
49
+ callers?: string[];
50
+ /**
51
+ * Outbound callees — qualified symbol names invoked from any symbol
52
+ * defined in this file. Same truncation contract as `callers`.
53
+ */
54
+ callees?: string[];
55
+ /**
56
+ * Number of unique files reachable from this file via outbound CALLS
57
+ * edges within the parent app's configured `trace_path` depth (default
58
+ * 2). The LLM uses this as a "blast radius" signal — high counts
59
+ * indicate the changed file sits structurally upstream of much of the
60
+ * codebase, so a regression here propagates broadly.
61
+ *
62
+ * Coerced to a non-negative integer (fractional values floored,
63
+ * negatives clamped to 0).
64
+ */
65
+ blast_radius_files_count: number;
66
+ /**
67
+ * Per-file resolution outcome:
68
+ * - `ok` — symbols found in cbm graph; callers/callees populated
69
+ * from `trace_path` results.
70
+ * - `no_symbols` — file is in the changed set but cbm's `search_graph`
71
+ * returned no Function/Method nodes for it (data file,
72
+ * config, generated code, language not in cbm's 155).
73
+ * - `missing` — cbm artifact for the project's current head SHA was
74
+ * not found on the PVC; the parent app's load step
75
+ * short-circuited with an empty entry per file.
76
+ * - `partial` — at least one `trace_path` query failed (cbm
77
+ * transient error, depth limit, or query timeout); the
78
+ * callers/callees lists may be incomplete.
79
+ */
80
+ graph_status?: 'ok' | 'no_symbols' | 'missing' | 'partial';
81
+ }
82
+ export interface CodebaseGraphContext {
83
+ /** Optional default-branch SHA the cbm artifact was indexed from. */
84
+ default_branch_sha?: string;
85
+ /**
86
+ * Optional ISO-8601 timestamp recorded when the parent app composed
87
+ * this payload. Useful for forensic debugging if the soak shows
88
+ * unexpected behavior; not surfaced in the prompt.
89
+ */
90
+ parsed_at?: string;
91
+ /**
92
+ * Roll-up resolution status across all files in the request:
93
+ * - `full` — every changed file was found in the cbm graph and at
94
+ * least one symbol traced.
95
+ * - `partial` — some files traced cleanly, others were `no_symbols` or
96
+ * `partial`.
97
+ * - `none` — the cbm artifact was loaded but no changed file
98
+ * produced traceable symbols (highly unusual; surface
99
+ * to ops via `coverage` panel).
100
+ * - `empty` — the parent app could not load a cbm artifact for the
101
+ * current head SHA (`codebase_graph_heads` row missing
102
+ * or stale). Fail-open; the LLM ignores this block.
103
+ */
104
+ coverage?: 'full' | 'partial' | 'none' | 'empty';
105
+ /**
106
+ * Per-file rows — already filtered by the parent app to the PR's
107
+ * changed-file set, so the LLM sees a compact "files touched by this
108
+ * PR with their structural-graph context" slice. Empty array means
109
+ * "graph configured but no overlap" — the formatter short-circuits
110
+ * to empty string in that case.
111
+ */
112
+ files: CodebaseGraphFileEntry[];
113
+ /** Optional metadata block for forensic/debug correlation; not surfaced in prompt. */
114
+ metadata?: {
115
+ project_name?: string;
116
+ };
117
+ }
118
+ /**
119
+ * Parse and validate a codebase-graph context JSON payload (throws on
120
+ * structural error). Caps mirror import-graph (500 files, 20 callers per
121
+ * file) so the prompt-budget worst case is symmetric across the two
122
+ * structural contexts.
123
+ */
124
+ export declare function parseCodebaseGraphContext(data: unknown): CodebaseGraphContext;
125
+ /**
126
+ * Format the context for inclusion in a PR-reviewer user prompt. Compact by
127
+ * design — symbol lists are truncated and the table renders only the most
128
+ * structurally-significant signals so the block stays well under the
129
+ * import-graph + runtime-enrichment budget envelope.
130
+ *
131
+ * Files are rendered most-blast-radius first to anchor the LLM's attention
132
+ * on the structurally-upstream files when the prompt is truncated.
133
+ */
134
+ export declare function formatCodebaseGraphContextForPrompt(ctx: CodebaseGraphContext): string;
135
+ //# sourceMappingURL=codebase_graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codebase_graph.d.ts","sourceRoot":"","sources":["../../../src/schemas/codebase_graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;;;;;OASG;IACH,wBAAwB,EAAE,MAAM,CAAC;IACjC;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE,IAAI,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;CAC5D;AAED,MAAM,WAAW,oBAAoB;IACnC,qEAAqE;IACrE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;IACjD;;;;;;OAMG;IACH,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC,sFAAsF;IACtF,QAAQ,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACtC;AA+BD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG,oBAAoB,CA8D7E;AAED;;;;;;;;GAQG;AACH,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,oBAAoB,GAAG,MAAM,CAkDrF"}
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ /**
3
+ * Codebase-graph context input (v2.6.0 / parent-app plan §8.18 Phase 2) —
4
+ * per-changed-file structural-graph summary passed to `pr_reviewer` so the LLM
5
+ * can factor symbol-level callers/callees and downstream blast-radius into its
6
+ * severity + confidence calls.
7
+ *
8
+ * Distinct from `--import-graph-context` (file-level inbound import counts via
9
+ * SCIP). This context is *symbol-level* (cbm tree-sitter graph; 155 languages):
10
+ * - `callers` — qualified symbol names whose body invokes a symbol
11
+ * defined in the changed file.
12
+ * - `callees` — qualified symbol names invoked from a symbol defined
13
+ * in the changed file.
14
+ * - `blast_radius_files_count` — number of unique files reachable via
15
+ * outbound CALLS edges within the configured depth.
16
+ *
17
+ * The parent app's `composeCodebaseGraphContextPayload`
18
+ * (`<parent-app>/backend/src/services/codebaseGraph/`) does the cbm MCP queries
19
+ * (`search_graph` to find symbols defined in each changed file →
20
+ * `trace_path(direction=both, mode=calls, depth=2)` per symbol) and writes the
21
+ * JSON file. The agent here only parses + formats it for the prompt — no MCP
22
+ * query at agent runtime (Phase 3 is the live-MCP variant).
23
+ *
24
+ * Shape mirrors the v5.4.0 import-graph and v2.3.0 runtime-enrichment patterns
25
+ * exactly so that `prScanProcessor` can reuse the same fail-open + size-cap +
26
+ * coverage tagging conventions across all three structural-context families.
27
+ *
28
+ * **§8.5 PHI gate**: cbm sees only source-code text from CapsuleHealth-owned
29
+ * repos (no PHI). The schema accepts only structural-edge fields; any extras
30
+ * on per-file entries are silently dropped (mirrors runtime-enrichment's PHI
31
+ * minimization invariant defensively, even though cbm's input surface
32
+ * cannot contain PHI by construction).
33
+ */
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.parseCodebaseGraphContext = parseCodebaseGraphContext;
36
+ exports.formatCodebaseGraphContextForPrompt = formatCodebaseGraphContextForPrompt;
37
+ const MAX_FILES = 500;
38
+ const MAX_CALLERS_PER_FILE = 20;
39
+ const MAX_CALLEES_PER_FILE = 20;
40
+ const MAX_SYMBOLS_PER_FILE = 20;
41
+ const VALID_GRAPH_STATUSES = new Set([
42
+ 'ok',
43
+ 'no_symbols',
44
+ 'missing',
45
+ 'partial',
46
+ ]);
47
+ const VALID_COVERAGE_VALUES = new Set([
48
+ 'full',
49
+ 'partial',
50
+ 'none',
51
+ 'empty',
52
+ ]);
53
+ const sanitizeStringArray = (input, cap) => {
54
+ if (!Array.isArray(input)) {
55
+ return undefined;
56
+ }
57
+ const cleaned = input
58
+ .filter((c) => typeof c === 'string' && c.trim().length > 0)
59
+ .slice(0, cap);
60
+ return cleaned.length > 0 ? cleaned : undefined;
61
+ };
62
+ /**
63
+ * Parse and validate a codebase-graph context JSON payload (throws on
64
+ * structural error). Caps mirror import-graph (500 files, 20 callers per
65
+ * file) so the prompt-budget worst case is symmetric across the two
66
+ * structural contexts.
67
+ */
68
+ function parseCodebaseGraphContext(data) {
69
+ if (!data || typeof data !== 'object') {
70
+ throw new Error('Codebase-graph context must be a JSON object');
71
+ }
72
+ const o = data;
73
+ if (!Array.isArray(o.files)) {
74
+ throw new Error('Codebase-graph context must include a "files" array');
75
+ }
76
+ if (o.files.length > MAX_FILES) {
77
+ throw new Error(`Codebase-graph context supports at most ${MAX_FILES} files per run`);
78
+ }
79
+ const files = [];
80
+ for (const item of o.files) {
81
+ if (!item || typeof item !== 'object') {
82
+ throw new Error('Each codebase-graph file entry must be an object');
83
+ }
84
+ const f = item;
85
+ if (typeof f.file !== 'string' || !f.file.trim()) {
86
+ throw new Error('Each codebase-graph file entry must have a non-empty string "file"');
87
+ }
88
+ if (typeof f.blast_radius_files_count !== 'number' ||
89
+ !Number.isFinite(f.blast_radius_files_count)) {
90
+ throw new Error('Each codebase-graph file entry must have a numeric "blast_radius_files_count"');
91
+ }
92
+ const graphStatus = typeof f.graph_status === 'string' &&
93
+ VALID_GRAPH_STATUSES.has(f.graph_status)
94
+ ? f.graph_status
95
+ : undefined;
96
+ files.push({
97
+ file: String(f.file),
98
+ symbols_changed: sanitizeStringArray(f.symbols_changed, MAX_SYMBOLS_PER_FILE),
99
+ callers: sanitizeStringArray(f.callers, MAX_CALLERS_PER_FILE),
100
+ callees: sanitizeStringArray(f.callees, MAX_CALLEES_PER_FILE),
101
+ blast_radius_files_count: Math.max(0, Math.trunc(f.blast_radius_files_count)),
102
+ graph_status: graphStatus,
103
+ });
104
+ }
105
+ const coverage = typeof o.coverage === 'string' &&
106
+ VALID_COVERAGE_VALUES.has(o.coverage)
107
+ ? o.coverage
108
+ : undefined;
109
+ return {
110
+ default_branch_sha: typeof o.default_branch_sha === 'string' ? o.default_branch_sha : undefined,
111
+ parsed_at: typeof o.parsed_at === 'string' ? o.parsed_at : undefined,
112
+ coverage,
113
+ files,
114
+ metadata: o.metadata && typeof o.metadata === 'object'
115
+ ? {
116
+ project_name: typeof o.metadata.project_name === 'string'
117
+ ? o.metadata.project_name
118
+ : undefined,
119
+ }
120
+ : undefined,
121
+ };
122
+ }
123
+ /**
124
+ * Format the context for inclusion in a PR-reviewer user prompt. Compact by
125
+ * design — symbol lists are truncated and the table renders only the most
126
+ * structurally-significant signals so the block stays well under the
127
+ * import-graph + runtime-enrichment budget envelope.
128
+ *
129
+ * Files are rendered most-blast-radius first to anchor the LLM's attention
130
+ * on the structurally-upstream files when the prompt is truncated.
131
+ */
132
+ function formatCodebaseGraphContextForPrompt(ctx) {
133
+ if (ctx.files.length === 0) {
134
+ return '';
135
+ }
136
+ const sorted = [...ctx.files].sort((a, b) => b.blast_radius_files_count - a.blast_radius_files_count);
137
+ const lines = [];
138
+ lines.push('### Codebase-graph context (symbol-level callers/callees, plan §8.18 Phase 2)');
139
+ lines.push('For each changed file below, the parent app queried the codebase-memory-mcp graph for symbols defined in the file and traced their inbound (callers) and outbound (callees) CALLS edges. Use this as a structural-impact signal: a high `blast radius` means a regression in the file propagates to many downstream files; a non-empty `callers` list means the changed code is reached by other code paths and is more likely to fire under realistic traffic.');
140
+ lines.push('Treat this as advisory — when callers ≥ 1 and blast radius ≥ 5, lean toward keeping medium/high-severity findings on the file even if the diff alone looks low-risk. When `graph_status` is `no_symbols` (data file, generated code, unsupported language), structural reach is not measurable from this signal — fall back to your default judgment.');
141
+ if (ctx.default_branch_sha) {
142
+ lines.push(`Graph built from default-branch SHA \`${ctx.default_branch_sha.slice(0, 12)}\`.`);
143
+ }
144
+ if (ctx.coverage && ctx.coverage !== 'full') {
145
+ lines.push(`_Coverage: **${ctx.coverage}** — entries with \`graph_status=missing\` or \`partial\` will **not** be downranked (fail-open)._`);
146
+ }
147
+ lines.push('');
148
+ lines.push('| File | Callers | Callees | Blast radius | Status |');
149
+ lines.push('|---|---|---|---:|:---:|');
150
+ for (const f of sorted) {
151
+ const status = f.graph_status ?? 'ok';
152
+ const callers = f.callers && f.callers.length > 0
153
+ ? f.callers
154
+ .slice(0, 3)
155
+ .map((c) => `\`${c}\``)
156
+ .join(', ') + (f.callers.length > 3 ? ` (+${f.callers.length - 3})` : '')
157
+ : '—';
158
+ const callees = f.callees && f.callees.length > 0
159
+ ? f.callees
160
+ .slice(0, 3)
161
+ .map((c) => `\`${c}\``)
162
+ .join(', ') + (f.callees.length > 3 ? ` (+${f.callees.length - 3})` : '')
163
+ : '—';
164
+ lines.push(`| \`${f.file}\` | ${callers} | ${callees} | ${f.blast_radius_files_count} | ${status} |`);
165
+ }
166
+ lines.push('');
167
+ return lines.join('\n');
168
+ }
169
+ //# sourceMappingURL=codebase_graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codebase_graph.js","sourceRoot":"","sources":["../../../src/schemas/codebase_graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Learned-guidance synthesizer schemas (v2.5.0 / parent-app plan §3.8 — CLLG).
3
+ *
4
+ * The parent app collects three signal streams (dismissal validations,
5
+ * `addressed` PR outcomes, 👍 feedback) and buckets them by CWE. For each
6
+ * eligible bucket it asks this role to emit ONE short policy bullet that
7
+ * captures the class-level pattern (e.g. *"Trust the CSRF middleware in
8
+ * `auth/csrf.ts`; do not flag PR routes that go through it."*).
9
+ *
10
+ * Input file shape (passed via `--inputs <file>`; matches the JSON the
11
+ * parent app's `runSynthesizerAgent` writes in `learnedGuidanceSynthesizer.ts`):
12
+ *
13
+ * {
14
+ * "buckets": [
15
+ * {
16
+ * "cwe": "CWE-79",
17
+ * "signal_count": 12,
18
+ * "example_dismissal_reasons": [
19
+ * "duplicate of issue #4321 - already mitigated by helmet middleware",
20
+ * "auto-escaped by React JSX",
21
+ * ...
22
+ * ]
23
+ * },
24
+ * ...
25
+ * ]
26
+ * }
27
+ *
28
+ * Output shape on stdout (structured JSON, written to `-o <file>` per the
29
+ * parent app's spawn contract; backend rejects anything off-schema with
30
+ * `outcome=validation_error`):
31
+ *
32
+ * {
33
+ * "bullets": [
34
+ * {
35
+ * "cwe": "CWE-79",
36
+ * "bullet": "≤300 chars positive-form rule the pr_reviewer can apply",
37
+ * "confidence": 0.85
38
+ * },
39
+ * ...
40
+ * ]
41
+ * }
42
+ *
43
+ * The role is a pure transform: no Read/Grep tools, no source-tree
44
+ * access. Output is constrained by `LEARNED_GUIDANCE_OUTPUT_SCHEMA` so a
45
+ * malformed bullet list never reaches the parent app's prompt budget.
46
+ */
47
+ export interface LearnedGuidanceBucketInput {
48
+ cwe: string;
49
+ signal_count: number;
50
+ example_dismissal_reasons: string[];
51
+ }
52
+ export interface LearnedGuidanceInputs {
53
+ buckets: LearnedGuidanceBucketInput[];
54
+ }
55
+ /** Output character cap. Stays in lockstep with the parent app's `MAX_BULLET_LEN = 300`. */
56
+ export declare const MAX_BULLET_LEN = 300;
57
+ export interface LearnedGuidanceBullet {
58
+ cwe: string;
59
+ bullet: string;
60
+ confidence: number;
61
+ }
62
+ export interface LearnedGuidanceOutput {
63
+ bullets: LearnedGuidanceBullet[];
64
+ }
65
+ /**
66
+ * Parse and validate a `LearnedGuidanceInputs` object loaded from the
67
+ * `--inputs` JSON file. Throws on any structural deviation; the CLI
68
+ * wrapper in `main.ts` exits non-zero so the parent app sees the error
69
+ * via stderr (and stays fail-closed: zero bullets persisted).
70
+ */
71
+ export declare function parseLearnedGuidanceInputs(data: unknown): LearnedGuidanceInputs;
72
+ /**
73
+ * Convenience loader matching the pattern used by `loadRetestContext`
74
+ * etc. — read JSON from disk, parse, validate, return.
75
+ *
76
+ * Caller is responsible for path validation (we expect `main.ts` to run
77
+ * the file path through `validateInputFilePath` before calling this so
78
+ * traversal attempts never reach the loader).
79
+ */
80
+ export declare function loadLearnedGuidanceInputs(absolutePath: string): LearnedGuidanceInputs;
81
+ /**
82
+ * Build the user-facing prompt for the synthesizer role. The prompt:
83
+ * 1. States the task and the success bar (positive-form rule, not generic).
84
+ * 2. Lists each bucket with its CWE, signal count, and a few example reasons.
85
+ * 3. Reminds the model of the schema, the per-bullet length cap, and the
86
+ * confidence scale.
87
+ *
88
+ * The system prompt (set in `agent_options.ts`) plus the JSON schema
89
+ * enforcement (set on `Options.outputFormat`) enforce the structural
90
+ * contract; this prompt focuses on the *content* contract.
91
+ */
92
+ export declare function buildLearnedGuidanceUserPrompt(inputs: LearnedGuidanceInputs): string;
93
+ export declare const LEARNED_GUIDANCE_OUTPUT_SCHEMA: Record<string, unknown>;
94
+ /** Convenience empty-output shell for tests / agent-side fallback. */
95
+ export declare function emptyLearnedGuidanceOutput(): LearnedGuidanceOutput;
96
+ //# sourceMappingURL=learned_guidance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learned_guidance.d.ts","sourceRoot":"","sources":["../../../src/schemas/learned_guidance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAQH,MAAM,WAAW,0BAA0B;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,yBAAyB,EAAE,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,0BAA0B,EAAE,CAAC;CACvC;AAaD,4FAA4F;AAC5F,eAAO,MAAM,cAAc,MAAM,CAAC;AAMlC,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,qBAAqB,EAAE,CAAC;CAClC;AAMD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,qBAAqB,CA2D/E;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,qBAAqB,CAYrF;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAmDpF;AAMD,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAoClE,CAAC;AAEF,sEAAsE;AACtE,wBAAgB,0BAA0B,IAAI,qBAAqB,CAElE"}