fix(agent): harden permissions and startup readiness
This commit is contained in:
@@ -64,6 +64,64 @@ export class OpencodeRuntimeAdapter {
|
||||
return requireData(response.data, "global.health");
|
||||
}
|
||||
|
||||
async warmup(): Promise<void> {
|
||||
const client = await this.ensureClient();
|
||||
const healthStartedAt = Date.now();
|
||||
const healthResponse = await client.global.health();
|
||||
const health = requireData(healthResponse.data, "global.health");
|
||||
logDevelopmentDebug("opencode warmup health check completed", {
|
||||
elapsedMs: Math.max(0, Date.now() - healthStartedAt),
|
||||
healthy: health.healthy,
|
||||
version: health.version,
|
||||
});
|
||||
|
||||
const sessionStartedAt = Date.now();
|
||||
const sessionResponse = await client.session.create({
|
||||
title: "tjwater-agent-warmup",
|
||||
});
|
||||
const session = requireData(sessionResponse.data, "session.create");
|
||||
logDevelopmentDebug("opencode warmup session created", {
|
||||
elapsedMs: Math.max(0, Date.now() - sessionStartedAt),
|
||||
sessionId: session.id,
|
||||
});
|
||||
|
||||
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 toolsStartedAt = Date.now();
|
||||
const toolsResponse = await client.tool.list({ provider, model });
|
||||
const tools = requireData(toolsResponse.data, "tool.list");
|
||||
logDevelopmentDebug("opencode warmup tools loaded", {
|
||||
elapsedMs: Math.max(0, Date.now() - toolsStartedAt),
|
||||
model: config.OPENCODE_MODEL,
|
||||
sessionId: session.id,
|
||||
toolCount: tools.length,
|
||||
});
|
||||
} finally {
|
||||
const cleanupStartedAt = Date.now();
|
||||
let cleanupSucceeded = true;
|
||||
await client.session.delete(
|
||||
{ sessionID: session.id },
|
||||
{ throwOnError: true },
|
||||
).catch((error) => {
|
||||
cleanupSucceeded = false;
|
||||
logger.warn(
|
||||
{ err: error, sessionId: session.id },
|
||||
"failed to remove opencode warmup session",
|
||||
);
|
||||
});
|
||||
logDevelopmentDebug("opencode warmup session cleanup completed", {
|
||||
elapsedMs: Math.max(0, Date.now() - cleanupStartedAt),
|
||||
sessionId: session.id,
|
||||
succeeded: cleanupSucceeded,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async createSession(title?: string) {
|
||||
const client = await this.ensureClient();
|
||||
const response = await client.session.create({
|
||||
|
||||
+22
-12
@@ -75,6 +75,8 @@ app.get("/health", async (_req, res) => {
|
||||
const runtime = await opencodeRuntime.health();
|
||||
res.json({
|
||||
ok: true,
|
||||
ready: true,
|
||||
warmed_up: true,
|
||||
runtime,
|
||||
sessions: sessionBridge.count(),
|
||||
});
|
||||
@@ -82,6 +84,8 @@ app.get("/health", async (_req, res) => {
|
||||
const detail = error instanceof Error ? error.message : String(error);
|
||||
res.status(503).json({
|
||||
ok: false,
|
||||
ready: false,
|
||||
warmed_up: true,
|
||||
message: "opencode runtime unavailable",
|
||||
detail,
|
||||
sessions: sessionBridge.count(),
|
||||
@@ -148,23 +152,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),
|
||||
@@ -181,9 +174,26 @@ 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,
|
||||
ready: true,
|
||||
warmedUp: true,
|
||||
},
|
||||
"TJWaterAgent listening",
|
||||
);
|
||||
});
|
||||
|
||||
const shutdown = async () => {
|
||||
logger.info("shutting down TJWaterAgent");
|
||||
server.close();
|
||||
|
||||
Reference in New Issue
Block a user