elasticdash-test 0.1.26 → 0.1.27

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 (85) hide show
  1. package/README.md +100 -0
  2. package/dist/cli.js +175 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/index.cjs +62 -1
  5. package/dist/index.d.ts +2 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +2 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/tool-registry.d.ts +31 -0
  10. package/dist/tool-registry.d.ts.map +1 -0
  11. package/dist/tool-registry.js +73 -0
  12. package/dist/tool-registry.js.map +1 -0
  13. package/dist/tool-runner-worker.js +19 -2
  14. package/dist/tool-runner-worker.js.map +1 -1
  15. package/dist/utils/debug.d.ts +1 -1
  16. package/dist/utils/debug.d.ts.map +1 -1
  17. package/dist/utils/debug.js +2 -2
  18. package/dist/utils/debug.js.map +1 -1
  19. package/docs/observability_contract.md +192 -0
  20. package/package.json +2 -2
  21. package/src/cli.ts +184 -0
  22. package/src/index.ts +4 -0
  23. package/src/tool-registry.ts +94 -0
  24. package/src/tool-runner-worker.ts +17 -2
  25. package/src/utils/debug.ts +2 -2
  26. package/dist/cloud-client.d.ts +0 -34
  27. package/dist/cloud-client.d.ts.map +0 -1
  28. package/dist/cloud-client.js +0 -103
  29. package/dist/cloud-client.js.map +0 -1
  30. package/dist/evaluators/determinism.d.ts +0 -3
  31. package/dist/evaluators/determinism.d.ts.map +0 -1
  32. package/dist/evaluators/determinism.js +0 -116
  33. package/dist/evaluators/determinism.js.map +0 -1
  34. package/dist/evaluators/index.d.ts +0 -4
  35. package/dist/evaluators/index.d.ts.map +0 -1
  36. package/dist/evaluators/index.js +0 -61
  37. package/dist/evaluators/index.js.map +0 -1
  38. package/dist/evaluators/latency-budget.d.ts +0 -3
  39. package/dist/evaluators/latency-budget.d.ts.map +0 -1
  40. package/dist/evaluators/latency-budget.js +0 -45
  41. package/dist/evaluators/latency-budget.js.map +0 -1
  42. package/dist/evaluators/llm-judge.d.ts +0 -3
  43. package/dist/evaluators/llm-judge.d.ts.map +0 -1
  44. package/dist/evaluators/llm-judge.js +0 -125
  45. package/dist/evaluators/llm-judge.js.map +0 -1
  46. package/dist/evaluators/output-contains.d.ts +0 -3
  47. package/dist/evaluators/output-contains.d.ts.map +0 -1
  48. package/dist/evaluators/output-contains.js +0 -52
  49. package/dist/evaluators/output-contains.js.map +0 -1
  50. package/dist/evaluators/output-schema.d.ts +0 -3
  51. package/dist/evaluators/output-schema.d.ts.map +0 -1
  52. package/dist/evaluators/output-schema.js +0 -58
  53. package/dist/evaluators/output-schema.js.map +0 -1
  54. package/dist/evaluators/token-budget.d.ts +0 -3
  55. package/dist/evaluators/token-budget.d.ts.map +0 -1
  56. package/dist/evaluators/token-budget.js +0 -45
  57. package/dist/evaluators/token-budget.js.map +0 -1
  58. package/dist/evaluators/types.d.ts +0 -104
  59. package/dist/evaluators/types.d.ts.map +0 -1
  60. package/dist/evaluators/types.js +0 -6
  61. package/dist/evaluators/types.js.map +0 -1
  62. package/dist/test-group/cli.d.ts +0 -8
  63. package/dist/test-group/cli.d.ts.map +0 -1
  64. package/dist/test-group/cli.js +0 -162
  65. package/dist/test-group/cli.js.map +0 -1
  66. package/dist/test-group/git-context.d.ts +0 -3
  67. package/dist/test-group/git-context.d.ts.map +0 -1
  68. package/dist/test-group/git-context.js +0 -59
  69. package/dist/test-group/git-context.js.map +0 -1
  70. package/dist/test-group/reporter.d.ts +0 -4
  71. package/dist/test-group/reporter.d.ts.map +0 -1
  72. package/dist/test-group/reporter.js +0 -54
  73. package/dist/test-group/reporter.js.map +0 -1
  74. package/dist/test-group/runner.d.ts +0 -18
  75. package/dist/test-group/runner.d.ts.map +0 -1
  76. package/dist/test-group/runner.js +0 -234
  77. package/dist/test-group/runner.js.map +0 -1
  78. package/dist/tracing-universal.d.ts +0 -13
  79. package/dist/tracing-universal.d.ts.map +0 -1
  80. package/dist/tracing-universal.js +0 -33
  81. package/dist/tracing-universal.js.map +0 -1
  82. package/docs/backend_rerun_alignment.md +0 -291
  83. package/docs/backend_traceid_update.md +0 -141
  84. package/docs/observability_backend_contract.md +0 -577
  85. package/docs/observability_rerun_backend_plan.md +0 -596
