125 lines
3.0 KiB
TypeScript
125 lines
3.0 KiB
TypeScript
/**
|
|
* Subprocess wrapper for kiro-cli chat.
|
|
*
|
|
* Since Kiro uses AWS Smithy/Coral protocol (not standard REST),
|
|
* we use kiro-cli as a subprocess for actual inference.
|
|
*/
|
|
|
|
import { spawn } from "node:child_process";
|
|
import { findKiroCli } from "./cli-detector.js";
|
|
|
|
/**
|
|
* Available Kiro models.
|
|
* - auto: Models chosen by task (1x credit)
|
|
* - claude-sonnet-4: Hybrid reasoning and coding (1.3x credit)
|
|
* - claude-sonnet-4.5: Latest Claude Sonnet (1.3x credit)
|
|
* - claude-haiku-4.5: Latest Claude Haiku (0.4x credit)
|
|
* - claude-opus-4.5: Latest Claude Opus (premium)
|
|
*/
|
|
export type KiroModel =
|
|
| "auto"
|
|
| "claude-sonnet-4"
|
|
| "claude-sonnet-4.5"
|
|
| "claude-haiku-4.5"
|
|
| "claude-opus-4.5";
|
|
|
|
export type KiroChatOptions = {
|
|
/** Model to use (default: auto) */
|
|
model?: KiroModel;
|
|
/** Trust all tools without prompting */
|
|
trustAllTools?: boolean;
|
|
/** Timeout in milliseconds */
|
|
timeoutMs?: number;
|
|
};
|
|
|
|
/**
|
|
* Sends a chat message via kiro-cli subprocess.
|
|
*
|
|
* @param prompt The message to send
|
|
* @param options Chat options
|
|
* @returns The response from kiro-cli
|
|
* @throws Error if kiro-cli is not found or fails
|
|
*/
|
|
export async function kiroChat(
|
|
prompt: string,
|
|
options: KiroChatOptions = {},
|
|
): Promise<string> {
|
|
const cliPath = findKiroCli();
|
|
if (!cliPath) {
|
|
throw new Error("kiro-cli not found. Install with: brew install kiro-cli");
|
|
}
|
|
|
|
const args = ["chat", "--no-interactive"];
|
|
|
|
if (options.model && options.model !== "auto") {
|
|
args.push("--model", options.model);
|
|
}
|
|
|
|
if (options.trustAllTools) {
|
|
args.push("--trust-all-tools");
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const proc = spawn(cliPath, args, {
|
|
stdio: ["pipe", "pipe", "pipe"],
|
|
timeout: options.timeoutMs,
|
|
});
|
|
|
|
let stdout = "";
|
|
let stderr = "";
|
|
|
|
proc.stdout.on("data", (data: Buffer) => {
|
|
stdout += data.toString();
|
|
});
|
|
|
|
proc.stderr.on("data", (data: Buffer) => {
|
|
stderr += data.toString();
|
|
});
|
|
|
|
proc.on("close", (code) => {
|
|
if (code === 0) {
|
|
resolve(stdout.trim());
|
|
} else {
|
|
reject(
|
|
new Error(`kiro-cli failed (code ${code}): ${stderr || stdout}`),
|
|
);
|
|
}
|
|
});
|
|
|
|
proc.on("error", (err) => {
|
|
reject(new Error(`Failed to spawn kiro-cli: ${err.message}`));
|
|
});
|
|
|
|
// Send prompt and close stdin
|
|
proc.stdin.write(prompt + "\n");
|
|
proc.stdin.end();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Maps Clawdbot model IDs to Kiro model names.
|
|
*/
|
|
export function mapModelToKiro(modelId: string): KiroModel {
|
|
// Strip provider prefix if present
|
|
const model = modelId.replace(/^kiro\//, "");
|
|
|
|
switch (model) {
|
|
case "auto":
|
|
return "auto";
|
|
case "claude-sonnet-4":
|
|
case "sonnet-4":
|
|
return "claude-sonnet-4";
|
|
case "claude-sonnet-4.5":
|
|
case "sonnet-4.5":
|
|
return "claude-sonnet-4.5";
|
|
case "claude-haiku-4.5":
|
|
case "haiku-4.5":
|
|
return "claude-haiku-4.5";
|
|
case "claude-opus-4.5":
|
|
case "opus-4.5":
|
|
return "claude-opus-4.5";
|
|
default:
|
|
return "auto";
|
|
}
|
|
}
|