fix: run agent manager as health service
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
import { createServer } from "node:http";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AGENT_MGR_SERVICE_ID,
|
AGENT_MGR_SERVICE_ID,
|
||||||
createSkillsManifest
|
createSkillsManifest
|
||||||
@@ -14,7 +16,7 @@ import {
|
|||||||
resolveAgentRuntimeStateDir
|
resolveAgentRuntimeStateDir
|
||||||
} from "../../internal/agent/runtime.mjs";
|
} from "../../internal/agent/runtime.mjs";
|
||||||
|
|
||||||
const command = process.argv[2] || "help";
|
const command = process.argv[2] || process.env.HWLAB_AGENT_MGR_DEFAULT_COMMAND || "server";
|
||||||
const options = parseOptions(process.argv.slice(3));
|
const options = parseOptions(process.argv.slice(3));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -40,23 +42,11 @@ async function dispatch(name, opts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (name === "health") {
|
if (name === "health") {
|
||||||
const managerSkills = assessSkillsInjection({
|
return createHealthResponse(opts);
|
||||||
skillCommitId: opts.skillCommitId,
|
}
|
||||||
skillVersion: opts.skillVersion,
|
|
||||||
role: "manager"
|
if (name === "server") {
|
||||||
});
|
return serveHealth(opts);
|
||||||
const health = createRuntimeHealth({
|
|
||||||
stateDir: opts.stateDir,
|
|
||||||
managerSkills
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
serviceId: AGENT_MGR_SERVICE_ID,
|
|
||||||
ok: true,
|
|
||||||
health,
|
|
||||||
skillsManifest: managerSkills.status === "ready"
|
|
||||||
? createSkillsManifest({ commitId: managerSkills.commitId, version: managerSkills.version })
|
|
||||||
: null
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name === "create") {
|
if (name === "create") {
|
||||||
@@ -152,11 +142,84 @@ function requireOption(opts, key, flag) {
|
|||||||
return opts[key];
|
return opts[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createHealthResponse(opts) {
|
||||||
|
const managerSkills = assessSkillsInjection({
|
||||||
|
skillCommitId: opts.skillCommitId,
|
||||||
|
skillVersion: opts.skillVersion,
|
||||||
|
role: "manager"
|
||||||
|
});
|
||||||
|
const health = createRuntimeHealth({
|
||||||
|
stateDir: opts.stateDir,
|
||||||
|
managerSkills
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
serviceId: AGENT_MGR_SERVICE_ID,
|
||||||
|
ok: true,
|
||||||
|
health,
|
||||||
|
skillsManifest: managerSkills.status === "ready"
|
||||||
|
? createSkillsManifest({ commitId: managerSkills.commitId, version: managerSkills.version })
|
||||||
|
: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function serveHealth(opts) {
|
||||||
|
const port = Number.parseInt(process.env.PORT || process.env.HWLAB_PORT || "7410", 10);
|
||||||
|
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
||||||
|
throw new Error(`invalid PORT/HWLAB_PORT ${JSON.stringify(process.env.PORT || process.env.HWLAB_PORT)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = createServer((request, response) => {
|
||||||
|
const url = new URL(request.url || "/", "http://hwlab-agent-mgr.local");
|
||||||
|
if (url.pathname === "/health" || url.pathname === "/health/live") {
|
||||||
|
sendJson(response, 200, {
|
||||||
|
...createHealthResponse(opts),
|
||||||
|
environment: process.env.HWLAB_ENVIRONMENT || "dev",
|
||||||
|
commit: {
|
||||||
|
id: process.env.HWLAB_COMMIT_ID || "unknown",
|
||||||
|
source: "runtime-env"
|
||||||
|
},
|
||||||
|
image: {
|
||||||
|
reference: process.env.HWLAB_IMAGE || "unknown",
|
||||||
|
tag: process.env.HWLAB_IMAGE_TAG || "unknown",
|
||||||
|
digest: process.env.HWLAB_IMAGE_DIGEST || "unknown"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (url.pathname === "/" || url.pathname === "/help") {
|
||||||
|
sendJson(response, 200, help());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendJson(response, 404, { serviceId: AGENT_MGR_SERVICE_ID, ok: false, error: "not_found", path: url.pathname });
|
||||||
|
});
|
||||||
|
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
server.once("error", reject);
|
||||||
|
server.listen(port, "0.0.0.0", resolve);
|
||||||
|
});
|
||||||
|
printJSON({ serviceId: AGENT_MGR_SERVICE_ID, ok: true, status: "listening", port });
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
server.once("close", resolve);
|
||||||
|
server.once("error", reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendJson(response, statusCode, body) {
|
||||||
|
const payload = JSON.stringify(body, null, 2);
|
||||||
|
response.writeHead(statusCode, {
|
||||||
|
"content-type": "application/json; charset=utf-8",
|
||||||
|
"content-length": Buffer.byteLength(payload)
|
||||||
|
});
|
||||||
|
response.end(payload);
|
||||||
|
}
|
||||||
|
|
||||||
function help() {
|
function help() {
|
||||||
return {
|
return {
|
||||||
serviceId: AGENT_MGR_SERVICE_ID,
|
serviceId: AGENT_MGR_SERVICE_ID,
|
||||||
ok: true,
|
ok: true,
|
||||||
usage: [
|
usage: [
|
||||||
|
"node cmd/hwlab-agent-mgr/main.mjs server [--skill-commit-id COMMIT --skill-version VERSION] [--state-dir DIR]",
|
||||||
"node cmd/hwlab-agent-mgr/main.mjs health [--skill-commit-id COMMIT --skill-version VERSION] [--state-dir DIR]",
|
"node cmd/hwlab-agent-mgr/main.mjs health [--skill-commit-id COMMIT --skill-version VERSION] [--state-dir DIR]",
|
||||||
"node cmd/hwlab-agent-mgr/main.mjs create --agent-session-id ID --project-id ID [--goal TEXT --prompt TEXT] [--skill-commit-id COMMIT --skill-version VERSION] [--state-dir DIR]",
|
"node cmd/hwlab-agent-mgr/main.mjs create --agent-session-id ID --project-id ID [--goal TEXT --prompt TEXT] [--skill-commit-id COMMIT --skill-version VERSION] [--state-dir DIR]",
|
||||||
"node cmd/hwlab-agent-mgr/main.mjs status --agent-session-id ID [--state-dir DIR]",
|
"node cmd/hwlab-agent-mgr/main.mjs status --agent-session-id ID [--state-dir DIR]",
|
||||||
|
|||||||
Reference in New Issue
Block a user