flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/apps/web/app/lib/artifacts.server.ts

34 lines1,330 bytesCodeBlame
1import { env } from "cloudflare:workers";
2
3/**
4 * A run's artifacts, as the API keeps them in KV: a metadata key per
5 * artifact, `a/{run}/{name}`, and its bytes in chunks, `…#0`, `…#1`.
6 */
7export type ArtifactMeta = { name: string; size: number; at: number };
8
9type Meta = { size: number; chunks: number; at: number; name: string };
10
11export async function listArtifacts(run: string): Promise<ArtifactMeta[]> {
12 const listed = await env.BLOBS.list<Meta>({ prefix: `a/${run}/` });
13 return listed.keys
14 .filter((key) => !key.name.includes("#") && key.metadata)
15 .map((key) => ({ name: key.metadata!.name, size: key.metadata!.size, at: key.metadata!.at }))
16 .sort((a, b) => a.name.localeCompare(b.name));
17}
18
19export async function readArtifact(run: string, name: string): Promise<Uint8Array | null> {
20 const base = `a/${run}/${name}`;
21 const meta = await env.BLOBS.get<Meta>(base, "json");
22 if (!meta) return null;
23 const parts = await Promise.all(
24 Array.from({ length: meta.chunks }, (_, index) => env.BLOBS.get(`${base}#${index}`, "arrayBuffer")),
25 );
26 if (parts.some((part) => part == null)) return null;
27 const out = new Uint8Array(meta.size);
28 let offset = 0;
29 for (const part of parts as ArrayBuffer[]) {
30 out.set(new Uint8Array(part), offset);
31 offset += part.byteLength;
32 }
33 return out;
34}