@mcoda/codali 0.1.88 → 0.1.89

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 (68) hide show
  1. package/dist/cli/EvalCommand.d.ts +8 -0
  2. package/dist/cli/EvalCommand.d.ts.map +1 -1
  3. package/dist/cli/EvalCommand.js +93 -1
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +1 -0
  6. package/dist/docdex/DocdexClient.d.ts +8 -1
  7. package/dist/docdex/DocdexClient.d.ts.map +1 -1
  8. package/dist/docdex/DocdexClient.js +126 -33
  9. package/dist/eval/CodaliGatewayLiveHarness.d.ts +169 -0
  10. package/dist/eval/CodaliGatewayLiveHarness.d.ts.map +1 -0
  11. package/dist/eval/CodaliGatewayLiveHarness.js +824 -0
  12. package/dist/eval/GatewayEvalSuite.d.ts +202 -0
  13. package/dist/eval/GatewayEvalSuite.d.ts.map +1 -0
  14. package/dist/eval/GatewayEvalSuite.js +673 -0
  15. package/dist/gateway/AgentTierResolver.d.ts +74 -0
  16. package/dist/gateway/AgentTierResolver.d.ts.map +1 -0
  17. package/dist/gateway/AgentTierResolver.js +576 -0
  18. package/dist/gateway/AppToolGatewayDispatcher.d.ts +88 -0
  19. package/dist/gateway/AppToolGatewayDispatcher.d.ts.map +1 -0
  20. package/dist/gateway/AppToolGatewayDispatcher.js +381 -0
  21. package/dist/gateway/CodaliGateway.d.ts +73 -0
  22. package/dist/gateway/CodaliGateway.d.ts.map +1 -0
  23. package/dist/gateway/CodaliGateway.js +824 -0
  24. package/dist/gateway/CodaliGatewaySchemas.d.ts +21 -0
  25. package/dist/gateway/CodaliGatewaySchemas.d.ts.map +1 -0
  26. package/dist/gateway/CodaliGatewaySchemas.js +874 -0
  27. package/dist/gateway/CodaliGatewayStore.d.ts +157 -0
  28. package/dist/gateway/CodaliGatewayStore.d.ts.map +1 -0
  29. package/dist/gateway/CodaliGatewayStore.js +206 -0
  30. package/dist/gateway/CodaliGatewayTypes.d.ts +336 -0
  31. package/dist/gateway/CodaliGatewayTypes.d.ts.map +1 -0
  32. package/dist/gateway/CodaliGatewayTypes.js +1 -0
  33. package/dist/gateway/ContextPackBuilder.d.ts +43 -0
  34. package/dist/gateway/ContextPackBuilder.d.ts.map +1 -0
  35. package/dist/gateway/ContextPackBuilder.js +317 -0
  36. package/dist/gateway/EvidenceNormalizer.d.ts +42 -0
  37. package/dist/gateway/EvidenceNormalizer.d.ts.map +1 -0
  38. package/dist/gateway/EvidenceNormalizer.js +488 -0
  39. package/dist/gateway/GatewayPlanner.d.ts +195 -0
  40. package/dist/gateway/GatewayPlanner.d.ts.map +1 -0
  41. package/dist/gateway/GatewayPlanner.js +379 -0
  42. package/dist/gateway/GatewayPolicyCompiler.d.ts +30 -0
  43. package/dist/gateway/GatewayPolicyCompiler.d.ts.map +1 -0
  44. package/dist/gateway/GatewayPolicyCompiler.js +114 -0
  45. package/dist/gateway/GatewaySecurityPolicy.d.ts +14 -0
  46. package/dist/gateway/GatewaySecurityPolicy.d.ts.map +1 -0
  47. package/dist/gateway/GatewaySecurityPolicy.js +350 -0
  48. package/dist/gateway/GatewayStateMachine.d.ts +165 -0
  49. package/dist/gateway/GatewayStateMachine.d.ts.map +1 -0
  50. package/dist/gateway/GatewayStateMachine.js +790 -0
  51. package/dist/gateway/GatewayTraceReplay.d.ts +120 -0
  52. package/dist/gateway/GatewayTraceReplay.d.ts.map +1 -0
  53. package/dist/gateway/GatewayTraceReplay.js +273 -0
  54. package/dist/gateway/ToolCapabilityCompiler.d.ts +50 -0
  55. package/dist/gateway/ToolCapabilityCompiler.d.ts.map +1 -0
  56. package/dist/gateway/ToolCapabilityCompiler.js +442 -0
  57. package/dist/index.d.ts +30 -0
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +15 -0
  60. package/dist/runtime/CodaliRuntime.d.ts +7 -0
  61. package/dist/runtime/CodaliRuntime.d.ts.map +1 -1
  62. package/dist/runtime/CodaliRuntime.js +98 -54
  63. package/dist/tools/ToolRegistry.d.ts.map +1 -1
  64. package/dist/tools/ToolRegistry.js +4 -0
  65. package/dist/tools/ToolTypes.d.ts +1 -1
  66. package/dist/tools/ToolTypes.d.ts.map +1 -1
  67. package/dist/tools/ToolTypes.js +5 -1
  68. package/package.json +3 -3