@@ -1,125 +0,0 @@
1
- async function callJudgeLLM(prompt, output, model, provider) {
2
- const outputStr = typeof output === 'string' ? output : JSON.stringify(output, null, 2);
3
- const systemPrompt = `You are an evaluation judge. You will be given an output from an AI workflow and a criteria to evaluate it against. Respond with a single integer score from 0 to 10 on the first line, followed by a brief reasoning on the next line. 0 means completely failed, 10 means perfectly met.`;
4
- const userMessage = `## Criteria\n${prompt}\n\n## Output to evaluate\n${outputStr}\n\nScore from 0 to 10:`;
5
- if (provider === 'openai' || provider === 'default') {
6
- const apiKey = process.env.OPENAI_API_KEY;
7
- if (!apiKey)
8
- throw new Error('OPENAI_API_KEY not set (needed for LLM judge)');
9
- const res = await fetch('https://api.openai.com/v1/chat/completions', {
10
- method: 'POST',
11
- headers: {
12
- 'Authorization': `Bearer ${apiKey}`,
13
- 'Content-Type': 'application/json',
14
- },
15
- body: JSON.stringify({
16
- model,
17
- messages: [
18
- { role: 'system', content: systemPrompt },
19
- { role: 'user', content: userMessage },
20
- ],
21
- max_tokens: 200,
22
- temperature: 0,
23
- }),
24
- signal: AbortSignal.timeout(30_000),
25
- });
26
- if (!res.ok) {
27
- throw new Error(`OpenAI API error: ${res.status} ${res.statusText}`);
28
- }
29
- const json = await res.json();
30
- const content = json.choices?.[0]?.message?.content ?? '';
31
- return parseScoreVerdict(content);
32
- }
33
- if (provider === 'anthropic') {
34
- const apiKey = process.env.ANTHROPIC_API_KEY;
35
- if (!apiKey)
36
- throw new Error('ANTHROPIC_API_KEY not set (needed for LLM judge)');
37
- const res = await fetch('https://api.anthropic.com/v1/messages', {
38
- method: 'POST',
39
- headers: {
40
- 'x-api-key': apiKey,
41
- 'content-type': 'application/json',
42
- 'anthropic-version': '2023-06-01',
43
- },
44
- body: JSON.stringify({
45
- model,
46
- system: systemPrompt,
47
- messages: [{ role: 'user', content: userMessage }],
48
- max_tokens: 200,
49
- temperature: 0,
50
- }),
51
- signal: AbortSignal.timeout(30_000),
52
- });
53
- if (!res.ok) {
54
- throw new Error(`Anthropic API error: ${res.status} ${res.statusText}`);
55
- }
56
- const json = await res.json();
57
- const content = json.content?.[0]?.text ?? '';
58
- return parseScoreVerdict(content);
59
- }
60
- throw new Error(`Unsupported judge provider: ${provider}. Use 'openai' or 'anthropic'.`);
61
- }
62
- function parseScoreVerdict(content) {
63
- const lines = content.trim().split('\n');
64
- const firstLine = lines[0]?.trim() ?? '';
65
- const scoreMatch = firstLine.match(/(\d+)/);
66
- const score = scoreMatch ? Math.min(10, Math.max(0, parseInt(scoreMatch[1], 10))) : 0;
67
- const reasoning = lines.slice(1).join('\n').trim() || `Score: ${score}/10`;
68
- return { score, reasoning };
69
- }
70
- function resolveModel(expectation) {
71
- const provider = expectation.judgeProvider || detectProvider(expectation.judgeModel);
72
- const model = expectation.judgeModel || 'gpt-4o-mini';
73
- return { model, provider };
74
- }
75
- function detectProvider(model) {
76
- if (!model)
77
- return 'default';
78
- if (model.startsWith('claude'))
79
- return 'anthropic';
80
- return 'default';
81
- }
82
- export async function evaluateLLMJudge(expectation, runs) {
83
- if (!expectation.judgePrompt) {
84
- return {
85
- expectationId: expectation.id,
86
- type: 'llm-judge',
87
- passed: false,
88
- detail: 'No judge prompt provided',
89
- };
90
- }
91
- const threshold = expectation.judgeScoreThreshold ?? 7;
92
- const { model, provider } = resolveModel(expectation);
93
- const perRun = [];
94
- let allPassed = true;
95
- for (const run of runs) {
96
- try {
97
- const verdict = await callJudgeLLM(expectation.judgePrompt, run.output, model, provider === 'default' ? 'openai' : provider);
98
- const passed = verdict.score >= threshold;
99
- if (!passed)
100
- allPassed = false;
101
- perRun.push({
102
- runIndex: run.runIndex,
103
- passed,
104
- value: `${verdict.score}/10 — ${verdict.reasoning}`,
105
- });
106
- }
107
- catch (err) {
108
- allPassed = false;
109
- perRun.push({
110
- runIndex: run.runIndex,
111
- passed: false,
112
- value: `error: ${err.message}`,
113
- });
114
- }
115
- }
116
- const passedCount = perRun.filter((r) => r.passed).length;
117
- return {
118
- expectationId: expectation.id,
119
- type: 'llm-judge',
120
- passed: allPassed,
121
- detail: `${passedCount}/${runs.length} passed (threshold ≥ ${threshold}/10, model: ${model})`,
122
- perRun,
123
- };
124
- }
125
- //# sourceMappingURL=llm-judge.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"llm-judge.js","sourceRoot":"","sources":["../../src/evaluators/llm-judge.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import type { Expectation, SingleRunData, ExpectationResult } from './types.js';
2
- export declare function evaluateOutputContains(expectation: Expectation, runs: SingleRunData[]): ExpectationResult;
3
- //# sourceMappingURL=output-contains.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"output-contains.d.ts","sourceRoot":"","sources":["../../src/evaluators/output-contains.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAgB,MAAM,YAAY,CAAA;AAQ7F,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,aAAa,EAAE,GACpB,iBAAiB,CAgDnB"}
@@ -1,52 +0,0 @@
1
- function stringify(value) {
2
- if (typeof value === 'string')
3
- return value;
4
- if (value == null)
5
- return '';
6
- return JSON.stringify(value);
7
- }
8
- export function evaluateOutputContains(expectation, runs) {
9
- const perRun = [];
10
- let allPassed = true;
11
- for (const run of runs) {
12
- let output = stringify(run.output);
13
- let contains = expectation.containsText ?? '';
14
- let notContains = expectation.notContainsText ?? '';
15
- if (expectation.caseInsensitive) {
16
- output = output.toLowerCase();
17
- contains = contains.toLowerCase();
18
- notContains = notContains.toLowerCase();
19
- }
20
- let passed = true;
21
- const reasons = [];
22
- if (expectation.containsText && !output.includes(contains)) {
23
- passed = false;
24
- reasons.push(`missing "${expectation.containsText}"`);
25
- }
26
- if (expectation.notContainsText && output.includes(notContains)) {
27
- passed = false;
28
- reasons.push(`contains forbidden "${expectation.notContainsText}"`);
29
- }
30
- if (!passed)
31
- allPassed = false;
32
- perRun.push({
33
- runIndex: run.runIndex,
34
- passed,
35
- value: passed ? 'ok' : reasons.join('; '),
36
- });
37
- }
38
- const passedCount = perRun.filter((r) => r.passed).length;
39
- const parts = [`${passedCount}/${runs.length} passed`];
40
- if (expectation.containsText)
41
- parts.push(`contains: "${expectation.containsText}"`);
42
- if (expectation.notContainsText)
43
- parts.push(`excludes: "${expectation.notContainsText}"`);
44
- return {
45
- expectationId: expectation.id,
46
- type: 'output-contains',
47
- passed: allPassed,
48
- detail: parts.join(', '),
49
- perRun,
50
- };
51
- }
52
- //# sourceMappingURL=output-contains.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"output-contains.js","sourceRoot":"","sources":["../../src/evaluators/output-contains.ts"],"names":[],"mappings":"AAEA,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC3C,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,EAAE,CAAA;IAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,WAAwB,EACxB,IAAqB;IAErB,MAAM,MAAM,GAAmB,EAAE,CAAA;IACjC,IAAI,SAAS,GAAG,IAAI,CAAA;IAEpB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAClC,IAAI,QAAQ,GAAG,WAAW,CAAC,YAAY,IAAI,EAAE,CAAA;QAC7C,IAAI,WAAW,GAAG,WAAW,CAAC,eAAe,IAAI,EAAE,CAAA;QAEnD,IAAI,WAAW,CAAC,eAAe,EAAE,CAAC;YAChC,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAA;YAC7B,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAA;YACjC,WAAW,GAAG,WAAW,CAAC,WAAW,EAAE,CAAA;QACzC,CAAC;QAED,IAAI,MAAM,GAAG,IAAI,CAAA;QACjB,MAAM,OAAO,GAAa,EAAE,CAAA;QAE5B,IAAI,WAAW,CAAC,YAAY,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3D,MAAM,GAAG,KAAK,CAAA;YACd,OAAO,CAAC,IAAI,CAAC,YAAY,WAAW,CAAC,YAAY,GAAG,CAAC,CAAA;QACvD,CAAC;QAED,IAAI,WAAW,CAAC,eAAe,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAChE,MAAM,GAAG,KAAK,CAAA;YACd,OAAO,CAAC,IAAI,CAAC,uBAAuB,WAAW,CAAC,eAAe,GAAG,CAAC,CAAA;QACrE,CAAC;QAED,IAAI,CAAC,MAAM;YAAE,SAAS,GAAG,KAAK,CAAA;QAC9B,MAAM,CAAC,IAAI,CAAC;YACV,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,MAAM;YACN,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;SAC1C,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAA;IACzD,MAAM,KAAK,GAAa,CAAC,GAAG,WAAW,IAAI,IAAI,CAAC,MAAM,SAAS,CAAC,CAAA;IAChE,IAAI,WAAW,CAAC,YAAY;QAAE,KAAK,CAAC,IAAI,CAAC,cAAc,WAAW,CAAC,YAAY,GAAG,CAAC,CAAA;IACnF,IAAI,WAAW,CAAC,eAAe;QAAE,KAAK,CAAC,IAAI,CAAC,cAAc,WAAW,CAAC,eAAe,GAAG,CAAC,CAAA;IAEzF,OAAO;QACL,aAAa,EAAE,WAAW,CAAC,EAAE;QAC7B,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QACxB,MAAM;KACP,CAAA;AACH,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { Expectation, SingleRunData, ExpectationResult } from './types.js';
2
- export declare function evaluateOutputSchema(expectation: Expectation, runs: SingleRunData[]): Promise<ExpectationResult>;
3
- //# sourceMappingURL=output-schema.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"output-schema.d.ts","sourceRoot":"","sources":["../../src/evaluators/output-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAgB,MAAM,YAAY,CAAA;AAE7F,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,aAAa,EAAE,GACpB,OAAO,CAAC,iBAAiB,CAAC,CA4D5B"}
@@ -1,58 +0,0 @@
1
- export async function evaluateOutputSchema(expectation, runs) {
2
- if (!expectation.jsonSchema) {
3
- return {
4
- expectationId: expectation.id,
5
- type: 'output-schema',
6
- passed: true,
7
- detail: 'No JSON schema provided, skipped',
8
- };
9
- }
10
- // Dynamic import ajv — it's an optional dependency
11
- let Ajv;
12
- try {
13
- // @ts-ignore — ajv is an optional peer dependency
14
- Ajv = (await import('ajv')).default;
15
- }
16
- catch {
17
- return {
18
- expectationId: expectation.id,
19
- type: 'output-schema',
20
- passed: false,
21
- detail: 'ajv package not installed. Run: npm install ajv',
22
- };
23
- }
24
- const ajv = new Ajv({ allErrors: true });
25
- const validate = ajv.compile(expectation.jsonSchema);
26
- const perRun = [];
27
- let allPassed = true;
28
- for (const run of runs) {
29
- let data = run.output;
30
- // If output is a string, try to parse it as JSON
31
- if (typeof data === 'string') {
32
- try {
33
- data = JSON.parse(data);
34
- }
35
- catch {
36
- // leave as string — will likely fail validation
37
- }
38
- }
39
- const valid = validate(data);
40
- if (!valid) {
41
- allPassed = false;
42
- const errors = validate.errors?.map((e) => `${e.instancePath || '/'} ${e.message}`).join('; ') ?? 'unknown error';
43
- perRun.push({ runIndex: run.runIndex, passed: false, value: errors });
44
- }
45
- else {
46
- perRun.push({ runIndex: run.runIndex, passed: true, value: 'valid' });
47
- }
48
- }
49
- const passedCount = perRun.filter((r) => r.passed).length;
50
- return {
51
- expectationId: expectation.id,
52
- type: 'output-schema',
53
- passed: allPassed,
54
- detail: `${passedCount}/${runs.length} outputs match schema`,
55
- perRun,
56
- };
57
- }
58
- //# sourceMappingURL=output-schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"output-schema.js","sourceRoot":"","sources":["../../src/evaluators/output-schema.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,WAAwB,EACxB,IAAqB;IAErB,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;QAC5B,OAAO;YACL,aAAa,EAAE,WAAW,CAAC,EAAE;YAC7B,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,kCAAkC;SAC3C,CAAA;IACH,CAAC;IAED,mDAAmD;IACnD,IAAI,GAAQ,CAAA;IACZ,IAAI,CAAC;QACH,kDAAkD;QAClD,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAA;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,aAAa,EAAE,WAAW,CAAC,EAAE;YAC7B,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,iDAAiD;SAC1D,CAAA;IACH,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,CAAA;IAEpD,MAAM,MAAM,GAAmB,EAAE,CAAA;IACjC,IAAI,SAAS,GAAG,IAAI,CAAA;IAEpB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,IAAI,GAAG,GAAG,CAAC,MAAM,CAAA;QACrB,iDAAiD;QACjD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACzB,CAAC;YAAC,MAAM,CAAC;gBACP,gDAAgD;YAClD,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;QAC5B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,SAAS,GAAG,KAAK,CAAA;YACjB,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,YAAY,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,CAAA;YACtH,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACvE,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;QACvE,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAA;IAEzD,OAAO;QACL,aAAa,EAAE,WAAW,CAAC,EAAE;QAC7B,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,GAAG,WAAW,IAAI,IAAI,CAAC,MAAM,uBAAuB;QAC5D,MAAM;KACP,CAAA;AACH,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { Expectation, SingleRunData, ExpectationResult } from './types.js';
2
- export declare function evaluateTokenBudget(expectation: Expectation, runs: SingleRunData[]): ExpectationResult;
3
- //# sourceMappingURL=token-budget.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"token-budget.d.ts","sourceRoot":"","sources":["../../src/evaluators/token-budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAgB,MAAM,YAAY,CAAA;AAE7F,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,aAAa,EAAE,GACpB,iBAAiB,CAgDnB"}
@@ -1,45 +0,0 @@
1
- export function evaluateTokenBudget(expectation, runs) {
2
- const perRun = [];
3
- let allPassed = true;
4
- // Per-run check
5
- if (expectation.maxTokensPerRun != null) {
6
- for (const run of runs) {
7
- const tokens = run.tokenUsage.totalTokens;
8
- const passed = tokens <= expectation.maxTokensPerRun;
9
- if (!passed)
10
- allPassed = false;
11
- perRun.push({ runIndex: run.runIndex, passed, value: tokens });
12
- }
13
- }
14
- // Total check
15
- const totalTokens = runs.reduce((sum, r) => sum + r.tokenUsage.totalTokens, 0);
16
- if (expectation.maxTotalTokens != null && totalTokens > expectation.maxTotalTokens) {
17
- allPassed = false;
18
- }
19
- // If neither constraint is set, pass by default but populate per-run
20
- if (expectation.maxTokensPerRun == null && expectation.maxTotalTokens == null) {
21
- for (const run of runs) {
22
- perRun.push({ runIndex: run.runIndex, passed: true, value: run.tokenUsage.totalTokens });
23
- }
24
- }
25
- // Build detail string
26
- const avg = runs.length > 0 ? Math.round(totalTokens / runs.length) : 0;
27
- const parts = [];
28
- if (expectation.maxTokensPerRun != null) {
29
- const passedCount = perRun.filter((r) => r.passed).length;
30
- parts.push(`${passedCount}/${runs.length} runs under ${expectation.maxTokensPerRun} tokens/run`);
31
- }
32
- if (expectation.maxTotalTokens != null) {
33
- const totalPassed = totalTokens <= expectation.maxTotalTokens;
34
- parts.push(`total ${totalTokens} tokens ${totalPassed ? 'within' : 'exceeds'} ${expectation.maxTotalTokens} budget`);
35
- }
36
- parts.push(`avg ${avg} tokens/run`);
37
- return {
38
- expectationId: expectation.id,
39
- type: 'token-budget',
40
- passed: allPassed,
41
- detail: parts.join(', '),
42
- perRun: perRun.length > 0 ? perRun : undefined,
43
- };
44
- }
45
- //# sourceMappingURL=token-budget.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"token-budget.js","sourceRoot":"","sources":["../../src/evaluators/token-budget.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,mBAAmB,CACjC,WAAwB,EACxB,IAAqB;IAErB,MAAM,MAAM,GAAmB,EAAE,CAAA;IACjC,IAAI,SAAS,GAAG,IAAI,CAAA;IAEpB,gBAAgB;IAChB,IAAI,WAAW,CAAC,eAAe,IAAI,IAAI,EAAE,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC,WAAW,CAAA;YACzC,MAAM,MAAM,GAAG,MAAM,IAAI,WAAW,CAAC,eAAe,CAAA;YACpD,IAAI,CAAC,MAAM;gBAAE,SAAS,GAAG,KAAK,CAAA;YAC9B,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QAChE,CAAC;IACH,CAAC;IAED,cAAc;IACd,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;IAC9E,IAAI,WAAW,CAAC,cAAc,IAAI,IAAI,IAAI,WAAW,GAAG,WAAW,CAAC,cAAc,EAAE,CAAC;QACnF,SAAS,GAAG,KAAK,CAAA;IACnB,CAAC;IAED,qEAAqE;IACrE,IAAI,WAAW,CAAC,eAAe,IAAI,IAAI,IAAI,WAAW,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;QAC9E,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAA;QAC1F,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACvE,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,IAAI,WAAW,CAAC,eAAe,IAAI,IAAI,EAAE,CAAC;QACxC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAA;QACzD,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,IAAI,IAAI,CAAC,MAAM,eAAe,WAAW,CAAC,eAAe,aAAa,CAAC,CAAA;IAClG,CAAC;IACD,IAAI,WAAW,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;QACvC,MAAM,WAAW,GAAG,WAAW,IAAI,WAAW,CAAC,cAAc,CAAA;QAC7D,KAAK,CAAC,IAAI,CAAC,SAAS,WAAW,WAAW,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,IAAI,WAAW,CAAC,cAAc,SAAS,CAAC,CAAA;IACtH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,aAAa,CAAC,CAAA;IAEnC,OAAO;QACL,aAAa,EAAE,WAAW,CAAC,EAAE;QAC7B,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;KAC/C,CAAA;AACH,CAAC"}
@@ -1,104 +0,0 @@
1
- /**
2
- * Evaluator types — shared interfaces for the test group evaluation system.
3
- * Field names match the backend DB schema (camelCase versions of snake_case columns).
4
- */
5
- export type ExpectationType = 'llm-judge' | 'token-budget' | 'latency-budget' | 'output-contains' | 'output-schema' | 'determinism';
6
- export interface Expectation {
7
- id: number;
8
- testGroupId: number;
9
- type: ExpectationType;
10
- judgePrompt?: string;
11
- judgeModel?: string;
12
- judgeProvider?: string;
13
- judgeScoreThreshold?: number;
14
- maxTotalTokens?: number;
15
- maxTokensPerRun?: number;
16
- maxDurationMs?: number;
17
- maxTotalDurationMs?: number;
18
- containsText?: string;
19
- notContainsText?: string;
20
- caseInsensitive?: boolean;
21
- jsonSchema?: Record<string, unknown>;
22
- similarityThreshold?: number;
23
- }
24
- export interface TokenUsage {
25
- inputTokens: number;
26
- outputTokens: number;
27
- totalTokens: number;
28
- }
29
- export interface SingleRunData {
30
- runIndex: number;
31
- passed: boolean;
32
- durationMs: number;
33
- tokenUsage: TokenUsage;
34
- output: unknown;
35
- trace?: unknown;
36
- error?: string;
37
- startedAt?: string;
38
- completedAt?: string;
39
- }
40
- export interface PerRunResult {
41
- runIndex: number;
42
- passed: boolean;
43
- value: unknown;
44
- }
45
- export interface ExpectationResult {
46
- expectationId: number;
47
- type: ExpectationType;
48
- passed: boolean;
49
- detail: string;
50
- perRun?: PerRunResult[];
51
- }
52
- export interface EvaluationResult {
53
- passed: boolean;
54
- summary: string;
55
- results: ExpectationResult[];
56
- }
57
- export interface TestGroup {
58
- id: number;
59
- name: string;
60
- description?: string;
61
- projectId: number;
62
- workflowName: string;
63
- frozenEvents: unknown[];
64
- targetStepId: number;
65
- targetStepType: 'ai' | 'tool';
66
- mockInput?: unknown;
67
- promptMocks?: Record<string, string>;
68
- toolMocks?: Record<string, unknown>;
69
- expectations: Expectation[];
70
- runCount: number;
71
- passThreshold: 'all' | number;
72
- timeoutMs: number;
73
- tags?: string[];
74
- createdAt?: string;
75
- updatedAt?: string;
76
- }
77
- export interface GitContext {
78
- branch: string;
79
- commit: string;
80
- commitMessage?: string;
81
- prNumber?: number;
82
- prUrl?: string;
83
- }
84
- export interface TestGroupRunResult {
85
- testGroupId: number;
86
- triggeredBy: 'dashboard' | 'ci' | 'api' | 'schedule' | 'local';
87
- passed: boolean;
88
- summary: string;
89
- singleRuns: SingleRunData[];
90
- expectationResults: ExpectationResult[];
91
- gitContext?: GitContext;
92
- startedAt: string;
93
- completedAt: string;
94
- }
95
- export interface BatchResult {
96
- passed: boolean;
97
- summary: string;
98
- testGroupRunIds: number[];
99
- results: TestGroupRunResult[];
100
- gitContext?: GitContext;
101
- startedAt: string;
102
- completedAt: string;
103
- }
104
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/evaluators/types.ts"],"names":[],"mappings":"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"}
@@ -1,6 +0,0 @@
1
- /**
2
- * Evaluator types — shared interfaces for the test group evaluation system.
3
- * Field names match the backend DB schema (camelCase versions of snake_case columns).
4
- */
5
- export {};
6
- //# sourceMappingURL=types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/evaluators/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -1,8 +0,0 @@
1
- /**
2
- * Test-group CLI command tree.
3
- * Fully self-contained — does not import dashboard-server, browser-ui,
4
- * matchers, registry, or the .ai.test.ts runner.
5
- */
6
- import { Command } from 'commander';
7
- export declare function registerTestGroupCommand(program: Command): void;
8
- //# sourceMappingURL=cli.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/test-group/cli.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AASnC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0K/D"}
@@ -1,162 +0,0 @@
1
- /**
2
- * Test-group CLI command tree.
3
- * Fully self-contained — does not import dashboard-server, browser-ui,
4
- * matchers, registry, or the .ai.test.ts runner.
5
- */
6
- import { writeFileSync, mkdirSync } from 'node:fs';
7
- import path from 'node:path';
8
- import { resolveCloudConfig, fetchTestGroups, pushRunResult, pushBatchResult, exportTestGroups } from '../cloud-client.js';
9
- import { runAllTestGroups } from './runner.js';
10
- import { reportBatchResult } from './reporter.js';
11
- import { collectGitContext } from './git-context.js';
12
- export function registerTestGroupCommand(program) {
13
- const tg = program
14
- .command('test-group')
15
- .description('Run, list, or export cloud-managed test groups (CI/CD mode)')
16
- .option('--api-url <url>', 'ElasticDash API URL')
17
- .option('--api-key <key>', 'ElasticDash API key')
18
- .option('--project-id <id>', 'Project ID', '1');
19
- // ── test-group run ──────────────────────────────────────────
20
- tg.command('run')
21
- .description('Fetch test groups from cloud, execute locally, evaluate, and push results')
22
- .option('--all', 'Run all test groups for the project')
23
- .option('--name <name>', 'Run a specific test group by name')
24
- .option('--tag <tag>', 'Run test groups matching a tag')
25
- .option('--override-run-count <n>', 'Override run count for all groups', (v) => parseInt(v))
26
- .action(async (opts) => {
27
- try {
28
- const parentOpts = tg.opts();
29
- const config = resolveCloudConfig({
30
- apiUrl: parentOpts.apiUrl,
31
- apiKey: parentOpts.apiKey,
32
- projectId: parentOpts.projectId,
33
- });
34
- // Fetch test groups
35
- console.log('[elasticdash] Fetching test groups...');
36
- let groups = await fetchTestGroups(config, {
37
- tags: opts.tag ? [opts.tag] : undefined,
38
- });
39
- if (opts.name) {
40
- groups = groups.filter((g) => g.name === opts.name);
41
- }
42
- if (groups.length === 0) {
43
- console.error('[elasticdash] No test groups found matching the filters.');
44
- process.exit(2);
45
- }
46
- console.log(`[elasticdash] Running ${groups.length} test group(s)...`);
47
- const cwd = process.cwd();
48
- const gitContext = collectGitContext();
49
- // Execute all groups
50
- const batch = await runAllTestGroups(groups, cwd, {
51
- overrideRunCount: opts.overrideRunCount,
52
- });
53
- // Attach git context
54
- if (gitContext) {
55
- batch.gitContext = gitContext;
56
- for (const result of batch.results) {
57
- result.gitContext = gitContext;
58
- }
59
- }
60
- // Push results to cloud
61
- const runIds = [];
62
- for (const result of batch.results) {
63
- try {
64
- const pushed = await pushRunResult(config, result.testGroupId, result);
65
- runIds.push(pushed.id);
66
- }
67
- catch (err) {
68
- console.error(`[elasticdash] Failed to push results for "${result.summary.split(':')[0]}": ${err.message}`);
69
- }
70
- }
71
- // Push batch
72
- if (runIds.length > 0) {
73
- try {
74
- await pushBatchResult(config, {
75
- testGroupRunIds: runIds,
76
- gitBranch: gitContext?.branch,
77
- gitCommit: gitContext?.commit,
78
- passed: batch.passed,
79
- summary: batch.summary,
80
- });
81
- }
82
- catch (err) {
83
- console.error(`[elasticdash] Failed to push batch result: ${err.message}`);
84
- }
85
- }
86
- // Print report
87
- const cloudUrl = config.apiUrl ? `${config.apiUrl}/results` : undefined;
88
- reportBatchResult(batch, cloudUrl);
89
- process.exit(batch.passed ? 0 : 1);
90
- }
91
- catch (err) {
92
- console.error(`[elasticdash] Error: ${err.message}`);
93
- process.exit(2);
94
- }
95
- });
96
- // ── test-group list ─────────────────────────────────────────
97
- tg.command('list')
98
- .description('List test groups from the cloud platform')
99
- .action(async () => {
100
- try {
101
- const parentOpts = tg.opts();
102
- const config = resolveCloudConfig({
103
- apiUrl: parentOpts.apiUrl,
104
- apiKey: parentOpts.apiKey,
105
- projectId: parentOpts.projectId,
106
- });
107
- const groups = await fetchTestGroups(config);
108
- if (groups.length === 0) {
109
- console.log('No test groups found.');
110
- return;
111
- }
112
- // Print table
113
- console.log('');
114
- console.log(`${'Name'.padEnd(35)} ${'Workflow'.padEnd(25)} ${'Runs'.padEnd(6)} ${'Expectations'.padEnd(14)} Tags`);
115
- console.log('─'.repeat(100));
116
- for (const g of groups) {
117
- const name = (g.name || '(unnamed)').slice(0, 34).padEnd(35);
118
- const workflow = (g.workflowName || '').slice(0, 24).padEnd(25);
119
- const runs = String(g.runCount).padEnd(6);
120
- const expectations = String(g.expectations?.length ?? 0).padEnd(14);
121
- const tags = (g.tags ?? []).join(', ');
122
- console.log(`${name} ${workflow} ${runs} ${expectations} ${tags}`);
123
- }
124
- console.log('');
125
- console.log(`Total: ${groups.length} test group(s)`);
126
- }
127
- catch (err) {
128
- console.error(`[elasticdash] Error: ${err.message}`);
129
- process.exit(2);
130
- }
131
- });
132
- // ── test-group export ───────────────────────────────────────
133
- tg.command('export')
134
- .description('Export test groups to a local JSON file')
135
- .option('--output <path>', 'Output file path', '.elasticdash/test-groups.json')
136
- .action(async (opts) => {
137
- try {
138
- const parentOpts = tg.opts();
139
- const config = resolveCloudConfig({
140
- apiUrl: parentOpts.apiUrl,
141
- apiKey: parentOpts.apiKey,
142
- projectId: parentOpts.projectId,
143
- });
144
- const groups = await exportTestGroups(config);
145
- const cwd = process.cwd();
146
- const outputPath = path.resolve(cwd, opts.output);
147
- // Prevent path traversal outside the project directory
148
- if (!outputPath.startsWith(cwd + path.sep) && outputPath !== cwd) {
149
- console.error(`[elasticdash] Error: Output path must be within the project directory.`);
150
- process.exit(2);
151
- }
152
- mkdirSync(path.dirname(outputPath), { recursive: true });
153
- writeFileSync(outputPath, JSON.stringify(groups, null, 2) + '\n');
154
- console.log(`[elasticdash] Exported ${groups.length} test group(s) to ${outputPath}`);
155
- }
156
- catch (err) {
157
- console.error(`[elasticdash] Error: ${err.message}`);
158
- process.exit(2);
159
- }
160
- });
161
- }
162
- //# sourceMappingURL=cli.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/test-group/cli.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC1H,OAAO,EAAsB,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEpD,MAAM,UAAU,wBAAwB,CAAC,OAAgB;IACvD,MAAM,EAAE,GAAG,OAAO;SACf,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,6DAA6D,CAAC;SAC1E,MAAM,CAAC,iBAAiB,EAAE,qBAAqB,CAAC;SAChD,MAAM,CAAC,iBAAiB,EAAE,qBAAqB,CAAC;SAChD,MAAM,CAAC,mBAAmB,EAAE,YAAY,EAAE,GAAG,CAAC,CAAA;IAEjD,+DAA+D;IAE/D,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,2EAA2E,CAAC;SACxF,MAAM,CAAC,OAAO,EAAE,qCAAqC,CAAC;SACtD,MAAM,CAAC,eAAe,EAAE,mCAAmC,CAAC;SAC5D,MAAM,CAAC,aAAa,EAAE,gCAAgC,CAAC;SACvD,MAAM,CAAC,0BAA0B,EAAE,mCAAmC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;SAC3F,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,EAAE,CAAC,IAAI,EAAE,CAAA;YAC5B,MAAM,MAAM,GAAG,kBAAkB,CAAC;gBAChC,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,SAAS,EAAE,UAAU,CAAC,SAAS;aAChC,CAAC,CAAA;YAEF,oBAAoB;YACpB,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAA;YACpD,IAAI,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE;gBACzC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;aACxC,CAAC,CAAA;YAEF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAA;YACrD,CAAC;YAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAA;gBACzE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,yBAAyB,MAAM,CAAC,MAAM,mBAAmB,CAAC,CAAA;YAEtE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;YACzB,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAA;YAEtC,qBAAqB;YACrB,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;gBAChD,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;aACxC,CAAC,CAAA;YAEF,qBAAqB;YACrB,IAAI,UAAU,EAAE,CAAC;gBACf,KAAK,CAAC,UAAU,GAAG,UAAU,CAAA;gBAC7B,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;oBACnC,MAAM,CAAC,UAAU,GAAG,UAAU,CAAA;gBAChC,CAAC;YACH,CAAC;YAED,wBAAwB;YACxB,MAAM,MAAM,GAAa,EAAE,CAAA;YAC3B,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBACnC,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;oBACtE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBACxB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,6CAA6C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAO,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;gBACxH,CAAC;YACH,CAAC;YAED,aAAa;YACb,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC;oBACH,MAAM,eAAe,CAAC,MAAM,EAAE;wBAC5B,eAAe,EAAE,MAAM;wBACvB,SAAS,EAAE,UAAU,EAAE,MAAM;wBAC7B,SAAS,EAAE,UAAU,EAAE,MAAM;wBAC7B,MAAM,EAAE,KAAK,CAAC,MAAM;wBACpB,OAAO,EAAE,KAAK,CAAC,OAAO;qBACvB,CAAC,CAAA;gBACJ,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,8CAA+C,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;gBACvF,CAAC;YACH,CAAC;YAED,eAAe;YACf,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,UAAU,CAAC,CAAC,CAAC,SAAS,CAAA;YACvE,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;YAElC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,wBAAyB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;YAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC,CAAC,CAAA;IAEJ,+DAA+D;IAE/D,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,EAAE,CAAC,IAAI,EAAE,CAAA;YAC5B,MAAM,MAAM,GAAG,kBAAkB,CAAC;gBAChC,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,SAAS,EAAE,UAAU,CAAC,SAAS;aAChC,CAAC,CAAA;YAEF,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,CAAA;YAE5C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAA;gBACpC,OAAM;YACR,CAAC;YAED,cAAc;YACd,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YACf,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,CAAA;YAClH,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;YAE5B,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gBACvB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBAC5D,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBAC/D,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;gBACzC,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBACnE,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBACtC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,QAAQ,IAAI,IAAI,IAAI,YAAY,IAAI,IAAI,EAAE,CAAC,CAAA;YACpE,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YACf,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,MAAM,gBAAgB,CAAC,CAAA;QACtD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,wBAAyB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;YAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC,CAAC,CAAA;IAEJ,+DAA+D;IAE/D,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,yCAAyC,CAAC;SACtD,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,EAAE,+BAA+B,CAAC;SAC9E,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,EAAE,CAAC,IAAI,EAAE,CAAA;YAC5B,MAAM,MAAM,GAAG,kBAAkB,CAAC;gBAChC,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,SAAS,EAAE,UAAU,CAAC,SAAS;aAChC,CAAC,CAAA;YAEF,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAA;YAC7C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;YACzB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;YAEjD,uDAAuD;YACvD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;gBACjE,OAAO,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAA;gBACvF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YAED,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YACxD,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;YAEjE,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,MAAM,qBAAqB,UAAU,EAAE,CAAC,CAAA;QACvF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,wBAAyB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;YAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC,CAAC,CAAA;AACN,CAAC"}