fix(agent): warm up opencode on startup
This commit is contained in:
@@ -50,7 +50,10 @@ export class OpencodeRuntimeAdapter {
|
|||||||
|
|
||||||
async ensureClient(): Promise<OpencodeClient> {
|
async ensureClient(): Promise<OpencodeClient> {
|
||||||
if (!this.clientPromise) {
|
if (!this.clientPromise) {
|
||||||
this.clientPromise = this.bootstrapClient();
|
this.clientPromise = this.bootstrapClient().catch((error) => {
|
||||||
|
this.clientPromise = null;
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return this.clientPromise;
|
return this.clientPromise;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -283,8 +283,32 @@ const server = app.listen(config.PORT, config.HOST, () => {
|
|||||||
{ host: config.HOST, port: config.PORT },
|
{ host: config.HOST, port: config.PORT },
|
||||||
"TJWaterAgent listening",
|
"TJWaterAgent listening",
|
||||||
);
|
);
|
||||||
|
void warmupOpencodeRuntime();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const warmupOpencodeRuntime = async () => {
|
||||||
|
const startedAt = Date.now();
|
||||||
|
try {
|
||||||
|
await opencodeRuntime.ensureClient();
|
||||||
|
logger.info(
|
||||||
|
{
|
||||||
|
elapsedMs: Math.max(0, Date.now() - startedAt),
|
||||||
|
mode: config.OPENCODE_MODE,
|
||||||
|
},
|
||||||
|
"opencode runtime warmed up",
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(
|
||||||
|
{
|
||||||
|
err: error,
|
||||||
|
elapsedMs: Math.max(0, Date.now() - startedAt),
|
||||||
|
mode: config.OPENCODE_MODE,
|
||||||
|
},
|
||||||
|
"failed to warm up opencode runtime",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const shutdown = async () => {
|
const shutdown = async () => {
|
||||||
logger.info("shutting down TJWaterAgent");
|
logger.info("shutting down TJWaterAgent");
|
||||||
server.close();
|
server.close();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { describe, expect, it } from "bun:test";
|
import { describe, expect, it } from "bun:test";
|
||||||
|
import { type OpencodeClient } from "@opencode-ai/sdk/v2";
|
||||||
|
|
||||||
import { OpencodeRuntimeAdapter } from "../../src/runtime/opencode.js";
|
import { OpencodeRuntimeAdapter } from "../../src/runtime/opencode.js";
|
||||||
|
|
||||||
@@ -60,3 +61,27 @@ describe("OpencodeRuntimeAdapter.revertToUserMessage", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("OpencodeRuntimeAdapter.ensureClient", () => {
|
||||||
|
it("retries bootstrap after a failed startup attempt", async () => {
|
||||||
|
let attempts = 0;
|
||||||
|
const client = {
|
||||||
|
global: { health: async () => ({ data: { healthy: true } }) },
|
||||||
|
} as unknown as OpencodeClient;
|
||||||
|
const runtime = Object.assign(Object.create(OpencodeRuntimeAdapter.prototype), {
|
||||||
|
clientPromise: null,
|
||||||
|
closeServer: null,
|
||||||
|
bootstrapClient: async () => {
|
||||||
|
attempts += 1;
|
||||||
|
if (attempts === 1) {
|
||||||
|
throw new Error("startup failed");
|
||||||
|
}
|
||||||
|
return client;
|
||||||
|
},
|
||||||
|
}) as OpencodeRuntimeAdapter;
|
||||||
|
|
||||||
|
await expect(runtime.ensureClient()).rejects.toThrow("startup failed");
|
||||||
|
await expect(runtime.ensureClient()).resolves.toBe(client);
|
||||||
|
expect(attempts).toBe(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user