mirror of
https://github.com/openclaw/clawhub.git
synced 2026-08-14 00:47:57 +00:00
fix(search): resolve approved browse versions during pending review
Keep digest summary fast paths for ordinary listings while loading the last approved public version when a newer release is still pending review.
This commit is contained in:
committed by
Patrick Erichsen
parent
7fa17e159e
commit
64e5bcb676
@@ -4,6 +4,7 @@ import {
|
||||
hasPriorApprovedPublicSkillVersion,
|
||||
isPubliclyListableSkillVersion,
|
||||
isSkillPendingPublicReview,
|
||||
resolvePublicBrowseVersionForSkill,
|
||||
shouldExcludeSkillFromPublicBrowse,
|
||||
} from "./publicBrowse";
|
||||
|
||||
@@ -103,4 +104,82 @@ describe("publicBrowse", () => {
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("resolves the last approved version while a newer version is pending review", async () => {
|
||||
const approvedVersion = {
|
||||
_id: "skillVersions:approved",
|
||||
skillId: "skills:1",
|
||||
softDeletedAt: undefined,
|
||||
version: "1.0.0",
|
||||
createdAt: 1,
|
||||
changelog: "approved",
|
||||
changelogSource: "user",
|
||||
parsed: { frontmatter: {}, license: "MIT" },
|
||||
vtAnalysis: { status: "clean", checkedAt: 1 },
|
||||
llmAnalysis: { status: "clean", checkedAt: 1 },
|
||||
staticScan: {
|
||||
status: "clean",
|
||||
reasonCodes: [],
|
||||
findings: [],
|
||||
summary: "",
|
||||
engineVersion: "v1",
|
||||
checkedAt: 1,
|
||||
},
|
||||
};
|
||||
const pendingVersion = {
|
||||
_id: "skillVersions:pending",
|
||||
skillId: "skills:1",
|
||||
softDeletedAt: undefined,
|
||||
version: "2.0.0",
|
||||
createdAt: 2,
|
||||
changelog: "pending",
|
||||
changelogSource: "user",
|
||||
parsed: { frontmatter: {}, license: "MIT" },
|
||||
vtAnalysis: { status: "pending", checkedAt: 2 },
|
||||
};
|
||||
|
||||
const version = await resolvePublicBrowseVersionForSkill(
|
||||
{
|
||||
db: {
|
||||
get: async (id: string) => {
|
||||
if (id === "skills:1") {
|
||||
return {
|
||||
_id: "skills:1",
|
||||
latestVersionId: "skillVersions:pending",
|
||||
moderationSourceVersionId: "skillVersions:pending",
|
||||
moderationStatus: "active",
|
||||
moderationReason: "pending.scan",
|
||||
moderationFlags: undefined,
|
||||
stats: { versions: 2 },
|
||||
};
|
||||
}
|
||||
if (id === "skillVersions:pending") return pendingVersion;
|
||||
return null;
|
||||
},
|
||||
query: () => ({
|
||||
withIndex: () => ({
|
||||
order: () => ({
|
||||
take: async () => [pendingVersion, approvedVersion],
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
} as never,
|
||||
{
|
||||
_id: "skills:1",
|
||||
latestVersionId: "skillVersions:pending",
|
||||
moderationSourceVersionId: "skillVersions:pending",
|
||||
moderationStatus: "active",
|
||||
moderationReason: "pending.scan",
|
||||
moderationFlags: undefined,
|
||||
stats: { versions: 2 },
|
||||
softDeletedAt: undefined,
|
||||
moderationVerdict: "clean",
|
||||
githubScanStatus: "clean",
|
||||
},
|
||||
);
|
||||
|
||||
expect(version?._id).toBe("skillVersions:approved");
|
||||
expect(version?.version).toBe("1.0.0");
|
||||
});
|
||||
});
|
||||
|
||||
+51
-34
@@ -6005,55 +6005,72 @@ async function addOfficialStatusToOwnerInfo(
|
||||
|
||||
async function loadPublicLatestVersionForDigest(
|
||||
ctx: Pick<QueryCtx, "db">,
|
||||
digest: Pick<Doc<"skillSearchDigest">, "skillId" | "latestVersionId" | "latestVersionSkillId">,
|
||||
digest: Pick<
|
||||
Doc<"skillSearchDigest">,
|
||||
| "skillId"
|
||||
| "latestVersionId"
|
||||
| "latestVersionSkillId"
|
||||
| "moderationReason"
|
||||
| "moderationFlags"
|
||||
| "stats"
|
||||
| "moderationSourceVersionId"
|
||||
>,
|
||||
) {
|
||||
if (!digest.latestVersionId) return null;
|
||||
if (digest.latestVersionSkillId !== undefined && digest.latestVersionSkillId !== digest.skillId) {
|
||||
return null;
|
||||
}
|
||||
const skill = await ctx.db.get(digest.skillId);
|
||||
if (skill && isSkillPendingPublicReview(skill) && hasPriorApprovedPublicSkillVersion(skill)) {
|
||||
const version = await resolvePublicBrowseVersionForSkill(ctx, skill);
|
||||
return version && isPublicSkillVersionAvailableForSkill(version, digest.skillId)
|
||||
? version
|
||||
: null;
|
||||
}
|
||||
const version = await ctx.db.get(digest.latestVersionId);
|
||||
return isPublicSkillVersionAvailableForSkill(version, digest.skillId) ? version : null;
|
||||
}
|
||||
|
||||
function toDigestLatestVersionForSkill(digest: Doc<"skillSearchDigest">) {
|
||||
if (!digest.latestVersionSummary || !digest.latestVersionId) {
|
||||
return null;
|
||||
const needsApprovedSnapshot =
|
||||
isSkillPendingPublicReview(digest) && hasPriorApprovedPublicSkillVersion(digest);
|
||||
|
||||
if (!needsApprovedSnapshot) {
|
||||
const version = await ctx.db.get(digest.latestVersionId);
|
||||
return isPublicSkillVersionAvailableForSkill(version, digest.skillId) ? version : null;
|
||||
}
|
||||
if (digest.latestVersionSkillId !== digest.skillId) {
|
||||
return null;
|
||||
}
|
||||
return toPublicSkillListVersionFromSummary(
|
||||
digest.latestVersionSummary,
|
||||
digest.latestVersionId,
|
||||
digest.skillId,
|
||||
);
|
||||
|
||||
const skill = await ctx.db.get(digest.skillId);
|
||||
if (!skill) return null;
|
||||
const version = await resolvePublicBrowseVersionForSkill(ctx, skill);
|
||||
return version && isPublicSkillVersionAvailableForSkill(version, digest.skillId) ? version : null;
|
||||
}
|
||||
|
||||
async function resolveDigestLatestVersionForSkill(
|
||||
ctx: Pick<QueryCtx, "db">,
|
||||
digest: Doc<"skillSearchDigest">,
|
||||
) {
|
||||
if (!digest.latestVersionSummary || !digest.latestVersionId) {
|
||||
return null;
|
||||
const needsApprovedSnapshot =
|
||||
isSkillPendingPublicReview(digest) && hasPriorApprovedPublicSkillVersion(digest);
|
||||
|
||||
if (
|
||||
!needsApprovedSnapshot &&
|
||||
digest.latestVersionSummary &&
|
||||
digest.latestVersionId &&
|
||||
(digest.latestVersionSkillId === undefined || digest.latestVersionSkillId === digest.skillId)
|
||||
) {
|
||||
return toPublicSkillListVersionFromSummary(
|
||||
digest.latestVersionSummary,
|
||||
digest.latestVersionId,
|
||||
digest.skillId,
|
||||
);
|
||||
}
|
||||
if (digest.latestVersionSkillId === undefined) {
|
||||
const latestVersion = await loadPublicLatestVersionForDigest(ctx, digest);
|
||||
return latestVersion
|
||||
? toPublicSkillListVersionFromSummary(
|
||||
digest.latestVersionSummary,
|
||||
digest.latestVersionId,
|
||||
digest.skillId,
|
||||
)
|
||||
: null;
|
||||
|
||||
const version = await loadPublicLatestVersionForDigest(ctx, digest);
|
||||
if (!version) return null;
|
||||
|
||||
if (
|
||||
digest.latestVersionSummary &&
|
||||
digest.latestVersionId === version._id &&
|
||||
(digest.latestVersionSkillId === undefined || digest.latestVersionSkillId === digest.skillId)
|
||||
) {
|
||||
return toPublicSkillListVersionFromSummary(
|
||||
digest.latestVersionSummary,
|
||||
version._id,
|
||||
digest.skillId,
|
||||
);
|
||||
}
|
||||
return toDigestLatestVersionForSkill(digest);
|
||||
|
||||
return toPublicSkillListVersion(version);
|
||||
}
|
||||
|
||||
async function buildPublicSkillApiListEntryFromDigest(
|
||||
|
||||
Reference in New Issue
Block a user