Codemod db pass-through calls to domain modules: tasks + agents (C1 part 1/3)

Rewrite ~525 call sites from `db.<method>()` to `db.<module>.<method>()`
for tasks and agents domains (including `getAgent`/`findAgent`/`getTask`
which live on the `entityCrud` field). Delete the corresponding
pass-through methods on AppDatabaseBase. Structural types that narrowed
`db` to a bag of flat methods (CapabilityMatchDb, EscalationDeps,
SweepStaleReviewsDeps) are reshaped to match the new namespace. Internal
callback references inside database.ts/database-base.ts now invoke the
owning module directly (e.g. `this.agents.saveAgent`) rather than the
deleted pass-through.

The codemod lives at scripts/codemod/remove-appdatabase-passthrough.mjs
and filters by owning module + optional explicit method list. It is
idempotent and does not re-rewrite already-namespaced calls.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-20 13:17:01 -04:00
1 parent 411294afa6
commit 5e9b7acbc6
95 files changed
+1123 -793

No files matched your search

+5 -5
View File
@@ -12,7 +12,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
const targetAgentId = requireParam(params, "agentId");
const targetAgent = (() => {
try {
return db.getAgent(targetAgentId);
return db.entityCrud.getAgent(targetAgentId);
} catch (err) {
log.warn(`[api/agent-control] getAgent failed for ${targetAgentId}:`, err instanceof Error ? err.message : String(err));
return null;
@@ -52,7 +52,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
const targetAgentId = requireParam(params, "agentId");
let targetAgent;
try {
targetAgent = db.getAgent(targetAgentId);
targetAgent = db.entityCrud.getAgent(targetAgentId);
} catch (err) {
log.warn(`[api/agent-control] getAgent failed for heartbeat ${targetAgentId}:`, err instanceof Error ? err.message : String(err));
targetAgent = null;
@@ -86,7 +86,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
const agentId = requireParam(params, "agentId");
let agent;
try {
agent = db.getAgent(agentId);
agent = db.entityCrud.getAgent(agentId);
} catch (error) {
log.warn(`[api/agent-skills:GET] getAgent(${agentId}) failed: ${error instanceof Error ? error.message : String(error)}`);
agent = null;
@@ -118,7 +118,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
}
let agent;
try {
agent = db.getAgent(agentId);
agent = db.entityCrud.getAgent(agentId);
} catch (error) {
log.warn(`[api/agent-skills:POST] getAgent(${agentId}) failed: ${error instanceof Error ? error.message : String(error)}`);
agent = null;
@@ -142,7 +142,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
const skillId = requireParam(params, "skillId");
let agent;
try {
agent = db.getAgent(agentId);
agent = db.entityCrud.getAgent(agentId);
} catch (error) {
log.warn(`[api/agent-skills:DELETE] getAgent(${agentId}) failed: ${error instanceof Error ? error.message : String(error)}`);
agent = null;
+6 -6
View File
@@ -3,23 +3,23 @@ import type { AgentApiServer } from "./server-core";
export function registerAgentStandupRoute(server: AgentApiServer): void {
const db = server.db;
server.addRoute("GET", "/api/agents/me/standup", (_req, res, _params, token) => {
const agent = db.getAgent(token.agentId);
const agent = db.entityCrud.getAgent(token.agentId);
if (!agent || agent.companyId !== token.companyId) {
server.json(res, 404, { error: "Agent not found" });
return;
}
const directReports = db.listDirectReportsForStandup(token.companyId, token.agentId);
const directReports = db.agents.listDirectReportsForStandup(token.companyId, token.agentId);
const myTasks = db.listAssigneeTasksForStandup(token.companyId, token.agentId);
const myTasks = db.tasks.listAssigneeTasksForStandup(token.companyId, token.agentId);
const reportTasks = db.listTasksForAssignees(
const reportTasks = db.tasks.listTasksForAssignees(
token.companyId,
directReports.map((r) => r.id),
);
const reportStatusRows = directReports.length > 0
? db.listReportStatusesForStandup(token.companyId, token.agentId)
? db.agents.listReportStatusesForStandup(token.companyId, token.agentId)
: [];
const tasksAwaitingMyReview = reportTasks.filter((t) => t.status === "in_review");
@@ -46,7 +46,7 @@ export function registerAgentStandupRoute(server: AgentApiServer): void {
const unreadInbox = db.listAgentInboxUnread(token.companyId, token.agentId);
const senderIds = new Set(unreadInbox.map((m) => m.fromAgentId));
const senderNames = senderIds.size > 0
? new Map(db.listAgentNamesByIds(token.companyId, Array.from(senderIds)).map((row) => [row.id, row.name]))
? new Map(db.agents.listAgentNamesByIds(token.companyId, Array.from(senderIds)).map((row) => [row.id, row.name]))
: new Map<string, string>();
// Recent outputs the AGENT itself produced — closes the
+11 -11
View File
@@ -17,9 +17,9 @@ export function registerAgentRoutes(server: AgentApiServer) {
const callbacks = server.callbacks;
const onDomainChanged = server.onDomainChanged;
server.addRoute("GET", "/api/agents/me", (_req, res, _params, token) => {
const agent = db.getAgent(token.agentId);
const chainOfCommand = db.getChainOfCommand(token.agentId);
const directReports = db.getDirectReports(token.agentId, token.companyId);
const agent = db.entityCrud.getAgent(token.agentId);
const chainOfCommand = db.agents.getChainOfCommand(token.agentId);
const directReports = db.agents.getDirectReports(token.agentId, token.companyId);
server.json(res, 200, { agent, chainOfCommand, directReports });
});
@@ -40,7 +40,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
server.addRoute("GET", "/api/agents/:agentId/metrics", (_req, res, params, token) => {
const agentId = requireParam(params, "agentId");
const agent = db.getAgent(agentId);
const agent = db.entityCrud.getAgent(agentId);
if (!agent || agent.companyId !== token.companyId) {
server.json(res, 404, { error: "Agent not found" });
return;
@@ -57,7 +57,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
server.addRoute("GET", "/api/agents/:agentId", (_req, res, params, token) => {
let agent;
try {
agent = db.getAgent(requireParam(params, "agentId"));
agent = db.entityCrud.getAgent(requireParam(params, "agentId"));
} catch (err) {
log.warn(`[api/agents] getAgent failed:`, err instanceof Error ? err.message : String(err));
server.json(res, 404, { error: "Agent not found" });
@@ -67,12 +67,12 @@ export function registerAgentRoutes(server: AgentApiServer) {
server.json(res, 404, { error: "Agent not found" });
return;
}
const directReports = db.getDirectReports(agent.id, token.companyId);
const directReports = db.agents.getDirectReports(agent.id, token.companyId);
const reportsTo = agent.reportsTo;
const manager = reportsTo
? (() => {
try {
return db.getAgent(reportsTo);
return db.entityCrud.getAgent(reportsTo);
} catch (error) {
log.warn(`[api/agents] manager lookup failed for ${reportsTo}: ${error instanceof Error ? error.message : String(error)}`);
return null;
@@ -91,7 +91,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
server.json(res, 403, { error: "Company mismatch" });
return;
}
const agents = db.listAgentsForApi(params.companyId);
const agents = db.agents.listAgentsForApi(params.companyId);
server.json(res, 200, agents);
});
@@ -157,7 +157,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
resolvedReportsTo &&
resolvedReportsTo !== token.agentId &&
!canManageOrganization(db, companyId, token.agentId) &&
!db.getChainOfCommand(resolvedReportsTo).some((agent) => agent.id === token.agentId)
!db.agents.getChainOfCommand(resolvedReportsTo).some((agent) => agent.id === token.agentId)
) {
server.json(res, 403, { error: "Requested hire must report to you or a manager in your reporting chain." });
return;
@@ -181,7 +181,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
}
// Prevent duplicate agents: reject if a non-terminated agent with the same name already exists
const existingAgents = db.listExistingAgentsForHireCheck(companyId);
const existingAgents = db.agents.listExistingAgentsForHireCheck(companyId);
const duplicateByName = existingAgents.find(
(a) => a.name.toLowerCase() === input.name.toLowerCase(),
);
@@ -208,7 +208,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
const managerLabel = resolvedReportsTo
? (() => {
try {
return db.getAgent(resolvedReportsTo).name;
return db.entityCrud.getAgent(resolvedReportsTo).name;
} catch (err) {
log.warn(`[api/agents] getAgent failed for manager ${resolvedReportsTo}:`, err instanceof Error ? err.message : String(err));
return resolvedReportsTo;
+1 -1
View File
@@ -183,7 +183,7 @@ export function registerApprovalRoutes(server: AgentApiServer) {
body: commentBody,
});
// Wake mentioned agents in comment
const mentionedIds = db.findMentionedAgentIds(approval.companyId, commentBody);
const mentionedIds = db.agents.findMentionedAgentIds(approval.companyId, commentBody);
for (const mentionedId of mentionedIds) {
if (mentionedId !== token.agentId) {
onWakeAgent(mentionedId, approval.companyId, "approval_comment_mentioned");
+5 -5
View File
@@ -228,7 +228,7 @@ export function registerFileRoutes(server: AgentApiServer) {
server.addRoute("GET", "/api/issues/:issueId/work-products", (_req, res, params, token) => {
try {
const task = db.getTask(requireParam(params, "issueId"));
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
if (task.companyId !== token.companyId) { server.json(res, 404, { error: "Task not found" }); return; }
const products = db.listWorkProductsForTask(task.id, task.companyId);
server.json(res, 200, products);
@@ -240,7 +240,7 @@ export function registerFileRoutes(server: AgentApiServer) {
server.addRoute("POST", "/api/issues/:issueId/work-products", (_req, res, params, token, body) => {
try {
const task = db.getTask(requireParam(params, "issueId"));
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
if (task.companyId !== token.companyId) { server.json(res, 404, { error: "Task not found" }); return; }
const parsed = createWorkProductSchema.safeParse(body);
if (!parsed.success) { server.json(res, 400, { error: "Invalid input", details: parsed.error.flatten() }); return; }
@@ -294,7 +294,7 @@ export function registerFileRoutes(server: AgentApiServer) {
server.addRoute("GET", "/api/issues/:issueId/documents", (_req, res, params, token) => {
try {
const task = db.getTask(requireParam(params, "issueId"));
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
if (task.companyId !== token.companyId) { server.json(res, 404, { error: "Task not found" }); return; }
const links = db.listDocumentsForTask(task.id, task.companyId);
server.json(res, 200, links);
@@ -306,7 +306,7 @@ export function registerFileRoutes(server: AgentApiServer) {
server.addRoute("PUT", "/api/issues/:issueId/documents/:key", (_req, res, params, token, body) => {
try {
const task = db.getTask(requireParam(params, "issueId"));
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
if (task.companyId !== token.companyId) { server.json(res, 404, { error: "Task not found" }); return; }
const key = String(params.key ?? "").trim().toLowerCase();
if (!key || !/^[a-z0-9][a-z0-9_-]*$/.test(key) || key.length > 64) {
@@ -329,7 +329,7 @@ export function registerFileRoutes(server: AgentApiServer) {
server.addRoute("DELETE", "/api/issues/:issueId/documents/:key", (_req, res, params, token) => {
try {
const task = db.getTask(requireParam(params, "issueId"));
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
if (task.companyId !== token.companyId) { server.json(res, 404, { error: "Task not found" }); return; }
const key = String(params.key ?? "").trim().toLowerCase();
db.unlinkDocumentFromTask(task.id, key, task.companyId);
+1 -1
View File
@@ -133,7 +133,7 @@ export function registerMeetingRoutes(server: AgentApiServer) {
);
continue;
}
db.saveTask({
db.tasks.saveTask({
companyId: token.companyId,
title: item.title,
description: item.description ?? `Action item from meeting: ${data.title ?? existing.title}`,
+5 -5
View File
@@ -20,12 +20,12 @@ export function registerMessageRoutes(server: AgentApiServer) {
return;
}
try {
const task = db.getTask(requireParam(params, "issueId"));
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
if (task.companyId !== token.companyId) {
server.json(res, 404, { error: "Task not found" });
return;
}
const agent = db.getAgent(token.agentId);
const agent = db.entityCrud.getAgent(token.agentId);
const comment = db.addComment({
companyId: task.companyId,
taskId: task.id,
@@ -44,14 +44,14 @@ export function registerMessageRoutes(server: AgentApiServer) {
wokenForComment.add(task.assigneeAgentId);
}
const chain = db.getChainOfCommand(token.agentId);
const chain = db.agents.getChainOfCommand(token.agentId);
if (chain.length > 0 && chain[0].id !== token.agentId && !wokenForComment.has(chain[0].id)) {
onWakeAgent(chain[0].id, task.companyId, "comment");
wokenForComment.add(chain[0].id);
}
// @mention detection: wake any mentioned agents not already woken
const mentionedIds = db.findMentionedAgentIds(task.companyId, input.body);
const mentionedIds = db.agents.findMentionedAgentIds(task.companyId, input.body);
for (const mentionedId of mentionedIds) {
if (mentionedId !== token.agentId && !wokenForComment.has(mentionedId)) {
onWakeAgent(mentionedId, task.companyId, "comment_mentioned");
@@ -68,7 +68,7 @@ export function registerMessageRoutes(server: AgentApiServer) {
server.addRoute("GET", "/api/issues/:issueId/comments", (_req, res, params, token) => {
try {
const task = db.getTask(requireParam(params, "issueId"));
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
if (task.companyId !== token.companyId) {
server.json(res, 404, { error: "Task not found" });
return;
+20 -20
View File
@@ -38,17 +38,17 @@ export function registerTaskRoutes(server: AgentApiServer) {
const statuses = statusFilter ? statusFilter.split(",") : ["todo", "in_progress", "blocked"];
if (assigneeAgentId) {
const tasks = db.listAgentTasks(assigneeAgentId, companyId, statuses);
const tasks = db.tasks.listAgentTasks(assigneeAgentId, companyId, statuses);
server.json(res, 200, tasks);
} else {
const tasks = db.listTasksByStatuses(companyId, statuses);
const tasks = db.tasks.listTasksByStatuses(companyId, statuses);
server.json(res, 200, tasks);
}
});
server.addRoute("GET", "/api/issues/:issueId", (_req, res, params, token) => {
try {
const task = db.getTask(requireParam(params, "issueId"));
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
if (task.companyId !== token.companyId) {
server.json(res, 404, { error: "Task not found" });
return;
@@ -73,7 +73,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
}
let task;
try {
task = db.getTask(requireParam(params, "issueId"));
task = db.entityCrud.getTask(requireParam(params, "issueId"));
} catch (err) {
log.warn(`[api/tasks] getTask failed for checkout:`, err instanceof Error ? err.message : String(err));
server.json(res, 404, { error: "Task not found" });
@@ -88,7 +88,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
return;
}
const previousStatus = task.status;
const success = db.checkoutTask(task.id, token.runId);
const success = db.tasks.checkoutTask(task.id, token.runId);
if (!success) {
server.json(res, 409, { error: "Task cannot be checked out — already assigned or not in valid status" });
return;
@@ -108,7 +108,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
const update = parsedUpdate.data;
try {
const task = db.getTask(requireParam(params, "issueId"));
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
if (task.companyId !== token.companyId) {
server.json(res, 404, { error: "Task not found" });
return;
@@ -134,7 +134,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
taskId: task.id,
limit: 10,
});
const reviewerAgent = db.getAgent(token.agentId);
const reviewerAgent = db.entityCrud.getAgent(token.agentId);
const docTitles = docs.map((d) => d.title).join(", ");
db.requestApproval({
companyId: task.companyId,
@@ -145,11 +145,11 @@ export function registerTaskRoutes(server: AgentApiServer) {
impactSummary: `${reviewerAgent.name} reviewed and approved. Awaiting your final review.`.slice(0, 400),
payloadJson: JSON.stringify({ documentIds: docs.map((d) => d.id), documents: docs }),
});
db.setTaskRequiresUserReview(task.id, false);
db.tasks.setTaskRequiresUserReview(task.id, false);
if (task.assigneeAgentId) {
const prodAgent = db.getAgent(task.assigneeAgentId);
const prodAgent = db.entityCrud.getAgent(task.assigneeAgentId);
if (prodAgent.heartbeatEnabled) {
db.setHeartbeat(task.assigneeAgentId, false, prodAgent.heartbeatIntervalSec || 120);
db.agents.setHeartbeat(task.assigneeAgentId, false, prodAgent.heartbeatIntervalSec || 120);
}
}
db.addComment({ companyId: task.companyId, taskId: task.id, authorAgentId: null, authorName: "System", body: "Deliverable submitted for board review." });
@@ -169,7 +169,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
// advanceTaskStatus checks previousStatus !== newStatus internally,
// so it must run before saveTask writes the new status.
if (update.status && update.status !== task.status) {
db.advanceTaskStatus(task.id, update.status);
db.tasks.advanceTaskStatus(task.id, update.status);
}
const input: Record<string, unknown> = {
@@ -185,10 +185,10 @@ export function registerTaskRoutes(server: AgentApiServer) {
assigneeAgentId: newAssignee,
workspaceId: task.workspaceId,
};
db.saveTask(input as Parameters<typeof db.saveTask>[0]);
db.tasks.saveTask(input as Parameters<typeof db.tasks.saveTask>[0]);
if (update.comment) {
const agent = db.getAgent(token.agentId);
const agent = db.entityCrud.getAgent(token.agentId);
db.addComment({
companyId: task.companyId,
taskId: task.id,
@@ -219,7 +219,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
if (update.status && ["done", "in_review"].includes(update.status)) {
if (task.parentId) {
try {
const parentTask = db.getTask(task.parentId);
const parentTask = db.entityCrud.getTask(task.parentId);
if (parentTask.assigneeAgentId && parentTask.assigneeAgentId !== token.agentId) {
onWakeAgent(parentTask.assigneeAgentId, task.companyId, "subtask_completed");
}
@@ -233,7 +233,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
// This is not a subtask — use a distinct wake reason so the
// reviewer prompt does not misframe the work as "a subtask
// you delegated".
const chain = db.getChainOfCommand(token.agentId);
const chain = db.agents.getChainOfCommand(token.agentId);
if (chain.length > 0) {
onWakeAgent(chain[0].id, task.companyId, "task_review_requested");
}
@@ -241,7 +241,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
}
if (update.status === "blocked") {
const chain = db.getChainOfCommand(token.agentId);
const chain = db.agents.getChainOfCommand(token.agentId);
if (chain.length > 0) {
onWakeAgent(chain[0].id, task.companyId, "report_blocked");
}
@@ -261,7 +261,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
onWakeAgent(task.assigneeAgentId, task.companyId, "comment");
wokenForComment.add(task.assigneeAgentId);
}
const chain = db.getChainOfCommand(token.agentId);
const chain = db.agents.getChainOfCommand(token.agentId);
if (chain.length > 0 && chain[0].id !== token.agentId && !wokenForComment.has(chain[0].id)) {
onWakeAgent(chain[0].id, task.companyId, "comment");
}
@@ -333,7 +333,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
let id: string;
try {
id = db.saveTask({
id = db.tasks.saveTask({
companyId,
title: input.title,
description: input.description ?? "",
@@ -352,9 +352,9 @@ export function registerTaskRoutes(server: AgentApiServer) {
// Auto-infer task_type from assignee's department
if (input.assigneeAgentId) {
const assignee = db.getAgent(input.assigneeAgentId);
const assignee = db.entityCrud.getAgent(input.assigneeAgentId);
const inferredType = inferTaskType(assignee.department);
db.setTaskType(id, inferredType);
db.tasks.setTaskType(id, inferredType);
}
db.addActivity({