@workbench-ai/workbench-core 0.0.46

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 (72) hide show
  1. package/dist/adapter-auth.d.ts +63 -0
  2. package/dist/adapter-auth.d.ts.map +1 -0
  3. package/dist/adapter-auth.js +244 -0
  4. package/dist/execution-events.d.ts +53 -0
  5. package/dist/execution-events.d.ts.map +1 -0
  6. package/dist/execution-events.js +195 -0
  7. package/dist/execution-graph.d.ts +27 -0
  8. package/dist/execution-graph.d.ts.map +1 -0
  9. package/dist/execution-graph.js +126 -0
  10. package/dist/execution-jobs.d.ts +70 -0
  11. package/dist/execution-jobs.d.ts.map +1 -0
  12. package/dist/execution-jobs.js +229 -0
  13. package/dist/execution-outputs.d.ts +9 -0
  14. package/dist/execution-outputs.d.ts.map +1 -0
  15. package/dist/execution-outputs.js +393 -0
  16. package/dist/execution-phases.d.ts +21 -0
  17. package/dist/execution-phases.d.ts.map +1 -0
  18. package/dist/execution-phases.js +262 -0
  19. package/dist/execution-runtime-types.d.ts +35 -0
  20. package/dist/execution-runtime-types.d.ts.map +1 -0
  21. package/dist/execution-runtime-types.js +1 -0
  22. package/dist/execution-scheduler.d.ts +31 -0
  23. package/dist/execution-scheduler.d.ts.map +1 -0
  24. package/dist/execution-scheduler.js +241 -0
  25. package/dist/execution-traces.d.ts +16 -0
  26. package/dist/execution-traces.d.ts.map +1 -0
  27. package/dist/execution-traces.js +164 -0
  28. package/dist/execution-usage.d.ts +12 -0
  29. package/dist/execution-usage.d.ts.map +1 -0
  30. package/dist/execution-usage.js +433 -0
  31. package/dist/generic-spec.d.ts +113 -0
  32. package/dist/generic-spec.d.ts.map +1 -0
  33. package/dist/generic-spec.js +656 -0
  34. package/dist/index.d.ts +160 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +2858 -0
  37. package/dist/model-prices-litellm.d.ts +9674 -0
  38. package/dist/model-prices-litellm.d.ts.map +1 -0
  39. package/dist/model-prices-litellm.js +9668 -0
  40. package/dist/runtime-utils.d.ts +18 -0
  41. package/dist/runtime-utils.d.ts.map +1 -0
  42. package/dist/runtime-utils.js +108 -0
  43. package/dist/sandbox-backends/docker.d.ts +5 -0
  44. package/dist/sandbox-backends/docker.d.ts.map +1 -0
  45. package/dist/sandbox-backends/docker.js +568 -0
  46. package/dist/sandbox-backends/index.d.ts +37 -0
  47. package/dist/sandbox-backends/index.d.ts.map +1 -0
  48. package/dist/sandbox-backends/index.js +79 -0
  49. package/dist/sandbox-backends/names.d.ts +6 -0
  50. package/dist/sandbox-backends/names.d.ts.map +1 -0
  51. package/dist/sandbox-backends/names.js +14 -0
  52. package/dist/sandbox-backends/template-images.d.ts +4 -0
  53. package/dist/sandbox-backends/template-images.d.ts.map +1 -0
  54. package/dist/sandbox-backends/template-images.js +48 -0
  55. package/dist/sandbox-inputs.d.ts +27 -0
  56. package/dist/sandbox-inputs.d.ts.map +1 -0
  57. package/dist/sandbox-inputs.js +220 -0
  58. package/dist/sandbox-plane.d.ts +89 -0
  59. package/dist/sandbox-plane.d.ts.map +1 -0
  60. package/dist/sandbox-plane.js +327 -0
  61. package/dist/subject-patch.d.ts +8 -0
  62. package/dist/subject-patch.d.ts.map +1 -0
  63. package/dist/subject-patch.js +63 -0
  64. package/dist/trace-files.d.ts +18 -0
  65. package/dist/trace-files.d.ts.map +1 -0
  66. package/dist/trace-files.js +94 -0
  67. package/environments/libreoffice-agent/Dockerfile +13 -0
  68. package/environments/libreoffice-python/Dockerfile +11 -0
  69. package/environments/node-22/Dockerfile +3 -0
  70. package/environments/python-3.12/Dockerfile +8 -0
  71. package/package.json +42 -0
  72. package/worker/sandbox-adapter-runner.cjs +275 -0
