byollm 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +118 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +8 -0
- package/dist/bin.js.map +1 -0
- package/dist/chunk-S5WHDSUF.js +2358 -0
- package/dist/chunk-S5WHDSUF.js.map +1 -0
- package/dist/index.d.ts +913 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/allowlist.ts","../src/cli.ts","../src/budgets.ts","../src/client.ts","../src/config.ts","../src/ssrf.ts","../src/connect.ts","../src/ingress.ts","../src/pairings.ts","../src/paths.ts","../src/runner.ts","../src/backends/index.ts","../src/backends/claude-cli.ts","../src/backends/openai-http.ts","../src/compose.ts","../src/index.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { z } from \"zod\";\n\n/**\n * One person, on one server, allowed to run work on this machine.\n *\n * Keyed by **(server origin, user id)** because owner ids are\n * server-namespace-local: `alice` on one app is not `alice` on another, and a\n * list keyed by id alone would silently merge strangers.\n */\nexport const AllowEntry = z\n .object({\n /** Origin of the server that issued the id, e.g. `https://app.example.com`. */\n origin: z.string().min(1),\n /** The app's id for the user. */\n owner: z.string().min(1),\n /** Optional human label, so the list is readable a month later. */\n note: z.string().optional(),\n addedAt: z.number().int().positive(),\n })\n .strict();\nexport type AllowEntry = z.infer<typeof AllowEntry>;\n\nconst AllowFile = z\n .object({\n version: z.literal(1),\n entries: z.array(AllowEntry),\n })\n .strict();\n\n/**\n * The daemon's local `named` allowlist.\n *\n * byollm_001 Rev 1 §B: a `named` job is admitted only when *this* list names\n * its owner. A server's assertion that a runner is allowed is never enough —\n * honouring it would mean obeying the server rather than enforcing against\n * it. One file, every paired app, so the owner has one place to see everyone\n * who can use their machine.\n *\n * The list is **empty by default**, which is what makes a fresh daemon\n * effectively self-only until the owner deliberately widens it.\n */\nexport class Allowlist {\n readonly #path: string;\n #entries: AllowEntry[] = [];\n #loaded = false;\n\n constructor(path: string) {\n this.#path = path;\n }\n\n async load(): Promise<void> {\n try {\n const raw = await readFile(this.#path, \"utf8\");\n const parsed = AllowFile.safeParse(JSON.parse(raw));\n // A corrupt allowlist reads as empty rather than throwing: failing\n // closed here means refusing community work, which is the safe\n // direction, and the owner sees an empty `byollm allow --list`.\n this.#entries = parsed.success ? parsed.data.entries : [];\n } catch {\n this.#entries = [];\n }\n this.#loaded = true;\n }\n\n #assertLoaded(): void {\n if (!this.#loaded) {\n throw new Error(\"allowlist used before load()\");\n }\n }\n\n /** Does this list admit `owner` on `origin`? */\n admits(origin: string, owner: string): boolean {\n this.#assertLoaded();\n const normalized = normalizeOrigin(origin);\n return this.#entries.some(\n (entry) =>\n normalizeOrigin(entry.origin) === normalized && entry.owner === owner,\n );\n }\n\n /** A predicate bound to one origin, for {@link matchAudience}. */\n predicateFor(origin: string): (owner: string) => boolean {\n return (owner) => this.admits(origin, owner);\n }\n\n list(): readonly AllowEntry[] {\n this.#assertLoaded();\n return [...this.#entries];\n }\n\n async add(entry: Omit<AllowEntry, \"addedAt\">, now: number): Promise<void> {\n this.#assertLoaded();\n const normalized = normalizeOrigin(entry.origin);\n if (this.admits(normalized, entry.owner)) return;\n this.#entries.push(\n AllowEntry.parse({ ...entry, origin: normalized, addedAt: now }),\n );\n await this.#save();\n }\n\n /** Remove an entry. Returns whether anything was removed. */\n async remove(origin: string, owner: string): Promise<boolean> {\n this.#assertLoaded();\n const normalized = normalizeOrigin(origin);\n const before = this.#entries.length;\n this.#entries = this.#entries.filter(\n (entry) =>\n !(\n normalizeOrigin(entry.origin) === normalized && entry.owner === owner\n ),\n );\n if (this.#entries.length === before) return false;\n await this.#save();\n return true;\n }\n\n async #save(): Promise<void> {\n await mkdir(dirname(this.#path), { recursive: true });\n await writeFile(\n this.#path,\n `${JSON.stringify({ version: 1, entries: this.#entries }, null, 2)}\\n`,\n { mode: 0o600 },\n );\n }\n}\n\n/**\n * Compare origins by scheme, host and port only.\n *\n * `https://app.test/` and `https://app.test` must be the same entry — a\n * trailing slash is not a different server, and treating it as one would let\n * an allowlist silently fail to match.\n */\nexport function normalizeOrigin(input: string): string {\n try {\n return new URL(input).origin;\n } catch {\n return input.replace(/\\/+$/, \"\");\n }\n}\n","import { mkdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { hostname, userInfo } from \"node:os\";\nimport { createInterface } from \"node:readline/promises\";\nimport { Allowlist, normalizeOrigin } from \"./allowlist.js\";\nimport { Budgets } from \"./budgets.js\";\nimport { ClientError, ProtocolClient } from \"./client.js\";\nimport { loadConfig } from \"./config.js\";\nimport { connect } from \"./connect.js\";\nimport { IngressLog, stripControlChars } from \"./ingress.js\";\nimport { Pairings } from \"./pairings.js\";\nimport { daemonPaths, type DaemonPaths } from \"./paths.js\";\nimport { Runner, type RunnerEvent } from \"./runner.js\";\nimport { DAEMON_VERSION } from \"./index.js\";\n\nconst USAGE = `byollm — run an app's LLM jobs on your own models.\n\n byollm connect <url> pair with an app and start running its jobs\n byollm run [url] run jobs for a paired app (or all of them)\n byollm status what is connected, what is running, what it cost\n byollm log [--full] [-n N] every prompt that has run on this machine\n byollm pause stop claiming new work\n byollm resume start claiming again\n byollm allow <url> <user> let someone else's jobs run here (named audience)\n byollm allow --list who can currently use this machine\n byollm disallow <url> <user>\n byollm forget <url> drop a pairing\n byollm backends what is installed, healthy, and advertised\n\nConfig lives in ~/.byollm/config.json. Everything this daemon has ever run is\nin ~/.byollm/ingress.log — it is yours to read and yours to delete.\n`;\n\n/** Exit codes: 0 fine, 1 a real failure, 2 the user asked for something wrong. */\nexport type ExitCode = 0 | 1 | 2;\n\n/**\n * Everything the CLI touches outside itself.\n *\n * byollm_002 calls the meter the product's soul, which means it has to be\n * testable rather than merely observable by a human at a terminal. Injecting\n * the streams, the state directory and the confirmation prompt lets the tests\n * drive the real commands against a temporary `BYOLLM_HOME`.\n */\nexport interface CliIo {\n readonly out: (text: string) => void;\n readonly err: (text: string) => void;\n /** Answers the scarier-confirmation prompt when widening access. */\n readonly confirm: (question: string) => Promise<boolean>;\n}\n\nconst defaultIo: CliIo = {\n out: (text) => process.stdout.write(text),\n err: (text) => process.stderr.write(text),\n confirm: confirmInteractively,\n};\n\n/** Run one command. Exported so the tests drive the same code a user does. */\nexport async function runCli(\n argv: readonly string[],\n options: {\n paths?: DaemonPaths;\n io?: Partial<CliIo>;\n /**\n * Stops the polling loop. The executable wires this to SIGINT/SIGTERM;\n * anything embedding the CLI (including its tests) can stop it the same\n * way rather than by killing the process.\n */\n signal?: AbortSignal;\n } = {},\n): Promise<ExitCode> {\n const [command, ...rest] = argv;\n const paths = options.paths ?? daemonPaths();\n const io: CliIo = { ...defaultIo, ...options.io };\n const signal = options.signal;\n\n switch (command) {\n case undefined:\n case \"help\":\n case \"--help\":\n case \"-h\":\n io.out(USAGE);\n return 0;\n case \"--version\":\n case \"version\":\n io.out(`${DAEMON_VERSION}\\n`);\n return 0;\n case \"connect\":\n return commandConnect(paths, rest, io, signal);\n case \"run\":\n return commandRun(paths, rest, io, signal);\n case \"status\":\n return commandStatus(paths, io);\n case \"log\":\n return commandLog(paths, rest, io);\n case \"pause\":\n return commandPause(paths, true, io);\n case \"resume\":\n return commandPause(paths, false, io);\n case \"allow\":\n return commandAllow(paths, rest, io);\n case \"disallow\":\n return commandDisallow(paths, rest, io);\n case \"forget\":\n return commandForget(paths, rest, io);\n case \"backends\":\n return commandBackends(paths, io);\n default:\n io.err(`unknown command: ${command}\\n\\n${USAGE}`);\n return 2;\n }\n}\n\n// -- connect -----------------------------------------------------------------\n\nasync function commandConnect(\n paths: DaemonPaths,\n args: readonly string[],\n io: CliIo,\n signal?: AbortSignal,\n): Promise<ExitCode> {\n const target = args[0];\n if (target === undefined) {\n io.err(\"usage: byollm connect <url>\\n\");\n return 2;\n }\n\n const origin = normalizeOrigin(target);\n const { loaded, ingress, allowlist, budgets } = await context(paths);\n\n for (const problem of loaded.problems) {\n io.err(`config: ${problem.where}: ${problem.message}\\n`);\n }\n\n const client = new ProtocolClient({ origin });\n const runner = new Runner({\n client,\n runnerId: \"pending\",\n owner: \"pending\",\n daemonVersion: DAEMON_VERSION,\n loaded,\n allowlist,\n budgets,\n ingress,\n });\n\n const capabilities = await runner.detectCapabilities();\n if (capabilities.length === 0) {\n // Pairing while advertising nothing would produce a runner that silently\n // never receives work — a failure the user could not diagnose.\n io.err(\n \"No backend is reachable, so there is nothing to offer this app yet.\\n\" +\n \"Run `byollm backends` to see what is configured and what is wrong.\\n\",\n );\n return 1;\n }\n\n io.out(`\\nConnecting to ${origin}\\n`);\n\n const result = await connect({\n client,\n daemonVersion: DAEMON_VERSION,\n label: hostLabel(),\n capabilities,\n onCode: (info) => {\n const minutes = Math.max(\n 1,\n Math.round((info.expiresAt - Date.now()) / 60_000),\n );\n io.out(\n `\\n Open: ${info.verificationUrl}\\n` +\n ` Code: ${info.userCode} (expires in ${String(minutes)}m)\\n\\n` +\n ` waiting for approval…`,\n );\n },\n onPoll: () => {\n io.out(\".\");\n },\n ...(signal === undefined ? {} : { signal }),\n });\n\n if (!result.ok) {\n io.out(`\\n\\n ${result.message}\\n`);\n return 1;\n }\n\n const pairings = new Pairings(paths.pairings);\n await pairings.load();\n await pairings.put(result.pairing);\n\n io.out(\n ` paired as ${result.pairing.ownerLabel ?? result.pairing.owner}\\n\\n` +\n `Now running jobs for ${origin}. Ctrl-C to stop.\\n\\n`,\n );\n\n return runLoop(paths, [result.pairing.origin], io, signal);\n}\n\n// -- run ---------------------------------------------------------------------\n\nasync function commandRun(\n paths: DaemonPaths,\n args: readonly string[],\n io: CliIo,\n signal?: AbortSignal,\n): Promise<ExitCode> {\n const pairings = new Pairings(paths.pairings);\n await pairings.load();\n\n const target = args[0];\n const origins =\n target === undefined\n ? pairings.list().map((pairing) => pairing.origin)\n : [normalizeOrigin(target)];\n\n if (origins.length === 0) {\n io.err(\"No apps are paired yet. Run `byollm connect <url>` first.\\n\");\n return 2;\n }\n return runLoop(paths, origins, io, signal);\n}\n\nasync function runLoop(\n paths: DaemonPaths,\n origins: readonly string[],\n io: CliIo,\n signal?: AbortSignal,\n): Promise<ExitCode> {\n const { loaded, ingress, allowlist, budgets } = await context(paths);\n const pairings = new Pairings(paths.pairings);\n await pairings.load();\n\n const controller = new AbortController();\n signal?.addEventListener(\n \"abort\",\n () => {\n controller.abort();\n },\n { once: true },\n );\n const runners: Runner[] = [];\n\n for (const origin of origins) {\n const pairing = pairings.get(origin);\n if (!pairing) {\n io.err(`not paired with ${origin}\\n`);\n continue;\n }\n const runner = new Runner({\n client: new ProtocolClient({ origin, token: pairing.token }),\n runnerId: pairing.runnerId,\n owner: pairing.owner,\n daemonVersion: DAEMON_VERSION,\n loaded,\n allowlist,\n budgets,\n ingress,\n onEvent: (event) => {\n report(origin, event, io);\n },\n });\n runners.push(runner);\n }\n\n if (runners.length === 0) return 2;\n\n // Leases are released on the way out, so the app sees work return to the\n // queue at once instead of waiting for a lease to lapse.\n // Only take over the process's signals when nobody handed us one of their\n // own — an embedder (or a test) that passed a signal owns its own lifecycle.\n if (signal === undefined) {\n const stop = (): void => {\n controller.abort();\n void Promise.all(\n runners.map((runner) => runner.shutdown(\"shutdown\")),\n ).then(() => process.exit(0));\n };\n process.on(\"SIGINT\", stop);\n process.on(\"SIGTERM\", stop);\n }\n\n await ingress.applyRetention(Date.now());\n await Promise.all(runners.map((runner) => runner.run(controller.signal)));\n await Promise.all(runners.map((runner) => runner.shutdown(\"shutdown\")));\n return 0;\n}\n\n/**\n * One line per event.\n *\n * Every interpolated string that could contain remote text goes through\n * {@link stripControlChars} first: a refusal reason or an error message may\n * quote a payload, and text that can repaint a terminal can forge output\n * (byollm_004 §5's ANSI/log-injection row).\n */\nfunction report(origin: string, event: RunnerEvent, io: CliIo): void {\n const at = new Date().toISOString().slice(11, 19);\n const host = new URL(origin).host;\n\n switch (event.type) {\n case \"claimed\":\n io.out(`${at} ${host} claimed ${event.kind} ${event.jobId}\\n`);\n break;\n case \"finished\":\n io.out(\n `${at} ${host} ${event.outcome} ${event.jobId} ` +\n `(${String(event.durationMs)}ms)\\n`,\n );\n break;\n case \"refused\":\n io.out(\n `${at} ${host} refused ${event.jobId}: ` +\n `${stripControlChars(event.reason)}\\n`,\n );\n break;\n case \"revoked\":\n io.out(`${at} ${host} this runner was revoked. Stopping.\\n`);\n break;\n case \"error\":\n io.err(`${at} ${host} ${stripControlChars(event.message)}\\n`);\n break;\n case \"heartbeat\":\n break;\n }\n}\n\n// -- status ------------------------------------------------------------------\n\nasync function commandStatus(paths: DaemonPaths, io: CliIo): Promise<ExitCode> {\n const { loaded, ingress, allowlist, budgets } = await context(paths);\n const pairings = new Pairings(paths.pairings);\n await pairings.load();\n\n const paused = await isPaused(paths);\n const now = Date.now();\n\n io.out(`byollm ${DAEMON_VERSION}\\n`);\n io.out(`state: ${paused ? \"PAUSED\" : \"running\"}\\n\\n`);\n\n io.out(\"paired apps\\n\");\n const list = pairings.list();\n if (list.length === 0) {\n io.out(\" (none — run `byollm connect <url>`)\\n\");\n }\n for (const pairing of list) {\n io.out(` ${pairing.origin} as ${pairing.ownerLabel ?? pairing.owner}\\n`);\n }\n\n io.out(\"\\nroutes\\n\");\n if (loaded.routes.length === 0) {\n io.out(\" (none configured)\\n\");\n }\n for (const route of loaded.routes) {\n io.out(\n ` ${route.kind.padEnd(14)} ${route.backendId}:${route.model} ` +\n `offered to: ${route.offerScope}\\n`,\n );\n }\n for (const problem of loaded.problems) {\n io.out(` ! ${problem.where}: ${problem.message}\\n`);\n }\n\n const allowed = allowlist.list();\n io.out(\"\\nwho can use this machine\\n\");\n io.out(` you, always\\n`);\n if (allowed.length === 0) {\n io.out(\" nobody else\\n\");\n }\n for (const entry of allowed) {\n io.out(\n ` ${entry.owner} on ${entry.origin}` +\n `${entry.note === undefined ? \"\" : ` (${stripControlChars(entry.note)})`}\\n`,\n );\n }\n\n const usage = budgets.usage(now);\n io.out(\"\\ncommunity work done for others\\n\");\n io.out(\n ` ${String(usage.hour)} in the last hour (cap ${String(usage.limits.maxJobsPerHour)}), ` +\n `${String(usage.day)} today (cap ${String(usage.limits.maxJobsPerDay)})\\n`,\n );\n\n const entries = await ingress.read();\n const prompts = entries.filter((entry) => entry.type === \"prompt\");\n const outcomes = entries.filter((entry) => entry.type === \"outcome\");\n io.out(\"\\nthis machine has run\\n\");\n io.out(\n ` ${String(prompts.length)} prompts, ` +\n `${String(outcomes.filter((o) => o.outcome === \"ok\").length)} ok, ` +\n `${String(outcomes.filter((o) => o.outcome === \"error\").length)} failed, ` +\n `${String(outcomes.filter((o) => o.outcome === \"refused\").length)} refused\\n`,\n );\n io.out(\n ` full log: ${paths.ingressLog} (community prompts kept ` +\n `${String(loaded.config.ingress.communityPromptDays)} days, then hashed)\\n`,\n );\n return 0;\n}\n\n// -- log ---------------------------------------------------------------------\n\nasync function commandLog(\n paths: DaemonPaths,\n args: readonly string[],\n io: CliIo,\n): Promise<ExitCode> {\n const full = args.includes(\"--full\");\n const nIndex = args.findIndex((arg) => arg === \"-n\" || arg === \"--lines\");\n const limit =\n nIndex === -1 ? 20 : Math.max(1, Number(args[nIndex + 1] ?? \"20\") || 20);\n\n const { ingress } = await context(paths);\n const entries = await ingress.read();\n const shown = entries.slice(-limit);\n\n if (shown.length === 0) {\n io.out(\"nothing has run on this machine yet\\n\");\n return 0;\n }\n\n for (const entry of shown) {\n const at = new Date(entry.at).toISOString().replace(\"T\", \" \").slice(0, 19);\n if (entry.type === \"outcome\") {\n io.out(\n `${at} ${entry.outcome.padEnd(8)} ${entry.jobId}` +\n (entry.durationMs === undefined\n ? \"\"\n : ` ${String(entry.durationMs)}ms`) +\n `${entry.detail === undefined ? \"\" : ` ${stripControlChars(entry.detail)}`}\\n`,\n );\n continue;\n }\n\n io.out(\n `${at} ${entry.audience.padEnd(7)} ${entry.kind} ` +\n `via ${entry.backendId}:${entry.model} for ${entry.owner} ` +\n `@ ${new URL(entry.origin).host}\\n`,\n );\n if (entry.prompt === undefined) {\n // Retention removed the text. Say so — a blank line here would read as\n // \"empty prompt\", and zero must never look like unknown.\n io.out(\n ` prompt not retained (${String(entry.promptChars)} chars, ` +\n `sha256 ${entry.promptHash.slice(0, 16)}…)\\n`,\n );\n } else if (full) {\n io.out(`${indent(stripControlChars(entry.prompt))}\\n`);\n } else {\n const firstLine = entry.prompt.split(\"\\n\")[0] ?? \"\";\n io.out(\n ` ${stripControlChars(firstLine.slice(0, 90))}` +\n `${entry.prompt.length > 90 ? \"…\" : \"\"}\\n`,\n );\n }\n }\n if (!full) {\n io.out(`\\n(${String(entries.length)} entries; --full for whole prompts)\\n`);\n }\n return 0;\n}\n\nfunction indent(text: string): string {\n return text\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n}\n\n// -- pause / resume -----------------------------------------------------------\n\nasync function commandPause(\n paths: DaemonPaths,\n pause: boolean,\n io: CliIo,\n): Promise<ExitCode> {\n await mkdir(paths.root, { recursive: true });\n if (pause) {\n await writeFile(paths.pauseFlag, `${new Date().toISOString()}\\n`);\n io.out(\n \"paused — no new work will be claimed. `byollm resume` to start again.\\n\",\n );\n } else {\n await rm(paths.pauseFlag, { force: true });\n io.out(\"resumed\\n\");\n }\n return 0;\n}\n\nasync function isPaused(paths: DaemonPaths): Promise<boolean> {\n try {\n await stat(paths.pauseFlag);\n return true;\n } catch {\n return false;\n }\n}\n\n// -- allow / disallow ---------------------------------------------------------\n\nasync function commandAllow(\n paths: DaemonPaths,\n args: readonly string[],\n io: CliIo,\n): Promise<ExitCode> {\n const allowlist = new Allowlist(paths.allowlist);\n await allowlist.load();\n\n if (args[0] === \"--list\" || args.length === 0) {\n const entries = allowlist.list();\n if (entries.length === 0) {\n io.out(\n \"Nobody but you can run work on this machine.\\n\" +\n \"`byollm allow <app-url> <user-id>` to change that.\\n\",\n );\n return 0;\n }\n for (const entry of entries) {\n io.out(\n `${entry.owner} on ${entry.origin}` +\n `${entry.note === undefined ? \"\" : ` (${stripControlChars(entry.note)})`}\\n`,\n );\n }\n return 0;\n }\n\n const [rawOrigin, owner, ...noteParts] = args;\n if (rawOrigin === undefined || owner === undefined) {\n io.err(\"usage: byollm allow <app-url> <user-id> [note]\\n\");\n return 2;\n }\n const origin = normalizeOrigin(rawOrigin);\n\n // byollm_002: widening scope requires an explicit confirmation that names\n // what it means. Not a y/N on an ambiguous question — the actual sentence.\n const confirmed = await io.confirm(\n `\\nThis lets jobs belonging to \"${owner}\" on ${origin} run on this machine,\\n` +\n `using your hardware and electricity, whenever your daemon is online.\\n` +\n `Your subscription-backed models are never included — those stay yours alone.\\n\\n` +\n `Allow ${owner} to use this machine?`,\n );\n if (!confirmed) {\n io.out(\"nothing changed\\n\");\n return 0;\n }\n\n await allowlist.add(\n {\n origin,\n owner,\n ...(noteParts.length > 0 ? { note: noteParts.join(\" \") } : {}),\n },\n Date.now(),\n );\n io.out(`allowed ${owner} on ${origin}\\n`);\n return 0;\n}\n\nasync function commandDisallow(\n paths: DaemonPaths,\n args: readonly string[],\n io: CliIo,\n): Promise<ExitCode> {\n const [rawOrigin, owner] = args;\n if (rawOrigin === undefined || owner === undefined) {\n io.err(\"usage: byollm disallow <app-url> <user-id>\\n\");\n return 2;\n }\n const allowlist = new Allowlist(paths.allowlist);\n await allowlist.load();\n const removed = await allowlist.remove(normalizeOrigin(rawOrigin), owner);\n io.out(\n removed\n ? `${owner} can no longer use this machine\\n`\n : `${owner} was not on the list — nothing changed\\n`,\n );\n return 0;\n}\n\n// -- forget -------------------------------------------------------------------\n\nasync function commandForget(\n paths: DaemonPaths,\n args: readonly string[],\n io: CliIo,\n): Promise<ExitCode> {\n const target = args[0];\n if (target === undefined) {\n io.err(\"usage: byollm forget <app-url>\\n\");\n return 2;\n }\n const pairings = new Pairings(paths.pairings);\n await pairings.load();\n const removed = await pairings.remove(normalizeOrigin(target));\n io.out(\n removed\n ? `forgot ${normalizeOrigin(target)} — the app may still list this runner ` +\n `until you revoke it there too\\n`\n : `not paired with ${normalizeOrigin(target)}\\n`,\n );\n return 0;\n}\n\n// -- backends ------------------------------------------------------------------\n\nasync function commandBackends(\n paths: DaemonPaths,\n io: CliIo,\n): Promise<ExitCode> {\n const { loaded, ingress, allowlist, budgets } = await context(paths);\n const runner = new Runner({\n client: new ProtocolClient({ origin: \"https://unused.invalid\" }),\n runnerId: \"local\",\n owner: \"local\",\n daemonVersion: DAEMON_VERSION,\n loaded,\n allowlist,\n budgets,\n ingress,\n });\n\n const advertised = await runner.detectCapabilities();\n const advertisedKinds = new Set(advertised.map((c) => c.kind));\n\n io.out(\"configured routes\\n\");\n for (const route of loaded.routes) {\n const ok = advertisedKinds.has(route.kind);\n io.out(\n ` ${ok ? \"✓\" : \"✗\"} ${route.kind.padEnd(14)} ` +\n `${route.backendId}:${route.model}` +\n `${route.baseUrl === undefined ? \"\" : ` @ ${route.baseUrl}`}\\n`,\n );\n }\n for (const problem of loaded.problems) {\n io.out(` ! ${problem.where}: ${problem.message}\\n`);\n }\n io.out(\n `\\n${String(advertised.length)} of ${String(loaded.routes.length)} routes are ` +\n `healthy and will be advertised.\\n` +\n `A route that is not healthy is never offered to an app — the daemon does\\n` +\n `not advertise what it cannot actually run.\\n`,\n );\n return advertised.length === 0 ? 1 : 0;\n}\n\n// -- shared -------------------------------------------------------------------\n\nasync function context(paths: DaemonPaths): Promise<{\n loaded: Awaited<ReturnType<typeof loadConfig>>;\n ingress: IngressLog;\n allowlist: Allowlist;\n budgets: Budgets;\n}> {\n const loaded = await loadConfig(paths.config);\n const ingress = new IngressLog({\n path: paths.ingressLog,\n communityPromptDays: loaded.config.ingress.communityPromptDays,\n keepSelfPrompts: loaded.config.ingress.keepSelfPrompts,\n });\n const allowlist = new Allowlist(paths.allowlist);\n await allowlist.load();\n const budgets = new Budgets(paths.budgets, loaded.config.community);\n await budgets.load(Date.now());\n return { loaded, ingress, allowlist, budgets };\n}\n\n/**\n * Ask, on a real terminal.\n *\n * Refuses outright when stdin is not a TTY: widening who may use someone's\n * machine is not a thing to do on an implied yes from a script.\n */\nasync function confirmInteractively(question: string): Promise<boolean> {\n if (!process.stdin.isTTY) {\n process.stderr.write(\n \"refusing to widen access without an interactive confirmation\\n\",\n );\n return false;\n }\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n const answer = await rl.question(`${question} [y/N] `);\n return /^y(es)?$/i.test(answer.trim());\n } finally {\n rl.close();\n }\n}\n\n/**\n * How this machine appears in the app's runner list.\n *\n * `BYOLLM_LABEL` overrides it, because \"todd@Todds-MacBook-Pro\" is more than\n * some people want to hand an app they are only trying out.\n */\nfunction hostLabel(): string {\n const override = process.env[\"BYOLLM_LABEL\"];\n if (override !== undefined && override !== \"\") return override.slice(0, 120);\n try {\n return `${userInfo().username}@${hostname()}`.slice(0, 120);\n } catch {\n return hostname().slice(0, 120);\n }\n}\n\n/** The `byollm` executable. */\nexport async function main(argv: readonly string[]): Promise<ExitCode> {\n try {\n return await runCli(argv);\n } catch (error) {\n process.stderr.write(\n `${error instanceof ClientError || error instanceof Error ? error.message : String(error)}\\n`,\n );\n return 1;\n }\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { z } from \"zod\";\nimport type { CommunityBudget } from \"./config.js\";\n\nconst BudgetFile = z\n .object({\n version: z.literal(1),\n /** Epoch-ms timestamps of community jobs accepted, newest last. */\n accepted: z.array(z.number().int().positive()),\n })\n .strict();\n\nexport type BudgetRefusal = \"hourly-cap\" | \"daily-cap\" | \"payload-too-large\";\n\nexport type BudgetDecision =\n | { readonly ok: true }\n | {\n readonly ok: false;\n readonly refusal: BudgetRefusal;\n readonly detail: string;\n };\n\n/**\n * The owner's ceiling on work done for other people\n * ({@link MUSTS.COMMUNITY_BUDGETS}).\n *\n * byollm_004 §4 distinguishes two directions of abuse, and this is the one\n * aimed *at* the volunteer: a stranger who can enqueue unlimited `public`\n * jobs owns your GPU. Jobs for the machine's own owner are never counted —\n * their machine, their call.\n */\nexport class Budgets {\n readonly #path: string;\n readonly #limits: CommunityBudget;\n #accepted: number[] = [];\n #loaded = false;\n\n constructor(path: string, limits: CommunityBudget) {\n this.#path = path;\n this.#limits = limits;\n }\n\n async load(now: number): Promise<void> {\n try {\n const parsed = BudgetFile.safeParse(\n JSON.parse(await readFile(this.#path, \"utf8\")),\n );\n this.#accepted = parsed.success ? parsed.data.accepted : [];\n } catch {\n this.#accepted = [];\n }\n this.#prune(now);\n this.#loaded = true;\n }\n\n /**\n * May this community job run?\n *\n * @param payloadChars - total payload text length, checked against the\n * stricter community limit rather than the protocol's absolute ceiling.\n */\n check(now: number, payloadChars: number): BudgetDecision {\n if (!this.#loaded) throw new Error(\"budgets used before load()\");\n this.#prune(now);\n\n if (payloadChars > this.#limits.maxPayloadChars) {\n return {\n ok: false,\n refusal: \"payload-too-large\",\n detail:\n `community jobs are limited to ${String(this.#limits.maxPayloadChars)} ` +\n `characters; this one is ${String(payloadChars)}`,\n };\n }\n\n const hour = this.#countSince(now - 3_600_000);\n if (hour >= this.#limits.maxJobsPerHour) {\n return {\n ok: false,\n refusal: \"hourly-cap\",\n detail: `already ran ${String(hour)} community jobs in the last hour`,\n };\n }\n\n const day = this.#countSince(now - 86_400_000);\n if (day >= this.#limits.maxJobsPerDay) {\n return {\n ok: false,\n refusal: \"daily-cap\",\n detail: `already ran ${String(day)} community jobs today`,\n };\n }\n return { ok: true };\n }\n\n /** Count a community job as accepted. Call only after {@link check} passes. */\n async record(now: number): Promise<void> {\n this.#accepted.push(now);\n this.#prune(now);\n await mkdir(dirname(this.#path), { recursive: true });\n await writeFile(\n this.#path,\n JSON.stringify({ version: 1, accepted: this.#accepted }),\n { mode: 0o600 },\n );\n }\n\n /** Current usage, for `byollm status`. */\n usage(now: number): { hour: number; day: number; limits: CommunityBudget } {\n this.#prune(now);\n return {\n hour: this.#countSince(now - 3_600_000),\n day: this.#countSince(now - 86_400_000),\n limits: this.#limits,\n };\n }\n\n #countSince(since: number): number {\n return this.#accepted.filter((at) => at >= since).length;\n }\n\n /** Anything older than a day can never affect either window again. */\n #prune(now: number): void {\n const cutoff = now - 86_400_000;\n this.#accepted = this.#accepted.filter((at) => at >= cutoff);\n }\n}\n","import {\n ClaimResponse,\n HeartbeatResponse,\n PROTOCOL_VERSION,\n PairPollResponse,\n PairStartResponse,\n ReleaseResponse,\n ResultResponse,\n WireError,\n type Capability,\n type Endpoint,\n type JobOutcome,\n} from \"@byollm/protocol\";\nimport { type z } from \"zod\";\n\n/**\n * Why a protocol call failed, from the daemon's seat.\n *\n * byollm_002 requires that \"server unreachable\", \"revoked\", \"no matching\n * work\" and \"backend down\" never share a message. Three of those are\n * distinguishable here; the fourth is a local condition the loop reports\n * itself. \"No matching work\" is deliberately *not* an error — it is a `200`\n * with an empty list.\n */\nexport type ClientErrorKind =\n | \"unreachable\"\n | \"revoked\"\n | \"unauthorized\"\n | \"rejected\"\n | \"rate-limited\"\n | \"server-error\"\n | \"malformed-response\";\n\nexport class ClientError extends Error {\n override readonly name = \"ClientError\";\n constructor(\n readonly kind: ClientErrorKind,\n message: string,\n /** Seconds the server asked us to wait, when it said. */\n readonly retryAfter?: number,\n ) {\n super(message);\n }\n\n /** Is retrying this same call plausibly useful? */\n get retryable(): boolean {\n return (\n this.kind === \"unreachable\" ||\n this.kind === \"rate-limited\" ||\n this.kind === \"server-error\"\n );\n }\n}\n\nexport interface ClientOptions {\n /** The app's origin, e.g. `https://app.example.com`. */\n readonly origin: string;\n /** Bearer token from pairing. Absent while pairing. */\n readonly token?: string | undefined;\n /** Per-request timeout. */\n readonly timeoutMs?: number;\n /** Injectable fetch, for tests. */\n readonly fetch?: typeof fetch;\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/**\n * The daemon's outbound protocol client.\n *\n * Every call is outbound; nothing here ever listens. That is the whole\n * network posture of the product, and it lives in this one class.\n */\nexport class ProtocolClient {\n readonly #origin: string;\n readonly #token: string | undefined;\n readonly #timeoutMs: number;\n readonly #fetch: typeof fetch;\n\n constructor(options: ClientOptions) {\n this.#origin = options.origin.replace(/\\/+$/, \"\");\n this.#token = options.token;\n this.#timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.#fetch = options.fetch ?? globalThis.fetch;\n }\n\n /** A client for the same origin carrying a token. */\n withToken(token: string): ProtocolClient {\n return new ProtocolClient({\n origin: this.#origin,\n token,\n timeoutMs: this.#timeoutMs,\n fetch: this.#fetch,\n });\n }\n\n get origin(): string {\n return this.#origin;\n }\n\n async pairStart(input: {\n version: string;\n label: string;\n platform: \"darwin\" | \"linux\" | \"win32\";\n capabilities: readonly Capability[];\n }): Promise<PairStartResponse> {\n return this.#post(\"pair\", PairStartResponse, {\n protocolVersion: PROTOCOL_VERSION,\n action: \"start\",\n daemon: {\n version: input.version,\n label: input.label,\n platform: input.platform,\n },\n capabilities: input.capabilities,\n });\n }\n\n async pairPoll(deviceCode: string): Promise<PairPollResponse> {\n return this.#post(\"pair\", PairPollResponse, {\n protocolVersion: PROTOCOL_VERSION,\n action: \"poll\",\n deviceCode,\n });\n }\n\n async claim(input: {\n runnerId: string;\n capabilities: readonly Capability[];\n max: number;\n }): Promise<ClaimResponse> {\n return this.#post(\"claim\", ClaimResponse, {\n protocolVersion: PROTOCOL_VERSION,\n runnerId: input.runnerId,\n capabilities: input.capabilities,\n max: input.max,\n });\n }\n\n async heartbeat(input: {\n runnerId: string;\n daemonVersion: string;\n capabilities: readonly Capability[];\n activeJobIds: readonly string[];\n paused: boolean;\n }): Promise<HeartbeatResponse> {\n return this.#post(\"heartbeat\", HeartbeatResponse, {\n protocolVersion: PROTOCOL_VERSION,\n runnerId: input.runnerId,\n daemonVersion: input.daemonVersion,\n capabilities: input.capabilities,\n activeJobIds: input.activeJobIds,\n paused: input.paused,\n });\n }\n\n async result(input: {\n runnerId: string;\n jobId: string;\n outcome: JobOutcome;\n model: string;\n backendClass: \"http\" | \"process\";\n durationMs: number;\n }): Promise<ResultResponse> {\n return this.#post(\"result\", ResultResponse, {\n protocolVersion: PROTOCOL_VERSION,\n ...input,\n });\n }\n\n async release(input: {\n runnerId: string;\n jobIds: readonly string[];\n reason: \"shutdown\" | \"pause\" | \"revoked\" | \"backend-down\" | \"refused\";\n }): Promise<ReleaseResponse> {\n return this.#post(\"release\", ReleaseResponse, {\n protocolVersion: PROTOCOL_VERSION,\n runnerId: input.runnerId,\n jobIds: input.jobIds,\n reason: input.reason,\n });\n }\n\n async #post<T>(\n endpoint: Endpoint,\n schema: z.ZodType<T>,\n body: unknown,\n ): Promise<T> {\n const headers: Record<string, string> = {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n };\n if (this.#token !== undefined) {\n headers[\"authorization\"] = `Bearer ${this.#token}`;\n }\n\n let response: Response;\n try {\n response = await this.#fetch(`${this.#origin}/byollm/${endpoint}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n redirect: \"error\",\n signal: AbortSignal.timeout(this.#timeoutMs),\n });\n } catch (error) {\n // No response at all: the server is unreachable. Distinct from every\n // answer it could have given us, including a refusal.\n throw new ClientError(\n \"unreachable\",\n `could not reach ${this.#origin} (${error instanceof Error ? error.message : \"unknown error\"})`,\n );\n }\n\n const text = await response.text();\n let parsed: unknown;\n try {\n parsed = text === \"\" ? {} : JSON.parse(text);\n } catch {\n throw new ClientError(\n \"malformed-response\",\n `${this.#origin} returned HTTP ${String(response.status)} with a body that is not JSON`,\n );\n }\n\n if (!response.ok) {\n throw this.#toError(response, parsed);\n }\n\n const result = schema.safeParse(parsed);\n if (!result.success) {\n // A server whose response does not match the protocol is not one we can\n // safely guess about.\n throw new ClientError(\n \"malformed-response\",\n `${this.#origin} returned a ${endpoint} response that does not match protocol v${PROTOCOL_VERSION}`,\n );\n }\n return result.data;\n }\n\n #toError(response: Response, body: unknown): ClientError {\n const wire = WireError.safeParse(body);\n const retryAfterHeader = response.headers.get(\"retry-after\");\n const retryAfter =\n wire.success && wire.data.retryAfter !== undefined\n ? wire.data.retryAfter\n : retryAfterHeader !== null && /^\\d+$/.test(retryAfterHeader)\n ? Number(retryAfterHeader)\n : undefined;\n\n const message = wire.success\n ? wire.data.message\n : `${this.#origin} returned HTTP ${String(response.status)}`;\n\n if (wire.success && wire.data.error === \"revoked\") {\n return new ClientError(\"revoked\", message, retryAfter);\n }\n switch (response.status) {\n case 401:\n return new ClientError(\"unauthorized\", message, retryAfter);\n case 403:\n return new ClientError(\"revoked\", message, retryAfter);\n case 429:\n return new ClientError(\"rate-limited\", message, retryAfter);\n case 400:\n case 404:\n // Never retried: the request is wrong, and repeating it stays wrong.\n return new ClientError(\"rejected\", message, retryAfter);\n default:\n return response.status >= 500\n ? new ClientError(\"server-error\", message, retryAfter)\n : new ClientError(\"rejected\", message, retryAfter);\n }\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport {\n BackendIdSchema,\n JobKind,\n OfferScope,\n backendDescriptor,\n effectiveOfferScope,\n type BackendId,\n} from \"@byollm/protocol\";\nimport { z } from \"zod\";\nimport { checkBaseUrl } from \"./ssrf.js\";\n\n/**\n * One configured backend instance.\n *\n * `openai-http` may be configured many times — one per model server the owner\n * runs (Ollama here, `mlx_lm.server` there, a llama.cpp box on the LAN). That\n * is byollm_001 Rev 1 §A's \"one backend, N base URLs\".\n */\nexport const BackendConfig = z\n .object({\n backend: BackendIdSchema,\n /** Required for HTTP-class backends; meaningless for process-class. */\n baseUrl: z.string().optional(),\n /**\n * What the owner is willing to run for others. Subscription-class\n * backends ignore this and are locked to `self`\n * ({@link MUSTS.SUBSCRIPTION_SELF_LOCK}).\n */\n offer: OfferScope.default(\"self\"),\n /**\n * Name of an environment variable holding this backend's API key, for a\n * remote OpenAI-compatible server that needs one. The *name*, never the\n * value — a key does not belong in a config file the owner may share.\n */\n apiKeyEnv: z.string().optional(),\n })\n .strict();\nexport type BackendConfig = z.infer<typeof BackendConfig>;\n\n/** Which backend instance and model serves a job kind. */\nexport const RouteConfig = z\n .object({\n /** Key into {@link DaemonConfig.backends}. */\n backend: z.string().min(1),\n /** The model name, owner-chosen. A payload can never influence this. */\n model: z.string().min(1),\n })\n .strict();\nexport type RouteConfig = z.infer<typeof RouteConfig>;\n\n/**\n * Budgets applied to jobs whose owner is not this machine's owner\n * ({@link MUSTS.COMMUNITY_BUDGETS}).\n */\nexport const CommunityBudget = z\n .object({\n maxJobsPerHour: z.number().int().positive().default(20),\n maxJobsPerDay: z.number().int().positive().default(100),\n /** Wall-clock ceiling for one community job. */\n maxWallClockMs: z.number().int().positive().default(120_000),\n /** Output-size ceiling for one community job. */\n maxOutputBytes: z\n .number()\n .int()\n .positive()\n .default(256 * 1024),\n /** Payload-size ceiling — stricter than the protocol's absolute limit. */\n maxPayloadChars: z.number().int().positive().default(100_000),\n })\n .strict();\nexport type CommunityBudget = z.infer<typeof CommunityBudget>;\n\n/** Ingress-log retention (byollm_004 Rev 1). */\nexport const IngressRetention = z\n .object({\n /**\n * How long a `named`/`public` prompt is kept in full before being reduced\n * to a hash. A volunteer must not indefinitely retain strangers' content.\n */\n communityPromptDays: z.number().int().positive().default(7),\n /** Whether the owner's own prompts are kept in full. Their call. */\n keepSelfPrompts: z.boolean().default(true),\n })\n .strict();\nexport type IngressRetention = z.infer<typeof IngressRetention>;\n\n/** Ceilings applied to every job, community or not. */\nexport const Limits = z\n .object({\n maxWallClockMs: z.number().int().positive().default(600_000),\n maxOutputBytes: z\n .number()\n .int()\n .positive()\n .default(4 * 1024 * 1024),\n })\n .strict();\nexport type Limits = z.infer<typeof Limits>;\n\nexport const DaemonConfig = z\n .object({\n backends: z.record(z.string().min(1), BackendConfig),\n // `partialRecord`, not `record`: zod 4's `record` with an enum key\n // demands every member be present, which would force an owner who only\n // wants `llm.generate` to also configure `llm.chat`. Routing one kind and\n // not the other is a legitimate setup — the unrouted kind is simply never\n // advertised.\n routes: z.partialRecord(JobKind, RouteConfig),\n /** How many jobs to run at once. */\n concurrency: z.number().int().min(1).max(32).default(2),\n // `prefault`, not `default`: zod 4's `.default()` takes an *output* value,\n // which would mean restating every nested default here where it could\n // drift. `prefault` feeds `{}` through the schema so the nested defaults\n // stay the single source of truth.\n community: CommunityBudget.prefault({}),\n ingress: IngressRetention.prefault({}),\n limits: Limits.prefault({}),\n })\n .strict();\nexport type DaemonConfig = z.infer<typeof DaemonConfig>;\n\n/** A route resolved against its backend, ready to execute. */\nexport interface ResolvedRoute {\n readonly kind: z.infer<typeof JobKind>;\n readonly backendKey: string;\n readonly backendId: BackendId;\n readonly backendClass: \"http\" | \"process\";\n readonly model: string;\n /** After the subscription lock is applied — never the raw configured value. */\n readonly offerScope: z.infer<typeof OfferScope>;\n readonly baseUrl: string | undefined;\n readonly apiKeyEnv: string | undefined;\n}\n\nexport interface ConfigProblem {\n readonly where: string;\n readonly message: string;\n}\n\nexport interface LoadedConfig {\n readonly config: DaemonConfig;\n readonly routes: readonly ResolvedRoute[];\n /** Non-fatal problems: a route that cannot be served is dropped, not fatal. */\n readonly problems: readonly ConfigProblem[];\n}\n\n/** The config used when the owner has not written one. */\nexport const DEFAULT_CONFIG: DaemonConfig = DaemonConfig.parse({\n backends: {\n ollama: { backend: \"openai-http\", baseUrl: \"http://127.0.0.1:11434/v1\" },\n },\n routes: {\n \"llm.generate\": { backend: \"ollama\", model: \"llama3.2\" },\n \"llm.chat\": { backend: \"ollama\", model: \"llama3.2\" },\n },\n});\n\n/**\n * Read and resolve `~/.byollm/config.json`.\n *\n * A missing file yields {@link DEFAULT_CONFIG}; a malformed one throws,\n * because silently running with defaults when the owner *did* write a config\n * would execute work under rules they did not choose.\n */\nexport async function loadConfig(path: string): Promise<LoadedConfig> {\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch (error) {\n if (isNotFound(error)) return resolveConfig(DEFAULT_CONFIG);\n throw error;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new Error(\n `${path} is not valid JSON: ${error instanceof Error ? error.message : \"unknown error\"}`,\n { cause: error },\n );\n }\n\n const result = DaemonConfig.safeParse(parsed);\n if (!result.success) {\n const issues = result.error.issues\n .map((issue) => ` ${issue.path.join(\".\") || \"(root)\"}: ${issue.message}`)\n .join(\"\\n\");\n throw new Error(`${path} is not a valid byollm config:\\n${issues}`);\n }\n return resolveConfig(result.data);\n}\n\n/**\n * Turn a parsed config into executable routes, applying the subscription lock\n * and rejecting unusable backends.\n *\n * A problem here is not fatal: a machine with three routes and one broken\n * backend should serve the other two and say so, rather than refusing to\n * start. What it must never do is *advertise* the broken one\n * ({@link MUSTS.CAPABILITY_IS_DETECTED}).\n */\nexport function resolveConfig(config: DaemonConfig): LoadedConfig {\n const routes: ResolvedRoute[] = [];\n const problems: ConfigProblem[] = [];\n\n for (const [kind, route] of Object.entries(config.routes)) {\n const where = `routes.${kind}`;\n const backend = config.backends[route.backend];\n if (!backend) {\n problems.push({\n where,\n message: `backend \"${route.backend}\" is not defined in backends`,\n });\n continue;\n }\n\n const descriptor = backendDescriptor(backend.backend);\n\n if (descriptor.class === \"http\") {\n if (backend.baseUrl === undefined) {\n problems.push({\n where: `backends.${route.backend}`,\n message: \"an HTTP-class backend needs a baseUrl\",\n });\n continue;\n }\n const check = checkBaseUrl(backend.baseUrl);\n if (!check.ok) {\n problems.push({\n where: `backends.${route.backend}.baseUrl`,\n message: check.detail,\n });\n continue;\n }\n }\n\n const configured = backend.offer;\n const offerScope = effectiveOfferScope(configured, descriptor.account);\n if (offerScope !== configured) {\n problems.push({\n where: `backends.${route.backend}.offer`,\n message:\n `\"${configured}\" was ignored: ${descriptor.label} runs on your own ` +\n `subscription, so it is locked to your work only`,\n });\n }\n\n routes.push({\n kind: kind as z.infer<typeof JobKind>,\n backendKey: route.backend,\n backendId: backend.backend,\n backendClass: descriptor.class,\n model: route.model,\n offerScope,\n baseUrl: backend.baseUrl,\n apiKeyEnv: backend.apiKeyEnv,\n });\n }\n\n return { config, routes, problems };\n}\n\nfunction isNotFound(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: unknown }).code === \"ENOENT\"\n );\n}\n","import { isIP } from \"node:net\";\n\n/**\n * Why a base URL was refused.\n */\nexport type BaseUrlRefusal =\n | \"not-a-url\"\n | \"bad-scheme\"\n | \"credentials-in-url\"\n | \"cloud-metadata\"\n | \"link-local\"\n | \"wildcard-address\";\n\nexport type BaseUrlCheck =\n | { readonly ok: true; readonly url: URL }\n | {\n readonly ok: false;\n readonly refusal: BaseUrlRefusal;\n readonly detail: string;\n };\n\n/**\n * Hostnames that resolve to a cloud instance's credential endpoint. Reaching\n * one from a machine running in a cloud VM hands out IAM credentials.\n */\nconst METADATA_HOSTS = new Set([\n \"metadata.google.internal\",\n \"metadata.goog\",\n \"instance-data\",\n \"metadata\",\n]);\n\n/** Literal addresses of the same endpoints. */\nconst METADATA_ADDRESSES = new Set([\n \"169.254.169.254\",\n \"169.254.170.2\",\n \"fd00:ec2::254\",\n]);\n\n/**\n * Validate an owner-configured backend base URL\n * ({@link MUSTS.HTTP_BASE_URL_SAFE}).\n *\n * **What this is and is not.** byollm_004 Rev 1 calls the HTTP-class threat\n * surface \"SSRF-shaped\", and the shape matters: the base URL comes from the\n * machine owner's config and from nowhere else — no payload field can set it,\n * redirect it, or append to it. There is therefore no attacker-controlled\n * input channel into this value at all. What remains is an owner who\n * misconfigures their own machine, and the one case where that is genuinely\n * dangerous is a cloud metadata endpoint.\n *\n * So this deliberately **allows loopback and private LAN addresses**. Blocking\n * them, as a generic SSRF filter would, would refuse\n * `http://127.0.0.1:11434` — which is Ollama's default and the entire point of\n * the product. A filter that breaks the primary path in exchange for no real\n * protection is theatre, and byollm_004's honesty rule forbids claiming it as\n * a guarantee.\n *\n * Redirects are a separate matter and are refused outright by the HTTP\n * backend, so a permitted base URL cannot become a forbidden one in flight.\n */\nexport function checkBaseUrl(raw: string): BaseUrlCheck {\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n return {\n ok: false,\n refusal: \"not-a-url\",\n detail: \"base URL is not a valid absolute URL\",\n };\n }\n\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n return {\n ok: false,\n refusal: \"bad-scheme\",\n detail: `base URL scheme ${url.protocol} is not http or https`,\n };\n }\n\n if (url.username !== \"\" || url.password !== \"\") {\n // Credentials in the URL would end up in logs and error messages.\n return {\n ok: false,\n refusal: \"credentials-in-url\",\n detail: \"base URL must not embed a username or password\",\n };\n }\n\n const host = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, \"\");\n\n if (METADATA_HOSTS.has(host) || METADATA_ADDRESSES.has(host)) {\n return {\n ok: false,\n refusal: \"cloud-metadata\",\n detail: `${host} is a cloud metadata endpoint`,\n };\n }\n\n // 169.254.0.0/16 and fe80::/10 — link-local. The metadata addresses above\n // live here too; this catches the rest of the range.\n if (isIP(host) === 4 && host.startsWith(\"169.254.\")) {\n return {\n ok: false,\n refusal: \"link-local\",\n detail: `${host} is link-local`,\n };\n }\n if (isIP(host) === 6 && /^fe[89ab]/.test(host)) {\n return {\n ok: false,\n refusal: \"link-local\",\n detail: `${host} is link-local`,\n };\n }\n\n // A wildcard address is a listening address, not a destination.\n if (host === \"0.0.0.0\" || host === \"::\" || host === \"\") {\n return {\n ok: false,\n refusal: \"wildcard-address\",\n detail: `${host || \"(empty)\"} is not a destination address`,\n };\n }\n\n return { ok: true, url };\n}\n\n/** Human-readable explanations for the trust UI and startup errors. */\nexport const BASE_URL_REFUSAL_MESSAGES: Readonly<\n Record<BaseUrlRefusal, string>\n> = Object.freeze({\n \"not-a-url\": \"that base URL could not be parsed\",\n \"bad-scheme\": \"a backend base URL must be http or https\",\n \"credentials-in-url\":\n \"put credentials in the backend's auth config, not in the URL\",\n \"cloud-metadata\":\n \"that address is a cloud metadata endpoint and would expose instance credentials\",\n \"link-local\": \"link-local addresses are refused\",\n \"wildcard-address\":\n \"that is an address to listen on, not one to connect to — use 127.0.0.1\",\n});\n","import { platform } from \"node:os\";\nimport type { Capability } from \"@byollm/protocol\";\nimport { ClientError, type ProtocolClient } from \"./client.js\";\nimport type { Pairing } from \"./pairings.js\";\n\nexport interface ConnectOptions {\n readonly client: ProtocolClient;\n readonly daemonVersion: string;\n readonly label: string;\n readonly capabilities: readonly Capability[];\n /** Called once, with what to show the user. */\n readonly onCode: (info: {\n userCode: string;\n verificationUrl: string;\n expiresAt: number;\n }) => void;\n /** Called each poll, so a CLI can show it is still waiting. */\n readonly onPoll?: () => void;\n readonly now?: () => number;\n readonly sleep?: (ms: number) => Promise<void>;\n readonly signal?: AbortSignal;\n}\n\nexport type ConnectResult =\n | { readonly ok: true; readonly pairing: Pairing }\n | {\n readonly ok: false;\n readonly reason: \"denied\" | \"expired\" | \"aborted\";\n readonly message: string;\n };\n\n/**\n * The device-code pairing flow, from the daemon's side.\n *\n * The daemon asks for a code, shows it, and polls. The user approves inside\n * the app's own authenticated session, which is how the server learns who\n * they are — the daemon never asserts an identity and never accepts a pasted\n * long-lived secret ({@link MUSTS.PAIR_INTERACTIVE}).\n *\n * Nothing listens on the user's machine for this. A loopback redirect would\n * be fewer keystrokes and would contradict the product's whole posture, as\n * well as breaking on the headless boxes most likely to be running a model.\n */\nexport async function connect(options: ConnectOptions): Promise<ConnectResult> {\n const now = options.now ?? Date.now;\n const sleep = options.sleep ?? defaultSleep;\n\n const started = await options.client.pairStart({\n version: options.daemonVersion,\n label: options.label,\n platform: currentPlatform(),\n capabilities: options.capabilities,\n });\n\n options.onCode({\n userCode: started.userCode,\n verificationUrl: started.verificationUrl,\n expiresAt: started.expiresAt,\n });\n\n for (;;) {\n if (options.signal?.aborted === true) {\n return { ok: false, reason: \"aborted\", message: \"pairing was canceled\" };\n }\n if (now() >= started.expiresAt) {\n return {\n ok: false,\n reason: \"expired\",\n message: \"the pairing code expired before it was approved\",\n };\n }\n\n await sleep(started.pollIntervalMs);\n options.onPoll?.();\n\n let polled;\n try {\n polled = await options.client.pairPoll(started.deviceCode);\n } catch (error) {\n // A blip while waiting for a human is not a failure — keep polling\n // until the code itself expires.\n if (error instanceof ClientError && error.retryable) continue;\n throw error;\n }\n\n switch (polled.status) {\n case \"pending\":\n continue;\n case \"denied\":\n return {\n ok: false,\n reason: \"denied\",\n message: \"the pairing request was declined\",\n };\n case \"expired\":\n return {\n ok: false,\n reason: \"expired\",\n message: \"the pairing code expired before it was approved\",\n };\n case \"approved\":\n return {\n ok: true,\n pairing: {\n origin: options.client.origin,\n runnerId: polled.runnerId,\n token: polled.runnerToken,\n owner: polled.owner,\n ...(polled.ownerLabel === undefined\n ? {}\n : { ownerLabel: polled.ownerLabel }),\n pairedAt: now(),\n },\n };\n }\n }\n}\n\n/** The platform, narrowed to what the protocol accepts. */\nexport function currentPlatform(): \"darwin\" | \"linux\" | \"win32\" {\n const current = platform();\n if (current === \"darwin\" || current === \"linux\" || current === \"win32\") {\n return current;\n }\n // byollm_002 scopes v1 to macOS and Linux. Anything else reports as linux\n // rather than refusing outright — the protocol field is descriptive, and a\n // BSD user with Ollama running should not be blocked by a label.\n return \"linux\";\n}\n\nconst defaultSleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n","import { createHash } from \"node:crypto\";\nimport { appendFile, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { Audience } from \"@byollm/protocol\";\nimport { z } from \"zod\";\n\n/**\n * A prompt about to be executed.\n *\n * Written *before* the backend is called\n * ({@link MUSTS.INGRESS_LOGGED_BEFORE_EXECUTION}), so a job that wedges or\n * crashes the machine still leaves a record of what it was.\n */\nexport const PromptEntry = z\n .object({\n type: z.literal(\"prompt\"),\n at: z.number().int().positive(),\n /** Origin of the server that sent the job. */\n origin: z.string().min(1),\n jobId: z.string().min(1),\n kind: z.string().min(1),\n audience: z.string().min(1),\n /** Who this prompt is *for* — which, for community work, is not you. */\n owner: z.string().min(1),\n backendId: z.string().min(1),\n backendClass: z.string().min(1),\n model: z.string().min(1),\n /** Always present, including after retention drops the text. */\n promptHash: z.string().length(64),\n promptChars: z.number().int().nonnegative(),\n /**\n * The prompt itself. Absent means \"not retained\" — distinct from an empty\n * prompt, which the protocol forbids anyway. Zero and unknown never look\n * alike.\n */\n prompt: z.string().optional(),\n })\n .strict();\nexport type PromptEntry = z.infer<typeof PromptEntry>;\n\n/** How a job ended. A separate line, so the prompt line is never rewritten. */\nexport const OutcomeEntry = z\n .object({\n type: z.literal(\"outcome\"),\n at: z.number().int().positive(),\n jobId: z.string().min(1),\n outcome: z.enum([\"ok\", \"error\", \"canceled\", \"refused\"]),\n /** Present for a job that ran; absent for one refused before execution. */\n durationMs: z.number().int().nonnegative().optional(),\n outputChars: z.number().int().nonnegative().optional(),\n /** Why, for `error` and `refused`. */\n detail: z.string().optional(),\n })\n .strict();\nexport type OutcomeEntry = z.infer<typeof OutcomeEntry>;\n\nexport const IngressEntry = z.discriminatedUnion(\"type\", [\n PromptEntry,\n OutcomeEntry,\n]);\nexport type IngressEntry = z.infer<typeof IngressEntry>;\n\nexport interface IngressOptions {\n readonly path: string;\n /** Days to keep a community prompt in full before reducing it to its hash. */\n readonly communityPromptDays: number;\n /** Whether to record the owner's own prompts in full. */\n readonly keepSelfPrompts: boolean;\n}\n\n/**\n * The append-only record of every prompt that has run on this machine.\n *\n * byollm_002 calls the meter the product's soul. This is it: one JSONL file\n * the owner can read, grep and delete, written before execution rather than\n * after.\n */\nexport class IngressLog {\n readonly #options: IngressOptions;\n\n constructor(options: IngressOptions) {\n this.#options = options;\n }\n\n /** Record a prompt. Await this before starting the backend call. */\n async recordPrompt(input: {\n at: number;\n origin: string;\n jobId: string;\n kind: string;\n audience: Audience;\n owner: string;\n backendId: string;\n backendClass: string;\n model: string;\n prompt: string;\n }): Promise<void> {\n // Community prompts are always kept initially — retention reduces them\n // later. Only the owner's own prompts can be opted out of up front.\n const keepText =\n input.audience === \"self\" ? this.#options.keepSelfPrompts : true;\n\n await this.#append({\n type: \"prompt\",\n at: input.at,\n origin: input.origin,\n jobId: input.jobId,\n kind: input.kind,\n audience: input.audience,\n owner: input.owner,\n backendId: input.backendId,\n backendClass: input.backendClass,\n model: input.model,\n promptHash: hashText(input.prompt),\n promptChars: input.prompt.length,\n ...(keepText ? { prompt: input.prompt } : {}),\n });\n }\n\n /** Record how a job ended. */\n async recordOutcome(input: {\n at: number;\n jobId: string;\n outcome: OutcomeEntry[\"outcome\"];\n durationMs?: number;\n outputChars?: number;\n detail?: string;\n }): Promise<void> {\n await this.#append({\n type: \"outcome\",\n at: input.at,\n jobId: input.jobId,\n outcome: input.outcome,\n ...(input.durationMs === undefined\n ? {}\n : { durationMs: input.durationMs }),\n ...(input.outputChars === undefined\n ? {}\n : { outputChars: input.outputChars }),\n ...(input.detail === undefined ? {} : { detail: input.detail }),\n });\n }\n\n async #append(entry: IngressEntry): Promise<void> {\n await mkdir(dirname(this.#options.path), { recursive: true });\n // JSON.stringify escapes control characters, so a prompt containing ANSI\n // escapes or newlines cannot forge a log line or repaint the terminal of\n // whoever later reads the file ({@link MUSTS.OUTPUT_INERT}).\n await appendFile(this.#options.path, `${JSON.stringify(entry)}\\n`, {\n mode: 0o600,\n });\n }\n\n /** Read the log, oldest first. Malformed lines are skipped, not fatal. */\n async read(): Promise<IngressEntry[]> {\n let raw: string;\n try {\n raw = await readFile(this.#options.path, \"utf8\");\n } catch {\n return [];\n }\n const entries: IngressEntry[] = [];\n for (const line of raw.split(\"\\n\")) {\n if (line.trim() === \"\") continue;\n try {\n const parsed = IngressEntry.safeParse(JSON.parse(line));\n if (parsed.success) entries.push(parsed.data);\n } catch {\n // A truncated final line after a hard kill is expected, not an error.\n }\n }\n return entries;\n }\n\n /**\n * Apply retention: drop the text of community prompts older than the\n * window, keeping the hash, the metadata and the character count.\n *\n * byollm_004 Rev 1: a volunteer must not indefinitely retain strangers'\n * content. The hash stays, so the owner can still prove what ran.\n *\n * @returns how many entries were reduced.\n */\n async applyRetention(now: number): Promise<number> {\n const entries = await this.read();\n const cutoff = now - this.#options.communityPromptDays * 86_400_000;\n let reduced = 0;\n\n const kept = entries.map((entry) => {\n if (entry.type !== \"prompt\") return entry;\n const isCommunity =\n entry.audience === \"named\" || entry.audience === \"public\";\n if (!isCommunity || entry.prompt === undefined || entry.at >= cutoff) {\n return entry;\n }\n reduced += 1;\n const { prompt: _dropped, ...rest } = entry;\n return rest;\n });\n\n if (reduced > 0) {\n // The log is append-only in operation; retention is the one deliberate\n // exception, and it only ever removes text.\n await writeFile(\n this.#options.path,\n `${kept.map((entry) => JSON.stringify(entry)).join(\"\\n\")}\\n`,\n { mode: 0o600 },\n );\n }\n return reduced;\n }\n}\n\n/** SHA-256 of a prompt, hex. */\nexport function hashText(text: string): string {\n return createHash(\"sha256\").update(text, \"utf8\").digest(\"hex\");\n}\n\n/**\n * Replace terminal control sequences before printing untrusted text.\n *\n * Model output and job payloads both reach the owner's terminal through\n * `byollm log` and `byollm status`. Text that can move the cursor or set\n * colours can forge output — the ANSI/log-injection row of byollm_004 §5's\n * corpus. Stored bytes stay verbatim; only the *display* is sanitised, so the\n * log remains an honest record of what actually arrived.\n *\n * Tab and newline are kept: they are legitimate content, not control.\n */\nexport function stripControlChars(text: string): string {\n // eslint-disable-next-line no-control-regex -- matching control characters is the entire purpose\n return text.replace(/[\\u0000-\\u0008\\u000B-\\u001F\\u007F-\\u009F]/g, \"\\uFFFD\");\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { z } from \"zod\";\nimport { normalizeOrigin } from \"./allowlist.js\";\n\n/**\n * One paired server.\n *\n * A daemon may pair with several apps; each pairing is a separate identity\n * with its own token and its own owner. Nothing is shared between them —\n * `owner` from one server means nothing on another\n * ({@link MUSTS.PAIR_ONE_USER}).\n */\nexport const Pairing = z\n .object({\n origin: z.string().min(1),\n runnerId: z.string().min(1),\n /** Bearer token. This file is written 0600 for exactly this reason. */\n token: z.string().min(1),\n /** The app's id for this daemon's owner. */\n owner: z.string().min(1),\n ownerLabel: z.string().optional(),\n pairedAt: z.number().int().positive(),\n })\n .strict();\nexport type Pairing = z.infer<typeof Pairing>;\n\nconst PairingFile = z\n .object({ version: z.literal(1), pairings: z.array(Pairing) })\n .strict();\n\n/** The daemon's paired servers, on disk. */\nexport class Pairings {\n readonly #path: string;\n #pairings: Pairing[] = [];\n #loaded = false;\n\n constructor(path: string) {\n this.#path = path;\n }\n\n async load(): Promise<void> {\n try {\n const parsed = PairingFile.safeParse(\n JSON.parse(await readFile(this.#path, \"utf8\")),\n );\n this.#pairings = parsed.success ? parsed.data.pairings : [];\n } catch {\n this.#pairings = [];\n }\n this.#loaded = true;\n }\n\n list(): readonly Pairing[] {\n this.#assertLoaded();\n return [...this.#pairings];\n }\n\n get(origin: string): Pairing | undefined {\n this.#assertLoaded();\n const normalized = normalizeOrigin(origin);\n return this.#pairings.find(\n (pairing) => normalizeOrigin(pairing.origin) === normalized,\n );\n }\n\n /** Add or replace the pairing for an origin. Re-pairing supersedes. */\n async put(pairing: Pairing): Promise<void> {\n this.#assertLoaded();\n const normalized = normalizeOrigin(pairing.origin);\n this.#pairings = this.#pairings.filter(\n (existing) => normalizeOrigin(existing.origin) !== normalized,\n );\n this.#pairings.push({ ...pairing, origin: normalized });\n await this.#save();\n }\n\n /** Forget a pairing. Returns whether one was removed. */\n async remove(origin: string): Promise<boolean> {\n this.#assertLoaded();\n const normalized = normalizeOrigin(origin);\n const before = this.#pairings.length;\n this.#pairings = this.#pairings.filter(\n (pairing) => normalizeOrigin(pairing.origin) !== normalized,\n );\n if (this.#pairings.length === before) return false;\n await this.#save();\n return true;\n }\n\n #assertLoaded(): void {\n if (!this.#loaded) throw new Error(\"pairings used before load()\");\n }\n\n async #save(): Promise<void> {\n await mkdir(dirname(this.#path), { recursive: true });\n await writeFile(\n this.#path,\n `${JSON.stringify({ version: 1, pairings: this.#pairings }, null, 2)}\\n`,\n // Tokens live here. Nobody else on a shared machine gets to read them.\n { mode: 0o600 },\n );\n }\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/**\n * Where the daemon keeps its state.\n *\n * One directory the owner can `ls`, `cat` and delete. The trust surface is\n * the product (byollm_002), and a trust surface you cannot find is not one.\n */\nexport interface DaemonPaths {\n /** `~/.byollm` — everything below lives here. */\n readonly root: string;\n /** Job routing and backend configuration, owner-authored. */\n readonly config: string;\n /** Paired servers: origin, runner id, token, owner. */\n readonly pairings: string;\n /** The local `named` allowlist — one file, every app. */\n readonly allowlist: string;\n /** Append-only JSONL: every prompt that has run on this machine. */\n readonly ingressLog: string;\n /** Community-job counters, for rate limits and the daily cap. */\n readonly budgets: string;\n /** Set while the owner has the daemon paused. */\n readonly pauseFlag: string;\n /**\n * Per-job scratch directories. A process-class backend runs with its `cwd`\n * set to an empty one of these and nothing else (byollm_004 §2).\n */\n readonly scratch: string;\n}\n\n/** Resolve the daemon's paths, rooted at `~/.byollm` unless overridden. */\nexport function daemonPaths(root = defaultRoot()): DaemonPaths {\n return {\n root,\n config: join(root, \"config.json\"),\n pairings: join(root, \"pairings.json\"),\n allowlist: join(root, \"allow.json\"),\n ingressLog: join(root, \"ingress.log\"),\n budgets: join(root, \"budgets.json\"),\n pauseFlag: join(root, \"paused\"),\n scratch: join(root, \"scratch\"),\n };\n}\n\n/**\n * `BYOLLM_HOME` exists so the conformance kit and the adversarial suite can\n * run real daemons without touching the developer's own `~/.byollm`.\n */\nexport function defaultRoot(): string {\n return process.env[\"BYOLLM_HOME\"] ?? join(homedir(), \".byollm\");\n}\n","import {\n REFUSAL_MESSAGES,\n backendDescriptor,\n matchAudience,\n payloadTextLength,\n type Capability,\n type ClaimedJob,\n type JobOutcome,\n} from \"@byollm/protocol\";\nimport type { Allowlist } from \"./allowlist.js\";\nimport { createBackend, type Backend } from \"./backends/index.js\";\nimport type { Budgets } from \"./budgets.js\";\nimport { ClientError, type ProtocolClient } from \"./client.js\";\nimport { composePrompt } from \"./compose.js\";\nimport type { LoadedConfig, ResolvedRoute } from \"./config.js\";\nimport type { IngressLog } from \"./ingress.js\";\n\n/** What the daemon is currently doing, for `byollm status`. */\nexport interface RunnerStatus {\n readonly origin: string;\n readonly owner: string;\n readonly runnerId: string;\n readonly paused: boolean;\n readonly revoked: boolean;\n readonly activeJobs: number;\n readonly capabilities: readonly Capability[];\n /** Set when the last server contact failed — one of the four truths. */\n readonly lastError?: string;\n readonly completed: number;\n readonly refused: number;\n}\n\nexport interface RunnerOptions {\n readonly client: ProtocolClient;\n readonly runnerId: string;\n readonly owner: string;\n readonly daemonVersion: string;\n readonly loaded: LoadedConfig;\n readonly allowlist: Allowlist;\n readonly budgets: Budgets;\n readonly ingress: IngressLog;\n /** Heartbeat cadence before jitter. */\n readonly heartbeatMs?: number;\n readonly now?: () => number;\n /** Notified on every state change, so the CLI can render progress. */\n readonly onEvent?: (event: RunnerEvent) => void;\n /** Injectable backend factory, so tests need no real model server. */\n readonly backendFactory?: (route: ResolvedRoute) => Backend;\n}\n\nexport type RunnerEvent =\n | { readonly type: \"heartbeat\"; readonly capabilities: number }\n | { readonly type: \"claimed\"; readonly jobId: string; readonly kind: string }\n | {\n readonly type: \"refused\";\n readonly jobId: string;\n readonly reason: string;\n }\n | {\n readonly type: \"finished\";\n readonly jobId: string;\n readonly outcome: string;\n readonly durationMs: number;\n }\n | { readonly type: \"revoked\" }\n | { readonly type: \"error\"; readonly message: string };\n\nconst DEFAULT_HEARTBEAT_MS = 10_000;\n\n/**\n * The daemon's loop: heartbeat, claim, execute, report.\n *\n * Everything that makes the daemon a *trust anchor* rather than a worker\n * happens in {@link Runner.admit} and {@link Runner.runJob} — the local\n * audience check, the budget check, and the ingress write that precedes\n * execution. The loop itself is deliberately dull.\n */\nexport class Runner {\n readonly #options: RunnerOptions;\n readonly #backends = new Map<string, Backend>();\n readonly #active = new Map<string, AbortController>();\n readonly #now: () => number;\n #capabilities: Capability[] = [];\n #paused = false;\n #revoked = false;\n #stopped = false;\n #lastError: string | undefined;\n #completed = 0;\n #refused = 0;\n\n constructor(options: RunnerOptions) {\n this.#options = options;\n this.#now = options.now ?? Date.now;\n }\n\n status(): RunnerStatus {\n return {\n origin: this.#options.client.origin,\n owner: this.#options.owner,\n runnerId: this.#options.runnerId,\n paused: this.#paused,\n revoked: this.#revoked,\n activeJobs: this.#active.size,\n capabilities: [...this.#capabilities],\n ...(this.#lastError === undefined ? {} : { lastError: this.#lastError }),\n completed: this.#completed,\n refused: this.#refused,\n };\n }\n\n pause(): void {\n this.#paused = true;\n }\n\n resume(): void {\n this.#paused = false;\n }\n\n /**\n * Build the capability matrix: owner config intersected with what is\n * actually reachable and healthy right now\n * ({@link MUSTS.CAPABILITY_IS_DETECTED}).\n *\n * A configured route whose backend is down simply does not appear. The\n * daemon then receives no work for it, which is the correct outcome and one\n * the owner can see in `byollm status`.\n */\n async detectCapabilities(): Promise<Capability[]> {\n const capabilities: Capability[] = [];\n\n for (const route of this.#options.loaded.routes) {\n const backend = this.#backendFor(route);\n const health = await backend.health();\n if (!health.healthy) continue;\n\n // If the backend enumerates its models, honour that: advertising a\n // model the server does not have would be advertising a lie.\n if (\n health.models.length > 0 &&\n !modelPresent(health.models, route.model)\n ) {\n continue;\n }\n\n capabilities.push({\n kind: route.kind,\n backendId: route.backendId,\n backendClass: route.backendClass,\n model: route.model,\n offerScope: route.offerScope,\n });\n }\n\n this.#capabilities = capabilities;\n return capabilities;\n }\n\n #backendFor(route: ResolvedRoute): Backend {\n const key = `${route.backendKey}:${route.backendId}`;\n let backend = this.#backends.get(key);\n if (!backend) {\n backend =\n this.#options.backendFactory?.(route) ??\n createBackend(route.backendId, {\n baseUrl: route.baseUrl,\n apiKeyEnv: route.apiKeyEnv,\n });\n this.#backends.set(key, backend);\n }\n return backend;\n }\n\n #routeFor(kind: string): ResolvedRoute | undefined {\n return this.#options.loaded.routes.find((route) => route.kind === kind);\n }\n\n /**\n * Decide whether this machine will run a claimed job.\n *\n * The server already applied its own version of the audience rules, and\n * that is not what this checks. This is the daemon enforcing against the\n * server: the local `named` allowlist\n * ({@link MUSTS.NAMED_LOCAL_ALLOWLIST}), the subscription self-lock, and\n * the owner's community budgets. A job that fails here is released with\n * reason `refused`, which the server remembers so it is never offered back.\n */\n admit(job: ClaimedJob): { ok: true } | { ok: false; reason: string } {\n const route = this.#routeFor(job.kind);\n if (!route) {\n // An unknown or unrouted kind is refused, never guessed\n // ({@link MUSTS.KIND_TYPED_ONLY}).\n return { ok: false, reason: REFUSAL_MESSAGES[\"no-capability\"] };\n }\n\n const match = matchAudience(\n {\n owner: job.owner,\n audience: job.audience,\n audienceAllow: job.audienceAllow,\n },\n {\n owner: this.#options.owner,\n offerScope: route.offerScope,\n account: backendDescriptor(route.backendId).account,\n // The daemon's own list — the whole point of Rev 1 §B.\n locallyAllows: this.#options.allowlist.predicateFor(\n this.#options.client.origin,\n ),\n },\n );\n if (!match.ok) {\n return { ok: false, reason: REFUSAL_MESSAGES[match.refusal] };\n }\n\n if (job.owner !== this.#options.owner) {\n const decision = this.#options.budgets.check(\n this.#now(),\n payloadTextLength({\n kind: job.kind,\n payload: job.payload,\n } as Parameters<typeof payloadTextLength>[0]),\n );\n if (!decision.ok) return { ok: false, reason: decision.detail };\n }\n\n return { ok: true };\n }\n\n /**\n * Execute one admitted job.\n *\n * Order is load-bearing: the ingress write is awaited *before* the backend\n * is touched ({@link MUSTS.INGRESS_LOGGED_BEFORE_EXECUTION}), so a job that\n * hangs the machine still leaves a record of what it was.\n */\n async runJob(job: ClaimedJob): Promise<JobOutcome> {\n const route = this.#routeFor(job.kind);\n if (!route) {\n return {\n outcome: \"error\",\n code: \"no-capability\",\n message: \"this machine has no route for that job kind\",\n retryable: false,\n };\n }\n\n const controller = new AbortController();\n this.#active.set(job.id, controller);\n\n const prompt = composePrompt(job);\n const community = job.owner !== this.#options.owner;\n const limits = this.#options.loaded.config;\n\n await this.#options.ingress.recordPrompt({\n at: this.#now(),\n origin: this.#options.client.origin,\n jobId: job.id,\n kind: job.kind,\n audience: job.audience,\n owner: job.owner,\n backendId: route.backendId,\n backendClass: route.backendClass,\n model: route.model,\n prompt,\n });\n\n if (community) await this.#options.budgets.record(this.#now());\n\n try {\n const backend = this.#backendFor(route);\n const result = await backend.execute({\n prompt,\n model: route.model,\n // Community jobs run under the owner's tighter ceiling.\n timeoutMs: community\n ? Math.min(\n limits.community.maxWallClockMs,\n limits.limits.maxWallClockMs,\n )\n : limits.limits.maxWallClockMs,\n maxOutputBytes: community\n ? Math.min(\n limits.community.maxOutputBytes,\n limits.limits.maxOutputBytes,\n )\n : limits.limits.maxOutputBytes,\n signal: controller.signal,\n });\n\n const outcome: JobOutcome = result.ok\n ? { outcome: \"ok\", text: result.text }\n : result.code === \"canceled\"\n ? { outcome: \"canceled\" }\n : {\n outcome: \"error\",\n code: result.code,\n message: result.message,\n retryable: result.retryable,\n };\n\n await this.#options.ingress.recordOutcome({\n at: this.#now(),\n jobId: job.id,\n outcome: outcome.outcome,\n durationMs: result.durationMs,\n outputChars: result.ok ? result.text.length : 0,\n ...(result.ok ? {} : { detail: result.message }),\n });\n\n this.#completed += 1;\n this.#options.onEvent?.({\n type: \"finished\",\n jobId: job.id,\n outcome: outcome.outcome,\n durationMs: result.durationMs,\n });\n return outcome;\n } finally {\n this.#active.delete(job.id);\n }\n }\n\n /** Abort a job's in-flight backend call ({@link MUSTS.CANCEL_HONORED}). */\n cancelJob(jobId: string): void {\n this.#active.get(jobId)?.abort();\n }\n\n /** Abort everything — revocation, or shutdown. */\n cancelAll(): void {\n for (const controller of this.#active.values()) controller.abort();\n }\n\n /**\n * Run until stopped.\n *\n * Resumable and idempotent by job id: a daemon that dies mid-job loses\n * nothing, because the server reclaims the lease and offers the job again.\n */\n async run(signal: AbortSignal): Promise<void> {\n const heartbeatMs = this.#options.heartbeatMs ?? DEFAULT_HEARTBEAT_MS;\n\n while (!signal.aborted && !this.#stopped) {\n try {\n await this.tick();\n this.#lastError = undefined;\n } catch (error) {\n this.#lastError =\n error instanceof Error ? error.message : \"unknown error\";\n this.#options.onEvent?.({\n type: \"error\",\n message: this.#lastError,\n });\n if (error instanceof ClientError && error.kind === \"revoked\") {\n this.#revoked = true;\n this.cancelAll();\n this.#options.onEvent?.({ type: \"revoked\" });\n return;\n }\n const backoff =\n error instanceof ClientError && error.retryAfter !== undefined\n ? error.retryAfter * 1000\n : heartbeatMs;\n await sleep(backoff, signal);\n continue;\n }\n // Jitter so a fleet of daemons does not synchronise into a thundering\n // herd against one server.\n await sleep(heartbeatMs * (0.85 + Math.random() * 0.3), signal);\n }\n }\n\n /** One heartbeat-and-claim cycle. Exposed so tests can step deterministically. */\n async tick(): Promise<void> {\n const capabilities = await this.detectCapabilities();\n\n const heartbeat = await this.#options.client.heartbeat({\n runnerId: this.#options.runnerId,\n daemonVersion: this.#options.daemonVersion,\n capabilities,\n activeJobIds: [...this.#active.keys()],\n paused: this.#paused,\n });\n this.#options.onEvent?.({\n type: \"heartbeat\",\n capabilities: capabilities.length,\n });\n\n if (heartbeat.revoked) {\n this.#revoked = true;\n this.cancelAll();\n this.#options.onEvent?.({ type: \"revoked\" });\n this.#stopped = true;\n return;\n }\n\n // A job the server says we lost must be abandoned, not finished\n // ({@link MUSTS.LEASE_HONORED}).\n for (const jobId of heartbeat.lost) this.cancelJob(jobId);\n for (const jobId of heartbeat.cancel) this.cancelJob(jobId);\n\n if (this.#paused || capabilities.length === 0) return;\n\n const free = this.#options.loaded.config.concurrency - this.#active.size;\n if (free <= 0) return;\n\n const { jobs } = await this.#options.client.claim({\n runnerId: this.#options.runnerId,\n capabilities,\n max: free,\n });\n\n // Not awaited: claimed jobs run concurrently up to the owner's limit, and\n // the loop keeps heartbeating so their leases stay alive.\n //\n // The `catch` is load-bearing. Without it, a failure in the background\n // handler — an ingress write that cannot land because the disk is full or\n // the state directory has gone — becomes an unhandled rejection and takes\n // the whole daemon down. The lease lapses instead and the server offers\n // the job again, which is the recovery the protocol is built around.\n for (const job of jobs) {\n void this.#handle(job).catch((error: unknown) => {\n this.#lastError =\n error instanceof Error ? error.message : \"unknown error\";\n this.#options.onEvent?.({ type: \"error\", message: this.#lastError });\n });\n }\n }\n\n async #handle(job: ClaimedJob): Promise<void> {\n this.#options.onEvent?.({\n type: \"claimed\",\n jobId: job.id,\n kind: job.kind,\n });\n\n const admission = this.admit(job);\n if (!admission.ok) {\n this.#refused += 1;\n await this.#options.ingress.recordOutcome({\n at: this.#now(),\n jobId: job.id,\n outcome: \"refused\",\n detail: admission.reason,\n });\n this.#options.onEvent?.({\n type: \"refused\",\n jobId: job.id,\n reason: admission.reason,\n });\n await this.#safely(() =>\n this.#options.client.release({\n runnerId: this.#options.runnerId,\n jobIds: [job.id],\n reason: \"refused\",\n }),\n );\n return;\n }\n\n const route = this.#routeFor(job.kind);\n const outcome = await this.runJob(job);\n\n await this.#safely(() =>\n this.#options.client.result({\n runnerId: this.#options.runnerId,\n jobId: job.id,\n outcome,\n model: route?.model ?? \"unknown\",\n backendClass: route?.backendClass ?? \"http\",\n durationMs: 0,\n }),\n );\n }\n\n /**\n * Report-and-forget.\n *\n * A failed *report* must not crash the loop or re-run the job: the lease\n * will lapse and the server will offer the work again, which is exactly the\n * recovery the protocol is built around.\n */\n async #safely(action: () => Promise<unknown>): Promise<void> {\n try {\n await action();\n } catch (error) {\n this.#lastError =\n error instanceof Error ? error.message : \"unknown error\";\n }\n }\n\n /** Release everything on shutdown, so nothing waits for a lease to lapse. */\n async shutdown(reason: \"shutdown\" | \"pause\"): Promise<void> {\n this.#stopped = true;\n const jobIds = [...this.#active.keys()];\n this.cancelAll();\n if (jobIds.length === 0) return;\n await this.#safely(() =>\n this.#options.client.release({\n runnerId: this.#options.runnerId,\n jobIds,\n reason,\n }),\n );\n }\n}\n\n/** Case-insensitive model match that tolerates Ollama's `:latest` suffix. */\nfunction modelPresent(models: readonly string[], wanted: string): boolean {\n const target = wanted.toLowerCase();\n return models.some((model) => {\n const id = model.toLowerCase();\n return (\n id === target || id === `${target}:latest` || `${id}:latest` === target\n );\n });\n}\n\nfunction sleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n signal.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timer);\n resolve();\n },\n { once: true },\n );\n });\n}\n","import { BACKEND_IDS, type BackendId } from \"@byollm/protocol\";\nimport { ClaudeCliBackend } from \"./claude-cli.js\";\nimport { OpenAiHttpBackend } from \"./openai-http.js\";\nimport type { Backend, BackendInit } from \"./types.js\";\n\n/**\n * Construct a backend instance.\n *\n * The switch is exhaustive over {@link BackendId}, so adding a backend to the\n * protocol registry without implementing it here is a compile error rather\n * than a runtime surprise — and adding one without adversarial rows fails the\n * suite's coverage check.\n */\nexport function createBackend(id: BackendId, init: BackendInit): Backend {\n switch (id) {\n case \"openai-http\":\n return new OpenAiHttpBackend(init);\n case \"claude-cli\":\n return new ClaudeCliBackend();\n }\n}\n\n/** Every backend the daemon can construct. */\nexport const IMPLEMENTED_BACKEND_IDS: readonly BackendId[] = BACKEND_IDS;\n\nexport { ClaudeCliBackend, childEnv, claudeArgv } from \"./claude-cli.js\";\nexport { OpenAiHttpBackend } from \"./openai-http.js\";\nexport type {\n Backend,\n BackendErrorCode,\n BackendHealth,\n BackendInit,\n BackendRequest,\n BackendResult,\n} from \"./types.js\";\n","import { execFile, spawn } from \"node:child_process\";\nimport { mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { BackendClass, BackendId } from \"@byollm/protocol\";\nimport type {\n Backend,\n BackendHealth,\n BackendRequest,\n BackendResult,\n} from \"./types.js\";\n\n/**\n * The exact argv this backend ever runs, minus the model.\n *\n * A frozen literal, not a builder, so there is no code path that appends to\n * it and no mechanism to pass job-supplied arguments\n * ({@link MUSTS.NO_SHELL_INTERPOLATION}). The adversarial suite asserts that\n * every hostile payload it throws produces exactly this argv.\n *\n * - `--print` — non-interactive, answer and exit.\n * - `--output-format text` — plain text, no envelope to misparse.\n * - `--tools \"\"` — the CLI's own switch for *disabling every built-in tool*.\n * byollm_004 §2 requires the model have no tools; this is the flag that\n * delivers it. Verified against the shipped CLI, not assumed.\n * - `--strict-mcp-config` with an empty `--mcp-config` — no MCP servers, and\n * none inherited from the user's own settings.\n * - `--no-session-persistence` — a job leaves no session behind.\n */\nconst FIXED_ARGV = Object.freeze([\n \"--print\",\n \"--output-format\",\n \"text\",\n \"--tools\",\n \"\",\n \"--strict-mcp-config\",\n \"--mcp-config\",\n '{\"mcpServers\":{}}',\n \"--no-session-persistence\",\n]);\n\n/**\n * Environment variables a `claude` child is allowed to see.\n *\n * Everything else is dropped, so a prompt that says \"read your environment\"\n * finds nothing worth having ({@link MUSTS.STRIPPED_CHILD_ENV}).\n *\n * `HOME` is present and that is a deliberate, documented compromise: the CLI\n * reads its subscription credentials from the user's own config directory, so\n * removing `HOME` would remove the authentication this backend exists to use.\n * The honest statement is in `docs/security.md` — the child can reach the\n * filesystem the user can reach, and what stops it doing anything with that\n * is having no tools, not the environment.\n *\n * `ANTHROPIC_API_KEY` is deliberately **absent**: byollm_002 requires that\n * billing cannot silently move from the subscription to a metered key.\n */\nconst ENV_ALLOWLIST = Object.freeze([\n \"PATH\",\n \"HOME\",\n \"LANG\",\n \"LC_ALL\",\n \"TZ\",\n \"TMPDIR\",\n]);\n\n/** Build the child's environment from the allowlist. */\nexport function childEnv(\n source: NodeJS.ProcessEnv = process.env,\n): Record<string, string> {\n const env: Record<string, string> = {};\n for (const name of ENV_ALLOWLIST) {\n const value = source[name];\n if (value !== undefined) env[name] = value;\n }\n // Signals to the CLI that it is not attached to a terminal, so it never\n // tries to render interactive UI into a pipe.\n env[\"CI\"] = \"1\";\n return env;\n}\n\n/** The argv this backend would run for a given model. Exported for the suite. */\nexport function claudeArgv(model: string): readonly string[] {\n return Object.freeze([...FIXED_ARGV, \"--model\", model]);\n}\n\n/**\n * The process-class backend: the user's own `claude` CLI, on their own\n * subscription.\n *\n * Subscription-class, so its offer scope is locked to `self`\n * ({@link MUSTS.SUBSCRIPTION_SELF_LOCK}) — one account runs one person's work.\n *\n * Every requirement of byollm_004 §2 applies here and is implemented here:\n * fixed argv, prompt on stdin, stripped environment, empty scratch `cwd`, no\n * inherited descriptors beyond the three std streams, hard timeout, hard\n * output cap.\n */\nexport class ClaudeCliBackend implements Backend {\n readonly id: BackendId = \"claude-cli\";\n readonly class: BackendClass = \"process\";\n readonly #binary: string;\n\n /**\n * @param binary - which executable to run. Defaults to `claude` and is\n * **not reachable from configuration**: {@link createBackend} constructs\n * this with no arguments, and {@link BackendInit} has no field for it. It\n * exists so the adversarial suite can substitute a probe that reports the\n * argv, environment, cwd and stdin it actually received — which is the only\n * way to *prove* byollm_004 §2 rather than assert it.\n */\n constructor(binary = \"claude\") {\n this.#binary = binary;\n }\n\n async health(): Promise<BackendHealth> {\n const version = await new Promise<string | null>((resolve) => {\n // execFile, never exec: no shell is involved even for our own fixed\n // arguments (the eslint rule bans the shell-invoking variants outright).\n execFile(\n this.#binary,\n [\"--version\"],\n { timeout: 10_000, env: childEnv() },\n (error, stdout) => {\n resolve(error ? null : stdout.trim());\n },\n );\n });\n\n if (version === null) {\n return {\n healthy: false,\n models: [],\n detail:\n \"the `claude` CLI is not installed or not on PATH \" +\n \"(https://claude.com/claude-code)\",\n };\n }\n // The CLI does not enumerate models, and inventing a list would breach\n // \"never advertise what isn't real\". The configured model is the claim,\n // and a wrong one surfaces as `model-not-found` on first use.\n return { healthy: true, models: [] };\n }\n\n async execute(request: BackendRequest): Promise<BackendResult> {\n const started = Date.now();\n // An empty directory of our own making. The child's `cwd` is never the\n // daemon's, never the user's home, and never anything a payload named.\n const scratch = await mkdtemp(join(tmpdir(), \"byollm-job-\"));\n\n try {\n return await this.#spawn(request, scratch, started);\n } finally {\n await rm(scratch, { recursive: true, force: true });\n }\n }\n\n async #spawn(\n request: BackendRequest,\n scratch: string,\n started: number,\n ): Promise<BackendResult> {\n return new Promise<BackendResult>((resolve) => {\n // Check before spawning, not only via the listener below: a job\n // cancelled between the claim and this line arrives with its signal\n // already aborted, and `addEventListener(\"abort\")` never fires for a\n // signal that has already fired. Without this the child would spawn and\n // run to completion after the owner had already said stop.\n if (request.signal.aborted) {\n resolve({\n ok: false,\n code: \"canceled\",\n message: \"the job was canceled before it started\",\n retryable: false,\n durationMs: Date.now() - started,\n });\n return;\n }\n\n const child = spawn(this.#binary, claudeArgv(request.model), {\n cwd: scratch,\n env: childEnv(),\n // Exactly the three std streams. Nothing else is inherited, so the\n // child cannot reach a descriptor the daemon happens to hold open.\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n // No shell, ever. With `shell: false` the argv array is passed to\n // execvp verbatim and metacharacters in it are just bytes.\n shell: false,\n detached: false,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n let outputBytes = 0;\n let settled = false;\n let exited = false;\n let reason: \"timeout\" | \"canceled\" | \"output-too-large\" | null = null;\n\n const finish = (result: BackendResult): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n request.signal.removeEventListener(\"abort\", onAbort);\n resolve(result);\n };\n\n const kill = (why: typeof reason): void => {\n reason = why;\n // SIGTERM first, SIGKILL shortly after: a wedged child must not be\n // able to outlive its budget by ignoring the polite signal.\n //\n // The escalation is gated on `exited`, which we set from the `close`\n // event, and NOT on `child.killed` — that flag means \"a signal was\n // sent\", not \"the process died\", so gating on it would mean the\n // SIGKILL never fires against exactly the child that ignores SIGTERM.\n child.kill(\"SIGTERM\");\n setTimeout(() => {\n if (!exited) child.kill(\"SIGKILL\");\n }, 2_000).unref();\n };\n\n const timer = setTimeout(() => {\n kill(\"timeout\");\n }, request.timeoutMs);\n\n const onAbort = (): void => {\n kill(\"canceled\");\n };\n request.signal.addEventListener(\"abort\", onAbort, { once: true });\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n outputBytes += chunk.byteLength;\n if (outputBytes > request.maxOutputBytes) {\n kill(\"output-too-large\");\n return;\n }\n stdout += chunk.toString(\"utf8\");\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n // Bounded independently: a chatty stderr must not exhaust memory\n // either, and it is only ever used for a diagnostic message.\n if (stderr.length < 8_192) stderr += chunk.toString(\"utf8\");\n });\n\n child.on(\"error\", (error: Error) => {\n finish({\n ok: false,\n code: \"backend-unreachable\",\n message: `could not start the claude CLI: ${error.message}`,\n retryable: false,\n durationMs: Date.now() - started,\n });\n });\n\n child.on(\"close\", (code) => {\n exited = true;\n const durationMs = Date.now() - started;\n\n if (reason === \"canceled\") {\n finish({\n ok: false,\n code: \"canceled\",\n message: \"the job was canceled\",\n retryable: false,\n durationMs,\n });\n return;\n }\n if (reason === \"timeout\") {\n finish({\n ok: false,\n code: \"timeout\",\n message: `the model did not answer within ${String(request.timeoutMs)}ms`,\n retryable: true,\n durationMs,\n });\n return;\n }\n if (reason === \"output-too-large\") {\n finish({\n ok: false,\n code: \"output-too-large\",\n message: `the model produced more than ${String(request.maxOutputBytes)} bytes`,\n retryable: false,\n durationMs,\n });\n return;\n }\n if (code !== 0) {\n finish({\n ok: false,\n code: \"backend-error\",\n message:\n stderr.trim() === \"\"\n ? `the claude CLI exited with status ${String(code)}`\n : `the claude CLI failed: ${firstLine(stderr)}`,\n retryable: false,\n durationMs,\n });\n return;\n }\n finish({ ok: true, text: stdout, durationMs });\n });\n\n // The prompt goes here and nowhere else: on stdin, as bytes, after the\n // argv is already fixed. This is the line byollm_004 §2 is about.\n child.stdin.on(\"error\", () => {\n // A child that died before reading stdin surfaces through `close`.\n });\n child.stdin.end(request.prompt, \"utf8\");\n });\n }\n}\n\n/** First line of stderr, for a one-line diagnostic. */\nfunction firstLine(text: string): string {\n return text.trim().split(\"\\n\")[0] ?? \"\";\n}\n","import type { BackendClass, BackendId } from \"@byollm/protocol\";\nimport { checkBaseUrl } from \"../ssrf.js\";\nimport type {\n Backend,\n BackendHealth,\n BackendInit,\n BackendRequest,\n BackendResult,\n} from \"./types.js\";\n\n/**\n * The HTTP-class backend: any server speaking OpenAI-compatible\n * `/v1/chat/completions`.\n *\n * One implementation covers Ollama, `mlx_lm.server`, llama.cpp server and\n * vLLM (byollm_001 Rev 1 §A) — the collapse that puts MLX inference in v1.\n *\n * **Why this is the safest class.** It spawns nothing, so byollm_004 §2's\n * argv, stdin, environment and sandbox requirements do not apply *by\n * construction* rather than by discipline. The prompt travels as a JSON\n * string in a request body; there is no command line for it to escape into\n * because there is no command line.\n *\n * What remains is the destination, and that is nailed down: the base URL\n * comes from owner config, is validated once at load and again here, and\n * redirects are refused so a permitted URL cannot become a forbidden one in\n * flight ({@link MUSTS.HTTP_BASE_URL_SAFE}).\n */\nexport class OpenAiHttpBackend implements Backend {\n readonly id: BackendId = \"openai-http\";\n readonly class: BackendClass = \"http\";\n readonly #baseUrl: URL;\n readonly #apiKeyEnv: string | undefined;\n\n constructor(init: BackendInit) {\n if (init.baseUrl === undefined) {\n throw new Error(\"openai-http backend requires a baseUrl\");\n }\n const check = checkBaseUrl(init.baseUrl);\n if (!check.ok) {\n throw new Error(`refusing base URL: ${check.detail}`);\n }\n this.#baseUrl = check.url;\n this.#apiKeyEnv = init.apiKeyEnv;\n }\n\n /**\n * Build a URL under the configured base.\n *\n * The path is a hardcoded literal from this file — never anything derived\n * from a job — and the result is re-checked against the base's origin so a\n * surprising `baseUrl` (say, one with a `..` path) cannot walk elsewhere.\n */\n #endpoint(path: \"chat/completions\" | \"models\"): URL {\n const base = this.#baseUrl.href.endsWith(\"/\")\n ? this.#baseUrl.href\n : `${this.#baseUrl.href}/`;\n const url = new URL(path, base);\n if (url.origin !== this.#baseUrl.origin) {\n throw new Error(\"computed endpoint left the configured origin\");\n }\n return url;\n }\n\n #headers(): Record<string, string> {\n const headers: Record<string, string> = {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n };\n if (this.#apiKeyEnv !== undefined) {\n const key = process.env[this.#apiKeyEnv];\n if (key !== undefined && key !== \"\") {\n headers[\"authorization\"] = `Bearer ${key}`;\n }\n }\n return headers;\n }\n\n async health(): Promise<BackendHealth> {\n try {\n const response = await fetch(this.#endpoint(\"models\"), {\n method: \"GET\",\n headers: this.#headers(),\n redirect: \"error\",\n signal: AbortSignal.timeout(5_000),\n });\n if (!response.ok) {\n return {\n healthy: false,\n models: [],\n detail: `model list returned HTTP ${String(response.status)}`,\n };\n }\n const body: unknown = await response.json();\n return { healthy: true, models: extractModelIds(body) };\n } catch (error) {\n return {\n healthy: false,\n models: [],\n detail: describeFetchError(error, this.#baseUrl.origin),\n };\n }\n }\n\n async execute(request: BackendRequest): Promise<BackendResult> {\n const started = Date.now();\n // One timeout governs the call whether it stalls before or during the\n // response body — a server that accepts and then dribbles forever must\n // not be able to wedge the machine.\n const timeout = AbortSignal.timeout(request.timeoutMs);\n const signal = AbortSignal.any([request.signal, timeout]);\n\n try {\n const response = await fetch(this.#endpoint(\"chat/completions\"), {\n method: \"POST\",\n headers: this.#headers(),\n // The payload is a JSON string field. Nothing about it is parsed as\n // configuration, and `model` comes from owner config.\n body: JSON.stringify({\n model: request.model,\n messages: [{ role: \"user\", content: request.prompt }],\n stream: false,\n }),\n redirect: \"error\",\n signal,\n });\n\n if (response.status === 401 || response.status === 403) {\n return this.#fail(\n \"unauthorized\",\n \"the model server rejected our credentials\",\n false,\n started,\n );\n }\n if (response.status === 404) {\n return this.#fail(\n \"model-not-found\",\n `the model server does not know \"${request.model}\"`,\n false,\n started,\n );\n }\n if (!response.ok) {\n return this.#fail(\n \"backend-error\",\n `the model server returned HTTP ${String(response.status)}`,\n response.status >= 500,\n started,\n );\n }\n\n const text = await readCapped(response, request.maxOutputBytes, signal);\n if (text === null) {\n // A hostile or broken local model producing unbounded output must not\n // be able to exhaust memory — byollm_004 §5's zip-bomb row.\n return this.#fail(\n \"output-too-large\",\n `the model produced more than ${String(request.maxOutputBytes)} bytes`,\n false,\n started,\n );\n }\n\n const content = extractContent(text);\n if (content === null) {\n return this.#fail(\n \"backend-error\",\n \"the model server's response was not in OpenAI chat-completion shape\",\n false,\n started,\n );\n }\n return { ok: true, text: content, durationMs: Date.now() - started };\n } catch (error) {\n if (request.signal.aborted) {\n return this.#fail(\"canceled\", \"the job was canceled\", false, started);\n }\n if (isAbort(error)) {\n return this.#fail(\n \"timeout\",\n `the model did not answer within ${String(request.timeoutMs)}ms`,\n true,\n started,\n );\n }\n return this.#fail(\n \"backend-unreachable\",\n describeFetchError(error, this.#baseUrl.origin),\n true,\n started,\n );\n }\n }\n\n #fail(\n code: Exclude<BackendResult & { ok: false }, never>[\"code\"],\n message: string,\n retryable: boolean,\n started: number,\n ): BackendResult {\n return {\n ok: false,\n code,\n message,\n retryable,\n durationMs: Date.now() - started,\n };\n }\n}\n\n/**\n * Read a response body, refusing to buffer past `maxBytes`.\n *\n * `response.text()` would happily allocate whatever the server sends. Reading\n * the stream and stopping at the cap is what makes the ceiling real.\n *\n * @returns the text, or null if the cap was exceeded.\n */\nasync function readCapped(\n response: Response,\n maxBytes: number,\n signal: AbortSignal,\n): Promise<string | null> {\n const body = response.body;\n if (body === null) return \"\";\n\n // `getReader()` is typed as `any` chunks under this lib target; the stream\n // is bytes, and saying so is what lets the cap arithmetic below be checked.\n const reader = (body as ReadableStream<Uint8Array>).getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n try {\n for (;;) {\n signal.throwIfAborted();\n const { done, value } = await reader.read();\n if (done) break;\n total += value.byteLength;\n if (total > maxBytes) {\n await reader.cancel();\n return null;\n }\n chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n return new TextDecoder().decode(concat(chunks, total));\n}\n\nfunction concat(chunks: readonly Uint8Array[], total: number): Uint8Array {\n const out = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n out.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return out;\n}\n\n/** Pull the assistant text out of an OpenAI chat-completion response. */\nfunction extractContent(raw: string): string | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) return null;\n const choices = (parsed as { choices?: unknown }).choices;\n if (!Array.isArray(choices) || choices.length === 0) return null;\n const message = (choices[0] as { message?: unknown }).message;\n if (typeof message !== \"object\" || message === null) return null;\n const content = (message as { content?: unknown }).content;\n return typeof content === \"string\" ? content : null;\n}\n\n/** Model ids from an OpenAI `/v1/models` response. */\nfunction extractModelIds(body: unknown): string[] {\n if (typeof body !== \"object\" || body === null) return [];\n const data = (body as { data?: unknown }).data;\n if (!Array.isArray(data)) return [];\n return data\n .map((entry) =>\n typeof entry === \"object\" && entry !== null\n ? (entry as { id?: unknown }).id\n : undefined,\n )\n .filter((id): id is string => typeof id === \"string\");\n}\n\nfunction isAbort(error: unknown): boolean {\n return (\n error instanceof Error &&\n (error.name === \"AbortError\" || error.name === \"TimeoutError\")\n );\n}\n\n/**\n * A reachability failure the owner can act on.\n *\n * Deliberately names the origin and not the underlying error text, which for\n * `fetch` is often a bare \"fetch failed\" that tells nobody anything.\n */\nfunction describeFetchError(error: unknown, origin: string): string {\n const cause =\n error instanceof Error && \"cause\" in error && error.cause instanceof Error\n ? error.cause.message\n : error instanceof Error\n ? error.message\n : \"unknown error\";\n return `could not reach the model server at ${origin} (${cause})`;\n}\n","import type { ClaimedJob } from \"@byollm/protocol\";\n\n/**\n * Reduce a job's payload to the single string a backend receives.\n *\n * This is the narrowest point in the daemon: everything upstream deals in a\n * job, everything downstream deals in text and an owner-chosen model. By\n * construction there is nothing left for a payload to influence.\n *\n * **On `system`.** byollm_004 §2 forbids payload text on a command line, and\n * the `claude` CLI's only system-prompt input is the argv flag\n * `--system-prompt` — so a payload's `system` can never be passed that way.\n * It is folded into the stdin text instead, under a plain delimiter. That\n * costs a little role fidelity on process-class backends and is documented\n * rather than papered over; HTTP-class backends could carry the role natively\n * but use the same composition so a job produces identical text on either\n * class, which is what makes results comparable across runners.\n */\nexport function composePrompt(job: ClaimedJob): string {\n if (job.kind === \"llm.generate\") {\n const payload = job.payload as { prompt: string; system?: string };\n return joinSections([systemSection(payload.system), payload.prompt]);\n }\n\n const payload = job.payload as {\n messages: { role: string; content: string }[];\n system?: string;\n };\n const turns = payload.messages\n .map((message) => `${roleLabel(message.role)}: ${message.content}`)\n .join(\"\\n\\n\");\n return joinSections([systemSection(payload.system), turns]);\n}\n\nfunction systemSection(system: string | undefined): string | undefined {\n if (system === undefined || system.trim() === \"\") return undefined;\n return `System instructions:\\n${system}`;\n}\n\nfunction roleLabel(role: string): string {\n switch (role) {\n case \"assistant\":\n return \"Assistant\";\n case \"system\":\n return \"System\";\n default:\n return \"User\";\n }\n}\n\nfunction joinSections(sections: readonly (string | undefined)[]): string {\n return sections.filter((section) => section !== undefined).join(\"\\n\\n\");\n}\n","/**\n * `byollm` — what end users run.\n *\n * The CLI (`byollm connect`, `status`, `log`, `pause`, `allow`) is the\n * product surface; this module is the same machinery as a library, so the\n * conformance kit can drive a real daemon in-process instead of shelling out.\n *\n * @packageDocumentation\n */\n\nexport { Allowlist, normalizeOrigin, type AllowEntry } from \"./allowlist.js\";\n\nexport { main, runCli, type CliIo, type ExitCode } from \"./cli.js\";\n\nexport {\n ClaudeCliBackend,\n IMPLEMENTED_BACKEND_IDS,\n OpenAiHttpBackend,\n childEnv,\n claudeArgv,\n createBackend,\n type Backend,\n type BackendErrorCode,\n type BackendHealth,\n type BackendInit,\n type BackendRequest,\n type BackendResult,\n} from \"./backends/index.js\";\n\nexport { Budgets, type BudgetDecision, type BudgetRefusal } from \"./budgets.js\";\n\nexport {\n ClientError,\n ProtocolClient,\n type ClientErrorKind,\n type ClientOptions,\n} from \"./client.js\";\n\nexport { composePrompt } from \"./compose.js\";\n\nexport {\n DEFAULT_CONFIG,\n DaemonConfig,\n loadConfig,\n resolveConfig,\n type BackendConfig,\n type CommunityBudget,\n type ConfigProblem,\n type IngressRetention,\n type LoadedConfig,\n type Limits,\n type ResolvedRoute,\n type RouteConfig,\n} from \"./config.js\";\n\nexport {\n connect,\n currentPlatform,\n type ConnectOptions,\n type ConnectResult,\n} from \"./connect.js\";\n\nexport {\n IngressLog,\n hashText,\n stripControlChars,\n type IngressEntry,\n type IngressOptions,\n type OutcomeEntry,\n type PromptEntry,\n} from \"./ingress.js\";\n\nexport { daemonPaths, defaultRoot, type DaemonPaths } from \"./paths.js\";\n\nexport { Pairings, type Pairing } from \"./pairings.js\";\n\nexport {\n Runner,\n type RunnerEvent,\n type RunnerOptions,\n type RunnerStatus,\n} from \"./runner.js\";\n\nexport {\n BASE_URL_REFUSAL_MESSAGES,\n checkBaseUrl,\n type BaseUrlCheck,\n type BaseUrlRefusal,\n} from \"./ssrf.js\";\n\n/**\n * This daemon's version, reported on pairing and on every heartbeat.\n *\n * Kept in step with `package.json` by a test rather than by a build-time\n * define: an app's runner list shows this string, so a stale one is a lie\n * told to every user, and a literal that a test pins cannot drift quietly.\n */\nexport const DAEMON_VERSION = \"0.1.0-alpha.0\";\n"],"mappings":"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","names":["mkdir","rm","writeFile","mkdir","readFile","writeFile","dirname","z","readFile","z","z","readFile","sleep","mkdir","readFile","writeFile","dirname","z","mkdir","readFile","writeFile","dirname","z","z","readFile","mkdir","dirname","writeFile","backendDescriptor","join","payload","backendDescriptor","firstLine","mkdir","writeFile","rm"]}
|