From abf8fe80151e51d7548feedcc1fa93e56459d256 Mon Sep 17 00:00:00 2001 From: AHMET BAYHAN BAYRAMOGLU <49499275+ABB65@users.noreply.github.com> Date: Mon, 13 Jul 2026 14:15:18 +0300 Subject: [PATCH] docs: propagate media facet + fix stale provider reference in VitePress site MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audit of the docs LAYER after the media-tools + capability-aware-listing releases. `vitepress build` passes clean (no dead links); these fix consistency/completeness gaps the per-PR edits missed: - reference/providers.md (canonical RepoProvider reference): - add `media?: MediaProvider` to the interface listing + a Media facet section documenting MediaProvider and the media asset/input types - fix `mergeBranch` signature (missing `opts?: { removeSourceBranch? }`) and MergeResult (missing `remote?` cleanup outcome) — both stale since the merge-source-delete opt-in change, never documented - packages/types.md: add the six media types to the Provider Contract Types catalog; update RepoProvider + MergeResult row descriptions - guides/providers.md: correct the localWorktree capability row (was `init/scaffold/.../bulk`; those gate on projectRoot, not the capability) to match TOOL_REQUIREMENTS + the embedding guide, add the projectRoot + media-facet gating notes - packages/cli.md: clarify stdio serves the 19 core tools (media needs a media-capable provider) — drop the dangling "Same 19 tools" Docs site is private (not published), so no changeset. --- docs/guides/providers.md | 6 ++++- docs/packages/cli.md | 2 +- docs/packages/types.md | 15 +++++++++-- docs/reference/providers.md | 50 +++++++++++++++++++++++++++++++++++-- 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/docs/guides/providers.md b/docs/guides/providers.md index b3ea57d..9f19653 100644 --- a/docs/guides/providers.md +++ b/docs/guides/providers.md @@ -31,7 +31,7 @@ Some tools need more than a git provider can offer — normalize has to walk you | Capability | LocalProvider | GitHubProvider | GitLabProvider | Tools that require it | |---|---|---|---|---| -| `localWorktree` | ✓ | — | — | `init`, `scaffold`, `validate --fix`, `submit`, `merge`, `bulk` | +| `localWorktree` | ✓ | — | — | `validate --fix`, `submit`, `merge`, `branch_list`, `branch_delete` | | `sourceRead` | ✓ | — | — | `apply` (extract mode) | | `sourceWrite` | ✓ | — | — | `apply` (reuse mode) | | `astScan` | ✓ | — | — | `scan` | @@ -39,6 +39,10 @@ Some tools need more than a git provider can offer — normalize has to walk you | `branchProtection` | — | ✓ | ✓ | merge fallback detection | | `pullRequestFallback` | — | ✓ | ✓ | merge fallback creation | +A separate requirement — a local `projectRoot` on disk, not a capability flag — gates `init`, `scaffold`, `doctor`, and `bulk`. Tool listing is capability-aware: `tools/list` only advertises tools the resolved provider + `projectRoot` pair can satisfy, so a remote-provider session simply doesn't show the tools it couldn't run (see [MCP Tools](/packages/mcp) and `TOOL_REQUIREMENTS` in `@contentrain/mcp/tools/availability`). + +The five `contentrain_media_*` tools gate on a separate optional facet, `RepoProvider.media` (an object, not a capability flag). They appear only on providers that expose a media stack — Studio MCP Cloud — and never on Local / GitHub / GitLab. + Read-only tools (`status`, `describe`, `describe_format`, `content_list`, `validate` without `--fix`) work on every provider. Write tools (`content_save`, `content_delete`, `model_save`, `model_delete`) work over any provider too — a remote provider posts the changes as a single atomic commit and always returns `action: pending-review` so Studio (or whoever orchestrates the server) drives the merge. `content_list` with `resolve: true` requires local filesystem access today because relation hydration walks other models' content files. The reader-backed path rejects it with a descriptive error. diff --git a/docs/packages/cli.md b/docs/packages/cli.md index d3ee6fc..ad9ec47 100644 --- a/docs/packages/cli.md +++ b/docs/packages/cli.md @@ -299,7 +299,7 @@ Serves REST endpoints (`/api/status`, `/api/content`, `/api/branches`, `/api/doc contentrain serve --stdio ``` -For IDE agents. Same 19 tools, stdio transport. +For IDE agents. Uses `LocalProvider`, so it serves the 19 core tools over stdio (the `contentrain_media_*` tools need a media-capable provider such as Studio MCP Cloud). #### MCP HTTP diff --git a/docs/packages/types.md b/docs/packages/types.md index fcb23cc..5132920 100644 --- a/docs/packages/types.md +++ b/docs/packages/types.md @@ -120,7 +120,7 @@ Third-party developers can implement custom providers by implementing these inte | Interface / Type | Purpose | |-----------|---------| -| `RepoProvider` | Full provider contract: read, write, branch, merge, diff operations | +| `RepoProvider` | Full provider contract: read, write, branch, merge, diff operations, plus an optional `media?: MediaProvider` facet | | `RepoReader` | Read-only interface (readFile, listDirectory, fileExists) | | `RepoWriter` | Write interface (applyPlan for atomic commits) | | `ProviderCapabilities` | Capability flags (localWorktree, sourceRead, sourceWrite, pushRemote, branchProtection, pullRequestFallback, astScan) | @@ -129,10 +129,21 @@ Third-party developers can implement custom providers by implementing these inte | `Commit` | Result of a commit operation (sha, message, author, timestamp) | | `Branch` | Git branch metadata (name, sha, protected) | | `FileDiff` | File change within a plan (path, status, before, after) | -| `MergeResult` | Merge outcome (merged flag, sha, pullRequestUrl, optional `sync?: SyncResult` for LocalProvider) | +| `MergeResult` | Merge outcome (merged flag, sha, pullRequestUrl, optional `sync?: SyncResult` for LocalProvider, optional `remote?` source-branch cleanup outcome) | | `SyncResult` | Selective file sync result (synced, skipped, optional warning) | | `CommitAuthor` | Commit author metadata (name, email) | +Media facet types (implemented by providers exposing a media stack — drives the `contentrain_media_*` tools): + +| Interface / Type | Purpose | +|-----------|---------| +| `MediaProvider` | Optional `RepoProvider.media` facet: `list` / `get` / `ingest` / `update` / `delete` | +| `MediaAsset` | One asset — `id`, `path` (`media/...`), optional `url`, `mime`, `size`, `alt`, `tags`, `createdAt`, `meta` | +| `MediaListOptions` | List filters (`search`, `tag`, `limit`, `cursor`) | +| `MediaListResult` | List page (`assets`, optional `nextCursor`, `total`) | +| `MediaIngestInput` | URL-based ingest input (`url`, optional `filename`, `alt`, `tags`) | +| `MediaUpdateInput` | Metadata patch (`alt`, `tags`, `filename`) | + Pre-built capability set: - `LOCAL_CAPABILITIES` — Full capability set for LocalProvider (all seven capabilities enabled). Exported from `@contentrain/types` for custom providers that back onto the local filesystem. diff --git a/docs/reference/providers.md b/docs/reference/providers.md index a6c35be..71e4a76 100644 --- a/docs/reference/providers.md +++ b/docs/reference/providers.md @@ -61,17 +61,25 @@ interface RepoProvider extends RepoReader, RepoWriter { // providers, where media stays a relative path. readonly mediaBaseUrl?: string + // Optional media facet. Present only on providers whose backend exposes a + // media stack (e.g. Studio MCP Cloud); drives the `contentrain_media_*` + // tools, which are not registered when this is absent. + readonly media?: MediaProvider + listBranches(prefix?: string): Promise createBranch(name: string, fromRef?: string): Promise deleteBranch(name: string): Promise getBranchDiff(branch: string, base?: string): Promise - mergeBranch(branch: string, into: string): Promise + // opts.removeSourceBranch deletes the source after a successful merge + // (opt-in, best-effort — reported via MergeResult.remote). Long-lived + // branches (into, contentrain, the default branch) are never deleted. + mergeBranch(branch: string, into: string, opts?: { removeSourceBranch?: boolean }): Promise isMerged(branch: string, into?: string): Promise getDefaultBranch(): Promise } ``` -`MergeResult` is `{ merged, sha, pullRequestUrl, sync? }`. GitHubProvider fills `sha` on direct merges; GitLabProvider fills both `sha` and `pullRequestUrl` (merges via MR). LocalProvider populates `sync: SyncResult` to describe file syncing to the working tree. When branch protection blocks a direct merge, any provider may return `merged: false` with a `pullRequestUrl` fallback. +`MergeResult` is `{ merged, sha, pullRequestUrl, sync?, remote? }`. GitHubProvider fills `sha` on direct merges; GitLabProvider fills both `sha` and `pullRequestUrl` (merges via MR). LocalProvider populates `sync: SyncResult` to describe file syncing to the working tree. When branch protection blocks a direct merge, any provider may return `merged: false` with a `pullRequestUrl` fallback. `remote` reports the outcome of the optional post-merge source-branch cleanup (`deleted`, plus `skipped` for an expected no-op or `warning` for a non-fatal failure). ## Capabilities @@ -127,6 +135,39 @@ export const LOCAL_CAPABILITIES: ProviderCapabilities = { } ``` +## Media facet (optional) + +`RepoProvider.media` is an optional facet — not a capability flag. When a provider implements it (hosted providers such as Studio MCP Cloud), the `contentrain_media_*` tools are registered; when it is absent (Local / GitHub / GitLab), those tools never appear in `tools/list`. It is a deterministic passthrough to the backend's media stack — MCP makes no media decisions. + +```ts +interface MediaProvider { + list(opts?: MediaListOptions): Promise + get(id: string): Promise + ingest(input: MediaIngestInput): Promise // URL-based; provider owns SSRF/MIME/size policy + update(id: string, patch: MediaUpdateInput): Promise + delete(id: string): Promise +} + +interface MediaAsset { + id: string + path: string // repo-relative storage path content fields reference (media/...) + url?: string // absolute delivery URL when resolvable (see mediaBaseUrl) + mime?: string + size?: number + alt?: string + tags?: string[] + createdAt?: string + meta?: Record // provider-defined extras (dimensions, blurhash, variants) +} + +interface MediaListOptions { search?: string; tag?: string; limit?: number; cursor?: string } +interface MediaListResult { assets: MediaAsset[]; nextCursor?: string; total?: number } +interface MediaIngestInput { url: string; filename?: string; alt?: string; tags?: string[] } +interface MediaUpdateInput { alt?: string; tags?: string[]; filename?: string } +``` + +MCP has no binary channel, so ingest is URL-based: the agent supplies a source URL and the provider fetches it server-side under its own SSRF/MIME/size policy. See [MCP Tools → Media Tools](/packages/mcp) for the tool-level reference. + ## Supporting types ```ts @@ -155,6 +196,11 @@ interface MergeResult { sha: string | null pullRequestUrl: string | null sync?: SyncResult // Only populated by LocalProvider + remote?: { // Post-merge source-branch cleanup outcome + deleted: boolean + skipped?: string // Expected no-op (cleanup disabled, no remote, ref gone) + warning?: string // Non-fatal failure (offline, auth) — merge still succeeded + } } interface SyncResult {