fix(agent): stabilize large tool results
This commit is contained in:
@@ -7,6 +7,10 @@ import { resolve } from "node:path";
|
||||
|
||||
import { config } from "../config.js";
|
||||
import { logger } from "../logger.js";
|
||||
import {
|
||||
cleanupExpiredToolOutputs,
|
||||
resolveOpencodeToolOutputDirectory,
|
||||
} from "./opencodeToolOutputCleanup.js";
|
||||
|
||||
const isDevelopmentDebugLoggingEnabled = process.env.NODE_ENV === "development";
|
||||
|
||||
@@ -46,6 +50,7 @@ const getRuntimeMessageId = (message: RuntimeMessage) => message.info.id;
|
||||
export class OpencodeRuntimeAdapter {
|
||||
private clientPromise: Promise<OpencodeClient> | null = null;
|
||||
private closeServer: (() => void) | null = null;
|
||||
private toolOutputCleanupTimer: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
async ensureClient(): Promise<OpencodeClient> {
|
||||
if (!this.clientPromise) {
|
||||
@@ -380,12 +385,18 @@ export class OpencodeRuntimeAdapter {
|
||||
}
|
||||
|
||||
async dispose(): Promise<void> {
|
||||
if (this.toolOutputCleanupTimer) {
|
||||
clearInterval(this.toolOutputCleanupTimer);
|
||||
this.toolOutputCleanupTimer = null;
|
||||
}
|
||||
this.closeServer?.();
|
||||
this.closeServer = null;
|
||||
this.clientPromise = null;
|
||||
}
|
||||
|
||||
private async bootstrapClient(): Promise<OpencodeClient> {
|
||||
await this.cleanupToolOutputs();
|
||||
|
||||
// embedded 模式下,把服务内工具桥地址注入到 opencode 进程环境里,
|
||||
// 这样 .opencode/tools 下的自定义工具可以回调本服务。
|
||||
process.env.TJWATER_AGENT_INTERNAL_BASE_URL = `http://127.0.0.1:${config.PORT}`;
|
||||
@@ -436,9 +447,39 @@ export class OpencodeRuntimeAdapter {
|
||||
this.closeServer = () => {
|
||||
runtime.server.close();
|
||||
};
|
||||
this.startToolOutputCleanupLoop();
|
||||
|
||||
return runtime.client;
|
||||
}
|
||||
|
||||
private async cleanupToolOutputs(): Promise<void> {
|
||||
const directory = resolveOpencodeToolOutputDirectory();
|
||||
const ttlMs = config.RESULT_REF_TTL_HOURS * 60 * 60 * 1000;
|
||||
try {
|
||||
const result = await cleanupExpiredToolOutputs(directory, ttlMs);
|
||||
if (result.removed > 0) {
|
||||
logger.info(
|
||||
{ directory, ...result },
|
||||
"removed expired opencode tool output files",
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
{ err: error, directory },
|
||||
"failed to clean expired opencode tool output files",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private startToolOutputCleanupLoop(): void {
|
||||
if (this.toolOutputCleanupTimer) {
|
||||
return;
|
||||
}
|
||||
this.toolOutputCleanupTimer = setInterval(() => {
|
||||
void this.cleanupToolOutputs();
|
||||
}, config.RESULT_REF_CLEANUP_INTERVAL_MS);
|
||||
this.toolOutputCleanupTimer.unref();
|
||||
}
|
||||
}
|
||||
|
||||
export const opencodeRuntime = new OpencodeRuntimeAdapter();
|
||||
@@ -448,6 +489,10 @@ function buildOpencodeConfig(): Record<string, unknown> {
|
||||
deepMerge(readProjectOpencodeConfig(), readEnvOpencodeConfig()),
|
||||
{
|
||||
model: config.OPENCODE_MODEL,
|
||||
tool_output: {
|
||||
max_bytes: config.MAX_INLINE_RESULT_BYTES,
|
||||
max_lines: 2000,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user