@@ -0,0 +1,126 @@
1
+ import { resolveEngineCaseExecutionConfig, runtimeNetwork, runtimeResources, runtimeSandboxRef, } from "./generic-spec.js";
2
+ export function compileWorkbenchExecutionGraph(input) {
3
+ const workflow = input.workflow ?? "improve";
4
+ const sampleIndex = input.sampleIndex ?? 0;
5
+ const caseId = input.caseId ?? "current";
6
+ const subjectRef = input.subjectRef ?? `workbench://benchmarks/${input.projectId}/subjects/${input.subjectId}`;
7
+ const caseRef = input.caseRef ?? `workbench://benchmarks/${input.projectId}/engine-cases/${caseId}`;
8
+ if (!input.engineCase) {
9
+ throw new Error("Execution graph compilation requires an engine case.");
10
+ }
11
+ const engineCase = input.engineCase;
12
+ const executionConfig = resolveEngineCaseExecutionConfig({
13
+ spec: input.spec,
14
+ engineCase,
15
+ });
16
+ const nodes = [];
17
+ const executions = [];
18
+ const optimizerExecutionId = executionId(input, "improve", "current", 0);
19
+ const optimizerOutputRef = `execution://${optimizerExecutionId}/subject_patch`;
20
+ const engineAdapter = input.spec.engineRun;
21
+ if (workflow === "improve") {
22
+ if (!input.spec.optimizer || !input.spec.improve) {
23
+ throw new Error("Optimizer YAML is required for improve execution graphs.");
24
+ }
25
+ pushExecution(nodes, executions, createExecution({
26
+ input,
27
+ purpose: "improve",
28
+ adapter: input.spec.improve,
29
+ inputs: [
30
+ inputRef("subject", subjectRef, "/workspace/input/subject", false),
31
+ inputRef("traces", `workbench://benchmarks/${input.projectId}/runs/${input.runId}/traces`, "/workspace/input/traces", false),
32
+ ],
33
+ outputs: [outputContract("subject_patch", "workbench.subject_patch.v1")],
34
+ metadata: {
35
+ attemptIndex: input.attemptIndex,
36
+ sampleIndex: 0,
37
+ caseId: "current",
38
+ benchmark: input.spec.benchmark.name,
39
+ edits: input.spec.optimizer.edits,
40
+ },
41
+ runtime: input.spec.environment,
42
+ idOverride: optimizerExecutionId,
43
+ }), []);
44
+ }
45
+ const runSubjectRef = workflow === "improve" ? optimizerOutputRef : subjectRef;
46
+ const attemptExecutionId = executionId(input, "attempt", caseId, sampleIndex);
47
+ pushExecution(nodes, executions, createExecution({
48
+ input,
49
+ purpose: "attempt",
50
+ adapter: engineAdapter,
51
+ inputs: [
52
+ inputRef("subject", runSubjectRef, "/workspace/input/subject", false),
53
+ inputRef("case", caseRef, "/workspace/input/case", false),
54
+ ],
55
+ outputs: [outputContract("result", "workbench.result.v1")],
56
+ metadata: {
57
+ attemptIndex: input.attemptIndex,
58
+ sampleIndex,
59
+ caseId,
60
+ engineCase: engineCase,
61
+ ...(executionConfig.environment.workdir ? { workdir: executionConfig.environment.workdir } : {}),
62
+ },
63
+ runtime: executionConfig.environment,
64
+ idOverride: attemptExecutionId,
65
+ }), workflow === "improve" ? [optimizerExecutionId] : []);
66
+ return { nodes, executions };
67
+ }
68
+ function pushExecution(nodes, executions, execution, dependsOn) {
69
+ nodes.push({
70
+ execution,
71
+ dependsOn,
72
+ });
73
+ executions.push(execution);
74
+ }
75
+ function createExecution(args) {
76
+ return {
77
+ id: args.idOverride ?? executionId(args.input, args.purpose, args.input.caseId ?? "current", args.input.sampleIndex ?? 0),
78
+ projectId: args.input.projectId,
79
+ runId: args.input.runId,
80
+ subjectId: args.input.subjectId,
81
+ purpose: args.purpose,
82
+ adapter: args.adapter,
83
+ sandbox: args.input.environmentRef &&
84
+ runtimeSandboxRef(args.runtime) === runtimeSandboxRef(args.input.spec.environment)
85
+ ? {
86
+ kind: "oci",
87
+ ref: args.input.environmentRef,
88
+ }
89
+ : {
90
+ kind: "oci",
91
+ ref: runtimeSandboxRef(args.runtime),
92
+ },
93
+ inputs: args.inputs,
94
+ outputs: args.outputs,
95
+ policy: executionPolicy(args.input.ownerUserId, args.runtime),
96
+ metadata: args.metadata,
97
+ };
98
+ }
99
+ function executionPolicy(tenantId, runtime) {
100
+ return {
101
+ tenantId,
102
+ resources: runtimeResources(runtime),
103
+ network: runtimeNetwork(runtime),
104
+ };
105
+ }
106
+ function executionId(input, purpose, caseId, sampleIndex, suffix) {
107
+ const caseKey = caseId.replace(/[^a-z0-9_]/giu, "_");
108
+ const parts = [
109
+ "exec",
110
+ input.runId.replace(/[^a-z0-9_]/giu, "_"),
111
+ `attempt_${String(input.attemptIndex).padStart(3, "0")}`,
112
+ `case_${caseKey}`,
113
+ `sample_${String(sampleIndex).padStart(3, "0")}`,
114
+ purpose,
115
+ ];
116
+ if (suffix) {
117
+ parts.push(suffix.replace(/[^a-z0-9_]/giu, "_"));
118
+ }
119
+ return parts.join("_");
120
+ }
121
+ function inputRef(name, ref, mountPath, writable) {
122
+ return { name, ref, mountPath, writable };
123
+ }
124
+ function outputContract(name, schema, required = true) {
125
+ return { name, schema, required };
126
+ }
@@ -0,0 +1,70 @@
1
+ import type { HostedWorkbenchJob, Json, SurfaceSnapshotFile, WorkbenchExecutionSpec } from "@workbench-ai/workbench-contract";
2
+ import type { GenericRunSpec, WorkbenchEngineCase } from "./generic-spec.ts";
3
+ export type WorkbenchRunWorkflow = "eval" | "improve";
4
+ export declare const MAX_WORKBENCH_RUN_BUDGET = 20;
5
+ export declare function expectedWorkbenchRunJobCount(args: {
6
+ workflow: WorkbenchRunWorkflow;
7
+ budget: number;
8
+ samples: number;
9
+ caseCount: number;
10
+ }): number;
11
+ export declare function validateWorkbenchRunEnvelope(args: {
12
+ workflow: WorkbenchRunWorkflow;
13
+ budget: number;
14
+ samples: number;
15
+ caseCount: number;
16
+ }): string | null;
17
+ export declare function attemptJobCountForRunSpec(_spec: GenericRunSpec): number;
18
+ export declare function planWorkbenchExecutionJobsForPurpose(args: {
19
+ ownerUserId: string;
20
+ projectId: string;
21
+ runId: string;
22
+ subjectId: string;
23
+ attemptIndex: number;
24
+ samples: number;
25
+ caseIds?: readonly string[];
26
+ spec: GenericRunSpec;
27
+ workflow: WorkbenchRunWorkflow;
28
+ purpose: WorkbenchExecutionSpec["purpose"];
29
+ now: string;
30
+ baseFiles?: readonly SurfaceSnapshotFile[];
31
+ engineCases: readonly WorkbenchEngineCase[];
32
+ traceFiles?: readonly SurfaceSnapshotFile[];
33
+ environmentRef?: string;
34
+ environmentRefsByCase?: ReadonlyMap<string, string>;
35
+ baseId?: string | null;
36
+ }): HostedWorkbenchJob[];
37
+ export declare function engineCaseIds(engineCases: readonly WorkbenchEngineCase[]): string[];
38
+ export declare function engineCaseForCase(engineCases: readonly WorkbenchEngineCase[], caseId: string): WorkbenchEngineCase;
39
+ export declare function createWorkbenchExecutionJob(args: {
40
+ projectId: string;
41
+ runId: string;
42
+ subjectId: string;
43
+ execution: WorkbenchExecutionSpec;
44
+ dependsOn: readonly string[];
45
+ now: string;
46
+ baseFiles?: readonly SurfaceSnapshotFile[];
47
+ traceFiles?: readonly SurfaceSnapshotFile[];
48
+ baseId?: string | null;
49
+ }): HostedWorkbenchJob;
50
+ export declare function createBaselineSubjectExecution(args: {
51
+ ownerUserId: string;
52
+ projectId: string;
53
+ runId: string;
54
+ subjectId: string;
55
+ attemptIndex: number;
56
+ }): WorkbenchExecutionSpec;
57
+ export declare function createBaselineSubjectJob(args: {
58
+ ownerUserId: string;
59
+ projectId: string;
60
+ runId: string;
61
+ subjectId: string;
62
+ files: readonly SurfaceSnapshotFile[];
63
+ now: string;
64
+ baseId: string | null;
65
+ attemptIndex: number;
66
+ fileSet?: Json;
67
+ }): HostedWorkbenchJob;
68
+ export declare function workbenchExecutionJobId(executionId: string): string;
69
+ export declare function workbenchExecutionJobPurpose(job: HostedWorkbenchJob): WorkbenchExecutionSpec["purpose"] | null;
70
+ //# sourceMappingURL=execution-jobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-jobs.d.ts","sourceRoot":"","sources":["../src/execution-jobs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,229 @@
1
+ import { compileWorkbenchExecutionGraph, } from "./execution-graph.js";
2
+ export const MAX_WORKBENCH_RUN_BUDGET = 20;
3
+ export function expectedWorkbenchRunJobCount(args) {
4
+ const caseCount = Math.max(1, Math.floor(args.caseCount));
5
+ if (args.workflow === "improve") {
6
+ return args.budget * (1 + (args.samples * caseCount));
7
+ }
8
+ return 1 + (args.samples * caseCount);
9
+ }
10
+ export function validateWorkbenchRunEnvelope(args) {
11
+ if (!Number.isSafeInteger(args.budget) || args.budget <= 0) {
12
+ return "Run budget must be a positive integer.";
13
+ }
14
+ if (!Number.isSafeInteger(args.samples) || args.samples <= 0) {
15
+ return "Run samples must be a positive integer.";
16
+ }
17
+ if (!Number.isSafeInteger(args.caseCount) || args.caseCount <= 0) {
18
+ return "Run case count must be a positive integer.";
19
+ }
20
+ if (args.budget > MAX_WORKBENCH_RUN_BUDGET) {
21
+ return `Run budget cannot exceed ${MAX_WORKBENCH_RUN_BUDGET}.`;
22
+ }
23
+ return null;
24
+ }
25
+ export function attemptJobCountForRunSpec(_spec) {
26
+ return 1;
27
+ }
28
+ export function planWorkbenchExecutionJobsForPurpose(args) {
29
+ const jobs = [];
30
+ const engineCases = args.engineCases;
31
+ const caseIds = args.caseIds && args.caseIds.length > 0
32
+ ? [...args.caseIds]
33
+ : engineCaseIds(engineCases);
34
+ if (caseIds.length === 0) {
35
+ throw new Error("Run planning requires at least one engine case.");
36
+ }
37
+ for (const caseId of caseIds) {
38
+ const engineCase = engineCaseForCase(engineCases, caseId);
39
+ for (let sampleIndex = 0; sampleIndex < args.samples; sampleIndex += 1) {
40
+ const graph = compileWorkbenchExecutionGraph({
41
+ ownerUserId: args.ownerUserId,
42
+ projectId: args.projectId,
43
+ runId: args.runId,
44
+ subjectId: args.subjectId,
45
+ attemptIndex: args.attemptIndex,
46
+ sampleIndex,
47
+ caseId,
48
+ spec: args.spec,
49
+ engineCase: engineCase.case,
50
+ environmentRef: args.environmentRefsByCase?.get(caseId) ?? args.environmentRef,
51
+ workflow: args.workflow === "improve" ? "improve" : "eval",
52
+ });
53
+ for (const node of graph.nodes) {
54
+ if (node.execution.purpose !== args.purpose) {
55
+ continue;
56
+ }
57
+ jobs.push(createWorkbenchExecutionJob({
58
+ projectId: args.projectId,
59
+ runId: args.runId,
60
+ subjectId: args.subjectId,
61
+ execution: node.execution,
62
+ dependsOn: node.dependsOn,
63
+ now: args.now,
64
+ ...(args.baseFiles ? { baseFiles: args.baseFiles } : {}),
65
+ ...(args.traceFiles ? { traceFiles: args.traceFiles } : {}),
66
+ ...(args.baseId ? { baseId: args.baseId } : {}),
67
+ }));
68
+ }
69
+ }
70
+ }
71
+ return jobs.filter((job, index) => jobs.findIndex((entry) => entry.id === job.id) === index);
72
+ }
73
+ export function engineCaseIds(engineCases) {
74
+ return [...new Set(engineCases.map((bundle) => bundle.id))].sort();
75
+ }
76
+ export function engineCaseForCase(engineCases, caseId) {
77
+ const engineCase = engineCases.find((bundle) => bundle.id === caseId);
78
+ if (!engineCase) {
79
+ throw new Error(`Task bundle not found for case ${caseId}.`);
80
+ }
81
+ return engineCase;
82
+ }
83
+ export function createWorkbenchExecutionJob(args) {
84
+ const attemptIndex = readExecutionMetadataNumber(args.execution, "attemptIndex");
85
+ const sampleIndex = readExecutionMetadataNumber(args.execution, "sampleIndex");
86
+ const caseId = readExecutionMetadataString(args.execution, "caseId");
87
+ return {
88
+ id: workbenchExecutionJobId(args.execution.id),
89
+ projectId: args.projectId,
90
+ runId: args.runId,
91
+ subjectId: args.subjectId,
92
+ kind: "execute",
93
+ status: "queued",
94
+ attempt: 0,
95
+ createdAt: args.now,
96
+ updatedAt: args.now,
97
+ input: {
98
+ execution: args.execution,
99
+ dependsOn: args.dependsOn.map(workbenchExecutionJobId),
100
+ subjectId: args.subjectId,
101
+ attemptIndex,
102
+ sampleIndex,
103
+ caseId,
104
+ ...(args.baseFiles ? { baseFiles: args.baseFiles.map((file) => ({ ...file })) } : {}),
105
+ ...(args.traceFiles ? { traceFiles: args.traceFiles.map((file) => ({ ...file })) } : {}),
106
+ ...(args.baseId ? { baseId: args.baseId } : {}),
107
+ },
108
+ };
109
+ }
110
+ export function createBaselineSubjectExecution(args) {
111
+ return {
112
+ id: `exec_${args.runId.replace(/[^a-z0-9_]/giu, "_")}_attempt_${String(args.attemptIndex).padStart(3, "0")}_case_current_sample_000_improve`,
113
+ projectId: args.projectId,
114
+ runId: args.runId,
115
+ subjectId: args.subjectId,
116
+ purpose: "improve",
117
+ adapter: {
118
+ use: "baseline",
119
+ with: {},
120
+ },
121
+ sandbox: {
122
+ kind: "snapshot",
123
+ ref: "workbench/baseline-subject",
124
+ },
125
+ inputs: [],
126
+ outputs: [{
127
+ name: "subject_patch",
128
+ schema: "workbench.subject_patch.v1",
129
+ required: true,
130
+ }],
131
+ policy: {
132
+ tenantId: args.ownerUserId,
133
+ resources: {
134
+ cpu: 1,
135
+ memoryGb: 1,
136
+ diskGb: 1,
137
+ timeoutMinutes: 1,
138
+ },
139
+ network: {
140
+ egress: "none",
141
+ },
142
+ },
143
+ metadata: {
144
+ attemptIndex: args.attemptIndex,
145
+ sampleIndex: 0,
146
+ caseId: "current",
147
+ baseline: true,
148
+ },
149
+ };
150
+ }
151
+ export function createBaselineSubjectJob(args) {
152
+ const execution = createBaselineSubjectExecution({
153
+ ownerUserId: args.ownerUserId,
154
+ projectId: args.projectId,
155
+ runId: args.runId,
156
+ subjectId: args.subjectId,
157
+ attemptIndex: args.attemptIndex,
158
+ });
159
+ const files = args.files.map((file) => ({ ...file }));
160
+ return {
161
+ id: workbenchExecutionJobId(execution.id),
162
+ projectId: args.projectId,
163
+ runId: args.runId,
164
+ subjectId: args.subjectId,
165
+ kind: "execute",
166
+ status: "succeeded",
167
+ attempt: 1,
168
+ createdAt: args.now,
169
+ startedAt: args.now,
170
+ finishedAt: args.now,
171
+ updatedAt: args.now,
172
+ input: {
173
+ execution,
174
+ dependsOn: [],
175
+ subjectId: args.subjectId,
176
+ attemptIndex: args.attemptIndex,
177
+ baseline: true,
178
+ },
179
+ output: {
180
+ ok: true,
181
+ executionId: execution.id,
182
+ purpose: "improve",
183
+ subjectId: args.subjectId,
184
+ attemptIndex: args.attemptIndex,
185
+ baseId: args.baseId,
186
+ subjectPatch: {
187
+ files,
188
+ fileChanges: [],
189
+ },
190
+ fileChanges: [],
191
+ files,
192
+ ...(args.fileSet ? { fileSet: args.fileSet } : {}),
193
+ traces: [],
194
+ },
195
+ };
196
+ }
197
+ export function workbenchExecutionJobId(executionId) {
198
+ return `job_${executionId.replace(/[^a-z0-9_]/giu, "_")}`;
199
+ }
200
+ export function workbenchExecutionJobPurpose(job) {
201
+ if (job.kind !== "execute") {
202
+ return null;
203
+ }
204
+ const execution = asRecord(asRecord(job.input).execution);
205
+ const purpose = execution.purpose;
206
+ return purpose === "improve" || purpose === "attempt" ? purpose : null;
207
+ }
208
+ function readExecutionMetadataNumber(execution, key) {
209
+ const raw = execution.metadata[key];
210
+ if (typeof raw === "number" && Number.isFinite(raw)) {
211
+ return raw;
212
+ }
213
+ throw new Error(`Execution ${execution.id} is missing numeric metadata.${key}.`);
214
+ }
215
+ function readExecutionMetadataString(execution, key) {
216
+ const raw = execution.metadata[key];
217
+ if (typeof raw === "string" && raw.length > 0) {
218
+ return raw;
219
+ }
220
+ throw new Error(`Execution ${execution.id} is missing string metadata.${key}.`);
221
+ }
222
+ function asRecord(value) {
223
+ return value && typeof value === "object" && !Array.isArray(value)
224
+ ? value
225
+ : {};
226
+ }
227
+ function normalizeRelativePath(value) {
228
+ return value.trim().replace(/\\/gu, "/").replace(/^\/+/u, "").replace(/\/+$/u, "");
229
+ }
@@ -0,0 +1,9 @@
1
+ import type { Json, WorkbenchSubjectPatch, WorkbenchExecutionSpec, WorkbenchResult } from "@workbench-ai/workbench-contract";
2
+ export interface WorkbenchExecutionOutputPayloads {
3
+ subjectPatch?: WorkbenchSubjectPatch;
4
+ result?: WorkbenchResult;
5
+ }
6
+ export declare function validateWorkbenchExecutionOutputPayloads(execution: WorkbenchExecutionSpec, payloads: Record<string, Json>): WorkbenchExecutionOutputPayloads;
7
+ export declare function collectWorkbenchExecutionIsolationIssues(execution: WorkbenchExecutionSpec): string[];
8
+ export declare function assertWorkbenchExecutionIsolation(execution: WorkbenchExecutionSpec): void;
9
+ //# sourceMappingURL=execution-outputs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-outputs.d.ts","sourceRoot":"","sources":["../src/execution-outputs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,IAAI,EAEJ,qBAAqB,EAErB,sBAAsB,EACtB,eAAe,EAChB,MAAM,kCAAkC,CAAC;AAI1C,MAAM,WAAW,gCAAgC;IAC/C,YAAY,CAAC,EAAE,qBAAqB,CAAC;IACrC,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED,wBAAgB,wCAAwC,CACtD,SAAS,EAAE,sBAAsB,EACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAC7B,gCAAgC,CAoClC;AAED,wBAAgB,wCAAwC,CAAC,SAAS,EAAE,sBAAsB,GAAG,MAAM,EAAE,CAoFpG;AAsBD,wBAAgB,iCAAiC,CAAC,SAAS,EAAE,sBAAsB,GAAG,IAAI,CAKzF"}