All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
224 lines
6.5 KiB
TypeScript
224 lines
6.5 KiB
TypeScript
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
import { EventBuilder } from "../src/event-builder.js";
|
|
import { ResolvedConfig } from "../src/config.js";
|
|
import {
|
|
TaskType,
|
|
Complexity,
|
|
Harness,
|
|
Provider,
|
|
Outcome,
|
|
QualityGate,
|
|
RepoSizeCategory,
|
|
} from "../src/types/events.js";
|
|
|
|
function makeConfig(): ResolvedConfig {
|
|
return {
|
|
serverUrl: "https://tel.example.com",
|
|
apiKey: "a".repeat(64),
|
|
instanceId: "my-instance-uuid",
|
|
enabled: true,
|
|
submitIntervalMs: 300_000,
|
|
maxQueueSize: 1000,
|
|
batchSize: 100,
|
|
requestTimeoutMs: 10_000,
|
|
predictionCacheTtlMs: 21_600_000,
|
|
dryRun: false,
|
|
maxRetries: 3,
|
|
onError: () => {},
|
|
};
|
|
}
|
|
|
|
describe("EventBuilder", () => {
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it("should build a complete TaskCompletionEvent", () => {
|
|
const builder = new EventBuilder(makeConfig());
|
|
const event = builder.build({
|
|
task_duration_ms: 15000,
|
|
task_type: TaskType.IMPLEMENTATION,
|
|
complexity: Complexity.HIGH,
|
|
harness: Harness.CLAUDE_CODE,
|
|
model: "claude-3-opus",
|
|
provider: Provider.ANTHROPIC,
|
|
estimated_input_tokens: 2000,
|
|
estimated_output_tokens: 1000,
|
|
actual_input_tokens: 2200,
|
|
actual_output_tokens: 1100,
|
|
estimated_cost_usd_micros: 100000,
|
|
actual_cost_usd_micros: 110000,
|
|
quality_gate_passed: true,
|
|
quality_gates_run: [
|
|
QualityGate.BUILD,
|
|
QualityGate.TEST,
|
|
QualityGate.LINT,
|
|
],
|
|
quality_gates_failed: [],
|
|
context_compactions: 2,
|
|
context_rotations: 1,
|
|
context_utilization_final: 0.75,
|
|
outcome: Outcome.SUCCESS,
|
|
retry_count: 0,
|
|
language: "typescript",
|
|
repo_size_category: RepoSizeCategory.MEDIUM,
|
|
});
|
|
|
|
expect(event.task_type).toBe(TaskType.IMPLEMENTATION);
|
|
expect(event.complexity).toBe(Complexity.HIGH);
|
|
expect(event.model).toBe("claude-3-opus");
|
|
expect(event.quality_gates_run).toEqual([
|
|
QualityGate.BUILD,
|
|
QualityGate.TEST,
|
|
QualityGate.LINT,
|
|
]);
|
|
expect(event.language).toBe("typescript");
|
|
expect(event.repo_size_category).toBe(RepoSizeCategory.MEDIUM);
|
|
});
|
|
|
|
it("should auto-generate event_id as UUID", () => {
|
|
const builder = new EventBuilder(makeConfig());
|
|
const event = builder.build({
|
|
task_duration_ms: 1000,
|
|
task_type: TaskType.TESTING,
|
|
complexity: Complexity.LOW,
|
|
harness: Harness.AIDER,
|
|
model: "gpt-4",
|
|
provider: Provider.OPENAI,
|
|
estimated_input_tokens: 100,
|
|
estimated_output_tokens: 50,
|
|
actual_input_tokens: 100,
|
|
actual_output_tokens: 50,
|
|
estimated_cost_usd_micros: 1000,
|
|
actual_cost_usd_micros: 1000,
|
|
quality_gate_passed: true,
|
|
quality_gates_run: [],
|
|
quality_gates_failed: [],
|
|
context_compactions: 0,
|
|
context_rotations: 0,
|
|
context_utilization_final: 0.3,
|
|
outcome: Outcome.SUCCESS,
|
|
retry_count: 0,
|
|
});
|
|
|
|
// UUID format: 8-4-4-4-12 hex chars
|
|
expect(event.event_id).toMatch(
|
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,
|
|
);
|
|
|
|
// Each event should get a unique ID
|
|
const event2 = builder.build({
|
|
task_duration_ms: 1000,
|
|
task_type: TaskType.TESTING,
|
|
complexity: Complexity.LOW,
|
|
harness: Harness.AIDER,
|
|
model: "gpt-4",
|
|
provider: Provider.OPENAI,
|
|
estimated_input_tokens: 100,
|
|
estimated_output_tokens: 50,
|
|
actual_input_tokens: 100,
|
|
actual_output_tokens: 50,
|
|
estimated_cost_usd_micros: 1000,
|
|
actual_cost_usd_micros: 1000,
|
|
quality_gate_passed: true,
|
|
quality_gates_run: [],
|
|
quality_gates_failed: [],
|
|
context_compactions: 0,
|
|
context_rotations: 0,
|
|
context_utilization_final: 0.3,
|
|
outcome: Outcome.SUCCESS,
|
|
retry_count: 0,
|
|
});
|
|
|
|
expect(event.event_id).not.toBe(event2.event_id);
|
|
});
|
|
|
|
it("should auto-set timestamp to ISO 8601", () => {
|
|
const now = new Date("2026-02-07T10:00:00.000Z");
|
|
vi.setSystemTime(now);
|
|
|
|
const builder = new EventBuilder(makeConfig());
|
|
const event = builder.build({
|
|
task_duration_ms: 1000,
|
|
task_type: TaskType.DEBUGGING,
|
|
complexity: Complexity.MEDIUM,
|
|
harness: Harness.OPENCODE,
|
|
model: "claude-3-sonnet",
|
|
provider: Provider.ANTHROPIC,
|
|
estimated_input_tokens: 500,
|
|
estimated_output_tokens: 200,
|
|
actual_input_tokens: 500,
|
|
actual_output_tokens: 200,
|
|
estimated_cost_usd_micros: 5000,
|
|
actual_cost_usd_micros: 5000,
|
|
quality_gate_passed: false,
|
|
quality_gates_run: [QualityGate.TEST],
|
|
quality_gates_failed: [QualityGate.TEST],
|
|
context_compactions: 0,
|
|
context_rotations: 0,
|
|
context_utilization_final: 0.4,
|
|
outcome: Outcome.FAILURE,
|
|
retry_count: 1,
|
|
});
|
|
|
|
expect(event.timestamp).toBe("2026-02-07T10:00:00.000Z");
|
|
});
|
|
|
|
it("should set instance_id from config", () => {
|
|
const config = makeConfig();
|
|
const builder = new EventBuilder(config);
|
|
const event = builder.build({
|
|
task_duration_ms: 1000,
|
|
task_type: TaskType.PLANNING,
|
|
complexity: Complexity.LOW,
|
|
harness: Harness.UNKNOWN,
|
|
model: "test-model",
|
|
provider: Provider.UNKNOWN,
|
|
estimated_input_tokens: 0,
|
|
estimated_output_tokens: 0,
|
|
actual_input_tokens: 0,
|
|
actual_output_tokens: 0,
|
|
estimated_cost_usd_micros: 0,
|
|
actual_cost_usd_micros: 0,
|
|
quality_gate_passed: true,
|
|
quality_gates_run: [],
|
|
quality_gates_failed: [],
|
|
context_compactions: 0,
|
|
context_rotations: 0,
|
|
context_utilization_final: 0,
|
|
outcome: Outcome.SUCCESS,
|
|
retry_count: 0,
|
|
});
|
|
|
|
expect(event.instance_id).toBe("my-instance-uuid");
|
|
});
|
|
|
|
it("should set schema_version to 1.0", () => {
|
|
const builder = new EventBuilder(makeConfig());
|
|
const event = builder.build({
|
|
task_duration_ms: 1000,
|
|
task_type: TaskType.REFACTORING,
|
|
complexity: Complexity.CRITICAL,
|
|
harness: Harness.KILO_CODE,
|
|
model: "gemini-pro",
|
|
provider: Provider.GOOGLE,
|
|
estimated_input_tokens: 3000,
|
|
estimated_output_tokens: 2000,
|
|
actual_input_tokens: 3000,
|
|
actual_output_tokens: 2000,
|
|
estimated_cost_usd_micros: 80000,
|
|
actual_cost_usd_micros: 80000,
|
|
quality_gate_passed: true,
|
|
quality_gates_run: [QualityGate.TYPECHECK],
|
|
quality_gates_failed: [],
|
|
context_compactions: 5,
|
|
context_rotations: 2,
|
|
context_utilization_final: 0.95,
|
|
outcome: Outcome.SUCCESS,
|
|
retry_count: 0,
|
|
});
|
|
|
|
expect(event.schema_version).toBe("1.0");
|
|
});
|
|
});
|