From 61b332583c4fcbf71890ae67e3f0f104d67706b9 Mon Sep 17 00:00:00 2001 From: ddCat <2695092045@qq.com> Date: Wed, 26 Aug 2026 16:28:45 +0800 Subject: [PATCH] =?UTF-8?q?refactor(canvas):=20=E7=94=9F=E6=88=90=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=20-=20=E6=94=B6=E6=95=9B=E6=8F=92=E4=BB=B6=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E5=B9=B6=E7=A7=BB=E9=99=A4=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E5=88=86=E6=94=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/service/protocol_registry.go | 24 ++- .../internal/service/protocol_runtime_test.go | 18 +++ .../canvas/canvas-config-composer.tsx | 14 +- .../canvas/canvas-config-node-panel.tsx | 150 +++++------------- .../components/canvas/canvas-create-menu.tsx | 11 +- .../components/canvas/canvas-node-content.tsx | 9 +- web/src/components/canvas/canvas-node.tsx | 67 +++++--- web/src/components/canvas/canvas-toolbar.tsx | 2 +- web/src/constant/canvas.ts | 4 +- .../lib/canvas/canvas-project-generation.ts | 9 +- .../definitions/add-node-menu-tools.tsx | 31 +--- .../canvas/tool-registry/tool-definition.ts | 2 +- .../components/channel-model-manager.tsx | 4 +- .../canvas/use-canvas-node-operations.ts | 4 +- web/src/styles/globals.css | 124 +++++++++------ 15 files changed, 227 insertions(+), 246 deletions(-) diff --git a/backend/internal/service/protocol_registry.go b/backend/internal/service/protocol_registry.go index d953d061d..a2818032c 100644 --- a/backend/internal/service/protocol_registry.go +++ b/backend/internal/service/protocol_registry.go @@ -70,11 +70,13 @@ func (s *Service) PluginProviderCatalog(scope, capability string, includeUnavail continue } item := PluginProviderCatalogItem{ID: provider.ID, Version: plugin.Manifest.Version, Name: provider.Label, Vendor: plugin.Manifest.Author, Categories: provider.Capabilities, Scopes: provider.Scopes, BaseURL: provider.BaseURL, Enabled: plugin.Status == "enabled", UnavailableReason: plugin.Error, Workflows: workflowsForProvider(plugin.Manifest.Contributes.Workflows, provider.ID)} - item.Create = operationSummary(provider.Create) - if provider.Poll != nil { - item.Poll = operationSummary(*provider.Poll) + item.Create, item.Poll, item.ContentType = operationSummary(provider.Create), operationSummaryPtr(provider.Poll), provider.Create.ContentType + // The registry metadata is the canonical provider projection. This keeps + // host-backed dispatch paths out of every user-facing catalog consumer. + if adapter, ok := canonicalProviderAdapter(s.protocolRegistry(), provider.ID); ok { + metadata := adapter.Metadata() + item.Create, item.Poll, item.ContentType = metadata.Create, metadata.Poll, metadata.ContentType } - item.ContentType = provider.Create.ContentType if includeUnavailable || item.Enabled { items = append(items, item) } @@ -83,6 +85,13 @@ func (s *Service) PluginProviderCatalog(scope, capability string, includeUnavail return items } +func canonicalProviderAdapter(registry *protocol.Registry, id string) (protocol.Adapter, bool) { + if adapter, ok := protocol.Builtins().Resolve(id); ok { + return adapter, true + } + return registry.Resolve(id) +} + func containsPluginSurface(items []protocol.Surface, want protocol.Surface) bool { for _, item := range items { if item == want { @@ -114,6 +123,13 @@ func operationSummary(operation protocol.ManifestOperation) string { return strings.ToUpper(operation.Method) + " " + path } +func operationSummaryPtr(operation *protocol.ManifestOperation) string { + if operation == nil { + return "" + } + return operationSummary(*operation) +} + func (s *Service) protocolRegistry() *protocol.Registry { if s.pluginRuntime != nil { if registry := s.pluginRuntime.registrySnapshot(); registry != nil { diff --git a/backend/internal/service/protocol_runtime_test.go b/backend/internal/service/protocol_runtime_test.go index 474fce80b..b5d6010fb 100644 --- a/backend/internal/service/protocol_runtime_test.go +++ b/backend/internal/service/protocol_runtime_test.go @@ -35,6 +35,24 @@ func TestPluginViewIncludesDocumentationForEveryBundledProtocol(t *testing.T) { } } +func TestBundledProviderCatalogExposesUpstreamOperation(t *testing.T) { + center, err := newPluginRuntime(t.TempDir()) + if err != nil { + t.Fatal(err) + } + catalog := (&Service{pluginRuntime: center}).PluginProviderCatalog(string(protocol.SurfaceAdminSystemChannel), string(protocol.CapabilityVideo), false) + for _, item := range catalog { + if item.ID != "xai-video" { + continue + } + if item.Create != "POST /v1/videos/generations" || strings.Contains(item.Create, "__host__") { + t.Fatalf("xAI catalog create operation = %q", item.Create) + } + return + } + t.Fatal("xAI bundled provider missing from administrator catalog") +} + func TestPluginRuntimeIsTheProtocolSourceOfTruth(t *testing.T) { dataDir := t.TempDir() center, err := newPluginRuntime(dataDir) diff --git a/web/src/components/canvas/canvas-config-composer.tsx b/web/src/components/canvas/canvas-config-composer.tsx index 194766a25..b3cd4cb77 100644 --- a/web/src/components/canvas/canvas-config-composer.tsx +++ b/web/src/components/canvas/canvas-config-composer.tsx @@ -161,13 +161,13 @@ export function CanvasConfigComposer({ value, inputs, skillReferences = [], gene return (