mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-15 10:30:37 +09:00
Merge pull request #1655 from paperclipai/pr/pap-795-company-portability
feat(portability): improve company import and export flow
This commit is contained in:
commit
eeb7e1a91a
36 changed files with 5238 additions and 271 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -99,6 +99,8 @@ type RuntimeSkillEntryOptions = {
|
|||
materializeMissing?: boolean;
|
||||
};
|
||||
|
||||
const skillInventoryRefreshPromises = new Map<string, Promise<void>>();
|
||||
|
||||
const PROJECT_SCAN_DIRECTORY_ROOTS = [
|
||||
"skills",
|
||||
"skills/.curated",
|
||||
|
|
@ -188,6 +190,18 @@ function normalizeSkillKey(value: string | null | undefined) {
|
|||
return segments.length > 0 ? segments.join("/") : null;
|
||||
}
|
||||
|
||||
export function normalizeGitHubSkillDirectory(
|
||||
value: string | null | undefined,
|
||||
fallback: string,
|
||||
) {
|
||||
const normalized = normalizePortablePath(value ?? "");
|
||||
if (!normalized) return normalizePortablePath(fallback);
|
||||
if (path.posix.basename(normalized).toLowerCase() === "skill.md") {
|
||||
return normalizePortablePath(path.posix.dirname(normalized));
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
function hashSkillValue(value: string) {
|
||||
return createHash("sha256").update(value).digest("hex").slice(0, 10);
|
||||
}
|
||||
|
|
@ -1017,7 +1031,10 @@ async function readUrlSkillImports(
|
|||
repo: parsed.repo,
|
||||
ref: ref,
|
||||
trackingRef,
|
||||
repoSkillDir: basePrefix ? `${basePrefix}${skillDir}` : skillDir,
|
||||
repoSkillDir: normalizeGitHubSkillDirectory(
|
||||
basePrefix ? `${basePrefix}${skillDir}` : skillDir,
|
||||
slug,
|
||||
),
|
||||
};
|
||||
const inventory = filteredPaths
|
||||
.filter((entry) => entry === relativeSkillPath || entry.startsWith(`${skillDir}/`))
|
||||
|
|
@ -1474,8 +1491,25 @@ export function companySkillService(db: Db) {
|
|||
}
|
||||
|
||||
async function ensureSkillInventoryCurrent(companyId: string) {
|
||||
await ensureBundledSkills(companyId);
|
||||
await pruneMissingLocalPathSkills(companyId);
|
||||
const existingRefresh = skillInventoryRefreshPromises.get(companyId);
|
||||
if (existingRefresh) {
|
||||
await existingRefresh;
|
||||
return;
|
||||
}
|
||||
|
||||
const refreshPromise = (async () => {
|
||||
await ensureBundledSkills(companyId);
|
||||
await pruneMissingLocalPathSkills(companyId);
|
||||
})();
|
||||
|
||||
skillInventoryRefreshPromises.set(companyId, refreshPromise);
|
||||
try {
|
||||
await refreshPromise;
|
||||
} finally {
|
||||
if (skillInventoryRefreshPromises.get(companyId) === refreshPromise) {
|
||||
skillInventoryRefreshPromises.delete(companyId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function list(companyId: string): Promise<CompanySkillListItem[]> {
|
||||
|
|
@ -1646,7 +1680,7 @@ export function companySkillService(db: Db) {
|
|||
const owner = asString(metadata.owner);
|
||||
const repo = asString(metadata.repo);
|
||||
const ref = skill.sourceRef ?? asString(metadata.ref) ?? "main";
|
||||
const repoSkillDir = normalizePortablePath(asString(metadata.repoSkillDir) ?? skill.slug);
|
||||
const repoSkillDir = normalizeGitHubSkillDirectory(asString(metadata.repoSkillDir), skill.slug);
|
||||
if (!owner || !repo) {
|
||||
throw unprocessable("Skill source metadata is incomplete.");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue