Implement agent hiring, approval workflows, config revisions, LLM reflection, and sidebar badges

Agent management: hire endpoint with permission gates and pending_approval status,
config revision tracking with rollback, agent duplicate route, permission CRUD.
Block pending_approval agents from auth, heartbeat, and assignments.

Approvals: revision request/resubmit flow, approval comments CRUD, issue-approval
linking, auto-wake agents on approval decisions with context snapshot.

Costs: per-agent breakdown, period filtering (month/week/day/all), cost by agent
list endpoint.

Adapters: agentConfigurationDoc on all adapters, /llms/agent-configuration.txt
reflection routes. Inject PAPERCLIP_APPROVAL_ID, PAPERCLIP_APPROVAL_STATUS,
PAPERCLIP_LINKED_ISSUE_IDS into adapter environments.

Sidebar badges endpoint for pending approval/inbox counts. Dashboard and company
settings extensions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Forgotten
2026-02-19 13:02:41 -06:00
parent db0b19bf9d
commit c09037ffad
28 changed files with 2393 additions and 148 deletions

View File

@@ -53,7 +53,7 @@ export function actorMiddleware(db: Db): RequestHandler {
return;
}
if (agentRecord.status === "terminated") {
if (agentRecord.status === "terminated" || agentRecord.status === "pending_approval") {
next();
return;
}
@@ -74,6 +74,17 @@ export function actorMiddleware(db: Db): RequestHandler {
.set({ lastUsedAt: new Date() })
.where(eq(agentApiKeys.id, key.id));
const agentRecord = await db
.select()
.from(agents)
.where(eq(agents.id, key.agentId))
.then((rows) => rows[0] ?? null);
if (!agentRecord || agentRecord.status === "terminated" || agentRecord.status === "pending_approval") {
next();
return;
}
req.actor = {
type: "agent",
agentId: key.agentId,