forked from farhoodlabs/paperclip
Revert "feat(skills): add dryRun flag for scan prune path"
This reverts commit 13f0fee7d86334291f6faa2794ba67e9c7e90f35.
This commit is contained in:
@@ -176,7 +176,6 @@ export type {
|
|||||||
CompanySkillProjectScanRequest,
|
CompanySkillProjectScanRequest,
|
||||||
CompanySkillProjectScanSkipped,
|
CompanySkillProjectScanSkipped,
|
||||||
CompanySkillProjectScanConflict,
|
CompanySkillProjectScanConflict,
|
||||||
CompanySkillProjectScanPruned,
|
|
||||||
CompanySkillProjectScanResult,
|
CompanySkillProjectScanResult,
|
||||||
CompanySkillCreateRequest,
|
CompanySkillCreateRequest,
|
||||||
CompanySkillFileDetail,
|
CompanySkillFileDetail,
|
||||||
@@ -562,7 +561,6 @@ export {
|
|||||||
companySkillProjectScanRequestSchema,
|
companySkillProjectScanRequestSchema,
|
||||||
companySkillProjectScanSkippedSchema,
|
companySkillProjectScanSkippedSchema,
|
||||||
companySkillProjectScanConflictSchema,
|
companySkillProjectScanConflictSchema,
|
||||||
companySkillProjectScanPrunedSchema,
|
|
||||||
companySkillProjectScanResultSchema,
|
companySkillProjectScanResultSchema,
|
||||||
companySkillCreateSchema,
|
companySkillCreateSchema,
|
||||||
companySkillFileDetailSchema,
|
companySkillFileDetailSchema,
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ export interface CompanySkillImportResult {
|
|||||||
export interface CompanySkillProjectScanRequest {
|
export interface CompanySkillProjectScanRequest {
|
||||||
projectIds?: string[];
|
projectIds?: string[];
|
||||||
workspaceIds?: string[];
|
workspaceIds?: string[];
|
||||||
dryRun?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CompanySkillProjectScanSkipped {
|
export interface CompanySkillProjectScanSkipped {
|
||||||
@@ -119,14 +118,6 @@ export interface CompanySkillProjectScanConflict {
|
|||||||
reason: string;
|
reason: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CompanySkillProjectScanPruned {
|
|
||||||
skillId: string;
|
|
||||||
slug: string;
|
|
||||||
key: string;
|
|
||||||
sourceLocator: string | null;
|
|
||||||
affectedAgents: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CompanySkillProjectScanResult {
|
export interface CompanySkillProjectScanResult {
|
||||||
scannedProjects: number;
|
scannedProjects: number;
|
||||||
scannedWorkspaces: number;
|
scannedWorkspaces: number;
|
||||||
@@ -135,9 +126,7 @@ export interface CompanySkillProjectScanResult {
|
|||||||
updated: CompanySkill[];
|
updated: CompanySkill[];
|
||||||
skipped: CompanySkillProjectScanSkipped[];
|
skipped: CompanySkillProjectScanSkipped[];
|
||||||
conflicts: CompanySkillProjectScanConflict[];
|
conflicts: CompanySkillProjectScanConflict[];
|
||||||
pruned: CompanySkillProjectScanPruned[];
|
|
||||||
warnings: string[];
|
warnings: string[];
|
||||||
dryRun: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CompanySkillCreateRequest {
|
export interface CompanySkillCreateRequest {
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ export type {
|
|||||||
CompanySkillProjectScanRequest,
|
CompanySkillProjectScanRequest,
|
||||||
CompanySkillProjectScanSkipped,
|
CompanySkillProjectScanSkipped,
|
||||||
CompanySkillProjectScanConflict,
|
CompanySkillProjectScanConflict,
|
||||||
CompanySkillProjectScanPruned,
|
|
||||||
CompanySkillProjectScanResult,
|
CompanySkillProjectScanResult,
|
||||||
CompanySkillCreateRequest,
|
CompanySkillCreateRequest,
|
||||||
CompanySkillFileDetail,
|
CompanySkillFileDetail,
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ export const companySkillUpdateAuthSchema = z.object({
|
|||||||
export const companySkillProjectScanRequestSchema = z.object({
|
export const companySkillProjectScanRequestSchema = z.object({
|
||||||
projectIds: z.array(z.string().uuid()).optional(),
|
projectIds: z.array(z.string().uuid()).optional(),
|
||||||
workspaceIds: z.array(z.string().uuid()).optional(),
|
workspaceIds: z.array(z.string().uuid()).optional(),
|
||||||
dryRun: z.boolean().optional(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const companySkillProjectScanSkippedSchema = z.object({
|
export const companySkillProjectScanSkippedSchema = z.object({
|
||||||
@@ -102,14 +101,6 @@ export const companySkillProjectScanConflictSchema = z.object({
|
|||||||
reason: z.string().min(1),
|
reason: z.string().min(1),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const companySkillProjectScanPrunedSchema = z.object({
|
|
||||||
skillId: z.string().uuid(),
|
|
||||||
slug: z.string().min(1),
|
|
||||||
key: z.string().min(1),
|
|
||||||
sourceLocator: z.string().nullable(),
|
|
||||||
affectedAgents: z.array(z.string()),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const companySkillProjectScanResultSchema = z.object({
|
export const companySkillProjectScanResultSchema = z.object({
|
||||||
scannedProjects: z.number().int().nonnegative(),
|
scannedProjects: z.number().int().nonnegative(),
|
||||||
scannedWorkspaces: z.number().int().nonnegative(),
|
scannedWorkspaces: z.number().int().nonnegative(),
|
||||||
@@ -118,9 +109,7 @@ export const companySkillProjectScanResultSchema = z.object({
|
|||||||
updated: z.array(companySkillSchema),
|
updated: z.array(companySkillSchema),
|
||||||
skipped: z.array(companySkillProjectScanSkippedSchema),
|
skipped: z.array(companySkillProjectScanSkippedSchema),
|
||||||
conflicts: z.array(companySkillProjectScanConflictSchema),
|
conflicts: z.array(companySkillProjectScanConflictSchema),
|
||||||
pruned: z.array(companySkillProjectScanPrunedSchema),
|
|
||||||
warnings: z.array(z.string()),
|
warnings: z.array(z.string()),
|
||||||
dryRun: z.boolean(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const companySkillCreateSchema = z.object({
|
export const companySkillCreateSchema = z.object({
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ export {
|
|||||||
companySkillProjectScanRequestSchema,
|
companySkillProjectScanRequestSchema,
|
||||||
companySkillProjectScanSkippedSchema,
|
companySkillProjectScanSkippedSchema,
|
||||||
companySkillProjectScanConflictSchema,
|
companySkillProjectScanConflictSchema,
|
||||||
companySkillProjectScanPrunedSchema,
|
|
||||||
companySkillProjectScanResultSchema,
|
companySkillProjectScanResultSchema,
|
||||||
companySkillCreateSchema,
|
companySkillCreateSchema,
|
||||||
companySkillFileDetailSchema,
|
companySkillFileDetailSchema,
|
||||||
|
|||||||
@@ -282,46 +282,4 @@ describeEmbeddedPostgres("scanProjectWorkspaces prune path", () => {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("reports pruned skills without deleting when dryRun is true", async () => {
|
|
||||||
stubGitHubSource(["keep-skill"]);
|
|
||||||
|
|
||||||
const { companySkillService } = await import("../services/company-skills.js");
|
|
||||||
const svc = companySkillService(db);
|
|
||||||
const result = await svc.scanProjectWorkspaces(companyId, { dryRun: true });
|
|
||||||
|
|
||||||
// The result should flag dryRun and list what would be pruned
|
|
||||||
expect(result.dryRun).toBe(true);
|
|
||||||
expect(result.pruned).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
slug: "prune-skill",
|
|
||||||
affectedAgents: expect.arrayContaining(["Builder"]),
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
|
|
||||||
// No warnings emitted (nothing was actually deleted)
|
|
||||||
const pruneWarnings = result.warnings.filter((w) => w.includes("prune-skill"));
|
|
||||||
expect(pruneWarnings).toHaveLength(0);
|
|
||||||
|
|
||||||
// Both skills should still exist in the database
|
|
||||||
const remaining = await db
|
|
||||||
.select()
|
|
||||||
.from(companySkills)
|
|
||||||
.where(eq(companySkills.companyId, companyId));
|
|
||||||
const remainingSlugs = remaining.map((r) => r.slug);
|
|
||||||
expect(remainingSlugs).toContain("keep-skill");
|
|
||||||
expect(remainingSlugs).toContain("prune-skill");
|
|
||||||
|
|
||||||
// Agent config should be unchanged
|
|
||||||
const [agentRow] = await db
|
|
||||||
.select()
|
|
||||||
.from(agents)
|
|
||||||
.where(eq(agents.id, agentId));
|
|
||||||
const config = agentRow!.adapterConfig as Record<string, unknown>;
|
|
||||||
const syncConfig = config.paperclipSkillSync as Record<string, unknown>;
|
|
||||||
const desiredSkills = syncConfig.desiredSkills as string[];
|
|
||||||
expect(desiredSkills).toContain("test-org/test-skills/prune-skill");
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -78,9 +78,7 @@ describe("company skill mutation permissions", () => {
|
|||||||
updated: [],
|
updated: [],
|
||||||
skipped: [],
|
skipped: [],
|
||||||
conflicts: [],
|
conflicts: [],
|
||||||
pruned: [],
|
|
||||||
warnings: [],
|
warnings: [],
|
||||||
dryRun: false,
|
|
||||||
});
|
});
|
||||||
mockLogActivity.mockResolvedValue(undefined);
|
mockLogActivity.mockResolvedValue(undefined);
|
||||||
mockAccessService.canUser.mockResolvedValue(true);
|
mockAccessService.canUser.mockResolvedValue(true);
|
||||||
@@ -295,13 +293,9 @@ describe("company skill mutation permissions", () => {
|
|||||||
updated: [],
|
updated: [],
|
||||||
skipped: [],
|
skipped: [],
|
||||||
conflicts: [],
|
conflicts: [],
|
||||||
pruned: [
|
|
||||||
{ skillId: "skill-1", slug: "ghost-skill", key: "vercel-labs/agent-browser/ghost-skill", sourceLocator: "https://github.com/vercel-labs/agent-browser", affectedAgents: ["Builder"] },
|
|
||||||
],
|
|
||||||
warnings: [
|
warnings: [
|
||||||
'Skill "ghost-skill" was removed from https://github.com/vercel-labs/agent-browser and detached from Builder.',
|
'Skill "ghost-skill" was removed from https://github.com/vercel-labs/agent-browser and detached from Builder.',
|
||||||
],
|
],
|
||||||
dryRun: false,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const res = await request(await createApp({
|
const res = await request(await createApp({
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import type {
|
|||||||
CompanySkillImportResult,
|
CompanySkillImportResult,
|
||||||
CompanySkillListItem,
|
CompanySkillListItem,
|
||||||
CompanySkillProjectScanConflict,
|
CompanySkillProjectScanConflict,
|
||||||
CompanySkillProjectScanPruned,
|
|
||||||
CompanySkillProjectScanRequest,
|
CompanySkillProjectScanRequest,
|
||||||
CompanySkillProjectScanResult,
|
CompanySkillProjectScanResult,
|
||||||
CompanySkillProjectScanSkipped,
|
CompanySkillProjectScanSkipped,
|
||||||
@@ -1861,10 +1860,8 @@ export function companySkillService(db: Db) {
|
|||||||
? await projects.listByIds(companyId, input.projectIds)
|
? await projects.listByIds(companyId, input.projectIds)
|
||||||
: await projects.list(companyId);
|
: await projects.list(companyId);
|
||||||
const workspaceFilter = new Set(input.workspaceIds ?? []);
|
const workspaceFilter = new Set(input.workspaceIds ?? []);
|
||||||
const dryRun = input.dryRun === true;
|
|
||||||
const skipped: CompanySkillProjectScanSkipped[] = [];
|
const skipped: CompanySkillProjectScanSkipped[] = [];
|
||||||
const conflicts: CompanySkillProjectScanConflict[] = [];
|
const conflicts: CompanySkillProjectScanConflict[] = [];
|
||||||
const pruned: CompanySkillProjectScanPruned[] = [];
|
|
||||||
const warnings: string[] = [];
|
const warnings: string[] = [];
|
||||||
const imported: CompanySkill[] = [];
|
const imported: CompanySkill[] = [];
|
||||||
const updated: CompanySkill[] = [];
|
const updated: CompanySkill[] = [];
|
||||||
@@ -2046,18 +2043,6 @@ export function companySkillService(db: Db) {
|
|||||||
for (const skill of skillsAtSource) {
|
for (const skill of skillsAtSource) {
|
||||||
if (currentSlugs.has(skill.slug)) continue;
|
if (currentSlugs.has(skill.slug)) continue;
|
||||||
const usedByAgents = await usage(companyId, skill.key);
|
const usedByAgents = await usage(companyId, skill.key);
|
||||||
const affectedAgentNames = usedByAgents.map((a) => a.name);
|
|
||||||
|
|
||||||
pruned.push({
|
|
||||||
skillId: skill.id,
|
|
||||||
slug: skill.slug,
|
|
||||||
key: skill.key,
|
|
||||||
sourceLocator: skill.sourceLocator,
|
|
||||||
affectedAgents: affectedAgentNames,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (dryRun) continue;
|
|
||||||
|
|
||||||
if (usedByAgents.length > 0) {
|
if (usedByAgents.length > 0) {
|
||||||
// Detach the skill from all agents that have it, then delete
|
// Detach the skill from all agents that have it, then delete
|
||||||
for (const agent of usedByAgents) {
|
for (const agent of usedByAgents) {
|
||||||
@@ -2074,7 +2059,7 @@ export function companySkillService(db: Db) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
warnings.push(
|
warnings.push(
|
||||||
`Skill "${skill.slug}" was removed from ${sourceLocator} and detached from ${affectedAgentNames.join(", ")}.`,
|
`Skill "${skill.slug}" was removed from ${sourceLocator} and detached from ${usedByAgents.map((a) => a.name).join(", ")}.`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
warnings.push(
|
warnings.push(
|
||||||
@@ -2097,9 +2082,7 @@ export function companySkillService(db: Db) {
|
|||||||
updated,
|
updated,
|
||||||
skipped,
|
skipped,
|
||||||
conflicts,
|
conflicts,
|
||||||
pruned,
|
|
||||||
warnings,
|
warnings,
|
||||||
dryRun,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user