Files
growqr-backend/src/index.ts
NinjasPyajamas 2d471c61b4 feat: introduce workflow job management and agent orchestration
- 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.
2026-05-21 23:17:26 +05:30

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);
});