@@ -0,0 +1,317 @@
1
+ const DEFAULT_MAX_DECISION_FACTS = 24;
2
+ const DEFAULT_MAX_EXCERPT_CHARS = 1200;
3
+ const DEFAULT_MAX_CONTEXT_PACK_TOKENS = 12000;
4
+ const FRESHNESS_SCORE = {
5
+ fresh: 1,
6
+ recent: 0.75,
7
+ unknown: 0.4,
8
+ stale: 0.1,
9
+ };
10
+ const SOURCE_QUALITY = {
11
+ app_tool: 0.9,
12
+ docdex: 1,
13
+ file: 0.75,
14
+ github: 0.9,
15
+ jira: 0.9,
16
+ microsoft: 0.9,
17
+ model_observation: 0.2,
18
+ };
19
+ const isRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
20
+ const positiveInteger = (value, fallback) => Number.isFinite(value) && value !== undefined && value > 0
21
+ ? Math.floor(value)
22
+ : fallback;
23
+ const clampUnit = (value) => Number.isFinite(value) && value !== undefined
24
+ ? Math.max(0, Math.min(1, value))
25
+ : 0;
26
+ const uniqueInOrder = (values) => {
27
+ const seen = new Set();
28
+ const output = [];
29
+ for (const value of values) {
30
+ const normalized = value.trim();
31
+ if (!normalized || seen.has(normalized))
32
+ continue;
33
+ seen.add(normalized);
34
+ output.push(normalized);
35
+ }
36
+ return output;
37
+ };
38
+ const estimateTokens = (value) => {
39
+ const text = typeof value === "string" ? value : JSON.stringify(value ?? "");
40
+ return Math.max(1, Math.ceil(text.length / 4));
41
+ };
42
+ export const estimateCodaliContextPackTokens = (pack) => estimateTokens({
43
+ originalQuery: pack.originalQuery,
44
+ decisionFacts: pack.decisionFacts.map((evidence) => ({
45
+ id: evidence.id,
46
+ claim: evidence.claim,
47
+ summary: evidence.summary,
48
+ sourceType: evidence.sourceType,
49
+ sourceId: evidence.sourceId,
50
+ sourceUri: evidence.sourceUri,
51
+ sourceTitle: evidence.sourceTitle,
52
+ confidence: evidence.confidence,
53
+ relevance: evidence.relevance,
54
+ freshness: evidence.freshness,
55
+ usedTool: evidence.usedTool,
56
+ })),
57
+ contradictions: pack.contradictions,
58
+ missingInformation: pack.missingInformation,
59
+ selectedExcerpts: pack.selectedExcerpts,
60
+ toolSummary: pack.toolSummary,
61
+ });
62
+ const normalizeClaimFingerprint = (claim) => claim
63
+ .toLowerCase()
64
+ .replace(/[^a-z0-9]+/g, " ")
65
+ .trim()
66
+ .replace(/\s+/g, " ");
67
+ const sourceQualityScore = (evidence) => {
68
+ const sourceType = evidence.sourceType.toLowerCase();
69
+ const direct = SOURCE_QUALITY[sourceType];
70
+ const base = direct ?? (sourceType.includes("docdex") ? 1 : 0.55);
71
+ const provenanceBoost = evidence.sourceId || evidence.sourceUri ? 0.05 : 0;
72
+ return Math.min(1, base + provenanceBoost);
73
+ };
74
+ const evidenceRankScore = (evidence) => {
75
+ const relevance = clampUnit(evidence.relevance);
76
+ const confidence = clampUnit(evidence.confidence);
77
+ const freshness = FRESHNESS_SCORE[evidence.freshness ?? "unknown"] ?? FRESHNESS_SCORE.unknown;
78
+ const sourceQuality = sourceQualityScore(evidence);
79
+ return (relevance * 0.42 +
80
+ confidence * 0.34 +
81
+ freshness * 0.1 +
82
+ sourceQuality * 0.14);
83
+ };
84
+ const compareEvidence = (left, right) => {
85
+ const scoreDiff = evidenceRankScore(right) - evidenceRankScore(left);
86
+ if (scoreDiff !== 0)
87
+ return scoreDiff;
88
+ const confidenceDiff = clampUnit(right.confidence) - clampUnit(left.confidence);
89
+ if (confidenceDiff !== 0)
90
+ return confidenceDiff;
91
+ const relevanceDiff = clampUnit(right.relevance) - clampUnit(left.relevance);
92
+ if (relevanceDiff !== 0)
93
+ return relevanceDiff;
94
+ return left.id.localeCompare(right.id);
95
+ };
96
+ const cloneEvidenceForContext = (evidence, mergedEvidenceIds = []) => {
97
+ const { rawExcerpt: _rawExcerpt, rawPayloadRef: _rawPayloadRef, ...rest } = evidence;
98
+ return {
99
+ ...rest,
100
+ metadata: {
101
+ ...(evidence.metadata ?? {}),
102
+ contextRankScore: Number(evidenceRankScore(evidence).toFixed(6)),
103
+ ...(mergedEvidenceIds.length > 0 ? { mergedEvidenceIds } : {}),
104
+ },
105
+ };
106
+ };
107
+ const selectExcerptText = (evidence, maxExcerptChars) => {
108
+ const raw = evidence.sourceType === "model_observation"
109
+ ? evidence.summary ?? evidence.claim
110
+ : evidence.rawExcerpt ?? evidence.summary ?? evidence.claim;
111
+ const normalized = raw.trim().replace(/\s+/g, " ");
112
+ if (normalized.length <= maxExcerptChars) {
113
+ return normalized;
114
+ }
115
+ return normalized.slice(0, Math.max(0, maxExcerptChars - 15)).trimEnd() + " [truncated]";
116
+ };
117
+ const dedupeAndRankEvidence = (evidence) => {
118
+ const groups = new Map();
119
+ for (const item of evidence) {
120
+ const fingerprint = normalizeClaimFingerprint(item.claim);
121
+ const key = fingerprint || item.id;
122
+ const existing = groups.get(key) ?? [];
123
+ existing.push(item);
124
+ groups.set(key, existing);
125
+ }
126
+ const ranked = [];
127
+ const duplicateIdsByWinner = new Map();
128
+ const droppedDuplicateIds = [];
129
+ for (const group of groups.values()) {
130
+ const sorted = [...group].sort(compareEvidence);
131
+ const winner = sorted[0];
132
+ if (!winner)
133
+ continue;
134
+ const duplicateIds = sorted.slice(1).map((item) => item.id);
135
+ if (duplicateIds.length > 0) {
136
+ duplicateIdsByWinner.set(winner.id, duplicateIds);
137
+ droppedDuplicateIds.push(...duplicateIds);
138
+ }
139
+ ranked.push(winner);
140
+ }
141
+ return {
142
+ ranked: ranked.sort(compareEvidence),
143
+ duplicateIdsByWinner,
144
+ droppedDuplicateIds,
145
+ };
146
+ };
147
+ const summarizeTools = (calls) => {
148
+ const byTool = new Map();
149
+ for (const call of calls) {
150
+ const statuses = byTool.get(call.tool) ?? {};
151
+ statuses[call.status] = (statuses[call.status] ?? 0) + 1;
152
+ byTool.set(call.tool, statuses);
153
+ }
154
+ return [...byTool.entries()]
155
+ .sort(([left], [right]) => left.localeCompare(right))
156
+ .map(([tool, statuses]) => ({
157
+ tool,
158
+ calls: Object.values(statuses).reduce((sum, value) => sum + value, 0),
159
+ statuses,
160
+ }));
161
+ };
162
+ const readRequestFromTrace = (trace) => {
163
+ const request = trace?.run.request;
164
+ if (!isRecord(request) || typeof request.query !== "string") {
165
+ return undefined;
166
+ }
167
+ return request;
168
+ };
169
+ const readVerificationFromTrace = (trace) => {
170
+ const metadata = trace?.run.metadata;
171
+ if (!isRecord(metadata) || !isRecord(metadata.verification)) {
172
+ return undefined;
173
+ }
174
+ return metadata.verification;
175
+ };
176
+ const normalizeContradictions = (contradictions) => {
177
+ const seen = new Set();
178
+ const output = [];
179
+ for (const contradiction of contradictions) {
180
+ const summary = contradiction.summary.trim();
181
+ if (!summary)
182
+ continue;
183
+ const evidenceIds = uniqueInOrder(contradiction.evidenceIds ?? []);
184
+ const key = `${summary}:${evidenceIds.join(",")}`;
185
+ if (seen.has(key))
186
+ continue;
187
+ seen.add(key);
188
+ output.push({ summary, evidenceIds });
189
+ }
190
+ return output;
191
+ };
192
+ export const buildCodaliContextPack = (input) => {
193
+ const traceRequest = readRequestFromTrace(input.trace);
194
+ const request = input.request ?? traceRequest;
195
+ const verification = input.verification ?? readVerificationFromTrace(input.trace);
196
+ const maxContextPackTokens = positiveInteger(input.maxContextPackTokens ?? request?.policy?.maxContextPackTokens, DEFAULT_MAX_CONTEXT_PACK_TOKENS);
197
+ const maxDecisionFacts = positiveInteger(input.maxDecisionFacts ?? request?.policy?.maxEvidenceItems, DEFAULT_MAX_DECISION_FACTS);
198
+ const maxExcerptChars = positiveInteger(input.maxExcerptChars, DEFAULT_MAX_EXCERPT_CHARS);
199
+ const evidence = input.evidence ?? input.trace?.evidence ?? [];
200
+ const toolCalls = input.toolCalls ?? input.trace?.toolCalls ?? [];
201
+ const originalQuery = input.originalQuery ??
202
+ request?.query ??
203
+ (typeof input.trace?.run.request === "object" &&
204
+ input.trace?.run.request &&
205
+ "query" in input.trace.run.request &&
206
+ typeof input.trace.run.request.query === "string"
207
+ ? input.trace.run.request.query
208
+ : "");
209
+ const warnings = [];
210
+ const { ranked, duplicateIdsByWinner, droppedDuplicateIds } = dedupeAndRankEvidence(evidence);
211
+ const missingInformation = uniqueInOrder(verification?.missingInformation ?? []);
212
+ const contradictions = normalizeContradictions(verification?.contradictions ?? []);
213
+ const toolSummary = summarizeTools(toolCalls);
214
+ const decisionFacts = [];
215
+ const selectedExcerpts = [];
216
+ const selectedEvidenceIds = [];
217
+ const droppedEvidenceIds = new Set(droppedDuplicateIds);
218
+ let contextPack = {
219
+ id: `context-pack-${input.runId}`,
220
+ runId: input.runId,
221
+ originalQuery,
222
+ decisionFacts,
223
+ contradictions,
224
+ missingInformation,
225
+ selectedExcerpts,
226
+ toolSummary,
227
+ tokenEstimate: 1,
228
+ metadata: {
229
+ maxContextPackTokens,
230
+ sourceEvidenceCount: evidence.length,
231
+ deduplicatedEvidenceCount: ranked.length,
232
+ duplicateEvidenceIds: droppedDuplicateIds,
233
+ },
234
+ };
235
+ let tokenEstimate = estimateCodaliContextPackTokens(contextPack);
236
+ for (const evidenceItem of ranked) {
237
+ if (decisionFacts.length >= maxDecisionFacts) {
238
+ droppedEvidenceIds.add(evidenceItem.id);
239
+ continue;
240
+ }
241
+ const fact = cloneEvidenceForContext(evidenceItem, duplicateIdsByWinner.get(evidenceItem.id) ?? []);
242
+ const excerptText = selectExcerptText(evidenceItem, maxExcerptChars);
243
+ const excerpt = {
244
+ evidenceId: evidenceItem.id,
245
+ text: excerptText,
246
+ };
247
+ const candidatePack = {
248
+ ...contextPack,
249
+ decisionFacts: [...decisionFacts, fact],
250
+ selectedExcerpts: [...selectedExcerpts, excerpt],
251
+ tokenEstimate,
252
+ };
253
+ const candidateEstimate = estimateCodaliContextPackTokens(candidatePack);
254
+ if (candidateEstimate > maxContextPackTokens && decisionFacts.length > 0) {
255
+ droppedEvidenceIds.add(evidenceItem.id);
256
+ warnings.push(`context_pack_budget_dropped:${evidenceItem.id}`);
257
+ continue;
258
+ }
259
+ decisionFacts.push(fact);
260
+ selectedExcerpts.push(excerpt);
261
+ selectedEvidenceIds.push(evidenceItem.id);
262
+ tokenEstimate = Math.min(candidateEstimate, maxContextPackTokens);
263
+ contextPack = {
264
+ ...candidatePack,
265
+ tokenEstimate,
266
+ };
267
+ }
268
+ for (const evidenceItem of ranked) {
269
+ if (!selectedEvidenceIds.includes(evidenceItem.id)) {
270
+ droppedEvidenceIds.add(evidenceItem.id);
271
+ }
272
+ }
273
+ contextPack = {
274
+ ...contextPack,
275
+ decisionFacts,
276
+ selectedExcerpts,
277
+ tokenEstimate: Math.min(estimateCodaliContextPackTokens(contextPack), maxContextPackTokens),
278
+ metadata: {
279
+ ...(contextPack.metadata ?? {}),
280
+ selectedEvidenceIds,
281
+ droppedEvidenceIds: [...droppedEvidenceIds].sort(),
282
+ warningCount: warnings.length,
283
+ },
284
+ };
285
+ return {
286
+ contextPack,
287
+ selectedEvidenceIds,
288
+ droppedEvidenceIds: [...droppedEvidenceIds].sort(),
289
+ warnings,
290
+ };
291
+ };
292
+ export class CodaliContextPackBuilder {
293
+ constructor(options) {
294
+ this.options = options;
295
+ }
296
+ async buildAndPersist(input) {
297
+ const trace = await this.options.store.readRunTrace(input.runId);
298
+ if (!trace) {
299
+ throw new Error(`GATEWAY_RUN_NOT_FOUND: ${input.runId}`);
300
+ }
301
+ const result = buildCodaliContextPack({
302
+ runId: input.runId,
303
+ request: input.request,
304
+ trace,
305
+ verification: input.verification,
306
+ maxContextPackTokens: input.maxContextPackTokens,
307
+ maxDecisionFacts: input.maxDecisionFacts ?? this.options.maxDecisionFacts,
308
+ maxExcerptChars: input.maxExcerptChars ?? this.options.maxExcerptChars,
309
+ });
310
+ const saved = await this.options.store.saveContextPack(input.runId, result.contextPack);
311
+ return {
312
+ ...result,
313
+ contextPack: saved,
314
+ };
315
+ }
316
+ }
317
+ export const createCodaliContextPackBuilder = (options) => new CodaliContextPackBuilder(options);
@@ -0,0 +1,42 @@
1
+ import type { CodaliEvidenceItem } from "./CodaliGatewayTypes.js";
2
+ export interface CodaliEvidenceNormalizerToolCall {
3
+ tool: string;
4
+ status?: "success" | "failed" | "blocked" | string;
5
+ args?: unknown;
6
+ result?: unknown;
7
+ errorCode?: string;
8
+ errorMessage?: string;
9
+ metadata?: Record<string, unknown>;
10
+ }
11
+ export interface CodaliEvidenceNormalizerInput {
12
+ runId: string;
13
+ taskId?: string;
14
+ stageId?: string;
15
+ originalQuery?: string;
16
+ workerOutput?: unknown;
17
+ evidence?: unknown[];
18
+ toolCalls?: CodaliEvidenceNormalizerToolCall[];
19
+ requireTenantScope?: boolean;
20
+ defaultTenantScoped?: boolean;
21
+ defaultSourceType?: string;
22
+ defaultTool?: string;
23
+ maxEvidenceItems?: number;
24
+ }
25
+ export interface CodaliEvidenceRejectedItem {
26
+ reason: string;
27
+ claim?: string;
28
+ sourceType?: string;
29
+ sourceId?: string;
30
+ sourceUri?: string;
31
+ usedTool?: string;
32
+ value?: unknown;
33
+ }
34
+ export interface CodaliEvidenceNormalizerResult {
35
+ evidence: CodaliEvidenceItem[];
36
+ rejected: CodaliEvidenceRejectedItem[];
37
+ warnings: string[];
38
+ duplicateCount: number;
39
+ }
40
+ export declare const normalizeCodaliEvidence: (input: CodaliEvidenceNormalizerInput) => CodaliEvidenceNormalizerResult;
41
+ export declare const normalizeGatewayEvidence: (input: CodaliEvidenceNormalizerInput) => CodaliEvidenceNormalizerResult;
42
+ //# sourceMappingURL=EvidenceNormalizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EvidenceNormalizer.d.ts","sourceRoot":"","sources":["../../src/gateway/EvidenceNormalizer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EAEnB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,gCAAgC;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IACnD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,gCAAgC,EAAE,CAAC;IAC/C,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,QAAQ,EAAE,0BAA0B,EAAE,CAAC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AA0eD,eAAO,MAAM,uBAAuB,GAClC,OAAO,6BAA6B,KACnC,8BA+HF,CAAC;AAEF,eAAO,MAAM,wBAAwB,UAlI5B,6BAA6B,KACnC,8BAiI4D,CAAC"}