@tai42/studio-sdk 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +15 -0
- package/README.md +318 -0
- package/SECURITY.md +51 -0
- package/dist/components/badge.d.ts +13 -0
- package/dist/components/badge.d.ts.map +1 -0
- package/dist/components/badge.js +14 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/checkbox.d.ts +24 -0
- package/dist/components/checkbox.d.ts.map +1 -0
- package/dist/components/checkbox.js +31 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/code-block.d.ts +7 -0
- package/dist/components/code-block.d.ts.map +1 -0
- package/dist/components/code-block.js +23 -0
- package/dist/components/code-block.js.map +1 -0
- package/dist/components/completion-input.d.ts +31 -0
- package/dist/components/completion-input.d.ts.map +1 -0
- package/dist/components/completion-input.js +61 -0
- package/dist/components/completion-input.js.map +1 -0
- package/dist/components/components.css +2212 -0
- package/dist/components/confirm-dialog.d.ts +40 -0
- package/dist/components/confirm-dialog.d.ts.map +1 -0
- package/dist/components/confirm-dialog.js +11 -0
- package/dist/components/confirm-dialog.js.map +1 -0
- package/dist/components/control-styles.d.ts +12 -0
- package/dist/components/control-styles.d.ts.map +1 -0
- package/dist/components/control-styles.js +14 -0
- package/dist/components/control-styles.js.map +1 -0
- package/dist/components/copy-field.d.ts +8 -0
- package/dist/components/copy-field.d.ts.map +1 -0
- package/dist/components/copy-field.js +106 -0
- package/dist/components/copy-field.js.map +1 -0
- package/dist/components/dialog.d.ts +21 -0
- package/dist/components/dialog.d.ts.map +1 -0
- package/dist/components/dialog.js +25 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/drawer.d.ts +22 -0
- package/dist/components/drawer.d.ts.map +1 -0
- package/dist/components/drawer.js +32 -0
- package/dist/components/drawer.js.map +1 -0
- package/dist/components/error-boundary.d.ts +33 -0
- package/dist/components/error-boundary.d.ts.map +1 -0
- package/dist/components/error-boundary.js +36 -0
- package/dist/components/error-boundary.js.map +1 -0
- package/dist/components/extension-combo-builder.d.ts +70 -0
- package/dist/components/extension-combo-builder.d.ts.map +1 -0
- package/dist/components/extension-combo-builder.js +154 -0
- package/dist/components/extension-combo-builder.js.map +1 -0
- package/dist/components/extension-grouping.d.ts +65 -0
- package/dist/components/extension-grouping.d.ts.map +1 -0
- package/dist/components/extension-grouping.js +78 -0
- package/dist/components/extension-grouping.js.map +1 -0
- package/dist/components/extension-picker.d.ts +35 -0
- package/dist/components/extension-picker.d.ts.map +1 -0
- package/dist/components/extension-picker.js +31 -0
- package/dist/components/extension-picker.js.map +1 -0
- package/dist/components/external-link.d.ts +19 -0
- package/dist/components/external-link.d.ts.map +1 -0
- package/dist/components/external-link.js +12 -0
- package/dist/components/external-link.js.map +1 -0
- package/dist/components/field.d.ts +64 -0
- package/dist/components/field.d.ts.map +1 -0
- package/dist/components/field.js +56 -0
- package/dist/components/field.js.map +1 -0
- package/dist/components/fleet-report.d.ts +39 -0
- package/dist/components/fleet-report.d.ts.map +1 -0
- package/dist/components/fleet-report.js +50 -0
- package/dist/components/fleet-report.js.map +1 -0
- package/dist/components/fonts.css +22 -0
- package/dist/components/icons.d.ts +142 -0
- package/dist/components/icons.d.ts.map +1 -0
- package/dist/components/icons.js +139 -0
- package/dist/components/icons.js.map +1 -0
- package/dist/components/inputs.d.ts +52 -0
- package/dist/components/inputs.d.ts.map +1 -0
- package/dist/components/inputs.js +35 -0
- package/dist/components/inputs.js.map +1 -0
- package/dist/components/json-diff.d.ts +40 -0
- package/dist/components/json-diff.d.ts.map +1 -0
- package/dist/components/json-diff.js +119 -0
- package/dist/components/json-diff.js.map +1 -0
- package/dist/components/json-tree.d.ts +8 -0
- package/dist/components/json-tree.d.ts.map +1 -0
- package/dist/components/json-tree.js +70 -0
- package/dist/components/json-tree.js.map +1 -0
- package/dist/components/modal-focus.d.ts +15 -0
- package/dist/components/modal-focus.d.ts.map +1 -0
- package/dist/components/modal-focus.js +136 -0
- package/dist/components/modal-focus.js.map +1 -0
- package/dist/components/page-header.d.ts +56 -0
- package/dist/components/page-header.d.ts.map +1 -0
- package/dist/components/page-header.js +24 -0
- package/dist/components/page-header.js.map +1 -0
- package/dist/components/primitives.d.ts +186 -0
- package/dist/components/primitives.d.ts.map +1 -0
- package/dist/components/primitives.js +204 -0
- package/dist/components/primitives.js.map +1 -0
- package/dist/components/progress-bar.d.ts +29 -0
- package/dist/components/progress-bar.d.ts.map +1 -0
- package/dist/components/progress-bar.js +48 -0
- package/dist/components/progress-bar.js.map +1 -0
- package/dist/components/radio-group.d.ts +37 -0
- package/dist/components/radio-group.d.ts.map +1 -0
- package/dist/components/radio-group.js +56 -0
- package/dist/components/radio-group.js.map +1 -0
- package/dist/components/reveal-input.d.ts +13 -0
- package/dist/components/reveal-input.d.ts.map +1 -0
- package/dist/components/reveal-input.js +31 -0
- package/dist/components/reveal-input.js.map +1 -0
- package/dist/components/scroll-region.d.ts +85 -0
- package/dist/components/scroll-region.d.ts.map +1 -0
- package/dist/components/scroll-region.js +574 -0
- package/dist/components/scroll-region.js.map +1 -0
- package/dist/components/select.d.ts +53 -0
- package/dist/components/select.d.ts.map +1 -0
- package/dist/components/select.js +33 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/table.d.ts +59 -0
- package/dist/components/table.d.ts.map +1 -0
- package/dist/components/table.js +20 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/tabs.d.ts +15 -0
- package/dist/components/tabs.d.ts.map +1 -0
- package/dist/components/tabs.js +13 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/tags.d.ts +46 -0
- package/dist/components/tags.d.ts.map +1 -0
- package/dist/components/tags.js +68 -0
- package/dist/components/tags.js.map +1 -0
- package/dist/components/tokens.css +392 -0
- package/dist/components/tokens.d.ts +15 -0
- package/dist/components/tokens.d.ts.map +1 -0
- package/dist/components/tokens.js +101 -0
- package/dist/components/tokens.js.map +1 -0
- package/dist/components/tool-picker.d.ts +24 -0
- package/dist/components/tool-picker.d.ts.map +1 -0
- package/dist/components/tool-picker.js +97 -0
- package/dist/components/tool-picker.js.map +1 -0
- package/dist/components/tooltip.d.ts +17 -0
- package/dist/components/tooltip.d.ts.map +1 -0
- package/dist/components/tooltip.js +18 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/version-history-panel.d.ts +71 -0
- package/dist/components/version-history-panel.d.ts.map +1 -0
- package/dist/components/version-history-panel.js +148 -0
- package/dist/components/version-history-panel.js.map +1 -0
- package/dist/download.d.ts +7 -0
- package/dist/download.d.ts.map +1 -0
- package/dist/download.js +18 -0
- package/dist/download.js.map +1 -0
- package/dist/element-slot.d.ts +4 -0
- package/dist/element-slot.d.ts.map +1 -0
- package/dist/element-slot.js +20 -0
- package/dist/element-slot.js.map +1 -0
- package/dist/elicitation/ElicitationForm.d.ts +34 -0
- package/dist/elicitation/ElicitationForm.d.ts.map +1 -0
- package/dist/elicitation/ElicitationForm.js +24 -0
- package/dist/elicitation/ElicitationForm.js.map +1 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +15 -0
- package/dist/errors.js.map +1 -0
- package/dist/extension-combos.d.ts +13 -0
- package/dist/extension-combos.d.ts.map +1 -0
- package/dist/extension-combos.js +9 -0
- package/dist/extension-combos.js.map +1 -0
- package/dist/hooks/useApi.d.ts +1222 -0
- package/dist/hooks/useApi.d.ts.map +1 -0
- package/dist/hooks/useApi.js +22 -0
- package/dist/hooks/useApi.js.map +1 -0
- package/dist/hooks/useAuth.d.ts +13 -0
- package/dist/hooks/useAuth.d.ts.map +1 -0
- package/dist/hooks/useAuth.js +53 -0
- package/dist/hooks/useAuth.js.map +1 -0
- package/dist/hooks/useBreakpoint.d.ts +10 -0
- package/dist/hooks/useBreakpoint.d.ts.map +1 -0
- package/dist/hooks/useBreakpoint.js +66 -0
- package/dist/hooks/useBreakpoint.js.map +1 -0
- package/dist/hooks/useCapabilities.d.ts +88 -0
- package/dist/hooks/useCapabilities.d.ts.map +1 -0
- package/dist/hooks/useCapabilities.js +203 -0
- package/dist/hooks/useCapabilities.js.map +1 -0
- package/dist/hooks/useSse.d.ts +13 -0
- package/dist/hooks/useSse.d.ts.map +1 -0
- package/dist/hooks/useSse.js +298 -0
- package/dist/hooks/useSse.js.map +1 -0
- package/dist/hooks/useTheme.d.ts +20 -0
- package/dist/hooks/useTheme.d.ts.map +1 -0
- package/dist/hooks/useTheme.js +97 -0
- package/dist/hooks/useTheme.js.map +1 -0
- package/dist/hooks/useUnauthorized.d.ts +3 -0
- package/dist/hooks/useUnauthorized.d.ts.map +1 -0
- package/dist/hooks/useUnauthorized.js +18 -0
- package/dist/hooks/useUnauthorized.js.map +1 -0
- package/dist/host.d.ts +11 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +10 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +118 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/navigation/context.d.ts +25 -0
- package/dist/navigation/context.d.ts.map +1 -0
- package/dist/navigation/context.js +45 -0
- package/dist/navigation/context.js.map +1 -0
- package/dist/navigation/index.d.ts +4 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +2 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/navigation/types.d.ts +97 -0
- package/dist/navigation/types.d.ts.map +1 -0
- package/dist/navigation/types.js +16 -0
- package/dist/navigation/types.js.map +1 -0
- package/dist/plugin/host-state.d.ts +45 -0
- package/dist/plugin/host-state.d.ts.map +1 -0
- package/dist/plugin/host-state.js +62 -0
- package/dist/plugin/host-state.js.map +1 -0
- package/dist/plugin/registry.d.ts +35 -0
- package/dist/plugin/registry.d.ts.map +1 -0
- package/dist/plugin/registry.js +129 -0
- package/dist/plugin/registry.js.map +1 -0
- package/dist/plugin/types.d.ts +165 -0
- package/dist/plugin/types.d.ts.map +1 -0
- package/dist/plugin/types.js +2 -0
- package/dist/plugin/types.js.map +1 -0
- package/dist/plugin/version.d.ts +34 -0
- package/dist/plugin/version.d.ts.map +1 -0
- package/dist/plugin/version.js +37 -0
- package/dist/plugin/version.js.map +1 -0
- package/dist/query-keys.d.ts +31 -0
- package/dist/query-keys.d.ts.map +1 -0
- package/dist/query-keys.js +31 -0
- package/dist/query-keys.js.map +1 -0
- package/dist/schema-editor/SchemaEditor.d.ts +43 -0
- package/dist/schema-editor/SchemaEditor.d.ts.map +1 -0
- package/dist/schema-editor/SchemaEditor.js +106 -0
- package/dist/schema-editor/SchemaEditor.js.map +1 -0
- package/dist/schema-editor/index.d.ts +10 -0
- package/dist/schema-editor/index.d.ts.map +1 -0
- package/dist/schema-editor/index.js +8 -0
- package/dist/schema-editor/index.js.map +1 -0
- package/dist/schema-editor/lint.d.ts +37 -0
- package/dist/schema-editor/lint.d.ts.map +1 -0
- package/dist/schema-editor/lint.js +49 -0
- package/dist/schema-editor/lint.js.map +1 -0
- package/dist/schema-form/SchemaForm.d.ts +70 -0
- package/dist/schema-form/SchemaForm.d.ts.map +1 -0
- package/dist/schema-form/SchemaForm.js +13 -0
- package/dist/schema-form/SchemaForm.js.map +1 -0
- package/dist/schema-form/array-field.d.ts +20 -0
- package/dist/schema-form/array-field.d.ts.map +1 -0
- package/dist/schema-form/array-field.js +39 -0
- package/dist/schema-form/array-field.js.map +1 -0
- package/dist/schema-form/classify.d.ts +87 -0
- package/dist/schema-form/classify.d.ts.map +1 -0
- package/dist/schema-form/classify.js +199 -0
- package/dist/schema-form/classify.js.map +1 -0
- package/dist/schema-form/context.d.ts +4 -0
- package/dist/schema-form/context.d.ts.map +1 -0
- package/dist/schema-form/context.js +14 -0
- package/dist/schema-form/context.js.map +1 -0
- package/dist/schema-form/default-value.d.ts +8 -0
- package/dist/schema-form/default-value.d.ts.map +1 -0
- package/dist/schema-form/default-value.js +64 -0
- package/dist/schema-form/default-value.js.map +1 -0
- package/dist/schema-form/enum-field.d.ts +19 -0
- package/dist/schema-form/enum-field.d.ts.map +1 -0
- package/dist/schema-form/enum-field.js +26 -0
- package/dist/schema-form/enum-field.js.map +1 -0
- package/dist/schema-form/field-group.d.ts +9 -0
- package/dist/schema-form/field-group.d.ts.map +1 -0
- package/dist/schema-form/field-group.js +32 -0
- package/dist/schema-form/field-group.js.map +1 -0
- package/dist/schema-form/field-node.d.ts +24 -0
- package/dist/schema-form/field-node.d.ts.map +1 -0
- package/dist/schema-form/field-node.js +51 -0
- package/dist/schema-form/field-node.js.map +1 -0
- package/dist/schema-form/index.d.ts +13 -0
- package/dist/schema-form/index.d.ts.map +1 -0
- package/dist/schema-form/index.js +11 -0
- package/dist/schema-form/index.js.map +1 -0
- package/dist/schema-form/media-field.d.ts +24 -0
- package/dist/schema-form/media-field.d.ts.map +1 -0
- package/dist/schema-form/media-field.js +169 -0
- package/dist/schema-form/media-field.js.map +1 -0
- package/dist/schema-form/media.d.ts +40 -0
- package/dist/schema-form/media.d.ts.map +1 -0
- package/dist/schema-form/media.js +65 -0
- package/dist/schema-form/media.js.map +1 -0
- package/dist/schema-form/object-fields.d.ts +20 -0
- package/dist/schema-form/object-fields.d.ts.map +1 -0
- package/dist/schema-form/object-fields.js +24 -0
- package/dist/schema-form/object-fields.js.map +1 -0
- package/dist/schema-form/resolve.d.ts +41 -0
- package/dist/schema-form/resolve.d.ts.map +1 -0
- package/dist/schema-form/resolve.js +102 -0
- package/dist/schema-form/resolve.js.map +1 -0
- package/dist/schema-form/string-field.d.ts +20 -0
- package/dist/schema-form/string-field.d.ts.map +1 -0
- package/dist/schema-form/string-field.js +68 -0
- package/dist/schema-form/string-field.js.map +1 -0
- package/dist/schema-form/styles.d.ts +18 -0
- package/dist/schema-form/styles.d.ts.map +1 -0
- package/dist/schema-form/styles.js +18 -0
- package/dist/schema-form/styles.js.map +1 -0
- package/dist/schema-form/types.d.ts +67 -0
- package/dist/schema-form/types.d.ts.map +1 -0
- package/dist/schema-form/types.js +10 -0
- package/dist/schema-form/types.js.map +1 -0
- package/dist/schema-form/union-field.d.ts +24 -0
- package/dist/schema-form/union-field.d.ts.map +1 -0
- package/dist/schema-form/union-field.js +55 -0
- package/dist/schema-form/union-field.js.map +1 -0
- package/dist/schema-form/union.d.ts +4 -0
- package/dist/schema-form/union.d.ts.map +1 -0
- package/dist/schema-form/union.js +68 -0
- package/dist/schema-form/union.js.map +1 -0
- package/dist/schema-form/unsupported-notice.d.ts +18 -0
- package/dist/schema-form/unsupported-notice.d.ts.map +1 -0
- package/dist/schema-form/unsupported-notice.js +8 -0
- package/dist/schema-form/unsupported-notice.js.map +1 -0
- package/dist/schema-form/validate.d.ts +18 -0
- package/dist/schema-form/validate.d.ts.map +1 -0
- package/dist/schema-form/validate.js +162 -0
- package/dist/schema-form/validate.js.map +1 -0
- package/dist/structured-output/StructuredOutput.d.ts +27 -0
- package/dist/structured-output/StructuredOutput.d.ts.map +1 -0
- package/dist/structured-output/StructuredOutput.js +41 -0
- package/dist/structured-output/StructuredOutput.js.map +1 -0
- package/dist/testing.d.ts +80 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +207 -0
- package/dist/testing.js.map +1 -0
- package/package.json +101 -0
- package/src/components/badge.tsx +31 -0
- package/src/components/checkbox.tsx +93 -0
- package/src/components/code-block.tsx +37 -0
- package/src/components/completion-input.tsx +137 -0
- package/src/components/components.css +2212 -0
- package/src/components/confirm-dialog.tsx +77 -0
- package/src/components/control-styles.ts +14 -0
- package/src/components/copy-field.tsx +178 -0
- package/src/components/dialog.tsx +76 -0
- package/src/components/drawer.tsx +83 -0
- package/src/components/error-boundary.tsx +56 -0
- package/src/components/extension-combo-builder.tsx +305 -0
- package/src/components/extension-grouping.ts +116 -0
- package/src/components/extension-picker.tsx +97 -0
- package/src/components/external-link.tsx +40 -0
- package/src/components/field.tsx +169 -0
- package/src/components/fleet-report.tsx +136 -0
- package/src/components/fonts.css +22 -0
- package/src/components/icons.tsx +504 -0
- package/src/components/inputs.tsx +125 -0
- package/src/components/json-diff.tsx +192 -0
- package/src/components/json-tree.tsx +129 -0
- package/src/components/modal-focus.ts +150 -0
- package/src/components/page-header.tsx +107 -0
- package/src/components/primitives.tsx +489 -0
- package/src/components/progress-bar.tsx +100 -0
- package/src/components/radio-group.tsx +160 -0
- package/src/components/reveal-input.tsx +87 -0
- package/src/components/scroll-region.tsx +703 -0
- package/src/components/select.tsx +149 -0
- package/src/components/table.tsx +94 -0
- package/src/components/tabs.tsx +51 -0
- package/src/components/tags.tsx +137 -0
- package/src/components/tokens.css +392 -0
- package/src/components/tokens.ts +102 -0
- package/src/components/tool-picker.tsx +175 -0
- package/src/components/tooltip.tsx +46 -0
- package/src/components/version-history-panel.tsx +407 -0
- package/src/css.d.ts +2 -0
- package/src/download.ts +17 -0
- package/src/element-slot.ts +22 -0
- package/src/elicitation/ElicitationForm.tsx +87 -0
- package/src/errors.ts +12 -0
- package/src/extension-combos.ts +18 -0
- package/src/hooks/useApi.ts +27 -0
- package/src/hooks/useAuth.ts +67 -0
- package/src/hooks/useBreakpoint.ts +78 -0
- package/src/hooks/useCapabilities.ts +242 -0
- package/src/hooks/useSse.ts +314 -0
- package/src/hooks/useTheme.ts +133 -0
- package/src/hooks/useUnauthorized.ts +20 -0
- package/src/host.ts +15 -0
- package/src/index.ts +267 -0
- package/src/navigation/context.tsx +90 -0
- package/src/navigation/index.ts +9 -0
- package/src/navigation/types.ts +90 -0
- package/src/plugin/host-state.ts +93 -0
- package/src/plugin/registry.ts +174 -0
- package/src/plugin/types.ts +178 -0
- package/src/plugin/version.ts +44 -0
- package/src/query-keys.ts +34 -0
- package/src/schema-editor/SchemaEditor.tsx +186 -0
- package/src/schema-editor/index.ts +9 -0
- package/src/schema-editor/lint.ts +70 -0
- package/src/schema-form/SchemaForm.tsx +107 -0
- package/src/schema-form/array-field.tsx +110 -0
- package/src/schema-form/classify.ts +302 -0
- package/src/schema-form/context.ts +17 -0
- package/src/schema-form/default-value.ts +65 -0
- package/src/schema-form/enum-field.tsx +65 -0
- package/src/schema-form/field-group.tsx +71 -0
- package/src/schema-form/field-node.tsx +161 -0
- package/src/schema-form/index.ts +12 -0
- package/src/schema-form/media-field.tsx +281 -0
- package/src/schema-form/media.ts +69 -0
- package/src/schema-form/object-fields.tsx +74 -0
- package/src/schema-form/resolve.ts +114 -0
- package/src/schema-form/string-field.tsx +161 -0
- package/src/schema-form/styles.ts +20 -0
- package/src/schema-form/types.ts +71 -0
- package/src/schema-form/union-field.tsx +122 -0
- package/src/schema-form/union.ts +78 -0
- package/src/schema-form/unsupported-notice.tsx +39 -0
- package/src/schema-form/validate.ts +183 -0
- package/src/structured-output/StructuredOutput.tsx +81 -0
- package/src/testing.ts +235 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tai42/studio-sdk — the PLUGIN SURFACE: everything a Studio plugin (and every
|
|
3
|
+
* feature) is allowed to touch.
|
|
4
|
+
*
|
|
5
|
+
* 1. The STUDIO-PLUGIN API a plugin implements: the `PluginContext` its `register`
|
|
6
|
+
* entry receives, the contribution types, and the compatibility gate.
|
|
7
|
+
* 2. The design system + hooks every feature (and every plugin) builds on.
|
|
8
|
+
*
|
|
9
|
+
* The host registry (`loadPlugin`/`getContributions`) is DELIBERATELY absent here
|
|
10
|
+
* so the served plugin asset cannot forge, wipe, or enumerate the registry; it is
|
|
11
|
+
* exported only from `@tai42/studio-sdk/host`, which the host bundle imports. See
|
|
12
|
+
* SECURITY.md for the trust boundary.
|
|
13
|
+
*
|
|
14
|
+
* The three shared modules (react, react-dom, @tai42/studio-sdk) are singletons
|
|
15
|
+
* across the plugin boundary; this package imports nothing internal at runtime
|
|
16
|
+
* (the `ApiClient`/`Interaction` types are type-only imports).
|
|
17
|
+
*/
|
|
18
|
+
// The design system, delivered by the BARREL so each host app loads it once and a
|
|
19
|
+
// plugin never ships its own copy. These are bare side-effect imports, so they
|
|
20
|
+
// survive bundling only while this module is itself listed in the package's
|
|
21
|
+
// `sideEffects` (both `./dist/index.js` and `./src/index.ts` — `files` ships src
|
|
22
|
+
// too). Without that entry webpack and Vite treat the barrel as side-effect-free
|
|
23
|
+
// and drop all three, and a published consumer gets zero CSS; `sideEffects` is
|
|
24
|
+
// kept honest against these lines by `package-side-effects.test.ts`.
|
|
25
|
+
import './components/tokens.css';
|
|
26
|
+
import './components/fonts.css';
|
|
27
|
+
import './components/components.css';
|
|
28
|
+
|
|
29
|
+
// -- Plugin API --------------------------------------------------------------
|
|
30
|
+
export type {
|
|
31
|
+
PluginContext,
|
|
32
|
+
PluginEntry,
|
|
33
|
+
ToolPanelProps,
|
|
34
|
+
PluginPageProps,
|
|
35
|
+
SettingsTabProps,
|
|
36
|
+
ToolPanelContribution,
|
|
37
|
+
PageContribution,
|
|
38
|
+
RegisteredPage,
|
|
39
|
+
SettingsTabContribution,
|
|
40
|
+
RegisteredSettingsTab,
|
|
41
|
+
NavEntryContribution,
|
|
42
|
+
RegisteredNavEntry,
|
|
43
|
+
PluginContributions,
|
|
44
|
+
RequiredCapabilities,
|
|
45
|
+
} from './plugin/types';
|
|
46
|
+
export { STUDIO_PLUGIN_API_VERSION, checkPluginApiVersion } from './plugin/version';
|
|
47
|
+
export type { VersionGateResult } from './plugin/version';
|
|
48
|
+
|
|
49
|
+
// -- Hooks -------------------------------------------------------------------
|
|
50
|
+
export { ApiProvider, useApi } from './hooks/useApi';
|
|
51
|
+
export type { ApiClient } from './hooks/useApi';
|
|
52
|
+
export { UnauthorizedProvider, useOnUnauthorized } from './hooks/useUnauthorized';
|
|
53
|
+
export { AuthProvider, useAuth } from './hooks/useAuth';
|
|
54
|
+
export type { AuthState } from './hooks/useAuth';
|
|
55
|
+
export {
|
|
56
|
+
CapabilityProvider,
|
|
57
|
+
useCapabilities,
|
|
58
|
+
useCanWrite,
|
|
59
|
+
isFullProjection,
|
|
60
|
+
coversAnyRoute,
|
|
61
|
+
coversRoute,
|
|
62
|
+
coversWrite,
|
|
63
|
+
} from './hooks/useCapabilities';
|
|
64
|
+
export type { CapabilityState, CapabilityContextValue } from './hooks/useCapabilities';
|
|
65
|
+
export { ThemeProvider, useTheme } from './hooks/useTheme';
|
|
66
|
+
export type { Theme, ThemePreference, ThemeState } from './hooks/useTheme';
|
|
67
|
+
export { useBreakpoint } from './hooks/useBreakpoint';
|
|
68
|
+
export type { Breakpoint, BreakpointState } from './hooks/useBreakpoint';
|
|
69
|
+
export { useInteractionsStream } from './hooks/useSse';
|
|
70
|
+
export type { InteractionsStreamState, StreamInteraction } from './hooks/useSse';
|
|
71
|
+
|
|
72
|
+
// -- Navigation (shell ⇄ feature route-token contract) -----------------------
|
|
73
|
+
export { NavigationProvider, AppLink, useAppNavigate, useResolvePath } from './navigation';
|
|
74
|
+
export type {
|
|
75
|
+
AppLinkProps,
|
|
76
|
+
RouteToken,
|
|
77
|
+
RouteSearch,
|
|
78
|
+
RouteSearchByToken,
|
|
79
|
+
PageProps,
|
|
80
|
+
NavigationContextValue,
|
|
81
|
+
} from './navigation';
|
|
82
|
+
|
|
83
|
+
// -- Utilities ---------------------------------------------------------------
|
|
84
|
+
export { errorMessage } from './errors';
|
|
85
|
+
export { downloadBlob } from './download';
|
|
86
|
+
|
|
87
|
+
// -- Cross-feature query keys ------------------------------------------------
|
|
88
|
+
export { toolsListKey, extensionsQueryKey, subMcpKey, tokensPayloadKey } from './query-keys';
|
|
89
|
+
|
|
90
|
+
// -- Extension-combo editing helpers -----------------------------------------
|
|
91
|
+
export { comboElementNames, extensionElementName } from './extension-combos';
|
|
92
|
+
|
|
93
|
+
// -- Design system -----------------------------------------------------------
|
|
94
|
+
export { Button, Card, Skeleton, EmptyState, ErrorState, Spinner } from './components/primitives';
|
|
95
|
+
export type {
|
|
96
|
+
ButtonProps,
|
|
97
|
+
LinkButtonProps,
|
|
98
|
+
ButtonVariant,
|
|
99
|
+
CardProps,
|
|
100
|
+
SkeletonProps,
|
|
101
|
+
EmptyStateProps,
|
|
102
|
+
ErrorStateProps,
|
|
103
|
+
SpinnerProps,
|
|
104
|
+
} from './components/primitives';
|
|
105
|
+
export { PageHeader, Page, Stack } from './components/page-header';
|
|
106
|
+
export type { PageHeaderProps, PageLayoutProps, StackProps } from './components/page-header';
|
|
107
|
+
export { ErrorBoundary } from './components/error-boundary';
|
|
108
|
+
export type { ErrorBoundaryProps } from './components/error-boundary';
|
|
109
|
+
export { Field, useFieldControl } from './components/field';
|
|
110
|
+
export type { FieldProps, FieldControlProps } from './components/field';
|
|
111
|
+
export { TextInput, Textarea, NumberInput } from './components/inputs';
|
|
112
|
+
export type { TextInputProps, TextareaProps, NumberInputProps } from './components/inputs';
|
|
113
|
+
export { Select } from './components/select';
|
|
114
|
+
export type {
|
|
115
|
+
SelectProps,
|
|
116
|
+
SelectGroupsProps,
|
|
117
|
+
SelectOption,
|
|
118
|
+
SelectGroup,
|
|
119
|
+
} from './components/select';
|
|
120
|
+
export { Checkbox } from './components/checkbox';
|
|
121
|
+
export type { CheckboxProps } from './components/checkbox';
|
|
122
|
+
export { RadioGroup } from './components/radio-group';
|
|
123
|
+
export type { RadioGroupProps, RadioOption } from './components/radio-group';
|
|
124
|
+
export { Badge } from './components/badge';
|
|
125
|
+
export type { BadgeProps } from './components/badge';
|
|
126
|
+
export { Tabs } from './components/tabs';
|
|
127
|
+
export type { TabsProps, TabItem } from './components/tabs';
|
|
128
|
+
export { Dialog } from './components/dialog';
|
|
129
|
+
export type { DialogProps } from './components/dialog';
|
|
130
|
+
export { ConfirmDialog } from './components/confirm-dialog';
|
|
131
|
+
export type { ConfirmDialogProps } from './components/confirm-dialog';
|
|
132
|
+
export { Drawer } from './components/drawer';
|
|
133
|
+
export type { DrawerProps } from './components/drawer';
|
|
134
|
+
export { Tooltip } from './components/tooltip';
|
|
135
|
+
export type { TooltipProps } from './components/tooltip';
|
|
136
|
+
export { Table, THead, TBody, TR, TH, TD } from './components/table';
|
|
137
|
+
export type {
|
|
138
|
+
TableProps,
|
|
139
|
+
TableSectionProps,
|
|
140
|
+
TableRowProps,
|
|
141
|
+
THProps,
|
|
142
|
+
TDProps,
|
|
143
|
+
NumericColumnProps,
|
|
144
|
+
} from './components/table';
|
|
145
|
+
export { ScrollRegion, useOverflowRegion, useProseScrollRegions } from './components/scroll-region';
|
|
146
|
+
export type {
|
|
147
|
+
ScrollRegionProps,
|
|
148
|
+
OverflowRegionAttributes,
|
|
149
|
+
ProseScrollLabels,
|
|
150
|
+
} from './components/scroll-region';
|
|
151
|
+
export { JsonTree } from './components/json-tree';
|
|
152
|
+
export type { JsonTreeProps } from './components/json-tree';
|
|
153
|
+
export { JsonDiff, diffJson } from './components/json-diff';
|
|
154
|
+
export type { JsonDiffProps, JsonDiffRow } from './components/json-diff';
|
|
155
|
+
export { TagChips, TagsInput } from './components/tags';
|
|
156
|
+
export type { TagChipsProps, TagsInputProps } from './components/tags';
|
|
157
|
+
export { CodeBlock } from './components/code-block';
|
|
158
|
+
export type { CodeBlockProps } from './components/code-block';
|
|
159
|
+
export { FleetReport } from './components/fleet-report';
|
|
160
|
+
export type { FleetReportProps } from './components/fleet-report';
|
|
161
|
+
export { ExternalLinkButton, isSafeHttpUrl } from './components/external-link';
|
|
162
|
+
// The URL half of the link-safety pair: `isSafeHttpUrl` answers yes/no, this one
|
|
163
|
+
// hands back the parsed URL, so a caller that needs the URL does not re-parse it.
|
|
164
|
+
export { safeHttpUrl } from './components/primitives';
|
|
165
|
+
export type { ExternalLinkButtonProps } from './components/external-link';
|
|
166
|
+
export { ToolPicker } from './components/tool-picker';
|
|
167
|
+
export type { ToolPickerProps } from './components/tool-picker';
|
|
168
|
+
export { ExtensionPicker } from './components/extension-picker';
|
|
169
|
+
export type { ExtensionPickerProps } from './components/extension-picker';
|
|
170
|
+
export { ExtensionComboBuilder } from './components/extension-combo-builder';
|
|
171
|
+
export type { ExtensionComboBuilderProps } from './components/extension-combo-builder';
|
|
172
|
+
export {
|
|
173
|
+
baseNameOf,
|
|
174
|
+
groupIntoFamilies,
|
|
175
|
+
groupByKind,
|
|
176
|
+
kindVariant,
|
|
177
|
+
NON_STACKABLE_KIND,
|
|
178
|
+
} from './components/extension-grouping';
|
|
179
|
+
export type { ExtensionFamily, ExtensionKindGroup } from './components/extension-grouping';
|
|
180
|
+
export { VersionHistoryPanel } from './components/version-history-panel';
|
|
181
|
+
export type {
|
|
182
|
+
VersionHistoryPanelProps,
|
|
183
|
+
VersionHistoryEntry,
|
|
184
|
+
} from './components/version-history-panel';
|
|
185
|
+
export { RevealInput } from './components/reveal-input';
|
|
186
|
+
export type { RevealInputProps } from './components/reveal-input';
|
|
187
|
+
export { CopyField } from './components/copy-field';
|
|
188
|
+
export type { CopyFieldProps } from './components/copy-field';
|
|
189
|
+
export { TOKEN_NAMES } from './components/tokens';
|
|
190
|
+
export type { TokenName } from './components/tokens';
|
|
191
|
+
|
|
192
|
+
// -- Iconography (the only sanctioned marks; Unicode glyphs are banned) -------
|
|
193
|
+
export {
|
|
194
|
+
NAV_ICONS,
|
|
195
|
+
DashboardIcon,
|
|
196
|
+
ToolsIcon,
|
|
197
|
+
AgentsIcon,
|
|
198
|
+
PresetsIcon,
|
|
199
|
+
ExtensionsIcon,
|
|
200
|
+
TemplatesIcon,
|
|
201
|
+
ConnectorsIcon,
|
|
202
|
+
HooksIcon,
|
|
203
|
+
StorageIcon,
|
|
204
|
+
SchedulingIcon,
|
|
205
|
+
InteractionsIcon,
|
|
206
|
+
NotificationsIcon,
|
|
207
|
+
MarketplaceIcon,
|
|
208
|
+
ManifestIcon,
|
|
209
|
+
SettingsIcon,
|
|
210
|
+
SystemIcon,
|
|
211
|
+
SearchIcon,
|
|
212
|
+
SignOutIcon,
|
|
213
|
+
MenuIcon,
|
|
214
|
+
CloseIcon,
|
|
215
|
+
FilterIcon,
|
|
216
|
+
ArrowLeftIcon,
|
|
217
|
+
ArrowUpIcon,
|
|
218
|
+
ArrowDownIcon,
|
|
219
|
+
ChevronDownIcon,
|
|
220
|
+
ChevronRightIcon,
|
|
221
|
+
CheckIcon,
|
|
222
|
+
MinusIcon,
|
|
223
|
+
CopyIcon,
|
|
224
|
+
ExternalLinkIcon,
|
|
225
|
+
EyeIcon,
|
|
226
|
+
EyeOffIcon,
|
|
227
|
+
SortAscIcon,
|
|
228
|
+
SortDescIcon,
|
|
229
|
+
SunIcon,
|
|
230
|
+
MoonIcon,
|
|
231
|
+
MonitorIcon,
|
|
232
|
+
CheckCircleIcon,
|
|
233
|
+
AlertTriangleIcon,
|
|
234
|
+
XCircleIcon,
|
|
235
|
+
PendingIcon,
|
|
236
|
+
} from './components/icons';
|
|
237
|
+
export type { IconProps, IconComponent } from './components/icons';
|
|
238
|
+
|
|
239
|
+
// -- Schema-driven forms -----------------------------------------------------
|
|
240
|
+
export {
|
|
241
|
+
SchemaForm,
|
|
242
|
+
defaultValueForSchema,
|
|
243
|
+
validateAgainstSchema,
|
|
244
|
+
resolveRef,
|
|
245
|
+
} from './schema-form';
|
|
246
|
+
export type {
|
|
247
|
+
SchemaFormProps,
|
|
248
|
+
CompletionProvider,
|
|
249
|
+
JsonSchema,
|
|
250
|
+
JsonSchemaType,
|
|
251
|
+
Discriminator,
|
|
252
|
+
SchemaFormErrors,
|
|
253
|
+
} from './schema-form';
|
|
254
|
+
|
|
255
|
+
// -- Schema-editor (validated JSON-Schema authoring control) -----------------
|
|
256
|
+
export { SchemaEditor, lintSchemaText } from './schema-editor';
|
|
257
|
+
export type { SchemaEditorProps, SchemaEditorChange, SchemaLintResult } from './schema-editor';
|
|
258
|
+
|
|
259
|
+
// -- MCP context widgets (elicitation / progress / completions / output) -----
|
|
260
|
+
export { ProgressBar } from './components/progress-bar';
|
|
261
|
+
export type { ProgressBarProps } from './components/progress-bar';
|
|
262
|
+
export { CompletionInput } from './components/completion-input';
|
|
263
|
+
export type { CompletionInputProps } from './components/completion-input';
|
|
264
|
+
export { ElicitationForm } from './elicitation/ElicitationForm';
|
|
265
|
+
export type { ElicitationFormProps } from './elicitation/ElicitationForm';
|
|
266
|
+
export { StructuredOutput } from './structured-output/StructuredOutput';
|
|
267
|
+
export type { StructuredOutputProps } from './structured-output/StructuredOutput';
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createContext,
|
|
3
|
+
createElement,
|
|
4
|
+
useCallback,
|
|
5
|
+
useContext,
|
|
6
|
+
type AriaAttributes,
|
|
7
|
+
type MouseEvent,
|
|
8
|
+
type ReactNode,
|
|
9
|
+
} from 'react';
|
|
10
|
+
|
|
11
|
+
import type { NavigationContextValue, RouteSearch, RouteToken } from './types';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Shell-provided navigation. The context has no default: a feature rendered
|
|
15
|
+
* outside the shell's {@link NavigationProvider} is a wiring bug, so
|
|
16
|
+
* {@link useNavigation} raises loudly rather than silently no-op'ing a
|
|
17
|
+
* transition.
|
|
18
|
+
*/
|
|
19
|
+
const NavigationContext = createContext<NavigationContextValue | null>(null);
|
|
20
|
+
|
|
21
|
+
export function NavigationProvider({
|
|
22
|
+
value,
|
|
23
|
+
children,
|
|
24
|
+
}: {
|
|
25
|
+
value: NavigationContextValue;
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
}): ReactNode {
|
|
28
|
+
return createElement(NavigationContext.Provider, { value }, children);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function useNavigation(): NavigationContextValue {
|
|
32
|
+
const ctx = useContext(NavigationContext);
|
|
33
|
+
if (ctx === null) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
'useNavigation must be used within a <NavigationProvider> (the shell provides it).',
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return ctx;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Imperative navigation to a shell route token with its typed search params. */
|
|
42
|
+
export function useAppNavigate(): NavigationContextValue['navigate'] {
|
|
43
|
+
return useNavigation().navigate;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Resolve a token + search to the href the shell would route to. */
|
|
47
|
+
export function useResolvePath(): NavigationContextValue['resolvePath'] {
|
|
48
|
+
return useNavigation().resolvePath;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface AppLinkProps<T extends RouteToken> {
|
|
52
|
+
to: T;
|
|
53
|
+
search?: RouteSearch<T>;
|
|
54
|
+
children: ReactNode;
|
|
55
|
+
className?: string;
|
|
56
|
+
'aria-label'?: string;
|
|
57
|
+
'aria-current'?: AriaAttributes['aria-current'];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A real anchor (so middle-click / open-in-new-tab keep working) that drives a
|
|
62
|
+
* client-side transition on plain left-click. Modified clicks (new tab/window,
|
|
63
|
+
* download) fall through to the browser's default handling.
|
|
64
|
+
*/
|
|
65
|
+
export function AppLink<T extends RouteToken>({
|
|
66
|
+
to,
|
|
67
|
+
search,
|
|
68
|
+
children,
|
|
69
|
+
className,
|
|
70
|
+
'aria-label': ariaLabel,
|
|
71
|
+
'aria-current': ariaCurrent,
|
|
72
|
+
}: AppLinkProps<T>): ReactNode {
|
|
73
|
+
const { navigate, resolvePath } = useNavigation();
|
|
74
|
+
const href = resolvePath(to, search);
|
|
75
|
+
const onClick = useCallback(
|
|
76
|
+
(event: MouseEvent<HTMLAnchorElement>) => {
|
|
77
|
+
if (event.defaultPrevented) return;
|
|
78
|
+
if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
|
|
79
|
+
return;
|
|
80
|
+
event.preventDefault();
|
|
81
|
+
navigate(to, search);
|
|
82
|
+
},
|
|
83
|
+
[navigate, to, search],
|
|
84
|
+
);
|
|
85
|
+
return createElement(
|
|
86
|
+
'a',
|
|
87
|
+
{ href, className, 'aria-label': ariaLabel, 'aria-current': ariaCurrent, onClick },
|
|
88
|
+
children,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shell ⇄ feature navigation contract.
|
|
3
|
+
*
|
|
4
|
+
* Routing is SHELL-owned: feature packages never see path strings and never
|
|
5
|
+
* define routes. They navigate through named ROUTE TOKENS — the keys of
|
|
6
|
+
* {@link RouteSearchByToken} — which the shell resolves to real paths. A token
|
|
7
|
+
* is an opaque, compile-time handle: renaming or removing one here is a type
|
|
8
|
+
* error at every call site, exactly the property free-form path strings lack.
|
|
9
|
+
*
|
|
10
|
+
* This contract lives in the SDK because it is the ONLY internal module a feature
|
|
11
|
+
* may import (a feature importing the shell is a boundary violation). The shell
|
|
12
|
+
* supplies the runtime resolution via {@link NavigationContextValue}; features
|
|
13
|
+
* consume it type-safely.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Every top-level route the shell owns, mapped to its typed search parameters.
|
|
18
|
+
* A route with no parameters maps to the empty object. Detail views are driven
|
|
19
|
+
* by a search parameter (e.g. the selected tool / connection), keeping the route
|
|
20
|
+
* map flat — one entry per feature surface, matching the shell route map.
|
|
21
|
+
*/
|
|
22
|
+
export interface RouteSearchByToken {
|
|
23
|
+
login: Record<string, never>;
|
|
24
|
+
tools: { tool?: string; tags?: string[] };
|
|
25
|
+
agents: Record<string, never>;
|
|
26
|
+
presets: { preset?: string };
|
|
27
|
+
extensions: Record<string, never>;
|
|
28
|
+
interactions: Record<string, never>;
|
|
29
|
+
notifications: Record<string, never>;
|
|
30
|
+
connectors: { connection?: string };
|
|
31
|
+
hooks: Record<string, never>;
|
|
32
|
+
templates: { template?: string };
|
|
33
|
+
storage: { filter?: string };
|
|
34
|
+
manifest: Record<string, never>;
|
|
35
|
+
settings: Record<string, never>;
|
|
36
|
+
system: Record<string, never>;
|
|
37
|
+
scheduling: Record<string, never>;
|
|
38
|
+
observability: {
|
|
39
|
+
tab?: 'dashboard' | 'tracing';
|
|
40
|
+
from?: string;
|
|
41
|
+
to?: string;
|
|
42
|
+
tags?: string[];
|
|
43
|
+
status?: 'error' | 'success';
|
|
44
|
+
minCost?: number;
|
|
45
|
+
maxCost?: number;
|
|
46
|
+
minTokens?: number;
|
|
47
|
+
maxTokens?: number;
|
|
48
|
+
minLatencyMs?: number;
|
|
49
|
+
maxLatencyMs?: number;
|
|
50
|
+
sort?: 'createdAt' | 'cost' | 'latencyMs' | 'totalTokens';
|
|
51
|
+
dir?: 'asc' | 'desc';
|
|
52
|
+
trace?: string;
|
|
53
|
+
};
|
|
54
|
+
marketplace: {
|
|
55
|
+
tab?: 'browse' | 'installed';
|
|
56
|
+
q?: string;
|
|
57
|
+
kind?: string;
|
|
58
|
+
category?: string;
|
|
59
|
+
tags?: string[];
|
|
60
|
+
sort?: 'downloads' | 'updated' | 'name' | 'relevance';
|
|
61
|
+
plugin?: string;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** An opaque, typed handle to a shell route. */
|
|
66
|
+
export type RouteToken = keyof RouteSearchByToken;
|
|
67
|
+
|
|
68
|
+
/** The search parameters a given route token accepts. */
|
|
69
|
+
export type RouteSearch<T extends RouteToken> = RouteSearchByToken[T];
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Props the shell passes to a feature's page component: the route's typed search
|
|
73
|
+
* parameters. Features type their exported page as `PageProps<'tools'>` and read
|
|
74
|
+
* `search` — they receive route state as data, never by importing the router.
|
|
75
|
+
*/
|
|
76
|
+
export interface PageProps<T extends RouteToken> {
|
|
77
|
+
search: RouteSearch<T>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The runtime navigation surface the shell provides through
|
|
82
|
+
* {@link NavigationProvider}. `navigate` performs a client-side transition;
|
|
83
|
+
* `resolvePath` produces the href a link should point at (so an AppLink is a real
|
|
84
|
+
* anchor — middle-click / open-in-new-tab work — while still driving a
|
|
85
|
+
* client-side transition on plain click).
|
|
86
|
+
*/
|
|
87
|
+
export interface NavigationContextValue {
|
|
88
|
+
navigate: <T extends RouteToken>(token: T, search?: RouteSearch<T>) => void;
|
|
89
|
+
resolvePath: <T extends RouteToken>(token: T, search?: RouteSearch<T>) => string;
|
|
90
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The plugin host-readiness store: a host-driven mirror of the plugin load pass's
|
|
3
|
+
* public state that feature pages subscribe to. The app shell's loader is the
|
|
4
|
+
* single driver — it calls {@link setPluginHostState} on every transition — and a
|
|
5
|
+
* feature page reads the current status plus the committed contributions through
|
|
6
|
+
* {@link usePluginContributions}, without importing the app shell (the dependency
|
|
7
|
+
* points the other way).
|
|
8
|
+
*
|
|
9
|
+
* This module reads the contribution registry ({@link getContributions}), so it is
|
|
10
|
+
* part of the HOST-ONLY surface (`@tai42/studio-sdk/host`), never the plugin surface:
|
|
11
|
+
* a served plugin bundle can neither drive this store nor enumerate the registry
|
|
12
|
+
* through it. See SECURITY.md for the trust boundary.
|
|
13
|
+
*/
|
|
14
|
+
import { useSyncExternalStore } from 'react';
|
|
15
|
+
|
|
16
|
+
import type { PluginContributions } from './types';
|
|
17
|
+
import { getContributions } from './registry';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The plugin load pass's public state, mirrored for feature pages to read. It is
|
|
21
|
+
* the shape the app shell's loader store already exposes: `status` gates when the
|
|
22
|
+
* contributions are complete, and the error fields carry the loud failures.
|
|
23
|
+
*/
|
|
24
|
+
export interface PluginLoaderState {
|
|
25
|
+
/** `idle` before the first pass, `loading` while it runs, `ready` once done. */
|
|
26
|
+
readonly status: 'idle' | 'loading' | 'ready';
|
|
27
|
+
/** Names of plugins whose bundle imported and registered successfully. */
|
|
28
|
+
readonly loaded: readonly string[];
|
|
29
|
+
/** Plugin name → loud error message (version mismatch / load failure). */
|
|
30
|
+
readonly errors: Readonly<Record<string, string>>;
|
|
31
|
+
/** A registry-listing failure that is NOT a 401 (surfaced loudly, never hidden). */
|
|
32
|
+
readonly registryError: string | null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const INITIAL_HOST_STATE: PluginLoaderState = {
|
|
36
|
+
status: 'idle',
|
|
37
|
+
loaded: [],
|
|
38
|
+
errors: {},
|
|
39
|
+
registryError: null,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
let hostState: PluginLoaderState = INITIAL_HOST_STATE;
|
|
43
|
+
const listeners = new Set<() => void>();
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The host loader pushes every load-pass transition here (it stays the single
|
|
47
|
+
* driver); every subscriber is notified so feature pages re-render off it.
|
|
48
|
+
*/
|
|
49
|
+
export function setPluginHostState(state: PluginLoaderState): void {
|
|
50
|
+
hostState = state;
|
|
51
|
+
for (const listener of listeners) listener();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** The current mirrored host state — the snapshot {@link usePluginContributions} reads. */
|
|
55
|
+
export function getPluginHostState(): PluginLoaderState {
|
|
56
|
+
return hostState;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Subscribe to host-state transitions; returns the unsubscribe function
|
|
61
|
+
* `useSyncExternalStore` requires so a subscriber detaches on unmount.
|
|
62
|
+
*/
|
|
63
|
+
export function subscribePluginHost(listener: () => void): () => void {
|
|
64
|
+
listeners.add(listener);
|
|
65
|
+
return () => {
|
|
66
|
+
listeners.delete(listener);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Tests reset the module-level host state between cases. */
|
|
71
|
+
export function __resetPluginHostState(): void {
|
|
72
|
+
hostState = INITIAL_HOST_STATE;
|
|
73
|
+
listeners.clear();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** What {@link usePluginContributions} returns: the load status and the registry. */
|
|
77
|
+
export interface PluginContributionsSnapshot {
|
|
78
|
+
/** The load pass's status; contributions are only complete once it is `'ready'`. */
|
|
79
|
+
readonly status: PluginLoaderState['status'];
|
|
80
|
+
/** The committed contributions, meaningful only when `status === 'ready'`. */
|
|
81
|
+
readonly contributions: PluginContributions;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Subscribe to the plugin host state and read the committed contributions. The
|
|
86
|
+
* status drives re-renders as the load pass advances; `contributions` is only
|
|
87
|
+
* meaningful once `status === 'ready'` (before then the pass has committed
|
|
88
|
+
* nothing, so callers render their non-plugin content).
|
|
89
|
+
*/
|
|
90
|
+
export function usePluginContributions(): PluginContributionsSnapshot {
|
|
91
|
+
const status = useSyncExternalStore(subscribePluginHost, () => getPluginHostState().status);
|
|
92
|
+
return { status, contributions: getContributions() };
|
|
93
|
+
}
|