Merge branch 'master' of github.com-dotta:paperclipai/paperclip

* 'master' of github.com-dotta:paperclipai/paperclip:
  fix(ui): render sub-goals in goal detail tree
  fix: exclude terminated agents from list and org chart endpoints
This commit is contained in:
Dotta
2026-03-05 11:03:55 -06:00
3 changed files with 14 additions and 6 deletions

View File

@@ -1,5 +1,5 @@
import { createHash, randomBytes } from "node:crypto";
import { and, desc, eq, inArray } from "drizzle-orm";
import { and, desc, eq, inArray, ne } from "drizzle-orm";
import type { Db } from "@paperclipai/db";
import {
agents,
@@ -251,8 +251,12 @@ export function agentService(db: Db) {
}
return {
list: async (companyId: string) => {
const rows = await db.select().from(agents).where(eq(agents.companyId, companyId));
list: async (companyId: string, options?: { includeTerminated?: boolean }) => {
const conditions = [eq(agents.companyId, companyId)];
if (!options?.includeTerminated) {
conditions.push(ne(agents.status, "terminated"));
}
const rows = await db.select().from(agents).where(and(...conditions));
return rows.map(normalizeAgentRow);
},
@@ -469,7 +473,10 @@ export function agentService(db: Db) {
},
orgForCompany: async (companyId: string) => {
const rows = await db.select().from(agents).where(eq(agents.companyId, companyId));
const rows = await db
.select()
.from(agents)
.where(and(eq(agents.companyId, companyId), ne(agents.status, "terminated")));
const normalizedRows = rows.map(normalizeAgentRow);
const byManager = new Map<string | null, typeof normalizedRows>();
for (const row of normalizedRows) {

View File

@@ -564,7 +564,7 @@ export function companyPortabilityService(db: Db) {
requiredSecrets: [],
};
const allAgentRows = include.agents ? await agents.list(companyId) : [];
const allAgentRows = include.agents ? await agents.list(companyId, { includeTerminated: true }) : [];
const agentRows = allAgentRows.filter((agent) => agent.status !== "terminated");
if (include.agents) {
const skipped = allAgentRows.length - agentRows.length;

View File

@@ -92,7 +92,8 @@ function GoalNode({ goal, children, allGoals, depth, goalLink, onSelect }: GoalN
}
export function GoalTree({ goals, goalLink, onSelect }: GoalTreeProps) {
const roots = goals.filter((g) => !g.parentId);
const goalIds = new Set(goals.map((g) => g.id));
const roots = goals.filter((g) => !g.parentId || !goalIds.has(g.parentId));
if (goals.length === 0) {
return <p className="text-sm text-muted-foreground">No goals.</p>;