Files
bot-agents/src/opencode.ts
T
Danny Kim ea20f6d629 Show the selected bot profile and add OpenRouter fallback (#18)
Uses Codex first, then Claude, then OpenCode through OpenRouter when quota is exhausted.

Every generated comment and review now identifies the selected profile and model in a final quote. The dependent action interface remains one master key.

Verified formatting, lint, type checks, encrypted profile decryption, current OpenCode CLI flags, and 45 tests.

Reviewed-on: #18
Reviewed-by: bot <noreply@capsulizers.com>
Co-authored-by: Danny Kim <temeddix@gmail.com>
Co-committed-by: Danny Kim <temeddix@gmail.com>
2026-09-24 01:39:49 +00:00

60 lines
1.8 KiB
TypeScript

export function openCodeArgs(model: string, prompt: string): string[] {
return [
"run",
"--format",
"json",
"--auto",
"--model",
model,
prompt,
];
}
type ChunkWriter = (chunk: Uint8Array) => void | Promise<void>;
export async function collectOpenCodeOutput(
stdout: ReadableStream<Uint8Array>,
stderr: ReadableStream<Uint8Array>,
writeStdout: ChunkWriter,
writeStderr: ChunkWriter,
): Promise<{ stdout: string; stderr: string }> {
const collect = async (
stream: ReadableStream<Uint8Array>,
write: ChunkWriter,
) => {
const chunks: Uint8Array[] = [];
for await (const chunk of stream) {
chunks.push(chunk);
await write(chunk);
}
const length = chunks.reduce((total, chunk) => total + chunk.length, 0);
const joined = new Uint8Array(length);
let offset = 0;
for (const chunk of chunks) {
joined.set(chunk, offset);
offset += chunk.length;
}
return new TextDecoder().decode(joined);
};
const [output, error] = await Promise.all([
collect(stdout, writeStdout),
collect(stderr, writeStderr),
]);
return { stdout: output, stderr: error };
}
export function parseOpenCodeEvents(output: string): string {
let result: string | undefined;
for (const line of output.split("\n")) {
if (line.trim() === "") continue;
const event: unknown = JSON.parse(line);
if (typeof event !== "object" || event === null) continue;
const { type, part } = event as Record<string, unknown>;
if (type !== "text" || typeof part !== "object" || part === null) continue;
const text = (part as Record<string, unknown>).text;
if (typeof text === "string" && text.trim() !== "") result = text;
}
if (result === undefined) throw new Error("OpenCode produced no text output");
return result;
}