fix(agent): complete opencode warmup before serving

The previous fire-and-forget startup only created the SDK client, leaving the first chat to await project and tool initialization. Warm the real session/tool path and gate port listening on completion.
This commit is contained in:
2026-08-04 15:25:00 +08:00
parent 94529cb141
commit 07016451d6
3 changed files with 90 additions and 12 deletions
+32
View File
@@ -64,6 +64,38 @@ export class OpencodeRuntimeAdapter {
return requireData(response.data, "global.health");
}
async warmup(): Promise<void> {
const client = await this.ensureClient();
const healthResponse = await client.global.health();
requireData(healthResponse.data, "global.health");
const sessionResponse = await client.session.create({
title: "tjwater-agent-warmup",
});
const session = requireData(sessionResponse.data, "session.create");
try {
const [provider, model] = config.OPENCODE_MODEL.split("/");
if (!provider || !model) {
throw new Error(
`invalid OPENCODE_MODEL; expected provider/model, received ${config.OPENCODE_MODEL}`,
);
}
const toolsResponse = await client.tool.list({ provider, model });
requireData(toolsResponse.data, "tool.list");
} finally {
await client.session.delete(
{ sessionID: session.id },
{ throwOnError: true },
).catch((error) => {
logger.warn(
{ err: error, sessionId: session.id },
"failed to remove opencode warmup session",
);
});
}
}
async createSession(title?: string) {
const client = await this.ensureClient();
const response = await client.session.create({
+13 -12
View File
@@ -488,23 +488,12 @@ const bootstrap = async () => {
resultReferenceStore.initialize(),
sessionTranscriptStore.initialize(),
]);
resultReferenceStore.startCleanupLoop();
};
await bootstrap();
const server = app.listen(config.PORT, config.HOST, () => {
logger.info(
{ host: config.HOST, port: config.PORT },
"TJWaterAgent listening",
);
void warmupOpencodeRuntime();
});
const warmupOpencodeRuntime = async () => {
const startedAt = Date.now();
try {
await opencodeRuntime.ensureClient();
await opencodeRuntime.warmup();
logger.info(
{
elapsedMs: Math.max(0, Date.now() - startedAt),
@@ -521,9 +510,21 @@ const warmupOpencodeRuntime = async () => {
},
"failed to warm up opencode runtime",
);
throw error;
}
};
await bootstrap();
await warmupOpencodeRuntime();
resultReferenceStore.startCleanupLoop();
const server = app.listen(config.PORT, config.HOST, () => {
logger.info(
{ host: config.HOST, port: config.PORT },
"TJWaterAgent listening",
);
});
const shutdown = async () => {
logger.info("shutting down TJWaterAgent");
server.close();