feat(editor): load strict contract bundles#12
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for loading a canonical “editor contract bundle” (strict contracts + schemas + metadata) via a new host callback, while keeping legacy schema/plugin loaders as a fallback. This extends schema state in the editor store and surfaces contract metadata in the property panel for modules and pipeline steps.
Changes:
- Introduces
onEditorBundleRequestand new public bundle/contract/message/schema types for the editor host interface. - Extends
moduleSchemaStoreto load/normalize bundles (modules, steps, coercion rules, contracts/messages, YAML schemas) and provides lookup helpers. - Displays contract metadata in the Property Panel and adds/updates tests for bundle loading and UI rendering.
Reviewed changes
Copilot reviewed 7 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/types/editor.ts | Adds public types for editor contract bundles, contracts/messages, and YAML schemas, plus the new host callback prop. |
| src/stores/moduleSchemaStore.ts | Adds bundle-aware schema state, bundle loading/normalization integration, and contract/message/schema lookup helpers. |
| src/stores/moduleSchemaStore.contracts.test.ts | New tests covering contract bundle loading and overlay behavior. |
| src/generated/load-schemas.ts | Adds normalizeEditorContractBundle to safely default missing bundle sections. |
| src/generated/load-schemas.test.ts | Tests for bundle normalization behavior. |
| src/components/properties/PropertyPanel.tsx | Surfaces contract metadata for selected module/step nodes. |
| src/components/properties/PropertyPanel.test.tsx | Tests contract metadata rendering for module and step nodes. |
| src/components/WorkflowEditor.tsx | Loads editor bundle via onEditorBundleRequest with fallback to legacy schema callbacks. |
| src/components/WorkflowEditor.test.tsx | Tests bundle-preferred loading and legacy fallback scenarios. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const [schemaData, pluginData] = await Promise.all([ | ||
| onSchemaRequest ? onSchemaRequest() : Promise.resolve(null), | ||
| onPluginSchemaRequest ? onPluginSchemaRequest() : Promise.resolve(null), | ||
| ]); | ||
| if (cancelled) return; | ||
| if (schemaData) loadSchemas(schemaData.modules as Parameters<typeof loadSchemas>[0]); | ||
| if (pluginData) loadPluginSchemas(pluginData); |
There was a problem hiding this comment.
loadLegacySchemas uses Promise.all for onSchemaRequest and onPluginSchemaRequest. If either callback rejects, the whole await rejects and you end up loading neither schema set (and you can also get an unhandled rejection from the effect). Consider handling these independently (e.g., Promise.allSettled or separate try/catch per callback) so one failing callback doesn’t prevent the other from being applied.
| const [schemaData, pluginData] = await Promise.all([ | |
| onSchemaRequest ? onSchemaRequest() : Promise.resolve(null), | |
| onPluginSchemaRequest ? onPluginSchemaRequest() : Promise.resolve(null), | |
| ]); | |
| if (cancelled) return; | |
| if (schemaData) loadSchemas(schemaData.modules as Parameters<typeof loadSchemas>[0]); | |
| if (pluginData) loadPluginSchemas(pluginData); | |
| const [schemaResult, pluginResult] = await Promise.allSettled([ | |
| onSchemaRequest ? onSchemaRequest() : Promise.resolve(null), | |
| onPluginSchemaRequest ? onPluginSchemaRequest() : Promise.resolve(null), | |
| ]); | |
| if (cancelled) return; | |
| if (schemaResult.status === 'fulfilled') { | |
| const schemaData = schemaResult.value; | |
| if (schemaData) loadSchemas(schemaData.modules as Parameters<typeof loadSchemas>[0]); | |
| } else { | |
| console.warn('Failed to load legacy schemas:', schemaResult.reason); | |
| } | |
| if (pluginResult.status === 'fulfilled') { | |
| const pluginData = pluginResult.value; | |
| if (pluginData) loadPluginSchemas(pluginData); | |
| } else { | |
| console.warn('Failed to load legacy plugin schemas:', pluginResult.reason); | |
| } |
Summary
onEditorBundleRequesthost callback while preserving legacy schema/plugin callbacksVerification
git diff --check HEAD~2..HEADnpx tsc --noEmitnpm test(44 files / 4107 tests)npm run buildnpm run lintcurrently blocked by repo ESLint 9 config migration: missingeslint.config.(js|mjs|cjs)Review
Depends on Workflow PR #501, merged as
00dce7ba96af43ca3d5a125f8b223d89fb0c49a2.