- Added workflow job actor to manage job application workflows. - Implemented agent catalog for various workflow agents. - Created service agents for interview, roleplay, and Q-Score functionalities. - Enhanced user authentication to automatically create users if they do not exist. - Updated configuration to support new LLM provider and API keys. - Introduced new routes for agent and workflow management. - Refactored Docker management to improve Gitea admin user creation and token generation. - Removed deprecated Anthropics SDK integration.
90 lines
2.5 KiB
TypeScript
90 lines
2.5 KiB
TypeScript
import { serve } from "@hono/node-server";
|
|
import { Hono } from "hono";
|
|
import { cors } from "hono/cors";
|
|
import { HTTPException } from "hono/http-exception";
|
|
import { config } from "./config.js";
|
|
import { log } from "./log.js";
|
|
import { registry } from "./actors/registry.js";
|
|
import { actorRoutes } from "./routes/actors.js";
|
|
import { opencodeRoutes } from "./routes/opencode.js";
|
|
import { gitRoutes } from "./routes/git.js";
|
|
import { userRoutes } from "./routes/users.js";
|
|
import { agentRoutes } from "./routes/agents.js";
|
|
import { workflowRoutes } from "./routes/workflows.js";
|
|
import { db } from "./db/client.js";
|
|
import { hydratePortAllocator, reconcileOnBoot } from "./docker/manager.js";
|
|
|
|
async function main() {
|
|
// Boot-time DB sanity + reconcile.
|
|
await db.execute("select 1");
|
|
await hydratePortAllocator();
|
|
await reconcileOnBoot();
|
|
|
|
const app = new Hono();
|
|
|
|
app.use(
|
|
"*",
|
|
cors({
|
|
origin: config.frontendOrigin.split(",").map((s) => s.trim()),
|
|
credentials: true,
|
|
allowHeaders: ["authorization", "content-type", "x-growqr-user"],
|
|
}),
|
|
);
|
|
|
|
app.onError((err, c) => {
|
|
if (err instanceof HTTPException) {
|
|
return err.getResponse();
|
|
}
|
|
log.error({ err }, "unhandled error");
|
|
return c.json({ error: "internal" }, 500);
|
|
});
|
|
|
|
app.get("/", (c) =>
|
|
c.json({ name: "growqr-backend", status: "ok", env: config.nodeEnv }),
|
|
);
|
|
|
|
app.get("/healthz", async (c) => {
|
|
try {
|
|
await db.execute("select 1");
|
|
return c.json({ ok: true });
|
|
} catch (err) {
|
|
return c.json(
|
|
{ ok: false, error: err instanceof Error ? err.message : String(err) },
|
|
503,
|
|
);
|
|
}
|
|
});
|
|
|
|
// Rivet Kit actor traffic (frontend uses @rivetkit/react against this prefix).
|
|
app.all("/api/rivet/*", (c) => registry.handler(c.req.raw));
|
|
|
|
// PRD HTTP control plane (auth-gated).
|
|
app.route("/users", userRoutes());
|
|
app.route("/agents", agentRoutes());
|
|
app.route("/workflows", workflowRoutes());
|
|
app.route("/actors", actorRoutes());
|
|
app.route("/opencode", opencodeRoutes());
|
|
app.route("/git", gitRoutes());
|
|
|
|
if (process.env.RIVET_RUN_ENGINE === "1") {
|
|
delete process.env.RIVET_ENDPOINT;
|
|
}
|
|
registry.startRunner();
|
|
|
|
serve({ fetch: app.fetch, port: config.port }, (info) => {
|
|
log.info(
|
|
{
|
|
port: info.port,
|
|
rivet: config.rivetEndpoint,
|
|
env: config.nodeEnv,
|
|
},
|
|
"growqr-backend listening",
|
|
);
|
|
});
|
|
}
|
|
|
|
main().catch((err) => {
|
|
log.error({ err }, "fatal startup error");
|
|
process.exit(1);
|
|
});
|