elasticdash-sdk 0.2.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.
- package/LICENSE +21 -0
- package/README.md +775 -0
- package/dist/browser-ui.d.ts +43 -0
- package/dist/browser-ui.d.ts.map +1 -0
- package/dist/browser-ui.js +246 -0
- package/dist/browser-ui.js.map +1 -0
- package/dist/capture/event.d.ts +33 -0
- package/dist/capture/event.d.ts.map +1 -0
- package/dist/capture/event.js +2 -0
- package/dist/capture/event.js.map +1 -0
- package/dist/capture/index.d.ts +4 -0
- package/dist/capture/index.d.ts.map +1 -0
- package/dist/capture/index.js +4 -0
- package/dist/capture/index.js.map +1 -0
- package/dist/capture/recorder.d.ts +24 -0
- package/dist/capture/recorder.d.ts.map +1 -0
- package/dist/capture/recorder.js +46 -0
- package/dist/capture/recorder.js.map +1 -0
- package/dist/capture/replay.d.ts +20 -0
- package/dist/capture/replay.d.ts.map +1 -0
- package/dist/capture/replay.js +47 -0
- package/dist/capture/replay.js.map +1 -0
- package/dist/ci/api-client.d.ts +38 -0
- package/dist/ci/api-client.d.ts.map +1 -0
- package/dist/ci/api-client.js +96 -0
- package/dist/ci/api-client.js.map +1 -0
- package/dist/ci/benchmark.d.ts +33 -0
- package/dist/ci/benchmark.d.ts.map +1 -0
- package/dist/ci/benchmark.js +213 -0
- package/dist/ci/benchmark.js.map +1 -0
- package/dist/ci/ed-runner.d.ts +48 -0
- package/dist/ci/ed-runner.d.ts.map +1 -0
- package/dist/ci/ed-runner.js +260 -0
- package/dist/ci/ed-runner.js.map +1 -0
- package/dist/ci/executor.d.ts +13 -0
- package/dist/ci/executor.d.ts.map +1 -0
- package/dist/ci/executor.js +542 -0
- package/dist/ci/executor.js.map +1 -0
- package/dist/ci/git-info.d.ts +17 -0
- package/dist/ci/git-info.d.ts.map +1 -0
- package/dist/ci/git-info.js +102 -0
- package/dist/ci/git-info.js.map +1 -0
- package/dist/ci/index.d.ts +6 -0
- package/dist/ci/index.d.ts.map +1 -0
- package/dist/ci/index.js +4 -0
- package/dist/ci/index.js.map +1 -0
- package/dist/ci/measurement.d.ts +9 -0
- package/dist/ci/measurement.d.ts.map +1 -0
- package/dist/ci/measurement.js +15 -0
- package/dist/ci/measurement.js.map +1 -0
- package/dist/ci/replay.d.ts +31 -0
- package/dist/ci/replay.d.ts.map +1 -0
- package/dist/ci/replay.js +96 -0
- package/dist/ci/replay.js.map +1 -0
- package/dist/ci/reporters/default.d.ts +8 -0
- package/dist/ci/reporters/default.d.ts.map +1 -0
- package/dist/ci/reporters/default.js +46 -0
- package/dist/ci/reporters/default.js.map +1 -0
- package/dist/ci/reporters/index.d.ts +8 -0
- package/dist/ci/reporters/index.d.ts.map +1 -0
- package/dist/ci/reporters/index.js +14 -0
- package/dist/ci/reporters/index.js.map +1 -0
- package/dist/ci/reporters/json.d.ts +8 -0
- package/dist/ci/reporters/json.d.ts.map +1 -0
- package/dist/ci/reporters/json.js +14 -0
- package/dist/ci/reporters/json.js.map +1 -0
- package/dist/ci/reporters/junit.d.ts +8 -0
- package/dist/ci/reporters/junit.d.ts.map +1 -0
- package/dist/ci/reporters/junit.js +48 -0
- package/dist/ci/reporters/junit.js.map +1 -0
- package/dist/ci/runner.d.ts +3 -0
- package/dist/ci/runner.d.ts.map +1 -0
- package/dist/ci/runner.js +187 -0
- package/dist/ci/runner.js.map +1 -0
- package/dist/ci/test-discovery.d.ts +5 -0
- package/dist/ci/test-discovery.d.ts.map +1 -0
- package/dist/ci/test-discovery.js +11 -0
- package/dist/ci/test-discovery.js.map +1 -0
- package/dist/ci/test-loader.d.ts +19 -0
- package/dist/ci/test-loader.d.ts.map +1 -0
- package/dist/ci/test-loader.js +149 -0
- package/dist/ci/test-loader.js.map +1 -0
- package/dist/ci/test-registry.d.ts +42 -0
- package/dist/ci/test-registry.d.ts.map +1 -0
- package/dist/ci/test-registry.js +18 -0
- package/dist/ci/test-registry.js.map +1 -0
- package/dist/ci/trace-schema.d.ts +30 -0
- package/dist/ci/trace-schema.d.ts.map +1 -0
- package/dist/ci/trace-schema.js +66 -0
- package/dist/ci/trace-schema.js.map +1 -0
- package/dist/ci/trace-writer.d.ts +16 -0
- package/dist/ci/trace-writer.d.ts.map +1 -0
- package/dist/ci/trace-writer.js +108 -0
- package/dist/ci/trace-writer.js.map +1 -0
- package/dist/ci/types.d.ts +108 -0
- package/dist/ci/types.d.ts.map +1 -0
- package/dist/ci/types.js +3 -0
- package/dist/ci/types.js.map +1 -0
- package/dist/ci/upload-client.d.ts +74 -0
- package/dist/ci/upload-client.d.ts.map +1 -0
- package/dist/ci/upload-client.js +195 -0
- package/dist/ci/upload-client.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +716 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/agent-state.d.ts +47 -0
- package/dist/core/agent-state.d.ts.map +1 -0
- package/dist/core/agent-state.js +137 -0
- package/dist/core/agent-state.js.map +1 -0
- package/dist/core/judge-utils.d.ts +22 -0
- package/dist/core/judge-utils.d.ts.map +1 -0
- package/dist/core/judge-utils.js +211 -0
- package/dist/core/judge-utils.js.map +1 -0
- package/dist/core/registry.d.ts +28 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +52 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/dashboard-server.d.ts +65 -0
- package/dist/dashboard-server.d.ts.map +1 -0
- package/dist/dashboard-server.js +3940 -0
- package/dist/dashboard-server.js.map +1 -0
- package/dist/execution/tool-runner.d.ts +26 -0
- package/dist/execution/tool-runner.d.ts.map +1 -0
- package/dist/execution/tool-runner.js +316 -0
- package/dist/execution/tool-runner.js.map +1 -0
- package/dist/html/dashboard.html +2218 -0
- package/dist/http.d.ts +14 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +13 -0
- package/dist/http.js.map +1 -0
- package/dist/index.cjs +8102 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dist/interceptors/ai-interceptor.d.ts +26 -0
- package/dist/interceptors/ai-interceptor.d.ts.map +1 -0
- package/dist/interceptors/ai-interceptor.js +756 -0
- package/dist/interceptors/ai-interceptor.js.map +1 -0
- package/dist/interceptors/db-auto.d.ts +8 -0
- package/dist/interceptors/db-auto.d.ts.map +1 -0
- package/dist/interceptors/db-auto.js +217 -0
- package/dist/interceptors/db-auto.js.map +1 -0
- package/dist/interceptors/db.d.ts +23 -0
- package/dist/interceptors/db.d.ts.map +1 -0
- package/dist/interceptors/db.js +137 -0
- package/dist/interceptors/db.js.map +1 -0
- package/dist/interceptors/http.d.ts +28 -0
- package/dist/interceptors/http.d.ts.map +1 -0
- package/dist/interceptors/http.js +356 -0
- package/dist/interceptors/http.js.map +1 -0
- package/dist/interceptors/side-effects.d.ts +7 -0
- package/dist/interceptors/side-effects.d.ts.map +1 -0
- package/dist/interceptors/side-effects.js +72 -0
- package/dist/interceptors/side-effects.js.map +1 -0
- package/dist/interceptors/telemetry-push.d.ts +142 -0
- package/dist/interceptors/telemetry-push.d.ts.map +1 -0
- package/dist/interceptors/telemetry-push.js +463 -0
- package/dist/interceptors/telemetry-push.js.map +1 -0
- package/dist/interceptors/tool.d.ts +2 -0
- package/dist/interceptors/tool.d.ts.map +1 -0
- package/dist/interceptors/tool.js +274 -0
- package/dist/interceptors/tool.js.map +1 -0
- package/dist/interceptors/workflow-ai.d.ts +5 -0
- package/dist/interceptors/workflow-ai.d.ts.map +1 -0
- package/dist/interceptors/workflow-ai.js +382 -0
- package/dist/interceptors/workflow-ai.js.map +1 -0
- package/dist/internals/conditional-recorder.d.ts +21 -0
- package/dist/internals/conditional-recorder.d.ts.map +1 -0
- package/dist/internals/conditional-recorder.js +54 -0
- package/dist/internals/conditional-recorder.js.map +1 -0
- package/dist/internals/mock-resolver.d.ts +146 -0
- package/dist/internals/mock-resolver.d.ts.map +1 -0
- package/dist/internals/mock-resolver.js +427 -0
- package/dist/internals/mock-resolver.js.map +1 -0
- package/dist/matchers/index.d.ts +96 -0
- package/dist/matchers/index.d.ts.map +1 -0
- package/dist/matchers/index.js +668 -0
- package/dist/matchers/index.js.map +1 -0
- package/dist/observability.d.ts +82 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +471 -0
- package/dist/observability.js.map +1 -0
- package/dist/portal-executor.d.ts +30 -0
- package/dist/portal-executor.d.ts.map +1 -0
- package/dist/portal-executor.js +324 -0
- package/dist/portal-executor.js.map +1 -0
- package/dist/portal-server.d.ts +3 -0
- package/dist/portal-server.d.ts.map +1 -0
- package/dist/portal-server.js +279 -0
- package/dist/portal-server.js.map +1 -0
- package/dist/proxy/llm-capture.d.ts +14 -0
- package/dist/proxy/llm-capture.d.ts.map +1 -0
- package/dist/proxy/llm-capture.js +264 -0
- package/dist/proxy/llm-capture.js.map +1 -0
- package/dist/reporter.d.ts +3 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +72 -0
- package/dist/reporter.js.map +1 -0
- package/dist/runWorkflowSubprocess.d.ts +14 -0
- package/dist/runWorkflowSubprocess.d.ts.map +1 -0
- package/dist/runWorkflowSubprocess.js +66 -0
- package/dist/runWorkflowSubprocess.js.map +1 -0
- package/dist/runner.d.ts +16 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +138 -0
- package/dist/runner.js.map +1 -0
- package/dist/socket-connector.d.ts +22 -0
- package/dist/socket-connector.d.ts.map +1 -0
- package/dist/socket-connector.js +104 -0
- package/dist/socket-connector.js.map +1 -0
- package/dist/telemetry-batcher.d.ts +56 -0
- package/dist/telemetry-batcher.d.ts.map +1 -0
- package/dist/telemetry-batcher.js +143 -0
- package/dist/telemetry-batcher.js.map +1 -0
- package/dist/test-setup.d.ts +12 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/test-setup.js +13 -0
- package/dist/test-setup.js.map +1 -0
- package/dist/tool-registry.d.ts +31 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +73 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/tool-runner-worker.d.ts +2 -0
- package/dist/tool-runner-worker.d.ts.map +1 -0
- package/dist/tool-runner-worker.js +215 -0
- package/dist/tool-runner-worker.js.map +1 -0
- package/dist/trace-adapter/context.d.ts +72 -0
- package/dist/trace-adapter/context.d.ts.map +1 -0
- package/dist/trace-adapter/context.js +80 -0
- package/dist/trace-adapter/context.js.map +1 -0
- package/dist/tracing.d.ts +2 -0
- package/dist/tracing.d.ts.map +1 -0
- package/dist/tracing.js +59 -0
- package/dist/tracing.js.map +1 -0
- package/dist/trigger-executor.d.ts +12 -0
- package/dist/trigger-executor.d.ts.map +1 -0
- package/dist/trigger-executor.js +130 -0
- package/dist/trigger-executor.js.map +1 -0
- package/dist/types/portal.d.ts +76 -0
- package/dist/types/portal.d.ts.map +1 -0
- package/dist/types/portal.js +2 -0
- package/dist/types/portal.js.map +1 -0
- package/dist/utils/debug.d.ts +3 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +8 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/license-error.d.ts +23 -0
- package/dist/utils/license-error.d.ts.map +1 -0
- package/dist/utils/license-error.js +42 -0
- package/dist/utils/license-error.js.map +1 -0
- package/dist/utils/redact.d.ts +7 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/redact.js +26 -0
- package/dist/utils/redact.js.map +1 -0
- package/dist/workflow-runner-worker.d.ts +2 -0
- package/dist/workflow-runner-worker.d.ts.map +1 -0
- package/dist/workflow-runner-worker.js +329 -0
- package/dist/workflow-runner-worker.js.map +1 -0
- package/dist/workflow-runner.d.ts +14 -0
- package/dist/workflow-runner.d.ts.map +1 -0
- package/dist/workflow-runner.js +34 -0
- package/dist/workflow-runner.js.map +1 -0
- package/docs/agent-coding-instructions.md +138 -0
- package/docs/agent-integration-guide.md +564 -0
- package/docs/agents.md +140 -0
- package/docs/dashboard.md +394 -0
- package/docs/deno.md +69 -0
- package/docs/instrumentation.md +424 -0
- package/docs/langfuse-trace-structure.md +145 -0
- package/docs/matchers.md +173 -0
- package/docs/observability_contract.md +192 -0
- package/docs/observability_mode.md +195 -0
- package/docs/quickstart.md +621 -0
- package/docs/security-compliance.md +566 -0
- package/docs/test-writing-guidelines.md +444 -0
- package/docs/tools.md +165 -0
- package/docs/workflow-modes.md +253 -0
- package/package.json +76 -0
- package/src/browser-ui.ts +281 -0
- package/src/capture/event.ts +30 -0
- package/src/capture/index.ts +3 -0
- package/src/capture/recorder.ts +62 -0
- package/src/capture/replay.ts +55 -0
- package/src/ci/api-client.ts +136 -0
- package/src/ci/benchmark.ts +257 -0
- package/src/ci/ed-runner.ts +351 -0
- package/src/ci/executor.ts +671 -0
- package/src/ci/git-info.ts +127 -0
- package/src/ci/index.ts +5 -0
- package/src/ci/measurement.ts +25 -0
- package/src/ci/replay.ts +127 -0
- package/src/ci/reporters/default.ts +50 -0
- package/src/ci/reporters/index.ts +21 -0
- package/src/ci/reporters/json.ts +18 -0
- package/src/ci/reporters/junit.ts +61 -0
- package/src/ci/runner.ts +208 -0
- package/src/ci/test-discovery.ts +16 -0
- package/src/ci/test-loader.ts +187 -0
- package/src/ci/test-registry.ts +62 -0
- package/src/ci/trace-schema.ts +96 -0
- package/src/ci/trace-writer.ts +107 -0
- package/src/ci/types.ts +115 -0
- package/src/ci/upload-client.ts +300 -0
- package/src/cli.ts +811 -0
- package/src/core/agent-state.ts +162 -0
- package/src/core/judge-utils.ts +232 -0
- package/src/core/registry.ts +92 -0
- package/src/dashboard-server.ts +2047 -0
- package/src/execution/tool-runner.ts +352 -0
- package/src/html/dashboard.html +2218 -0
- package/src/http.ts +13 -0
- package/src/index.ts +138 -0
- package/src/interceptors/ai-interceptor.ts +798 -0
- package/src/interceptors/db-auto.ts +243 -0
- package/src/interceptors/db.ts +156 -0
- package/src/interceptors/http.ts +393 -0
- package/src/interceptors/side-effects.ts +83 -0
- package/src/interceptors/telemetry-push.ts +537 -0
- package/src/interceptors/tool.ts +287 -0
- package/src/interceptors/workflow-ai.ts +419 -0
- package/src/internals/conditional-recorder.ts +63 -0
- package/src/internals/mock-resolver.ts +492 -0
- package/src/matchers/index.ts +824 -0
- package/src/observability.ts +501 -0
- package/src/portal-executor.ts +355 -0
- package/src/portal-server.ts +304 -0
- package/src/proxy/llm-capture.ts +301 -0
- package/src/reporter.ts +81 -0
- package/src/runWorkflowSubprocess.ts +74 -0
- package/src/runner.ts +178 -0
- package/src/socket-connector.ts +117 -0
- package/src/telemetry-batcher.ts +191 -0
- package/src/test-setup.ts +16 -0
- package/src/tool-registry.ts +94 -0
- package/src/tool-runner-worker.ts +244 -0
- package/src/trace-adapter/context.ts +156 -0
- package/src/tracing.ts +62 -0
- package/src/trigger-executor.ts +171 -0
- package/src/types/agent.d.ts +63 -0
- package/src/types/expect.d.ts +81 -0
- package/src/types/modules.d.ts +2 -0
- package/src/types/portal.ts +69 -0
- package/src/utils/debug.ts +8 -0
- package/src/utils/license-error.ts +43 -0
- package/src/utils/redact.ts +25 -0
- package/src/workflow-runner-worker.ts +386 -0
- package/src/workflow-runner.ts +58 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { fetchTestGroups, submitTestRun, createBatch } from './api-client.js';
|
|
3
|
+
import { executeTest } from './executor.js';
|
|
4
|
+
import { detectGitInfo } from './git-info.js';
|
|
5
|
+
// ─── CI Runner ───────────────────────────────────────────────
|
|
6
|
+
// Orchestrates the full CI/CD test flow:
|
|
7
|
+
// 1. Fetch test groups from backend
|
|
8
|
+
// 2. Execute each test
|
|
9
|
+
// 3. Submit results
|
|
10
|
+
// 4. Create batch
|
|
11
|
+
// 5. Print summary
|
|
12
|
+
export async function runCI(config) {
|
|
13
|
+
const { serverUrl, apiKey } = config;
|
|
14
|
+
const cwd = process.cwd();
|
|
15
|
+
// Debug: log config so CI logs show what was received
|
|
16
|
+
console.log(`[elasticdash ci] serverUrl: ${serverUrl || '(not set)'}`);
|
|
17
|
+
console.log(`[elasticdash ci] apiKey: ${apiKey ? apiKey.substring(0, 7) + '...' + apiKey.substring(apiKey.length - 4) : '(not set)'}`);
|
|
18
|
+
// Merge explicit git info with auto-detected CI env
|
|
19
|
+
const detected = detectGitInfo();
|
|
20
|
+
const gitBranch = config.gitBranch || detected.branch;
|
|
21
|
+
const gitCommit = config.gitCommit || detected.commit;
|
|
22
|
+
const gitCommitMessage = config.gitCommitMessage || detected.commitMessage;
|
|
23
|
+
const gitPrNumber = config.gitPrNumber || detected.prNumber;
|
|
24
|
+
const gitPrUrl = config.gitPrUrl || detected.prUrl;
|
|
25
|
+
const triggeredBy = config.triggeredBy || 'ci';
|
|
26
|
+
const overallStart = Date.now();
|
|
27
|
+
// Step 1: Fetch test groups
|
|
28
|
+
console.log(chalk.cyan('\n[elasticdash ci] Fetching test groups...'));
|
|
29
|
+
const testGroups = await fetchTestGroups(serverUrl, apiKey, {
|
|
30
|
+
workflowName: config.workflowName,
|
|
31
|
+
tags: config.tags,
|
|
32
|
+
});
|
|
33
|
+
if (testGroups.length === 0) {
|
|
34
|
+
console.log(chalk.yellow('[elasticdash ci] No active test groups found.'));
|
|
35
|
+
return {
|
|
36
|
+
total: 0, passed: 0, failed: 0, skipped: 0,
|
|
37
|
+
durationMs: Date.now() - overallStart,
|
|
38
|
+
batchId: null,
|
|
39
|
+
results: [],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const totalTests = testGroups.reduce((sum, g) => sum + g.tests.length, 0);
|
|
43
|
+
console.log(chalk.cyan(`[elasticdash ci] Found ${testGroups.length} test group(s), ${totalTests} test(s) total.\n`));
|
|
44
|
+
// Step 2 & 3: Execute and submit
|
|
45
|
+
const allResults = [];
|
|
46
|
+
const runIds = [];
|
|
47
|
+
for (const group of testGroups) {
|
|
48
|
+
console.log(chalk.white.bold(` ${group.name}`) + chalk.gray(` (${group.tests.length} tests)`));
|
|
49
|
+
for (const test of group.tests) {
|
|
50
|
+
const testLabel = test.name || `${test.test_type}:${test.target_step_name || 'unnamed'}`;
|
|
51
|
+
process.stdout.write(chalk.gray(` ${testLabel} ... `));
|
|
52
|
+
const testStart = Date.now();
|
|
53
|
+
let testResult;
|
|
54
|
+
try {
|
|
55
|
+
const execution = await executeTest(test, cwd);
|
|
56
|
+
// Submit result to backend
|
|
57
|
+
const payload = {
|
|
58
|
+
testGroupTestId: test.id,
|
|
59
|
+
triggeredBy,
|
|
60
|
+
passed: execution.passed,
|
|
61
|
+
summary: execution.passed ? 'Passed' : 'Failed',
|
|
62
|
+
gitBranch, gitCommit, gitCommitMessage, gitPrNumber, gitPrUrl,
|
|
63
|
+
singleRuns: execution.singleRuns,
|
|
64
|
+
expectationResults: execution.expectationResults,
|
|
65
|
+
startedAt: new Date(testStart).toISOString(),
|
|
66
|
+
completedAt: new Date().toISOString(),
|
|
67
|
+
};
|
|
68
|
+
let runId = null;
|
|
69
|
+
try {
|
|
70
|
+
const submitted = await submitTestRun(serverUrl, apiKey, group.id, payload);
|
|
71
|
+
runId = submitted.id;
|
|
72
|
+
runIds.push(runId);
|
|
73
|
+
}
|
|
74
|
+
catch (submitErr) {
|
|
75
|
+
// Non-fatal: log but don't fail the test
|
|
76
|
+
console.error(chalk.yellow(`\n [warn] Failed to submit result: ${submitErr instanceof Error ? submitErr.message : String(submitErr)}`));
|
|
77
|
+
}
|
|
78
|
+
testResult = {
|
|
79
|
+
testGroupId: group.id,
|
|
80
|
+
testGroupName: group.name,
|
|
81
|
+
testId: test.id,
|
|
82
|
+
testName: test.name,
|
|
83
|
+
testType: test.test_type,
|
|
84
|
+
passed: execution.passed,
|
|
85
|
+
runId,
|
|
86
|
+
singleRuns: execution.singleRuns,
|
|
87
|
+
expectationResults: execution.expectationResults,
|
|
88
|
+
durationMs: execution.durationMs,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
testResult = {
|
|
93
|
+
testGroupId: group.id,
|
|
94
|
+
testGroupName: group.name,
|
|
95
|
+
testId: test.id,
|
|
96
|
+
testName: test.name,
|
|
97
|
+
testType: test.test_type,
|
|
98
|
+
passed: false,
|
|
99
|
+
runId: null,
|
|
100
|
+
singleRuns: [],
|
|
101
|
+
expectationResults: [],
|
|
102
|
+
error: err instanceof Error ? err.message : String(err),
|
|
103
|
+
durationMs: Date.now() - testStart,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
allResults.push(testResult);
|
|
107
|
+
// Print result
|
|
108
|
+
const durationStr = chalk.gray(`(${testResult.durationMs}ms)`);
|
|
109
|
+
if (testResult.passed) {
|
|
110
|
+
console.log(chalk.green('PASS') + ` ${durationStr}`);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
console.log(chalk.red('FAIL') + ` ${durationStr}`);
|
|
114
|
+
if (testResult.error) {
|
|
115
|
+
console.log(chalk.red(` ${testResult.error}`));
|
|
116
|
+
}
|
|
117
|
+
// Show errors from individual single runs
|
|
118
|
+
for (const run of testResult.singleRuns) {
|
|
119
|
+
if (!run.passed && run.error) {
|
|
120
|
+
console.log(chalk.red(` [run ${run.runIndex}] ${run.error}`));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Show failed expectations
|
|
124
|
+
for (const exp of testResult.expectationResults) {
|
|
125
|
+
if (!exp.passed) {
|
|
126
|
+
console.log(chalk.red(` [${exp.type}] ${exp.detail || 'failed'}`));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
console.log(); // blank line between groups
|
|
132
|
+
}
|
|
133
|
+
// Step 4: Create batch
|
|
134
|
+
let batchId = null;
|
|
135
|
+
if (runIds.length > 0) {
|
|
136
|
+
try {
|
|
137
|
+
const passedCount = allResults.filter((r) => r.passed).length;
|
|
138
|
+
const allPassed = passedCount === allResults.length;
|
|
139
|
+
const batch = await createBatch(serverUrl, apiKey, {
|
|
140
|
+
testGroupRunIds: runIds,
|
|
141
|
+
status: allPassed ? 'success' : 'failed',
|
|
142
|
+
passed: allPassed,
|
|
143
|
+
summary: `CI: ${passedCount}/${allResults.length} passed`,
|
|
144
|
+
gitBranch, gitCommit,
|
|
145
|
+
startedAt: new Date(overallStart).toISOString(),
|
|
146
|
+
completedAt: new Date().toISOString(),
|
|
147
|
+
});
|
|
148
|
+
batchId = batch.id;
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Non-fatal
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Step 5: Print summary
|
|
155
|
+
const passed = allResults.filter((r) => r.passed).length;
|
|
156
|
+
const failed = allResults.filter((r) => !r.passed).length;
|
|
157
|
+
const durationMs = Date.now() - overallStart;
|
|
158
|
+
console.log(chalk.white.bold('─'.repeat(50)));
|
|
159
|
+
console.log(chalk.white.bold('Summary'));
|
|
160
|
+
console.log(chalk.white.bold('─'.repeat(50)));
|
|
161
|
+
console.log(` Total: ${allResults.length}`);
|
|
162
|
+
console.log(` ${chalk.green(`Passed: ${passed}`)}`);
|
|
163
|
+
if (failed > 0) {
|
|
164
|
+
console.log(` ${chalk.red(`Failed: ${failed}`)}`);
|
|
165
|
+
}
|
|
166
|
+
console.log(` Duration: ${(durationMs / 1000).toFixed(1)}s`);
|
|
167
|
+
if (batchId) {
|
|
168
|
+
console.log(` Batch ID: ${batchId}`);
|
|
169
|
+
}
|
|
170
|
+
console.log(chalk.white.bold('─'.repeat(50)));
|
|
171
|
+
if (failed > 0) {
|
|
172
|
+
console.log(chalk.red(`\n[elasticdash ci] ${failed} test(s) failed.\n`));
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
console.log(chalk.green(`\n[elasticdash ci] All tests passed.\n`));
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
total: allResults.length,
|
|
179
|
+
passed,
|
|
180
|
+
failed,
|
|
181
|
+
skipped: 0,
|
|
182
|
+
durationMs,
|
|
183
|
+
batchId,
|
|
184
|
+
results: allResults,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/ci/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-discovery.d.ts","sourceRoot":"","sources":["../../src/ci/test-discovery.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,wBAAsB,iBAAiB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQpF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import fg from 'fast-glob';
|
|
2
|
+
export async function discoverTestFiles(options) {
|
|
3
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
4
|
+
const files = await fg('**/ed_tests.{ts,js}', {
|
|
5
|
+
cwd,
|
|
6
|
+
absolute: true,
|
|
7
|
+
ignore: ['**/node_modules/**', '**/.git/**', '**/.ed_traces/**'],
|
|
8
|
+
});
|
|
9
|
+
return files.sort();
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=test-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-discovery.js","sourceRoot":"","sources":["../../src/ci/test-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,WAAW,CAAA;AAO1B,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAyB;IAC/D,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAA;IACzC,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,qBAAqB,EAAE;QAC5C,GAAG;QACH,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,CAAC,oBAAoB,EAAE,YAAY,EAAE,kBAAkB,CAAC;KACjE,CAAC,CAAA;IACF,OAAO,KAAK,CAAC,IAAI,EAAE,CAAA;AACrB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TestDefinition } from './test-registry.js';
|
|
2
|
+
import type { DiskTrace } from './trace-schema.js';
|
|
3
|
+
export interface ValidatedTest extends TestDefinition {
|
|
4
|
+
resolvedTracePath: string;
|
|
5
|
+
traceData: DiskTrace;
|
|
6
|
+
}
|
|
7
|
+
export interface ValidationError {
|
|
8
|
+
file: string;
|
|
9
|
+
testName?: string;
|
|
10
|
+
message: string;
|
|
11
|
+
}
|
|
12
|
+
export interface LoadTestsResult {
|
|
13
|
+
tests: ValidatedTest[];
|
|
14
|
+
errors: ValidationError[];
|
|
15
|
+
}
|
|
16
|
+
export declare function loadTests(options?: {
|
|
17
|
+
cwd?: string;
|
|
18
|
+
}): Promise<LoadTestsResult>;
|
|
19
|
+
//# sourceMappingURL=test-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-loader.d.ts","sourceRoot":"","sources":["../../src/ci/test-loader.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAElD,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,aAAa,EAAE,CAAA;IACtB,MAAM,EAAE,eAAe,EAAE,CAAA;CAC1B;AAED,wBAAsB,SAAS,CAAC,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAkKpF"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { resolve, dirname } from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { discoverTestFiles } from './test-discovery.js';
|
|
5
|
+
import { getTestRegistry, clearTestRegistry } from './test-registry.js';
|
|
6
|
+
export async function loadTests(options) {
|
|
7
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
8
|
+
const files = await discoverTestFiles({ cwd });
|
|
9
|
+
const allDefinitions = [];
|
|
10
|
+
const errors = [];
|
|
11
|
+
// Phase 1: import each test file and collect definitions
|
|
12
|
+
for (const file of files) {
|
|
13
|
+
clearTestRegistry();
|
|
14
|
+
try {
|
|
15
|
+
// Cache-bust so re-imports within the same process re-execute the module
|
|
16
|
+
const fileUrl = pathToFileURL(file).href + `?t=${Date.now()}`;
|
|
17
|
+
await import(fileUrl);
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
errors.push({
|
|
21
|
+
file,
|
|
22
|
+
message: `Failed to import test file: ${err instanceof Error ? err.message : String(err)}`,
|
|
23
|
+
});
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const defs = getTestRegistry();
|
|
27
|
+
for (const def of defs) {
|
|
28
|
+
def._sourceFile = file;
|
|
29
|
+
}
|
|
30
|
+
allDefinitions.push(...defs);
|
|
31
|
+
}
|
|
32
|
+
clearTestRegistry();
|
|
33
|
+
// Phase 2: validate definitions
|
|
34
|
+
const tests = [];
|
|
35
|
+
const seenNames = new Map(); // name → source file
|
|
36
|
+
for (const def of allDefinitions) {
|
|
37
|
+
const file = def._sourceFile;
|
|
38
|
+
// Validate name
|
|
39
|
+
if (!def.name || typeof def.name !== 'string' || def.name.trim().length === 0) {
|
|
40
|
+
errors.push({ file, testName: def.name, message: 'Test name must be a non-empty string' });
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Check uniqueness
|
|
44
|
+
if (seenNames.has(def.name)) {
|
|
45
|
+
errors.push({
|
|
46
|
+
file,
|
|
47
|
+
testName: def.name,
|
|
48
|
+
message: `Duplicate test name "${def.name}" (also defined in ${seenNames.get(def.name)})`,
|
|
49
|
+
});
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
seenNames.set(def.name, file);
|
|
53
|
+
// Resolve trace path relative to the test file's directory
|
|
54
|
+
const resolvedTracePath = resolve(dirname(file), def.trace);
|
|
55
|
+
// Read and parse trace file
|
|
56
|
+
let traceData;
|
|
57
|
+
try {
|
|
58
|
+
const raw = await readFile(resolvedTracePath, 'utf-8');
|
|
59
|
+
traceData = JSON.parse(raw);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
errors.push({
|
|
63
|
+
file,
|
|
64
|
+
testName: def.name,
|
|
65
|
+
message: `Cannot read/parse trace file "${def.trace}": ${err instanceof Error ? err.message : String(err)}`,
|
|
66
|
+
});
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
// Validate trace has steps array
|
|
70
|
+
if (!Array.isArray(traceData.steps)) {
|
|
71
|
+
errors.push({ file, testName: def.name, message: `Trace file "${def.trace}" has no steps array` });
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
// Validate target
|
|
75
|
+
if (!def.target || !def.target.step_id || !def.target.type) {
|
|
76
|
+
errors.push({ file, testName: def.name, message: 'Target must have type and step_id' });
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const matchedStep = traceData.steps.find(s => s.step_id === def.target.step_id);
|
|
80
|
+
if (!matchedStep) {
|
|
81
|
+
errors.push({
|
|
82
|
+
file,
|
|
83
|
+
testName: def.name,
|
|
84
|
+
message: `step_id "${def.target.step_id}" not found in trace "${def.trace}"`,
|
|
85
|
+
});
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (matchedStep.type !== def.target.type) {
|
|
89
|
+
errors.push({
|
|
90
|
+
file,
|
|
91
|
+
testName: def.name,
|
|
92
|
+
message: `target.type "${def.target.type}" does not match step type "${matchedStep.type}" for step_id "${def.target.step_id}"`,
|
|
93
|
+
});
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
// Validate benchmarks
|
|
97
|
+
if (!def.benchmarks || typeof def.benchmarks !== 'object') {
|
|
98
|
+
errors.push({ file, testName: def.name, message: 'Benchmarks must be specified' });
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const hasMaxDuration = def.benchmarks.max_duration_ms !== undefined;
|
|
102
|
+
const hasMaxTokens = def.benchmarks.max_tokens_total !== undefined;
|
|
103
|
+
const hasOutputContains = def.benchmarks.output_contains !== undefined;
|
|
104
|
+
const hasOutputNotContains = def.benchmarks.output_not_contains !== undefined;
|
|
105
|
+
const hasLLMJudge = def.benchmarks.llm_judge !== undefined;
|
|
106
|
+
if (!hasMaxDuration && !hasMaxTokens && !hasOutputContains && !hasOutputNotContains && !hasLLMJudge) {
|
|
107
|
+
errors.push({ file, testName: def.name, message: 'At least one benchmark must be specified' });
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
let valid = true;
|
|
111
|
+
if (hasMaxDuration) {
|
|
112
|
+
if (typeof def.benchmarks.max_duration_ms !== 'number' || def.benchmarks.max_duration_ms <= 0) {
|
|
113
|
+
errors.push({ file, testName: def.name, message: 'max_duration_ms must be a positive number' });
|
|
114
|
+
valid = false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (hasMaxTokens) {
|
|
118
|
+
if (typeof def.benchmarks.max_tokens_total !== 'number' || def.benchmarks.max_tokens_total <= 0) {
|
|
119
|
+
errors.push({ file, testName: def.name, message: 'max_tokens_total must be a positive number' });
|
|
120
|
+
valid = false;
|
|
121
|
+
}
|
|
122
|
+
if (def.target.type !== 'ai_call') {
|
|
123
|
+
errors.push({ file, testName: def.name, message: 'max_tokens_total can only be used with ai_call targets' });
|
|
124
|
+
valid = false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (!valid)
|
|
128
|
+
continue;
|
|
129
|
+
// Validate run (optional but must be a function if present)
|
|
130
|
+
if (def.run !== undefined && typeof def.run !== 'function') {
|
|
131
|
+
errors.push({ file, testName: def.name, message: 'run must be a function' });
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
// Validate timeout_ms (optional but must be a positive number if present)
|
|
135
|
+
if (def.timeout_ms !== undefined) {
|
|
136
|
+
if (typeof def.timeout_ms !== 'number' || def.timeout_ms <= 0) {
|
|
137
|
+
errors.push({ file, testName: def.name, message: 'timeout_ms must be a positive number' });
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
tests.push({
|
|
142
|
+
...def,
|
|
143
|
+
resolvedTracePath,
|
|
144
|
+
traceData,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return { tests, errors };
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=test-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-loader.js","sourceRoot":"","sources":["../../src/ci/test-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface TestTarget {
|
|
2
|
+
type: 'tool_call' | 'ai_call';
|
|
3
|
+
step_id: string;
|
|
4
|
+
}
|
|
5
|
+
export interface LLMJudgeBenchmark {
|
|
6
|
+
/** The prompt sent to the LLM judge to evaluate the step's output. */
|
|
7
|
+
judge_prompt: string;
|
|
8
|
+
/** Minimum score (0-10) required to pass. Defaults to 7. */
|
|
9
|
+
judge_score_threshold?: number;
|
|
10
|
+
/** LLM provider to use for judging. Defaults to 'openai'. */
|
|
11
|
+
judge_provider?: 'openai' | 'claude' | 'gemini' | 'grok' | 'kimi';
|
|
12
|
+
/** Model override for the judge LLM. */
|
|
13
|
+
judge_model?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface TestBenchmarks {
|
|
16
|
+
max_duration_ms?: number;
|
|
17
|
+
max_tokens_total?: number;
|
|
18
|
+
/** Assert that the step's output contains this substring. */
|
|
19
|
+
output_contains?: string;
|
|
20
|
+
/** Assert that the step's output does NOT contain this substring. */
|
|
21
|
+
output_not_contains?: string;
|
|
22
|
+
/** LLM-as-a-judge evaluation of the step's output quality. */
|
|
23
|
+
llm_judge?: LLMJudgeBenchmark;
|
|
24
|
+
}
|
|
25
|
+
export interface TestDefinition {
|
|
26
|
+
name: string;
|
|
27
|
+
trace: string;
|
|
28
|
+
target: TestTarget;
|
|
29
|
+
benchmarks: TestBenchmarks;
|
|
30
|
+
/** Custom input that overrides the trace's recorded input. Can be a static value or an async function for dynamic resolution (e.g. fetching from a database or API). */
|
|
31
|
+
input?: unknown | (() => Promise<unknown> | unknown);
|
|
32
|
+
/** The function that invokes the workflow under test. Receives the resolved input (custom or from trace) as its argument. Required for execution (Phase 3). */
|
|
33
|
+
run?: (input?: unknown) => Promise<void>;
|
|
34
|
+
/** Per-test timeout in milliseconds. Defaults to 60000. */
|
|
35
|
+
timeout_ms?: number;
|
|
36
|
+
/** Set internally by the loader to the absolute path of the source file */
|
|
37
|
+
_sourceFile?: string;
|
|
38
|
+
}
|
|
39
|
+
export declare function defineTest(def: Omit<TestDefinition, '_sourceFile'>): void;
|
|
40
|
+
export declare function getTestRegistry(): TestDefinition[];
|
|
41
|
+
export declare function clearTestRegistry(): void;
|
|
42
|
+
//# sourceMappingURL=test-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-registry.d.ts","sourceRoot":"","sources":["../../src/ci/test-registry.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,WAAW,GAAG,SAAS,CAAA;IAC7B,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,YAAY,EAAE,MAAM,CAAA;IACpB,4DAA4D;IAC5D,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,6DAA6D;IAC7D,cAAc,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAA;IACjE,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,6DAA6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,qEAAqE;IACrE,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,8DAA8D;IAC9D,SAAS,CAAC,EAAE,iBAAiB,CAAA;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,UAAU,CAAA;IAClB,UAAU,EAAE,cAAc,CAAA;IAC1B,wKAAwK;IACxK,KAAK,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAA;IACpD,+JAA+J;IAC/J,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAWD,wBAAgB,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC,GAAG,IAAI,CAEzE;AAED,wBAAgB,eAAe,IAAI,cAAc,EAAE,CAElD;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Use a globalThis-backed registry so that the CLI (global install) and the
|
|
2
|
+
// test file (local node_modules) share the same array even when they resolve
|
|
3
|
+
// to different module instances.
|
|
4
|
+
const g = globalThis;
|
|
5
|
+
const ED_TEST_REGISTRY_KEY = '__elasticdash_ed_test_registry__';
|
|
6
|
+
const registry = g[ED_TEST_REGISTRY_KEY] ?? [];
|
|
7
|
+
if (!g[ED_TEST_REGISTRY_KEY])
|
|
8
|
+
g[ED_TEST_REGISTRY_KEY] = registry;
|
|
9
|
+
export function defineTest(def) {
|
|
10
|
+
registry.push({ ...def });
|
|
11
|
+
}
|
|
12
|
+
export function getTestRegistry() {
|
|
13
|
+
return [...registry];
|
|
14
|
+
}
|
|
15
|
+
export function clearTestRegistry() {
|
|
16
|
+
registry.length = 0;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=test-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-registry.js","sourceRoot":"","sources":["../../src/ci/test-registry.ts"],"names":[],"mappings":"AA0CA,4EAA4E;AAC5E,6EAA6E;AAC7E,iCAAiC;AACjC,MAAM,CAAC,GAAG,UAAqC,CAAA;AAC/C,MAAM,oBAAoB,GAAG,kCAAkC,CAAA;AAC/D,MAAM,QAAQ,GACX,CAAC,CAAC,oBAAoB,CAAsB,IAAI,EAAE,CAAA;AACrD,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC;IAAE,CAAC,CAAC,oBAAoB,CAAC,GAAG,QAAQ,CAAA;AAEhE,MAAM,UAAU,UAAU,CAAC,GAAwC;IACjE,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,CAAA;AAC3B,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAA;AACtB,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAA;AACrB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { WorkflowEvent } from '../capture/event.js';
|
|
2
|
+
export declare let SDK_VERSION: string;
|
|
3
|
+
export interface DiskTraceStep {
|
|
4
|
+
step_id: string;
|
|
5
|
+
type: 'tool_call' | 'ai_call';
|
|
6
|
+
name: string;
|
|
7
|
+
input: unknown;
|
|
8
|
+
output: unknown;
|
|
9
|
+
started_at: string;
|
|
10
|
+
ended_at: string;
|
|
11
|
+
duration_ms: number;
|
|
12
|
+
tokens?: {
|
|
13
|
+
input: number;
|
|
14
|
+
output: number;
|
|
15
|
+
total: number;
|
|
16
|
+
} | null;
|
|
17
|
+
}
|
|
18
|
+
export interface DiskTrace {
|
|
19
|
+
trace_id: string;
|
|
20
|
+
created_at: string;
|
|
21
|
+
sdk_version: string;
|
|
22
|
+
workflow: {
|
|
23
|
+
name: string;
|
|
24
|
+
input: unknown;
|
|
25
|
+
output: unknown;
|
|
26
|
+
};
|
|
27
|
+
steps: DiskTraceStep[];
|
|
28
|
+
}
|
|
29
|
+
export declare function workflowEventsToDiskTrace(events: WorkflowEvent[], traceId: string): DiskTrace;
|
|
30
|
+
//# sourceMappingURL=trace-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-schema.d.ts","sourceRoot":"","sources":["../../src/ci/trace-schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,eAAO,IAAI,WAAW,QAAY,CAAA;AAUlC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,WAAW,GAAG,SAAS,CAAA;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CACjE;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,OAAO,CAAA;QACd,MAAM,EAAE,OAAO,CAAA;KAChB,CAAA;IACD,KAAK,EAAE,aAAa,EAAE,CAAA;CACvB;AAQD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAkD7F"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
export let SDK_VERSION = 'unknown';
|
|
5
|
+
try {
|
|
6
|
+
// Works in both ESM (import.meta.url) and CJS (__dirname) contexts
|
|
7
|
+
const base = typeof __dirname !== 'undefined' ? __dirname : dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const pkg = JSON.parse(readFileSync(join(base, '..', '..', 'package.json'), 'utf-8'));
|
|
9
|
+
SDK_VERSION = pkg.version;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
// Bundled context — version not critical
|
|
13
|
+
}
|
|
14
|
+
function mapEventType(type) {
|
|
15
|
+
if (type === 'tool')
|
|
16
|
+
return 'tool_call';
|
|
17
|
+
if (type === 'ai')
|
|
18
|
+
return 'ai_call';
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
export function workflowEventsToDiskTrace(events, traceId) {
|
|
22
|
+
const workflowEvent = events.find(e => e.type === 'workflow');
|
|
23
|
+
const counters = { tool_call: 0, ai_call: 0 };
|
|
24
|
+
const steps = [];
|
|
25
|
+
for (const event of events) {
|
|
26
|
+
const mappedType = mapEventType(event.type);
|
|
27
|
+
if (!mappedType)
|
|
28
|
+
continue;
|
|
29
|
+
const index = counters[mappedType]++;
|
|
30
|
+
const stepId = `${mappedType}_${index}`;
|
|
31
|
+
const startedAt = new Date(event.timestamp).toISOString();
|
|
32
|
+
const endedAt = new Date(event.timestamp + event.durationMs).toISOString();
|
|
33
|
+
let tokens = null;
|
|
34
|
+
if (mappedType === 'ai_call' && event.usage) {
|
|
35
|
+
tokens = {
|
|
36
|
+
input: event.usage.inputTokens ?? 0,
|
|
37
|
+
output: event.usage.outputTokens ?? 0,
|
|
38
|
+
total: event.usage.totalTokens ?? ((event.usage.inputTokens ?? 0) + (event.usage.outputTokens ?? 0)),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
steps.push({
|
|
42
|
+
step_id: stepId,
|
|
43
|
+
type: mappedType,
|
|
44
|
+
name: event.name,
|
|
45
|
+
input: event.input,
|
|
46
|
+
output: event.output,
|
|
47
|
+
started_at: startedAt,
|
|
48
|
+
ended_at: endedAt,
|
|
49
|
+
duration_ms: event.durationMs,
|
|
50
|
+
tokens,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
const now = new Date();
|
|
54
|
+
return {
|
|
55
|
+
trace_id: traceId,
|
|
56
|
+
created_at: now.toISOString(),
|
|
57
|
+
sdk_version: SDK_VERSION,
|
|
58
|
+
workflow: {
|
|
59
|
+
name: workflowEvent?.name ?? 'unknown',
|
|
60
|
+
input: workflowEvent?.input ?? null,
|
|
61
|
+
output: workflowEvent?.output ?? null,
|
|
62
|
+
},
|
|
63
|
+
steps,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=trace-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-schema.js","sourceRoot":"","sources":["../../src/ci/trace-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { WorkflowEvent } from '../capture/event.js';
|
|
2
|
+
import type { DiskTrace } from './trace-schema.js';
|
|
3
|
+
export declare function isTraceCaptureEnabled(): boolean;
|
|
4
|
+
export declare function generateTraceFilename(): string;
|
|
5
|
+
export declare function scrubSecrets(obj: unknown): unknown;
|
|
6
|
+
export declare function writeTraceToDisk(trace: DiskTrace, cwd?: string): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Synchronous write for use in process.on('exit') handlers where async is not possible.
|
|
9
|
+
*/
|
|
10
|
+
export declare function writeTraceToDiskSync(trace: DiskTrace, cwd?: string): void;
|
|
11
|
+
export declare function maybeCaptureTrace(events: WorkflowEvent[], traceId?: string, cwd?: string): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Synchronous version of maybeCaptureTrace for process exit handlers.
|
|
14
|
+
*/
|
|
15
|
+
export declare function maybeCaptureTraceSync(events: WorkflowEvent[], traceId?: string, cwd?: string): void;
|
|
16
|
+
//# sourceMappingURL=trace-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-writer.d.ts","sourceRoot":"","sources":["../../src/ci/trace-writer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAMlD,wBAAgB,qBAAqB,IAAI,OAAO,CAW/C;AAGD,wBAAgB,qBAAqB,IAAI,MAAM,CAO9C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAelD;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYpF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAYzE;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS9G;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CASnG"}
|