Something went wrong. Try again.
A collaborative coding-agent orchestrator for atproto radl.app
Something went wrong. Try again.
TypeScript
12345678910111213141516171819202122232425262728293031323334353637383940414243444546import type { ReviewFinding, StrongRef } from './generated/records.js'
export interface SubmitArtifactRpc { method: 'submitArtifact'; token: string; title: string; body: string; criteria?: string[]; branch?: string; commit?: string; pr?: string }export interface AskQuestionRpc { method: 'askQuestion'; token: string; body: string }/** A review turn's terminal RPC. No `body` field — a ReviewRecord has none; the verdict plus * structured findings are the whole payload. The daemon owns `subject` and `request` (from turn * context), so they are deliberately absent from the wire envelope. */export interface SubmitReviewRpc { method: 'submitReview'; token: string; verdict: 'approve' | 'request_changes'; findings: ReviewFinding[] }/** An answer turn's terminal RPC: the body of the reply, and nothing else. The daemon owns every * anchoring field — goal, `parent`/`root`, the `re` backref, the mention of whoever is being replied * to — from turn context, so a turn can only reply to the message its request named. */export interface SubmitAnswerRpc { method: 'submitAnswer'; token: string; body: string }export type TurnRpcRequest = SubmitArtifactRpc | AskQuestionRpc | SubmitReviewRpc | SubmitAnswerRpcexport type TurnRpcResponse = { ok: true; ref: StrongRef } | { ok: false; error: string }export const TURN_LIMITS = { artifactBodyChars: 100_000, /** `com.disnetdev.radial.artifact`'s `title` ceiling. A record over it is one every materializer * would drop, so both writers refuse it rather than write it — see `normalizeArtifactTitle`. */ artifactTitleChars: 200, messageBodyChars: 30_000, // The review lexicon caps findings at 100 entries × 10,000-char bodies (~1MB of body text alone, // more once JSON-encoded with per-finding path/line/severity). 2MB comfortably covers the largest // valid review payload; the per-field character limits above still bound artifact/message bodies. maxFrameBytes: 2_000_000, frameTimeoutMs: 30_000,} as const
/** * An artifact's `title` as it will be STORED, or `undefined` when the value cannot be stored. * * `title` is optional in the lexicon — records signed before the field existed cannot be rewritten, * and a required field would put every one of them in `index.ignored` — but a writer that has the * field must not produce a blank or over-long one. So the normalization lives here, shared by both * writers (the sidecar's direct `artifact post` and the daemon's turn socket), and each surfaces its * own error for the `undefined`: they have very different audiences, but there is only one rule about * what a title is. * * Whitespace is trimmed before the ceiling is applied, because trimmed is what gets written. */export function normalizeArtifactTitle(value: unknown): string | undefined { if (typeof value !== 'string') return undefined const title = value.trim() if (title === '' || title.length > TURN_LIMITS.artifactTitleChars) return undefined return title}