Repository navigation
docs(rfc): propose plugin interfaces - #2549
Conversation
Replace the Source and Artifact plugin frameworks with a few interfaces that PC Server calls through the Supervisor. Core keeps only Sources, Artifacts, collection targets, and consumption progress; plugins no longer have managed lifecycle state. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…APIs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dge collection Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hidb4ai
left a comment
There was a problem hiding this comment.
The simplification is reasonable, but the retry/storage and no-op/provenance contracts need to be consistent before this RFC is accepted. The two inline findings apply to both translations.
Bring the RFC in line with the implementation and the decisions since the last revision: user changes run through the plugin in a host process that starts for every loaded plugin; Artifact plugins may declare their own Source Definitions; Inputs can name a Projection per Source type; plugin storage, models, and the generic create and Source write contracts are spelled out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hidb4ai
left a comment
There was a problem hiding this comment.
The content-digest storage guidance and the explicit distinction between generation no-ops and user-edit provenance address my earlier RFC findings. One new contract gap remains: plugins cannot detect a same-dimension embedding-model change.
| class PluginModels(Protocol): | ||
| embedding_available: bool # whether Server has an embedding model | ||
| embedding_dimension: int | None # vector dimension; None without an embedding model | ||
| generation_available: bool # whether Server has a generation model |
There was a problem hiding this comment.
[P2] Preserve an embedding-space identity for plugin indexes
Replacing embedding_profile with availability flags and a dimension leaves plugins unable to implement the rebuild-on-configuration-change rule below. If an index was built with model A and Server restarts with a different model B of the same dimension, all exposed metadata stays unchanged, but embed() now returns vectors from a different space. The plugin can silently compare them with A's persisted vectors or mix both spaces in the same index. The existing core distinguishes same-dimension profiles for precisely this reason. Expose a non-secret embedding-space/profile fingerprint that changes with the model or relevant encoding configuration, and require it to match the persisted index before reuse. Please align both language versions.
…place the old frameworks in one migration - Rename the factory to setup; render_artifact is required, search_artifacts optional, and generate required only with a schedule or on_sources, with a methods-at-a-glance table. - Core no longer indexes plugin families: generic search passes the complete request to the plugin, and Prepared Context sections may list plugin families with optional search controls. - One new migration revision adds pc_artifacts.metadata (plugin name and version), accepts plugin: bindings without registration, keeps the FTS check to built-in rows, bumps the export record format, and refuses to upgrade while the old plugin frameworks still hold data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ir own Source types Standalone Source plugins, collection targets, and edge collection move to a follow-up proposal, which will replace the old Source plugin framework; this RFC replaces only the old Artifact plugin framework, and the old Source plugin framework stays unchanged until then. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d Context budget as the request's Prepared Context passes the request's byte budget and fills plugin entries in section order, and receipt families become strings so plugin entries count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…plugin Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… and change their own Artifacts Implements the Artifact plugin part of RFC oceanbase#2549 and the plugin APIs and Dashboard pages of RFC oceanbase#2579, and replaces the managed Artifact plugin framework (oceanbase#2246). - A plugin is a directory with plugin.py assigning an ArtifactPlugin. Server checks it in a child process; generate runs in Supervisor Workers, and render_artifact, search_artifacts, user changes, Source writes of the plugin's own types, and plugin routes run in a per-plugin host process. - Plugins present (GET .../rendering) and search their own families: generic search passes the complete request to search_artifacts, and Prepared Context sections may list plugin families. Core builds no index for them. - Revision v1_5_0_005 removes the previous framework's storage only when it is empty, adds pc_artifacts.metadata (plugin name and code digest), and accepts plugin: bindings; frozen revision resources are unchanged. Portable revision records move to schema version 3 and still restore version 2. - Plugin APIs mount at /v1/plugins/{name}/api with a configurable body ceiling, and plugin pages run in a sandboxed Dashboard frame. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
RFC oceanbase#2549 renamed the factory to setup and requires render_artifact; standalone Source plugins moved to RFC oceanbase#2617, so the examples declare routes and pages on an Artifact plugin that brings its own Source type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(rfc): propose plugin hot reload and plugin-defined APIs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(rfc): number plugin hot reload RFC as 2579 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(rfc): import plugins from version snapshots and mount routes as a group Pin every call to a read-only snapshot named by the content digest so a draining host never mixes versions and a failed update keeps the old one, detect changes by content instead of size and mtime, mount plugin routes under their own group with per-route Scope authorization, let plugins create Scopes with core's existing permission, and state page isolation as session isolation, stopping forwarding once the iframe navigates. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(rfc): keep the plugin reload RFC at the contract level Move scan, host replacement, and hosting page flows and the literal CSP header to the implementation design. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(rfc): let plugin routes opt in as MCP tools Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(rfc): let plugins upgrade their own data through a load hook Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(rfc): confirm write access in handlers, declare route body limits, and record API changes as Sources Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(rfc): name the factory setup and show routes on an Artifact plugin RFC #2549 renamed the factory to setup and requires render_artifact; standalone Source plugins moved to RFC #2617, so the examples declare routes and pages on an Artifact plugin that brings its own Source type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(rfc): run upgrade on every role, keep it small, and name MCP tools without collisions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… and change their own Artifacts Implements the Artifact plugin part of RFC oceanbase#2549 and the plugin APIs and Dashboard pages of RFC oceanbase#2579, and replaces the managed Artifact plugin framework (oceanbase#2246). - A plugin is a directory with plugin.py assigning an ArtifactPlugin. Server checks it in a child process; generate runs in Supervisor Workers, and render_artifact, search_artifacts, user changes, Source writes of the plugin's own types, and plugin routes run in a per-plugin host process. - Plugins present (GET .../rendering) and search their own families: generic search passes the complete request to search_artifacts, and Prepared Context sections may list plugin families. Core builds no index for them. - Revision v1_5_0_005 removes the previous framework's storage only when it is empty, adds pc_artifacts.metadata (plugin name and code digest), and accepts plugin: bindings; frozen revision resources are unchanged. Portable revision records move to schema version 3 and still restore version 2. - Plugin APIs mount at /v1/plugins/{name}/api with a configurable body ceiling, and plugin pages run in a sandboxed Dashboard frame. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Which issue or RFC does this PR close?
This PR proposes a new RFC that replaces the plugin contracts and management mechanisms of RFC #2175 (Artifact plugins, implemented in #2246). It is implemented in #2616. Standalone Source plugins and collection, which replace RFC #2012, are proposed separately in #2617.
Rationale for this change
The managed Artifact plugin framework makes PC Server carry plugin lifecycle on behalf of third-party code: persisted enable/disable/reload/unload state machines, registration-generation fencing, and frozen content schemas with framework-built declarative indexes. As discussed with maintainers, plugins should instead implement a few interfaces that PC Server calls when needed, similar to Dify's plugin model, and own their content structure and indexes.
What changes are included in this PR?
New RFC
docs/{en,zh}/rfcs/2549-plugin-interfaces.md(Chinese first, English translation in sync):plugin.py, which assigns anArtifactPlugindeclaration toplugin; no manifest file.setup(ctx)returns the plugin object.render_artifact(required),generate(required with a schedule oron_sources), and optionalsearch_artifactsand user-change methods (create_artifact,update_artifact,merge_artifacts,forget_artifact,restore_artifact). A methods-at-a-glance table lists when each is called and where it runs. Reads, history, governance, and tags call no plugin method.GET .../{artifact_id}/renderingreturns the plugin's default presentation. Generic search passes the complete request tosearch_artifacts, and core keeps only current, active revisions the caller may read. Prepared Context sections may list plugin families, with an optionalsearchpassed through.generatewrites inasync with writer.transaction(), committed with the consumption cursor; user changes go through the plugin, with core handling authorization, version checks, and provenance. Plugins may declare their own Source types to record what users asked for.ctx.storageandctx.modelsgive plugins dedicated storage and the Server's models without credentials.pc_artifacts.metadatawith the writing plugin's name and version, acceptsplugin:bindings without registration, and keeps frozen revision resources unchanged; portable revision records gainmetadata.Are there any user-facing changes?
This PR changes documentation only. The proposed design, implemented in #2616, removes
/v1/admin/artifact-plugins,powercontext.artifact_plugins, andPOWERCONTEXT_SERVER_ARTIFACT_PLUGINS_DIR, and refuses to upgrade while plugins of the old framework still hold data. Typed clients seeCreateArtifactRequestbecome a choice between built-in and plugin branches, and several family fields (ArtifactCreated.family,TaggableArtifactFamily,ContextAssemblySection.family, receipt families) andCreateSourceRequest.source_typebecome strings; wire formats of existing requests are unchanged.How was this change tested?
uv run prek run --files docs/en/rfcs/2549-plugin-interfaces.md docs/zh/rfcs/2549-plugin-interfaces.mdAI usage statement
Drafted with Claude Code (Claude Opus 5.5) under the author's direction and review.
🤖 Generated with Claude Code