@cat-factory/orchestration 0.20.0 → 0.21.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,248 @@
1
+ import { assertFound, ConflictError, inlineModelRef, requireWorkspace, resolveScopedModelProvider, ValidationError, } from '@cat-factory/kernel';
2
+ import { catFactoryObservability } from '@cat-factory/agents';
3
+ import { SANDBOX_REPO_FIXTURE_KINDS } from '@cat-factory/contracts';
4
+ import { expandMatrix, listBaselines, listBuiltinFixtures, rubricFor, sandboxKindMeta, versionLabel, weightedTotal, } from '@cat-factory/sandbox';
5
+ import { generateText } from 'ai';
6
+ import { composeExperimentDetail } from './SandboxService.js';
7
+ import { buildJudgePrompt, coerceJudgeScores, extractJson, gradedDimensionCount, JUDGE_SYSTEM_PROMPT, objectiveFor, parseModelCatalogId, renderFixtureInput, } from './sandbox.logic.js';
8
+ /**
9
+ * The Sandbox run-driver + judge. {@link launch} expands a draft experiment's matrix
10
+ * into cells, runs each inline candidate (one LLM call against the prompt-version's
11
+ * system text + the fixture's rendered input), grades it with the judge model against
12
+ * the task rubric, and records the deterministic objective score alongside. It drives
13
+ * synchronously to completion (bounded by a cell cap at create time + an optional token
14
+ * budget) — every cell is a single inline LLM call, so there is no durable fan-out.
15
+ *
16
+ * Container/repo fixtures (a real checkout) are not yet supported here and are refused at
17
+ * launch with a clear message; the builtin fixtures are all inline. Both runtimes wire
18
+ * this identically, so the refusal — like the run itself — is runtime-symmetric.
19
+ */
20
+ export class SandboxRunService {
21
+ deps;
22
+ constructor(deps) {
23
+ this.deps = deps;
24
+ }
25
+ async launch(workspaceId, experimentId) {
26
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
27
+ const experiment = assertFound(await this.deps.sandboxExperimentRepository.get(workspaceId, experimentId), 'SandboxExperiment', experimentId);
28
+ if (experiment.status === 'running') {
29
+ throw new ConflictError('This experiment is already running.');
30
+ }
31
+ const meta = sandboxKindMeta(experiment.agentKind);
32
+ if (!meta)
33
+ throw new ValidationError(`"${experiment.agentKind}" is not a Sandbox-testable kind`);
34
+ if (meta.bucket === 'container') {
35
+ throw new ValidationError(`The "${experiment.agentKind}" agent runs in a container; container experiments are not yet supported in the Sandbox.`);
36
+ }
37
+ const provider = await this.providerFor(workspaceId);
38
+ const prompts = await this.resolvePrompts(workspaceId, experiment);
39
+ const fixtures = await this.resolveFixtures(workspaceId, experiment);
40
+ const rubric = rubricFor(meta.rubric);
41
+ // Atomically claim the run BEFORE touching the grid: the conditional transition to
42
+ // `running` lets exactly one concurrent launch win, so two simultaneous launches can't
43
+ // both clear + re-expand the grid (duplicating cells) or race the grid-clearing deletes.
44
+ // The fast-path read above is just a friendly early error; THIS is the authoritative gate.
45
+ // Validation/resolution runs first, so a bad request never mutates state or strands the
46
+ // experiment `running`. The `finally` below settles the terminal status from here on.
47
+ if (!(await this.deps.sandboxExperimentRepository.claimForRun(workspaceId, experimentId))) {
48
+ throw new ConflictError('This experiment is already running.');
49
+ }
50
+ // The experiment is a SCORED comparison: a cell only counts toward a successful
51
+ // experiment once it is actually graded. A cell that produced candidate output but
52
+ // whose grading failed is kept inspectable (status `done` + an error), but it does
53
+ // NOT make the experiment look healthy — an experiment whose every grade failed
54
+ // settles `failed`, not `done` with a grid of unscored `—` cells.
55
+ let graded = 0;
56
+ // Everything that mutates the grid runs INSIDE this try, so the `finally` settles the
57
+ // terminal status no matter where it throws — the claim above already set `running`, so
58
+ // a failure anywhere below can never strand the experiment in `running`.
59
+ try {
60
+ // A relaunch re-runs from scratch: drop the prior result grid (grades before runs, so
61
+ // the grade scoping subquery still resolves the cells) so cells don't accumulate.
62
+ await this.deps.sandboxGradeRepository.removeByExperiment(workspaceId, experimentId);
63
+ await this.deps.sandboxRunRepository.removeByExperiment(workspaceId, experimentId);
64
+ // Persist the queued grid first, then drive each cell. (The claim above already set
65
+ // the experiment `running`.)
66
+ const now = this.deps.clock.now();
67
+ const runs = expandMatrix(experiment, {
68
+ makeId: () => this.deps.idGenerator.next('sbr'),
69
+ labelFor: (id) => prompts.get(id)?.label ?? id,
70
+ now,
71
+ });
72
+ for (const run of runs)
73
+ await this.deps.sandboxRunRepository.upsert(workspaceId, run);
74
+ // Drive every cell synchronously to completion. The terminal status is derived from
75
+ // the cell outcomes and ALWAYS settled in `finally` — a thrown error (or every cell
76
+ // failing) leaves the experiment `failed`, never stuck `running`. NOTE: this runs the
77
+ // whole matrix inline in the request; the cell cap + token budget bound it, but a true
78
+ // durable fan-out (Workflows / pg-boss, like execution+bootstrap) is the proper home
79
+ // for large matrices and the tracked follow-up.
80
+ const budget = experiment.budgetTokens;
81
+ let spent = 0;
82
+ for (const run of runs) {
83
+ if (budget !== null && spent >= budget) {
84
+ await this.failRun(workspaceId, run, 'Token budget exhausted before this cell ran.');
85
+ continue;
86
+ }
87
+ const prompt = prompts.get(run.promptVersionId);
88
+ const fixture = fixtures.get(run.fixtureId);
89
+ if (!prompt || !fixture) {
90
+ await this.failRun(workspaceId, run, prompt
91
+ ? `Unknown fixture "${run.fixtureId}"`
92
+ : `Unknown prompt version "${run.promptVersionId}"`);
93
+ continue;
94
+ }
95
+ const taskInput = renderFixtureInput(fixture);
96
+ // Phase 1 — run the candidate. A failure here means the cell produced nothing,
97
+ // so the whole cell is `failed`.
98
+ let done;
99
+ try {
100
+ const candidateRef = this.refFor(run.model);
101
+ const started = this.deps.clock.now();
102
+ const candidate = await generateText({
103
+ model: provider.resolve(candidateRef),
104
+ system: prompt.systemText,
105
+ prompt: taskInput,
106
+ temperature: 0.2,
107
+ maxOutputTokens: 4000,
108
+ providerOptions: catFactoryObservability({
109
+ agentKind: `sandbox:${experiment.agentKind}`,
110
+ workspaceId,
111
+ }),
112
+ });
113
+ const latencyMs = this.deps.clock.now() - started;
114
+ const usage = {
115
+ inputTokens: candidate.usage.inputTokens ?? 0,
116
+ outputTokens: candidate.usage.outputTokens ?? 0,
117
+ };
118
+ spent += usage.inputTokens + usage.outputTokens;
119
+ done = {
120
+ ...run,
121
+ status: 'done',
122
+ outputText: candidate.text,
123
+ usage,
124
+ latencyMs,
125
+ startedAt: started,
126
+ finishedAt: this.deps.clock.now(),
127
+ };
128
+ await this.deps.sandboxRunRepository.upsert(workspaceId, done);
129
+ }
130
+ catch (e) {
131
+ await this.failRun(workspaceId, run, e instanceof Error ? e.message : String(e));
132
+ continue;
133
+ }
134
+ // Phase 2 — grade the cell (rubric + objective). A grading failure must NOT
135
+ // discard the candidate output: keep the `done` run and record the grading error
136
+ // on it so the produced output stays inspectable.
137
+ try {
138
+ const judgeRef = this.refFor(experiment.judgeModel);
139
+ const judged = await generateText({
140
+ model: provider.resolve(judgeRef),
141
+ system: JUDGE_SYSTEM_PROMPT,
142
+ prompt: buildJudgePrompt(rubric, taskInput, done.outputText ?? '', expectationsOf(fixture)),
143
+ temperature: 0,
144
+ maxOutputTokens: 2000,
145
+ providerOptions: catFactoryObservability({ agentKind: 'sandbox:judge', workspaceId }),
146
+ });
147
+ spent += (judged.usage.inputTokens ?? 0) + (judged.usage.outputTokens ?? 0);
148
+ // Treat an unparseable / empty / reasoning-only judge reply as a grading
149
+ // FAILURE rather than recording a confident weightedTotal ≈ 1.0: if the judge
150
+ // scored not a single rubric dimension, coerceJudgeScores would silently floor
151
+ // every dimension to 1, which is indistinguishable from a real bottom grade and
152
+ // would pollute the comparison grid. Throw instead so the cell records the error.
153
+ const parsed = extractJson(judged.text);
154
+ if (gradedDimensionCount(rubric, parsed) === 0) {
155
+ throw new Error('The judge returned no parseable rubric scores (empty or non-JSON reply).');
156
+ }
157
+ const scores = coerceJudgeScores(rubric, parsed);
158
+ const grade = {
159
+ id: this.deps.idGenerator.next('sbg'),
160
+ runId: run.id,
161
+ judgeModel: experiment.judgeModel,
162
+ scores,
163
+ weightedTotal: weightedTotal(meta.rubric, scores),
164
+ objective: objectiveFor(fixture, done.outputText ?? ''),
165
+ createdAt: this.deps.clock.now(),
166
+ };
167
+ await this.deps.sandboxGradeRepository.upsert(workspaceId, grade);
168
+ graded++;
169
+ }
170
+ catch (e) {
171
+ await this.deps.sandboxRunRepository.upsert(workspaceId, {
172
+ ...done,
173
+ error: `Grading failed: ${e instanceof Error ? e.message : String(e)}`,
174
+ });
175
+ }
176
+ }
177
+ }
178
+ finally {
179
+ // Settle the terminal status from the outcomes: any cell that was actually graded
180
+ // → `done`, otherwise `failed` (every candidate failed, OR every grade failed — the
181
+ // grid carries no usable scores either way). This always runs, so the experiment is
182
+ // never left `running`.
183
+ await this.deps.sandboxExperimentRepository.setStatus(workspaceId, experimentId, graded > 0 ? 'done' : 'failed');
184
+ }
185
+ return this.detail(workspaceId, experimentId);
186
+ }
187
+ // ---- internals ------------------------------------------------------------
188
+ async failRun(workspaceId, run, error) {
189
+ await this.deps.sandboxRunRepository.upsert(workspaceId, {
190
+ ...run,
191
+ status: 'failed',
192
+ error,
193
+ finishedAt: this.deps.clock.now(),
194
+ });
195
+ }
196
+ /** Resolve every prompt version referenced by the matrix to its system text + label. */
197
+ async resolvePrompts(workspaceId, experiment) {
198
+ const baselines = listBaselines(this.deps.clock.now());
199
+ const map = new Map();
200
+ for (const id of new Set(experiment.matrix.promptVersionIds)) {
201
+ if (id.startsWith('baseline:')) {
202
+ const baseline = baselines.find((b) => b.id === id);
203
+ if (!baseline)
204
+ throw new ValidationError(`Unknown baseline prompt "${id}"`);
205
+ map.set(id, { systemText: baseline.systemText, label: baseline.name });
206
+ }
207
+ else {
208
+ const version = assertFound(await this.deps.sandboxPromptVersionRepository.get(workspaceId, id), 'SandboxPromptVersion', id);
209
+ map.set(id, { systemText: version.systemText, label: versionLabel(version) });
210
+ }
211
+ }
212
+ return map;
213
+ }
214
+ /** Resolve every fixture referenced by the matrix (stored, else builtin), refusing repo fixtures. */
215
+ async resolveFixtures(workspaceId, experiment) {
216
+ const builtins = new Map(listBuiltinFixtures(this.deps.clock.now()).map((f) => [f.id, f]));
217
+ const map = new Map();
218
+ for (const id of new Set(experiment.matrix.fixtureIds)) {
219
+ const fixture = (await this.deps.sandboxFixtureRepository.get(workspaceId, id)) ?? builtins.get(id);
220
+ if (!fixture)
221
+ throw new ValidationError(`Unknown fixture "${id}"`);
222
+ if (SANDBOX_REPO_FIXTURE_KINDS.includes(fixture.kind)) {
223
+ throw new ValidationError(`Fixture "${fixture.name}" needs a repository checkout; repo fixtures are not yet supported in the Sandbox.`);
224
+ }
225
+ map.set(id, fixture);
226
+ }
227
+ return map;
228
+ }
229
+ /** The model provider for a workspace's scope (per-scope DB pool, else the static one). */
230
+ async providerFor(workspaceId) {
231
+ const provider = await resolveScopedModelProvider(workspaceId, this.deps);
232
+ if (!provider)
233
+ throw new ValidationError('No model provider is configured for the Sandbox');
234
+ return provider;
235
+ }
236
+ /** A catalog id → inline-servable {@link ModelRef} (subscription models degrade to the default). */
237
+ refFor(modelId) {
238
+ const resolved = this.deps.resolveModelId?.(modelId) ?? parseModelCatalogId(modelId);
239
+ return inlineModelRef(resolved, this.deps.defaultModelRef ?? resolved);
240
+ }
241
+ detail(workspaceId, experimentId) {
242
+ return composeExperimentDetail(this.deps, workspaceId, experimentId);
243
+ }
244
+ }
245
+ function expectationsOf(fixture) {
246
+ return fixture.objective?.kind === 'findings' ? fixture.objective.expectations : [];
247
+ }
248
+ //# sourceMappingURL=SandboxRunService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SandboxRunService.js","sourceRoot":"","sources":["../../../src/modules/sandbox/SandboxRunService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ import type { Clock, IdGenerator, ModelRef, SandboxExperiment, SandboxExperimentRepository, SandboxFixture, SandboxFixtureRepository, SandboxGrade, SandboxGradeRepository, SandboxPromptVersion, SandboxPromptVersionRepository, SandboxRun, SandboxRunRepository, WorkspaceRepository } from '@cat-factory/kernel';
2
+ import type { CreateSandboxExperimentInput, CreateSandboxFixtureInput, CloneSandboxPromptInput, SaveSandboxVersionInput, SetSandboxLabelsInput } from '@cat-factory/contracts';
3
+ import { type SandboxAgentKindMeta } from '@cat-factory/sandbox';
4
+ /** A safety ceiling on how many cells one experiment may expand to (cost guard). */
5
+ export declare const MAX_SANDBOX_CELLS = 100;
6
+ /** The composed experiment view: the experiment plus its result grid (cells + grades). */
7
+ export interface SandboxExperimentDetail {
8
+ experiment: SandboxExperiment;
9
+ runs: SandboxRun[];
10
+ grades: SandboxGrade[];
11
+ }
12
+ /** The three repositories needed to compose an {@link SandboxExperimentDetail}. */
13
+ export interface SandboxDetailRepositories {
14
+ sandboxExperimentRepository: SandboxExperimentRepository;
15
+ sandboxRunRepository: SandboxRunRepository;
16
+ sandboxGradeRepository: SandboxGradeRepository;
17
+ }
18
+ /**
19
+ * Load an experiment and its result grid (cells + grades). Shared by the read endpoint
20
+ * (`SandboxService.getExperiment`) and the run-driver's returned grid
21
+ * (`SandboxRunService.launch`) so the two can never compose a divergent detail shape.
22
+ */
23
+ export declare function composeExperimentDetail(repos: SandboxDetailRepositories, workspaceId: string, experimentId: string): Promise<SandboxExperimentDetail>;
24
+ /** The opt-in Sandbox overview the management surface loads on open. */
25
+ export interface SandboxOverview {
26
+ agentKinds: readonly SandboxAgentKindMeta[];
27
+ prompts: SandboxPromptVersion[];
28
+ fixtures: SandboxFixture[];
29
+ experiments: SandboxExperiment[];
30
+ /**
31
+ * The matrix cell cap (the cost guard {@link MAX_SANDBOX_CELLS} enforced at create). Surfaced
32
+ * so the UI gates the builder on the SAME limit instead of re-encoding the literal, which
33
+ * would silently disagree if the cap ever changes.
34
+ */
35
+ maxCells: number;
36
+ }
37
+ export interface SandboxServiceDependencies {
38
+ sandboxPromptVersionRepository: SandboxPromptVersionRepository;
39
+ sandboxFixtureRepository: SandboxFixtureRepository;
40
+ sandboxExperimentRepository: SandboxExperimentRepository;
41
+ sandboxRunRepository: SandboxRunRepository;
42
+ sandboxGradeRepository: SandboxGradeRepository;
43
+ workspaceRepository: WorkspaceRepository;
44
+ idGenerator: IdGenerator;
45
+ clock: Clock;
46
+ /** The routing default model ref, used to default an experiment's judge model. */
47
+ defaultModelRef?: ModelRef;
48
+ }
49
+ /**
50
+ * Management CRUD for the Sandbox (the parallel prompt/model testing surface): the
51
+ * shipped baselines + stored candidate prompt versions, the fixture library (builtins
52
+ * seeded lazily on first list, plus workspace-authored ones), and experiment definitions
53
+ * + their result grids. Running an experiment lives in {@link SandboxRunService}; this
54
+ * service is the persistence-facing half. Everything is workspace-scoped.
55
+ */
56
+ export declare class SandboxService {
57
+ private readonly deps;
58
+ constructor(deps: SandboxServiceDependencies);
59
+ /** The full opt-in overview the UI loads when the Sandbox surface opens. */
60
+ overview(workspaceId: string): Promise<SandboxOverview>;
61
+ /** The shipped baselines (synthetic) followed by stored candidate versions. */
62
+ listPrompts(workspaceId: string, agentKind?: string): Promise<SandboxPromptVersion[]>;
63
+ /** Clone a shipped baseline into a fresh editable candidate lineage at version 1. */
64
+ clonePrompt(workspaceId: string, input: CloneSandboxPromptInput): Promise<SandboxPromptVersion>;
65
+ /** Append a new candidate version. The parent may be a baseline (starts a lineage) or a candidate. */
66
+ saveVersion(workspaceId: string, input: SaveSandboxVersionInput): Promise<SandboxPromptVersion>;
67
+ /** Replace a candidate version's labels. */
68
+ setLabels(workspaceId: string, id: string, input: SetSandboxLabelsInput): Promise<SandboxPromptVersion>;
69
+ /** Soft-archive a candidate version (hidden from the default listing). */
70
+ archivePrompt(workspaceId: string, id: string): Promise<void>;
71
+ /** The fixture library, seeding the builtin fixtures on first use. */
72
+ listFixtures(workspaceId: string): Promise<SandboxFixture[]>;
73
+ /** Create a workspace-authored fixture. */
74
+ createFixture(workspaceId: string, input: CreateSandboxFixtureInput): Promise<SandboxFixture>;
75
+ /** Remove a workspace-authored fixture. Builtin fixtures cannot be removed. */
76
+ removeFixture(workspaceId: string, id: string): Promise<void>;
77
+ listExperiments(workspaceId: string): Promise<SandboxExperiment[]>;
78
+ /** An experiment with its result grid (cells + grades). */
79
+ getExperiment(workspaceId: string, id: string): Promise<SandboxExperimentDetail>;
80
+ /** Create a draft experiment. Launching it (the run-driver) expands + grades the matrix. */
81
+ createExperiment(workspaceId: string, input: CreateSandboxExperimentInput): Promise<SandboxExperiment>;
82
+ /** Resolve the shipped baseline a clone derives from (by base-prompt id, else by kind). */
83
+ private resolveBaseline;
84
+ /** Seed the builtin fixture library for a workspace that has none yet. Idempotent. */
85
+ private ensureBuiltinFixtures;
86
+ /**
87
+ * The judge model to use when the caller didn't pick one: the deployment's routing
88
+ * default. We do NOT guess a provider — if no default is configured (e.g. a minimal
89
+ * deployment), require an explicit `judgeModel` at create time rather than defaulting to
90
+ * a vendor that may have no key, which would otherwise fail every cell's grade at launch.
91
+ */
92
+ private defaultJudgeModel;
93
+ }
94
+ //# sourceMappingURL=SandboxService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SandboxService.d.ts","sourceRoot":"","sources":["../../../src/modules/sandbox/SandboxService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,227 @@
1
+ import { assertFound, ConflictError, requireWorkspace, ValidationError } from '@cat-factory/kernel';
2
+ import { cellCount, firstVersionFromBaseline, isRunnableMatrix, listBaselines, listBuiltinFixtures, nextVersion, SANDBOX_AGENT_KINDS, baselineVersionId, sandboxKindMeta, } from '@cat-factory/sandbox';
3
+ /** A safety ceiling on how many cells one experiment may expand to (cost guard). */
4
+ export const MAX_SANDBOX_CELLS = 100;
5
+ /**
6
+ * Load an experiment and its result grid (cells + grades). Shared by the read endpoint
7
+ * (`SandboxService.getExperiment`) and the run-driver's returned grid
8
+ * (`SandboxRunService.launch`) so the two can never compose a divergent detail shape.
9
+ */
10
+ export async function composeExperimentDetail(repos, workspaceId, experimentId) {
11
+ const experiment = assertFound(await repos.sandboxExperimentRepository.get(workspaceId, experimentId), 'SandboxExperiment', experimentId);
12
+ const [runs, grades] = await Promise.all([
13
+ repos.sandboxRunRepository.listByExperiment(workspaceId, experimentId),
14
+ repos.sandboxGradeRepository.listByExperiment(workspaceId, experimentId),
15
+ ]);
16
+ return { experiment, runs, grades };
17
+ }
18
+ /**
19
+ * Management CRUD for the Sandbox (the parallel prompt/model testing surface): the
20
+ * shipped baselines + stored candidate prompt versions, the fixture library (builtins
21
+ * seeded lazily on first list, plus workspace-authored ones), and experiment definitions
22
+ * + their result grids. Running an experiment lives in {@link SandboxRunService}; this
23
+ * service is the persistence-facing half. Everything is workspace-scoped.
24
+ */
25
+ export class SandboxService {
26
+ deps;
27
+ constructor(deps) {
28
+ this.deps = deps;
29
+ }
30
+ /** The full opt-in overview the UI loads when the Sandbox surface opens. */
31
+ async overview(workspaceId) {
32
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
33
+ const [prompts, fixtures, experiments] = await Promise.all([
34
+ this.listPrompts(workspaceId),
35
+ this.listFixtures(workspaceId),
36
+ this.deps.sandboxExperimentRepository.list(workspaceId),
37
+ ]);
38
+ return {
39
+ agentKinds: SANDBOX_AGENT_KINDS,
40
+ prompts,
41
+ fixtures,
42
+ experiments,
43
+ maxCells: MAX_SANDBOX_CELLS,
44
+ };
45
+ }
46
+ // ---- prompt versions ------------------------------------------------------
47
+ /** The shipped baselines (synthetic) followed by stored candidate versions. */
48
+ async listPrompts(workspaceId, agentKind) {
49
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
50
+ const baselines = listBaselines(this.deps.clock.now());
51
+ const candidates = agentKind
52
+ ? await this.deps.sandboxPromptVersionRepository.listByKind(workspaceId, agentKind)
53
+ : await this.deps.sandboxPromptVersionRepository.list(workspaceId);
54
+ const baseSlice = agentKind ? baselines.filter((b) => b.agentKind === agentKind) : baselines;
55
+ return [...baseSlice, ...candidates];
56
+ }
57
+ /** Clone a shipped baseline into a fresh editable candidate lineage at version 1. */
58
+ async clonePrompt(workspaceId, input) {
59
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
60
+ const source = this.resolveBaseline(input.agentKind, input.basePromptId);
61
+ const meta = sandboxKindMeta(input.agentKind);
62
+ const name = input.name ?? meta?.label ?? input.agentKind;
63
+ const version = firstVersionFromBaseline({
64
+ agentKind: source.agentKind,
65
+ systemText: source.systemText,
66
+ basePromptId: source.basePromptId,
67
+ }, name, {
68
+ id: this.deps.idGenerator.next('sbp'),
69
+ createdAt: this.deps.clock.now(),
70
+ createdBy: null,
71
+ labels: input.labels ?? [],
72
+ });
73
+ await this.deps.sandboxPromptVersionRepository.upsert(workspaceId, version);
74
+ return version;
75
+ }
76
+ /** Append a new candidate version. The parent may be a baseline (starts a lineage) or a candidate. */
77
+ async saveVersion(workspaceId, input) {
78
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
79
+ const fields = {
80
+ id: this.deps.idGenerator.next('sbp'),
81
+ createdAt: this.deps.clock.now(),
82
+ createdBy: null,
83
+ labels: input.labels ?? [],
84
+ };
85
+ if (input.parentId.startsWith('baseline:')) {
86
+ const baseline = listBaselines(this.deps.clock.now()).find((b) => b.id === input.parentId);
87
+ if (!baseline)
88
+ throw new ValidationError(`Unknown baseline prompt "${input.parentId}"`);
89
+ const meta = sandboxKindMeta(baseline.agentKind);
90
+ const version = firstVersionFromBaseline({
91
+ agentKind: baseline.agentKind,
92
+ systemText: input.systemText,
93
+ basePromptId: baseline.basePromptId,
94
+ }, meta?.label ?? baseline.agentKind, fields);
95
+ await this.deps.sandboxPromptVersionRepository.upsert(workspaceId, version);
96
+ return version;
97
+ }
98
+ const parent = assertFound(await this.deps.sandboxPromptVersionRepository.get(workspaceId, input.parentId), 'SandboxPromptVersion', input.parentId);
99
+ const version = nextVersion(parent, input.systemText, fields);
100
+ await this.deps.sandboxPromptVersionRepository.upsert(workspaceId, version);
101
+ return version;
102
+ }
103
+ /** Replace a candidate version's labels. */
104
+ async setLabels(workspaceId, id, input) {
105
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
106
+ const existing = assertFound(await this.deps.sandboxPromptVersionRepository.get(workspaceId, id), 'SandboxPromptVersion', id);
107
+ const updated = { ...existing, labels: input.labels };
108
+ await this.deps.sandboxPromptVersionRepository.upsert(workspaceId, updated);
109
+ return updated;
110
+ }
111
+ /** Soft-archive a candidate version (hidden from the default listing). */
112
+ async archivePrompt(workspaceId, id) {
113
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
114
+ await this.deps.sandboxPromptVersionRepository.archive(workspaceId, id, this.deps.clock.now());
115
+ }
116
+ // ---- fixtures -------------------------------------------------------------
117
+ /** The fixture library, seeding the builtin fixtures on first use. */
118
+ async listFixtures(workspaceId) {
119
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
120
+ await this.ensureBuiltinFixtures(workspaceId);
121
+ return this.deps.sandboxFixtureRepository.list(workspaceId);
122
+ }
123
+ /** Create a workspace-authored fixture. */
124
+ async createFixture(workspaceId, input) {
125
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
126
+ const fixture = {
127
+ id: this.deps.idGenerator.next('sbf'),
128
+ kind: input.kind,
129
+ name: input.name,
130
+ payload: input.payload ?? null,
131
+ repoRef: input.repoRef ?? null,
132
+ objective: input.objective ?? null,
133
+ origin: 'custom',
134
+ createdAt: this.deps.clock.now(),
135
+ };
136
+ await this.deps.sandboxFixtureRepository.upsert(workspaceId, fixture);
137
+ return fixture;
138
+ }
139
+ /** Remove a workspace-authored fixture. Builtin fixtures cannot be removed. */
140
+ async removeFixture(workspaceId, id) {
141
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
142
+ const existing = await this.deps.sandboxFixtureRepository.get(workspaceId, id);
143
+ if (existing?.origin === 'builtin') {
144
+ throw new ConflictError('Builtin fixtures cannot be deleted.');
145
+ }
146
+ await this.deps.sandboxFixtureRepository.remove(workspaceId, id);
147
+ }
148
+ // ---- experiments ----------------------------------------------------------
149
+ async listExperiments(workspaceId) {
150
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
151
+ return this.deps.sandboxExperimentRepository.list(workspaceId);
152
+ }
153
+ /** An experiment with its result grid (cells + grades). */
154
+ async getExperiment(workspaceId, id) {
155
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
156
+ return composeExperimentDetail(this.deps, workspaceId, id);
157
+ }
158
+ /** Create a draft experiment. Launching it (the run-driver) expands + grades the matrix. */
159
+ async createExperiment(workspaceId, input) {
160
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
161
+ const meta = sandboxKindMeta(input.agentKind);
162
+ if (!meta) {
163
+ throw new ValidationError(`"${input.agentKind}" is not a Sandbox-testable agent kind`);
164
+ }
165
+ // Refuse container kinds up front: the in-product run driver only runs inline cells,
166
+ // so a container experiment could be persisted but never launched. Reject at create
167
+ // time rather than leaving an un-launchable draft in the workspace.
168
+ if (meta.bucket === 'container') {
169
+ throw new ValidationError(`The "${input.agentKind}" agent runs in a container; container experiments are not yet supported in the Sandbox.`);
170
+ }
171
+ if (!isRunnableMatrix(input.matrix)) {
172
+ throw new ValidationError('The experiment matrix needs at least one prompt, model and fixture');
173
+ }
174
+ const repeats = input.repeats ?? 1;
175
+ const total = cellCount(input.matrix, repeats);
176
+ if (total > MAX_SANDBOX_CELLS) {
177
+ throw new ValidationError(`This matrix expands to ${total} cells; the limit is ${MAX_SANDBOX_CELLS}. Narrow the selection.`);
178
+ }
179
+ const experiment = {
180
+ id: this.deps.idGenerator.next('sbx'),
181
+ name: input.name,
182
+ agentKind: input.agentKind,
183
+ judgeModel: input.judgeModel ?? this.defaultJudgeModel(),
184
+ repeats,
185
+ status: 'draft',
186
+ matrix: input.matrix,
187
+ budgetTokens: input.budgetTokens ?? null,
188
+ createdAt: this.deps.clock.now(),
189
+ createdBy: null,
190
+ };
191
+ await this.deps.sandboxExperimentRepository.upsert(workspaceId, experiment);
192
+ return experiment;
193
+ }
194
+ // ---- internals ------------------------------------------------------------
195
+ /** Resolve the shipped baseline a clone derives from (by base-prompt id, else by kind). */
196
+ resolveBaseline(agentKind, basePromptId) {
197
+ const baselines = listBaselines(this.deps.clock.now());
198
+ const wantedId = basePromptId ? `baseline:${basePromptId}` : baselineVersionId(agentKind);
199
+ const source = baselines.find((b) => b.id === wantedId) ?? baselines.find((b) => b.agentKind === agentKind);
200
+ if (!source)
201
+ throw new ValidationError(`No baseline prompt for agent kind "${agentKind}"`);
202
+ return source;
203
+ }
204
+ /** Seed the builtin fixture library for a workspace that has none yet. Idempotent. */
205
+ async ensureBuiltinFixtures(workspaceId) {
206
+ const current = await this.deps.sandboxFixtureRepository.list(workspaceId);
207
+ if (current.length > 0)
208
+ return;
209
+ for (const fixture of listBuiltinFixtures(this.deps.clock.now())) {
210
+ await this.deps.sandboxFixtureRepository.upsert(workspaceId, fixture);
211
+ }
212
+ }
213
+ /**
214
+ * The judge model to use when the caller didn't pick one: the deployment's routing
215
+ * default. We do NOT guess a provider — if no default is configured (e.g. a minimal
216
+ * deployment), require an explicit `judgeModel` at create time rather than defaulting to
217
+ * a vendor that may have no key, which would otherwise fail every cell's grade at launch.
218
+ */
219
+ defaultJudgeModel() {
220
+ const ref = this.deps.defaultModelRef;
221
+ if (!ref) {
222
+ throw new ValidationError('No default model is configured for the Sandbox judge; specify judgeModel explicitly.');
223
+ }
224
+ return `${ref.provider}:${ref.model}`;
225
+ }
226
+ }
227
+ //# sourceMappingURL=SandboxService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SandboxService.js","sourceRoot":"","sources":["../../../src/modules/sandbox/SandboxService.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAQnG,OAAO,EACL,SAAS,EACT,wBAAwB,EACxB,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EAEnB,iBAAiB,EACjB,eAAe,GAChB,MAAM,sBAAsB,CAAA;AAE7B,oFAAoF;AACpF,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAA;AAgBpC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,KAAgC,EAChC,WAAmB,EACnB,YAAoB;IAEpB,MAAM,UAAU,GAAG,WAAW,CAC5B,MAAM,KAAK,CAAC,2BAA2B,CAAC,GAAG,CAAC,WAAW,EAAE,YAAY,CAAC,EACtE,mBAAmB,EACnB,YAAY,CACb,CAAA;IACD,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACvC,KAAK,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,WAAW,EAAE,YAAY,CAAC;QACtE,KAAK,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,WAAW,EAAE,YAAY,CAAC;KACzE,CAAC,CAAA;IACF,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AACrC,CAAC;AA6BD;;;;;;GAMG;AACH,MAAM,OAAO,cAAc;IACI,IAAI;IAAjC,YAA6B,IAAgC;oBAAhC,IAAI;IAA+B,CAAC;IAEjE,4EAA4E;IAC5E,KAAK,CAAC,QAAQ,CAAC,WAAmB;QAChC,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACzD,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC;YAC7B,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,WAAW,CAAC;SACxD,CAAC,CAAA;QACF,OAAO;YACL,UAAU,EAAE,mBAAmB;YAC/B,OAAO;YACP,QAAQ;YACR,WAAW;YACX,QAAQ,EAAE,iBAAiB;SAC5B,CAAA;IACH,CAAC;IAED,8EAA8E;IAE9E,+EAA+E;IAC/E,KAAK,CAAC,WAAW,CAAC,WAAmB,EAAE,SAAkB;QACvD,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;QACtD,MAAM,UAAU,GAAG,SAAS;YAC1B,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,CAAC;YACnF,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QACpE,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAC5F,OAAO,CAAC,GAAG,SAAS,EAAE,GAAG,UAAU,CAAC,CAAA;IACtC,CAAC;IAED,qFAAqF;IACrF,KAAK,CAAC,WAAW,CACf,WAAmB,EACnB,KAA8B;QAE9B,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,YAAY,CAAC,CAAA;QACxE,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC,SAAS,CAAA;QACzD,MAAM,OAAO,GAAG,wBAAwB,CACtC;YACE,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,YAAY,EAAE,MAAM,CAAC,YAAY;SAClC,EACD,IAAI,EACJ;YACE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;YACrC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YAChC,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE;SAC3B,CACF,CAAA;QACD,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QAC3E,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,sGAAsG;IACtG,KAAK,CAAC,WAAW,CACf,WAAmB,EACnB,KAA8B;QAE9B,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,MAAM,MAAM,GAAG;YACb,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;YACrC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YAChC,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE;SAC3B,CAAA;QACD,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3C,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,QAAQ,CAAC,CAAA;YAC1F,IAAI,CAAC,QAAQ;gBAAE,MAAM,IAAI,eAAe,CAAC,4BAA4B,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAA;YACvF,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;YAChD,MAAM,OAAO,GAAG,wBAAwB,CACtC;gBACE,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,YAAY,EAAE,QAAQ,CAAC,YAAY;aACpC,EACD,IAAI,EAAE,KAAK,IAAI,QAAQ,CAAC,SAAS,EACjC,MAAM,CACP,CAAA;YACD,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;YAC3E,OAAO,OAAO,CAAA;QAChB,CAAC;QACD,MAAM,MAAM,GAAG,WAAW,CACxB,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,EAC/E,sBAAsB,EACtB,KAAK,CAAC,QAAQ,CACf,CAAA;QACD,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;QAC7D,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QAC3E,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,4CAA4C;IAC5C,KAAK,CAAC,SAAS,CACb,WAAmB,EACnB,EAAU,EACV,KAA4B;QAE5B,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,MAAM,QAAQ,GAAG,WAAW,CAC1B,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,EACnE,sBAAsB,EACtB,EAAE,CACH,CAAA;QACD,MAAM,OAAO,GAAG,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAA;QACrD,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QAC3E,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,0EAA0E;IAC1E,KAAK,CAAC,aAAa,CAAC,WAAmB,EAAE,EAAU;QACjD,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;IAChG,CAAC;IAED,8EAA8E;IAE9E,sEAAsE;IACtE,KAAK,CAAC,YAAY,CAAC,WAAmB;QACpC,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAA;QAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IAC7D,CAAC;IAED,2CAA2C;IAC3C,KAAK,CAAC,aAAa,CACjB,WAAmB,EACnB,KAAgC;QAEhC,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,MAAM,OAAO,GAAmB;YAC9B,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;YACrC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;YAC9B,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;YAC9B,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI;YAClC,MAAM,EAAE,QAAQ;YAChB,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;SACjC,CAAA;QACD,MAAM,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QACrE,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,+EAA+E;IAC/E,KAAK,CAAC,aAAa,CAAC,WAAmB,EAAE,EAAU;QACjD,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;QAC9E,IAAI,QAAQ,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,IAAI,aAAa,CAAC,qCAAqC,CAAC,CAAA;QAChE,CAAC;QACD,MAAM,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;IAClE,CAAC;IAED,8EAA8E;IAE9E,KAAK,CAAC,eAAe,CAAC,WAAmB;QACvC,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,OAAO,IAAI,CAAC,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IAChE,CAAC;IAED,2DAA2D;IAC3D,KAAK,CAAC,aAAa,CAAC,WAAmB,EAAE,EAAU;QACjD,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,OAAO,uBAAuB,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,CAAA;IAC5D,CAAC;IAED,4FAA4F;IAC5F,KAAK,CAAC,gBAAgB,CACpB,WAAmB,EACnB,KAAmC;QAEnC,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,eAAe,CAAC,IAAI,KAAK,CAAC,SAAS,wCAAwC,CAAC,CAAA;QACxF,CAAC;QACD,qFAAqF;QACrF,oFAAoF;QACpF,oEAAoE;QACpE,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAChC,MAAM,IAAI,eAAe,CACvB,QAAQ,KAAK,CAAC,SAAS,0FAA0F,CAClH,CAAA;QACH,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,eAAe,CACvB,oEAAoE,CACrE,CAAA;QACH,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;QAClC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC9C,IAAI,KAAK,GAAG,iBAAiB,EAAE,CAAC;YAC9B,MAAM,IAAI,eAAe,CACvB,0BAA0B,KAAK,wBAAwB,iBAAiB,yBAAyB,CAClG,CAAA;QACH,CAAC;QACD,MAAM,UAAU,GAAsB;YACpC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;YACrC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,IAAI,CAAC,iBAAiB,EAAE;YACxD,OAAO;YACP,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,IAAI;YACxC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YAChC,SAAS,EAAE,IAAI;SAChB,CAAA;QACD,MAAM,IAAI,CAAC,IAAI,CAAC,2BAA2B,CAAC,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,CAAA;QAC3E,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,8EAA8E;IAE9E,2FAA2F;IACnF,eAAe,CAAC,SAAiB,EAAE,YAA2B;QACpE,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;QACtD,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,YAAY,YAAY,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAA;QACzF,MAAM,MAAM,GACV,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAA;QAC9F,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,eAAe,CAAC,sCAAsC,SAAS,GAAG,CAAC,CAAA;QAC1F,OAAO,MAAM,CAAA;IACf,CAAC;IAED,sFAAsF;IAC9E,KAAK,CAAC,qBAAqB,CAAC,WAAmB;QACrD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAC1E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAM;QAC9B,KAAK,MAAM,OAAO,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;YACjE,MAAM,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QACvE,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,iBAAiB;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAA;QACrC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,eAAe,CACvB,sFAAsF,CACvF,CAAA;QACH,CAAC;QACD,OAAO,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,KAAK,EAAE,CAAA;IACvC,CAAC;CACF"}