refactor(db): group database domain modules
This commit is contained in:
1 parent
e43a89096d
commit
6da0a58769
160 files changed
+2124
-1999
No files matched your search
@@ -12,7 +12,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
|
||||
const targetAgentId = requireParam(params, "agentId");
|
||||
const targetAgent = (() => {
|
||||
try {
|
||||
return db.entityCrud.getAgent(targetAgentId);
|
||||
return db.core.entity.getAgent(targetAgentId);
|
||||
} catch (err) {
|
||||
log.warn(`[api/agent-control] getAgent failed for ${targetAgentId}:`, err instanceof Error ? err.message : String(err));
|
||||
return null;
|
||||
@@ -31,7 +31,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
|
||||
});
|
||||
const parsed = wakeSchema.safeParse(body);
|
||||
const reason = parsed.success ? parsed.data.reason : "peer_request";
|
||||
const alreadyActive = db.runs.hasActiveRun({ companyId: token.companyId, agentId: targetAgentId });
|
||||
const alreadyActive = db.core.runs.hasActiveRun({ companyId: token.companyId, agentId: targetAgentId });
|
||||
const runId = onWakeAgent(targetAgentId, token.companyId, reason);
|
||||
if (runId) {
|
||||
server.json(res, 200, { ok: true, runId, message: `Wake started for agent ${targetAgentId}` });
|
||||
@@ -52,7 +52,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
|
||||
const targetAgentId = requireParam(params, "agentId");
|
||||
let targetAgent;
|
||||
try {
|
||||
targetAgent = db.entityCrud.getAgent(targetAgentId);
|
||||
targetAgent = db.core.entity.getAgent(targetAgentId);
|
||||
} catch (err) {
|
||||
log.warn(`[api/agent-control] getAgent failed for heartbeat ${targetAgentId}:`, err instanceof Error ? err.message : String(err));
|
||||
targetAgent = null;
|
||||
@@ -65,7 +65,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Current agent is not allowed to trigger heartbeat for this agent" });
|
||||
return;
|
||||
}
|
||||
const alreadyActive = db.runs.hasActiveRun({ companyId: token.companyId, agentId: targetAgentId });
|
||||
const alreadyActive = db.core.runs.hasActiveRun({ companyId: token.companyId, agentId: targetAgentId });
|
||||
const runId = onWakeAgent(targetAgentId, token.companyId, "peer_request");
|
||||
if (runId) {
|
||||
server.json(res, 200, { ok: true, runId, message: `Heartbeat triggered for agent ${targetAgentId}` });
|
||||
@@ -86,7 +86,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
|
||||
const agentId = requireParam(params, "agentId");
|
||||
let agent;
|
||||
try {
|
||||
agent = db.entityCrud.getAgent(agentId);
|
||||
agent = db.core.entity.getAgent(agentId);
|
||||
} catch (error) {
|
||||
log.warn(`[api/agent-skills:GET] getAgent(${agentId}) failed: ${error instanceof Error ? error.message : String(error)}`);
|
||||
agent = null;
|
||||
@@ -95,9 +95,9 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
|
||||
server.json(res, 404, { error: "Agent not found in your company" });
|
||||
return;
|
||||
}
|
||||
const skillIds = db.skills.listAgentSkillAssignments(agentId);
|
||||
const skillIds = db.core.skills.listAgentSkillAssignments(agentId);
|
||||
const skills = skillIds
|
||||
.map((sid) => db.skills.getCompanySkill(token.companyId, sid))
|
||||
.map((sid) => db.core.skills.getCompanySkill(token.companyId, sid))
|
||||
.filter((s): s is NonNullable<typeof s> => s != null);
|
||||
server.json(res, 200, skills.map((s) => ({
|
||||
id: s.id,
|
||||
@@ -118,7 +118,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
|
||||
}
|
||||
let agent;
|
||||
try {
|
||||
agent = db.entityCrud.getAgent(agentId);
|
||||
agent = db.core.entity.getAgent(agentId);
|
||||
} catch (error) {
|
||||
log.warn(`[api/agent-skills:POST] getAgent(${agentId}) failed: ${error instanceof Error ? error.message : String(error)}`);
|
||||
agent = null;
|
||||
@@ -127,12 +127,12 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
|
||||
server.json(res, 404, { error: "Agent not found in your company" });
|
||||
return;
|
||||
}
|
||||
const skill = db.skills.getCompanySkill(token.companyId, parsed.data.skillId);
|
||||
const skill = db.core.skills.getCompanySkill(token.companyId, parsed.data.skillId);
|
||||
if (!skill) {
|
||||
server.json(res, 404, { error: "Skill not found in your company" });
|
||||
return;
|
||||
}
|
||||
db.skills.assignSkillToAgent(agentId, parsed.data.skillId);
|
||||
db.core.skills.assignSkillToAgent(agentId, parsed.data.skillId);
|
||||
onDomainChanged();
|
||||
server.json(res, 200, { ok: true, message: `Skill "${skill.name}" assigned to agent ${agent.name}` });
|
||||
});
|
||||
@@ -142,7 +142,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
|
||||
const skillId = requireParam(params, "skillId");
|
||||
let agent;
|
||||
try {
|
||||
agent = db.entityCrud.getAgent(agentId);
|
||||
agent = db.core.entity.getAgent(agentId);
|
||||
} catch (error) {
|
||||
log.warn(`[api/agent-skills:DELETE] getAgent(${agentId}) failed: ${error instanceof Error ? error.message : String(error)}`);
|
||||
agent = null;
|
||||
@@ -151,7 +151,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) {
|
||||
server.json(res, 404, { error: "Agent not found in your company" });
|
||||
return;
|
||||
}
|
||||
db.skills.removeSkillFromAgent(agentId, skillId);
|
||||
db.core.skills.removeSkillFromAgent(agentId, skillId);
|
||||
onDomainChanged();
|
||||
server.json(res, 200, { ok: true, message: `Skill removed from agent ${agent.name}` });
|
||||
});
|
||||
|
||||
@@ -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.entityCrud.getAgent(token.agentId);
|
||||
const agent = db.core.entity.getAgent(token.agentId);
|
||||
if (!agent || agent.companyId !== token.companyId) {
|
||||
server.json(res, 404, { error: "Agent not found" });
|
||||
return;
|
||||
}
|
||||
|
||||
const directReports = db.agents.listDirectReportsForStandup(token.companyId, token.agentId);
|
||||
const directReports = db.core.agents.listDirectReportsForStandup(token.companyId, token.agentId);
|
||||
|
||||
const myTasks = db.tasks.listAssigneeTasksForStandup(token.companyId, token.agentId);
|
||||
const myTasks = db.core.tasks.listAssigneeTasksForStandup(token.companyId, token.agentId);
|
||||
|
||||
const reportTasks = db.tasks.listTasksForAssignees(
|
||||
const reportTasks = db.core.tasks.listTasksForAssignees(
|
||||
token.companyId,
|
||||
directReports.map((r) => r.id),
|
||||
);
|
||||
|
||||
const reportStatusRows = directReports.length > 0
|
||||
? db.agents.listReportStatusesForStandup(token.companyId, token.agentId)
|
||||
? db.core.agents.listReportStatusesForStandup(token.companyId, token.agentId)
|
||||
: [];
|
||||
|
||||
const tasksAwaitingMyReview = reportTasks.filter((t) => t.status === "in_review");
|
||||
@@ -33,20 +33,20 @@ export function registerAgentStandupRoute(server: AgentApiServer): void {
|
||||
...reportTasks.map((t) => t.id),
|
||||
]);
|
||||
const twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString();
|
||||
const recentComments = db.activityMod.listRecentTaskComments([...allRelevantTaskIds], twoHoursAgo, 20);
|
||||
const recentComments = db.core.activity.listRecentTaskComments([...allRelevantTaskIds], twoHoursAgo, 20);
|
||||
|
||||
const myPendingApprovals = db.approvalsMod.listAgentPendingApprovals(token.companyId, token.agentId);
|
||||
const myResolvedApprovals = db.approvalsMod.listAgentResolvedApprovals(token.companyId, token.agentId, 5);
|
||||
const myPendingApprovals = db.core.approvals.listAgentPendingApprovals(token.companyId, token.agentId);
|
||||
const myResolvedApprovals = db.core.approvals.listAgentResolvedApprovals(token.companyId, token.agentId, 5);
|
||||
|
||||
// Unread inbox lives in the standup briefing as the agent's
|
||||
// canonical view of pending communication. Pre-fix the agent had
|
||||
// to make a second API call to /messages?unreadOnly=true that the
|
||||
// model frequently skipped, so messages from peers and managers
|
||||
// sat dark while the agent posted heartbeat status comments.
|
||||
const unreadInbox = db.messages.listAgentInboxUnread(token.companyId, token.agentId);
|
||||
const unreadInbox = db.core.messages.listAgentInboxUnread(token.companyId, token.agentId);
|
||||
const senderIds = new Set(unreadInbox.map((m) => m.fromAgentId));
|
||||
const senderNames = senderIds.size > 0
|
||||
? new Map(db.agents.listAgentNamesByIds(token.companyId, Array.from(senderIds)).map((row) => [row.id, row.name]))
|
||||
? new Map(db.core.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
|
||||
@@ -59,10 +59,10 @@ export function registerAgentStandupRoute(server: AgentApiServer): void {
|
||||
// surface keeps the briefing readable.
|
||||
const RECENT_OUTPUT_LIMIT = 20;
|
||||
const myTaskIds = new Set(myTasks.map((t) => t.id));
|
||||
const recentDocuments = db.documentsMod.listDocuments(token.companyId)
|
||||
const recentDocuments = db.core.documents.listDocuments(token.companyId)
|
||||
.filter((doc) => doc.authorAgentId === token.agentId)
|
||||
.slice(0, RECENT_OUTPUT_LIMIT);
|
||||
const recentWorkProducts = db.documentsMod.listWorkProductsForCompany(token.companyId)
|
||||
const recentWorkProducts = db.core.documents.listWorkProductsForCompany(token.companyId)
|
||||
.filter((wp) => wp.taskId !== null && myTaskIds.has(wp.taskId))
|
||||
.slice(0, RECENT_OUTPUT_LIMIT);
|
||||
|
||||
@@ -71,7 +71,7 @@ export function registerAgentStandupRoute(server: AgentApiServer): void {
|
||||
...myTasks.map<[string, string]>((t) => [t.id, t.title]),
|
||||
...reportTasks.map<[string, string]>((t) => [t.id, t.title]),
|
||||
]);
|
||||
const socialAccounts = db.social.listSocialAccounts(token.companyId);
|
||||
const socialAccounts = db.core.social.listSocialAccounts(token.companyId);
|
||||
|
||||
server.json(res, 200, {
|
||||
agent: { id: agent.id, name: agent.name, role: agent.role, status: agent.status },
|
||||
|
||||
@@ -24,9 +24,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.entityCrud.getAgent(token.agentId);
|
||||
const chainOfCommand = db.agents.getChainOfCommand(token.agentId);
|
||||
const directReports = db.agents.getDirectReports(token.agentId, token.companyId);
|
||||
const agent = db.core.entity.getAgent(token.agentId);
|
||||
const chainOfCommand = db.core.agents.getChainOfCommand(token.agentId);
|
||||
const directReports = db.core.agents.getDirectReports(token.agentId, token.companyId);
|
||||
server.json(res, 200, { agent, chainOfCommand, directReports });
|
||||
});
|
||||
|
||||
@@ -36,7 +36,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
|
||||
// and the standup module is registered separately in api-server/index.ts.
|
||||
|
||||
server.addRoute("GET", "/api/agents/me/metrics", (_req, res, _params, token) => {
|
||||
const companyMetrics = db.company.getCompanyMetrics(token.companyId, 30);
|
||||
const companyMetrics = db.core.company.getCompanyMetrics(token.companyId, 30);
|
||||
const agentMetric = companyMetrics.agentMetrics.find(m => m.agentId === token.agentId);
|
||||
if (!agentMetric) {
|
||||
server.json(res, 404, { error: "Metrics not found" });
|
||||
@@ -47,12 +47,12 @@ export function registerAgentRoutes(server: AgentApiServer) {
|
||||
|
||||
server.addRoute("GET", "/api/agents/:agentId/metrics", (_req, res, params, token) => {
|
||||
const agentId = requireParam(params, "agentId");
|
||||
const agent = db.entityCrud.getAgent(agentId);
|
||||
const agent = db.core.entity.getAgent(agentId);
|
||||
if (!agent || agent.companyId !== token.companyId) {
|
||||
server.json(res, 404, { error: "Agent not found" });
|
||||
return;
|
||||
}
|
||||
const companyMetrics = db.company.getCompanyMetrics(token.companyId, 30);
|
||||
const companyMetrics = db.core.company.getCompanyMetrics(token.companyId, 30);
|
||||
const agentMetric = companyMetrics.agentMetrics.find((metric) => metric.agentId === agentId);
|
||||
if (!agentMetric) {
|
||||
server.json(res, 404, { error: "Metrics not found" });
|
||||
@@ -64,7 +64,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
|
||||
server.addRoute("GET", "/api/agents/:agentId", (_req, res, params, token) => {
|
||||
let agent;
|
||||
try {
|
||||
agent = db.entityCrud.getAgent(requireParam(params, "agentId"));
|
||||
agent = db.core.entity.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" });
|
||||
@@ -74,12 +74,12 @@ export function registerAgentRoutes(server: AgentApiServer) {
|
||||
server.json(res, 404, { error: "Agent not found" });
|
||||
return;
|
||||
}
|
||||
const directReports = db.agents.getDirectReports(agent.id, token.companyId);
|
||||
const directReports = db.core.agents.getDirectReports(agent.id, token.companyId);
|
||||
const reportsTo = agent.reportsTo;
|
||||
const manager = reportsTo
|
||||
? (() => {
|
||||
try {
|
||||
return db.entityCrud.getAgent(reportsTo);
|
||||
return db.core.entity.getAgent(reportsTo);
|
||||
} catch (error) {
|
||||
log.warn(`[api/agents] manager lookup failed for ${reportsTo}: ${error instanceof Error ? error.message : String(error)}`);
|
||||
return null;
|
||||
@@ -98,7 +98,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Company mismatch" });
|
||||
return;
|
||||
}
|
||||
const agents = db.agents.listAgentsForApi(params.companyId);
|
||||
const agents = db.core.agents.listAgentsForApi(params.companyId);
|
||||
server.json(res, 200, agents);
|
||||
});
|
||||
|
||||
@@ -183,14 +183,14 @@ export function registerAgentRoutes(server: AgentApiServer) {
|
||||
resolvedReportsTo &&
|
||||
resolvedReportsTo !== token.agentId &&
|
||||
!canManageOrganization(db, companyId, token.agentId) &&
|
||||
!db.agents.getChainOfCommand(resolvedReportsTo).some((agent) => agent.id === token.agentId)
|
||||
!db.core.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;
|
||||
}
|
||||
const connectorRecord = (() => {
|
||||
try {
|
||||
return db.connectorsCrud.getConnector(input.connectorId);
|
||||
return db.core.connectors.getConnector(input.connectorId);
|
||||
} catch (err) {
|
||||
log.warn(`[api/agents] getConnector failed for ${input.connectorId}:`, err instanceof Error ? err.message : String(err));
|
||||
return null;
|
||||
@@ -207,7 +207,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
|
||||
}
|
||||
|
||||
// Prevent duplicate agents: reject if a non-terminated agent with the same name already exists
|
||||
const existingAgents = db.agents.listExistingAgentsForHireCheck(companyId);
|
||||
const existingAgents = db.core.agents.listExistingAgentsForHireCheck(companyId);
|
||||
const duplicateByName = existingAgents.find(
|
||||
(a) => a.name.toLowerCase() === input.name.toLowerCase(),
|
||||
);
|
||||
@@ -216,7 +216,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
// Also check pending hire approvals with the same name to prevent concurrent duplicate requests
|
||||
const pendingHires = db.approvalsMod.listPendingHireApprovalPayloads(companyId);
|
||||
const pendingHires = db.core.approvals.listPendingHireApprovalPayloads(companyId);
|
||||
for (const pending of pendingHires) {
|
||||
try {
|
||||
const payload = pending.payloadJson ? JSON.parse(pending.payloadJson) as Record<string, unknown> : {};
|
||||
@@ -234,7 +234,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
|
||||
const managerLabel = resolvedReportsTo
|
||||
? (() => {
|
||||
try {
|
||||
return db.entityCrud.getAgent(resolvedReportsTo).name;
|
||||
return db.core.entity.getAgent(resolvedReportsTo).name;
|
||||
} catch (err) {
|
||||
log.warn(`[api/agents] getAgent failed for manager ${resolvedReportsTo}:`, err instanceof Error ? err.message : String(err));
|
||||
return resolvedReportsTo;
|
||||
@@ -283,7 +283,7 @@ export function registerAgentRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
db.activityMod.addActivity({
|
||||
db.core.activity.addActivity({
|
||||
companyId,
|
||||
actor: token.agentId,
|
||||
action: "agent.hire_requested",
|
||||
|
||||
@@ -74,7 +74,7 @@ export function registerApprovalRoutes(server: AgentApiServer) {
|
||||
// Reject the request at the API boundary so the model cannot
|
||||
// circumvent the ordering by resubmitting.
|
||||
if (input.type === "approve_ceo_strategy") {
|
||||
const companyHireApprovals = db.approvalsMod.listCompanyApprovalsByType(companyId, "hire_agent");
|
||||
const companyHireApprovals = db.core.approvals.listCompanyApprovalsByType(companyId, "hire_agent");
|
||||
if (companyHireApprovals.length === 0) {
|
||||
server.json(res, 409, {
|
||||
error: "approve_ceo_strategy requires at least one hire_agent approval to exist first. Submit the intended hires, then file the strategy.",
|
||||
@@ -82,7 +82,7 @@ export function registerApprovalRoutes(server: AgentApiServer) {
|
||||
});
|
||||
return;
|
||||
}
|
||||
const existingStrategy = db.approvalsMod.listCompanyApprovalsByType(companyId, "approve_ceo_strategy")
|
||||
const existingStrategy = db.core.approvals.listCompanyApprovalsByType(companyId, "approve_ceo_strategy")
|
||||
.find((a) => a.state === "pending" || a.state === "approved");
|
||||
if (existingStrategy) {
|
||||
server.json(res, 409, {
|
||||
@@ -117,7 +117,7 @@ export function registerApprovalRoutes(server: AgentApiServer) {
|
||||
|
||||
let id: string;
|
||||
try {
|
||||
id = db.approvalsMod.requestApproval({
|
||||
id = db.core.approvals.requestApproval({
|
||||
companyId,
|
||||
type: input.type,
|
||||
relatedTaskId: input.relatedTaskId ?? null,
|
||||
@@ -132,7 +132,7 @@ export function registerApprovalRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
db.activityMod.addActivity({
|
||||
db.core.activity.addActivity({
|
||||
companyId,
|
||||
actor: token.agentId,
|
||||
action: "approval.created",
|
||||
@@ -186,7 +186,7 @@ export function registerApprovalRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
const statuses = parsedQuery.data.status?.split(",").filter(Boolean) ?? null;
|
||||
const approvals = db.approvalsMod.listApprovalsForApi(companyId, {
|
||||
const approvals = db.core.approvals.listApprovalsForApi(companyId, {
|
||||
requestedByAgentId: parsedQuery.data.requestedByAgentId,
|
||||
relatedTaskId: parsedQuery.data.relatedTaskId,
|
||||
statuses,
|
||||
@@ -195,7 +195,7 @@ export function registerApprovalRoutes(server: AgentApiServer) {
|
||||
});
|
||||
|
||||
server.addRoute("GET", "/api/approvals/:approvalId", (_req, res, params, token) => {
|
||||
const approval = db.approvalsMod.findApprovalById(requireParam(params, "approvalId"));
|
||||
const approval = db.core.approvals.findApprovalById(requireParam(params, "approvalId"));
|
||||
if (!approval || approval.companyId !== token.companyId) {
|
||||
server.json(res, 404, { error: "Approval not found" });
|
||||
return;
|
||||
@@ -209,28 +209,28 @@ export function registerApprovalRoutes(server: AgentApiServer) {
|
||||
|
||||
server.addRoute("GET", "/api/approvals/:approvalId/comments", (_req, res, params, token) => {
|
||||
const approvalId = requireParam(params, "approvalId");
|
||||
const approval = db.approvalsMod.findApprovalById(approvalId);
|
||||
const approval = db.core.approvals.findApprovalById(approvalId);
|
||||
if (!approval) { server.json(res, 404, { error: "Approval not found" }); return; }
|
||||
if (approval.companyId !== token.companyId) { server.json(res, 403, { error: "Company mismatch" }); return; }
|
||||
const comments = db.approvalsMod.listApprovalComments(approvalId, approval.companyId);
|
||||
const comments = db.core.approvals.listApprovalComments(approvalId, approval.companyId);
|
||||
server.json(res, 200, comments);
|
||||
});
|
||||
|
||||
server.addRoute("POST", "/api/approvals/:approvalId/comments", (_req, res, params, token, body) => {
|
||||
const approval = db.approvalsMod.findApprovalById(requireParam(params, "approvalId"));
|
||||
const approval = db.core.approvals.findApprovalById(requireParam(params, "approvalId"));
|
||||
if (!approval) { server.json(res, 404, { error: "Approval not found" }); return; }
|
||||
if (approval.companyId !== token.companyId) { server.json(res, 403, { error: "Company mismatch" }); return; }
|
||||
const data = body as Record<string, unknown>;
|
||||
const commentBody = typeof data.body === "string" ? data.body.trim() : "";
|
||||
if (!commentBody) { server.json(res, 400, { error: "Comment body is required" }); return; }
|
||||
const commentId = db.approvalsMod.addApprovalComment({
|
||||
const commentId = db.core.approvals.addApprovalComment({
|
||||
companyId: approval.companyId,
|
||||
approvalId: approval.id,
|
||||
authorAgentId: token.agentId ?? null,
|
||||
body: commentBody,
|
||||
});
|
||||
// Wake mentioned agents in comment
|
||||
const mentionedIds = db.agents.findMentionedAgentIds(approval.companyId, commentBody);
|
||||
const mentionedIds = db.core.agents.findMentionedAgentIds(approval.companyId, commentBody);
|
||||
for (const mentionedId of mentionedIds) {
|
||||
if (mentionedId !== token.agentId) {
|
||||
onWakeAgent(mentionedId, approval.companyId, "approval_comment_mentioned");
|
||||
@@ -241,7 +241,7 @@ export function registerApprovalRoutes(server: AgentApiServer) {
|
||||
});
|
||||
|
||||
server.addRoute("POST", "/api/approvals/:approvalId/resubmit", (_req, res, params, token) => {
|
||||
const approval = db.approvalsMod.findApprovalById(requireParam(params, "approvalId"));
|
||||
const approval = db.core.approvals.findApprovalById(requireParam(params, "approvalId"));
|
||||
if (!approval) { server.json(res, 404, { error: "Approval not found" }); return; }
|
||||
if (approval.companyId !== token.companyId) { server.json(res, 403, { error: "Company mismatch" }); return; }
|
||||
if (approval.state !== "revision_requested") {
|
||||
@@ -252,34 +252,34 @@ export function registerApprovalRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Only the requesting agent can resubmit this approval" });
|
||||
return;
|
||||
}
|
||||
db.approvalsMod.resubmitApproval(approval.id, approval.companyId);
|
||||
db.core.approvals.resubmitApproval(approval.id, approval.companyId);
|
||||
onDomainChanged();
|
||||
server.json(res, 200, { resubmitted: true });
|
||||
});
|
||||
|
||||
server.addRoute("GET", "/api/approvals/:approvalId/tasks", (_req, res, params, token) => {
|
||||
const approvalId = requireParam(params, "approvalId");
|
||||
const approval = db.approvalsMod.findApprovalById(approvalId);
|
||||
const approval = db.core.approvals.findApprovalById(approvalId);
|
||||
if (!approval) { server.json(res, 404, { error: "Approval not found" }); return; }
|
||||
if (approval.companyId !== token.companyId) { server.json(res, 403, { error: "Company mismatch" }); return; }
|
||||
const taskIds = db.approvalsMod.listTasksForApproval(approvalId);
|
||||
const taskIds = db.core.approvals.listTasksForApproval(approvalId);
|
||||
server.json(res, 200, taskIds);
|
||||
});
|
||||
|
||||
server.addRoute("POST", "/api/approvals/:approvalId/tasks", (_req, res, params, token, body) => {
|
||||
const approvalId = requireParam(params, "approvalId");
|
||||
const approval = db.approvalsMod.findApprovalById(approvalId);
|
||||
const approval = db.core.approvals.findApprovalById(approvalId);
|
||||
if (!approval) { server.json(res, 404, { error: "Approval not found" }); return; }
|
||||
if (approval.companyId !== token.companyId) { server.json(res, 403, { error: "Company mismatch" }); return; }
|
||||
const data = body as Record<string, unknown>;
|
||||
const taskIds = Array.isArray(data.taskIds) ? data.taskIds.filter((id): id is string => typeof id === "string") : [];
|
||||
if (taskIds.length === 0) { server.json(res, 400, { error: "taskIds array is required" }); return; }
|
||||
for (const taskId of taskIds) {
|
||||
if (!db.settings.belongsToCompany("tasks", taskId, token.companyId)) {
|
||||
if (!db.core.settings.belongsToCompany("tasks", taskId, token.companyId)) {
|
||||
server.json(res, 400, { error: `Task ${taskId} does not belong to this company` }); return;
|
||||
}
|
||||
}
|
||||
db.approvalsMod.linkManyTasksToApproval(approvalId, taskIds, token.companyId, token.agentId ?? null);
|
||||
db.core.approvals.linkManyTasksToApproval(approvalId, taskIds, token.companyId, token.agentId ?? null);
|
||||
onDomainChanged();
|
||||
server.json(res, 200, { linked: taskIds.length });
|
||||
});
|
||||
|
||||
@@ -71,15 +71,15 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
const reviewerAgentId = data.reviewerAgentId ?? null;
|
||||
const projectId = data.projectId ?? null;
|
||||
const goalId = data.goalId ?? null;
|
||||
if (reviewerAgentId && !db.settings.belongsToCompany("agents", reviewerAgentId, token.companyId)) {
|
||||
if (reviewerAgentId && !db.core.settings.belongsToCompany("agents", reviewerAgentId, token.companyId)) {
|
||||
server.json(res, 400, { error: "Reviewer agent does not belong to the current company" });
|
||||
return;
|
||||
}
|
||||
if (projectId && !db.settings.belongsToCompany("projects", projectId, token.companyId)) {
|
||||
if (projectId && !db.core.settings.belongsToCompany("projects", projectId, token.companyId)) {
|
||||
server.json(res, 400, { error: "Project does not belong to the current company" });
|
||||
return;
|
||||
}
|
||||
if (goalId && !db.settings.belongsToCompany("goals", goalId, token.companyId)) {
|
||||
if (goalId && !db.core.settings.belongsToCompany("goals", goalId, token.companyId)) {
|
||||
server.json(res, 400, { error: "Goal does not belong to the current company" });
|
||||
return;
|
||||
}
|
||||
@@ -114,7 +114,7 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Company mismatch" });
|
||||
return;
|
||||
}
|
||||
const docs = db.documentsMod.listDocuments(token.companyId);
|
||||
const docs = db.core.documents.listDocuments(token.companyId);
|
||||
server.json(res, 200, docs);
|
||||
});
|
||||
|
||||
@@ -128,7 +128,7 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
server.json(res, 400, { error: "Missing documentId" });
|
||||
return;
|
||||
}
|
||||
const doc = db.documentsMod.getDocumentForUpdate(documentId, token.companyId);
|
||||
const doc = db.core.documents.getDocumentForUpdate(documentId, token.companyId);
|
||||
if (!doc) {
|
||||
server.json(res, 404, { error: "Document not found in this company" });
|
||||
return;
|
||||
@@ -146,7 +146,7 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
server.json(res, 400, { error: "Missing documentId" });
|
||||
return;
|
||||
}
|
||||
const doc = db.documentsMod.getDocumentForUpdate(documentId, token.companyId);
|
||||
const doc = db.core.documents.getDocumentForUpdate(documentId, token.companyId);
|
||||
if (!doc) {
|
||||
server.json(res, 404, { error: "Document not found in this company" });
|
||||
return;
|
||||
@@ -158,14 +158,14 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
const reviewerAgentId = data.reviewerAgentId !== undefined
|
||||
? (data.reviewerAgentId ?? null)
|
||||
: doc.reviewerAgentId;
|
||||
if (data.reviewerAgentId !== undefined && reviewerAgentId && !db.settings.belongsToCompany("agents", reviewerAgentId, token.companyId)) {
|
||||
if (data.reviewerAgentId !== undefined && reviewerAgentId && !db.core.settings.belongsToCompany("agents", reviewerAgentId, token.companyId)) {
|
||||
server.json(res, 400, { error: "Reviewer agent does not belong to the current company" });
|
||||
return;
|
||||
}
|
||||
|
||||
// Conflict detection: if baseRevisionId provided, verify it matches current
|
||||
if (data.baseRevisionId !== undefined) {
|
||||
const currentRevId = db.documentsMod.getDocumentLatestRevisionId(documentId);
|
||||
const currentRevId = db.core.documents.getDocumentLatestRevisionId(documentId);
|
||||
if (currentRevId && data.baseRevisionId !== currentRevId) {
|
||||
server.json(res, 409, { error: "Document was updated by someone else", currentRevisionId: currentRevId });
|
||||
return;
|
||||
@@ -182,7 +182,7 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
// Content update → create revision for audit trail
|
||||
let updatedVersion = doc.version;
|
||||
if (data.content !== undefined) {
|
||||
const revision = db.documentsMod.createDocumentRevision({
|
||||
const revision = db.core.documents.createDocumentRevision({
|
||||
documentId,
|
||||
companyId: token.companyId,
|
||||
body: data.content,
|
||||
@@ -194,9 +194,9 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
|
||||
// Field updates (title, reviewer, tags, etc.)
|
||||
if (data.status !== undefined) {
|
||||
db.documentsMod.updateDocumentStatus(documentId, token.companyId, data.status);
|
||||
db.core.documents.updateDocumentStatus(documentId, token.companyId, data.status);
|
||||
}
|
||||
db.documentsMod.saveDocument({
|
||||
db.core.documents.saveDocument({
|
||||
id: documentId,
|
||||
companyId: token.companyId,
|
||||
type: data.type ?? doc.type,
|
||||
@@ -213,14 +213,14 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
});
|
||||
|
||||
onDomainChanged();
|
||||
server.json(res, 200, { updated: true, latestRevisionId: db.documentsMod.getDocumentLatestRevisionId(documentId) });
|
||||
server.json(res, 200, { updated: true, latestRevisionId: db.core.documents.getDocumentLatestRevisionId(documentId) });
|
||||
});
|
||||
|
||||
server.addRoute("GET", "/api/companies/:companyId/documents/:documentId/revisions", (_req, res, params, token) => {
|
||||
if (params.companyId !== token.companyId) { server.json(res, 403, { error: "Company mismatch" }); return; }
|
||||
const documentId = params.documentId;
|
||||
if (!documentId) { server.json(res, 400, { error: "Missing documentId" }); return; }
|
||||
const revisions = db.documentsMod.listDocumentRevisions(documentId, token.companyId);
|
||||
const revisions = db.core.documents.listDocumentRevisions(documentId, token.companyId);
|
||||
server.json(res, 200, revisions);
|
||||
});
|
||||
|
||||
@@ -228,9 +228,9 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
|
||||
server.addRoute("GET", "/api/issues/:issueId/work-products", (_req, res, params, token) => {
|
||||
try {
|
||||
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
|
||||
const task = db.core.entity.getTask(requireParam(params, "issueId"));
|
||||
if (task.companyId !== token.companyId) { server.json(res, 404, { error: "Task not found" }); return; }
|
||||
const products = db.documentsMod.listWorkProductsForTask(task.id, task.companyId);
|
||||
const products = db.core.documents.listWorkProductsForTask(task.id, task.companyId);
|
||||
server.json(res, 200, products);
|
||||
} catch (error) {
|
||||
log.warn(`[api/work-products] list failed for issue ${params.issueId}: ${error instanceof Error ? error.message : String(error)}`);
|
||||
@@ -240,12 +240,12 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
|
||||
server.addRoute("POST", "/api/issues/:issueId/work-products", (_req, res, params, token, body) => {
|
||||
try {
|
||||
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
|
||||
const task = db.core.entity.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; }
|
||||
const data = parsed.data;
|
||||
const id = db.documentsMod.createWorkProduct({
|
||||
const id = db.core.documents.createWorkProduct({
|
||||
companyId: task.companyId,
|
||||
taskId: task.id,
|
||||
projectId: data.projectId ?? task.projectId,
|
||||
@@ -275,7 +275,7 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
if (!wpId) { server.json(res, 400, { error: "Missing workProductId" }); return; }
|
||||
const parsed = updateWorkProductSchema.safeParse(body);
|
||||
if (!parsed.success) { server.json(res, 400, { error: "Invalid input", details: parsed.error.flatten() }); return; }
|
||||
const changes = db.documentsMod.updateWorkProduct(wpId, token.companyId, parsed.data);
|
||||
const changes = db.core.documents.updateWorkProduct(wpId, token.companyId, parsed.data);
|
||||
if (changes === 0) { server.json(res, 404, { error: "Work product not found" }); return; }
|
||||
onDomainChanged();
|
||||
server.json(res, 200, { updated: true });
|
||||
@@ -284,7 +284,7 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
server.addRoute("DELETE", "/api/work-products/:workProductId", (_req, res, params, token) => {
|
||||
const wpId = params.workProductId;
|
||||
if (!wpId) { server.json(res, 400, { error: "Missing workProductId" }); return; }
|
||||
const changes = db.documentsMod.deleteWorkProduct(wpId, token.companyId);
|
||||
const changes = db.core.documents.deleteWorkProduct(wpId, token.companyId);
|
||||
if (changes === 0) { server.json(res, 404, { error: "Work product not found" }); return; }
|
||||
onDomainChanged();
|
||||
server.json(res, 200, { deleted: true });
|
||||
@@ -294,9 +294,9 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
|
||||
server.addRoute("GET", "/api/issues/:issueId/documents", (_req, res, params, token) => {
|
||||
try {
|
||||
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
|
||||
const task = db.core.entity.getTask(requireParam(params, "issueId"));
|
||||
if (task.companyId !== token.companyId) { server.json(res, 404, { error: "Task not found" }); return; }
|
||||
const links = db.documentsMod.listDocumentsForTask(task.id, task.companyId);
|
||||
const links = db.core.documents.listDocumentsForTask(task.id, task.companyId);
|
||||
server.json(res, 200, links);
|
||||
} catch (error) {
|
||||
log.warn(`[api/task-documents] list failed for issue ${params.issueId}: ${error instanceof Error ? error.message : String(error)}`);
|
||||
@@ -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.entityCrud.getTask(requireParam(params, "issueId"));
|
||||
const task = db.core.entity.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) {
|
||||
@@ -315,10 +315,10 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
const parsed = linkDocumentSchema.safeParse(body);
|
||||
if (!parsed.success) { server.json(res, 400, { error: "Invalid input", details: parsed.error.flatten() }); return; }
|
||||
const documentId = parsed.data.documentId;
|
||||
if (!db.settings.belongsToCompany("documents", documentId, token.companyId)) {
|
||||
if (!db.core.settings.belongsToCompany("documents", documentId, token.companyId)) {
|
||||
server.json(res, 400, { error: "Document does not belong to this company" }); return;
|
||||
}
|
||||
const linkId = db.documentsMod.linkDocumentToTask(task.id, documentId, task.companyId, key);
|
||||
const linkId = db.core.documents.linkDocumentToTask(task.id, documentId, task.companyId, key);
|
||||
onDomainChanged();
|
||||
server.json(res, 200, { id: linkId, key });
|
||||
} catch (error) {
|
||||
@@ -329,10 +329,10 @@ export function registerFileRoutes(server: AgentApiServer) {
|
||||
|
||||
server.addRoute("DELETE", "/api/issues/:issueId/documents/:key", (_req, res, params, token) => {
|
||||
try {
|
||||
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
|
||||
const task = db.core.entity.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.documentsMod.unlinkDocumentFromTask(task.id, key, task.companyId);
|
||||
db.core.documents.unlinkDocumentFromTask(task.id, key, task.companyId);
|
||||
onDomainChanged();
|
||||
server.json(res, 200, { unlinked: true });
|
||||
} catch (error) {
|
||||
|
||||
@@ -33,7 +33,7 @@ export function registerMeetingRoutes(server: AgentApiServer) {
|
||||
try {
|
||||
const parsedParticipants = JSON.parse(input.participantAgentIds) as string[];
|
||||
for (const agentId of parsedParticipants) {
|
||||
if (typeof agentId !== "string" || !db.settings.belongsToCompany("agents", agentId, token.companyId)) {
|
||||
if (typeof agentId !== "string" || !db.core.settings.belongsToCompany("agents", agentId, token.companyId)) {
|
||||
server.json(res, 400, { error: "Meeting participants must belong to the current company" });
|
||||
return;
|
||||
}
|
||||
@@ -43,7 +43,7 @@ export function registerMeetingRoutes(server: AgentApiServer) {
|
||||
server.json(res, 400, { error: "participantAgentIds must be a JSON array of agent ids" });
|
||||
return;
|
||||
}
|
||||
const id = db.knowledgeMod.saveMeeting({
|
||||
const id = db.core.knowledge.saveMeeting({
|
||||
companyId: token.companyId,
|
||||
type: input.type,
|
||||
title: input.title,
|
||||
@@ -63,13 +63,13 @@ export function registerMeetingRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Company mismatch" });
|
||||
return;
|
||||
}
|
||||
const meetings = db.knowledgeMod.listMeetings(token.companyId);
|
||||
const meetings = db.core.knowledge.listMeetings(token.companyId);
|
||||
server.json(res, 200, meetings);
|
||||
});
|
||||
|
||||
server.addRoute("PATCH", "/api/meetings/:meetingId", (_req, res, params, token, body) => {
|
||||
const meetingId = requireParam(params, "meetingId");
|
||||
const existing = db.knowledgeMod.getMeeting(meetingId, token.companyId);
|
||||
const existing = db.core.knowledge.getMeeting(meetingId, token.companyId);
|
||||
if (!existing) {
|
||||
server.json(res, 404, { error: "Meeting not found" });
|
||||
return;
|
||||
@@ -102,13 +102,13 @@ export function registerMeetingRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
for (const item of actionItems) {
|
||||
if (item.assigneeAgentId && !db.settings.belongsToCompany("agents", item.assigneeAgentId, token.companyId)) {
|
||||
if (item.assigneeAgentId && !db.core.settings.belongsToCompany("agents", item.assigneeAgentId, token.companyId)) {
|
||||
server.json(res, 400, { error: "Meeting action item assignees must belong to the current company" });
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
db.knowledgeMod.saveMeeting({
|
||||
db.core.knowledge.saveMeeting({
|
||||
id: meetingId,
|
||||
companyId: token.companyId,
|
||||
type: data.type ?? "department_sync",
|
||||
@@ -133,7 +133,7 @@ export function registerMeetingRoutes(server: AgentApiServer) {
|
||||
);
|
||||
continue;
|
||||
}
|
||||
db.tasks.saveTask({
|
||||
db.core.tasks.saveTask({
|
||||
companyId: token.companyId,
|
||||
title: item.title,
|
||||
description: item.description ?? `Action item from meeting: ${data.title ?? existing.title}`,
|
||||
|
||||
@@ -20,13 +20,13 @@ export function registerMessageRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
|
||||
const task = db.core.entity.getTask(requireParam(params, "issueId"));
|
||||
if (task.companyId !== token.companyId) {
|
||||
server.json(res, 404, { error: "Task not found" });
|
||||
return;
|
||||
}
|
||||
const agent = db.entityCrud.getAgent(token.agentId);
|
||||
const comment = db.activityMod.addComment({
|
||||
const agent = db.core.entity.getAgent(token.agentId);
|
||||
const comment = db.core.activity.addComment({
|
||||
companyId: task.companyId,
|
||||
taskId: task.id,
|
||||
authorAgentId: token.agentId,
|
||||
@@ -44,14 +44,14 @@ export function registerMessageRoutes(server: AgentApiServer) {
|
||||
wokenForComment.add(task.assigneeAgentId);
|
||||
}
|
||||
|
||||
const chain = db.agents.getChainOfCommand(token.agentId);
|
||||
const chain = db.core.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.agents.findMentionedAgentIds(task.companyId, input.body);
|
||||
const mentionedIds = db.core.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.entityCrud.getTask(requireParam(params, "issueId"));
|
||||
const task = db.core.entity.getTask(requireParam(params, "issueId"));
|
||||
if (task.companyId !== token.companyId) {
|
||||
server.json(res, 404, { error: "Task not found" });
|
||||
return;
|
||||
@@ -78,7 +78,7 @@ export function registerMessageRoutes(server: AgentApiServer) {
|
||||
server.json(res, 404, { error: "Task not found" });
|
||||
return;
|
||||
}
|
||||
const comments = db.activityMod.listComments(requireParam(params, "issueId"));
|
||||
const comments = db.core.activity.listComments(requireParam(params, "issueId"));
|
||||
server.json(res, 200, comments);
|
||||
});
|
||||
|
||||
@@ -142,7 +142,7 @@ export function registerMessageRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const messages = db.messages.listAgentMessages(companyId, {
|
||||
const messages = db.core.messages.listAgentMessages(companyId, {
|
||||
agentId: token.agentId,
|
||||
channel: channelParam ?? undefined,
|
||||
channelTargetId: channelTargetId && channelTargetId.length > 0 ? channelTargetId : undefined,
|
||||
@@ -158,12 +158,12 @@ export function registerMessageRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Company mismatch" });
|
||||
return;
|
||||
}
|
||||
const message = db.messages.getAgentMessage(requireParam(params, "messageId"), companyId);
|
||||
const message = db.core.messages.getAgentMessage(requireParam(params, "messageId"), companyId);
|
||||
if (!message) {
|
||||
server.json(res, 404, { error: "Message not found" });
|
||||
return;
|
||||
}
|
||||
const visibleToAgent = db.messages.listAgentMessages(companyId, {
|
||||
const visibleToAgent = db.core.messages.listAgentMessages(companyId, {
|
||||
agentId: token.agentId,
|
||||
messageId: message.id,
|
||||
limit: 1,
|
||||
@@ -172,7 +172,7 @@ export function registerMessageRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "This message is not visible to the current agent" });
|
||||
return;
|
||||
}
|
||||
db.messages.markMessageReadForReader(requireParam(params, "messageId"), companyId, token.agentId);
|
||||
db.core.messages.markMessageReadForReader(requireParam(params, "messageId"), companyId, token.agentId);
|
||||
onDomainChanged();
|
||||
server.json(res, 200, { ok: true });
|
||||
});
|
||||
|
||||
@@ -34,7 +34,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
|
||||
const input = parsed.data;
|
||||
|
||||
const account = db.social.getSocialAccount(input.socialAccountId, companyId);
|
||||
const account = db.core.social.getSocialAccount(input.socialAccountId, companyId);
|
||||
if (!account) {
|
||||
server.json(res, 404, { error: "Social account not found" });
|
||||
return;
|
||||
@@ -42,7 +42,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
|
||||
const postActions = ["post", "reply", "dm"];
|
||||
if (account.requireApproval && postActions.includes(input.actionType)) {
|
||||
const approvalId = db.approvalsMod.requestApproval({
|
||||
const approvalId = db.core.approvals.requestApproval({
|
||||
companyId,
|
||||
type: "dangerous_command",
|
||||
relatedTaskId: null,
|
||||
@@ -51,7 +51,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
impactSummary: `Will ${input.actionType} on ${account.displayName || account.accountName}'s ${account.platform} account. Content will be publicly visible.`,
|
||||
});
|
||||
|
||||
const actionId = db.social.saveBrowserAction({
|
||||
const actionId = db.core.social.saveBrowserAction({
|
||||
companyId,
|
||||
socialAccountId: input.socialAccountId,
|
||||
agentId: token.agentId,
|
||||
@@ -61,7 +61,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
approvalId,
|
||||
});
|
||||
|
||||
db.activityMod.addActivity({
|
||||
db.core.activity.addActivity({
|
||||
companyId,
|
||||
actor: token.agentId,
|
||||
action: "browser.action_pending_approval",
|
||||
@@ -75,7 +75,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const actionId = db.social.saveBrowserAction({
|
||||
const actionId = db.core.social.saveBrowserAction({
|
||||
companyId,
|
||||
socialAccountId: input.socialAccountId,
|
||||
agentId: token.agentId,
|
||||
@@ -84,7 +84,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
status: "queued",
|
||||
});
|
||||
|
||||
db.activityMod.addActivity({
|
||||
db.core.activity.addActivity({
|
||||
companyId,
|
||||
actor: token.agentId,
|
||||
action: "browser.action_queued",
|
||||
@@ -108,7 +108,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Company mismatch" });
|
||||
return;
|
||||
}
|
||||
const accounts = db.social.listSocialAccounts(requireParam(params, "companyId"));
|
||||
const accounts = db.core.social.listSocialAccounts(requireParam(params, "companyId"));
|
||||
const sanitized = accounts.map(a => ({
|
||||
id: a.id,
|
||||
platform: a.platform,
|
||||
@@ -134,7 +134,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const account = db.social.getSocialAccount(parsed.data.socialAccountId, companyId);
|
||||
const account = db.core.social.getSocialAccount(parsed.data.socialAccountId, companyId);
|
||||
if (!account) {
|
||||
server.json(res, 404, { error: "Social account not found" });
|
||||
return;
|
||||
@@ -142,7 +142,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
|
||||
const contentPreview = parsed.data.content.slice(0, 120) + (parsed.data.content.length > 120 ? "..." : "");
|
||||
|
||||
const approvalId = db.approvalsMod.requestApproval({
|
||||
const approvalId = db.core.approvals.requestApproval({
|
||||
companyId,
|
||||
requestedByAgentId: token.agentId,
|
||||
type: "social_post",
|
||||
@@ -171,7 +171,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
const status = url.searchParams.get("status") ?? undefined;
|
||||
const limit = Number(url.searchParams.get("limit") || 50);
|
||||
|
||||
const actions = db.social.listBrowserActions(requireParam(params, "companyId"), { socialAccountId, status, limit });
|
||||
const actions = db.core.social.listBrowserActions(requireParam(params, "companyId"), { socialAccountId, status, limit });
|
||||
server.json(res, 200, actions);
|
||||
});
|
||||
|
||||
@@ -198,7 +198,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
}
|
||||
|
||||
const input = parsed.data;
|
||||
const id = db.knowledgeMod.saveKnowledgeEntry({
|
||||
const id = db.core.knowledge.saveKnowledgeEntry({
|
||||
companyId: token.companyId,
|
||||
category: input.category,
|
||||
topic: input.topic,
|
||||
@@ -219,7 +219,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Company mismatch" });
|
||||
return;
|
||||
}
|
||||
const entries = db.knowledgeMod.listKnowledgeEntries(token.companyId);
|
||||
const entries = db.core.knowledge.listKnowledgeEntries(token.companyId);
|
||||
server.json(res, 200, entries);
|
||||
});
|
||||
|
||||
@@ -231,7 +231,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Company mismatch" });
|
||||
return;
|
||||
}
|
||||
const skills = db.skills.listCompanySkills(companyId);
|
||||
const skills = db.core.skills.listCompanySkills(companyId);
|
||||
server.json(res, 200, skills.map((s) => ({
|
||||
id: s.id,
|
||||
name: s.name,
|
||||
@@ -244,7 +244,7 @@ export function registerMiscRoutes(server: AgentApiServer) {
|
||||
});
|
||||
|
||||
server.addRoute("GET", "/api/skills/:skillId", (_req, res, params, token) => {
|
||||
const skill = db.skills.getCompanySkill(token.companyId, requireParam(params, "skillId"));
|
||||
const skill = db.core.skills.getCompanySkill(token.companyId, requireParam(params, "skillId"));
|
||||
if (!skill) {
|
||||
server.json(res, 404, { error: "Skill not found" });
|
||||
return;
|
||||
|
||||
@@ -16,7 +16,7 @@ function parsePositiveInt(value: string | null, fallback: number) {
|
||||
}
|
||||
|
||||
function resolveAuthorizedRun(server: AgentApiServer, token: TokenPayload, runId: string) {
|
||||
const runState = server.db.runs.getRunAuthState(runId);
|
||||
const runState = server.db.core.runs.getRunAuthState(runId);
|
||||
if (!runState || runState.companyId !== token.companyId || runState.agentId !== token.agentId) {
|
||||
return null;
|
||||
}
|
||||
@@ -40,7 +40,7 @@ export function registerRunRoutes(server: AgentApiServer) {
|
||||
const url = new URL(req.url ?? "/", `http://127.0.0.1:${server.port}`);
|
||||
const offset = parsePositiveInt(url.searchParams.get("offset"), 0);
|
||||
const limit = Math.min(parsePositiveInt(url.searchParams.get("limit"), DEFAULT_EVENT_LIMIT), MAX_EVENT_LIMIT);
|
||||
const events = server.db.runs.listRunEvents(runId, token.companyId, { offset, limit });
|
||||
const events = server.db.core.runs.listRunEvents(runId, token.companyId, { offset, limit });
|
||||
server.json(res, 200, { events, nextOffset: offset + events.length });
|
||||
});
|
||||
|
||||
@@ -66,7 +66,7 @@ export function registerRunRoutes(server: AgentApiServer) {
|
||||
|
||||
const flushPendingEvents = () => {
|
||||
while (true) {
|
||||
const events = server.db.runs.listRunEventsAfter(runId, token.companyId, cursor, SSE_BATCH_LIMIT);
|
||||
const events = server.db.core.runs.listRunEventsAfter(runId, token.companyId, cursor, SSE_BATCH_LIMIT);
|
||||
if (events.length === 0) return;
|
||||
for (const event of events) {
|
||||
writeSse(res, "run-event", event);
|
||||
|
||||
@@ -39,17 +39,17 @@ export function registerTaskRoutes(server: AgentApiServer) {
|
||||
const statuses = statusFilter ? statusFilter.split(",") : ["todo", "in_progress", "blocked"];
|
||||
|
||||
if (assigneeAgentId) {
|
||||
const tasks = db.tasks.listAgentTasks(assigneeAgentId, companyId, statuses);
|
||||
const tasks = db.core.tasks.listAgentTasks(assigneeAgentId, companyId, statuses);
|
||||
server.json(res, 200, tasks);
|
||||
} else {
|
||||
const tasks = db.tasks.listTasksByStatuses(companyId, statuses);
|
||||
const tasks = db.core.tasks.listTasksByStatuses(companyId, statuses);
|
||||
server.json(res, 200, tasks);
|
||||
}
|
||||
});
|
||||
|
||||
server.addRoute("GET", "/api/issues/:issueId", (_req, res, params, token) => {
|
||||
try {
|
||||
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
|
||||
const task = db.core.entity.getTask(requireParam(params, "issueId"));
|
||||
if (task.companyId !== token.companyId) {
|
||||
server.json(res, 404, { error: "Task not found" });
|
||||
return;
|
||||
@@ -74,7 +74,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
|
||||
}
|
||||
let task;
|
||||
try {
|
||||
task = db.entityCrud.getTask(requireParam(params, "issueId"));
|
||||
task = db.core.entity.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" });
|
||||
@@ -89,7 +89,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
const previousStatus = task.status;
|
||||
const success = db.tasks.checkoutTask(task.id, token.runId);
|
||||
const success = db.core.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;
|
||||
@@ -109,7 +109,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
|
||||
const update = parsedUpdate.data;
|
||||
|
||||
try {
|
||||
const task = db.entityCrud.getTask(requireParam(params, "issueId"));
|
||||
const task = db.core.entity.getTask(requireParam(params, "issueId"));
|
||||
if (task.companyId !== token.companyId) {
|
||||
server.json(res, 404, { error: "Task not found" });
|
||||
return;
|
||||
@@ -133,10 +133,10 @@ export function registerTaskRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const actorAgent = db.entityCrud.getAgent(token.agentId);
|
||||
const actorAgent = db.core.entity.getAgent(token.agentId);
|
||||
let reviewRequest: { reviewerAgentName: string; documents: Array<{ id: string; title: string } & Record<string, unknown>> } | null = null;
|
||||
if (effectiveStatus === "done" && task.requiresUserReview) {
|
||||
const docs = db.documentsMod.listImportantDocsForReview({
|
||||
const docs = db.core.documents.listImportantDocsForReview({
|
||||
companyId: task.companyId,
|
||||
types: IMPORTANT_DOC_TYPES,
|
||||
authorAgentId: task.assigneeAgentId ?? null,
|
||||
@@ -146,7 +146,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
|
||||
reviewRequest = { reviewerAgentName: actorAgent.name, documents: docs };
|
||||
}
|
||||
|
||||
const updateResult = db.tasks.updateTaskWithReviewSideEffects({
|
||||
const updateResult = db.core.tasks.updateTaskWithReviewSideEffects({
|
||||
taskId: task.id,
|
||||
companyId: task.companyId,
|
||||
actorAgentId: token.agentId,
|
||||
@@ -183,7 +183,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
|
||||
if (update.status && ["done", "in_review"].includes(newStatus)) {
|
||||
if (updateResult.parentId) {
|
||||
try {
|
||||
const parentTask = db.entityCrud.getTask(updateResult.parentId);
|
||||
const parentTask = db.core.entity.getTask(updateResult.parentId);
|
||||
if (parentTask.assigneeAgentId && parentTask.assigneeAgentId !== token.agentId) {
|
||||
onWakeAgent(parentTask.assigneeAgentId, task.companyId, "subtask_completed");
|
||||
}
|
||||
@@ -197,7 +197,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.agents.getChainOfCommand(token.agentId);
|
||||
const chain = db.core.agents.getChainOfCommand(token.agentId);
|
||||
if (chain.length > 0) {
|
||||
onWakeAgent(chain[0].id, task.companyId, "task_review_requested");
|
||||
}
|
||||
@@ -205,7 +205,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
|
||||
}
|
||||
|
||||
if (update.status && newStatus === "blocked") {
|
||||
const chain = db.agents.getChainOfCommand(token.agentId);
|
||||
const chain = db.core.agents.getChainOfCommand(token.agentId);
|
||||
if (chain.length > 0) {
|
||||
onWakeAgent(chain[0].id, task.companyId, "report_blocked");
|
||||
}
|
||||
@@ -225,7 +225,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
|
||||
onWakeAgent(task.assigneeAgentId, task.companyId, "comment");
|
||||
wokenForComment.add(task.assigneeAgentId);
|
||||
}
|
||||
const chain = db.agents.getChainOfCommand(token.agentId);
|
||||
const chain = db.core.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");
|
||||
}
|
||||
@@ -297,7 +297,7 @@ export function registerTaskRoutes(server: AgentApiServer) {
|
||||
|
||||
let id: string;
|
||||
try {
|
||||
id = db.tasks.saveTask({
|
||||
id = db.core.tasks.saveTask({
|
||||
companyId,
|
||||
title: input.title,
|
||||
description: input.description ?? "",
|
||||
@@ -317,12 +317,12 @@ export function registerTaskRoutes(server: AgentApiServer) {
|
||||
|
||||
// Auto-infer task_type from assignee's department
|
||||
if (input.assigneeAgentId) {
|
||||
const assignee = db.entityCrud.getAgent(input.assigneeAgentId);
|
||||
const assignee = db.core.entity.getAgent(input.assigneeAgentId);
|
||||
const inferredType = inferTaskType(assignee.department);
|
||||
db.tasks.setTaskType(id, inferredType);
|
||||
db.core.tasks.setTaskType(id, inferredType);
|
||||
}
|
||||
|
||||
db.activityMod.addActivity({
|
||||
db.core.activity.addActivity({
|
||||
companyId,
|
||||
actor: token.agentId,
|
||||
action: "task.created",
|
||||
|
||||
@@ -35,7 +35,7 @@ export function registerWorkGraphRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = db.entityCrud.saveProject({
|
||||
const id = db.core.entity.saveProject({
|
||||
companyId,
|
||||
name: input.name,
|
||||
description: input.description ?? "",
|
||||
@@ -45,7 +45,7 @@ export function registerWorkGraphRoutes(server: AgentApiServer) {
|
||||
targetDate: input.targetDate ?? null,
|
||||
});
|
||||
|
||||
db.activityMod.addActivity({
|
||||
db.core.activity.addActivity({
|
||||
companyId,
|
||||
actor: token.agentId,
|
||||
action: "project.created",
|
||||
@@ -79,7 +79,7 @@ export function registerWorkGraphRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const existing = db.entityCrud.getProjectForUpdate(projectId, token.companyId);
|
||||
const existing = db.core.entity.getProjectForUpdate(projectId, token.companyId);
|
||||
if (!existing) {
|
||||
server.json(res, 404, { error: "Project not found" });
|
||||
return;
|
||||
@@ -91,7 +91,7 @@ export function registerWorkGraphRoutes(server: AgentApiServer) {
|
||||
}
|
||||
|
||||
try {
|
||||
db.entityCrud.saveProject({
|
||||
db.core.entity.saveProject({
|
||||
id: projectId,
|
||||
companyId: token.companyId,
|
||||
name: parsed.data.name ?? existing.name,
|
||||
@@ -135,8 +135,8 @@ export function registerWorkGraphRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = db.entityCrud.saveGoal(input);
|
||||
db.activityMod.addActivity({
|
||||
const id = db.core.entity.saveGoal(input);
|
||||
db.core.activity.addActivity({
|
||||
companyId,
|
||||
actor: token.agentId,
|
||||
action: "goal.created",
|
||||
@@ -167,7 +167,7 @@ export function registerWorkGraphRoutes(server: AgentApiServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const existing = db.entityCrud.getGoalForUpdate(goalId, token.companyId);
|
||||
const existing = db.core.entity.getGoalForUpdate(goalId, token.companyId);
|
||||
if (!existing) {
|
||||
server.json(res, 404, { error: "Goal not found" });
|
||||
return;
|
||||
@@ -179,7 +179,7 @@ export function registerWorkGraphRoutes(server: AgentApiServer) {
|
||||
}
|
||||
|
||||
try {
|
||||
db.entityCrud.saveGoal({
|
||||
db.core.entity.saveGoal({
|
||||
id: goalId,
|
||||
companyId: token.companyId,
|
||||
title: parsed.data.title ?? existing.title,
|
||||
@@ -200,7 +200,7 @@ export function registerWorkGraphRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Company mismatch" });
|
||||
return;
|
||||
}
|
||||
const goals = db.entityCrud.listGoals(params.companyId);
|
||||
const goals = db.core.entity.listGoals(params.companyId);
|
||||
server.json(res, 200, goals);
|
||||
});
|
||||
|
||||
@@ -209,7 +209,7 @@ export function registerWorkGraphRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Company mismatch" });
|
||||
return;
|
||||
}
|
||||
const projects = db.entityCrud.listProjects(params.companyId);
|
||||
const projects = db.core.entity.listProjects(params.companyId);
|
||||
server.json(res, 200, projects);
|
||||
});
|
||||
|
||||
@@ -219,7 +219,7 @@ export function registerWorkGraphRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Company mismatch" });
|
||||
return;
|
||||
}
|
||||
const sprints = db.knowledgeMod.listSprints(companyId);
|
||||
const sprints = db.core.knowledge.listSprints(companyId);
|
||||
server.json(res, 200, sprints);
|
||||
});
|
||||
|
||||
@@ -231,7 +231,7 @@ export function registerWorkGraphRoutes(server: AgentApiServer) {
|
||||
}
|
||||
const data = body as Record<string, unknown>;
|
||||
try {
|
||||
const id = db.knowledgeMod.saveSprint({
|
||||
const id = db.core.knowledge.saveSprint({
|
||||
companyId,
|
||||
name: String(data.name ?? "Sprint"),
|
||||
goal: String(data.goal ?? ""),
|
||||
@@ -256,7 +256,7 @@ export function registerWorkGraphRoutes(server: AgentApiServer) {
|
||||
server.json(res, 403, { error: "Company mismatch" });
|
||||
return;
|
||||
}
|
||||
const { agents, tasks, recentActivity } = db.company.getDashboardSnapshot(companyId);
|
||||
const { agents, tasks, recentActivity } = db.core.company.getDashboardSnapshot(companyId);
|
||||
|
||||
const tasksByStatus: Record<string, number> = {};
|
||||
for (const t of tasks) {
|
||||
|
||||
@@ -230,7 +230,7 @@ export class AgentApiServer {
|
||||
if (typeof claimedRunId !== "string" || claimedRunId.trim() !== token.runId) {
|
||||
return { ok: false, status: 401, error: "Missing or mismatched X-Agent-Company-Run-Id header" };
|
||||
}
|
||||
const runState = this._db.runs.getRunAuthState(token.runId);
|
||||
const runState = this._db.core.runs.getRunAuthState(token.runId);
|
||||
if (!runState || runState.companyId !== token.companyId || runState.agentId !== token.agentId) {
|
||||
return { ok: false, status: 403, error: "Token references an unknown or mismatched run" };
|
||||
}
|
||||
@@ -362,7 +362,7 @@ export class AgentApiServer {
|
||||
companyId: string,
|
||||
refs: Array<{ id: string | null | undefined; table: "agents" | "goals" | "projects" | "tasks" | "workspaces" | "approvals"; label: string }>,
|
||||
) {
|
||||
const invalid = refs.find((ref) => ref.id && !this._db.settings.belongsToCompany(ref.table, ref.id, companyId));
|
||||
const invalid = refs.find((ref) => ref.id && !this._db.core.settings.belongsToCompany(ref.table, ref.id, companyId));
|
||||
if (!invalid) return false;
|
||||
this.json(res, 422, { error: `${invalid.label} does not belong to the current company` });
|
||||
return true;
|
||||
|
||||
Reference in new issue
Block a user