- Added ensureOrg and ensureOrgRepo methods to GiteaClient for centralized organization and repository management. - Updated main application flow to ensure central Gitea readiness at startup. - Introduced prompt-loader for dynamic loading of agent modules and system prompts from disk. - Refactored agent routes to return sub-agent module catalog. - Modified git routes to interact with a central Gitea instance instead of per-user containers. - Updated workflow routes to utilize a unified user actor per user, streamlining job application workflows. - Improved service agent handling with a new lightweight reference type.
77 lines
2.4 KiB
TypeScript
77 lines
2.4 KiB
TypeScript
import { Hono } from "hono";
|
|
import { z } from "zod";
|
|
import { createClient } from "rivetkit/client";
|
|
import { config } from "../config.js";
|
|
import { requireUser, type AuthContext } from "../auth/clerk.js";
|
|
import type { Registry } from "../actors/registry.js";
|
|
|
|
const client = createClient<Registry>(config.rivetEndpoint);
|
|
|
|
// Per changes.md §5: one unified userActor per user.
|
|
function userActorFor(userId: string) {
|
|
return client.userActor.getOrCreate([userId]);
|
|
}
|
|
|
|
export function workflowRoutes() {
|
|
const app = new Hono<AuthContext>();
|
|
app.use("*", requireUser);
|
|
|
|
app.post("/job-application", async (c) => {
|
|
const userId = c.get("userId");
|
|
const body = z
|
|
.object({ goal: z.string().min(1).optional() })
|
|
.parse(await c.req.json().catch(() => ({})));
|
|
const handle = userActorFor(userId);
|
|
await handle.init({ userId });
|
|
const state = await handle.startWorkflow({ goal: body.goal });
|
|
return c.json({ workflow: state });
|
|
});
|
|
|
|
app.get("/job-application", async (c) => {
|
|
const userId = c.get("userId");
|
|
const handle = userActorFor(userId);
|
|
await handle.init({ userId });
|
|
const state = await handle.getWorkflowStatus();
|
|
return c.json({ workflow: state });
|
|
});
|
|
|
|
app.post("/job-application/pause", async (c) => {
|
|
const userId = c.get("userId");
|
|
const workflow = await userActorFor(userId).pauseWorkflow();
|
|
return c.json({ workflow });
|
|
});
|
|
|
|
app.post("/job-application/resume", async (c) => {
|
|
const userId = c.get("userId");
|
|
const workflow = await userActorFor(userId).resumeWorkflow();
|
|
return c.json({ workflow });
|
|
});
|
|
|
|
app.post("/job-application/agents/:moduleId/run", async (c) => {
|
|
const userId = c.get("userId");
|
|
const moduleId = c.req.param("moduleId");
|
|
const workflow = await userActorFor(userId).runWorkflowModule({ moduleId });
|
|
return c.json({ workflow });
|
|
});
|
|
|
|
app.post("/job-application/agents/:moduleId/score", async (c) => {
|
|
const userId = c.get("userId");
|
|
const moduleId = c.req.param("moduleId");
|
|
const body = z
|
|
.object({
|
|
question: z.string().min(1),
|
|
answer: z.string().min(1),
|
|
score: z.number().min(0).max(100),
|
|
notes: z.string().optional(),
|
|
})
|
|
.parse(await c.req.json());
|
|
const workflow = await userActorFor(userId).recordQaScore({
|
|
moduleId,
|
|
...body,
|
|
});
|
|
return c.json({ workflow });
|
|
});
|
|
|
|
return app;
|
|
}
|