import { DurableObject } from "cloudflare:workers";
import { LogSubscribers } from "./log-stream";
import { ensureRunnerContainer, INTERNAL_API_URL } from "../containers/ready";
import { authenticatedRemote } from "../git/artifacts";
import { completeJob, loadJobExecution, markJobStarted, resolveSecrets, mintJobCloneToken, updateStep } from "./jobs";
import { buildJobScript, jobTimeoutCommand, MARKER_NONCE_FILE } from "./script";
import { addMaskValue, declaredNames, parseMarker, withOutput } from "./markers";
import { JobMasks, splitLogChunk } from "./job-masks";
import { stepSecretNames } from "./compile";
import { recordJobArtifact, saveJobOutputs } from "./job-records";
import { jobTokenEnv, mintJobToken } from "./job-token";
import { randomId } from "../crypto";
import type { Conclusion } from "~/lib/types";
import { PURGE_DELAY_MS } from "./runner-meta";
import type { JobMeta, LogRow } from "./runner-meta";
const POLL_INTERVAL_MS = 1500;
const READ_CHUNK_BYTES = 256 * 1024;
const TOKEN_GRACE_SECONDS = 600;
const SETUP_STEP = -1;
const WORKSPACE = "/workspace";
const SCRIPT_PATH = `${WORKSPACE}/.gitfor-job.sh`;
const LOG_PATH = `${WORKSPACE}/.gitfor-job.log`;
const EXIT_PATH = `${WORKSPACE}/.gitfor-job.exit`;
const GIT_TASK_TIMEOUT_SECONDS = 900;
const GIT_TASK_IDLE_MS = 5 * 60 * 1000;
const MAX_LOG_BYTES = 20 * 1024 * 1024;
const MAX_LINE_CHARS = 16 * 1024;
const LOG_BYTES_KEY = "logBytes";
const MAX_CLOUD_ARTIFACTS = 20;
const MAX_CLOUD_ARTIFACT_BYTES = 1024 * 1024 * 1024;
const ARTIFACT_DIR = `${WORKSPACE}/.gitfor/artifacts`;
async function readAll(stream: ReadableStream | null): Promise<string> {
return stream ? new Response(stream).text() : "";
}
export class Runner extends DurableObject<Env> {
private readonly masks = new JobMasks(this.ctx.storage);
private readonly streams = new LogSubscribers();