@leostera/evalkit 0.5.0 → 0.6.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/CHANGELOG.md +55 -1
- package/README.md +10 -8
- package/dist/cli.mjs +1227 -258
- package/dist/dashboard/assets/index-BK9x-zoi.css +2 -0
- package/dist/dashboard/assets/index-DzsDLGHx.js +32 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/files-C-U0-PWW.mjs +0 -2
- package/dist/index-db-vbqEGFaU.mjs +0 -2
- package/dist/index.d.mts +1344 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -4
- package/dist/runner.d.mts +807 -11
- package/dist/runner.d.mts.map +1 -1
- package/dist/runner.mjs +2 -2
- package/dist/share-worker.d.mts +76 -1
- package/dist/share-worker.d.mts.map +1 -1
- package/dist/share-worker.mjs +0 -2
- package/dist/share.d.mts +149 -6
- package/dist/share.d.mts.map +1 -1
- package/dist/share.mjs +1 -1
- package/dist/skills/evalkit/SKILL.md +32 -0
- package/dist/skills/evalkit-agents/SKILL.md +16 -0
- package/dist/skills/evalkit-datasets/SKILL.md +17 -0
- package/dist/skills/evalkit-evals/SKILL.md +19 -0
- package/dist/skills/evalkit-judges/SKILL.md +17 -0
- package/dist/skills/evalkit-matrices/SKILL.md +14 -0
- package/dist/skills/evalkit-results/SKILL.md +14 -0
- package/dist/{src-DoPs9Yug.mjs → src-CVSCn3bZ.mjs} +445 -115
- package/dist/{src-DzZueFn3.mjs → src-CZnDXP1K.mjs} +46 -10
- package/dist/{src-ButXPY8P.mjs → src-D4tCwxNb.mjs} +418 -94
- package/package.json +3 -2
- package/dist/cli.mjs.map +0 -1
- package/dist/dashboard/assets/index-D9NtA46z.css +0 -2
- package/dist/dashboard/assets/index-DrBwLKJD.js +0 -30
- package/dist/files-C-U0-PWW.mjs.map +0 -1
- package/dist/index-db-HdZXelOS.d.mts +0 -142
- package/dist/index-db-HdZXelOS.d.mts.map +0 -1
- package/dist/index-db-vbqEGFaU.mjs.map +0 -1
- package/dist/index-lOw0fmak.d.mts +0 -1028
- package/dist/index-lOw0fmak.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/share-worker.mjs.map +0 -1
- package/dist/src-ButXPY8P.mjs.map +0 -1
- package/dist/src-DoPs9Yug.mjs.map +0 -1
- package/dist/src-DzZueFn3.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"files-C-U0-PWW.mjs","names":[],"sources":["../../share/src/files.ts"],"sourcesContent":["/** Where uploaded result files live: R2 in a Worker, a directory elsewhere. */\nexport type ShareFiles = {\n get(key: string): Promise<ReadableStream<Uint8Array> | Uint8Array | null>;\n put(key: string, data: Uint8Array | string): Promise<void>;\n /** Every key below `prefix`, in no particular order. */\n list(prefix: string): AsyncIterable<string>;\n};\n\n/** The subset of the Workers R2 binding used here. */\nexport type R2BucketLike = {\n get(key: string): Promise<{ body: ReadableStream<Uint8Array> } | null>;\n put(key: string, value: Uint8Array | string): Promise<unknown>;\n list(options: { prefix: string; cursor?: string }): Promise<{\n objects: { key: string }[];\n truncated: boolean;\n cursor?: string;\n }>;\n};\n\nexport function r2Files(bucket: R2BucketLike): ShareFiles {\n return {\n async get(key) {\n return (await bucket.get(key))?.body ?? null;\n },\n async put(key, data) {\n await bucket.put(key, data);\n },\n async *list(prefix) {\n let cursor: string | undefined;\n do {\n const page = await bucket.list({ prefix, cursor });\n for (const object of page.objects) yield object.key;\n cursor = page.truncated ? page.cursor : undefined;\n } while (cursor);\n },\n };\n}\n"],"mappings":";AAmBA,SAAgB,QAAQ,QAAkC;CACxD,OAAO;EACL,MAAM,IAAI,KAAK;GACb,QAAQ,MAAM,OAAO,IAAI,GAAG,EAAA,EAAI,QAAQ;EAC1C;EACA,MAAM,IAAI,KAAK,MAAM;GACnB,MAAM,OAAO,IAAI,KAAK,IAAI;EAC5B;EACA,OAAO,KAAK,QAAQ;GAClB,IAAI;GACJ,GAAG;IACD,MAAM,OAAO,MAAM,OAAO,KAAK;KAAE;KAAQ;IAAO,CAAC;IACjD,KAAK,MAAM,UAAU,KAAK,SAAS,MAAM,OAAO;IAChD,SAAS,KAAK,YAAY,KAAK,SAAS,KAAA;GAC1C,SAAS;EACX;CACF;AACF"}
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
//#region ../share/src/files.d.ts
|
|
2
|
-
/** Where uploaded result files live: R2 in a Worker, a directory elsewhere. */
|
|
3
|
-
type ShareFiles = {
|
|
4
|
-
get(key: string): Promise<ReadableStream<Uint8Array> | Uint8Array | null>;
|
|
5
|
-
put(key: string, data: Uint8Array | string): Promise<void>;
|
|
6
|
-
/** Every key below `prefix`, in no particular order. */
|
|
7
|
-
list(prefix: string): AsyncIterable<string>;
|
|
8
|
-
};
|
|
9
|
-
/** The subset of the Workers R2 binding used here. */
|
|
10
|
-
type R2BucketLike = {
|
|
11
|
-
get(key: string): Promise<{
|
|
12
|
-
body: ReadableStream<Uint8Array>;
|
|
13
|
-
} | null>;
|
|
14
|
-
put(key: string, value: Uint8Array | string): Promise<unknown>;
|
|
15
|
-
list(options: {
|
|
16
|
-
prefix: string;
|
|
17
|
-
cursor?: string;
|
|
18
|
-
}): Promise<{
|
|
19
|
-
objects: {
|
|
20
|
-
key: string;
|
|
21
|
-
}[];
|
|
22
|
-
truncated: boolean;
|
|
23
|
-
cursor?: string;
|
|
24
|
-
}>;
|
|
25
|
-
};
|
|
26
|
-
declare function r2Files(bucket: R2BucketLike): ShareFiles;
|
|
27
|
-
//#endregion
|
|
28
|
-
//#region ../share/src/bundle.d.ts
|
|
29
|
-
/**
|
|
30
|
-
* A run bundle: the snapshot files for one run, as one gzip-compressed body.
|
|
31
|
-
*
|
|
32
|
-
* "EKBUNDLE" (8 bytes) · header length (u32 BE) · header JSON · file bytes…
|
|
33
|
-
* header = { format: 1, files: [{ path, size }, …] }, bytes in that order.
|
|
34
|
-
*
|
|
35
|
-
* Both ends are EvalKit, so this is simpler than tar and has no path-length limit.
|
|
36
|
-
*/
|
|
37
|
-
declare const BUNDLE_FORMAT = 1;
|
|
38
|
-
type BundleFile = {
|
|
39
|
-
path: string;
|
|
40
|
-
data: Uint8Array;
|
|
41
|
-
};
|
|
42
|
-
declare function encodeBundle(files: BundleFile[]): Promise<Uint8Array>;
|
|
43
|
-
/** Decode and check the framing; path rules are enforced by the caller. */
|
|
44
|
-
declare function decodeBundle(body: Uint8Array, limits: {
|
|
45
|
-
maxBytes: number;
|
|
46
|
-
}): Promise<BundleFile[]>;
|
|
47
|
-
//#endregion
|
|
48
|
-
//#region ../share/src/upload.d.ts
|
|
49
|
-
/** Finished runs only: a shared run's files are immutable once stored. */
|
|
50
|
-
type SharedRunStatus = 'passed' | 'failed' | 'errored';
|
|
51
|
-
type SharedSource = {
|
|
52
|
-
repo: string;
|
|
53
|
-
project: string;
|
|
54
|
-
commit: string;
|
|
55
|
-
ref?: string;
|
|
56
|
-
committedAt?: string;
|
|
57
|
-
dirty: boolean;
|
|
58
|
-
};
|
|
59
|
-
/** The fields of an uploaded run.json the server relies on. */
|
|
60
|
-
type SharedRun = {
|
|
61
|
-
id: string;
|
|
62
|
-
evalId: string;
|
|
63
|
-
suiteId?: string;
|
|
64
|
-
status: SharedRunStatus;
|
|
65
|
-
score?: number;
|
|
66
|
-
startedAt: string;
|
|
67
|
-
source: SharedSource;
|
|
68
|
-
/** Repository key (`repo` plus `/~project`), checked to be URL- and path-safe. */
|
|
69
|
-
repoKey: string;
|
|
70
|
-
/** The whole run.json object, served as-is in runs.json. */
|
|
71
|
-
summary: unknown;
|
|
72
|
-
};
|
|
73
|
-
/** A run bundle that passed every check; storing it cannot fail on its contents. */
|
|
74
|
-
type RunUpload = {
|
|
75
|
-
run: SharedRun;
|
|
76
|
-
runJson: Uint8Array;
|
|
77
|
-
catalog?: Uint8Array;
|
|
78
|
-
/** trials.json and trials/** files. */
|
|
79
|
-
files: BundleFile[];
|
|
80
|
-
};
|
|
81
|
-
declare function parseUpload(bundle: readonly BundleFile[]): RunUpload;
|
|
82
|
-
//#endregion
|
|
83
|
-
//#region ../share/src/index-db.d.ts
|
|
84
|
-
/**
|
|
85
|
-
* The share server's metadata index: repositories, commits and runs.
|
|
86
|
-
* R2 (or a directory) holds the files; this index answers "what exists" and
|
|
87
|
-
* every listing query. It is derived from stored run.json files and can be
|
|
88
|
-
* rebuilt from them (`POST /api/v1/reindex`).
|
|
89
|
-
*/
|
|
90
|
-
/** Synchronous SQLite access, provided by Durable Object storage or bun:sqlite. */
|
|
91
|
-
type Sql = {
|
|
92
|
-
all<T>(query: string, ...params: SqlValue[]): T[];
|
|
93
|
-
run(query: string, ...params: SqlValue[]): void;
|
|
94
|
-
transaction<T>(work: () => T): T;
|
|
95
|
-
};
|
|
96
|
-
type SqlValue = string | number | null;
|
|
97
|
-
type RepoRow = {
|
|
98
|
-
key: string;
|
|
99
|
-
url: string;
|
|
100
|
-
project: string;
|
|
101
|
-
firstSeenAt: string;
|
|
102
|
-
lastUploadAt: string;
|
|
103
|
-
commits: number;
|
|
104
|
-
};
|
|
105
|
-
type CommitRow = {
|
|
106
|
-
commit: string;
|
|
107
|
-
ref?: string;
|
|
108
|
-
committedAt?: string;
|
|
109
|
-
firstSeenAt: string;
|
|
110
|
-
runs: number;
|
|
111
|
-
passed: number;
|
|
112
|
-
failed: number;
|
|
113
|
-
};
|
|
114
|
-
/** The operations the app needs; async so a Durable Object can sit behind it. */
|
|
115
|
-
type ShareIndex = {
|
|
116
|
-
hasRun(runId: string): Promise<boolean>;
|
|
117
|
-
recordRun(run: SharedRun): Promise<void>;
|
|
118
|
-
repos(): Promise<RepoRow[]>;
|
|
119
|
-
commits(repo: string): Promise<CommitRow[]>;
|
|
120
|
-
runs(repo: string, sha: string): Promise<unknown[]>;
|
|
121
|
-
/** Full SHA for a full SHA, a unique prefix (≥ 7), or a ref's latest commit. */
|
|
122
|
-
resolve(repo: string, ref: string): Promise<string | undefined>;
|
|
123
|
-
latest(repo: string): Promise<string | undefined>;
|
|
124
|
-
};
|
|
125
|
-
declare class ShareIndexDb {
|
|
126
|
-
private readonly sql;
|
|
127
|
-
private readonly now;
|
|
128
|
-
constructor(sql: Sql, now?: () => Date);
|
|
129
|
-
hasRun(runId: string): boolean;
|
|
130
|
-
/** Idempotent: recording an indexed run again changes nothing. */
|
|
131
|
-
recordRun(run: SharedRun): void;
|
|
132
|
-
repos(): RepoRow[];
|
|
133
|
-
commits(repo: string): CommitRow[];
|
|
134
|
-
runs(repo: string, sha: string): unknown[];
|
|
135
|
-
resolve(repo: string, ref: string): string | undefined;
|
|
136
|
-
latest(repo: string): string | undefined;
|
|
137
|
-
}
|
|
138
|
-
/** Adapt the synchronous index (bun:sqlite) to the app's async interface. */
|
|
139
|
-
declare function asyncIndex(db: ShareIndexDb): ShareIndex;
|
|
140
|
-
//#endregion
|
|
141
|
-
export { r2Files as _, Sql as a, SharedRun as c, BUNDLE_FORMAT as d, BundleFile as f, ShareFiles as g, R2BucketLike as h, ShareIndexDb as i, SharedRunStatus as l, encodeBundle as m, RepoRow as n, SqlValue as o, decodeBundle as p, ShareIndex as r, asyncIndex as s, CommitRow as t, parseUpload as u };
|
|
142
|
-
//# sourceMappingURL=index-db-HdZXelOS.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-db-HdZXelOS.d.mts","names":[],"sources":["../../share/src/files.ts","../../share/src/bundle.ts","../../share/src/upload.ts","../../share/src/index-db.ts"],"mappings":";;KACY;EACV,IAAI,cAAc,QAAQ,eAAe,cAAc;EACvD,IAAI,aAAa,MAAM,sBAAsB;;EAE7C,KAAK,iBAAiB;;;KAIZ;EACV,IAAI,cAAc;IAAU,MAAM,eAAe;;EACjD,IAAI,aAAa,OAAO,sBAAsB;EAC9C,KAAK;IAAW;IAAgB;MAAoB;IAClD;MAAW;;IACX;IACA;;;iBAIY,QAAQ,QAAQ,eAAe;;;;;;;;;;;cCXlC;KAGD;EAAe;EAAc,MAAM;;iBAUzB,aAAa,OAAO,eAAe,QAAQ;;iBA2B3C,aACpB,MAAM,YACN;EAAU;IACT,QAAQ;;;;KCtCC;KAEA;EACV;EACA;EACA;EACA;EACA;EACA;;;KAIU;EACV;EACA;EACA;EACA,QAAQ;EACR;EACA;EACA,QAAQ;;EAER;;EAEA;;;KAUU;EACV,KAAK;EACL,SAAS;EACT,UAAU;;EAEV,OAAO;;iBAGO,YAAY,iBAAiB,eAAe;;;;;;;;;;KC5ChD;EACV,IAAI,GAAG,kBAAkB,QAAQ,aAAa;EAC9C,IAAI,kBAAkB,QAAQ;EAC9B,YAAY,GAAG,YAAY,IAAI;;KAErB;KAEA;EACV;EACA;EACA;EACA;EACA;EACA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;EACA;;;KAIU;EACV,OAAO,gBAAgB;EACvB,UAAU,KAAK,YAAY;EAC3B,SAAS,QAAQ;EACjB,QAAQ,eAAe,QAAQ;EAC/B,KAAK,cAAc,cAAc;;EAEjC,QAAQ,cAAc,cAAc;EACpC,OAAO,eAAe;;cA4CX;mBAEQ;mBACA;EAFnB,YACmB,KAAK,KACL,YAAW;EAK9B,OAAO;;EAKP,UAAU,KAAK;EAwDf,SAAS;EAST,QAAQ,eAAe;EAevB,KAAK,cAAc;EAUnB,QAAQ,cAAc;EAiBtB,OAAO;;;iBASO,WAAW,IAAI,eAAe"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-db-vbqEGFaU.mjs","names":[],"sources":["../../share/src/bundle.ts","../../share/src/html.ts","../../share/src/paths.ts","../../share/src/upload.ts","../../share/src/app.ts","../../share/src/index-db.ts"],"sourcesContent":["/**\n * A run bundle: the snapshot files for one run, as one gzip-compressed body.\n *\n * \"EKBUNDLE\" (8 bytes) · header length (u32 BE) · header JSON · file bytes…\n * header = { format: 1, files: [{ path, size }, …] }, bytes in that order.\n *\n * Both ends are EvalKit, so this is simpler than tar and has no path-length limit.\n */\nexport const BUNDLE_FORMAT = 1;\nconst MAGIC = new TextEncoder().encode('EKBUNDLE');\n\nexport type BundleFile = { path: string; data: Uint8Array };\n\nasync function pipe(\n data: Uint8Array,\n transform: CompressionStream | DecompressionStream,\n): Promise<Uint8Array> {\n const stream = new Blob([data as BlobPart]).stream().pipeThrough(transform);\n return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n\nexport async function encodeBundle(files: BundleFile[]): Promise<Uint8Array> {\n const header = new TextEncoder().encode(\n JSON.stringify({\n format: BUNDLE_FORMAT,\n files: files.map(({ path, data }) => ({ path, size: data.byteLength })),\n }),\n );\n const total =\n MAGIC.length +\n 4 +\n header.length +\n files.reduce((sum, file) => sum + file.data.byteLength, 0);\n const raw = new Uint8Array(total);\n raw.set(MAGIC, 0);\n new DataView(raw.buffer).setUint32(MAGIC.length, header.length);\n raw.set(header, MAGIC.length + 4);\n let offset = MAGIC.length + 4 + header.length;\n for (const file of files) {\n raw.set(file.data, offset);\n offset += file.data.byteLength;\n }\n return pipe(raw, new CompressionStream('gzip'));\n}\n\nexport class BundleError extends Error {}\n\n/** Decode and check the framing; path rules are enforced by the caller. */\nexport async function decodeBundle(\n body: Uint8Array,\n limits: { maxBytes: number },\n): Promise<BundleFile[]> {\n let raw: Uint8Array;\n try {\n raw = await pipe(body, new DecompressionStream('gzip'));\n } catch {\n throw new BundleError('Body is not a gzip-compressed EvalKit bundle');\n }\n if (raw.byteLength > limits.maxBytes)\n throw new BundleError(`Bundle exceeds ${limits.maxBytes} bytes`);\n if (\n raw.byteLength < MAGIC.length + 4 ||\n MAGIC.some((byte, index) => raw[index] !== byte)\n )\n throw new BundleError('Not an EvalKit bundle');\n const view = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);\n const headerLength = view.getUint32(MAGIC.length);\n const start = MAGIC.length + 4;\n let header: { format?: unknown; files?: { path: unknown; size: unknown }[] };\n try {\n header = JSON.parse(\n new TextDecoder().decode(raw.subarray(start, start + headerLength)),\n );\n } catch {\n throw new BundleError('Bundle header is not valid JSON');\n }\n if (header.format !== BUNDLE_FORMAT)\n throw new BundleError(`Unsupported bundle format ${String(header.format)}`);\n if (!Array.isArray(header.files))\n throw new BundleError('Bundle header has no file list');\n let offset = start + headerLength;\n const files: BundleFile[] = [];\n for (const entry of header.files) {\n if (\n typeof entry.path !== 'string' ||\n typeof entry.size !== 'number' ||\n !Number.isSafeInteger(entry.size) ||\n entry.size < 0 ||\n offset + entry.size > raw.byteLength\n )\n throw new BundleError('Bundle file list does not match its contents');\n files.push({\n path: entry.path,\n data: raw.subarray(offset, offset + entry.size),\n });\n offset += entry.size;\n }\n if (offset !== raw.byteLength)\n throw new BundleError('Bundle has trailing bytes');\n return files;\n}\n","/**\n * Turn the dashboard's index.html into a read-only page. The app derives its\n * router basename from `<base href>`. A static snapshot reads `data/…` below\n * the base; on the share server, `share` says where the API is.\n */\nexport type ShareContext = {\n /** All repositories: `/api/v1/repos`. */\n repos: string;\n /** This repository's commits, for the version picker. */\n commits?: string;\n /** This commit's snapshot data (replaces `<base>/data/`). */\n data?: string;\n repo?: string;\n /** A ref or SHA with no shared results. */\n missing?: string;\n};\n\nexport function dashboardIndex(\n html: string,\n options: { base: string; assets?: string; share?: ShareContext },\n): string {\n const attrs = [\n 'data-evalkit-snapshot=\"static\"',\n ...(options.share\n ? [`data-evalkit-share=\"${escapeAttr(JSON.stringify(options.share))}\"`]\n : []),\n ].join(' ');\n const result = html\n .replace('<html lang=\"en\">', `<html lang=\"en\" ${attrs}>`)\n .replace(\n '<head>',\n `<head>\\n <base href=\"${escapeAttr(options.base)}\" />`,\n )\n .replaceAll('\"/assets/', `\"${options.assets ?? './assets/'}`);\n if (\n !result.includes('data-evalkit-snapshot=\"static\"') ||\n !result.includes('<base href=')\n )\n throw new Error('Bundled dashboard index.html has an unexpected shape');\n return result;\n}\n\nfunction escapeAttr(value: string): string {\n return value\n .replaceAll('&', '&')\n .replaceAll('\"', '"')\n .replaceAll('<', '<');\n}\n","const UUID =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\nconst TRIAL_JSON =\n /^trials\\/([^/]+)\\/(detail|events|artifacts|workspace)\\.json$/;\nconst TRIAL_FILE = /^trials\\/([^/]+)\\/workspace\\/(.+)$/;\n\nexport const isUuid = (value: string) => UUID.test(value);\nexport const isSha = (value: string) => /^[0-9a-f]{40}$/.test(value);\n\n/** One path segment that cannot escape or alias another location. */\nexport function safeSegment(segment: string): boolean {\n return (\n segment.length > 0 &&\n segment.length <= 255 &&\n segment !== '.' &&\n segment !== '..' &&\n !/[\\\\/\\0]/.test(segment)\n );\n}\n\n/**\n * The only files a run bundle may contain (the snapshot format from\n * `evalkit build`, for one run). Never evaluator workspaces.\n */\nexport function allowedRunPath(path: string): boolean {\n if (path === 'run.json' || path === 'catalog.json' || path === 'trials.json')\n return true;\n const json = TRIAL_JSON.exec(path);\n if (json) return isUuid(json[1]!);\n const file = TRIAL_FILE.exec(path);\n return Boolean(\n file && isUuid(file[1]!) && file[2]!.split('/').every(safeSegment),\n );\n}\n\n/**\n * Repository key: normalized host/path, plus `/~<project>` for an eval\n * project below the repository root. Used in storage keys and URLs.\n */\nexport function repoKey(source: { repo: string; project: string }): string {\n return source.project ? `${source.repo}/~${source.project}` : source.repo;\n}\n\nexport function validRepoKey(key: string): boolean {\n const segments = key.split('/');\n return (\n segments.length >= 2 &&\n !segments.includes('-') &&\n segments.every(safeSegment)\n );\n}\n","import type { BundleFile } from './bundle.js';\nimport {\n allowedRunPath,\n isSha,\n isUuid,\n repoKey,\n validRepoKey,\n} from './paths.js';\n\n/** Rejected input: the client sent something the server will not store. */\nexport class Rejected extends Error {}\n\n/** Finished runs only: a shared run's files are immutable once stored. */\nexport type SharedRunStatus = 'passed' | 'failed' | 'errored';\n\nexport type SharedSource = {\n repo: string;\n project: string;\n commit: string;\n ref?: string;\n committedAt?: string;\n dirty: boolean;\n};\n\n/** The fields of an uploaded run.json the server relies on. */\nexport type SharedRun = {\n id: string;\n evalId: string;\n suiteId?: string;\n status: SharedRunStatus;\n score?: number;\n startedAt: string;\n source: SharedSource;\n /** Repository key (`repo` plus `/~project`), checked to be URL- and path-safe. */\n repoKey: string;\n /** The whole run.json object, served as-is in runs.json. */\n summary: unknown;\n};\n\nexport type RunCatalog = {\n catalog: unknown[];\n evals: unknown[];\n suites: unknown[];\n};\n\n/** A run bundle that passed every check; storing it cannot fail on its contents. */\nexport type RunUpload = {\n run: SharedRun;\n runJson: Uint8Array;\n catalog?: Uint8Array;\n /** trials.json and trials/** files. */\n files: BundleFile[];\n};\n\nexport function parseUpload(bundle: readonly BundleFile[]): RunUpload {\n const byPath = new Map<string, Uint8Array>();\n for (const file of bundle) {\n if (!allowedRunPath(file.path))\n throw new Rejected(`File not allowed in a run bundle: ${file.path}`);\n if (byPath.has(file.path))\n throw new Rejected(`Duplicate file in bundle: ${file.path}`);\n byPath.set(file.path, file.data);\n }\n const runJson = byPath.get('run.json');\n if (!runJson) throw new Rejected('Bundle has no run.json');\n const catalog = byPath.get('catalog.json');\n if (catalog) parseCatalog(catalog);\n return {\n run: parseRun(runJson),\n runJson,\n ...(catalog ? { catalog } : {}),\n files: bundle.filter(\n (file) => file.path !== 'run.json' && file.path !== 'catalog.json',\n ),\n };\n}\n\nexport function parseRun(data: Uint8Array): SharedRun {\n const value = record(parseJson(data, 'run.json'), 'run.json');\n const source = record(value.source, 'run.json source');\n const id = text(value.id, 'id');\n if (!isUuid(id)) throw new Rejected('run.json id must be a UUID');\n const commit = text(source.commit, 'source.commit');\n if (!isSha(commit))\n throw new Rejected('source.commit must be a full 40-character SHA');\n if (typeof source.dirty !== 'boolean')\n throw new Rejected('source.dirty must be a boolean');\n const status = value.status;\n if (status !== 'passed' && status !== 'failed' && status !== 'errored')\n throw new Rejected(\n `Only finished runs can be shared (status ${JSON.stringify(status)})`,\n );\n if (value.score !== undefined && typeof value.score !== 'number')\n throw new Rejected('score must be a number');\n const shared: SharedSource = {\n repo: text(source.repo, 'source.repo'),\n project: projectPath(source.project),\n commit,\n dirty: source.dirty,\n ...optionalText(source.ref, 'ref', 'source.ref'),\n ...optionalText(source.committedAt, 'committedAt', 'source.committedAt'),\n };\n const key = repoKey(shared);\n if (!validRepoKey(key)) throw new Rejected(`Invalid repository: ${key}`);\n return {\n id,\n evalId: text(value.evalId, 'evalId'),\n status,\n startedAt: text(value.startedAt, 'startedAt'),\n source: shared,\n repoKey: key,\n summary: value,\n ...optionalText(value.suiteId, 'suiteId', 'suiteId'),\n ...(typeof value.score === 'number' ? { score: value.score } : {}),\n };\n}\n\nexport function parseCatalog(data: Uint8Array): RunCatalog {\n const value = record(parseJson(data, 'catalog.json'), 'catalog.json');\n const list = (field: keyof RunCatalog) => {\n const items = value[field];\n if (!Array.isArray(items))\n throw new Rejected(`catalog.json ${field} must be a list`);\n return items as unknown[];\n };\n return {\n catalog: list('catalog'),\n evals: list('evals'),\n suites: list('suites'),\n };\n}\n\n/** The eval project's path in the repository; `''` at the root. */\nfunction projectPath(value: unknown): string {\n if (typeof value !== 'string')\n throw new Rejected('source.project must be a string');\n return value;\n}\n\nfunction parseJson(data: Uint8Array, name: string): unknown {\n try {\n return JSON.parse(new TextDecoder().decode(data));\n } catch {\n throw new Rejected(`${name} is not valid JSON`);\n }\n}\n\nfunction record(value: unknown, name: string): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value))\n throw new Rejected(`${name} must be an object`);\n return value as Record<string, unknown>;\n}\n\nfunction text(value: unknown, name: string): string {\n if (typeof value !== 'string' || !value)\n throw new Rejected(`${name} must be a non-empty string`);\n return value;\n}\n\nfunction optionalText<K extends string>(\n value: unknown,\n key: K,\n name: string,\n): Partial<Record<K, string>> {\n if (value === undefined || value === null || value === '') return {};\n return { [key]: text(value, name) } as Record<K, string>;\n}\n","import { Hono, type Context } from 'hono';\nimport { BundleError, decodeBundle } from './bundle.js';\nimport type { ShareFiles } from './files.js';\nimport { dashboardIndex } from './html.js';\nimport type { ShareIndex } from './index-db.js';\nimport { isSha, isUuid, safeSegment, validRepoKey } from './paths.js';\nimport {\n parseCatalog,\n parseRun,\n parseUpload,\n Rejected,\n type RunCatalog,\n type RunUpload,\n type SharedRun,\n} from './upload.js';\n\n/** The bundled dashboard: its index.html template and its JS/CSS files. */\nexport type DashboardAssets = {\n index(): Promise<string>;\n get(path: string): Promise<Response | null>;\n};\n\n/** One structured log event. Bounded fields only; never file contents. */\nexport type ShareEvent =\n | {\n event: 'share.upload';\n outcome: 'created' | 'exists';\n repo: string;\n commit: string;\n runId: string;\n files: number;\n bytes: number;\n }\n | { event: 'share.upload'; outcome: 'rejected'; reason: string }\n | { event: 'share.reindex'; runs: number; indexed: number }\n | { event: 'share.error'; method: string; path: string; error: string };\n\nexport type ShareAppOptions = {\n files: ShareFiles;\n index: ShareIndex;\n assets: DashboardAssets;\n /** Uncompressed bundle limit; the compressed body must also fit a Worker request. */\n maxBundleBytes?: number;\n /** Defaults to one JSON line per event on stdout (Workers Logs indexes these). */\n log?: (event: ShareEvent) => void;\n};\n\n/** What a non-API path shows. */\ntype SharePage =\n | { kind: 'repositories' }\n | { kind: 'missing'; repo: string; ref?: string }\n | { kind: 'commit'; repo: string; sha: string };\n\nconst IMMUTABLE = 'public, max-age=31536000, immutable';\nconst NO_CACHE = { 'cache-control': 'no-cache' };\nconst RUN_FILE =\n /^repos\\/(.+)\\/commits\\/([0-9a-f]{40})\\/runs\\/([^/]+)\\/run\\.json$/;\nconst EMPTY_CATALOG: RunCatalog = { catalog: [], evals: [], suites: [] };\n\nconst jsonLine = (event: ShareEvent) => console.log(JSON.stringify(event));\n\n/**\n * The share server: a small JSON API plus the dashboard app. It stores\n * uploaded run bundles and shows one read-only snapshot per repository commit.\n *\n * POST /api/v1/uploads one run bundle\n * POST /api/v1/reindex rebuild the index from stored run.json files\n * GET /api/v1/repos indexed repositories\n * GET /api/v1/repos/<repo>/-/commits commits, newest first\n * GET /api/v1/repos/<repo>/-/<sha>/data/… snapshot data\n * GET /assets/* dashboard JS/CSS\n * GET /<repo> → latest commit\n * GET /<repo>/-/<ref|prefix>/… → full SHA\n * GET everything else the dashboard app\n *\n * There is no authentication: run it on a private network.\n */\nexport function createShareApp(options: ShareAppOptions) {\n const { files, index, assets } = options;\n const log = options.log ?? jsonLine;\n const maxBundleBytes = options.maxBundleBytes ?? 256 * 1024 * 1024;\n const app = new Hono();\n\n app.onError((error, context) => {\n log({\n event: 'share.error',\n method: context.req.method,\n path: context.req.path,\n error: error instanceof Error ? error.message : String(error),\n });\n return context.json({ error: 'Internal error' }, 500);\n });\n\n app.post('/api/v1/uploads', async (context) => {\n let upload: RunUpload;\n try {\n const body = new Uint8Array(await context.req.arrayBuffer());\n upload = parseUpload(\n await decodeBundle(body, { maxBytes: maxBundleBytes }),\n );\n } catch (error) {\n if (!(error instanceof BundleError || error instanceof Rejected))\n throw error;\n log({\n event: 'share.upload',\n outcome: 'rejected',\n reason: error.message,\n });\n return context.json({ error: error.message }, 400);\n }\n const { run } = upload;\n const url = new URL(\n `/${run.repoKey}/-/${run.source.commit}/runs/${run.id}`,\n context.req.url,\n ).href;\n const exists = await index.hasRun(run.id);\n if (!exists) await storeRun(upload);\n const outcome = exists ? 'exists' : 'created';\n log({\n event: 'share.upload',\n outcome,\n repo: run.repoKey,\n commit: run.source.commit,\n runId: run.id,\n files: upload.files.length,\n bytes: upload.files.reduce((sum, file) => sum + file.data.byteLength, 0),\n });\n return context.json(\n { status: outcome, url },\n outcome === 'created' ? 201 : 200,\n );\n });\n\n /** Files first, index last: a run becomes visible only once it is indexed. */\n async function storeRun({\n run,\n runJson,\n catalog,\n files: runFiles,\n }: RunUpload) {\n const commitBase = `repos/${run.repoKey}/commits/${run.source.commit}`;\n const runBase = `${commitBase}/runs/${run.id}`;\n for (const file of runFiles)\n await files.put(`${runBase}/${file.path}`, file.data);\n // A committed run's catalog describes the commit; a dirty run's only fills a gap.\n if (\n catalog &&\n (!run.source.dirty || !(await files.get(`${commitBase}/catalog.json`)))\n )\n await files.put(`${commitBase}/catalog.json`, catalog);\n await files.put(`${runBase}/run.json`, runJson);\n await index.recordRun(run);\n }\n\n app.post('/api/v1/reindex', async (context) => {\n let runs = 0;\n let indexed = 0;\n for await (const key of files.list('repos/')) {\n if (!RUN_FILE.test(key)) continue;\n runs += 1;\n const run = storedRun(await readBytes(await files.get(key)));\n if (!run || (await index.hasRun(run.id))) continue;\n await index.recordRun(run);\n indexed += 1;\n }\n log({ event: 'share.reindex', runs, indexed });\n return context.json({ runs, indexed });\n });\n\n app.get('/api/v1/repos', async (context) =>\n context.json({ repos: await index.repos() }, 200, NO_CACHE),\n );\n\n // /api/v1/repos/<repo>/-/commits and /api/v1/repos/<repo>/-/<sha>/data/…\n app.get('/api/v1/repos/*', async (context) => {\n const path = context.req.path.slice('/api/v1/repos/'.length);\n const marker = path.indexOf('/-/');\n const key = marker === -1 ? '' : path.slice(0, marker);\n if (!validRepoKey(key))\n return context.json({ error: 'Unknown repository' }, 404);\n const [sha = '', kind, ...segments] = path.slice(marker + 3).split('/');\n if (sha === 'commits' && kind === undefined)\n return context.json(\n { repo: key, commits: await index.commits(key) },\n 200,\n NO_CACHE,\n );\n if (!isSha(sha) || kind !== 'data')\n return context.json({ error: 'Not found' }, 404);\n return serveData(context, key, sha, segments.map(decodeURIComponent));\n });\n\n // The bundled dashboard's JS/CSS. A Worker serves these as static assets\n // before this app runs; the Bun server serves them here.\n app.get('/assets/*', async (context) => {\n const path = context.req.path.slice('/assets/'.length);\n if (!path.split('/').every(safeSegment)) return context.notFound();\n const response = await assets.get(path);\n if (!response) return context.notFound();\n const headers = new Headers(response.headers);\n headers.set('cache-control', IMMUTABLE);\n return new Response(response.body, { status: response.status, headers });\n });\n\n app.all('/api/*', (context) => context.json({ error: 'Not found' }, 404));\n\n // Every other path is the dashboard app. Short refs resolve to full SHAs\n // first, so every commit page URL names one immutable commit.\n app.get('*', async (context) => {\n const url = new URL(context.req.url);\n const path = url.pathname.replace(/\\/+$/, '');\n const marker = path.indexOf('/-/');\n if (marker === -1) return repositoryPage(context, path.slice(1));\n const repo = path.slice(1, marker);\n const [ref = '', ...rest] = url.pathname.slice(marker + 3).split('/');\n const sha = validRepoKey(repo)\n ? await index.resolve(repo, decodeURIComponent(ref))\n : undefined;\n if (!sha) return dashboardPage(context, { kind: 'missing', repo, ref });\n if (sha !== ref)\n return context.redirect(\n `/${repo}/-/${sha}/${rest.join('/')}${url.search}`,\n );\n return dashboardPage(context, { kind: 'commit', repo, sha });\n });\n\n /** `/` lists repositories; `/<repo>` opens its latest commit. */\n async function repositoryPage(context: Context, repo: string) {\n if (!repo) return dashboardPage(context, { kind: 'repositories' });\n const latest = validRepoKey(repo) ? await index.latest(repo) : undefined;\n if (latest) return context.redirect(`/${repo}/-/${latest}/`);\n return dashboardPage(context, { kind: 'missing', repo });\n }\n\n /** The dashboard's index.html, told where this page's data lives. */\n async function dashboardPage(context: Context, page: SharePage) {\n const api =\n page.kind === 'repositories'\n ? undefined\n : `/api/v1/repos/${page.repo}/-/`;\n return context.html(\n dashboardIndex(await assets.index(), {\n base: page.kind === 'commit' ? `/${page.repo}/-/${page.sha}/` : '/',\n assets: '/assets/',\n share: {\n repos: '/api/v1/repos',\n ...(page.kind === 'repositories'\n ? {}\n : { repo: page.repo, commits: `${api}commits` }),\n ...(page.kind === 'commit' ? { data: `${api}${page.sha}/` } : {}),\n ...(page.kind === 'missing' && page.ref ? { missing: page.ref } : {}),\n },\n }),\n page.kind === 'missing' ? 404 : 200,\n NO_CACHE,\n );\n }\n\n async function serveData(\n context: Context,\n key: string,\n sha: string,\n segments: string[],\n ) {\n if (!segments.every(safeSegment)) return context.notFound();\n const path = segments.join('/');\n const commitBase = `repos/${key}/commits/${sha}`;\n if (path === 'runs.json')\n return context.json({ runs: await index.runs(key, sha) }, 200, NO_CACHE); // grows as runs are uploaded\n if (['catalog.json', 'evals.json', 'suites.json'].includes(path)) {\n // Parsed at upload, so a stored catalog is always well formed.\n const data = await readBytes(\n await files.get(`${commitBase}/catalog.json`),\n );\n const catalog = data ? parseCatalog(data) : EMPTY_CATALOG;\n return context.json(\n path === 'catalog.json'\n ? { evals: catalog.catalog }\n : path === 'evals.json'\n ? { evals: catalog.evals }\n : { suites: catalog.suites },\n 200,\n NO_CACHE,\n );\n }\n const runFile = /^runs\\/([^/]+)\\/(trials\\.json|trials\\/.+)$/.exec(path);\n if (!runFile || !isUuid(runFile[1]!)) return context.notFound();\n const body = await files.get(`${commitBase}/${path}`);\n if (!body) return context.notFound();\n const json = path.endsWith('.json') && !path.includes('/workspace/');\n return new Response(body as BodyInit, {\n headers: json\n ? { 'content-type': 'application/json', 'cache-control': IMMUTABLE }\n : {\n // Candidate files are untrusted content on this origin: never render them.\n 'content-type': 'application/octet-stream',\n 'x-content-type-options': 'nosniff',\n 'content-security-policy': 'sandbox',\n 'cache-control': IMMUTABLE,\n },\n });\n }\n\n return app;\n}\n\n/** A stored run.json, or undefined if it is not a shareable run. */\nfunction storedRun(data: Uint8Array | null): SharedRun | undefined {\n if (!data) return undefined;\n try {\n return parseRun(data);\n } catch (error) {\n if (error instanceof Rejected) return undefined;\n throw error;\n }\n}\n\nasync function readBytes(\n body: ReadableStream<Uint8Array> | Uint8Array | null,\n): Promise<Uint8Array | null> {\n if (!body) return null;\n if (body instanceof Uint8Array) return body;\n return new Uint8Array(await new Response(body).arrayBuffer());\n}\n","import type { SharedRun } from './upload.js';\n\n/**\n * The share server's metadata index: repositories, commits and runs.\n * R2 (or a directory) holds the files; this index answers \"what exists\" and\n * every listing query. It is derived from stored run.json files and can be\n * rebuilt from them (`POST /api/v1/reindex`).\n */\n\n/** Synchronous SQLite access, provided by Durable Object storage or bun:sqlite. */\nexport type Sql = {\n all<T>(query: string, ...params: SqlValue[]): T[];\n run(query: string, ...params: SqlValue[]): void;\n transaction<T>(work: () => T): T;\n};\nexport type SqlValue = string | number | null;\n\nexport type RepoRow = {\n key: string;\n url: string;\n project: string;\n firstSeenAt: string;\n lastUploadAt: string;\n commits: number;\n};\n\nexport type CommitRow = {\n commit: string;\n ref?: string;\n committedAt?: string;\n firstSeenAt: string;\n runs: number;\n passed: number;\n failed: number;\n};\n\n/** The operations the app needs; async so a Durable Object can sit behind it. */\nexport type ShareIndex = {\n hasRun(runId: string): Promise<boolean>;\n recordRun(run: SharedRun): Promise<void>;\n repos(): Promise<RepoRow[]>;\n commits(repo: string): Promise<CommitRow[]>;\n runs(repo: string, sha: string): Promise<unknown[]>;\n /** Full SHA for a full SHA, a unique prefix (≥ 7), or a ref's latest commit. */\n resolve(repo: string, ref: string): Promise<string | undefined>;\n latest(repo: string): Promise<string | undefined>;\n};\n\nconst MIGRATIONS = [\n `CREATE TABLE IF NOT EXISTS repos (\n key TEXT PRIMARY KEY,\n url TEXT NOT NULL,\n project TEXT NOT NULL,\n first_seen_at TEXT NOT NULL,\n last_upload_at TEXT NOT NULL\n )`,\n `CREATE TABLE IF NOT EXISTS commits (\n repo TEXT NOT NULL,\n sha TEXT NOT NULL,\n ref TEXT,\n committed_at TEXT,\n first_seen_at TEXT NOT NULL,\n runs INTEGER NOT NULL DEFAULT 0,\n passed INTEGER NOT NULL DEFAULT 0,\n failed INTEGER NOT NULL DEFAULT 0,\n PRIMARY KEY (repo, sha)\n )`,\n `CREATE TABLE IF NOT EXISTS runs (\n id TEXT PRIMARY KEY,\n repo TEXT NOT NULL,\n sha TEXT NOT NULL,\n eval_id TEXT NOT NULL,\n suite_id TEXT,\n status TEXT NOT NULL,\n score REAL,\n started_at TEXT NOT NULL,\n dirty INTEGER NOT NULL,\n summary_json TEXT NOT NULL,\n uploaded_at TEXT NOT NULL\n )`,\n `CREATE INDEX IF NOT EXISTS commits_by_time ON commits (repo, committed_at DESC)`,\n `CREATE INDEX IF NOT EXISTS commits_by_ref ON commits (repo, ref, committed_at DESC)`,\n `CREATE INDEX IF NOT EXISTS runs_by_commit ON runs (repo, sha)`,\n `CREATE INDEX IF NOT EXISTS runs_by_eval ON runs (repo, eval_id, started_at)`,\n];\n\n/** Newest first; commits without a commit time order by first upload. */\nconst BY_TIME = `ORDER BY COALESCE(committed_at, first_seen_at) DESC, first_seen_at DESC`;\n\nexport class ShareIndexDb {\n constructor(\n private readonly sql: Sql,\n private readonly now: () => Date = () => new Date(),\n ) {\n for (const statement of MIGRATIONS) sql.run(statement);\n }\n\n hasRun(runId: string): boolean {\n return this.sql.all('SELECT 1 FROM runs WHERE id = ?', runId).length > 0;\n }\n\n /** Idempotent: recording an indexed run again changes nothing. */\n recordRun(run: SharedRun): void {\n const at = this.now().toISOString();\n this.sql.transaction(() => {\n if (this.hasRun(run.id)) return;\n this.sql.run(\n `INSERT INTO repos (key, url, project, first_seen_at, last_upload_at)\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT (key) DO UPDATE SET last_upload_at = excluded.last_upload_at`,\n run.repoKey,\n run.source.repo,\n run.source.project,\n at,\n at,\n );\n this.sql.run(\n `INSERT INTO commits (repo, sha, ref, committed_at, first_seen_at)\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT (repo, sha) DO UPDATE SET\n ref = COALESCE(commits.ref, excluded.ref),\n committed_at = COALESCE(commits.committed_at, excluded.committed_at)`,\n run.repoKey,\n run.source.commit,\n run.source.ref ?? null,\n run.source.committedAt ?? null,\n at,\n );\n this.sql.run(\n `INSERT INTO runs (id, repo, sha, eval_id, suite_id, status, score,\n started_at, dirty, summary_json, uploaded_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n run.id,\n run.repoKey,\n run.source.commit,\n run.evalId,\n run.suiteId ?? null,\n run.status,\n run.score ?? null,\n run.startedAt,\n run.source.dirty ? 1 : 0,\n JSON.stringify(run.summary),\n at,\n );\n // Dirty runs are shown but never count towards a commit's results.\n if (!run.source.dirty)\n this.sql.run(\n `UPDATE commits SET runs = runs + 1,\n passed = passed + ?, failed = failed + ?\n WHERE repo = ? AND sha = ?`,\n run.status === 'passed' ? 1 : 0,\n run.status === 'failed' || run.status === 'errored' ? 1 : 0,\n run.repoKey,\n run.source.commit,\n );\n });\n }\n\n repos(): RepoRow[] {\n return this.sql.all<RepoRow>(\n `SELECT key, url, project, first_seen_at AS firstSeenAt,\n last_upload_at AS lastUploadAt,\n (SELECT COUNT(*) FROM commits WHERE commits.repo = repos.key) AS commits\n FROM repos ORDER BY last_upload_at DESC`,\n );\n }\n\n commits(repo: string): CommitRow[] {\n return this.sql\n .all<CommitRow & { ref: string | null; committedAt: string | null }>(\n `SELECT sha AS \"commit\", ref, committed_at AS committedAt,\n first_seen_at AS firstSeenAt, runs, passed, failed\n FROM commits WHERE repo = ? ${BY_TIME}`,\n repo,\n )\n .map(({ ref, committedAt, ...row }) => ({\n ...row,\n ...(ref ? { ref } : {}),\n ...(committedAt ? { committedAt } : {}),\n }));\n }\n\n runs(repo: string, sha: string): unknown[] {\n return this.sql\n .all<{ summary_json: string }>(\n 'SELECT summary_json FROM runs WHERE repo = ? AND sha = ? ORDER BY started_at DESC',\n repo,\n sha,\n )\n .map((row) => JSON.parse(row.summary_json) as unknown);\n }\n\n resolve(repo: string, ref: string): string | undefined {\n if (/^[0-9a-f]{7,40}$/.test(ref)) {\n const matches = this.sql.all<{ sha: string }>(\n 'SELECT sha FROM commits WHERE repo = ? AND sha LIKE ? LIMIT 2',\n repo,\n `${ref}%`,\n );\n if (matches.length === 1) return matches[0]!.sha;\n if (matches.length > 1) return undefined; // ambiguous prefix\n }\n return this.sql.all<{ sha: string }>(\n `SELECT sha FROM commits WHERE repo = ? AND ref = ? ${BY_TIME} LIMIT 1`,\n repo,\n ref,\n )[0]?.sha;\n }\n\n latest(repo: string): string | undefined {\n return this.sql.all<{ sha: string }>(\n `SELECT sha FROM commits WHERE repo = ? ${BY_TIME} LIMIT 1`,\n repo,\n )[0]?.sha;\n }\n}\n\n/** Adapt the synchronous index (bun:sqlite) to the app's async interface. */\nexport function asyncIndex(db: ShareIndexDb): ShareIndex {\n return {\n hasRun: async (runId) => db.hasRun(runId),\n recordRun: async (run) => db.recordRun(run),\n repos: async () => db.repos(),\n commits: async (repo) => db.commits(repo),\n runs: async (repo, sha) => db.runs(repo, sha),\n resolve: async (repo, ref) => db.resolve(repo, ref),\n latest: async (repo) => db.latest(repo),\n };\n}\n"],"mappings":"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"}
|