forked from farhoodlabs/paperclip
fork: add Gitea/Forgejo source support for company skills
Reintroduce Gitea/Forgejo as a skill import source on dev only, since the fork deploys against git.farh.net. Pasting a Gitea/Forgejo repo URL into the skills sidebar mirrors the existing GitHub experience: pin to a commit SHA, check for updates, read repo files. Server: new gitea-fetch.ts (URL builders, probe-cache helpers) and gitea-skills.ts (parse, probe, pin, tree, text, branch). Dispatch in readUrlSkillImports probes /api/v1/version and routes non-github.com hosts into the new readGiteaUrlSkillImports branch. updateStatus and readFile get a gitea arm alongside the github/skills_sh arm. Audit falls through to "remote not supported" the same way github does. UI: Server icon, Gitea source label, gitea in the "external" source class, Pin/Update UI gate widened to sourceType === "gitea". CLI help text updated. Existing github code is left byte-for-byte unchanged (wrapped in isGitHubDotCom) so dev <-> master syncs stay clean. PAT support, gitea portability descriptors, and gitea audit are deliberate follow-ups. Detection requires /api/v1/version to return Gitea-shaped JSON; the per-host result is cached for process lifetime with FIFO eviction at 1024 entries. Non-Gitea hosts fall through to the existing raw-markdown url branch. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -86,6 +86,7 @@ import {
|
||||
RefreshCw,
|
||||
Save,
|
||||
Search,
|
||||
Server,
|
||||
ShieldCheck,
|
||||
Trash2,
|
||||
Users,
|
||||
@@ -192,6 +193,8 @@ function sourceMeta(sourceBadge: CompanySkillSourceBadge, sourceLabel: string |
|
||||
return isSkillsShManaged
|
||||
? { icon: VercelMark, label: sourceLabel ?? "skills.sh", managedLabel: "skills.sh managed" }
|
||||
: { icon: Github, label: sourceLabel ?? "GitHub", managedLabel: "GitHub managed" };
|
||||
case "gitea":
|
||||
return { icon: Server, label: sourceLabel ?? "Gitea", managedLabel: "Gitea managed" };
|
||||
case "url":
|
||||
return { icon: Link2, label: sourceLabel ?? "URL", managedLabel: "URL managed" };
|
||||
case "local":
|
||||
@@ -329,7 +332,7 @@ function classifySource(skill: {
|
||||
if (kind === "optional") return "optional";
|
||||
return "company";
|
||||
}
|
||||
if (skill.sourceBadge === "github" || skill.sourceBadge === "skills_sh" || skill.sourceBadge === "url" || skill.sourceBadge === "local") {
|
||||
if (skill.sourceBadge === "github" || skill.sourceBadge === "skills_sh" || skill.sourceBadge === "gitea" || skill.sourceBadge === "url" || skill.sourceBadge === "local") {
|
||||
return "external";
|
||||
}
|
||||
return "company";
|
||||
@@ -1512,7 +1515,7 @@ function SkillPane({
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
{detail.sourceType === "github" && (
|
||||
{(detail.sourceType === "github" || detail.sourceType === "gitea") && (
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<span className="text-[11px] uppercase tracking-[0.18em] text-muted-foreground">Pin</span>
|
||||
<span className="font-mono text-xs">{currentPin ?? "untracked"}</span>
|
||||
@@ -1802,7 +1805,7 @@ export function CompanySkills() {
|
||||
enabled: Boolean(
|
||||
selectedCompanyId
|
||||
&& selectedSkillId
|
||||
&& (detailQuery.data?.sourceType === "github" || displayedDetail?.sourceType === "github"),
|
||||
&& (detailQuery.data?.sourceType === "github" || detailQuery.data?.sourceType === "gitea" || displayedDetail?.sourceType === "github" || displayedDetail?.sourceType === "gitea"),
|
||||
),
|
||||
staleTime: 60_000,
|
||||
});
|
||||
@@ -2297,7 +2300,7 @@ export function CompanySkills() {
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add a skill source</DialogTitle>
|
||||
<DialogDescription>
|
||||
Paste a local path, GitHub URL, or `skills.sh` command into the field first.
|
||||
Paste a local path, GitHub or Gitea/Forgejo URL, or `skills.sh` command into the field first.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="space-y-3 text-sm">
|
||||
@@ -2437,7 +2440,7 @@ export function CompanySkills() {
|
||||
<input
|
||||
value={source}
|
||||
onChange={(event) => setSource(event.target.value)}
|
||||
placeholder="Paste path, GitHub URL, or skills.sh command"
|
||||
placeholder="Paste path, GitHub or Gitea/Forgejo URL, or skills.sh command"
|
||||
className="w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground"
|
||||
/>
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user