Reduce company skill list payloads
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -29,7 +29,20 @@ export interface CompanySkill {
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
export interface CompanySkillListItem extends CompanySkill {
|
||||
export interface CompanySkillListItem {
|
||||
id: string;
|
||||
companyId: string;
|
||||
slug: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
sourceType: CompanySkillSourceType;
|
||||
sourceLocator: string | null;
|
||||
sourceRef: string | null;
|
||||
trustLevel: CompanySkillTrustLevel;
|
||||
compatibility: CompanySkillCompatibility;
|
||||
fileInventory: CompanySkillFileInventoryEntry[];
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
attachedAgentCount: number;
|
||||
editable: boolean;
|
||||
editableReason: string | null;
|
||||
|
||||
@@ -31,6 +31,7 @@ const issueSvc = {
|
||||
|
||||
const companySkillSvc = {
|
||||
list: vi.fn(),
|
||||
listFull: vi.fn(),
|
||||
readFile: vi.fn(),
|
||||
importPackageFiles: vi.fn(),
|
||||
};
|
||||
@@ -148,7 +149,7 @@ describe("company portability", () => {
|
||||
issueSvc.list.mockResolvedValue([]);
|
||||
issueSvc.getById.mockResolvedValue(null);
|
||||
issueSvc.getByIdentifier.mockResolvedValue(null);
|
||||
companySkillSvc.list.mockResolvedValue([
|
||||
const companySkills = [
|
||||
{
|
||||
id: "skill-1",
|
||||
companyId: "company-1",
|
||||
@@ -194,7 +195,9 @@ describe("company portability", () => {
|
||||
sourceKind: "local_path",
|
||||
},
|
||||
},
|
||||
]);
|
||||
];
|
||||
companySkillSvc.list.mockResolvedValue(companySkills);
|
||||
companySkillSvc.listFull.mockResolvedValue(companySkills);
|
||||
companySkillSvc.readFile.mockImplementation(async (_companyId: string, skillId: string, relativePath: string) => {
|
||||
if (skillId === "skill-2") {
|
||||
return {
|
||||
|
||||
@@ -1551,7 +1551,7 @@ export function companyPortabilityService(db: Db) {
|
||||
|
||||
const allAgentRows = include.agents ? await agents.list(companyId, { includeTerminated: true }) : [];
|
||||
const agentRows = allAgentRows.filter((agent) => agent.status !== "terminated");
|
||||
const companySkillRows = await companySkills.list(companyId);
|
||||
const companySkillRows = await companySkills.listFull(companyId);
|
||||
if (include.agents) {
|
||||
const skipped = allAgentRows.length - agentRows.length;
|
||||
if (skipped > 0) {
|
||||
|
||||
@@ -881,6 +881,30 @@ function enrichSkill(skill: CompanySkill, attachedAgentCount: number, usedByAgen
|
||||
};
|
||||
}
|
||||
|
||||
function toCompanySkillListItem(skill: CompanySkill, attachedAgentCount: number): CompanySkillListItem {
|
||||
const source = deriveSkillSourceInfo(skill);
|
||||
return {
|
||||
id: skill.id,
|
||||
companyId: skill.companyId,
|
||||
slug: skill.slug,
|
||||
name: skill.name,
|
||||
description: skill.description,
|
||||
sourceType: skill.sourceType,
|
||||
sourceLocator: skill.sourceLocator,
|
||||
sourceRef: skill.sourceRef,
|
||||
trustLevel: skill.trustLevel,
|
||||
compatibility: skill.compatibility,
|
||||
fileInventory: skill.fileInventory,
|
||||
createdAt: skill.createdAt,
|
||||
updatedAt: skill.updatedAt,
|
||||
attachedAgentCount,
|
||||
editable: source.editable,
|
||||
editableReason: source.editableReason,
|
||||
sourceLabel: source.sourceLabel,
|
||||
sourceBadge: source.sourceBadge,
|
||||
};
|
||||
}
|
||||
|
||||
export function companySkillService(db: Db) {
|
||||
const agents = agentService(db);
|
||||
const secretsSvc = secretService(db);
|
||||
@@ -905,21 +929,25 @@ export function companySkillService(db: Db) {
|
||||
}
|
||||
|
||||
async function list(companyId: string): Promise<CompanySkillListItem[]> {
|
||||
const rows = await listFull(companyId);
|
||||
const agentRows = await agents.list(companyId);
|
||||
return rows.map((skill) => {
|
||||
const attachedAgentCount = agentRows.filter((agent) => {
|
||||
const preference = readPaperclipSkillSyncPreference(agent.adapterConfig as Record<string, unknown>);
|
||||
return preference.desiredSkills.includes(skill.slug);
|
||||
}).length;
|
||||
return toCompanySkillListItem(skill, attachedAgentCount);
|
||||
});
|
||||
}
|
||||
|
||||
async function listFull(companyId: string): Promise<CompanySkill[]> {
|
||||
await ensureBundledSkills(companyId);
|
||||
const rows = await db
|
||||
.select()
|
||||
.from(companySkills)
|
||||
.where(eq(companySkills.companyId, companyId))
|
||||
.orderBy(asc(companySkills.name), asc(companySkills.slug));
|
||||
const agentRows = await agents.list(companyId);
|
||||
return rows.map((row) => {
|
||||
const skill = toCompanySkill(row);
|
||||
const attachedAgentCount = agentRows.filter((agent) => {
|
||||
const preference = readPaperclipSkillSyncPreference(agent.adapterConfig as Record<string, unknown>);
|
||||
return preference.desiredSkills.includes(skill.slug);
|
||||
}).length;
|
||||
return enrichSkill(skill, attachedAgentCount);
|
||||
});
|
||||
return rows.map((row) => toCompanySkill(row));
|
||||
}
|
||||
|
||||
async function getById(id: string) {
|
||||
@@ -1375,6 +1403,7 @@ export function companySkillService(db: Db) {
|
||||
|
||||
return {
|
||||
list,
|
||||
listFull,
|
||||
getById,
|
||||
getBySlug,
|
||||
detail,
|
||||
|
||||
Reference in New Issue
Block a user