Something went wrong. Try again.
A local-first event pipeline for independent agents, built on Jazz.
Something went wrong. Try again.
4.0 kB · 98 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899import { MAX_EVIDENCE_IDS, type WorkbenchContextSnapshot } from "./contracts.js";
/** * Workbench proposal runner seam. * * A runner receives the exact head version of one working document plus the * operator's exact context snapshot and returns one full replacement body. * The trusted workflow (`workflow.ts`) owns every durable effect: it appends * the requested event, runs the runner, records the run row, appends the * proposal event, and later applies a human decision. A runner never touches * Jazz, the filesystem, or the network on its own. * * Coordination point with the separate fx consumer work: an fx-backed runner * would implement this same interface, map the harness result frame's * `finalText` to `proposedText`, map its run id to `proposer.runId`, and * report the harness's own reason string. That adapter is not implemented * here and nothing in this module imports from `src/agents/harness/`; the * request/result shapes below are the contract the two sides share. */
export interface WorkbenchProposalRequest { documentId: string; baseVersionId: string; baseSha256: string; title: string; baseText: string; snapshot: WorkbenchContextSnapshot; maxProposedChars: number;}
export interface WorkbenchProposalResult { proposedText: string; reason: string; evidenceEventIds: string[];}
export interface WorkbenchProposalRunner { id: string; revision: string; /** Plain-language label shown next to the request control. */ label: string; /** Whether the runner performs LLM inference. The fixture runner does not. */ inference: "none" | "model"; propose(request: WorkbenchProposalRequest): Promise<WorkbenchProposalResult>;}
export const FIXTURE_RUNNER_ID = "fixture-deterministic";export const FIXTURE_RUNNER_REVISION = "1";
const SOURCES_HEADING = "## Sources";
/** * Deterministic fixture runner. It appends (or replaces) a `## Sources` * section listing each selected event and version, plus a one-line * `Summary:` paragraph counting the sources. Identical input yields identical * output; no inference occurs. */export const fixtureDeterministicRunner: WorkbenchProposalRunner = { id: FIXTURE_RUNNER_ID, revision: FIXTURE_RUNNER_REVISION, label: "Deterministic fixture (no inference)", inference: "none", async propose(request) { const lines: string[] = [SOURCES_HEADING, ""]; for (const event of request.snapshot.selectedEvents) { const excerpt = event.excerpt.replace(/\s+/g, " ").trim().slice(0, 120); lines.push(`- ${event.type} ${event.eventId.slice(0, 16)} — ${excerpt}`); } for (const version of request.snapshot.selectedVersions) { lines.push(`- version ${version.versionId.slice(0, 24)} (${version.sha256.slice(0, 12)})`); } const count = request.snapshot.selectedEvents.length + request.snapshot.selectedVersions.length; lines.push("", `Summary: this document cites ${count} selected source${count === 1 ? "" : "s"}.`); const base = stripSourcesSection(request.baseText).replace(/\s+$/, ""); const proposedText = `${base}${base ? "\n\n" : ""}${lines.join("\n")}\n`; if (proposedText.length > request.maxProposedChars) { throw new Error("Fixture runner output exceeds the proposal character bound"); } return { proposedText, reason: "fixture: append sources section", evidenceEventIds: request.snapshot.selectedEvents.map((event) => event.eventId).slice(0, MAX_EVIDENCE_IDS), }; },};
function stripSourcesSection(text: string): string { const index = text.indexOf(`\n${SOURCES_HEADING}`); if (text.startsWith(SOURCES_HEADING)) return ""; if (index === -1) return text; return text.slice(0, index);}
export type WorkbenchRunnerRegistry = ReadonlyMap<string, WorkbenchProposalRunner>;
export function createDefaultWorkbenchRunnerRegistry(): WorkbenchRunnerRegistry { return new Map([[fixtureDeterministicRunner.id, fixtureDeterministicRunner]]);}