feat: update webui extensions, models, and agent config
This commit is contained in:
@@ -6,6 +6,7 @@ import type { RunSnapshot, SendCmd, SubmitPromptOptions } from "../types/context
|
||||
export interface PiClient {
|
||||
sendCmd: SendCmd;
|
||||
submitPrompt: (options: SubmitPromptOptions) => void;
|
||||
sendExtensionUiResponse: (id: string, response: Record<string, unknown>) => void;
|
||||
getRunSnapshot: () => RunSnapshot;
|
||||
connectSseClient: (res: ServerResponse) => void;
|
||||
removeSseClient: (res: ServerResponse) => void;
|
||||
@@ -23,14 +24,32 @@ const BUFFERED_EVENT_TYPES = new Set([
|
||||
"tool_execution_end",
|
||||
"compaction_start",
|
||||
"compaction_end",
|
||||
"queue_update",
|
||||
"auto_retry_start",
|
||||
"auto_retry_end",
|
||||
"bash_update",
|
||||
]);
|
||||
|
||||
const DEFAULT_CMD_TIMEOUT_MS = 60_000;
|
||||
const PROMPT_PREFLIGHT_TIMEOUT_MS = 30_000;
|
||||
const PI_STDERR_BUFFER_MAX = 8192;
|
||||
|
||||
function formatSpawnArgs(args: string[]): string {
|
||||
return args.map((arg) => JSON.stringify(arg)).join(" ");
|
||||
}
|
||||
|
||||
function summarizeStderr(buffer: string): string {
|
||||
const trimmed = buffer.trim();
|
||||
if (!trimmed) return "(无 stderr 输出)";
|
||||
const lines = trimmed.split(/\r?\n/).filter(Boolean);
|
||||
return lines.slice(-8).join("\n");
|
||||
}
|
||||
|
||||
export function createPiClient(paths: WebUiPaths, onExit: (code: number | null) => void): PiClient {
|
||||
const piLaunch = resolvePiRpcLaunch(paths);
|
||||
console.log(`[webui] 启动 pi RPC (${piLaunch.mode}): ${piLaunch.command} ${piLaunch.args.join(" ")}`);
|
||||
console.log(
|
||||
`[webui] 启动 pi RPC (${piLaunch.mode}): ${piLaunch.command} ${formatSpawnArgs(piLaunch.args)}`,
|
||||
);
|
||||
|
||||
const pi = spawn(piLaunch.command, piLaunch.args, {
|
||||
cwd: paths.repoRoot,
|
||||
@@ -41,9 +60,20 @@ export function createPiClient(paths: WebUiPaths, onExit: (code: number | null)
|
||||
},
|
||||
});
|
||||
|
||||
pi.stderr.on("data", (data) => process.stderr.write(`[pi] ${data}`));
|
||||
// Keep stdin pipe open; closing it on Windows can trigger RPC shutdown via stdin "end".
|
||||
pi.stdin.write("");
|
||||
|
||||
let stderrBuffer = "";
|
||||
pi.stderr.on("data", (data: Buffer) => {
|
||||
const chunk = data.toString();
|
||||
stderrBuffer = (stderrBuffer + chunk).slice(-PI_STDERR_BUFFER_MAX);
|
||||
process.stderr.write(`[pi] ${data}`);
|
||||
});
|
||||
pi.on("exit", (code) => {
|
||||
console.log(`[webui] pi 退出, code=${code}`);
|
||||
if (code !== 0 && code !== null) {
|
||||
console.error(`[webui] pi RPC 启动失败 (code=${code}):\n${summarizeStderr(stderrBuffer)}`);
|
||||
}
|
||||
onExit(code);
|
||||
});
|
||||
|
||||
@@ -157,13 +187,16 @@ export function createPiClient(paths: WebUiPaths, onExit: (code: number | null)
|
||||
|
||||
function submitPrompt(options: SubmitPromptOptions): void {
|
||||
const id = `req_${++reqId}`;
|
||||
const line =
|
||||
JSON.stringify({
|
||||
type: "prompt",
|
||||
message: options.message,
|
||||
images: options.images,
|
||||
id,
|
||||
}) + "\n";
|
||||
const payload: Record<string, unknown> = {
|
||||
type: "prompt",
|
||||
message: options.message,
|
||||
images: options.images,
|
||||
id,
|
||||
};
|
||||
if (options.streamingBehavior) {
|
||||
payload.streamingBehavior = options.streamingBehavior;
|
||||
}
|
||||
const line = JSON.stringify(payload) + "\n";
|
||||
registerPending(
|
||||
id,
|
||||
{
|
||||
@@ -180,6 +213,11 @@ export function createPiClient(paths: WebUiPaths, onExit: (code: number | null)
|
||||
pi.stdin.write(line);
|
||||
}
|
||||
|
||||
function sendExtensionUiResponse(id: string, response: Record<string, unknown>): void {
|
||||
const line = JSON.stringify({ type: "extension_ui_response", id, ...response }) + "\n";
|
||||
pi.stdin.write(line);
|
||||
}
|
||||
|
||||
function connectSseClient(res: ServerResponse): void {
|
||||
const snapshot = getRunSnapshot();
|
||||
res.write(
|
||||
@@ -195,6 +233,7 @@ export function createPiClient(paths: WebUiPaths, onExit: (code: number | null)
|
||||
return {
|
||||
sendCmd,
|
||||
submitPrompt,
|
||||
sendExtensionUiResponse,
|
||||
getRunSnapshot,
|
||||
connectSseClient,
|
||||
removeSseClient: (res) => sseClients.delete(res),
|
||||
|
||||
Reference in New Issue
Block a user