v0.5.0
- Added
PipelineConfig.plugins: an optionallist[str]of bare plugin names. The_validate_pluginsvalidator rejects object / inline / tag-override entries and non-identifier names: a plugin is declared by name and resolves to a manifest yaml in the plugins directory. - Added catalog models in new
cuvis_ai_schemas/catalog.py:CatalogPortSpec,CatalogNodeEntry(fully-qualifiedclass_name), andCatalogPluginEntry(from_manifest_entry): the static node catalog the server reads to populate the palette without importing any plugin Python.dtypeis permissive (empty string = generic-tensor marker, mapped toD_TYPE_UNSPECIFIED);category/tagsare plain strings so newer readers degrade gracefully.CatalogNodeEntry.class_nameis validated as a fully-qualified dotted path of Python identifiers, so malformed forms such aspkg.,.Node, orpkg..Nodeare rejected on both the authoring and server-load paths. - Added the plugin-config contract here so schemas is the single source of truth (cuvis-ai-core drops its fork):
_BasePluginConfiggains an optionalpackage_nameauthor override, andPluginConfig = GitPluginConfig | LocalPluginConfigis exported.providescarriesCatalogNodeEntryitems directly, so the install list and the node catalog are the same list. - Breaking (proto): renamed
LoadPluginsResponse.loaded_plugins→registered_plugins(wire tag 1 retained). Reflects register-onlyLoadPluginsin cuvis-ai-core: entries are registered as catalog metadata, not installed; materialisation moves toLoadPipelinevia the pipeline'splugins:field. Regenerated the Python stubs. - Added an internal
RunRuntimeservice section tocuvis_ai.proto(parent ↔ child runtime). PrivateInitializeSessionhands the child its parent-owned session id, search paths, the resolved plugin dict, and FS paths; the parent forwardsLoadPipeline/LoadPipelineWeights/RestoreTrainRun/Inference/Train/CloseSession, the persistence + introspection RPCs (SavePipeline,SaveTrainRun,GetPipelineInputs/GetPipelineOutputs/GetPipelineVisualization,SetTrainRunConfig,GetTrainStatus),StopRun(graceful cancel with a grace window), andHealthCheck. Reuses the public message types; the publicCuvisAIServicesurface is untouched. Regenerated stubs viabuf generate. - Breaking (proto): a node port now maps to exactly one
PortSpec. Addedbool variadicto thePortSpecmessage, removed thePortSpecListmessage, and changedNodeInfo.input_specs/NodeInfo.output_specsfrommap<string, PortSpecList>tomap<string, PortSpec>. Regenerated the Python stubs. - Added
PortSpec.variadic(defaultFalse) to the dataclass andCatalogPortSpec.variadic;variadicmarks an input port for fan-in (the node receives a list) and is honored for input ports only.extensions/ui/port_display.pysurfaces a[Variadic]tooltip tag. - Changed
PortSpec.is_compatible_withto take a singlePortSpec(dropped thePortSpec | list[PortSpec]overload) andCatalogNodeEntry.input_specs/output_specstodict[str, CatalogPortSpec]; removed the single-spec→list coercion. - Collapsed plugin manifests so
providescarries the node list directly (class_name= fully-qualified class), and restricted pipelineplugins:to bare manifest names. - Tightened
ConnectionConfigsource/targetvalidation to reject empty node or port segments (e.g..outputs.portornode.outputs.), not just the wrong-arity case. - Pinned dependency floors (
pydantic>=2.12.5,pyyaml>=6.0.3;uv.lockin sync) and added adep_compatworkflow that audits the floors against the shared cuvis-ai-core audit script.
What's Changed
- schemas: plugins field, catalog models, RunRuntime proto, single-spec ports by @nghorbani in #19
Full Changelog: v0.4.1...v0.5.0