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>
This commit was merged in pull request #18.
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user