| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803 |
- #!/usr/bin/env bun
- export {};
- /**
- * Example: bun scripts/benchmark-opencode-cache.ts --server http://127.0.0.1:4096 --provider anthropic --model claude-sonnet-4-5 --runs 10 --output /tmp/cache.json --arm plugin-on --plugin-build $(git rev-parse HEAD)
- * Direct HTTP only: POST /session, POST/GET/DELETE /session/:id/message, GET /event, GET /global/health.
- */
- type Json = Record<string, unknown>;
- type Event = {
- at: number;
- type: string;
- sessionID?: string;
- messageID?: string;
- partID?: string;
- field?: string;
- partType?: string;
- status?: string;
- retryAttempt?: number;
- };
- type RequestObservation = {
- position: number;
- warmup: boolean;
- input: number | null;
- output: number | null;
- cacheRead: number | null;
- cacheWrite: number | null;
- totalInput: number | null;
- };
- type PromptLoopObservation = {
- turn: number;
- warmup: boolean;
- promptLoopTtftMs: number | null;
- promptLoopLatencyMs: number | null;
- };
- const HELP = `Usage: bun scripts/benchmark-opencode-cache.ts [options]
- Required:
- --server URL --provider ID --model ID --runs N --output PATH
- --arm ID Comparison arm identifier (for example plugin-on)
- --plugin-build ID Plugin build/commit identifier
- Options:
- --timeout-ms N Per-request timeout (default: 120000)
- --retries N Retry transient GET/create/probe failures (default: 2)
- --retry-delay-ms N Initial exponential-backoff delay (default: 500)
- --header NAME:VALUE Extra HTTP header; repeatable, never persisted
- --overwrite Replace an existing output file
- --help Show this help
- Each independent session explicitly targets agent "orchestrator" and the supplied
- provider/model. It requests Read(package.json), TodoWrite, a final answer, then a
- second user follow-up. Incomplete, retrying, compacted, or misrouted sessions are
- recorded as discards, never resampled. Output contains only normalized/redacted
- telemetry: no prompts, model text, tool I/O, workspace paths, headers, or event
- properties. Prompt-loop TTFT/latency are one observation per submitted user
- prompt, never copied to provider steps. SSE coverage must be established before
- prompts; an unavailable, malformed, or closed stream discards the session. A
- unique per-session nonce is kept only in live prompts.
- Assistant and provider errors are retained only as safe error-code classifications
- and always discard the session.
- Sessions are deleted after collection.
- `;
- function fail(message: string): never {
- console.error(`Error: ${message}\n\n${HELP}`);
- process.exit(2);
- }
- function isRecord(value: unknown): value is Json {
- return !!value && typeof value === 'object' && !Array.isArray(value);
- }
- function string(value: unknown) {
- return typeof value === 'string' ? value : undefined;
- }
- function number(value: unknown) {
- return typeof value === 'number' && Number.isFinite(value)
- ? value
- : undefined;
- }
- function errorCode(value: unknown) {
- if (!isRecord(value))
- return value === undefined || value === null ? null : 'unknown';
- const name = string(value.name) ?? string(value.code) ?? string(value.type);
- if (
- name === 'APIError' ||
- name === 'ProviderAuthError' ||
- name === 'MessageAbortedError' ||
- name === 'StructuredOutputError' ||
- name === 'ContextOverflowError' ||
- name === 'MessageOutputLengthError' ||
- name === 'Unknown'
- ) {
- return name;
- }
- return 'unknown';
- }
- function urlPath(base: string, route: string) {
- return `${base}${route.startsWith('/') ? route : `/${route}`}`;
- }
- const now = () => performance.timeOrigin + performance.now();
- const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
- function parseArgs(argv: string[]) {
- const values = new Map<string, string[]>();
- const flags = new Set<string>();
- const names = [
- '--server',
- '--provider',
- '--model',
- '--runs',
- '--output',
- '--arm',
- '--plugin-build',
- '--timeout-ms',
- '--retries',
- '--retry-delay-ms',
- '--header',
- ];
- for (let i = 0; i < argv.length; i += 1) {
- if (argv[i] === '--help') {
- console.log(HELP);
- process.exit(0);
- }
- if (argv[i] === '--overwrite') {
- flags.add(argv[i]);
- continue;
- }
- if (!names.includes(argv[i])) fail(`unknown argument ${argv[i]}`);
- const value = argv[i + 1];
- if (!value || value.startsWith('--')) fail(`missing value for ${argv[i]}`);
- values.set(argv[i], [...(values.get(argv[i]) ?? []), value]);
- i += 1;
- }
- const required = (name: string) => {
- const value = values.get(name)?.at(-1);
- if (!value) fail(`missing required ${name}`);
- return value;
- };
- const integer = (name: string, fallback?: number) => {
- const value = Number(values.get(name)?.at(-1) ?? fallback);
- if (
- !Number.isSafeInteger(value) ||
- value < 0 ||
- (name === '--runs' && value === 0)
- )
- fail(
- `${name} must be a ${name === '--runs' ? 'positive' : 'non-negative'} integer`,
- );
- return value;
- };
- let server: URL;
- try {
- server = new URL(required('--server'));
- } catch {
- fail('--server must be an absolute http(s) URL');
- }
- if (!['http:', 'https:'].includes(server.protocol))
- fail('--server must be an http(s) URL');
- const headers = new Headers();
- for (const value of values.get('--header') ?? []) {
- const split = value.indexOf(':');
- if (split < 1) fail('--header must be NAME:VALUE');
- headers.append(value.slice(0, split), value.slice(split + 1).trim());
- }
- return {
- server: server.toString().replace(/\/$/, ''),
- provider: required('--provider'),
- model: required('--model'),
- runs: integer('--runs'),
- output: required('--output'),
- arm: required('--arm'),
- pluginBuild: required('--plugin-build'),
- timeoutMs: integer('--timeout-ms', 120_000),
- retries: integer('--retries', 2),
- retryDelayMs: integer('--retry-delay-ms', 500),
- headers,
- overwrite: flags.has('--overwrite'),
- };
- }
- const args = parseArgs(process.argv.slice(2));
- if ((await Bun.file(args.output).exists()) && !args.overwrite)
- fail(`output already exists: ${args.output} (use --overwrite)`);
- async function request(
- method: string,
- route: string,
- body?: Json,
- retry = false,
- ) {
- let last = 'request failed';
- for (let attempt = 0; attempt <= args.retries; attempt += 1) {
- const controller = new AbortController();
- const timeout = setTimeout(() => controller.abort(), args.timeoutMs);
- try {
- const headers = new Headers(args.headers);
- if (body) headers.set('content-type', 'application/json');
- const response = await fetch(urlPath(args.server, route), {
- method,
- headers,
- body: body ? JSON.stringify(body) : undefined,
- signal: controller.signal,
- });
- const text = await response.text();
- if (response.ok)
- return text.trim() ? (JSON.parse(text) as unknown) : undefined;
- last = `${method} ${route} returned HTTP ${response.status}`;
- if (!retry || response.status < 500 || attempt === args.retries)
- throw new Error(last);
- } catch (error) {
- last = error instanceof Error ? error.message : String(error);
- if (!retry || attempt === args.retries) throw new Error(last);
- } finally {
- clearTimeout(timeout);
- }
- await sleep(args.retryDelayMs * 2 ** attempt);
- }
- throw new Error(last);
- }
- function normalizeEvent(value: unknown): Event | undefined {
- if (!isRecord(value) || !isRecord(value.properties)) return undefined;
- const properties = value.properties;
- const type = string(value.type);
- const sessionID = string(properties.sessionID);
- if (!type || !sessionID) return undefined;
- if (type === 'message.part.delta')
- return {
- at: now(),
- type,
- sessionID,
- messageID: string(properties.messageID),
- partID: string(properties.partID),
- field: string(properties.field),
- };
- if (type === 'message.part.updated' && isRecord(properties.part))
- return {
- at: now(),
- type,
- sessionID,
- messageID: string(properties.part.messageID),
- partID: string(properties.part.id),
- partType: string(properties.part.type),
- status: isRecord(properties.part.state)
- ? string(properties.part.state.status)
- : undefined,
- };
- if (type === 'message.updated' && isRecord(properties.info))
- return {
- at: now(),
- type,
- sessionID,
- messageID: string(properties.info.id),
- };
- if (type === 'session.status' && isRecord(properties.status))
- return {
- at: now(),
- type,
- sessionID,
- status: string(properties.status.type),
- retryAttempt: number(properties.status.attempt),
- };
- if (type.toLowerCase().includes('compaction'))
- return { at: now(), type, sessionID };
- return undefined;
- }
- type StreamCoverage = {
- ready: Promise<void>;
- readyResolve: () => void;
- issue: string | null;
- };
- function streamCoverage(): StreamCoverage {
- let readyResolve = () => {};
- const ready = new Promise<void>((resolve) => {
- readyResolve = resolve;
- });
- return { ready, readyResolve, issue: null };
- }
- async function awaitSseReadiness(coverage: StreamCoverage) {
- let timeout: ReturnType<typeof setTimeout> | undefined;
- try {
- await Promise.race([
- coverage.ready,
- new Promise<void>((_, reject) => {
- timeout = setTimeout(
- () => reject(new Error('SSE subscription readiness timed out')),
- Math.min(args.timeoutMs, 10_000),
- );
- }),
- ]);
- } finally {
- if (timeout) clearTimeout(timeout);
- }
- if (coverage.issue) throw new Error(coverage.issue);
- }
- async function eventStream(
- events: Event[],
- controller: AbortController,
- coverage: StreamCoverage,
- ) {
- try {
- const response = await fetch(urlPath(args.server, '/event'), {
- headers: args.headers,
- signal: controller.signal,
- });
- if (!response.ok || !response.body)
- throw new Error(`GET /event returned HTTP ${response.status}`);
- const reader = response.body.getReader();
- const decoder = new TextDecoder();
- let buffer = '';
- while (!controller.signal.aborted) {
- const chunk = await reader.read();
- if (chunk.done) break;
- buffer += decoder.decode(chunk.value, { stream: true });
- const frames = buffer.split(/\r?\n\r?\n/);
- buffer = frames.pop() ?? '';
- for (const frame of frames) {
- const data = frame
- .split(/\r?\n/)
- .find((line) => line.startsWith('data:'))
- ?.slice(5)
- .trim();
- if (!data) continue;
- try {
- const parsed = JSON.parse(data) as unknown;
- if (isRecord(parsed) && parsed.type === 'server.connected') {
- coverage.readyResolve();
- continue;
- }
- const event = normalizeEvent(parsed);
- if (event) events.push(event);
- } catch {
- coverage.issue ??= 'SSE delivered a malformed frame';
- coverage.readyResolve();
- }
- }
- }
- if (!controller.signal.aborted) {
- coverage.issue ??= 'SSE stream closed before collection completed';
- coverage.readyResolve();
- }
- } catch {
- if (!controller.signal.aborted) {
- coverage.issue ??= 'SSE stream connection failed';
- coverage.readyResolve();
- }
- }
- }
- function normalizeMessage(value: unknown) {
- if (!isRecord(value) || !isRecord(value.info)) return undefined;
- const info = value.info;
- const parts = Array.isArray(value.parts) ? value.parts : [];
- return {
- id: string(info.id),
- parentID: string(info.parentID),
- role: string(info.role),
- agent: string(info.agent),
- providerID: string(info.providerID),
- modelID: string(info.modelID),
- errorCode: errorCode(info.error),
- tokens: isRecord(info.tokens) ? info.tokens : undefined,
- parts: parts.filter(isRecord).map((part) => ({
- type: string(part.type),
- tool: string(part.tool),
- status: isRecord(part.state) ? string(part.state.status) : undefined,
- errorCode: part.type === 'retry' ? errorCode(part.error) : null,
- tokens: isRecord(part.tokens) ? part.tokens : undefined,
- })),
- };
- }
- function tokenObservation(
- tokens: unknown,
- position: number,
- warmup: boolean,
- ): RequestObservation {
- const tokenRecord = isRecord(tokens) ? tokens : {};
- const cache = isRecord(tokenRecord.cache) ? tokenRecord.cache : undefined;
- const input = number(tokenRecord.input) ?? null;
- const cacheRead = cache ? (number(cache.read) ?? null) : null;
- const cacheWrite = cache ? (number(cache.write) ?? null) : null;
- const totalInput =
- input === null || cacheRead === null || cacheWrite === null
- ? null
- : input + cacheRead + cacheWrite;
- return {
- position,
- warmup,
- input,
- output: number(tokenRecord.output) ?? null,
- cacheRead,
- cacheWrite,
- totalInput,
- };
- }
- function percentile(values: number[], p: number) {
- if (!values.length) return null;
- const sorted = [...values].sort((a, b) => a - b);
- return sorted[
- Math.min(sorted.length - 1, Math.ceil((p / 100) * sorted.length) - 1)
- ];
- }
- function boundedCoverage(observations: RequestObservation[]) {
- const measured = observations.filter(
- (item) => item.cacheRead !== null && item.totalInput !== null,
- );
- const total = measured.reduce((sum, item) => sum + (item.totalInput ?? 0), 0);
- return total > 0
- ? Math.min(
- 1,
- Math.max(
- 0,
- measured.reduce((sum, item) => sum + (item.cacheRead ?? 0), 0) /
- total,
- ),
- )
- : null;
- }
- function bootstrapCI<T>(
- sessions: T[][],
- metric: (items: T[]) => number | null,
- ) {
- const observed = metric(sessions.flat());
- if (!sessions.length || observed === null)
- return { estimate: observed, lower: null, upper: null, samples: 0 };
- let state = 0x9e3779b9;
- const random = () => {
- state = (state * 1664525 + 1013904223) >>> 0;
- return state / 2 ** 32;
- };
- const values: number[] = [];
- for (let i = 0; i < 2000; i += 1) {
- const sampled = Array.from(
- { length: sessions.length },
- () => sessions[Math.floor(random() * sessions.length)],
- ).flat();
- const value = metric(sampled);
- if (value !== null) values.push(value);
- }
- return {
- estimate: observed,
- lower: percentile(values, 2.5),
- upper: percentile(values, 97.5),
- samples: values.length,
- };
- }
- function firstPrompt(nonce: string) {
- return `Session marker: ${nonce}. Use the Read tool to inspect package.json. Then use the TodoWrite tool to create one completed, low-priority todo named "cache benchmark trace". Do not modify files. After both tools finish, reply with exactly: benchmark complete.`;
- }
- function followUp(nonce: string) {
- return `Session marker: ${nonce}. Without using tools, reply with exactly: follow-up complete.`;
- }
- async function run(index: number) {
- const events: Event[] = [];
- const controller = new AbortController();
- const coverage = streamCoverage();
- const stream = eventStream(events, controller, coverage);
- let sessionID: string | undefined;
- const record: Json = {
- runIndex: index,
- runOrder: index + 1,
- requestedRouting: {
- agent: 'orchestrator',
- providerID: args.provider,
- modelID: args.model,
- },
- };
- try {
- await awaitSseReadiness(coverage);
- const created = await request('POST', '/session', {}, true);
- sessionID = isRecord(created) ? string(created.id) : undefined;
- if (!sessionID) throw new Error('POST /session returned no session id');
- record.sessionID = sessionID;
- const nonce = crypto.randomUUID();
- const prompts: {
- parentMessageID?: string;
- startedAt: number;
- completedAt: number;
- }[] = [];
- for (const text of [firstPrompt(nonce), followUp(nonce)]) {
- const startedAt = now();
- const response = await request(
- 'POST',
- `/session/${encodeURIComponent(sessionID)}/message`,
- {
- agent: 'orchestrator',
- model: { providerID: args.provider, modelID: args.model },
- parts: [{ type: 'text', text }],
- },
- );
- const normalized = normalizeMessage(response);
- prompts.push({
- // POST /message returns the assistant message; its parent is this turn's user message.
- parentMessageID: normalized?.parentID,
- startedAt,
- completedAt: now(),
- });
- }
- const [rawMessages, rawSession] = await Promise.all([
- request(
- 'GET',
- `/session/${encodeURIComponent(sessionID)}/message`,
- undefined,
- true,
- ),
- request(
- 'GET',
- `/session/${encodeURIComponent(sessionID)}`,
- undefined,
- true,
- ),
- ]);
- const messages = Array.isArray(rawMessages)
- ? rawMessages
- .map(normalizeMessage)
- .filter((item): item is NonNullable<typeof item> => !!item)
- : [];
- const session = isRecord(rawSession) ? rawSession : {};
- const sessionModel = isRecord(session.model) ? session.model : {};
- const sessionEvents = events.filter(
- (event) => event.sessionID === sessionID,
- );
- const assistants = messages.filter(
- (message) => message.role === 'assistant',
- );
- const tools = assistants.flatMap((message) =>
- message.parts
- .filter((part) => part.type === 'tool')
- .map((part) => ({ tool: part.tool, status: part.status })),
- );
- const observations: RequestObservation[] = [];
- const promptLoops: PromptLoopObservation[] = [];
- let position = 0;
- for (const prompt of prompts) {
- const assistantIDs = new Set(
- assistants
- .filter((message) => message.parentID === prompt.parentMessageID)
- .map((message) => message.id)
- .filter((id): id is string => !!id),
- );
- promptLoops.push({
- turn: promptLoops.length + 1,
- warmup: promptLoops.length === 0,
- promptLoopTtftMs: (() => {
- const event = sessionEvents.find(
- (item) =>
- item.at >= prompt.startedAt &&
- item.at <= prompt.completedAt &&
- item.messageID &&
- assistantIDs.has(item.messageID) &&
- item.type === 'message.part.delta' &&
- ['text', 'reasoning'].includes(item.field ?? ''),
- );
- return event ? event.at - prompt.startedAt : null;
- })(),
- promptLoopLatencyMs: prompt.completedAt - prompt.startedAt,
- });
- const perPrompt = assistants
- .filter((message) => message.parentID === prompt.parentMessageID)
- .flatMap((message) =>
- message.parts
- .filter((part) => part.type === 'step-finish')
- .map((part) => part.tokens),
- );
- const tokenSets = perPrompt.length
- ? perPrompt
- : assistants
- .filter((message) => message.parentID === prompt.parentMessageID)
- .map((message) => message.tokens);
- for (const tokens of tokenSets) {
- position += 1;
- observations.push(tokenObservation(tokens, position, position === 1));
- }
- }
- const retries = sessionEvents.filter(
- (event) => event.type === 'session.status' && event.status === 'retry',
- ).length;
- const assistantErrorCodes = assistants
- .map((message) => message.errorCode)
- .filter((code): code is string => code !== null);
- const providerErrorCodes = messages.flatMap((message) =>
- message.parts
- .filter((part) => part.type === 'retry')
- .map((part) => part.errorCode)
- .filter((code): code is string => code !== null),
- );
- const historyRetry = messages.some((message) =>
- message.parts.some((part) => part.type === 'retry'),
- );
- const historyCompaction =
- string(session.agent) === 'compaction' ||
- messages.some(
- (message) =>
- message.agent === 'compaction' ||
- message.parts.some((part) => part.type === 'compaction'),
- ) ||
- (isRecord(session.time) && number(session.time.compacting) !== undefined);
- const compaction =
- historyCompaction ||
- sessionEvents.some((event) =>
- event.type.toLowerCase().includes('compaction'),
- );
- const routingMatches =
- string(session.agent) === 'orchestrator' &&
- string(sessionModel.providerID) === args.provider &&
- string(sessionModel.id) === args.model &&
- assistants.length > 0 &&
- assistants.every(
- (message) =>
- message.agent === 'orchestrator' &&
- message.providerID === args.provider &&
- message.modelID === args.model,
- );
- const reasons = [
- ...(tools.some(
- (tool) =>
- tool.tool?.toLowerCase() === 'read' && tool.status === 'completed',
- )
- ? []
- : ['missing completed Read tool']),
- ...(tools.some(
- (tool) =>
- tool.tool?.toLowerCase() === 'todowrite' &&
- tool.status === 'completed',
- )
- ? []
- : ['missing completed harmless TodoWrite tool']),
- ...(assistants.some((message) =>
- message.parts.some((part) => part.type === 'text'),
- )
- ? []
- : ['missing assistant final response']),
- ...(messages.filter((message) => message.role === 'user').length >= 2
- ? []
- : ['missing second user follow-up']),
- ...(routingMatches
- ? []
- : [
- 'observed session/assistant routing does not match orchestrator/provider/model',
- ]),
- ...assistantErrorCodes.map((code) =>
- ['APIError', 'ProviderAuthError'].includes(code)
- ? `provider_error:${code}`
- : `assistant_error:${code}`,
- ),
- ...providerErrorCodes.map((code) => `provider_error:${code}`),
- ...(coverage.issue ? [coverage.issue] : []),
- ...(retries || historyRetry ? ['session entered retry state'] : []),
- ...(compaction ? ['session compaction observed'] : []),
- ];
- record.observation = {
- routing: {
- sessionAgent: string(session.agent) ?? null,
- sessionProviderID: string(sessionModel.providerID) ?? null,
- sessionModelID: string(sessionModel.id) ?? null,
- assistantCount: assistants.length,
- },
- events: sessionEvents,
- tools,
- requests: observations,
- promptLoops,
- retries,
- compaction,
- historyRetry,
- historyCompaction,
- assistantErrorCodes,
- providerErrorCodes,
- };
- record.discarded = reasons.length > 0;
- if (reasons.length) record.discardReasons = reasons;
- } catch (error) {
- record.discarded = true;
- record.discardReasons = [
- error instanceof Error ? error.message : String(error),
- ];
- record.observation = { events };
- } finally {
- if (sessionID) {
- try {
- await request('DELETE', `/session/${encodeURIComponent(sessionID)}`);
- } catch {
- record.cleanupError = 'session deletion failed';
- }
- }
- controller.abort();
- await stream;
- }
- return record;
- }
- let hostVersion: string | null = null;
- try {
- const health = await request('GET', '/global/health', undefined, true);
- hostVersion = isRecord(health) ? (string(health.version) ?? null) : null;
- } catch {
- /* probe is optional */
- }
- const runs: Json[] = [];
- for (let index = 0; index < args.runs; index += 1) {
- console.error(`Running session ${index + 1}/${args.runs}`);
- runs.push(await run(index));
- }
- const eligible = runs.filter((run) => !run.discarded);
- const aggregateSessions = eligible.map((run) =>
- isRecord(run.observation) && Array.isArray(run.observation.requests)
- ? run.observation.requests
- .filter(isRecord)
- .map((item) => item as unknown as RequestObservation)
- .filter((item) => !item.warmup)
- : [],
- );
- const aggregate = aggregateSessions.flat();
- const promptLoopSessions = eligible.map((run) =>
- isRecord(run.observation) && Array.isArray(run.observation.promptLoops)
- ? run.observation.promptLoops
- .filter(isRecord)
- .map((item) => item as unknown as PromptLoopObservation)
- .filter((item) => !item.warmup)
- : [],
- );
- const promptLoops = promptLoopSessions.flat();
- const cacheMiss = (items: RequestObservation[]) => {
- const measured = items.filter((item) => item.cacheRead !== null);
- return measured.length
- ? measured.filter((item) => item.cacheRead === 0).length / measured.length
- : null;
- };
- const ttftP50 = (items: PromptLoopObservation[]) =>
- percentile(
- items
- .map((item) => item.promptLoopTtftMs)
- .filter((value): value is number => value !== null),
- 50,
- );
- const latencyP50 = (items: PromptLoopObservation[]) =>
- percentile(
- items
- .map((item) => item.promptLoopLatencyMs)
- .filter((value): value is number => value !== null),
- 50,
- );
- const report = {
- schemaVersion: 2,
- generatedAt: new Date().toISOString(),
- comparison: {
- arm: args.arm,
- pluginBuild: args.pluginBuild,
- hostOpenCodeVersion: hostVersion,
- runOrder: 'sequential independent sessions',
- routingFingerprint: {
- agent: 'orchestrator',
- providerID: args.provider,
- modelID: args.model,
- },
- },
- controls: {
- runs: args.runs,
- timeoutMs: args.timeoutMs,
- retries: args.retries,
- retryDelayMs: args.retryDelayMs,
- warmupRule:
- 'exclude request position 1 in each eligible session from aggregates',
- },
- metrics: {
- sessionsRequested: args.runs,
- sessionsEligible: eligible.length,
- sessionsDiscarded: runs.length - eligible.length,
- requestObservationsRaw: eligible.flatMap((run) =>
- isRecord(run.observation) && Array.isArray(run.observation.requests)
- ? run.observation.requests
- : [],
- ).length,
- requestObservationsAggregated: aggregate.length,
- promptLoopObservationsRaw: eligible.flatMap((run) =>
- isRecord(run.observation) && Array.isArray(run.observation.promptLoops)
- ? run.observation.promptLoops
- : [],
- ).length,
- promptLoopObservationsAggregated: promptLoops.length,
- primaryMetricsSessionBootstrap95CI: {
- zeroCacheMissRate: bootstrapCI(aggregateSessions, cacheMiss),
- cacheCoverage: bootstrapCI(aggregateSessions, boundedCoverage),
- promptLoopTtftMsP50: bootstrapCI(promptLoopSessions, ttftP50),
- promptLoopLatencyMsP50: bootstrapCI(promptLoopSessions, latencyP50),
- },
- },
- runs,
- };
- await Bun.write(args.output, `${JSON.stringify(report, null, 2)}\n`);
- console.error(
- `Wrote ${args.output}: ${eligible.length}/${args.runs} eligible sessions`,
- );
|