Skip to content

[5512] feat(api): catalog provider adapters (GitHub behind a registry) - #6626

Open
ardaerzin wants to merge 2 commits into
feat/skills-facade-webfrom
feat/skills-provider-adapters
Open

[5512] feat(api): catalog provider adapters (GitHub behind a registry)#6626
ardaerzin wants to merge 2 commits into
feat/skills-facade-webfrom
feat/skills-provider-adapters

Conversation

@ardaerzin

Copy link
Copy Markdown
Contributor

Context

The last piece of the backend review's requested direction (#4): import was GitHub-specific end to end — URL parsing, the tarball API, and provenance link shapes leaked through the import service, routes, and frontend. Adding any second catalog kind meant touching all of them.

Changes

New core/skills/providers/ package:

  • CatalogProvider contract: claims(source_url) -> Locator | None, fetch_snapshot(locator) -> Snapshot, item_url(...).
  • Neutral SourceLocator / SourceSnapshot DTOs; the stored origin.locator keeps the shared repository/ref/path keys (matching the review's canonical schema).
  • ProviderRegistry (resolve by URL claim with an optional explicit provider; get by stored provider name), wired in entrypoints/ with GitHub as the only registered adapter.

Everything GitHub-specific moved into providers/github.py; the shared archive rails (streamed size cap, decompression-bomb ceilings, traversal rejection) stay in fetcher.py for any archive-shipping provider. Update check/apply look the adapter up from the stored origin's provider — the field now does real work. Wire: repo_urlsource_url plus optional provider on scan/import (nothing shipped, so no aliasing). The frontend no longer builds provider URLs — it renders the adapter-supplied provenance link.

Before:

import_service → GitHubTarballFetcher → github.com hardcoded in update flows + FE

After:

import_service → registry.resolve(url) / registry.get(origin.provider) → adapter

Adding GitLab or a marketplace later = one adapter file + one registry entry.

Tests

  • 5 new provider/registry tests (URL claiming shapes, ref threading, unrecognized source, unregistered provider, item-url shape).
  • The import suite's fetcher stub became a registered filesystem provider, so every import test now exercises the registry too. Full API suite 3270; all web typechecks green.
  • Live on /m: scan, import markers (14/14 already imported), and per-section Check updates all running through the adapter path.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Sep 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
agenta-documentation Ready Ready Preview Sep 8, 2026 1:58am UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • release/.*

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Team

Run ID: 7df7955b-eb58-42f1-bfe0-77cbc58c4361

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Summary

Summary by CodeRabbit

  • New Features
    • Added provider-based skill source scanning and importing, with GitHub support.
    • Added optional provider selection for source requests.
    • Added provider-specific provenance links in imported skill details.
  • Changes
    • Renamed the source request and response field from repo_url to source_url.
    • Improved source URL validation and support for multiple catalog providers.
  • Documentation
    • Documented the provider adapter architecture and provenance updates.

Walkthrough

The skill import flow now uses registered catalog providers. GitHub fetching moves into a provider adapter. APIs use source_url and optional provider fields. Imports, updates, provenance, tests, and frontend mappings use provider-supplied source metadata.

Changes

Provider catalog import flow

Layer / File(s) Summary
Provider contracts and archive rails
api/oss/src/core/skills/providers/base.py, api/oss/src/core/skills/fetcher.py
Defines SourceLocator, SourceSnapshot, and CatalogProvider. Shared tarball extraction remains in fetcher.py.
Provider registry and GitHub adapter
api/oss/src/core/skills/providers/*, api/oss/tests/pytest/unit/skills/test_providers.py
Adds provider resolution, GitHub URL claims, tarball fetching, size limits, error mapping, and item URL generation.
Import service and provenance migration
api/oss/src/core/skills/import_service.py, api/oss/src/core/skills/provenance.py, api/oss/tests/pytest/unit/skills/test_import_service.py
Routes scan, import, and update operations through providers. Stores provider names, resolved versions, and provider-supplied URLs.
API and frontend contract wiring
api/entrypoints/routers.py, api/oss/src/apis/fastapi/skills/*, web/packages/agenta-skills/src/*, web/packages/agenta-skills-ui/src/*
Renames repo_url to source_url, adds optional provider fields, registers GitHub, and reads imported provenance URLs.
Architecture documentation
docs/design/agent-workflows/projects/skill-registry/plan-meta-provenance.md
Documents the provider adapter architecture and its integration points.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: 🟡 Moderate · up to f5b93

Imports from distinct providers can be skipped when their repository and path match. Provenance links can target the wrong item for reserved path characters, and web callers cannot select a provider through the exported source wrappers. These contract issues should be resolved before merge.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant SkillsRouter
  participant SkillImportService
  participant ProviderRegistry
  participant GitHubProvider
  Client->>SkillsRouter: Submit source_url and optional provider
  SkillsRouter->>SkillImportService: scan_source or import_from_source
  SkillImportService->>ProviderRegistry: resolve source
  ProviderRegistry->>GitHubProvider: claims source_url
  GitHubProvider-->>ProviderRegistry: SourceLocator
  ProviderRegistry-->>SkillImportService: Provider and locator
  SkillImportService->>GitHubProvider: fetch_snapshot
  GitHubProvider-->>SkillImportService: SourceSnapshot
  SkillImportService-->>SkillsRouter: Result with source_url, provider, and resolved_version
  SkillsRouter-->>Client: Scan or import response
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.71% which is insufficient. The required threshold is 60.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 42 functions across 15 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the provider adapter architecture, GitHub registry integration, API changes, frontend changes, and test coverage. It is directly related to the changeset.
Title check ✅ Passed The title clearly and concisely identifies the main change: adding catalog provider adapters with GitHub behind a registry.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 35.71% which is insufficient. The required threshold is 60.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 42 functions across 15 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/skills-provider-adapters

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

📘 Docs preview

Status ✅ Ready
Preview https://pr-6626-agenta-docs-preview.mahmoud-637.workers.dev/docs
Inspect Actions run
Commit 9d067fa95d03d6f839c8bd671e8ed832b3080010

This comment updates in place on every push.

@ardaerzin

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Team

Run ID: 73b97e24-b339-47f1-9174-2da1909083a3

📥 Commits

Reviewing files that changed from the base of the PR and between 7e04151 and f5b9303.

⛔ Files ignored due to path filters (5)
  • web/packages/agenta-api-client/src/generated/api/resources/skills/client/Client.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/resources/skills/client/requests/SkillSourceImportRequest.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/resources/skills/client/requests/SkillSourceScanRequest.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/ImportResult.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/SourceScanResult.ts is excluded by !**/generated/**
📒 Files selected for processing (16)
  • api/entrypoints/routers.py
  • api/oss/src/apis/fastapi/skills/models.py
  • api/oss/src/apis/fastapi/skills/router.py
  • api/oss/src/core/skills/fetcher.py
  • api/oss/src/core/skills/import_service.py
  • api/oss/src/core/skills/provenance.py
  • api/oss/src/core/skills/providers/__init__.py
  • api/oss/src/core/skills/providers/base.py
  • api/oss/src/core/skills/providers/github.py
  • api/oss/src/core/skills/providers/registry.py
  • api/oss/tests/pytest/unit/skills/test_import_service.py
  • api/oss/tests/pytest/unit/skills/test_providers.py
  • docs/design/agent-workflows/projects/skill-registry/plan-meta-provenance.md
  • web/packages/agenta-skills-ui/src/registrySections.ts
  • web/packages/agenta-skills/src/api/index.ts
  • web/packages/agenta-skills/src/core/schema.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 3 remain after this review.

c.path_in_repo
for c in scan.candidates
if (repository, c.path_in_repo) in index
if (locator.repository, c.path_in_repo) in index

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Include provider in every import identity check.

build_origin already stores provider, but _origin_index and both duplicate checks use only (repository, path). If two registered providers return the same pair, the second import can be incorrectly skipped. Key the index and the checks by (provider, repository, path), and add a two-provider regression test.

) -> Optional[str]:
if not resolved_version:
return None
return f"https://github.com/{locator.repository}/tree/{resolved_version}/{path}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Encode path before creating the GitHub URL.

A skill path containing #, ?, or % produces a different browser URL. The provenance link can then point to the wrong item. Encode path segments and keep / as a separator. Add a regression test with a reserved character.

Proposed fix
+from urllib.parse import quote
+
-        return f"https://github.com/{locator.repository}/tree/{resolved_version}/{path}"
+        encoded_path = quote(path, safe="/")
+        return f"https://github.com/{locator.repository}/tree/{resolved_version}/{encoded_path}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return f"https://github.com/{locator.repository}/tree/{resolved_version}/{path}"
from urllib.parse import quote
encoded_path = quote(path, safe="/")
return f"https://github.com/{locator.repository}/tree/{resolved_version}/{encoded_path}"


const data = await getSkillsClient().scanSkillSource(
{repo_url: repoUrl, ...(ref ? {ref} : {})},
{source_url: repoUrl, ...(ref ? {ref} : {})},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Forward provider through both public source wrappers.

@agenta/skills exports both wrappers, but their parameter interfaces omit provider and discard it before the generated requests. The backend forwards this field to ProviderRegistry.resolve, which selects the named adapter. Although GitHub is currently the only registered adapter, omitting the field prevents callers from selecting any additional registered provider.

Proposed fix
 export interface ScanSkillSourceParams {
     projectId: string
     repoUrl: string
+    provider?: string
     ref?: string
 }

 export async function scanSkillSource({
     projectId,
     repoUrl,
+    provider,
     ref,
 }: ScanSkillSourceParams) {
     const data = await getSkillsClient().scanSkillSource(
-        {source_url: repoUrl, ...(ref ? {ref} : {})},
+        {source_url: repoUrl, ...(provider ? {provider} : {}), ...(ref ? {ref} : {})},
         {queryParams: {project_id: projectId}},
     )
 }

 export interface ImportSkillSourceParams {
     projectId: string
     repoUrl: string
+    provider?: string
     ref?: string
     paths?: string[]
 }

 export async function importSkillSource({
     projectId,
     repoUrl,
+    provider,
     ref,
     paths,
 }: ImportSkillSourceParams) {
     const data = await getSkillsClient().importSkillSource(
         {
             source_url: repoUrl,
+            ...(provider ? {provider} : {}),
             ...(ref ? {ref} : {}),
             ...(paths ? {paths} : {}),
         },
         {queryParams: {project_id: projectId}},
     )
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{source_url: repoUrl, ...(ref ? {ref} : {})},
{source_url: repoUrl, ...(provider ? {provider} : {}), ...(ref ? {ref} : {})},

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. The remaining V1 implementation choices are accepted.

Implements the review's provider direction: a CatalogProvider contract
(claims / fetch_snapshot / item_url), neutral locator and snapshot DTOs,
and a ProviderRegistry wired in the entrypoints with GitHub as the only
registered adapter. Nothing outside providers/ mentions repos, refs, or
tarballs: the import service resolves adapters by URL claim (or an explicit
provider field), update flows look the adapter up from the stored origin's
provider, and provenance links are adapter-supplied. The wire renames
repo_url to source_url; the frontend stops building provider URLs and uses
the stored provenance link. Unit tests register a filesystem provider, so
every import test also exercises the registry.
…link

Two catalogs can name the same repository string, so the already-imported
index keys on provider + repository + path rather than assuming one catalog.
The GitHub adapter also encodes the item path, keeping links valid for paths
holding spaces or '#', and both public source wrappers forward the optional
provider so a caller can narrow resolution to one adapter.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants