ea20f6d629
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>
60 lines
1.8 KiB
TypeScript
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;
|
|
}
|