Reduce company skill list payloads
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
cca086b863
commit
8460fee380
4 changed files with 58 additions and 13 deletions
|
|
@ -29,7 +29,20 @@ export interface CompanySkill {
|
||||||
updatedAt: Date;
|
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;
|
attachedAgentCount: number;
|
||||||
editable: boolean;
|
editable: boolean;
|
||||||
editableReason: string | null;
|
editableReason: string | null;
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ const issueSvc = {
|
||||||
|
|
||||||
const companySkillSvc = {
|
const companySkillSvc = {
|
||||||
list: vi.fn(),
|
list: vi.fn(),
|
||||||
|
listFull: vi.fn(),
|
||||||
readFile: vi.fn(),
|
readFile: vi.fn(),
|
||||||
importPackageFiles: vi.fn(),
|
importPackageFiles: vi.fn(),
|
||||||
};
|
};
|
||||||
|
|
@ -148,7 +149,7 @@ describe("company portability", () => {
|
||||||
issueSvc.list.mockResolvedValue([]);
|
issueSvc.list.mockResolvedValue([]);
|
||||||
issueSvc.getById.mockResolvedValue(null);
|
issueSvc.getById.mockResolvedValue(null);
|
||||||
issueSvc.getByIdentifier.mockResolvedValue(null);
|
issueSvc.getByIdentifier.mockResolvedValue(null);
|
||||||
companySkillSvc.list.mockResolvedValue([
|
const companySkills = [
|
||||||
{
|
{
|
||||||
id: "skill-1",
|
id: "skill-1",
|
||||||
companyId: "company-1",
|
companyId: "company-1",
|
||||||
|
|
@ -194,7 +195,9 @@ describe("company portability", () => {
|
||||||
sourceKind: "local_path",
|
sourceKind: "local_path",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
];
|
||||||
|
companySkillSvc.list.mockResolvedValue(companySkills);
|
||||||
|
companySkillSvc.listFull.mockResolvedValue(companySkills);
|
||||||
companySkillSvc.readFile.mockImplementation(async (_companyId: string, skillId: string, relativePath: string) => {
|
companySkillSvc.readFile.mockImplementation(async (_companyId: string, skillId: string, relativePath: string) => {
|
||||||
if (skillId === "skill-2") {
|
if (skillId === "skill-2") {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -1551,7 +1551,7 @@ export function companyPortabilityService(db: Db) {
|
||||||
|
|
||||||
const allAgentRows = include.agents ? await agents.list(companyId, { includeTerminated: true }) : [];
|
const allAgentRows = include.agents ? await agents.list(companyId, { includeTerminated: true }) : [];
|
||||||
const agentRows = allAgentRows.filter((agent) => agent.status !== "terminated");
|
const agentRows = allAgentRows.filter((agent) => agent.status !== "terminated");
|
||||||
const companySkillRows = await companySkills.list(companyId);
|
const companySkillRows = await companySkills.listFull(companyId);
|
||||||
if (include.agents) {
|
if (include.agents) {
|
||||||
const skipped = allAgentRows.length - agentRows.length;
|
const skipped = allAgentRows.length - agentRows.length;
|
||||||
if (skipped > 0) {
|
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) {
|
export function companySkillService(db: Db) {
|
||||||
const agents = agentService(db);
|
const agents = agentService(db);
|
||||||
const secretsSvc = secretService(db);
|
const secretsSvc = secretService(db);
|
||||||
|
|
@ -905,21 +929,25 @@ export function companySkillService(db: Db) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function list(companyId: string): Promise<CompanySkillListItem[]> {
|
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);
|
await ensureBundledSkills(companyId);
|
||||||
const rows = await db
|
const rows = await db
|
||||||
.select()
|
.select()
|
||||||
.from(companySkills)
|
.from(companySkills)
|
||||||
.where(eq(companySkills.companyId, companyId))
|
.where(eq(companySkills.companyId, companyId))
|
||||||
.orderBy(asc(companySkills.name), asc(companySkills.slug));
|
.orderBy(asc(companySkills.name), asc(companySkills.slug));
|
||||||
const agentRows = await agents.list(companyId);
|
return rows.map((row) => toCompanySkill(row));
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getById(id: string) {
|
async function getById(id: string) {
|
||||||
|
|
@ -1375,6 +1403,7 @@ export function companySkillService(db: Db) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
list,
|
list,
|
||||||
|
listFull,
|
||||||
getById,
|
getById,
|
||||||
getBySlug,
|
getBySlug,
|
||||||
detail,
|
detail,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue