From 430e5d94ac192fb8f5dfb23181b92748e874e3cf Mon Sep 17 00:00:00 2001 From: Eliott C Date: Mon, 20 Nov 2023 21:34:19 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=89=20@huggingface/widgets=20(#297)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.cjs | 18 +- .github/workflows/lint-and-test.yml | 2 +- .github/workflows/widgets-publish.yml | 51 + .prettierrc | 4 +- package.json | 14 +- packages/agents/package.json | 4 +- packages/doc-internal/package.json | 2 +- packages/hub/package.json | 4 +- packages/inference/package.json | 5 +- packages/languages/package.json | 4 +- packages/tasks/package.json | 9 +- packages/tasks/src/index.ts | 11 +- packages/tasks/src/pipelines.ts | 11 + packages/widgets/.eslintignore | 14 + packages/widgets/.gitignore | 11 + packages/widgets/.prettierignore | 14 + packages/widgets/README.md | 18 + packages/widgets/package.json | 59 + packages/widgets/pnpm-lock.yaml | 1973 +++++++++++++++++ packages/widgets/postcss.config.js | 6 + packages/widgets/src/app.d.ts | 12 + packages/widgets/src/app.html | 12 + .../DemoThemeSwitcher.svelte | 60 + .../Icons/IconAudioClassification.svelte | 21 + .../components/Icons/IconAudioToAudio.svelte | 23 + .../IconAutomaticSpeechRecognition.svelte | 23 + .../lib/components/Icons/IconAzureML.svelte | 40 + .../lib/components/Icons/IconCaretDown.svelte | 19 + .../components/Icons/IconCaretDownV2.svelte | 11 + .../src/lib/components/Icons/IconCode.svelte | 21 + .../Icons/IconConversational.svelte | 23 + .../src/lib/components/Icons/IconCross.svelte | 21 + .../Icons/IconDepthEstimation.svelte | 10 + .../IconDocumentQuestionAnswering.svelte | 13 + .../Icons/IconFeatureExtraction.svelte | 21 + .../src/lib/components/Icons/IconFile.svelte | 21 + .../lib/components/Icons/IconFillMask.svelte | 27 + .../lib/components/Icons/IconGraphML.svelte | 23 + .../Icons/IconImageClassification.svelte | 23 + .../Icons/IconImageSegmentation.svelte | 24 + .../components/Icons/IconImageToImage.svelte | 25 + .../components/Icons/IconImageToText.svelte | 28 + .../src/lib/components/Icons/IconInfo.svelte | 20 + .../lib/components/Icons/IconLightning.svelte | 18 + .../lib/components/Icons/IconMagicWand.svelte | 22 + .../lib/components/Icons/IconMaximize.svelte | 23 + .../components/Icons/IconMicrophone.svelte | 25 + .../Icons/IconObjectDetection.svelte | 25 + .../Icons/IconQuestionAnswering.svelte | 21 + .../Icons/IconReinforcementLearning.svelte | 23 + .../lib/components/Icons/IconRobotics.svelte | 22 + .../src/lib/components/Icons/IconRow.svelte | 16 + .../Icons/IconSentenceSimilarity.svelte | 25 + .../src/lib/components/Icons/IconSpin.svelte | 30 + .../components/Icons/IconSummarization.svelte | 22 + .../Icons/IconTableQuestionAnswering.svelte | 21 + .../Icons/IconTabularClassification.svelte | 22 + .../Icons/IconTabularRegression.svelte | 20 + .../Icons/IconText2textGeneration.svelte | 27 + .../Icons/IconTextClassification.svelte | 33 + .../Icons/IconTextGeneration.svelte | 25 + .../components/Icons/IconTextToImage.svelte | 25 + .../components/Icons/IconTextToSpeech.svelte | 23 + .../components/Icons/IconTextToVideo.svelte | 23 + .../Icons/IconTokenClassification.svelte | 33 + .../components/Icons/IconTranslation.svelte | 24 + .../IconUnconditionalImageGeneration.svelte | 22 + .../Icons/IconVideoClassification.svelte | 24 + .../Icons/IconVoiceActivityDetection.svelte | 23 + .../Icons/IconZeroShotClassification.svelte | 51 + .../InferenceWidget/InferenceWidget.svelte | 100 + .../WidgetAddSentenceBtn.svelte | 12 + .../WidgetAudioTrack/WidgetAudioTrack.svelte | 17 + .../WidgetBloomDecoding.svelte | 55 + .../WidgetCheckbox/WidgetCheckbox.svelte | 17 + .../WidgetDropzone/WidgetDropzone.svelte | 89 + .../InferenceWidget/shared/WidgetExample.ts | 114 + .../WidgetFileInput/WidgetFileInput.svelte | 56 + .../shared/WidgetFooter/WidgetFooter.svelte | 33 + .../shared/WidgetHeader/WidgetHeader.svelte | 49 + .../shared/WidgetInfo/WidgetInfo.svelte | 116 + .../WidgetInputSamples.svelte | 98 + .../WidgetInputSamplesGroup.svelte | 81 + .../shared/WidgetLabel/WidgetLabel.svelte | 13 + .../WidgetModelLoading.svelte | 38 + .../WidgetOutputConvoBubble.svelte | 12 + .../WidgetOutputChart.svelte | 65 + .../WidgetOutputConvo.svelte | 33 + .../WidgetOutputTableQA.svelte | 52 + .../WidgetOutputText/WidgetOutputText.svelte | 10 + .../WidgetOutputTokens.svelte | 94 + .../WidgetQuickInput/WidgetQuickInput.svelte | 29 + .../shared/WidgetRadio/WidgetRadio.svelte | 21 + .../shared/WidgetRealtimeRecorder/Recorder.ts | 103 + .../WidgetRealtimeRecorder.svelte | 98 + .../shared/WidgetRecorder/Recorder.ts | 69 + .../WidgetRecorder/WidgetRecorder.svelte | 67 + .../WidgetShortcutRunLabel.svelte | 22 + .../shared/WidgetState/WidgetState.svelte | 17 + .../WidgetSubmitBtn/WidgetSubmitBtn.svelte | 37 + .../WidgetTableInput/WidgetTableInput.svelte | 112 + .../WidgetTextInput/WidgetTextInput.svelte | 20 + .../WidgetTextarea/WidgetTextarea.svelte | 106 + .../shared/WidgetTimer/WidgetTimer.svelte | 35 + .../shared/WidgetWrapper/WidgetWrapper.svelte | 159 ++ .../InferenceWidget/shared/consts.ts | 37 + .../InferenceWidget/shared/helpers.ts | 251 +++ .../InferenceWidget/shared/inputValidation.ts | 87 + .../shared/outputValidation.ts | 35 + .../InferenceWidget/shared/types.ts | 68 + .../lib/components/InferenceWidget/stores.ts | 4 + .../AudioClassificationWidget.svelte | 202 ++ .../AudioToAudioWidget.svelte | 191 ++ .../AutomaticSpeechRecognitionWidget.svelte | 226 ++ .../ConversationalWidget.svelte | 190 ++ .../FeatureExtractionWidget/DataTable.ts | 43 + .../FeatureExtractionWidget.svelte | 200 ++ .../FillMaskWidget/FillMaskWidget.svelte | 178 ++ .../ImageClassificationWidget.svelte | 176 ++ .../ImageSegmentationWidget/Canvas.svelte | 75 + .../ImageSegmentationWidget.svelte | 286 +++ .../ImageToImageWidget.svelte | 202 ++ .../ImageToTextWidget.svelte | 161 ++ .../ObjectDetectionWidget.svelte | 197 ++ .../SvgBoundingBoxes.svelte | 93 + .../QuestionAnsweringWidget.svelte | 177 ++ .../ReinforcementLearningWidget.svelte | 62 + .../SentenceSimilarityWidget.svelte | 187 ++ .../SummarizationWidget.svelte | 140 ++ .../TableQuestionAnsweringWidget.svelte | 196 ++ .../TabularDataWidget.svelte | 228 ++ .../TextGenerationWidget.svelte | 268 +++ .../TextToImageWidget.svelte | 155 ++ .../TextToSpeechWidget.svelte | 143 ++ .../TokenClassificationWidget.svelte | 265 +++ .../VisualQuestionAnsweringWidget.svelte | 204 ++ .../ZeroShotImageClassificationWidget.svelte | 228 ++ .../ZeroShotClassificationWidget.svelte | 200 ++ .../PipelineIcon/PipelineIcon.svelte | 89 + .../components/PipelineTag/PipelineTag.svelte | 16 + packages/widgets/src/lib/index.ts | 38 + .../src/lib/inferenceSnippets/inputs.ts | 129 ++ .../src/lib/inferenceSnippets/serveCurl.ts | 63 + .../src/lib/inferenceSnippets/serveJs.ts | 150 ++ .../src/lib/inferenceSnippets/servePython.ts | 114 + .../src/lib/interfaces/DefaultWidget.ts | 718 ++++++ .../lib/interfaces/InferenceDisplayability.ts | 14 + .../widgets/src/lib/interfaces/Libraries.ts | 766 +++++++ .../src/lib/interfaces/LibrariesToTasks.ts | 46 + packages/widgets/src/lib/interfaces/README.md | 13 + packages/widgets/src/lib/interfaces/Types.ts | 111 + packages/widgets/src/lib/utils/ViewUtils.ts | 138 ++ packages/widgets/src/routes/+layout.svelte | 7 + packages/widgets/src/routes/+page.svelte | 581 +++++ .../src/routes/[...model]/+page.svelte | 28 + .../widgets/src/routes/[...model]/+page.ts | 17 + packages/widgets/src/tailwind.css | 226 ++ packages/widgets/static/audioProcessor.js | 39 + packages/widgets/static/cats.jpg | Bin 0 -> 173131 bytes packages/widgets/static/favicon.png | Bin 0 -> 1571 bytes packages/widgets/svelte.config.js | 18 + packages/widgets/tailwind.config.cjs | 43 + packages/widgets/tsconfig.json | 15 + packages/widgets/vite.config.ts | 6 + pnpm-lock.yaml | 383 +++- pnpm-workspace.yaml | 1 + 166 files changed, 14478 insertions(+), 118 deletions(-) create mode 100644 .github/workflows/widgets-publish.yml create mode 100644 packages/widgets/.eslintignore create mode 100644 packages/widgets/.gitignore create mode 100644 packages/widgets/.prettierignore create mode 100644 packages/widgets/README.md create mode 100644 packages/widgets/package.json create mode 100644 packages/widgets/pnpm-lock.yaml create mode 100644 packages/widgets/postcss.config.js create mode 100644 packages/widgets/src/app.d.ts create mode 100644 packages/widgets/src/app.html create mode 100644 packages/widgets/src/lib/components/DemoThemeSwitcher/DemoThemeSwitcher.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconAudioClassification.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconAudioToAudio.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconAutomaticSpeechRecognition.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconAzureML.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconCaretDown.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconCaretDownV2.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconCode.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconConversational.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconCross.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconDepthEstimation.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconDocumentQuestionAnswering.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconFeatureExtraction.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconFile.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconFillMask.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconGraphML.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconImageClassification.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconImageSegmentation.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconImageToImage.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconImageToText.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconInfo.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconLightning.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconMagicWand.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconMaximize.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconMicrophone.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconObjectDetection.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconQuestionAnswering.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconReinforcementLearning.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconRobotics.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconRow.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconSentenceSimilarity.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconSpin.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconSummarization.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconTableQuestionAnswering.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconTabularClassification.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconTabularRegression.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconText2textGeneration.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconTextClassification.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconTextGeneration.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconTextToImage.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconTextToSpeech.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconTextToVideo.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconTokenClassification.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconTranslation.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconUnconditionalImageGeneration.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconVideoClassification.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconVoiceActivityDetection.svelte create mode 100644 packages/widgets/src/lib/components/Icons/IconZeroShotClassification.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/InferenceWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetAddSentenceBtn/WidgetAddSentenceBtn.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetAudioTrack/WidgetAudioTrack.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetBloomDecoding/WidgetBloomDecoding.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetCheckbox/WidgetCheckbox.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetDropzone/WidgetDropzone.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetExample.ts create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetFileInput/WidgetFileInput.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetFooter/WidgetFooter.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetHeader/WidgetHeader.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetInfo/WidgetInfo.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetInputSamples/WidgetInputSamples.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetInputSamplesGroup/WidgetInputSamplesGroup.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetLabel/WidgetLabel.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetModelLoading/WidgetModelLoading.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOuputConvoBubble/WidgetOutputConvoBubble.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputChart/WidgetOutputChart.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputConvo/WidgetOutputConvo.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputTableQA/WidgetOutputTableQA.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputText/WidgetOutputText.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputTokens/WidgetOutputTokens.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetQuickInput/WidgetQuickInput.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRadio/WidgetRadio.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRealtimeRecorder/Recorder.ts create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRealtimeRecorder/WidgetRealtimeRecorder.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRecorder/Recorder.ts create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRecorder/WidgetRecorder.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetShortcutRunLabel/WidgetShortcutRunLabel.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetState/WidgetState.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetSubmitBtn/WidgetSubmitBtn.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTableInput/WidgetTableInput.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTextInput/WidgetTextInput.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTextarea/WidgetTextarea.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTimer/WidgetTimer.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/WidgetWrapper/WidgetWrapper.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/consts.ts create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/helpers.ts create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/inputValidation.ts create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/outputValidation.ts create mode 100644 packages/widgets/src/lib/components/InferenceWidget/shared/types.ts create mode 100644 packages/widgets/src/lib/components/InferenceWidget/stores.ts create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/AudioClassificationWidget/AudioClassificationWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/AudioToAudioWidget/AudioToAudioWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/AutomaticSpeechRecognitionWidget/AutomaticSpeechRecognitionWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/ConversationalWidget/ConversationalWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/FeatureExtractionWidget/DataTable.ts create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/FeatureExtractionWidget/FeatureExtractionWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/FillMaskWidget/FillMaskWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/ImageClassificationWidget/ImageClassificationWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/ImageSegmentationWidget/Canvas.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/ImageSegmentationWidget/ImageSegmentationWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/ImageToImageWidget/ImageToImageWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/ImageToTextWidget/ImageToTextWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/ObjectDetectionWidget/ObjectDetectionWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/ObjectDetectionWidget/SvgBoundingBoxes.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/QuestionAnsweringWidget/QuestionAnsweringWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/ReinforcementLearningWidget/ReinforcementLearningWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/SentenceSimilarityWidget/SentenceSimilarityWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/SummarizationWidget/SummarizationWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/TableQuestionAnsweringWidget/TableQuestionAnsweringWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/TabularDataWidget/TabularDataWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/TextGenerationWidget/TextGenerationWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/TextToImageWidget/TextToImageWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/TextToSpeechWidget/TextToSpeechWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/TokenClassificationWidget/TokenClassificationWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/VisualQuestionAnsweringWidget/VisualQuestionAnsweringWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/ZeroShotImageClassificationWidget/ZeroShotImageClassificationWidget.svelte create mode 100644 packages/widgets/src/lib/components/InferenceWidget/widgets/ZeroShowClassificationWidget/ZeroShotClassificationWidget.svelte create mode 100644 packages/widgets/src/lib/components/PipelineIcon/PipelineIcon.svelte create mode 100644 packages/widgets/src/lib/components/PipelineTag/PipelineTag.svelte create mode 100644 packages/widgets/src/lib/index.ts create mode 100644 packages/widgets/src/lib/inferenceSnippets/inputs.ts create mode 100644 packages/widgets/src/lib/inferenceSnippets/serveCurl.ts create mode 100644 packages/widgets/src/lib/inferenceSnippets/serveJs.ts create mode 100644 packages/widgets/src/lib/inferenceSnippets/servePython.ts create mode 100644 packages/widgets/src/lib/interfaces/DefaultWidget.ts create mode 100644 packages/widgets/src/lib/interfaces/InferenceDisplayability.ts create mode 100644 packages/widgets/src/lib/interfaces/Libraries.ts create mode 100644 packages/widgets/src/lib/interfaces/LibrariesToTasks.ts create mode 100644 packages/widgets/src/lib/interfaces/README.md create mode 100644 packages/widgets/src/lib/interfaces/Types.ts create mode 100644 packages/widgets/src/lib/utils/ViewUtils.ts create mode 100644 packages/widgets/src/routes/+layout.svelte create mode 100644 packages/widgets/src/routes/+page.svelte create mode 100644 packages/widgets/src/routes/[...model]/+page.svelte create mode 100644 packages/widgets/src/routes/[...model]/+page.ts create mode 100644 packages/widgets/src/tailwind.css create mode 100644 packages/widgets/static/audioProcessor.js create mode 100644 packages/widgets/static/cats.jpg create mode 100644 packages/widgets/static/favicon.png create mode 100644 packages/widgets/svelte.config.js create mode 100644 packages/widgets/tailwind.config.cjs create mode 100644 packages/widgets/tsconfig.json create mode 100644 packages/widgets/vite.config.ts diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 4d861d5f5..c116d6da8 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,13 +1,18 @@ module.exports = { - extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"], + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:svelte/recommended", "prettier"], parser: "@typescript-eslint/parser", plugins: ["@typescript-eslint", "prettier"], root: true, env: { browser: true, - amd: true, + es2017: true, node: true, }, + parserOptions: { + sourceType: "module", + ecmaVersion: 2020, + extraFileExtensions: [".svelte"], + }, rules: { "no-constant-condition": "off", "@typescript-eslint/no-empty-function": "off", @@ -20,4 +25,13 @@ module.exports = { // For doc purposes, prefer interfaces "@typescript-eslint/consistent-type-definitions": ["error", "interface"], }, + overrides: [ + { + files: ["*.svelte"], + parser: "svelte-eslint-parser", + parserOptions: { + parser: "@typescript-eslint/parser", + }, + }, + ], }; diff --git a/.github/workflows/lint-and-test.yml b/.github/workflows/lint-and-test.yml index b7a516ebb..e75547281 100644 --- a/.github/workflows/lint-and-test.yml +++ b/.github/workflows/lint-and-test.yml @@ -45,7 +45,7 @@ jobs: pnpm --filter ...[${{ steps.since.outputs.SINCE }}] format:check - name: Check types - run: pnpm --filter ...[${{ steps.since.outputs.SINCE }}] type-check + run: pnpm --filter ...[${{ steps.since.outputs.SINCE }}] check - name: Test run: VCR_MODE=playback pnpm --filter ...[${{ steps.since.outputs.SINCE }}] test diff --git a/.github/workflows/widgets-publish.yml b/.github/workflows/widgets-publish.yml new file mode 100644 index 000000000..a663013cf --- /dev/null +++ b/.github/workflows/widgets-publish.yml @@ -0,0 +1,51 @@ +name: Widgets - Version and Release + +on: + workflow_dispatch: + inputs: + newversion: + description: "Semantic Version Bump Type (major minor patch)" + default: patch + +defaults: + run: + working-directory: packages/widgets + +jobs: + version_and_release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + token: ${{ secrets.BOT_ACCESS_TOKEN }} + - run: corepack enable + - uses: actions/setup-node@v3 + with: + node-version: "18" + cache: "pnpm" + cache-dependency-path: | + packages/widgets/pnpm-lock.yaml + # setting a registry enables the NODE_AUTH_TOKEN env variable where we can set an npm token. REQUIRED + registry-url: "https://registry.npmjs.org" + - run: pnpm install + - run: git config --global user.name machineuser + - run: git config --global user.email infra+machineuser@huggingface.co + - run: | + PACKAGE_VERSION=$(node -p "require('./package.json').version") + BUMPED_VERSION=$(node -p "require('semver').inc('$PACKAGE_VERSION', '${{ github.event.inputs.newversion }}')") + # Update package.json with the new version + node -e "const fs = require('fs'); const package = JSON.parse(fs.readFileSync('./package.json')); package.version = '$BUMPED_VERSION'; fs.writeFileSync('./package.json', JSON.stringify(package, null, '\t') + '\n');" + git commit . -m "🔖 @hugginface/widgets $BUMPED_VERSION" + git tag "widgets-v$BUMPED_VERSION" + - run: pnpm publish --no-git-checks . + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - run: git push --follow-tags + # hack - reuse actions/setup-node@v3 just to set a new registry + - uses: actions/setup-node@v3 + with: + node-version: "18" + registry-url: "https://npm.pkg.github.com" + - run: pnpm publish --no-git-checks . + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.prettierrc b/.prettierrc index 0001bb886..4593d117a 100644 --- a/.prettierrc +++ b/.prettierrc @@ -3,5 +3,7 @@ "useTabs": true, "tabWidth": 2, "printWidth": 120, - "trailingComma": "es5" + "trailingComma": "es5", + "plugins": ["prettier-plugin-svelte"], + "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] } diff --git a/package.json b/package.json index d25118752..c50760cbe 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,17 @@ { "license": "MIT", - "packageManager": "pnpm@8.3.1", + "packageManager": "pnpm@8.10.5", "dependencies": { "@typescript-eslint/eslint-plugin": "^5.51.0", "@typescript-eslint/parser": "^5.51.0", "eslint": "^8.35.0", - "eslint-config-prettier": "^8.6.0", + "eslint-config-prettier": "^9.0.0", "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.4", - "typescript": "^4.9.5", - "vite": "^4.1.4" + "eslint-plugin-svelte": "^2.30.0", + "prettier": "^3.0.0", + "prettier-plugin-svelte": "^3.0.0", + "typescript": "^5.0.0", + "vite": "4.1.4" }, "scripts": { "lint": "eslint --quiet --fix --ext .cjs,.ts .eslintrc.cjs", @@ -20,8 +22,8 @@ "devDependencies": { "@vitest/browser": "^0.29.7", "semver": "^7.5.0", - "tsup": "^6.7.0", "ts-node": "^10.9.1", + "tsup": "^6.7.0", "vitest": "^0.29.4", "webdriverio": "^8.6.7" } diff --git a/packages/agents/package.json b/packages/agents/package.json index 3f9d9b0b1..183d27df6 100644 --- a/packages/agents/package.json +++ b/packages/agents/package.json @@ -1,6 +1,6 @@ { "name": "@huggingface/agents", - "packageManager": "pnpm@8.3.1", + "packageManager": "pnpm@8.10.5", "version": "0.0.5", "description": "Multi-modal agents using Hugging Face's models", "repository": "https://github.com/huggingface/huggingface.js.git", @@ -34,7 +34,7 @@ "build": "tsup", "test": "vitest run", "test:browser": "vitest run --browser.name=chrome --browser.headless --config ./vitest-browser.config.ts", - "type-check": "tsc" + "check": "tsc" }, "files": [ "src", diff --git a/packages/doc-internal/package.json b/packages/doc-internal/package.json index 47a947c89..1e3b6311c 100644 --- a/packages/doc-internal/package.json +++ b/packages/doc-internal/package.json @@ -1,6 +1,6 @@ { "name": "@huggingface/doc-internal", - "packageManager": "pnpm@8.3.1", + "packageManager": "pnpm@8.10.5", "version": "1.0.0", "description": "Package to generate doc for other @huggingface packages", "private": true, diff --git a/packages/hub/package.json b/packages/hub/package.json index 3f08e038d..fb2836544 100644 --- a/packages/hub/package.json +++ b/packages/hub/package.json @@ -1,6 +1,6 @@ { "name": "@huggingface/hub", - "packageManager": "pnpm@8.3.1", + "packageManager": "pnpm@8.10.5", "version": "0.12.2", "description": "Utilities to interact with the Hugging Face hub", "repository": "https://github.com/huggingface/huggingface.js.git", @@ -36,7 +36,7 @@ "build": "tsup", "test": "vitest run", "test:browser": "vitest run --browser.name=chrome --browser.headless --config ./vitest-browser.config.ts", - "type-check": "tsc" + "check": "tsc" }, "files": [ "src", diff --git a/packages/inference/package.json b/packages/inference/package.json index a6e4f0070..5c99559bd 100644 --- a/packages/inference/package.json +++ b/packages/inference/package.json @@ -1,7 +1,7 @@ { "name": "@huggingface/inference", "version": "2.6.4", - "packageManager": "pnpm@8.3.1", + "packageManager": "pnpm@8.10.5", "license": "MIT", "author": "Tim Mikeladze ", "description": "Typescript wrapper for the Hugging Face Inference API", @@ -44,10 +44,11 @@ "lint:check": "eslint --ext .cjs,.ts .", "format": "prettier --write .", "format:check": "prettier --check .", + "prepare": "pnpm run build", "prepublishOnly": "pnpm run build", "test": "vitest run --config vitest.config.ts", "test:browser": "vitest run --browser.name=chrome --browser.headless --config vitest.config.ts", - "type-check": "tsc" + "check": "tsc" }, "devDependencies": { "@types/node": "18.13.0", diff --git a/packages/languages/package.json b/packages/languages/package.json index 080d50d89..39075e311 100644 --- a/packages/languages/package.json +++ b/packages/languages/package.json @@ -1,6 +1,6 @@ { "name": "@huggingface/languages", - "packageManager": "pnpm@8.3.1", + "packageManager": "pnpm@8.10.5", "version": "1.0.0", "description": "List of ISO-639 languages used in the Hub", "repository": "https://github.com/huggingface/huggingface.js.git", @@ -26,7 +26,7 @@ "prepublishOnly": "pnpm run build", "build": "tsup src/index.ts --format cjs,esm --clean --dts", "test": "vitest run", - "type-check": "tsc" + "check": "tsc" }, "files": [ "dist", diff --git a/packages/tasks/package.json b/packages/tasks/package.json index f31c52d92..2ee60dac6 100644 --- a/packages/tasks/package.json +++ b/packages/tasks/package.json @@ -1,8 +1,8 @@ { "name": "@huggingface/tasks", - "packageManager": "pnpm@8.3.1", - "version": "0.0.4", - "description": "List of ISO-639 languages used in the Hub", + "packageManager": "pnpm@8.10.5", + "version": "0.0.5", + "description": "List of ML tasks for huggingface.co/tasks", "repository": "https://github.com/huggingface/huggingface.js.git", "publishConfig": { "access": "public" @@ -25,7 +25,8 @@ "format:check": "prettier --check .", "prepublishOnly": "pnpm run build", "build": "tsup src/index.ts --format cjs,esm --clean --dts", - "type-check": "tsc" + "prepare": "pnpm run build", + "check": "tsc" }, "files": [ "dist", diff --git a/packages/tasks/src/index.ts b/packages/tasks/src/index.ts index 0519b7d96..d45f5d541 100644 --- a/packages/tasks/src/index.ts +++ b/packages/tasks/src/index.ts @@ -1,4 +1,13 @@ export type { TaskData, TaskDemo, TaskDemoEntry, ExampleRepo } from "./Types"; export { TASKS_DATA } from "./tasksData"; -export { PIPELINE_DATA, type PipelineType, type PipelineData, type Modality, MODALITIES } from "./pipelines"; +export { + PIPELINE_DATA, + PIPELINE_TYPES, + type PipelineType, + type PipelineData, + type Modality, + MODALITIES, + MODALITY_LABELS, +} from "./pipelines"; export { ModelLibrary } from "./modelLibraries"; +export type { ModelLibraryKey } from "./modelLibraries"; diff --git a/packages/tasks/src/pipelines.ts b/packages/tasks/src/pipelines.ts index ab22782d5..ae487d5e3 100644 --- a/packages/tasks/src/pipelines.ts +++ b/packages/tasks/src/pipelines.ts @@ -2,6 +2,16 @@ export const MODALITIES = ["cv", "nlp", "audio", "tabular", "multimodal", "rl", export type Modality = (typeof MODALITIES)[number]; +export const MODALITY_LABELS = { + multimodal: "Multimodal", + nlp: "Natural Language Processing", + audio: "Audio", + cv: "Computer Vision", + rl: "Reinforcement Learning", + tabular: "Tabular", + other: "Other", +} satisfies Record; + /** * Public interface for a sub task. * @@ -606,3 +616,4 @@ export const PIPELINE_DATA = { } satisfies Record; export type PipelineType = keyof typeof PIPELINE_DATA; +export const PIPELINE_TYPES = Object.keys(PIPELINE_DATA) as PipelineType[]; diff --git a/packages/widgets/.eslintignore b/packages/widgets/.eslintignore new file mode 100644 index 000000000..03cc13658 --- /dev/null +++ b/packages/widgets/.eslintignore @@ -0,0 +1,14 @@ +.DS_Store +node_modules +/dist +/build +/.svelte-kit +/package +.env +.env.* +!.env.example + +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock diff --git a/packages/widgets/.gitignore b/packages/widgets/.gitignore new file mode 100644 index 000000000..ac7211b40 --- /dev/null +++ b/packages/widgets/.gitignore @@ -0,0 +1,11 @@ +.DS_Store +node_modules +/build +/dist +/.svelte-kit +/package +.env +.env.* +!.env.example +vite.config.js.timestamp-* +vite.config.ts.timestamp-* diff --git a/packages/widgets/.prettierignore b/packages/widgets/.prettierignore new file mode 100644 index 000000000..03cc13658 --- /dev/null +++ b/packages/widgets/.prettierignore @@ -0,0 +1,14 @@ +.DS_Store +node_modules +/dist +/build +/.svelte-kit +/package +.env +.env.* +!.env.example + +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock diff --git a/packages/widgets/README.md b/packages/widgets/README.md new file mode 100644 index 000000000..64d097d3a --- /dev/null +++ b/packages/widgets/README.md @@ -0,0 +1,18 @@ +# Huggingface Widgets + +Open-source version of the inference widgets from huggingface.co + +> Built with Svelte and SvelteKit + +**Demo page:** https://huggingface.co/spaces/huggingfacejs/inference-widgets + +You can also run the demo locally: + +```console +pnpm install +pnpm dev +``` + +## Publishing + +Because `@huggingface/widgets` depends on `@huggingface/tasks`, you need to publish `@huggingface/tasks` first, and then `@huggingface/widgets`. diff --git a/packages/widgets/package.json b/packages/widgets/package.json new file mode 100644 index 000000000..b8e394020 --- /dev/null +++ b/packages/widgets/package.json @@ -0,0 +1,59 @@ +{ + "name": "@huggingface/widgets", + "packageManager": "pnpm@8.10.5", + "version": "0.0.4", + "publishConfig": { + "access": "public" + }, + "scripts": { + "dev": "vite dev", + "build": "vite build && npm run package", + "preview": "vite preview", + "package": "svelte-kit sync && svelte-package && publint", + "prepublishOnly": "npm run package", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "lint": "eslint --quiet --fix --ext .cjs,.ts .", + "lint:check": "eslint --ext .cjs,.ts .", + "format": "prettier --write .", + "format:check": "prettier --check ." + }, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "svelte": "./dist/index.js" + } + }, + "files": [ + "dist", + "src", + "!dist/**/*.test.*", + "!dist/**/*.spec.*", + "static/audioProcessor.js" + ], + "dependencies": { + "@huggingface/tasks": "workspace:^" + }, + "peerDependencies": { + "svelte": "^3.59.2" + }, + "devDependencies": { + "@sveltejs/adapter-auto": "^2.0.0", + "@sveltejs/kit": "^1.27.4", + "@sveltejs/package": "^2.0.0", + "@tailwindcss/forms": "^0.5.7", + "autoprefixer": "^10.4.16", + "eslint": "^8.28.0", + "postcss": "^8.4.31", + "publint": "^0.1.9", + "svelte": "^3.59.2", + "svelte-check": "^3.6.0", + "tailwindcss": "^3.3.5", + "tslib": "^2.4.1", + "typescript": "^5.0.0", + "vite": "^4.0.0" + }, + "svelte": "./dist/index.js", + "types": "./dist/index.d.ts", + "type": "module" +} diff --git a/packages/widgets/pnpm-lock.yaml b/packages/widgets/pnpm-lock.yaml new file mode 100644 index 000000000..4703ba0b3 --- /dev/null +++ b/packages/widgets/pnpm-lock.yaml @@ -0,0 +1,1973 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@huggingface/tasks': + specifier: workspace:^ + version: link:../tasks + +devDependencies: + '@sveltejs/adapter-auto': + specifier: ^2.0.0 + version: 2.0.0(@sveltejs/kit@1.27.4) + '@sveltejs/kit': + specifier: ^1.27.4 + version: 1.27.4(svelte@3.59.2)(vite@4.5.0) + '@sveltejs/package': + specifier: ^2.0.0 + version: 2.0.0(svelte@3.59.2)(typescript@5.0.4) + '@tailwindcss/forms': + specifier: ^0.5.7 + version: 0.5.7(tailwindcss@3.3.5) + autoprefixer: + specifier: ^10.4.16 + version: 10.4.16(postcss@8.4.31) + eslint: + specifier: ^8.28.0 + version: 8.28.0 + postcss: + specifier: ^8.4.31 + version: 8.4.31 + publint: + specifier: ^0.1.9 + version: 0.1.9 + svelte: + specifier: ^3.59.2 + version: 3.59.2 + svelte-check: + specifier: ^3.6.0 + version: 3.6.0(postcss@8.4.31)(svelte@3.59.2) + tailwindcss: + specifier: ^3.3.5 + version: 3.3.5 + tslib: + specifier: ^2.4.1 + version: 2.4.1 + typescript: + specifier: ^5.0.0 + version: 5.0.4 + vite: + specifier: ^4.0.0 + version: 4.5.0 + +packages: + + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@alloc/quick-lru@5.2.0: + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + dev: true + + /@esbuild/android-arm64@0.18.20: + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.18.20: + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.18.20: + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.18.20: + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.18.20: + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.18.20: + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.18.20: + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.18.20: + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.18.20: + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.18.20: + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.18.20: + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.18.20: + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.18.20: + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.18.20: + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.18.20: + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.18.20: + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.18.20: + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.18.20: + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.18.20: + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.18.20: + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.18.20: + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.18.20: + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint/eslintrc@1.4.1: + resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.23.0 + ignore: 5.3.0 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@fastify/busboy@2.1.0: + resolution: {integrity: sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==} + engines: {node: '>=14'} + dev: true + + /@humanwhocodes/config-array@0.11.13: + resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@2.0.1: + resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + dev: true + + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.20 + dev: true + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.20: + resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@polka/url@1.0.0-next.23: + resolution: {integrity: sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==} + dev: true + + /@sveltejs/adapter-auto@2.0.0(@sveltejs/kit@1.27.4): + resolution: {integrity: sha512-b+gkHFZgD771kgV3aO4avHFd7y1zhmMYy9i6xOK7m/rwmwaRO8gnF5zBc0Rgca80B2PMU1bKNxyBTHA14OzUAQ==} + peerDependencies: + '@sveltejs/kit': ^1.0.0 + dependencies: + '@sveltejs/kit': 1.27.4(svelte@3.59.2)(vite@4.5.0) + import-meta-resolve: 2.2.2 + dev: true + + /@sveltejs/kit@1.27.4(svelte@3.59.2)(vite@4.5.0): + resolution: {integrity: sha512-Vxl8Jf0C1+/8i/slsxFOnwJntCBDLueO/O6GJ0390KUnyW3Zs+4ZiIinD+cEcYnJPQQ9CRzVSr9Bn6DbmTn4Dw==} + engines: {node: ^16.14 || >=18} + hasBin: true + requiresBuild: true + peerDependencies: + svelte: ^3.54.0 || ^4.0.0-next.0 || ^5.0.0-next.0 + vite: ^4.0.0 + dependencies: + '@sveltejs/vite-plugin-svelte': 2.5.2(svelte@3.59.2)(vite@4.5.0) + '@types/cookie': 0.5.4 + cookie: 0.5.0 + devalue: 4.3.2 + esm-env: 1.0.0 + kleur: 4.1.5 + magic-string: 0.30.5 + mrmime: 1.0.1 + sade: 1.8.1 + set-cookie-parser: 2.6.0 + sirv: 2.0.3 + svelte: 3.59.2 + tiny-glob: 0.2.9 + undici: 5.26.5 + vite: 4.5.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@sveltejs/package@2.0.0(svelte@3.59.2)(typescript@5.0.4): + resolution: {integrity: sha512-sANz/dJibOHOe83hl8pFWUSypqefdYwPp6SUr0SmJxTNQFB5dDECEqwAwoy28DWCQFYl7DU+C1hKkTXyuKOdug==} + engines: {node: ^16.14 || >=18} + hasBin: true + peerDependencies: + svelte: ^3.44.0 + dependencies: + chokidar: 3.5.3 + kleur: 4.1.5 + sade: 1.8.1 + svelte: 3.59.2 + svelte2tsx: 0.6.25(svelte@3.59.2)(typescript@5.0.4) + transitivePeerDependencies: + - typescript + dev: true + + /@sveltejs/vite-plugin-svelte-inspector@1.0.4(@sveltejs/vite-plugin-svelte@2.5.2)(svelte@3.59.2)(vite@4.5.0): + resolution: {integrity: sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ==} + engines: {node: ^14.18.0 || >= 16} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^2.2.0 + svelte: ^3.54.0 || ^4.0.0 + vite: ^4.0.0 + dependencies: + '@sveltejs/vite-plugin-svelte': 2.5.2(svelte@3.59.2)(vite@4.5.0) + debug: 4.3.4 + svelte: 3.59.2 + vite: 4.5.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@sveltejs/vite-plugin-svelte@2.5.2(svelte@3.59.2)(vite@4.5.0): + resolution: {integrity: sha512-Dfy0Rbl+IctOVfJvWGxrX/3m6vxPLH8o0x+8FA5QEyMUQMo4kGOVIojjryU7YomBAexOTAuYf1RT7809yDziaA==} + engines: {node: ^14.18.0 || >= 16} + peerDependencies: + svelte: ^3.54.0 || ^4.0.0 || ^5.0.0-next.0 + vite: ^4.0.0 + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 1.0.4(@sveltejs/vite-plugin-svelte@2.5.2)(svelte@3.59.2)(vite@4.5.0) + debug: 4.3.4 + deepmerge: 4.3.1 + kleur: 4.1.5 + magic-string: 0.30.5 + svelte: 3.59.2 + svelte-hmr: 0.15.3(svelte@3.59.2) + vite: 4.5.0 + vitefu: 0.2.5(vite@4.5.0) + transitivePeerDependencies: + - supports-color + dev: true + + /@tailwindcss/forms@0.5.7(tailwindcss@3.3.5): + resolution: {integrity: sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==} + peerDependencies: + tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1' + dependencies: + mini-svg-data-uri: 1.4.4 + tailwindcss: 3.3.5 + dev: true + + /@types/cookie@0.5.4: + resolution: {integrity: sha512-7z/eR6O859gyWIAjuvBWFzNURmf2oPBmJlfVWkwehU5nzIyjwBsTh7WMmEEV4JFnHuQ3ex4oyTvfKzcyJVDBNA==} + dev: true + + /@types/pug@2.0.9: + resolution: {integrity: sha512-Yg4LkgFYvn1faISbDNWmcAC1XoDT8IoMUFspp5mnagKk+UvD2N0IWt5A7GRdMubsNWqgCLmrkf8rXkzNqb4szA==} + dev: true + + /acorn-jsx@5.3.2(acorn@8.11.2): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.2 + dev: true + + /acorn@8.11.2: + resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: true + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /autoprefixer@10.4.16(postcss@8.4.31): + resolution: {integrity: sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.22.1 + caniuse-lite: 1.0.30001563 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.0.0 + postcss: 8.4.31 + postcss-value-parser: 4.2.0 + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist@4.22.1: + resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001563 + electron-to-chromium: 1.4.588 + node-releases: 2.0.13 + update-browserslist-db: 1.0.13(browserslist@4.22.1) + dev: true + + /buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + dev: true + + /caniuse-lite@1.0.30001563: + resolution: {integrity: sha512-na2WUmOxnwIZtwnFI2CZ/3er0wdNzU7hN+cPYz/z2ajHThnkWjNBOpEPP4n+4r2WPM847JaMotaJE3bnfzjyKw==} + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /dedent-js@1.0.1: + resolution: {integrity: sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==} + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: true + + /detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + dev: true + + /devalue@4.3.2: + resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==} + dev: true + + /didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dev: true + + /dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /electron-to-chromium@1.4.588: + resolution: {integrity: sha512-soytjxwbgcCu7nh5Pf4S2/4wa6UIu+A3p03U2yVr53qGxi1/VTR3ENI+p50v+UxqqZAfl48j3z55ud7VHIOr9w==} + dev: true + + /es6-promise@3.3.1: + resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} + dev: true + + /esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + dev: true + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-utils@3.0.0(eslint@8.28.0): + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + dependencies: + eslint: 8.28.0 + eslint-visitor-keys: 2.1.0 + dev: true + + /eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.28.0: + resolution: {integrity: sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint/eslintrc': 1.4.1 + '@humanwhocodes/config-array': 0.11.13 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-utils: 3.0.0(eslint@8.28.0) + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.23.0 + grapheme-splitter: 1.0.4 + ignore: 5.3.0 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-sdsl: 4.4.2 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + regexpp: 3.2.0 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /esm-env@1.0.0: + resolution: {integrity: sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==} + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.2 + acorn-jsx: 5.3.2(acorn@8.11.2) + eslint-visitor-keys: 3.4.3 + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.9 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flatted@3.2.9: + resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + dev: true + + /fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@7.1.6: + resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: true + + /globals@13.23.0: + resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalyzer@0.1.0: + resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} + dev: true + + /globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /grapheme-splitter@1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + + /ignore-walk@5.0.1: + resolution: {integrity: sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + minimatch: 5.1.6 + dev: true + + /ignore@5.3.0: + resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /import-meta-resolve@2.2.2: + resolution: {integrity: sha512-f8KcQ1D80V7RnqVm+/lirO9zkOxjGxhaTC1IPrBGd3MEfNgmNG67tSUO9gTi2F3Blr2Az6g1vocaxzkVnWl9MA==} + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.0 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + dev: true + + /js-sdsl@4.4.2: + resolution: {integrity: sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==} + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + dev: true + + /lilconfig@3.0.0: + resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} + engines: {node: '>=14'} + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + dependencies: + tslib: 2.4.1 + dev: true + + /magic-string@0.27.0: + resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /magic-string@0.30.5: + resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + + /mini-svg-data-uri@1.4.4: + resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} + hasBin: true + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + dev: true + + /mrmime@1.0.1: + resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} + engines: {node: '>=10'} + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: true + + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + dependencies: + lower-case: 2.0.2 + tslib: 2.4.1 + dev: true + + /node-releases@2.0.13: + resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + dev: true + + /npm-bundled@2.0.1: + resolution: {integrity: sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + npm-normalize-package-bin: 2.0.0 + dev: true + + /npm-normalize-package-bin@2.0.0: + resolution: {integrity: sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dev: true + + /npm-packlist@5.1.3: + resolution: {integrity: sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + dependencies: + glob: 8.1.0 + ignore-walk: 5.0.1 + npm-bundled: 2.0.1 + npm-normalize-package-bin: 2.0.0 + dev: true + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + dependencies: + no-case: 3.0.4 + tslib: 2.4.1 + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + dev: true + + /pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + dev: true + + /postcss-import@15.1.0(postcss@8.4.31): + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.4.31 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + dev: true + + /postcss-js@4.0.1(postcss@8.4.31): + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.31 + dev: true + + /postcss-load-config@4.0.2(postcss@8.4.31): + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 3.0.0 + postcss: 8.4.31 + yaml: 2.3.4 + dev: true + + /postcss-nested@6.0.1(postcss@8.4.31): + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + dependencies: + postcss: 8.4.31 + postcss-selector-parser: 6.0.13 + dev: true + + /postcss-selector-parser@6.0.13: + resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + + /postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: true + + /postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /publint@0.1.9: + resolution: {integrity: sha512-O53y7vbePxuGFmEjgcrafMSlDpOJwOkj8YdexOt7yWlv7SB3rXoT3mHknyMJ3lf2UFH5Bmt6tnIkHcOTR6dEoA==} + engines: {node: '>=16'} + hasBin: true + dependencies: + npm-packlist: 5.1.3 + picocolors: 1.0.0 + sade: 1.8.1 + dev: true + + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + dependencies: + pify: 2.3.0 + dev: true + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /regexpp@3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup@3.29.4: + resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + dependencies: + mri: 1.2.0 + dev: true + + /sander@0.5.1: + resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} + dependencies: + es6-promise: 3.3.1 + graceful-fs: 4.2.11 + mkdirp: 0.5.6 + rimraf: 2.7.1 + dev: true + + /set-cookie-parser@2.6.0: + resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /sirv@2.0.3: + resolution: {integrity: sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==} + engines: {node: '>= 10'} + dependencies: + '@polka/url': 1.0.0-next.23 + mrmime: 1.0.1 + totalist: 3.0.1 + dev: true + + /sorcery@0.11.0: + resolution: {integrity: sha512-J69LQ22xrQB1cIFJhPfgtLuI6BpWRiWu1Y3vSsIwK/eAScqJxd/+CJlUuHQRdX2C9NGFamq+KqNywGgaThwfHw==} + hasBin: true + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + buffer-crc32: 0.2.13 + minimist: 1.2.8 + sander: 0.5.1 + dev: true + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /sucrase@3.34.0: + resolution: {integrity: sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==} + engines: {node: '>=8'} + hasBin: true + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + commander: 4.1.1 + glob: 7.1.6 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /svelte-check@3.6.0(postcss@8.4.31)(svelte@3.59.2): + resolution: {integrity: sha512-8VfqhfuRJ1sKW+o8isH2kPi0RhjXH1nNsIbCFGyoUHG+ZxVxHYRKcb+S8eaL/1tyj3VGvWYx3Y5+oCUsJgnzcw==} + hasBin: true + peerDependencies: + svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 + dependencies: + '@jridgewell/trace-mapping': 0.3.20 + chokidar: 3.5.3 + fast-glob: 3.3.2 + import-fresh: 3.3.0 + picocolors: 1.0.0 + sade: 1.8.1 + svelte: 3.59.2 + svelte-preprocess: 5.1.0(postcss@8.4.31)(svelte@3.59.2)(typescript@5.0.4) + typescript: 5.0.4 + transitivePeerDependencies: + - '@babel/core' + - coffeescript + - less + - postcss + - postcss-load-config + - pug + - sass + - stylus + - sugarss + dev: true + + /svelte-hmr@0.15.3(svelte@3.59.2): + resolution: {integrity: sha512-41snaPswvSf8TJUhlkoJBekRrABDXDMdpNpT2tfHIv4JuhgvHqLMhEPGtaQn0BmbNSTkuz2Ed20DF2eHw0SmBQ==} + engines: {node: ^12.20 || ^14.13.1 || >= 16} + peerDependencies: + svelte: ^3.19.0 || ^4.0.0 + dependencies: + svelte: 3.59.2 + dev: true + + /svelte-preprocess@5.1.0(postcss@8.4.31)(svelte@3.59.2)(typescript@5.0.4): + resolution: {integrity: sha512-EkErPiDzHAc0k2MF5m6vBNmRUh338h2myhinUw/xaqsLs7/ZvsgREiLGj03VrSzbY/TB5ZXgBOsKraFee5yceA==} + engines: {node: '>= 14.10.0'} + requiresBuild: true + peerDependencies: + '@babel/core': ^7.10.2 + coffeescript: ^2.5.1 + less: ^3.11.3 || ^4.0.0 + postcss: ^7 || ^8 + postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0 + pug: ^3.0.0 + sass: ^1.26.8 + stylus: ^0.55.0 + sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0 + svelte: ^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 + typescript: '>=3.9.5 || ^4.0.0 || ^5.0.0' + peerDependenciesMeta: + '@babel/core': + optional: true + coffeescript: + optional: true + less: + optional: true + postcss: + optional: true + postcss-load-config: + optional: true + pug: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + typescript: + optional: true + dependencies: + '@types/pug': 2.0.9 + detect-indent: 6.1.0 + magic-string: 0.27.0 + postcss: 8.4.31 + sorcery: 0.11.0 + strip-indent: 3.0.0 + svelte: 3.59.2 + typescript: 5.0.4 + dev: true + + /svelte2tsx@0.6.25(svelte@3.59.2)(typescript@5.0.4): + resolution: {integrity: sha512-hhBKL5X9gGvKQAZ9xLoHnbE9Yb00HxEZJlxcj2drxWK+Tpqcs/bnodjSfCGbqEhvNaUXYNbVL7s4dEXT+o0f6w==} + peerDependencies: + svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0 + typescript: ^4.9.4 || ^5.0.0 + dependencies: + dedent-js: 1.0.1 + pascal-case: 3.1.2 + svelte: 3.59.2 + typescript: 5.0.4 + dev: true + + /svelte@3.59.2: + resolution: {integrity: sha512-vzSyuGr3eEoAtT/A6bmajosJZIUWySzY2CzB3w2pgPvnkUjGqlDnsNnA0PMO+mMAhuyMul6C2uuZzY6ELSkzyA==} + engines: {node: '>= 8'} + dev: true + + /tailwindcss@3.3.5: + resolution: {integrity: sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.5.3 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.0 + lilconfig: 2.1.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.31 + postcss-import: 15.1.0(postcss@8.4.31) + postcss-js: 4.0.1(postcss@8.4.31) + postcss-load-config: 4.0.2(postcss@8.4.31) + postcss-nested: 6.0.1(postcss@8.4.31) + postcss-selector-parser: 6.0.13 + resolve: 1.22.8 + sucrase: 3.34.0 + transitivePeerDependencies: + - ts-node + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: true + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: true + + /tiny-glob@0.2.9: + resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} + dependencies: + globalyzer: 0.1.0 + globrex: 0.1.2 + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + dev: true + + /ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + dev: true + + /tslib@2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /typescript@5.0.4: + resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} + engines: {node: '>=12.20'} + hasBin: true + dev: true + + /undici@5.26.5: + resolution: {integrity: sha512-cSb4bPFd5qgR7qr2jYAi0hlX9n5YKK2ONKkLFkxl+v/9BvC0sOpZjBHDBSXc5lWAf5ty9oZdRXytBIHzgUcerw==} + engines: {node: '>=14.0'} + dependencies: + '@fastify/busboy': 2.1.0 + dev: true + + /update-browserslist-db@1.0.13(browserslist@4.22.1): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.22.1 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + dev: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /vite@4.5.0: + resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.18.20 + postcss: 8.4.31 + rollup: 3.29.4 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /vitefu@0.2.5(vite@4.5.0): + resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + vite: + optional: true + dependencies: + vite: 4.5.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /yaml@2.3.4: + resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} + engines: {node: '>= 14'} + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/packages/widgets/postcss.config.js b/packages/widgets/postcss.config.js new file mode 100644 index 000000000..7b75c83af --- /dev/null +++ b/packages/widgets/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/packages/widgets/src/app.d.ts b/packages/widgets/src/app.d.ts new file mode 100644 index 000000000..f59b884c5 --- /dev/null +++ b/packages/widgets/src/app.d.ts @@ -0,0 +1,12 @@ +// See https://kit.svelte.dev/docs/types#app +// for information about these interfaces +declare global { + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface Platform {} + } +} + +export {}; diff --git a/packages/widgets/src/app.html b/packages/widgets/src/app.html new file mode 100644 index 000000000..f22aeaad5 --- /dev/null +++ b/packages/widgets/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/packages/widgets/src/lib/components/DemoThemeSwitcher/DemoThemeSwitcher.svelte b/packages/widgets/src/lib/components/DemoThemeSwitcher/DemoThemeSwitcher.svelte new file mode 100644 index 000000000..244e51cc6 --- /dev/null +++ b/packages/widgets/src/lib/components/DemoThemeSwitcher/DemoThemeSwitcher.svelte @@ -0,0 +1,60 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconAudioClassification.svelte b/packages/widgets/src/lib/components/Icons/IconAudioClassification.svelte new file mode 100644 index 000000000..963570923 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconAudioClassification.svelte @@ -0,0 +1,21 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconAudioToAudio.svelte b/packages/widgets/src/lib/components/Icons/IconAudioToAudio.svelte new file mode 100644 index 000000000..ae5c4aeef --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconAudioToAudio.svelte @@ -0,0 +1,23 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconAutomaticSpeechRecognition.svelte b/packages/widgets/src/lib/components/Icons/IconAutomaticSpeechRecognition.svelte new file mode 100644 index 000000000..01b18c541 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconAutomaticSpeechRecognition.svelte @@ -0,0 +1,23 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconAzureML.svelte b/packages/widgets/src/lib/components/Icons/IconAzureML.svelte new file mode 100644 index 000000000..3fc373b4b --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconAzureML.svelte @@ -0,0 +1,40 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconCaretDown.svelte b/packages/widgets/src/lib/components/Icons/IconCaretDown.svelte new file mode 100644 index 000000000..ae3574382 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconCaretDown.svelte @@ -0,0 +1,19 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconCaretDownV2.svelte b/packages/widgets/src/lib/components/Icons/IconCaretDownV2.svelte new file mode 100644 index 000000000..f8b4baac5 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconCaretDownV2.svelte @@ -0,0 +1,11 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconCode.svelte b/packages/widgets/src/lib/components/Icons/IconCode.svelte new file mode 100644 index 000000000..a84e7b970 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconCode.svelte @@ -0,0 +1,21 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconConversational.svelte b/packages/widgets/src/lib/components/Icons/IconConversational.svelte new file mode 100644 index 000000000..38e01c10b --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconConversational.svelte @@ -0,0 +1,23 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconCross.svelte b/packages/widgets/src/lib/components/Icons/IconCross.svelte new file mode 100644 index 000000000..ae6b04ffc --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconCross.svelte @@ -0,0 +1,21 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconDepthEstimation.svelte b/packages/widgets/src/lib/components/Icons/IconDepthEstimation.svelte new file mode 100644 index 000000000..83362801b --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconDepthEstimation.svelte @@ -0,0 +1,10 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconDocumentQuestionAnswering.svelte b/packages/widgets/src/lib/components/Icons/IconDocumentQuestionAnswering.svelte new file mode 100644 index 000000000..6c1c84297 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconDocumentQuestionAnswering.svelte @@ -0,0 +1,13 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconFeatureExtraction.svelte b/packages/widgets/src/lib/components/Icons/IconFeatureExtraction.svelte new file mode 100644 index 000000000..c1806a76a --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconFeatureExtraction.svelte @@ -0,0 +1,21 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconFile.svelte b/packages/widgets/src/lib/components/Icons/IconFile.svelte new file mode 100644 index 000000000..0d50da5d5 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconFile.svelte @@ -0,0 +1,21 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconFillMask.svelte b/packages/widgets/src/lib/components/Icons/IconFillMask.svelte new file mode 100644 index 000000000..e096d5a8c --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconFillMask.svelte @@ -0,0 +1,27 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconGraphML.svelte b/packages/widgets/src/lib/components/Icons/IconGraphML.svelte new file mode 100644 index 000000000..6000b5ab3 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconGraphML.svelte @@ -0,0 +1,23 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconImageClassification.svelte b/packages/widgets/src/lib/components/Icons/IconImageClassification.svelte new file mode 100644 index 000000000..fa83eb205 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconImageClassification.svelte @@ -0,0 +1,23 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconImageSegmentation.svelte b/packages/widgets/src/lib/components/Icons/IconImageSegmentation.svelte new file mode 100644 index 000000000..d84e55c74 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconImageSegmentation.svelte @@ -0,0 +1,24 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconImageToImage.svelte b/packages/widgets/src/lib/components/Icons/IconImageToImage.svelte new file mode 100644 index 000000000..1ea332d30 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconImageToImage.svelte @@ -0,0 +1,25 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconImageToText.svelte b/packages/widgets/src/lib/components/Icons/IconImageToText.svelte new file mode 100644 index 000000000..8263c0801 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconImageToText.svelte @@ -0,0 +1,28 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconInfo.svelte b/packages/widgets/src/lib/components/Icons/IconInfo.svelte new file mode 100644 index 000000000..6b5a9b1f9 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconInfo.svelte @@ -0,0 +1,20 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconLightning.svelte b/packages/widgets/src/lib/components/Icons/IconLightning.svelte new file mode 100644 index 000000000..91d87c2cc --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconLightning.svelte @@ -0,0 +1,18 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconMagicWand.svelte b/packages/widgets/src/lib/components/Icons/IconMagicWand.svelte new file mode 100644 index 000000000..7aa63b2a2 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconMagicWand.svelte @@ -0,0 +1,22 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconMaximize.svelte b/packages/widgets/src/lib/components/Icons/IconMaximize.svelte new file mode 100644 index 000000000..872037067 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconMaximize.svelte @@ -0,0 +1,23 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconMicrophone.svelte b/packages/widgets/src/lib/components/Icons/IconMicrophone.svelte new file mode 100644 index 000000000..d46385493 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconMicrophone.svelte @@ -0,0 +1,25 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconObjectDetection.svelte b/packages/widgets/src/lib/components/Icons/IconObjectDetection.svelte new file mode 100644 index 000000000..ae1e1a7a6 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconObjectDetection.svelte @@ -0,0 +1,25 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconQuestionAnswering.svelte b/packages/widgets/src/lib/components/Icons/IconQuestionAnswering.svelte new file mode 100644 index 000000000..b57d90ac4 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconQuestionAnswering.svelte @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/packages/widgets/src/lib/components/Icons/IconReinforcementLearning.svelte b/packages/widgets/src/lib/components/Icons/IconReinforcementLearning.svelte new file mode 100644 index 000000000..802dc2437 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconReinforcementLearning.svelte @@ -0,0 +1,23 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconRobotics.svelte b/packages/widgets/src/lib/components/Icons/IconRobotics.svelte new file mode 100644 index 000000000..6f354638e --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconRobotics.svelte @@ -0,0 +1,22 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconRow.svelte b/packages/widgets/src/lib/components/Icons/IconRow.svelte new file mode 100644 index 000000000..7710d2b52 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconRow.svelte @@ -0,0 +1,16 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconSentenceSimilarity.svelte b/packages/widgets/src/lib/components/Icons/IconSentenceSimilarity.svelte new file mode 100644 index 000000000..def158c73 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconSentenceSimilarity.svelte @@ -0,0 +1,25 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconSpin.svelte b/packages/widgets/src/lib/components/Icons/IconSpin.svelte new file mode 100644 index 000000000..2afa35d83 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconSpin.svelte @@ -0,0 +1,30 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconSummarization.svelte b/packages/widgets/src/lib/components/Icons/IconSummarization.svelte new file mode 100644 index 000000000..8c0ee2fc5 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconSummarization.svelte @@ -0,0 +1,22 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconTableQuestionAnswering.svelte b/packages/widgets/src/lib/components/Icons/IconTableQuestionAnswering.svelte new file mode 100644 index 000000000..c11027345 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconTableQuestionAnswering.svelte @@ -0,0 +1,21 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconTabularClassification.svelte b/packages/widgets/src/lib/components/Icons/IconTabularClassification.svelte new file mode 100644 index 000000000..d4ce233b1 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconTabularClassification.svelte @@ -0,0 +1,22 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconTabularRegression.svelte b/packages/widgets/src/lib/components/Icons/IconTabularRegression.svelte new file mode 100644 index 000000000..ed4355c5d --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconTabularRegression.svelte @@ -0,0 +1,20 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconText2textGeneration.svelte b/packages/widgets/src/lib/components/Icons/IconText2textGeneration.svelte new file mode 100644 index 000000000..ed5a2c6c7 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconText2textGeneration.svelte @@ -0,0 +1,27 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconTextClassification.svelte b/packages/widgets/src/lib/components/Icons/IconTextClassification.svelte new file mode 100644 index 000000000..e747e6d2d --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconTextClassification.svelte @@ -0,0 +1,33 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconTextGeneration.svelte b/packages/widgets/src/lib/components/Icons/IconTextGeneration.svelte new file mode 100644 index 000000000..fa0153e0d --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconTextGeneration.svelte @@ -0,0 +1,25 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconTextToImage.svelte b/packages/widgets/src/lib/components/Icons/IconTextToImage.svelte new file mode 100644 index 000000000..a7adab86f --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconTextToImage.svelte @@ -0,0 +1,25 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconTextToSpeech.svelte b/packages/widgets/src/lib/components/Icons/IconTextToSpeech.svelte new file mode 100644 index 000000000..7c533cfcb --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconTextToSpeech.svelte @@ -0,0 +1,23 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconTextToVideo.svelte b/packages/widgets/src/lib/components/Icons/IconTextToVideo.svelte new file mode 100644 index 000000000..3082ea2e6 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconTextToVideo.svelte @@ -0,0 +1,23 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconTokenClassification.svelte b/packages/widgets/src/lib/components/Icons/IconTokenClassification.svelte new file mode 100644 index 000000000..27f3d3625 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconTokenClassification.svelte @@ -0,0 +1,33 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconTranslation.svelte b/packages/widgets/src/lib/components/Icons/IconTranslation.svelte new file mode 100644 index 000000000..c0d344420 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconTranslation.svelte @@ -0,0 +1,24 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconUnconditionalImageGeneration.svelte b/packages/widgets/src/lib/components/Icons/IconUnconditionalImageGeneration.svelte new file mode 100644 index 000000000..880d6ae9c --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconUnconditionalImageGeneration.svelte @@ -0,0 +1,22 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconVideoClassification.svelte b/packages/widgets/src/lib/components/Icons/IconVideoClassification.svelte new file mode 100644 index 000000000..669a372ca --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconVideoClassification.svelte @@ -0,0 +1,24 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconVoiceActivityDetection.svelte b/packages/widgets/src/lib/components/Icons/IconVoiceActivityDetection.svelte new file mode 100644 index 000000000..c896fee50 --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconVoiceActivityDetection.svelte @@ -0,0 +1,23 @@ + + + diff --git a/packages/widgets/src/lib/components/Icons/IconZeroShotClassification.svelte b/packages/widgets/src/lib/components/Icons/IconZeroShotClassification.svelte new file mode 100644 index 000000000..ebbe940ef --- /dev/null +++ b/packages/widgets/src/lib/components/Icons/IconZeroShotClassification.svelte @@ -0,0 +1,51 @@ + + + diff --git a/packages/widgets/src/lib/components/InferenceWidget/InferenceWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/InferenceWidget.svelte new file mode 100644 index 000000000..faf06bf8e --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/InferenceWidget.svelte @@ -0,0 +1,100 @@ + + +{#if widgetComponent} + +{/if} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetAddSentenceBtn/WidgetAddSentenceBtn.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetAddSentenceBtn/WidgetAddSentenceBtn.svelte new file mode 100644 index 000000000..7eca76ae4 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetAddSentenceBtn/WidgetAddSentenceBtn.svelte @@ -0,0 +1,12 @@ + + +{#if !isDisabled} + + +{/if} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetAudioTrack/WidgetAudioTrack.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetAudioTrack/WidgetAudioTrack.svelte new file mode 100644 index 000000000..b17f29a56 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetAudioTrack/WidgetAudioTrack.svelte @@ -0,0 +1,17 @@ + + +
+ {#if $$slots.default} + + {:else if label.length} +
{label}
+ {/if} + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetBloomDecoding/WidgetBloomDecoding.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetBloomDecoding/WidgetBloomDecoding.svelte new file mode 100644 index 000000000..19d630645 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetBloomDecoding/WidgetBloomDecoding.svelte @@ -0,0 +1,55 @@ + + + (isPromptTipOpen = false)} /> + +
+
+
+ sampling + +
+
+
+
+
+ greedy +
+
+ + (isPromptTipOpen = true)} + >ⓘ BLOOM prompting tips + {#if isPromptTipOpen} +
+ A good prompt: Do NOT talk to Bloom as an entity, it's not a chatbot but a webpage/blog/article completion + model. For the best behaviours: MIMIC a few words of a webpage similar to the content you want to generate. + Start a sentence as if YOU were writing a blog, webpage, math post, coding article and Bloom will generate a + coherent follow-up. +
+ {/if} +
+
+

+ {description} +

+
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetCheckbox/WidgetCheckbox.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetCheckbox/WidgetCheckbox.svelte new file mode 100644 index 000000000..e4e975e81 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetCheckbox/WidgetCheckbox.svelte @@ -0,0 +1,17 @@ + + + + + + + diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetDropzone/WidgetDropzone.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetDropzone/WidgetDropzone.svelte new file mode 100644 index 000000000..3cfb0f007 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetDropzone/WidgetDropzone.svelte @@ -0,0 +1,89 @@ + + + + +
{ + fileInput.click(); + }} + on:dragenter={() => { + isDragging = true; + }} + on:dragleave={() => { + isDragging = false; + }} + on:dragover|preventDefault + on:drop|preventDefault={onDrop} +> + {#if !imgSrc && !isDisabled} + {label} + {:else} +
+ +
+ {/if} + {#if isLoading} +
+ +
+ {/if} +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetExample.ts b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetExample.ts new file mode 100644 index 000000000..6428e7b0a --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetExample.ts @@ -0,0 +1,114 @@ +type TableData = Record; + +//#region outputs +export type WidgetExampleOutputLabels = Array<{ label: string; score: number }>; +export interface WidgetExampleOutputAnswerScore { + answer: string; + score: number; +} +export interface WidgetExampleOutputText { + text: string; +} +export interface WidgetExampleOutputUrl { + url: string; +} + +export type WidgetExampleOutput = + | WidgetExampleOutputLabels + | WidgetExampleOutputAnswerScore + | WidgetExampleOutputText + | WidgetExampleOutputUrl; +//#endregion + +export interface WidgetExampleBase { + example_title?: string; + group?: string; + /** + * Potential overrides to API parameters for this specific example + * (takes precedences over the model card metadata's inference.parameters) + */ + parameters?: { + /// token-classification + aggregation_strategy?: string; + /// text-generation + top_k?: number; + top_p?: number; + temperature?: number; + max_new_tokens?: number; + do_sample?: boolean; + /// text-to-image + negative_prompt?: string; + guidance_scale?: number; + num_inference_steps?: number; + }; + /** + * Optional output + */ + output?: TOutput; +} + +export interface WidgetExampleTextInput extends WidgetExampleBase { + text: string; +} + +export interface WidgetExampleTextAndContextInput + extends WidgetExampleTextInput { + context: string; +} + +export interface WidgetExampleTextAndTableInput extends WidgetExampleTextInput { + table: TableData; +} + +export interface WidgetExampleAssetInput extends WidgetExampleBase { + src: string; +} +export interface WidgetExampleAssetAndPromptInput + extends WidgetExampleAssetInput { + prompt: string; +} + +export type WidgetExampleAssetAndTextInput = WidgetExampleAssetInput & + WidgetExampleTextInput; + +export type WidgetExampleAssetAndZeroShotInput = WidgetExampleAssetInput & + WidgetExampleZeroShotTextInput; + +export interface WidgetExampleStructuredDataInput extends WidgetExampleBase { + structured_data: TableData; +} + +export interface WidgetExampleTableDataInput extends WidgetExampleBase { + table: TableData; +} + +export interface WidgetExampleZeroShotTextInput extends WidgetExampleTextInput { + text: string; + candidate_labels: string; + multi_class: boolean; +} + +export interface WidgetExampleSentenceSimilarityInput + extends WidgetExampleBase { + source_sentence: string; + sentences: string[]; +} + +//#endregion + +export type WidgetExample = + | WidgetExampleTextInput + | WidgetExampleTextAndContextInput + | WidgetExampleTextAndTableInput + | WidgetExampleAssetInput + | WidgetExampleAssetAndPromptInput + | WidgetExampleAssetAndTextInput + | WidgetExampleAssetAndZeroShotInput + | WidgetExampleStructuredDataInput + | WidgetExampleTableDataInput + | WidgetExampleZeroShotTextInput + | WidgetExampleSentenceSimilarityInput; + +type KeysOfUnion = T extends unknown ? keyof T : never; + +export type WidgetExampleAttribute = KeysOfUnion; diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetFileInput/WidgetFileInput.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetFileInput/WidgetFileInput.svelte new file mode 100644 index 000000000..9e4c6a54f --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetFileInput/WidgetFileInput.svelte @@ -0,0 +1,56 @@ + + +{#if !isDisabled} +
{ + isDragging = true; + }} + on:dragover|preventDefault + on:dragleave={() => { + isDragging = false; + }} + on:drop|preventDefault={(e) => { + isDragging = false; + fileInput.files = e.dataTransfer?.files ?? null; + onChange(); + }} + > + +
+{/if} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetFooter/WidgetFooter.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetFooter/WidgetFooter.svelte new file mode 100644 index 000000000..1ff674949 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetFooter/WidgetFooter.svelte @@ -0,0 +1,33 @@ + + +
+ {#if !isDisabled} + + {/if} + +
+{#if outputJson && isOutputJsonVisible} +
{outputJson}
+{/if} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetHeader/WidgetHeader.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetHeader/WidgetHeader.svelte new file mode 100644 index 000000000..a899908a4 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetHeader/WidgetHeader.svelte @@ -0,0 +1,49 @@ + + +
+ {#if !noTitle} + {#if title} +
+ {title} +
+ {:else} +
+ {#if !isDisabled} + + Inference API + {:else} + Inference Examples + {/if} +
+ + + + {/if} + {/if} +
+
+ {#if pipeline && task} + + + + {/if} + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetInfo/WidgetInfo.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetInfo/WidgetInfo.svelte new file mode 100644 index 000000000..f374dabef --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetInfo/WidgetInfo.svelte @@ -0,0 +1,116 @@ + + +
+
+ {#if model.id === "bigscience/bloom"} +
+
+ Powered by  + AzureML +
+
+
+ {@html getStatusReport(modelLoadInfo, azureState, true)} +
+
+ {:else if computeTime} + Computation time on {getComputeTypeMsg()}: {computeTime} + {:else if (model.inference === InferenceDisplayability.Yes || model.pipeline_tag === "reinforcement-learning") && !modelTooBig} + {@html getStatusReport(modelLoadInfo, state)} + {:else if model.inference === InferenceDisplayability.ExplicitOptOut} + Inference API has been turned off for this model. + {:else if model.inference === InferenceDisplayability.CustomCode} + Inference API does not yet support model repos that contain custom code. + {:else if model.inference === InferenceDisplayability.LibraryNotDetected} + + Unable to determine this model's library. Check the + + docs + . + + {:else if model.inference === InferenceDisplayability.PipelineNotDetected} + + Unable to determine this model’s pipeline type. Check the + + docs + . + + {:else if model.inference === InferenceDisplayability.PipelineLibraryPairNotSupported} + + Inference API does not yet support {model.library_name} models for this pipeline type. + + {:else if modelTooBig} + + Model is too large to load onto the free Inference API. To try the model, launch it on Inference Endpoints + instead. + + {:else} + + + Inference API is disabled for an unknown reason. Please open a + Discussion in the Community tab. + + {/if} +
+ {#if error} +
{error}
+ {/if} +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetInputSamples/WidgetInputSamples.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetInputSamples/WidgetInputSamples.svelte new file mode 100644 index 000000000..be37c4b60 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetInputSamples/WidgetInputSamples.svelte @@ -0,0 +1,98 @@ + + + + +
+ +
+
{title}
+ +
+ + {#if isOptionsVisible} +
+
+ {#each inputSamples as { example_title }, i} + +
_previewInputSample(i)} + on:click={() => _applyInputSample(i)} + > + {example_title} +
+ {/each} +
+
+ {/if} +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetInputSamplesGroup/WidgetInputSamplesGroup.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetInputSamplesGroup/WidgetInputSamplesGroup.svelte new file mode 100644 index 000000000..97283b988 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetInputSamplesGroup/WidgetInputSamplesGroup.svelte @@ -0,0 +1,81 @@ + + + + +
+ +
+
{title}
+ +
+ + {#if isOptionsVisible} +
+
+ {#each inputGroups as inputGroup, i} + +
chooseInputGroup(i)} + > + {inputGroup} +
+ {/each} +
+
+ {/if} +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetLabel/WidgetLabel.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetLabel/WidgetLabel.svelte new file mode 100644 index 000000000..03f1e5c9e --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetLabel/WidgetLabel.svelte @@ -0,0 +1,13 @@ + + + diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetModelLoading/WidgetModelLoading.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetModelLoading/WidgetModelLoading.svelte new file mode 100644 index 000000000..5c7e5f761 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetModelLoading/WidgetModelLoading.svelte @@ -0,0 +1,38 @@ + + +
+
+
+ + Model is loading +
+
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOuputConvoBubble/WidgetOutputConvoBubble.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOuputConvoBubble/WidgetOutputConvoBubble.svelte new file mode 100644 index 000000000..31ab4efa5 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOuputConvoBubble/WidgetOutputConvoBubble.svelte @@ -0,0 +1,12 @@ + + +
+ {text} +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputChart/WidgetOutputChart.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputChart/WidgetOutputChart.svelte new file mode 100644 index 000000000..a1fe65892 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputChart/WidgetOutputChart.svelte @@ -0,0 +1,65 @@ + + + +{#if output.length} +
+ + {#each output as { score, color }, index} + +
mouseover(index)} + on:mouseout={mouseout} + > +
+
+ {text(output[index])} +
+ {score.toFixed(3)} +
+ {/each} +
+{/if} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputConvo/WidgetOutputConvo.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputConvo/WidgetOutputConvo.svelte new file mode 100644 index 000000000..5a14cf9db --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputConvo/WidgetOutputConvo.svelte @@ -0,0 +1,33 @@ + + +
+
+ Input a message to start chatting with + {modelId}. +
+
+ {#each output as exchange} + + + {/each} +
+
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputTableQA/WidgetOutputTableQA.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputTableQA/WidgetOutputTableQA.svelte new file mode 100644 index 000000000..410fc55c3 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputTableQA/WidgetOutputTableQA.svelte @@ -0,0 +1,52 @@ + + +
+ {#if isAnswerOnlyOutput} + {output.answer} + {:else} + + {#if output.cells.length} + {output.cells.length} + match{output.cells.length > 1 ? "es" : ""} + : + {:else} + No matches + {/if} + + {#if output.cells.length} + {#each output.cells as answer} + {answer} + {/each} + {#if output.aggregator !== "NONE"} + {output.aggregator} + {/if} + {/if} + {/if} +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputText/WidgetOutputText.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputText/WidgetOutputText.svelte new file mode 100644 index 000000000..e1d051506 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputText/WidgetOutputText.svelte @@ -0,0 +1,10 @@ + + +{#if output.length} +

+ {output} +

+{/if} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputTokens/WidgetOutputTokens.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputTokens/WidgetOutputTokens.svelte new file mode 100644 index 000000000..58343a2cc --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetOutputTokens/WidgetOutputTokens.svelte @@ -0,0 +1,94 @@ + + +{#if text && output.length} + +
+ {@html render(text, output)} +
+{/if} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetQuickInput/WidgetQuickInput.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetQuickInput/WidgetQuickInput.svelte new file mode 100644 index 000000000..3a60295b8 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetQuickInput/WidgetQuickInput.svelte @@ -0,0 +1,29 @@ + + +
+ + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRadio/WidgetRadio.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRadio/WidgetRadio.svelte new file mode 100644 index 000000000..7cfb06a49 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRadio/WidgetRadio.svelte @@ -0,0 +1,21 @@ + + + + + + + diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRealtimeRecorder/Recorder.ts b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRealtimeRecorder/Recorder.ts new file mode 100644 index 000000000..be0e295d5 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRealtimeRecorder/Recorder.ts @@ -0,0 +1,103 @@ +export default class Recorder { + // see developers.google.com/web/updates/2016/01/mediarecorder + type: "audio" | "video" = "audio"; + private apiToken: string | undefined; + private audioContext: AudioContext | undefined; + private isLoggedIn = false; + private isModelLoaded = false; + private isEmptyBuffer = false; + private modelId: string; + private onError: (err: string) => void; + private updateModelLoading: (isLoading: boolean, estimatedTime?: number) => void; + private renderText: (txt: string) => void; + private renderWarning: (warning: string) => void; + private socket: WebSocket | undefined; + private stream: MediaStream | undefined; + + constructor( + modelId: string, + apiToken: string | undefined, + renderText: (txt: string) => void, + renderWarning: (warning: string) => void, + onError: (err: string) => void, + updateModelLoading: (isLoading: boolean, estimatedTime?: number) => void + ) { + this.modelId = modelId; + this.apiToken = apiToken || ""; + this.renderText = renderText; + this.renderWarning = renderWarning; + this.onError = onError; + this.updateModelLoading = updateModelLoading; + } + + async start(): Promise { + const constraints: MediaStreamConstraints = this.type === "video" ? { audio: true, video: true } : { audio: true }; + this.stream = await navigator.mediaDevices.getUserMedia(constraints); + + this.socket = new WebSocket(`wss://api-inference.huggingface.co/asr/live/cpu/${this.modelId}`); + + this.socket.onerror = () => { + this.onError("Webscoket connection error"); + }; + + this.socket.onopen = () => { + this.socket?.send(`Bearer ${this.apiToken}`); + }; + + this.updateModelLoading(true); + + this.socket.onmessage = (e: MessageEvent) => { + const data = JSON.parse(e.data); + if (data.type === "status" && data.message === "Successful login") { + this.isLoggedIn = true; + } else if (data.type === "status" && !!data.estimated_time && !this.isModelLoaded) { + this.updateModelLoading(true, data.estimated_time); + } else { + // data.type === "results" + this.isModelLoaded = true; + if (data.text) { + this.renderText(data.text); + } else if (!this.isEmptyBuffer) { + this.renderWarning("result was empty"); + } + } + }; + + this.audioContext = new AudioContext(); + await this.audioContext.audioWorklet.addModule("/audioProcessor.js"); + const microphone = this.audioContext.createMediaStreamSource(this.stream); + const dataExtractor = new AudioWorkletNode(this.audioContext, "AudioDataExtractor"); + microphone.connect(dataExtractor).connect(this.audioContext.destination); + + dataExtractor.port.onmessage = (event) => { + const { buffer, sampling_rate: samplingRate } = event.data; + this.isEmptyBuffer = buffer.reduce((sum: number, x: number) => sum + x) === 0; + if (this.isModelLoaded && this.isEmptyBuffer) { + this.renderWarning("🎤 input is empty: try speaking louder 🗣️ & make sure correct mic source is selected"); + } + const base64: string = btoa(String.fromCharCode(...new Uint8Array(buffer.buffer))); + const message = { + raw: base64, + sampling_rate: samplingRate, + }; + if (this.isLoggedIn) { + try { + this.socket?.send(JSON.stringify(message)); + } catch (e) { + this.onError(`Error sending data to websocket: ${e}`); + } + } + }; + } + + stop(): void { + this.isLoggedIn = false; + void this.audioContext?.close(); + this.socket?.close(); + if (this.stream) { + for (const t of this.stream.getTracks()) { + t.stop(); + } + } + } +} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRealtimeRecorder/WidgetRealtimeRecorder.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRealtimeRecorder/WidgetRealtimeRecorder.svelte new file mode 100644 index 000000000..6056084c2 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRealtimeRecorder/WidgetRealtimeRecorder.svelte @@ -0,0 +1,98 @@ + + + + +{#if isRecording} +
+ {#if warning} +

{warning}

+ {:else} +

{txt}

+ {/if} +
+{/if} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRecorder/Recorder.ts b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRecorder/Recorder.ts new file mode 100644 index 000000000..39bed256c --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRecorder/Recorder.ts @@ -0,0 +1,69 @@ +import { delay } from "$lib/utils/ViewUtils.js"; + +export default class Recorder { + // see developers.google.com/web/updates/2016/01/mediarecorder + type: "audio" | "video" = "audio"; + private stream?: MediaStream; + private mediaRecorder?: MediaRecorder; + private recordedBlobs: Blob[] = []; + public outputBlob?: Blob; + + get desiredMimeType(): string { + return this.type === "video" ? "video/webm" : "audio/webm"; + } + get mimeType(): string { + if (!this.mediaRecorder) { + throw new Error("MediaRecorder not initialized"); + } + return this.mediaRecorder.mimeType; + } + async start(): Promise { + this.recordedBlobs = []; + + const constraints: MediaStreamConstraints = this.type === "video" ? { audio: true, video: true } : { audio: true }; + this.stream = await navigator.mediaDevices.getUserMedia(constraints); + this.startRecording(); + } + private startRecording() { + if (!this.stream) { + throw new Error("Stream not initialized"); + } + this.outputBlob = undefined; + this.mediaRecorder = new MediaRecorder(this.stream, { + mimeType: this.desiredMimeType, + }); + this.mediaRecorder.onstop = this.handleStop.bind(this); + this.mediaRecorder.ondataavailable = this.handleDataAvailable.bind(this); + this.mediaRecorder.start(10); // timeslice in ms + } + handleStop(): void {} + handleDataAvailable(evt: BlobEvent): void { + if (evt.data && evt.data.size > 0) { + this.recordedBlobs.push(evt.data); + } + } + async stopRecording(): Promise { + if (this.mediaRecorder) { + this.mediaRecorder.stop(); + } + if (this.stream) { + for (const t of this.stream.getTracks()) { + t.stop(); // Stop stream. + } + } + + // handle stopRecording gets called before this.mediaRecorder is initialized + if (!this.mediaRecorder) { + return new Blob(this.recordedBlobs); + } + + await delay(30); + // Wait for the last blob in handleDataAvailable. + // Alternative: hook into `onstop` event. + const superBuffer = new Blob(this.recordedBlobs, { + type: this.mimeType, + }); + this.outputBlob = superBuffer; + return superBuffer; + } +} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRecorder/WidgetRecorder.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRecorder/WidgetRecorder.svelte new file mode 100644 index 000000000..05de83da5 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetRecorder/WidgetRecorder.svelte @@ -0,0 +1,67 @@ + + + diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetShortcutRunLabel/WidgetShortcutRunLabel.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetShortcutRunLabel/WidgetShortcutRunLabel.svelte new file mode 100644 index 000000000..322663467 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetShortcutRunLabel/WidgetShortcutRunLabel.svelte @@ -0,0 +1,22 @@ + + +{#if !isDisabled} + +{/if} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetState/WidgetState.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetState/WidgetState.svelte new file mode 100644 index 000000000..94be11f7b --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetState/WidgetState.svelte @@ -0,0 +1,17 @@ + + +
+
+
+ This model is currently loaded and running on the Inference API. +
+
+ ⚠️ This model could not be loaded by the inference API. ⚠️ +
+
+ This model can be loaded on the Inference API on-demand. +
+
+
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetSubmitBtn/WidgetSubmitBtn.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetSubmitBtn/WidgetSubmitBtn.svelte new file mode 100644 index 000000000..6fc03b2b1 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetSubmitBtn/WidgetSubmitBtn.svelte @@ -0,0 +1,37 @@ + + + + +{#if !isDisabled} + +{/if} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTableInput/WidgetTableInput.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTableInput/WidgetTableInput.svelte new file mode 100644 index 000000000..765ef6d23 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTableInput/WidgetTableInput.svelte @@ -0,0 +1,112 @@ + + +
+ {#if table.length > 1} + + + + {#each table[0] as header, x} + + {/each} + + + + {#each table.slice(1) as row, y} + + {#each row as cell, x} + + {/each} + + {/each} + +
editCell(e, [x, 0])} + > + {header} +
editCell(e, [x, y + 1])}>{cell}
+ {/if} +
+ +
+ {#if canAddRow} + + {/if} + {#if canAddCol} + + {/if} + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTextInput/WidgetTextInput.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTextInput/WidgetTextInput.svelte new file mode 100644 index 000000000..50665b478 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTextInput/WidgetTextInput.svelte @@ -0,0 +1,20 @@ + + + + + + + diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTextarea/WidgetTextarea.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTextarea/WidgetTextarea.svelte new file mode 100644 index 000000000..2f56f7314 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTextarea/WidgetTextarea.svelte @@ -0,0 +1,106 @@ + + + + + + + + + + diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTimer/WidgetTimer.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTimer/WidgetTimer.svelte new file mode 100644 index 000000000..2d41e1ac5 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTimer/WidgetTimer.svelte @@ -0,0 +1,35 @@ + + +{#if shouldDisplay && !isDisabled} + {counterHuman} +{/if} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetWrapper/WidgetWrapper.svelte b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetWrapper/WidgetWrapper.svelte new file mode 100644 index 000000000..4d171a03b --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/WidgetWrapper/WidgetWrapper.svelte @@ -0,0 +1,159 @@ + + +{#if isDisabled && !inputSamples.length} + + +{:else} +
+ {#if isMaximized} + + {/if} + + {#if !!inputGroups.length} +
+ + {#if inputGroups.length > 1} + group)} + /> + {/if} + +
+ {/if} +
+ + + {#if modelLoading.isLoading} + + {/if} + + +
+{/if} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/consts.ts b/packages/widgets/src/lib/components/InferenceWidget/shared/consts.ts new file mode 100644 index 000000000..1ec7359bf --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/consts.ts @@ -0,0 +1,37 @@ +/** + * Color palette for obj-det & img-seg widgets + */ +export const COLORS = [ + { + color: "red", + hex: "#f87171", + }, + { + color: "green", + hex: "#4ade80", + }, + { + color: "yellow", + hex: "#facc15", + }, + { + color: "blue", + hex: "#60a5fa", + }, + { + color: "orange", + hex: "#fb923c", + }, + { + color: "purple", + hex: "#c084fc", + }, + { + color: "cyan", + hex: "#22d3ee", + }, + { + color: "lime", + hex: "#a3e635", + }, +] as const; diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/helpers.ts b/packages/widgets/src/lib/components/InferenceWidget/shared/helpers.ts new file mode 100644 index 000000000..d34113757 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/helpers.ts @@ -0,0 +1,251 @@ +import type { ModelData } from "$lib/interfaces/Types.js"; +import { randomItem, parseJSON } from "../../../utils/ViewUtils.js"; +import type { WidgetExample, WidgetExampleAttribute } from "./WidgetExample.js"; +import type { ModelLoadInfo, TableData } from "./types.js"; +import { LoadState } from "./types.js"; + +const KEYS_TEXT: WidgetExampleAttribute[] = ["text", "context", "candidate_labels"]; +const KEYS_TABLE: WidgetExampleAttribute[] = ["table", "structured_data"]; +type QueryParamVal = string | null | boolean | (string | number)[][]; + +export function getQueryParamVal(key: WidgetExampleAttribute): QueryParamVal { + const searchParams = new URL(window.location.href).searchParams; + const value = searchParams.get(key); + if (KEYS_TEXT.includes(key)) { + return value; + } else if (KEYS_TABLE.includes(key)) { + const table = convertDataToTable((parseJSON(value) as TableData) ?? {}); + return table; + } else if (key === "multi_class") { + return value === "true"; + } + return value; +} + +export function getWidgetExample( + model: ModelData, + validateExample: (sample: WidgetExample) => sample is TWidgetExample +): TWidgetExample | undefined { + const validExamples = model.widgetData?.filter( + (sample): sample is TWidgetExample => sample && validateExample(sample) + ); + return validExamples?.length ? randomItem(validExamples) : undefined; +} + +// Update current url search params, keeping existing keys intact. +export function updateUrl(obj: Partial>): void { + if (!window) { + return; + } + + const sp = new URL(window.location.href).searchParams; + for (const [k, v] of Object.entries(obj)) { + if (v === undefined) { + sp.delete(k); + } else { + sp.set(k, v); + } + } + const path = `${window.location.pathname}?${sp.toString()}`; + window.history.replaceState(null, "", path); +} + +// Run through our own proxy to bypass CORS: +function proxify(url: string): string { + return url.startsWith(`http://localhost`) || new URL(url).host === window.location.host + ? url + : `https://widgets.hf.co/proxy?url=${url}`; +} + +// Get BLOB from a given URL after proxifying the URL +export async function getBlobFromUrl(url: string): Promise { + const proxiedUrl = proxify(url); + const res = await fetch(proxiedUrl); + const blob = await res.blob(); + return blob; +} + +interface Success { + computeTime: string; + output: T; + outputJson: string; + response: Response; + status: "success"; +} + +interface LoadingModel { + error: string; + estimatedTime: number; + status: "loading-model"; +} + +interface Error { + error: string; + status: "error"; +} + +interface CacheNotFound { + status: "cache not found"; +} + +type Result = Success | LoadingModel | Error | CacheNotFound; + +export async function callInferenceApi( + url: string, + repoId: string, + requestBody: Record, + apiToken = "", + outputParsingFn: (x: unknown) => T, + waitForModel = false, // If true, the server will only respond once the model has been loaded on the inference API, + includeCredentials = false, + isOnLoadCall = false, // If true, the server will try to answer from cache and not do anything if not + useCache = true +): Promise> { + const contentType = + "file" in requestBody && + requestBody["file"] && + typeof requestBody["file"] === "object" && + "type" in requestBody["file"] && + typeof requestBody["file"]["type"] === "string" + ? requestBody["file"]["type"] + : "application/json"; + + const headers = new Headers(); + headers.set("Content-Type", contentType); + if (apiToken) { + headers.set("Authorization", `Bearer ${apiToken}`); + } + if (waitForModel) { + headers.set("X-Wait-For-Model", "true"); + } + if (useCache === false) { + headers.set("X-Use-Cache", "false"); + } + if (isOnLoadCall) { + headers.set("X-Load-Model", "0"); + } + + const reqBody: File | string = + "file" in requestBody && requestBody["file"] instanceof File ? requestBody.file : JSON.stringify(requestBody); + + const response = await fetch(`${url}/models/${repoId}`, { + method: "POST", + body: reqBody, + headers, + credentials: includeCredentials ? "include" : "same-origin", + }); + + if (response.ok) { + // Success + const computeTime = response.headers.has("x-compute-time") + ? `${response.headers.get("x-compute-time")} s` + : `cached`; + const isMediaContent = (response.headers.get("content-type")?.search(/^(?:audio|image)/i) ?? -1) !== -1; + + const body = !isMediaContent ? await response.json() : await response.blob(); + + try { + const output = outputParsingFn(body); + const outputJson = !isMediaContent ? JSON.stringify(body, null, 2) : ""; + return { computeTime, output, outputJson, response, status: "success" }; + } catch (e) { + if (isOnLoadCall && body.error === "not loaded yet") { + return { status: "cache not found" }; + } + // Invalid output + const error = `API Implementation Error: ${String(e).replace(/^Error: /, "")}`; + return { error, status: "error" }; + } + } else { + // Error + const bodyText = await response.text(); + const body = parseJSON>(bodyText) ?? {}; + + if ( + body["error"] && + response.status === 503 && + body["estimated_time"] !== null && + body["estimated_time"] !== undefined + ) { + // Model needs loading + return { error: String(body["error"]), estimatedTime: +body["estimated_time"], status: "loading-model" }; + } else { + // Other errors + const { status, statusText } = response; + return { + error: String(body["error"]) || String(body["traceback"]) || `${status} ${statusText}`, + status: "error", + }; + } + } +} + +export async function getModelLoadInfo( + url: string, + repoId: string, + includeCredentials = false +): Promise { + const response = await fetch(`${url}/status/${repoId}`, { + credentials: includeCredentials ? "include" : "same-origin", + }); + const output = await response.json(); + if (response.ok && typeof output === "object" && output.loaded !== undefined) { + // eslint-disable-next-line @typescript-eslint/naming-convention + const { state, compute_type } = output; + return { compute_type, state }; + } else { + console.warn(response.status, output.error); + return { state: LoadState.Error }; + } +} + +// Extend Inference API requestBody with user supplied Inference API parameters +export function addInferenceParameters(requestBody: Record, model: ModelData): void { + const inference = model?.cardData?.inference; + if (typeof inference === "object") { + const inferenceParameters = inference?.parameters; + if (inferenceParameters) { + if (requestBody.parameters) { + requestBody.parameters = { ...requestBody.parameters, ...inferenceParameters }; + } else { + requestBody.parameters = inferenceParameters; + } + } + } +} + +/* + * Converts table from [[Header0, Header1, Header2], [Column0Val0, Column1Val0, Column2Val0], ...] + * to {Header0: [ColumnVal0, ...], Header1: [Column1Val0, ...], Header2: [Column2Val0, ...]} + */ +export function convertTableToData(table: (string | number)[][]): TableData { + return Object.fromEntries( + table[0].map((cell, x) => { + return [ + cell, + table + .slice(1) + .flat() + .filter((_, i) => i % table[0].length === x) + .map((v) => String(v)), // some models can only handle strings (no numbers) + ]; + }) + ); +} + +/** + * Converts data from {Header0: [ColumnVal0, ...], Header1: [Column1Val0, ...], Header2: [Column2Val0, ...]} + * to [[Header0, Header1, Header2], [Column0Val0, Column1Val0, Column2Val0], ...] + */ +export function convertDataToTable(data: TableData): (string | number)[][] { + const dataArray = Object.entries(data); // [header, cell[]][] + const nbCols = dataArray.length; + const nbRows = (dataArray[0]?.[1]?.length ?? 0) + 1; + return Array(nbRows) + .fill("") + .map((_, y) => + Array(nbCols) + .fill("") + .map((__, x) => (y === 0 ? dataArray[x][0] : dataArray[x][1][y - 1])) + ); +} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/inputValidation.ts b/packages/widgets/src/lib/components/InferenceWidget/shared/inputValidation.ts new file mode 100644 index 000000000..06224afdd --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/inputValidation.ts @@ -0,0 +1,87 @@ +import type { + WidgetExample, + WidgetExampleAssetAndPromptInput, + WidgetExampleAssetAndTextInput, + WidgetExampleAssetAndZeroShotInput, + WidgetExampleAssetInput, + WidgetExampleSentenceSimilarityInput, + WidgetExampleStructuredDataInput, + WidgetExampleTableDataInput, + WidgetExampleTextAndContextInput, + WidgetExampleTextAndTableInput, + WidgetExampleTextInput, + WidgetExampleZeroShotTextInput, +} from "./WidgetExample.js"; + +export function isTextInput(sample: WidgetExample): sample is WidgetExampleTextInput { + return "text" in sample; +} + +export function isTextAndContextInput( + sample: WidgetExample +): sample is WidgetExampleTextAndContextInput { + return isTextInput(sample) && "context" in sample; +} + +export function isAssetInput(sample: WidgetExample): sample is WidgetExampleAssetInput { + return "src" in sample; +} + +export function isAssetAndPromptInput( + sample: WidgetExample +): sample is WidgetExampleAssetAndPromptInput { + return isAssetInput(sample) && "prompt" in sample && typeof sample.prompt === "string"; +} + +export function isAssetAndTextInput( + sample: WidgetExample +): sample is WidgetExampleAssetAndTextInput { + return isAssetInput(sample) && isTextInput(sample); +} + +export function isStructuredDataInput( + sample: WidgetExample +): sample is WidgetExampleStructuredDataInput { + return "structured_data" in sample; +} + +export function isTableDataInput( + sample: WidgetExample +): sample is WidgetExampleTableDataInput { + return "table" in sample; +} + +function _isZeroShotTextInput( + sample: WidgetExample +): sample is Exclude, "text"> { + return "candidate_labels" in sample && "multi_class" in sample; +} + +export function isZeroShotTextInput( + sample: WidgetExample +): sample is WidgetExampleZeroShotTextInput { + return isTextInput(sample) && _isZeroShotTextInput(sample); +} + +export function isSentenceSimilarityInput( + sample: WidgetExample +): sample is WidgetExampleSentenceSimilarityInput { + return "source_sentence" in sample && "sentences" in sample; +} + +export function isTextAndTableInput( + sample: WidgetExample +): sample is WidgetExampleTextAndTableInput { + return ( + isTextInput(sample) && + "table" in sample && + Array.isArray(sample.table) && + sample.table.every((r) => Array.isArray(r) && r.every((c) => typeof c === "string" || typeof c === "number")) + ); +} + +export function isAssetAndZeroShotInput( + sample: WidgetExample +): sample is WidgetExampleAssetAndZeroShotInput { + return isAssetInput(sample) && _isZeroShotTextInput(sample); +} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/outputValidation.ts b/packages/widgets/src/lib/components/InferenceWidget/shared/outputValidation.ts new file mode 100644 index 000000000..66b092a2c --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/outputValidation.ts @@ -0,0 +1,35 @@ +import type { + WidgetExampleOutputLabels, + WidgetExampleOutputAnswerScore, + WidgetExampleOutputText, + WidgetExampleOutputUrl, +} from "./WidgetExample.js"; + +export function isValidOutputLabels(arg: unknown): arg is WidgetExampleOutputLabels { + return Array.isArray(arg) && arg.every((x) => typeof x.label === "string" && typeof x.score === "number"); +} + +export function isValidOutputAnswerScore(arg: unknown): arg is WidgetExampleOutputAnswerScore { + return ( + !!arg && + typeof arg === "object" && + "answer" in arg && + typeof arg["answer"] === "string" && + "score" in arg && + typeof arg["score"] === "number" + ); +} + +export function isValidOutputText(arg: unknown): arg is WidgetExampleOutputText { + return !!arg && typeof arg === "object" && "text" in arg && typeof arg["text"] === "string"; +} + +export function isValidOutputUrl(arg: unknown): arg is WidgetExampleOutputUrl { + return ( + !!arg && + typeof arg === "object" && + "url" in arg && + typeof arg["url"] === "string" && + arg["url"].startsWith("https://") + ); +} diff --git a/packages/widgets/src/lib/components/InferenceWidget/shared/types.ts b/packages/widgets/src/lib/components/InferenceWidget/shared/types.ts new file mode 100644 index 000000000..70b6f4b41 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/shared/types.ts @@ -0,0 +1,68 @@ +import type { ModelData } from "../../../interfaces/Types.js"; +import type { WidgetExampleOutput } from "./WidgetExample.js"; + +export interface WidgetProps { + apiToken?: string; + apiUrl: string; + callApiOnMount: boolean; + model: ModelData; + noTitle: boolean; + shouldUpdateUrl: boolean; + includeCredentials: boolean; + isLoggedIn?: boolean; +} + +export interface InferenceRunOpts { + withModelLoading?: boolean; + isOnLoadCall?: boolean; + useCache?: boolean; + exampleOutput?: TOutput; +} + +export interface ExampleRunOpts { + isPreview?: boolean; + inferenceOpts?: InferenceRunOpts; +} + +export enum LoadState { + Loadable = "Loadable", + Loaded = "Loaded", + TooBig = "TooBig", + Error = "error", +} + +export enum ComputeType { + CPU = "cpu", + GPU = "gpu", +} + +export interface ModelLoadInfo { + state: LoadState; + compute_type?: ComputeType; +} + +export type TableData = Record; + +export type HighlightCoordinates = Record; + +interface Box { + xmin: number; + ymin: number; + xmax: number; + ymax: number; +} + +export interface DetectedObject { + box: Box; + label: string; + score: number; + color?: string; +} +export interface ImageSegment { + label: string; + score: number; + mask: string; + color?: string; + imgData?: ImageData; + bitmap?: ImageBitmap; +} diff --git a/packages/widgets/src/lib/components/InferenceWidget/stores.ts b/packages/widgets/src/lib/components/InferenceWidget/stores.ts new file mode 100644 index 000000000..a9ed4f27e --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/stores.ts @@ -0,0 +1,4 @@ +import { writable } from "svelte/store"; +import type { ModelLoadInfo } from "./shared/types.js"; + +export const modelLoadStates = writable>({}); diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/AudioClassificationWidget/AudioClassificationWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/AudioClassificationWidget/AudioClassificationWidget.svelte new file mode 100644 index 000000000..d75cea4f8 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/AudioClassificationWidget/AudioClassificationWidget.svelte @@ -0,0 +1,202 @@ + + + + +
+ + {#if fileUrl} + + {/if} + { + getOutput(); + }} + /> + {#if warning} +
{warning}
+ {/if} + +
+ + + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/AudioToAudioWidget/AudioToAudioWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/AudioToAudioWidget/AudioToAudioWidget.svelte new file mode 100644 index 000000000..5592fc579 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/AudioToAudioWidget/AudioToAudioWidget.svelte @@ -0,0 +1,191 @@ + + + + +
+ + {#if fileUrl} + + {/if} + { + getOutput(); + }} + /> + +
+ + {#each output as item} +
+ {item.label}: + +
+ {/each} +
+
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/AutomaticSpeechRecognitionWidget/AutomaticSpeechRecognitionWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/AutomaticSpeechRecognitionWidget/AutomaticSpeechRecognitionWidget.svelte new file mode 100644 index 000000000..94687285a --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/AutomaticSpeechRecognitionWidget/AutomaticSpeechRecognitionWidget.svelte @@ -0,0 +1,226 @@ + + + + +
+ + {#if !isRealtimeRecording} + {#if fileUrl} + + {/if} + { + getOutput(); + }} + /> + {#if warning} +
{warning}
+ {/if} + {/if} + +
+ + + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/ConversationalWidget/ConversationalWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/ConversationalWidget/ConversationalWidget.svelte new file mode 100644 index 000000000..b3d90789d --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/ConversationalWidget/ConversationalWidget.svelte @@ -0,0 +1,190 @@ + + + + + +
+ { + getOutput(); + }} + submitButtonLabel="Send" + /> + +
+
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/FeatureExtractionWidget/DataTable.ts b/packages/widgets/src/lib/components/InferenceWidget/widgets/FeatureExtractionWidget/DataTable.ts new file mode 100644 index 000000000..551868a38 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/FeatureExtractionWidget/DataTable.ts @@ -0,0 +1,43 @@ +export class DataTable { + max: number; + min: number; + std: number; + + constructor(public body: number[] | number[][]) { + const all = this.body.flat(); + this.max = Math.max(...all); + this.min = Math.min(...all); + this.std = this.max - this.min; + } + + get isArrLevel0(): boolean { + return isArrLevel0(this.body); + } + + get oneDim(): number[] { + return this.body as number[]; + } + get twoDim(): number[][] { + return this.body as number[][]; + } + + bg(value: number): string { + if (value > this.min + this.std * 0.7) { + return "bg-green-100 dark:bg-green-800"; + } + if (value > this.min + this.std * 0.6) { + return "bg-green-50 dark:bg-green-900"; + } + if (value < this.min + this.std * 0.3) { + return "bg-red-100 dark:bg-red-800"; + } + if (value < this.min + this.std * 0.4) { + return "bg-red-50 dark:bg-red-900"; + } + return ""; + } +} + +function isArrLevel0(x: number[] | number[][]): x is number[] { + return typeof x[0] === "number"; +} diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/FeatureExtractionWidget/FeatureExtractionWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/FeatureExtractionWidget/FeatureExtractionWidget.svelte new file mode 100644 index 000000000..d9f07a526 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/FeatureExtractionWidget/FeatureExtractionWidget.svelte @@ -0,0 +1,200 @@ + + + + +
+ { + getOutput(); + }} + /> + +
+ + {#if output} + {#if output.isArrLevel0} +
+ + {#each range(numOfRows(output.oneDim.length)) as i} + + {#each range(SINGLE_DIM_COLS) as j} + {#if j * numOfRows(output.oneDim.length) + i < output.oneDim.length} + + + {/if} + {/each} + + {/each} +
+ {j * numOfRows(output.oneDim.length) + i} + + {output.oneDim[j * numOfRows(output.oneDim.length) + i].toFixed(3)} +
+
+ {:else} +
+ + + + {/each} + + {#each output.twoDim as column, i} + + + {#each column as x} + + {/each} + + {/each} +
+ {#each range(output.twoDim[0].length) as j} + {j}
{i} + {x.toFixed(3)} +
+
+ {/if} + {/if} +
+
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/FillMaskWidget/FillMaskWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/FillMaskWidget/FillMaskWidget.svelte new file mode 100644 index 000000000..b8c00e06d --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/FillMaskWidget/FillMaskWidget.svelte @@ -0,0 +1,178 @@ + + + + +
+ {#if model.pipeline_tag === "fill-mask"} +
+ Mask token: {model.mask_token} +
+ {/if} + + { + getOutput(); + }} + /> + +
+ + + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageClassificationWidget/ImageClassificationWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageClassificationWidget/ImageClassificationWidget.svelte new file mode 100644 index 000000000..33961aed5 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageClassificationWidget/ImageClassificationWidget.svelte @@ -0,0 +1,176 @@ + + + + +
+ (error = e)} + > + {#if imgSrc} + + {/if} + + + {#if imgSrc} + {#if imgSrc} +
+ +
+ {/if} + {/if} + + {#if warning} +
{warning}
+ {/if} + +
+ + + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageSegmentationWidget/Canvas.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageSegmentationWidget/Canvas.svelte new file mode 100644 index 000000000..082b1062e --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageSegmentationWidget/Canvas.svelte @@ -0,0 +1,75 @@ + + + + +
+
+ +
+ {#if output.length} + + mousemove(e, width, height)} + on:mouseout={mouseout} + /> + {/if} +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageSegmentationWidget/ImageSegmentationWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageSegmentationWidget/ImageSegmentationWidget.svelte new file mode 100644 index 000000000..beff590a6 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageSegmentationWidget/ImageSegmentationWidget.svelte @@ -0,0 +1,286 @@ + + + + +
+ (error = e)} + > + {#if imgSrc} + + {/if} + + + {#if imgSrc} + + {/if} + + {#if warning} +
{warning}
+ {/if} + + +
+ + + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageToImageWidget/ImageToImageWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageToImageWidget/ImageToImageWidget.svelte new file mode 100644 index 000000000..2d1ecbf36 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageToImageWidget/ImageToImageWidget.svelte @@ -0,0 +1,202 @@ + + + + +
+ (error = e)} + > + {#if imgSrc} + + {/if} + + + {#if imgSrc} + {#if imgSrc} +
+ +
+ {/if} + {/if} + + + { + getOutput(); + }} + /> + +
+ + {#if output.length} +
+ +
+ {/if} +
+
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageToTextWidget/ImageToTextWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageToTextWidget/ImageToTextWidget.svelte new file mode 100644 index 000000000..0b7acee47 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/ImageToTextWidget/ImageToTextWidget.svelte @@ -0,0 +1,161 @@ + + + + +
+ (error = e)} + > + {#if imgSrc} + + {/if} + + + {#if imgSrc} + {#if imgSrc} +
+ +
+ {/if} + {/if} + + {#if warning} +
{warning}
+ {/if} + +
+ + {#if model?.pipeline_tag !== "text-generation"} + + {/if} + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/ObjectDetectionWidget/ObjectDetectionWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/ObjectDetectionWidget/ObjectDetectionWidget.svelte new file mode 100644 index 000000000..a14e3ba28 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/ObjectDetectionWidget/ObjectDetectionWidget.svelte @@ -0,0 +1,197 @@ + + + + +
+ (error = e)} + > + {#if imgSrc} + + {/if} + + + {#if imgSrc} + + {/if} + + {#if warning} +
{warning}
+ {/if} + +
+ + + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/ObjectDetectionWidget/SvgBoundingBoxes.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/ObjectDetectionWidget/SvgBoundingBoxes.svelte new file mode 100644 index 000000000..90446b606 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/ObjectDetectionWidget/SvgBoundingBoxes.svelte @@ -0,0 +1,93 @@ + + + +
+
+ +
+ + + {#each boxes as { rect, color, index }} + + mouseover(index)} + on:mouseout={mouseout} + /> + {/each} + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/QuestionAnsweringWidget/QuestionAnsweringWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/QuestionAnsweringWidget/QuestionAnsweringWidget.svelte new file mode 100644 index 000000000..53479ee8f --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/QuestionAnsweringWidget/QuestionAnsweringWidget.svelte @@ -0,0 +1,177 @@ + + + + +
+ { + getOutput(); + }} + /> + + +
+ + {#if output} +
+ {output.answer} + {output.score.toFixed(3)} +
+ {/if} +
+
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/ReinforcementLearningWidget/ReinforcementLearningWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/ReinforcementLearningWidget/ReinforcementLearningWidget.svelte new file mode 100644 index 000000000..3e6714ab2 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/ReinforcementLearningWidget/ReinforcementLearningWidget.svelte @@ -0,0 +1,62 @@ + + + +
+ +
+ {#if replay === Replay.Available} + +
+
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/SentenceSimilarityWidget/SentenceSimilarityWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/SentenceSimilarityWidget/SentenceSimilarityWidget.svelte new file mode 100644 index 000000000..07308d7a8 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/SentenceSimilarityWidget/SentenceSimilarityWidget.svelte @@ -0,0 +1,187 @@ + + + + +
+ + + {#each Array(nComparisonSentences - 1) as _, idx} + + {/each} + { + nComparisonSentences++; + }} + /> + { + getOutput(); + }} + /> + +
+ + {#if output.length} + + {/if} + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/SummarizationWidget/SummarizationWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/SummarizationWidget/SummarizationWidget.svelte new file mode 100644 index 000000000..e2e4680d1 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/SummarizationWidget/SummarizationWidget.svelte @@ -0,0 +1,140 @@ + + + + +
+ + { + getOutput(); + }} + /> + +
+ + + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/TableQuestionAnsweringWidget/TableQuestionAnsweringWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/TableQuestionAnsweringWidget/TableQuestionAnsweringWidget.svelte new file mode 100644 index 000000000..d252b25c8 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/TableQuestionAnsweringWidget/TableQuestionAnsweringWidget.svelte @@ -0,0 +1,196 @@ + + + + +
+ { + getOutput(); + }} + /> + +
+ {#if output} + + {/if} + {#if table.length > 1 || table[0].length > 1} + + {/if} +
+
+
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/TabularDataWidget/TabularDataWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/TabularDataWidget/TabularDataWidget.svelte new file mode 100644 index 000000000..3c0a12f47 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/TabularDataWidget/TabularDataWidget.svelte @@ -0,0 +1,228 @@ + + + + +
+
+ {#if table.length > 1 || table[1]?.length > 1} + + {/if} +
+ { + getOutput(); + }} + /> + +
+ +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/TextGenerationWidget/TextGenerationWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/TextGenerationWidget/TextGenerationWidget.svelte new file mode 100644 index 000000000..9a23bb5ad --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/TextGenerationWidget/TextGenerationWidget.svelte @@ -0,0 +1,268 @@ + + + + +
+ + {#if model.id === "bigscience/bloom"} + + {/if} +
+ { + getOutput({ useCache }); + }} + /> + +
+ +
+
+ {#if warning} +
{warning}
+ {/if} + {#if isBloomLoginRequired} +
+ + Please + login + or + + register to try BLOOM 🌸 +
+ {/if} + +
+ + {#if model?.pipeline_tag !== "text-generation"} + + + {/if} + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/TextToImageWidget/TextToImageWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/TextToImageWidget/TextToImageWidget.svelte new file mode 100644 index 000000000..ff2d09221 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/TextToImageWidget/TextToImageWidget.svelte @@ -0,0 +1,155 @@ + + + + +
+ getOutput()} /> + +
+ + {#if output.length} +
+ +
+ {/if} +
+
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/TextToSpeechWidget/TextToSpeechWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/TextToSpeechWidget/TextToSpeechWidget.svelte new file mode 100644 index 000000000..27c174be9 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/TextToSpeechWidget/TextToSpeechWidget.svelte @@ -0,0 +1,143 @@ + + + + +
+ + { + getOutput(); + }} + /> + +
+ + {#if output.length} + + {/if} + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/TokenClassificationWidget/TokenClassificationWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/TokenClassificationWidget/TokenClassificationWidget.svelte new file mode 100644 index 000000000..f0f9fb258 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/TokenClassificationWidget/TokenClassificationWidget.svelte @@ -0,0 +1,265 @@ + + + + +
+ + { + getOutput(); + }} + /> + {#if warning} +
{warning}
+ {/if} + +
+ + + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/VisualQuestionAnsweringWidget/VisualQuestionAnsweringWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/VisualQuestionAnsweringWidget/VisualQuestionAnsweringWidget.svelte new file mode 100644 index 000000000..b37c6ea6d --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/VisualQuestionAnsweringWidget/VisualQuestionAnsweringWidget.svelte @@ -0,0 +1,204 @@ + + + + +
+ (error = e)} + > + {#if imgSrc} + + {/if} + + + {#if imgSrc} + {#if imgSrc} +
+ +
+ {/if} + {/if} + + { + getOutput(); + }} + /> + +
+ + {#if output} + + {/if} + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/ZeroShotImageClassificationWidget/ZeroShotImageClassificationWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/ZeroShotImageClassificationWidget/ZeroShotImageClassificationWidget.svelte new file mode 100644 index 000000000..cb2d4ee89 --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/ZeroShotImageClassificationWidget/ZeroShotImageClassificationWidget.svelte @@ -0,0 +1,228 @@ + + + + +
+ (error = e)} + > + {#if imgSrc} + + {/if} + + + {#if imgSrc} + {#if imgSrc} +
+ +
+ {/if} + {/if} + + + { + getOutput(); + }} + /> + +
+ + {#if output.length} + + {/if} + +
diff --git a/packages/widgets/src/lib/components/InferenceWidget/widgets/ZeroShowClassificationWidget/ZeroShotClassificationWidget.svelte b/packages/widgets/src/lib/components/InferenceWidget/widgets/ZeroShowClassificationWidget/ZeroShotClassificationWidget.svelte new file mode 100644 index 000000000..d3742b8ca --- /dev/null +++ b/packages/widgets/src/lib/components/InferenceWidget/widgets/ZeroShowClassificationWidget/ZeroShotClassificationWidget.svelte @@ -0,0 +1,200 @@ + + + + +
+ + + + { + getOutput(); + }} + /> + {#if warning} +
{warning}
+ {/if} + +
+ + {#if output.length} + + {/if} + +
diff --git a/packages/widgets/src/lib/components/PipelineIcon/PipelineIcon.svelte b/packages/widgets/src/lib/components/PipelineIcon/PipelineIcon.svelte new file mode 100644 index 000000000..990019763 --- /dev/null +++ b/packages/widgets/src/lib/components/PipelineIcon/PipelineIcon.svelte @@ -0,0 +1,89 @@ + + + diff --git a/packages/widgets/src/lib/components/PipelineTag/PipelineTag.svelte b/packages/widgets/src/lib/components/PipelineTag/PipelineTag.svelte new file mode 100644 index 000000000..dc2afad8a --- /dev/null +++ b/packages/widgets/src/lib/components/PipelineTag/PipelineTag.svelte @@ -0,0 +1,16 @@ + + +
+ + + {pipelineData ? pipelineData.name : pipeline} + +
diff --git a/packages/widgets/src/lib/index.ts b/packages/widgets/src/lib/index.ts new file mode 100644 index 000000000..a37f99cf4 --- /dev/null +++ b/packages/widgets/src/lib/index.ts @@ -0,0 +1,38 @@ +import InferenceWidget from "./components/InferenceWidget/InferenceWidget.svelte"; +import WidgetOutputChart from "./components/InferenceWidget/shared/WidgetOutputChart/WidgetOutputChart.svelte"; +import WidgetOutputTokens from "./components/InferenceWidget/shared/WidgetOutputTokens/WidgetOutputTokens.svelte"; +import PipelineIcon from "./components/PipelineIcon/PipelineIcon.svelte"; +import { modelLoadStates } from "./components/InferenceWidget/stores.js"; +import { InferenceDisplayability } from "./interfaces/InferenceDisplayability.js"; +import * as serveCurl from "./inferenceSnippets/serveCurl.js"; +import * as serveJs from "./inferenceSnippets/serveJs.js"; +import * as servePython from "./inferenceSnippets/servePython.js"; +import * as snippetInputs from "./inferenceSnippets/inputs.js"; +import { MODEL_LIBRARIES_UI_ELEMENTS } from "./interfaces/Libraries.js"; +import type { LibraryUiElement } from "./interfaces/Libraries.js"; +import type { TransformersInfo } from "./interfaces/Types.js"; +import { MAPPING_DEFAULT_WIDGET } from "./interfaces/DefaultWidget.js"; +import { LIBRARY_TASK_MAPPING_EXCLUDING_TRANSFORMERS } from "./interfaces/LibrariesToTasks.js"; + +export { + InferenceWidget, + WidgetOutputChart, + WidgetOutputTokens, + modelLoadStates, + InferenceDisplayability, + PipelineIcon, + serveCurl, + serveJs, + servePython, + snippetInputs, + MODEL_LIBRARIES_UI_ELEMENTS, + MAPPING_DEFAULT_WIDGET, + LIBRARY_TASK_MAPPING_EXCLUDING_TRANSFORMERS, +}; +export type { + WidgetExample, + WidgetExampleOutput, + WidgetExampleOutputUrl, + WidgetExampleTextInput, +} from "./components/InferenceWidget/shared/WidgetExample.js"; +export type { LibraryUiElement, TransformersInfo }; diff --git a/packages/widgets/src/lib/inferenceSnippets/inputs.ts b/packages/widgets/src/lib/inferenceSnippets/inputs.ts new file mode 100644 index 000000000..64e8c4c41 --- /dev/null +++ b/packages/widgets/src/lib/inferenceSnippets/inputs.ts @@ -0,0 +1,129 @@ +import type { PipelineType } from "@huggingface/tasks"; +import type { ModelData } from "../interfaces/Types.js"; + +const inputsZeroShotClassification = () => + `"Hi, I recently bought a device from your company but it is not working as advertised and I would like to get reimbursed!"`; + +const inputsTranslation = () => `"Меня зовут Вольфганг и я живу в Берлине"`; + +const inputsSummarization = () => + `"The tower is 324 metres (1,063 ft) tall, about the same height as an 81-storey building, and the tallest structure in Paris. Its base is square, measuring 125 metres (410 ft) on each side. During its construction, the Eiffel Tower surpassed the Washington Monument to become the tallest man-made structure in the world, a title it held for 41 years until the Chrysler Building in New York City was finished in 1930. It was the first structure to reach a height of 300 metres. Due to the addition of a broadcasting aerial at the top of the tower in 1957, it is now taller than the Chrysler Building by 5.2 metres (17 ft). Excluding transmitters, the Eiffel Tower is the second tallest free-standing structure in France after the Millau Viaduct."`; + +const inputsConversational = () => + `{ + "past_user_inputs": ["Which movie is the best ?"], + "generated_responses": ["It is Die Hard for sure."], + "text": "Can you explain why ?" + }`; + +const inputsTableQuestionAnswering = () => + `{ + "query": "How many stars does the transformers repository have?", + "table": { + "Repository": ["Transformers", "Datasets", "Tokenizers"], + "Stars": ["36542", "4512", "3934"], + "Contributors": ["651", "77", "34"], + "Programming language": [ + "Python", + "Python", + "Rust, Python and NodeJS" + ] + } + }`; + +const inputsQuestionAnswering = () => + `{ + "question": "What is my name?", + "context": "My name is Clara and I live in Berkeley." + }`; + +const inputsTextClassification = () => `"I like you. I love you"`; + +const inputsTokenClassification = () => `"My name is Sarah Jessica Parker but you can call me Jessica"`; + +const inputsTextGeneration = () => `"Can you please let us know more details about your "`; + +const inputsText2TextGeneration = () => `"The answer to the universe is"`; + +const inputsFillMask = (model: ModelData) => `"The answer to the universe is ${model.mask_token}."`; + +const inputsSentenceSimilarity = () => + `{ + "source_sentence": "That is a happy person", + "sentences": [ + "That is a happy dog", + "That is a very happy person", + "Today is a sunny day" + ] + }`; + +const inputsFeatureExtraction = () => `"Today is a sunny day and I will get some ice cream."`; + +const inputsImageClassification = () => `"cats.jpg"`; + +const inputsImageToText = () => `"cats.jpg"`; + +const inputsImageSegmentation = () => `"cats.jpg"`; + +const inputsObjectDetection = () => `"cats.jpg"`; + +const inputsAudioToAudio = () => `"sample1.flac"`; + +const inputsAudioClassification = () => `"sample1.flac"`; + +const inputsTextToImage = () => `"Astronaut riding a horse"`; + +const inputsTextToSpeech = () => `"The answer to the universe is 42"`; + +const inputsTextToAudio = () => `"liquid drum and bass, atmospheric synths, airy sounds"`; + +const inputsAutomaticSpeechRecognition = () => `"sample1.flac"`; + +const modelInputSnippets: { + [key in PipelineType]?: (model: ModelData) => string; +} = { + "audio-to-audio": inputsAudioToAudio, + "audio-classification": inputsAudioClassification, + "automatic-speech-recognition": inputsAutomaticSpeechRecognition, + conversational: inputsConversational, + "feature-extraction": inputsFeatureExtraction, + "fill-mask": inputsFillMask, + "image-classification": inputsImageClassification, + "image-to-text": inputsImageToText, + "image-segmentation": inputsImageSegmentation, + "object-detection": inputsObjectDetection, + "question-answering": inputsQuestionAnswering, + "sentence-similarity": inputsSentenceSimilarity, + summarization: inputsSummarization, + "table-question-answering": inputsTableQuestionAnswering, + "text-classification": inputsTextClassification, + "text-generation": inputsTextGeneration, + "text-to-image": inputsTextToImage, + "text-to-speech": inputsTextToSpeech, + "text-to-audio": inputsTextToAudio, + "text2text-generation": inputsText2TextGeneration, + "token-classification": inputsTokenClassification, + translation: inputsTranslation, + "zero-shot-classification": inputsZeroShotClassification, +}; + +// Use noWrap to put the whole snippet on a single line (removing new lines and tabulations) +// Use noQuotes to strip quotes from start & end (example: "abc" -> abc) +export function getModelInputSnippet(model: ModelData, noWrap = false, noQuotes = false): string { + if (model.pipeline_tag) { + const inputs = modelInputSnippets[model.pipeline_tag]; + if (inputs) { + let result = inputs(model); + if (noWrap) { + result = result.replace(/(?:(?:\r?\n|\r)\t*)|\t+/g, " "); + } + if (noQuotes) { + const REGEX_QUOTES = /^"(.+)"$/s; + const match = result.match(REGEX_QUOTES); + result = match ? match[1] : result; + } + return result; + } + } + return "No input example has been defined for this model task."; +} diff --git a/packages/widgets/src/lib/inferenceSnippets/serveCurl.ts b/packages/widgets/src/lib/inferenceSnippets/serveCurl.ts new file mode 100644 index 000000000..7a801e934 --- /dev/null +++ b/packages/widgets/src/lib/inferenceSnippets/serveCurl.ts @@ -0,0 +1,63 @@ +import type { PipelineType } from "@huggingface/tasks"; +import type { ModelData } from "../interfaces/Types.js"; +import { getModelInputSnippet } from "./inputs.js"; + +export const snippetBasic = (model: ModelData, accessToken: string): string => + `curl https://api-inference.huggingface.co/models/${model.id} \\ + -X POST \\ + -d '{"inputs": ${getModelInputSnippet(model, true)}}' \\ + -H 'Content-Type: application/json' \\ + -H "Authorization: Bearer ${accessToken || `{API_TOKEN}`}" +`; + +export const snippetZeroShotClassification = (model: ModelData, accessToken: string): string => + `curl https://api-inference.huggingface.co/models/${model.id} \\ + -X POST \\ + -d '{"inputs": ${getModelInputSnippet(model, true)}, "parameters": {"candidate_labels": ["refund", "legal", "faq"]}}' \\ + -H 'Content-Type: application/json' \\ + -H "Authorization: Bearer ${accessToken || `{API_TOKEN}`}" +`; + +export const snippetFile = (model: ModelData, accessToken: string): string => + `curl https://api-inference.huggingface.co/models/${model.id} \\ + -X POST \\ + --data-binary '@${getModelInputSnippet(model, true, true)}' \\ + -H "Authorization: Bearer ${accessToken || `{API_TOKEN}`}" +`; + +export const curlSnippets: Partial string>> = { + // Same order as in js/src/lib/interfaces/Types.ts + "text-classification": snippetBasic, + "token-classification": snippetBasic, + "table-question-answering": snippetBasic, + "question-answering": snippetBasic, + "zero-shot-classification": snippetZeroShotClassification, + translation: snippetBasic, + summarization: snippetBasic, + conversational: snippetBasic, + "feature-extraction": snippetBasic, + "text-generation": snippetBasic, + "text2text-generation": snippetBasic, + "fill-mask": snippetBasic, + "sentence-similarity": snippetBasic, + "automatic-speech-recognition": snippetFile, + "text-to-image": snippetBasic, + "text-to-speech": snippetBasic, + "text-to-audio": snippetBasic, + "audio-to-audio": snippetFile, + "audio-classification": snippetFile, + "image-classification": snippetFile, + "image-to-text": snippetFile, + "object-detection": snippetFile, + "image-segmentation": snippetFile, +}; + +export function getCurlInferenceSnippet(model: ModelData, accessToken: string): string { + return model.pipeline_tag && model.pipeline_tag in curlSnippets + ? curlSnippets[model.pipeline_tag]?.(model, accessToken) ?? "" + : ""; +} + +export function hasCurlInferenceSnippet(model: ModelData): boolean { + return !!model.pipeline_tag && model.pipeline_tag in curlSnippets; +} diff --git a/packages/widgets/src/lib/inferenceSnippets/serveJs.ts b/packages/widgets/src/lib/inferenceSnippets/serveJs.ts new file mode 100644 index 000000000..ef94c3064 --- /dev/null +++ b/packages/widgets/src/lib/inferenceSnippets/serveJs.ts @@ -0,0 +1,150 @@ +import type { PipelineType } from "@huggingface/tasks"; +import type { ModelData } from "../interfaces/Types.js"; +import { getModelInputSnippet } from "./inputs.js"; + +export const snippetBasic = (model: ModelData, accessToken: string): string => + `async function query(data) { + const response = await fetch( + "https://api-inference.huggingface.co/models/${model.id}", + { + headers: { Authorization: "Bearer ${accessToken || `{API_TOKEN}`}" }, + method: "POST", + body: JSON.stringify(data), + } + ); + const result = await response.json(); + return result; +} + +query({"inputs": ${getModelInputSnippet(model)}}).then((response) => { + console.log(JSON.stringify(response)); +});`; + +export const snippetZeroShotClassification = (model: ModelData, accessToken: string): string => + `async function query(data) { + const response = await fetch( + "https://api-inference.huggingface.co/models/${model.id}", + { + headers: { Authorization: "Bearer ${accessToken || `{API_TOKEN}`}" }, + method: "POST", + body: JSON.stringify(data), + } + ); + const result = await response.json(); + return result; +} + +query({"inputs": ${getModelInputSnippet( + model + )}, "parameters": {"candidate_labels": ["refund", "legal", "faq"]}}).then((response) => { + console.log(JSON.stringify(response)); +});`; + +export const snippetTextToImage = (model: ModelData, accessToken: string): string => + `async function query(data) { + const response = await fetch( + "https://api-inference.huggingface.co/models/${model.id}", + { + headers: { Authorization: "Bearer ${accessToken || `{API_TOKEN}`}" }, + method: "POST", + body: JSON.stringify(data), + } + ); + const result = await response.blob(); + return result; +} +query({"inputs": ${getModelInputSnippet(model)}}).then((response) => { + // Use image +});`; + +export const snippetTextToAudio = (model: ModelData, accessToken: string): string => { + const commonSnippet = `async function query(data) { + const response = await fetch( + "https://api-inference.huggingface.co/models/${model.id}", + { + headers: { Authorization: "Bearer ${accessToken || `{API_TOKEN}`}" }, + method: "POST", + body: JSON.stringify(data), + } + );`; + if (model.library_name === "transformers") { + return ( + commonSnippet + + ` + const result = await response.blob(); + return result; + } + query({"inputs": ${getModelInputSnippet(model)}}).then((response) => { + // Returns a byte object of the Audio wavform. Use it directly! + });` + ); + } else { + return ( + commonSnippet + + ` + const result = await response.json(); + return result; + } + + query({"inputs": ${getModelInputSnippet(model)}}).then((response) => { + console.log(JSON.stringify(response)); + });` + ); + } +}; + +export const snippetFile = (model: ModelData, accessToken: string): string => + `async function query(filename) { + const data = fs.readFileSync(filename); + const response = await fetch( + "https://api-inference.huggingface.co/models/${model.id}", + { + headers: { Authorization: "Bearer ${accessToken || `{API_TOKEN}`}" }, + method: "POST", + body: data, + } + ); + const result = await response.json(); + return result; +} + +query(${getModelInputSnippet(model)}).then((response) => { + console.log(JSON.stringify(response)); +});`; + +export const jsSnippets: Partial string>> = { + // Same order as in js/src/lib/interfaces/Types.ts + "text-classification": snippetBasic, + "token-classification": snippetBasic, + "table-question-answering": snippetBasic, + "question-answering": snippetBasic, + "zero-shot-classification": snippetZeroShotClassification, + translation: snippetBasic, + summarization: snippetBasic, + conversational: snippetBasic, + "feature-extraction": snippetBasic, + "text-generation": snippetBasic, + "text2text-generation": snippetBasic, + "fill-mask": snippetBasic, + "sentence-similarity": snippetBasic, + "automatic-speech-recognition": snippetFile, + "text-to-image": snippetTextToImage, + "text-to-speech": snippetTextToAudio, + "text-to-audio": snippetTextToAudio, + "audio-to-audio": snippetFile, + "audio-classification": snippetFile, + "image-classification": snippetFile, + "image-to-text": snippetFile, + "object-detection": snippetFile, + "image-segmentation": snippetFile, +}; + +export function getJsInferenceSnippet(model: ModelData, accessToken: string): string { + return model.pipeline_tag && model.pipeline_tag in jsSnippets + ? jsSnippets[model.pipeline_tag]?.(model, accessToken) ?? "" + : ""; +} + +export function hasJsInferenceSnippet(model: ModelData): boolean { + return !!model.pipeline_tag && model.pipeline_tag in jsSnippets; +} diff --git a/packages/widgets/src/lib/inferenceSnippets/servePython.ts b/packages/widgets/src/lib/inferenceSnippets/servePython.ts new file mode 100644 index 000000000..5ddbeabeb --- /dev/null +++ b/packages/widgets/src/lib/inferenceSnippets/servePython.ts @@ -0,0 +1,114 @@ +import type { PipelineType } from "@huggingface/tasks"; +import type { ModelData } from "../interfaces/Types.js"; +import { getModelInputSnippet } from "./inputs.js"; + +export const snippetZeroShotClassification = (model: ModelData): string => + `def query(payload): + response = requests.post(API_URL, headers=headers, json=payload) + return response.json() + +output = query({ + "inputs": ${getModelInputSnippet(model)}, + "parameters": {"candidate_labels": ["refund", "legal", "faq"]}, +})`; + +export const snippetBasic = (model: ModelData): string => + `def query(payload): + response = requests.post(API_URL, headers=headers, json=payload) + return response.json() + +output = query({ + "inputs": ${getModelInputSnippet(model)}, +})`; + +export const snippetFile = (model: ModelData): string => + `def query(filename): + with open(filename, "rb") as f: + data = f.read() + response = requests.post(API_URL, headers=headers, data=data) + return response.json() + +output = query(${getModelInputSnippet(model)})`; + +export const snippetTextToImage = (model: ModelData): string => + `def query(payload): + response = requests.post(API_URL, headers=headers, json=payload) + return response.content +image_bytes = query({ + "inputs": ${getModelInputSnippet(model)}, +}) +# You can access the image with PIL.Image for example +import io +from PIL import Image +image = Image.open(io.BytesIO(image_bytes))`; + +export const snippetTextToAudio = (model: ModelData): string => { + // Transformers TTS pipeline and api-inference-community (AIC) pipeline outputs are diverged + // with the latest update to inference-api (IA). + // Transformers IA returns a byte object (wav file), whereas AIC returns wav and sampling_rate. + if (model.library_name === "transformers") { + return `def query(payload): + response = requests.post(API_URL, headers=headers, json=payload) + return response.content + +audio_bytes = query({ + "inputs": ${getModelInputSnippet(model)}, +}) +# You can access the audio with IPython.display for example +from IPython.display import Audio +Audio(audio_bytes)`; + } else { + return `def query(payload): + response = requests.post(API_URL, headers=headers, json=payload) + return response.json() + +audio, sampling_rate = query({ + "inputs": ${getModelInputSnippet(model)}, +}) +# You can access the audio with IPython.display for example +from IPython.display import Audio +Audio(audio, rate=sampling_rate)`; + } +}; +export const pythonSnippets: Partial string>> = { + // Same order as in js/src/lib/interfaces/Types.ts + "text-classification": snippetBasic, + "token-classification": snippetBasic, + "table-question-answering": snippetBasic, + "question-answering": snippetBasic, + "zero-shot-classification": snippetZeroShotClassification, + translation: snippetBasic, + summarization: snippetBasic, + conversational: snippetBasic, + "feature-extraction": snippetBasic, + "text-generation": snippetBasic, + "text2text-generation": snippetBasic, + "fill-mask": snippetBasic, + "sentence-similarity": snippetBasic, + "automatic-speech-recognition": snippetFile, + "text-to-image": snippetTextToImage, + "text-to-speech": snippetTextToAudio, + "text-to-audio": snippetTextToAudio, + "audio-to-audio": snippetFile, + "audio-classification": snippetFile, + "image-classification": snippetFile, + "image-to-text": snippetFile, + "object-detection": snippetFile, + "image-segmentation": snippetFile, +}; + +export function getPythonInferenceSnippet(model: ModelData, accessToken: string): string { + const body = + model.pipeline_tag && model.pipeline_tag in pythonSnippets ? pythonSnippets[model.pipeline_tag]?.(model) ?? "" : ""; + + return `import requests + +API_URL = "https://api-inference.huggingface.co/models/${model.id}" +headers = {"Authorization": ${accessToken ? `"Bearer ${accessToken}"` : `f"Bearer {API_TOKEN}"`}} + +${body}`; +} + +export function hasPythonInferenceSnippet(model: ModelData): boolean { + return !!model.pipeline_tag && model.pipeline_tag in pythonSnippets; +} diff --git a/packages/widgets/src/lib/interfaces/DefaultWidget.ts b/packages/widgets/src/lib/interfaces/DefaultWidget.ts new file mode 100644 index 000000000..e7ad19621 --- /dev/null +++ b/packages/widgets/src/lib/interfaces/DefaultWidget.ts @@ -0,0 +1,718 @@ +import type { PipelineType } from "@huggingface/tasks"; +import type { WidgetExample } from "../components/InferenceWidget/shared/WidgetExample.js"; + +type LanguageCode = string; + +type PerLanguageMapping = Map; + +/// NOTE TO CONTRIBUTORS: +/// +/// When adding sample inputs for a new language, you don't +/// necessarily have to translate the inputs from existing languages. +/// (which were quite random to begin with) +/// +/// i.e. Feel free to be creative and provide better samples. +// + +/// The placeholder will be replaced by the correct mask token +/// in the following examples, depending on the model type +/// +/// see [INTERNAL] github.com/huggingface/moon-landing/blob/c5c3d45fe0ab27347b3ab27bdad646ef20732351/server/lib/App.ts#L254 +// + +const MAPPING_EN: PerLanguageMapping = new Map([ + ["text-classification", [`I like you. I love you`]], + [ + "token-classification", + [ + `My name is Wolfgang and I live in Berlin`, + `My name is Sarah and I live in London`, + `My name is Clara and I live in Berkeley, California.`, + ], + ], + [ + "table-question-answering", + [ + { + text: `How many stars does the transformers repository have?`, + table: { + Repository: ["Transformers", "Datasets", "Tokenizers"], + Stars: [36542, 4512, 3934], + Contributors: [651, 77, 34], + "Programming language": ["Python", "Python", "Rust, Python and NodeJS"], + }, + }, + ], + ], + [ + "question-answering", + [ + { + text: `Where do I live?`, + context: `My name is Wolfgang and I live in Berlin`, + }, + { + text: `Where do I live?`, + context: `My name is Sarah and I live in London`, + }, + { + text: `What's my name?`, + context: `My name is Clara and I live in Berkeley.`, + }, + { + text: `Which name is also used to describe the Amazon rainforest in English?`, + context: `The Amazon rainforest (Portuguese: Floresta Amazônica or Amazônia; Spanish: Selva Amazónica, Amazonía or usually Amazonia; French: Forêt amazonienne; Dutch: Amazoneregenwoud), also known in English as Amazonia or the Amazon Jungle, is a moist broadleaf forest that covers most of the Amazon basin of South America. This basin encompasses 7,000,000 square kilometres (2,700,000 sq mi), of which 5,500,000 square kilometres (2,100,000 sq mi) are covered by the rainforest. This region includes territory belonging to nine nations. The majority of the forest is contained within Brazil, with 60% of the rainforest, followed by Peru with 13%, Colombia with 10%, and with minor amounts in Venezuela, Ecuador, Bolivia, Guyana, Suriname and French Guiana. States or departments in four nations contain "Amazonas" in their names. The Amazon represents over half of the planet's remaining rainforests, and comprises the largest and most biodiverse tract of tropical rainforest in the world, with an estimated 390 billion individual trees divided into 16,000 species.`, + }, + ], + ], + [ + "zero-shot-classification", + [ + { + text: "I have a problem with my iphone that needs to be resolved asap!!", + candidate_labels: "urgent, not urgent, phone, tablet, computer", + multi_class: true, + }, + { + text: "Last week I upgraded my iOS version and ever since then my phone has been overheating whenever I use your app.", + candidate_labels: "mobile, website, billing, account access", + multi_class: false, + }, + { + text: "A new model offers an explanation for how the Galilean satellites formed around the solar system’s largest world. Konstantin Batygin did not set out to solve one of the solar system’s most puzzling mysteries when he went for a run up a hill in Nice, France. Dr. Batygin, a Caltech researcher, best known for his contributions to the search for the solar system’s missing “Planet Nine,” spotted a beer bottle. At a steep, 20 degree grade, he wondered why it wasn’t rolling down the hill. He realized there was a breeze at his back holding the bottle in place. Then he had a thought that would only pop into the mind of a theoretical astrophysicist: “Oh! This is how Europa formed.” Europa is one of Jupiter’s four large Galilean moons. And in a paper published Monday in the Astrophysical Journal, Dr. Batygin and a co-author, Alessandro Morbidelli, a planetary scientist at the Côte d’Azur Observatory in France, present a theory explaining how some moons form around gas giants like Jupiter and Saturn, suggesting that millimeter-sized grains of hail produced during the solar system’s formation became trapped around these massive worlds, taking shape one at a time into the potentially habitable moons we know today.", + candidate_labels: "space & cosmos, scientific discovery, microbiology, robots, archeology", + multi_class: true, + }, + ], + ], + ["translation", [`My name is Wolfgang and I live in Berlin`, `My name is Sarah and I live in London`]], + [ + "summarization", + [ + `The tower is 324 metres (1,063 ft) tall, about the same height as an 81-storey building, and the tallest structure in Paris. Its base is square, measuring 125 metres (410 ft) on each side. During its construction, the Eiffel Tower surpassed the Washington Monument to become the tallest man-made structure in the world, a title it held for 41 years until the Chrysler Building in New York City was finished in 1930. It was the first structure to reach a height of 300 metres. Due to the addition of a broadcasting aerial at the top of the tower in 1957, it is now taller than the Chrysler Building by 5.2 metres (17 ft). Excluding transmitters, the Eiffel Tower is the second tallest free-standing structure in France after the Millau Viaduct.`, + ], + ], + [ + "conversational", + [ + `Hey my name is Julien! How are you?`, + `Hey my name is Thomas! How are you?`, + `Hey my name is Mariama! How are you?`, + `Hey my name is Clara! How are you?`, + `Hey my name is Julien! How are you?`, + `Hi.`, + ], + ], + [ + "text-generation", + [ + `My name is Julien and I like to`, + `My name is Thomas and my main`, + `My name is Mariama, my favorite`, + `My name is Clara and I am`, + `My name is Lewis and I like to`, + `My name is Merve and my favorite`, + `My name is Teven and I am`, + `Once upon a time,`, + ], + ], + ["fill-mask", [`Paris is the of France.`, `The goal of life is .`]], + [ + "sentence-similarity", + [ + { + source_sentence: "That is a happy person", + sentences: ["That is a happy dog", "That is a very happy person", "Today is a sunny day"], + }, + ], + ], +]); + +const MAPPING_ZH: PerLanguageMapping = new Map([ + ["text-classification", [`我喜欢你。 我爱你`]], + ["token-classification", [`我叫沃尔夫冈,我住在柏林。`, `我叫萨拉,我住在伦敦。`, `我叫克拉拉,我住在加州伯克利。`]], + [ + "question-answering", + [ + { + text: `我住在哪里?`, + context: `我叫沃尔夫冈,我住在柏林。`, + }, + { + text: `我住在哪里?`, + context: `我叫萨拉,我住在伦敦。`, + }, + { + text: `我的名字是什么?`, + context: `我叫克拉拉,我住在伯克利。`, + }, + ], + ], + ["translation", [`我叫沃尔夫冈,我住在柏林。`, `我叫萨拉,我住在伦敦。`]], + [ + "zero-shot-classification", + [ + { + text: "房间干净明亮,非常不错", + candidate_labels: "这是一条差评, 这是一条好评", + }, + ], + ], + [ + "summarization", + [ + `该塔高324米(1063英尺),与一幢81层的建筑物一样高,是巴黎最高的建筑物。 它的底座是方形的,每边长125米(410英尺)。 在建造过程中,艾菲尔铁塔超过了华盛顿纪念碑,成为世界上最高的人造结构,它保持了41年的头衔,直到1930年纽约市的克莱斯勒大楼竣工。这是第一个到达300米高度的结构。 由于1957年在塔顶增加了广播天线,因此它现在比克莱斯勒大厦高5.2米(17英尺)。 除发射器外,艾菲尔铁塔是法国第二高的独立式建筑,仅次于米劳高架桥。`, + ], + ], + [ + "text-generation", + [`我叫朱利安,我喜欢`, `我叫托马斯,我的主要`, `我叫玛丽亚,我最喜欢的`, `我叫克拉拉,我是`, `从前,`], + ], + ["fill-mask", [`巴黎是国的首都。`, `生活的真谛是。`]], + [ + "sentence-similarity", + [ + { + source_sentence: "那是 個快樂的人", + sentences: ["那是 條快樂的狗", "那是 個非常幸福的人", "今天是晴天"], + }, + ], + ], +]); + +const MAPPING_FR: PerLanguageMapping = new Map([ + ["text-classification", [`Je t'apprécie beaucoup. Je t'aime.`]], + ["token-classification", [`Mon nom est Wolfgang et je vis à Berlin`]], + [ + "question-answering", + [ + { + text: `Où est-ce que je vis?`, + context: `Mon nom est Wolfgang et je vis à Berlin`, + }, + ], + ], + ["translation", [`Mon nom est Wolfgang et je vis à Berlin`]], + [ + "summarization", + [ + `La tour fait 324 mètres (1,063 pieds) de haut, environ la même hauteur qu'un immeuble de 81 étages, et est la plus haute structure de Paris. Sa base est carrée, mesurant 125 mètres (410 pieds) sur chaque côté. Durant sa construction, la tour Eiffel surpassa le Washington Monument pour devenir la plus haute structure construite par l'homme dans le monde, un titre qu'elle conserva pendant 41 ans jusqu'à l'achèvement du Chrysler Building à New-York City en 1930. Ce fut la première structure à atteindre une hauteur de 300 mètres. Avec l'ajout d'une antenne de radiodiffusion au sommet de la tour Eiffel en 1957, celle-ci redevint plus haute que le Chrysler Building de 5,2 mètres (17 pieds). En excluant les transmetteurs, elle est la seconde plus haute stucture autoportante de France après le viaduc de Millau.`, + ], + ], + ["text-generation", [`Mon nom est Julien et j'aime`, `Mon nom est Thomas et mon principal`, `Il était une fois`]], + ["fill-mask", [`Paris est la de la France.`]], + [ + "sentence-similarity", + [ + { + source_sentence: "C'est une personne heureuse", + sentences: [ + "C'est un chien heureux", + "C'est une personne très heureuse", + "Aujourd'hui est une journée ensoleillée", + ], + }, + ], + ], +]); + +const MAPPING_ES: PerLanguageMapping = new Map([ + ["text-classification", [`Te quiero. Te amo.`]], + ["token-classification", [`Me llamo Wolfgang y vivo en Berlin`]], + [ + "question-answering", + [ + { + text: `¿Dónde vivo?`, + context: `Me llamo Wolfgang y vivo en Berlin`, + }, + { + text: `¿Quién inventó el submarino?`, + context: `Isaac Peral fue un murciano que inventó el submarino`, + }, + { + text: `¿Cuántas personas hablan español?`, + context: `El español es el segundo idioma más hablado del mundo con más de 442 millones de hablantes`, + }, + ], + ], + [ + "translation", + [ + `Me llamo Wolfgang y vivo en Berlin`, + `Los ingredientes de una tortilla de patatas son: huevos, patatas y cebolla`, + ], + ], + [ + "summarization", + [ + `La torre tiene 324 metros (1.063 pies) de altura, aproximadamente la misma altura que un edificio de 81 pisos y la estructura más alta de París. Su base es cuadrada, mide 125 metros (410 pies) a cada lado. Durante su construcción, la Torre Eiffel superó al Washington Monument para convertirse en la estructura artificial más alta del mundo, un título que mantuvo durante 41 años hasta que el Chrysler Building en la ciudad de Nueva York se terminó en 1930. Fue la primera estructura en llegar Una altura de 300 metros. Debido a la adición de una antena de transmisión en la parte superior de la torre en 1957, ahora es más alta que el Chrysler Building en 5,2 metros (17 pies). Excluyendo los transmisores, la Torre Eiffel es la segunda estructura independiente más alta de Francia después del Viaducto de Millau.`, + ], + ], + [ + "text-generation", + [ + `Me llamo Julien y me gusta`, + `Me llamo Thomas y mi principal`, + `Me llamo Manuel y trabajo en`, + `Érase una vez,`, + `Si tú me dices ven, `, + ], + ], + ["fill-mask", [`Mi nombre es y vivo en Nueva York.`, `El español es un idioma muy en el mundo.`]], + [ + "sentence-similarity", + [ + { + source_sentence: "Esa es una persona feliz", + sentences: ["Ese es un perro feliz", "Esa es una persona muy feliz", "Hoy es un día soleado"], + }, + ], + ], +]); + +const MAPPING_RU: PerLanguageMapping = new Map([ + ["text-classification", [`Ты мне нравишься. Я тебя люблю`]], + ["token-classification", [`Меня зовут Вольфганг и я живу в Берлине`]], + [ + "question-answering", + [ + { + text: `Где живу?`, + context: `Меня зовут Вольфганг и я живу в Берлине`, + }, + ], + ], + ["translation", [`Меня зовут Вольфганг и я живу в Берлине`]], + [ + "summarization", + [ + `Высота башни составляет 324 метра (1063 фута), примерно такая же высота, как у 81-этажного здания, и самое высокое сооружение в Париже. Его основание квадратно, размером 125 метров (410 футов) с любой стороны. Во время строительства Эйфелева башня превзошла монумент Вашингтона, став самым высоким искусственным сооружением в мире, и этот титул она удерживала в течение 41 года до завершения строительство здания Крайслер в Нью-Йорке в 1930 году. Это первое сооружение которое достигло высоты 300 метров. Из-за добавления вещательной антенны на вершине башни в 1957 году она сейчас выше здания Крайслер на 5,2 метра (17 футов). За исключением передатчиков, Эйфелева башня является второй самой высокой отдельно стоящей структурой во Франции после виадука Мийо.`, + ], + ], + ["text-generation", [`Меня зовут Жюльен и`, `Меня зовут Томас и мой основной`, `Однажды`]], + ["fill-mask", [`Меня зовут и я инженер живущий в Нью-Йорке.`]], + [ + "sentence-similarity", + [ + { + source_sentence: "Это счастливый человек", + sentences: ["Это счастливая собака", "Это очень счастливый человек", "Сегодня солнечный день"], + }, + ], + ], +]); + +const MAPPING_UK: PerLanguageMapping = new Map([ + ["translation", [`Мене звати Вольфґанґ і я живу в Берліні.`]], + ["fill-mask", [`Мене звати .`]], +]); + +const MAPPING_IT: PerLanguageMapping = new Map([ + ["text-classification", [`Mi piaci. Ti amo`]], + [ + "token-classification", + [ + `Mi chiamo Wolfgang e vivo a Berlino`, + `Mi chiamo Sarah e vivo a Londra`, + `Mi chiamo Clara e vivo a Berkeley in California.`, + ], + ], + [ + "question-answering", + [ + { + text: `Dove vivo?`, + context: `Mi chiamo Wolfgang e vivo a Berlino`, + }, + { + text: `Dove vivo?`, + context: `Mi chiamo Sarah e vivo a Londra`, + }, + { + text: `Come mio chiamo?`, + context: `Mi chiamo Clara e vivo a Berkeley.`, + }, + ], + ], + ["translation", [`Mi chiamo Wolfgang e vivo a Berlino`, `Mi chiamo Sarah e vivo a Londra`]], + [ + "summarization", + [ + `La torre degli Asinelli è una delle cosiddette due torri di Bologna, simbolo della città, situate in piazza di porta Ravegnana, all'incrocio tra le antiche strade San Donato (ora via Zamboni), San Vitale, Maggiore e Castiglione. Eretta, secondo la tradizione, fra il 1109 e il 1119 dal nobile Gherardo Asinelli, la torre è alta 97,20 metri, pende verso ovest per 2,23 metri e presenta all'interno una scalinata composta da 498 gradini. Ancora non si può dire con certezza quando e da chi fu costruita la torre degli Asinelli. Si presume che la torre debba il proprio nome a Gherardo Asinelli, il nobile cavaliere di fazione ghibellina al quale se ne attribuisce la costruzione, iniziata secondo una consolidata tradizione l'11 ottobre 1109 e terminata dieci anni dopo, nel 1119.`, + ], + ], + [ + "text-generation", + [ + `Mi chiamo Loreto e mi piace`, + `Mi chiamo Thomas e il mio principale`, + `Mi chiamo Marianna, la mia cosa preferita`, + `Mi chiamo Clara e sono`, + `C'era una volta`, + ], + ], + ["fill-mask", [`Roma è la d'Italia.`, `Lo scopo della vita è .`]], + [ + "sentence-similarity", + [ + { + source_sentence: "Questa è una persona felice", + sentences: ["Questo è un cane felice", "Questa è una persona molto felice", "Oggi è una giornata di sole"], + }, + ], + ], +]); + +const MAPPING_FA: PerLanguageMapping = new Map([ + [ + "text-classification", + [`پروژه به موقع تحویل شد و همه چیز خوب بود.`, `سیب‌زمینی بی‌کیفیت بود.`, `قیمت و کیفیت عالی`, `خوب نبود اصلا`], + ], + [ + "token-classification", + [ + `این سریال به صورت رسمی در تاریخ دهم می ۲۰۱۱ توسط شبکه فاکس برای پخش رزرو شد.`, + `دفتر مرکزی شرکت پارس‌مینو در شهر اراک در استان مرکزی قرار دارد.`, + `وی در سال ۲۰۱۳ درگذشت و مسئول خاکسپاری و اقوامش برای او مراسم یادبود گرفتند.`, + ], + ], + [ + "question-answering", + [ + { + text: `من کجا زندگی میکنم؟`, + context: `نام من پژمان است و در گرگان زندگی میکنم.`, + }, + { + text: `نامم چیست و کجا زندگی می‌کنم؟`, + context: `اسمم سارا است و در آفریقای جنوبی زندگی میکنم.`, + }, + { + text: `نام من چیست؟`, + context: `من مریم هستم و در تبریز زندگی می‌کنم.`, + }, + { + text: `بیشترین مساحت جنگل آمازون در کدام کشور است؟`, + context: [ + "آمازون نام بزرگ‌ترین جنگل بارانی جهان است که در شمال آمریکای جنوبی قرار گرفته و بیشتر آن در خاک برزیل و پرو", + "جای دارد. بیش از نیمی از همه جنگل‌های بارانی باقی‌مانده در جهان در آمازون قرار دارد.", + "مساحت جنگل‌های آمازون ۵٫۵ میلیون کیلومتر مربع است که بین ۹ کشور تقسیم شده‌است.", + ].join("\n"), + }, + ], + ], + [ + "translation", + [ + "بیشتر مساحت جنگل‌های آمازون در حوضه آبریز رود آمازون و ۱۱۰۰ شاخه آن واقع شده‌است.", + "مردمان نَبَطی از هزاره‌های یکم و دوم پیش از میلاد در این منطقه زندگی می‌کردند.", + ], + ], + [ + "summarization", + [ + [ + "شاهنامه اثر حکیم ابوالقاسم فردوسی توسی، حماسه‌ای منظوم، بر حسب دست نوشته‌های ", + "موجود دربرگیرنده نزدیک به ۵۰٬۰۰۰ بیت تا نزدیک به ۶۱٬۰۰۰ بیت و یکی از ", + "بزرگ‌ترین و برجسته‌ترین سروده‌های حماسی جهان است که سرایش آن دست‌آوردِ ", + "دست‌کم سی سال کارِ پیوستهٔ این سخن‌سرای نامدار ایرانی است. موضوع این شاهکار ادبی،", + " افسانه‌ها و تاریخ ایران از آغاز تا حملهٔ عرب‌ها به ایران در سدهٔ هفتم میلادی است", + " (شاهنامه از سه بخش اسطوره، پهلوانی و تاریخی تشکیل شده‌است) که در چهار", + " دودمان پادشاهیِ پیشدادیان، کیانیان، اشکانیان و ساسانیان گنجانده می‌شود.", + " شاهنامه بر وزن «فَعولُن فعولن فعولن فَعَلْ»، در بحرِ مُتَقارِبِ مثمَّنِ محذوف نگاشته شده‌است.", + "هنگامی که زبان دانش و ادبیات در ایران زبان عربی بود، فردوسی، با سرودن شاهنامه", + " با ویژگی‌های هدف‌مندی که داشت، زبان پارسی را زنده و پایدار کرد. یکی از ", + " بن‌مایه‌های مهمی که فردوسی برای سرودن شاهنامه از آن استفاده کرد،", + " شاهنامهٔ ابومنصوری بود. شاهنامه نفوذ بسیاری در جهت‌گیری ", + " فرهنگ فارسی و نیز بازتاب‌های شکوه‌مندی در ادبیات جهان داشته‌است و شاعران ", + " بزرگی مانند گوته و ویکتور هوگو از آن به نیکی یاد کرده‌اند.", + ].join("\n"), + ], + ], + ["text-generation", ["اسم من نازنین است و من", "روزی روزگاری"]], + [ + "fill-mask", + [ + `زندگی یک سوال است و این که چگونه کنیم پاسخ این سوال!`, + `زندگی از مرگ پرسید: چرا همه من را دارند اما از تو متنفرند؟`, + ], + ], +]); + +const MAPPING_AR: PerLanguageMapping = new Map([ + ["text-classification", [`أحبك. أهواك`]], + [ + "token-classification", + [`إسمي محمد وأسكن في برلين`, `إسمي ساره وأسكن في لندن`, `إسمي سامي وأسكن في القدس في فلسطين.`], + ], + [ + "question-answering", + [ + { + text: `أين أسكن؟`, + context: `إسمي محمد وأسكن في بيروت`, + }, + { + text: `أين أسكن؟`, + context: `إسمي ساره وأسكن في لندن`, + }, + { + text: `ما اسمي؟`, + context: `اسمي سعيد وأسكن في حيفا.`, + }, + { + text: `ما لقب خالد بن الوليد بالعربية؟`, + context: `خالد بن الوليد من أبطال وقادة الفتح الإسلامي وقد تحدثت عنه اللغات الإنجليزية والفرنسية والإسبانية ولقب بسيف الله المسلول.`, + }, + ], + ], + ["translation", [`إسمي محمد وأسكن في برلين`, `إسمي ساره وأسكن في لندن`]], + [ + "summarization", + [ + `تقع الأهرامات في الجيزة قرب القاهرة في مصر وقد بنيت منذ عدة قرون، وقيل إنها كانت قبورا للفراعنة وتم بناؤها بعملية هندسية رائعة واستقدمت حجارتها من جبل المقطم وتم نقلها بالسفن أو على الرمل، وما تزال شامخة ويقصدها السياح من كافة أرجاء المعمورة.`, + ], + ], + [ + "text-generation", + [ + `إسمي محمد وأحب أن`, + `دع المكارم لا ترحل لبغيتها - واقعد فإنك أنت الطاعم الكاسي.`, + `لماذا نحن هنا؟`, + `القدس مدينة تاريخية، بناها الكنعانيون في`, + `كان يا ما كان في قديم الزمان`, + ], + ], + ["fill-mask", [`باريس فرنسا.`, `فلسفة الحياة هي .`]], + [ + "sentence-similarity", + [ + { + source_sentence: "هذا شخص سعيد", + sentences: ["هذا كلب سعيد", "هذا شخص سعيد جدا", "اليوم هو يوم مشمس"], + }, + ], + ], +]); + +const MAPPING_BN: PerLanguageMapping = new Map([ + ["text-classification", [`বাঙালির ঘরে ঘরে আজ নবান্ন উৎসব।`]], + [ + "token-classification", + [`আমার নাম জাহিদ এবং আমি ঢাকায় বাস করি।`, `তিনি গুগলে চাকরী করেন।`, `আমার নাম সুস্মিতা এবং আমি কলকাতায় বাস করি।`], + ], + ["translation", [`আমার নাম জাহিদ, আমি রংপুরে বাস করি।`, `আপনি কী আজকে বাসায় আসবেন?`]], + [ + "summarization", + [ + `‘ইকোনমিস্ট’ লিখেছে, অ্যান্টিবডির চার মাস স্থায়ী হওয়ার খবরটি দুই কারণে আনন্দের। অ্যান্টিবডি যত দিন পর্যন্ত শরীরে টিকবে, তত দিন সংক্রমণ থেকে সুরক্ষিত থাকা সম্ভব। অর্থাৎ, এমন এক টিকার প্রয়োজন হবে, যা অ্যান্টিবডির উত্পাদনকে প্ররোচিত করতে পারে এবং দীর্ঘস্থায়ী সুরক্ষা দিতে পারে। এগুলো খুঁজে বের করাও সহজ। এটি আভাস দেয়, ব্যাপক হারে অ্যান্টিবডি শনাক্তকরণ ফলাফল মোটামুটি নির্ভুল হওয়া উচিত। দ্বিতীয় আরেকটি গবেষণার নেতৃত্ব দিয়েছেন যুক্তরাজ্যের মেডিকেল রিসার্চ কাউন্সিলের (এমআরসি) ইমিউনোলজিস্ট তাও দং। তিনি টি-সেল শনাক্তকরণে কাজ করেছেন। টি-সেল শনাক্তকরণের প্রক্রিয়া অবশ্য অ্যান্টিবডির মতো এত আলোচিত নয়। তবে সংক্রমণের বিরুদ্ধে লড়াই এবং দীর্ঘমেয়াদি সুরক্ষায় সমান গুরুত্বপূর্ণ ভূমিকা পালন করে। গবেষণাসংক্রান্ত নিবন্ধ প্রকাশিত হয়েছে ‘নেচার ইমিউনোলজি’ সাময়িকীতে। তাঁরা বলছেন, গবেষণার ক্ষেত্রে কোভিড-১৯ মৃদু সংক্রমণের শিকার ২৮ ব্যক্তির রক্তের নমুনা, ১৪ জন গুরুতর অসুস্থ ও ১৬ জন সুস্থ ব্যক্তির রক্তের নমুনা পরীক্ষা করেছেন। গবেষণা নিবন্ধে বলা হয়, সংক্রমিত ব্যক্তিদের ক্ষেত্রে টি-সেলের তীব্র প্রতিক্রিয়া তাঁরা দেখেছেন। এ ক্ষেত্রে মৃদু ও গুরুতর অসুস্থ ব্যক্তিদের ক্ষেত্রে প্রতিক্রিয়ার ভিন্নতা পাওয়া গেছে।`, + ], + ], + ["text-generation", [`আমি রতন এবং আমি`, `তুমি যদি চাও তবে`, `মিথিলা আজকে বড্ড`]], + ["fill-mask", [`আমি বাংলায় গাই।`, `আমি খুব ভালোবাসি। `]], + [ + "question-answering", + [ + { + text: `প্রথম এশিয়া কাপ ক্রিকেট টুর্নামেন্ট কোথায় অনুষ্ঠিত হয় ?`, + context: `প্রথম টুর্নামেন্ট অনুষ্ঠিত হয় ১৯৮৪ সালে সংযুক্ত আরব আমিরাত এর শারজাহ তে যেখানে কাউন্সিলের মূল অফিস ছিল (১৯৯৫ পর্যন্ত)। ভারত শ্রীলঙ্কার সাথে আন্তরিকতাহীন ক্রিকেট সম্পর্কের কারণে ১৯৮৬ সালের টুর্নামেন্ট বর্জন করে। ১৯৯৩ সালে ভারত ও পাকিস্তান এর মধ্যে রাজনৈতিক অস্থিরতার কারণে এটি বাতিল হয়ে যায়। শ্রীলঙ্কা এশিয়া কাপ শুরু থেকে অংশ গ্রহণ করে আসছে। আন্তর্জাতিক ক্রিকেট কাউন্সিল নিয়ম করে দিয়েছে যে এশিয়া কাপের সকল খেলা অনুষ্ঠিত হবে অফিসিয়াল একদিনের আন্তর্জাতিক ক্রিকেট হিসেবে। এসিসি ঘোষনা অনুযায়ী প্রতি দুই বছর পর পর টুর্নামেন্ট অনুষ্ঠিত হয় ২০০৮ সাল থেকে।`, + }, + { + text: `ভারতীয় বাঙালি কথাসাহিত্যিক মহাশ্বেতা দেবীর মৃত্যু কবে হয় ?`, + context: `২০১৬ সালের ২৩ জুলাই হৃদরোগে আক্রান্ত হয়ে মহাশ্বেতা দেবী কলকাতার বেল ভিউ ক্লিনিকে ভর্তি হন। সেই বছরই ২৮ জুলাই একাধিক অঙ্গ বিকল হয়ে তাঁর মৃত্যু ঘটে। তিনি মধুমেহ, সেপ্টিসেমিয়া ও মূত্র সংক্রমণ রোগেও ভুগছিলেন।`, + }, + { + text: `মাস্টারদা সূর্যকুমার সেনের বাবার নাম কী ছিল ?`, + context: `সূর্য সেন ১৮৯৪ সালের ২২ মার্চ চট্টগ্রামের রাউজান থানার নোয়াপাড়ায় অর্থনৈতিক ভাবে অস্বচ্ছল পরিবারে জন্মগ্রহণ করেন। তাঁর পিতার নাম রাজমনি সেন এবং মাতার নাম শশী বালা সেন। রাজমনি সেনের দুই ছেলে আর চার মেয়ে। সূর্য সেন তাঁদের পরিবারের চতুর্থ সন্তান। দুই ছেলের নাম সূর্য ও কমল। চার মেয়ের নাম বরদাসুন্দরী, সাবিত্রী, ভানুমতী ও প্রমিলা। শৈশবে পিতা মাতাকে হারানো সূর্য সেন কাকা গৌরমনি সেনের কাছে মানুষ হয়েছেন। সূর্য সেন ছেলেবেলা থেকেই খুব মনোযোগী ভাল ছাত্র ছিলেন এবং ধর্মভাবাপন্ন গম্ভীর প্রকৃতির ছিলেন।`, + }, + ], + ], + [ + "sentence-similarity", + [ + { + source_sentence: "সে একজন সুখী ব্যক্তি", + sentences: ["সে হ্যাপি কুকুর", "সে খুব সুখী মানুষ", "আজ একটি রৌদ্রোজ্জ্বল দিন"], + }, + ], + ], +]); + +const MAPPING_MN: PerLanguageMapping = new Map([ + ["text-classification", [`Би чамд хайртай`]], + [ + "token-classification", + [ + `Намайг Дорж гэдэг. Би Улаанбаатарт амьдардаг.`, + `Намайг Ганбат гэдэг. Би Увс аймагт төрсөн.`, + `Манай улс таван хошуу малтай.`, + ], + ], + [ + "question-answering", + [ + { + text: `Та хаана амьдардаг вэ?`, + context: `Намайг Дорж гэдэг. Би Улаанбаатарт амьдардаг.`, + }, + { + text: `Таныг хэн гэдэг вэ?`, + context: `Намайг Дорж гэдэг. Би Улаанбаатарт амьдардаг.`, + }, + { + text: `Миний нэрийг хэн гэдэг вэ?`, + context: `Намайг Ганбат гэдэг. Би Увс аймагт төрсөн.`, + }, + ], + ], + ["translation", [`Намайг Дорж гэдэг. Би Улаанбаатарт амьдардаг.`, `Намайг Ганбат гэдэг. Би Увс аймагт төрсөн.`]], + [ + "summarization", + [ + `Монгол Улс (1992 оноос хойш) — дорно болон төв Азид оршдог бүрэн эрхт улс. Хойд талаараа Орос, бусад талаараа Хятад улстай хиллэдэг далайд гарцгүй орон. Нийслэл — Улаанбаатар хот. Алтайн нуруунаас Хянган, Соёноос Говь хүрсэн 1 сая 566 мянган км2 уудам нутагтай, дэлхийд нутаг дэвсгэрийн хэмжээгээр 19-рт жагсдаг. 2015 оны эхэнд Монгол Улсын хүн ам 3 сая хүрсэн (135-р олон). Үндсэндээ монгол үндэстэн (95 хувь), мөн хасаг, тува хүн байна. 16-р зуунаас хойш буддын шашин, 20-р зуунаас шашингүй байдал дэлгэрсэн ба албан хэрэгт монгол хэлээр харилцана.`, + ], + ], + [ + "text-generation", + [`Намайг Дорж гэдэг. Би`, `Хамгийн сайн дуучин бол`, `Миний дуртай хамтлаг бол`, `Эрт урьдын цагт`], + ], + ["fill-mask", [`Монгол улсын Улаанбаатар хотоос ярьж байна.`, `Миний амьдралын зорилго бол .`]], + [ + "automatic-speech-recognition", + [ + { + label: `Common Voice Train Example`, + src: `https://cdn-media.huggingface.co/common_voice/train/common_voice_mn_18577472.wav`, + }, + { + label: `Common Voice Test Example`, + src: `https://cdn-media.huggingface.co/common_voice/test/common_voice_mn_18577346.wav`, + }, + ], + ], + [ + "text-to-speech", + [ + `Би Монгол улсын иргэн.`, + `Энэхүү жишээ нь цаанаа ямар ч утга агуулаагүй болно`, + `Сар шинэдээ сайхан шинэлэж байна уу?`, + ], + ], + [ + "sentence-similarity", + [ + { + source_sentence: "Энэ бол аз жаргалтай хүн юм", + sentences: ["Энэ бол аз жаргалтай нохой юм", "Энэ бол маш их аз жаргалтай хүн юм", "Өнөөдөр нарлаг өдөр байна"], + }, + ], + ], +]); + +const MAPPING_SI: PerLanguageMapping = new Map([ + ["translation", [`සිංහල ඉතා අලංකාර භාෂාවකි.`, `මෙම තාක්ෂණය භාවිතා කරන ඔබට ස්තූතියි.`]], + ["fill-mask", [`මම ගෙදර .`, ` ඉගෙනීමට ගියාය.`]], +]); + +const MAPPING_DE: PerLanguageMapping = new Map([ + [ + "question-answering", + [ + { + text: `Wo wohne ich?`, + context: `Mein Name ist Wolfgang und ich lebe in Berlin`, + }, + { + text: `Welcher Name wird auch verwendet, um den Amazonas-Regenwald auf Englisch zu beschreiben?`, + context: `Der Amazonas-Regenwald, auf Englisch auch als Amazonien oder Amazonas-Dschungel bekannt, ist ein feuchter Laubwald, der den größten Teil des Amazonas-Beckens Südamerikas bedeckt. Dieses Becken umfasst 7.000.000 Quadratkilometer (2.700.000 Quadratmeilen), von denen 5.500.000 Quadratkilometer (2.100.000 Quadratmeilen) vom Regenwald bedeckt sind. Diese Region umfasst Gebiete von neun Nationen. Der größte Teil des Waldes befindet sich in Brasilien mit 60% des Regenwaldes, gefolgt von Peru mit 13%, Kolumbien mit 10% und geringen Mengen in Venezuela, Ecuador, Bolivien, Guyana, Suriname und Französisch-Guayana. Staaten oder Abteilungen in vier Nationen enthalten "Amazonas" in ihren Namen. Der Amazonas repräsentiert mehr als die Hälfte der verbleibenden Regenwälder des Planeten und umfasst den größten und artenreichsten tropischen Regenwald der Welt mit geschätzten 390 Milliarden Einzelbäumen, die in 16.000 Arten unterteilt sind.`, + }, + ], + ], + [ + "sentence-similarity", + [ + { + source_sentence: "Das ist eine glückliche Person", + sentences: [ + "Das ist ein glücklicher Hund", + "Das ist eine sehr glückliche Person", + "Heute ist ein sonniger Tag", + ], + }, + ], + ], +]); + +const MAPPING_DV: PerLanguageMapping = new Map([ + ["text-classification", [`އަހަރެން ގަޔާވޭ. އަހަރެން ލޯބިވޭ`]], + [ + "token-classification", + [ + `އަހަރެންގެ ނަމަކީ އަހުމަދު އަދި އަހަރެން ދިރިއުޅެނީ މާލޭގަ`, + `އަހަރެންގެ ނަމަކީ ސާރާ އަދި އަހަރެން ދިރިއުޅެނީ އުތީމުގަ`, + `އަހަރެންގެ ނަމަކީ އައިޝާ އަދި އަހަރެން ދިރިއުޅެނީ ފޭދޫ، އައްޑޫގަ`, + ], + ], + [ + "question-answering", + [ + { + text: `އަހަރެން ދިރިއުޅެނީ ކޮންތާކު؟`, + context: `އަހަރެންގެ ނަމަކީ އަހުމަދު އަދި އަހަރެން ދިރިއުޅެނީ މާލޭގަ`, + }, + { + text: `އަހަރެން ދިރިއުޅެނީ ކޮންތާކު؟`, + context: `އަހަރެންގެ ނަމަކީ ސާރާ އަދި އަހަރެން ދިރިއުޅެނީ އުތީމުގަ`, + }, + { + text: `އަހަރެންގެ ނަމަކީ ކޮބާ؟`, + context: `އަހަރެންގެ ނަމަކީ އައިޝާ އަދި އަހަރެން ދިރިއުޅެނީ ފޭދޫގަ`, + }, + { + text: `އެމޭޒަން ރެއިންފޮރެސްޓް ސިފަކޮށްދިނުމަށް އިނގިރޭސި ބަހުން ބޭނުންކުރާނީ ކޮންނަމެއް؟`, + context: `އެމޭޒަން ރެއިންފޮރެސްޓް (ޕޯޗުޖީޒް: ފްލޮރެސްޓާ އެމަސޮނިކާ ނުވަތަ އެމަސޮނިއާ؛ ސްޕެނިޝް: ސެލްވާ އެމަސޮނިކާ, އެމަސޮނިއާ ނޫނީ އާންމުކޮށް އެމަޒޯނިއާ؛ ފްރެންޗް: ފޮރޭ އެމެޒޮނިއެން؛ ޑަޗް: އެމެޒޯންރޭގެވައުޑް)، އިގިރޭސި ބަހުން ބުނާ އެމެޒޯނިއާ ނުވަތަ ދަ އެމޭޒަން ޖަންގަލް އަކީ, ސައުތު އެމެރިކާގެ އެމޭޒަން ބޭސިން ސަރަހައްދުގެ ބޮޑުބައެއްގައި ހިމެނޭ މޮއިސްޓް ބޮރޯޑްލީފް ފޮރެސްޓެއެކެވެ. އެމޭޒަން ބޭސިން ސަރަހައްދުގެ ބޮޑު މިނަކީ 7 މިލިއަން އަކަ ކިލޯމީޓަރ (2.7 މިލިއަން އަކަ މައިލް(. މީގެ ތެރެއިން 5.5 މިލިއަން އަކަ ކިލޯމީޓަރ (2.1 މިލިއަން އަކަ މައިލް) އަކީ މި ފޮރެސްޓެވެ. މި ސަރަހައްދުގައި 9 ގައުމަކަށް ނިސްބަތްވާ ޓެރިޓަރީ ހިމެނެއެވެ. 60% އާއިއެކެ އެންމެ ބޮޑު ބައެއް ނިސްބަތްވަނީ ބްރެޒިލްއަށެވެ. އޭގެ ފަހުތުން 13% އާއެކު ޕެރޫ އާއި 10% އާއެކު ކޮލަމްބިއާ އަދި ކުޑަ ބައެއް ހިމެނޭ ގޮތުން ވެނެޒުއެލާ, އެކްއަޑޯ, ބޮލިވިއާ, ގުޔާނާ, ސުރިނާމް އަދި ފްރެންޗް ގްއާނާ އަށް ވެސް ނިސްބަތްވެއެވެ. މީގެ ތެރެއިން 4 ގައުމެއްގައި "އެމެޒޮނާސް" ހިމަނައިގެން ސްޓޭޓް ނުވަތަ ޑިޕާޓްމަންޓް އަކަށް ނަންދީފައިވެއެވެ. މުޅި ދުނިޔޭގައި ބާކީ ހުރި ރެއިންފޮރެސްޓްގެ ތެރެއިން ދެބައިކުޅަ އެއްބަޔަށްވުރެބޮޑުވަރެއް އެމޭޒޮން ރެއިންފޮރެސްޓް ހިއްސާކުރެއެވެ. މިއީ މުޅި ދުނިޔެއިން އެންމޮ ބޮޑު އަދި އެންމެ ބައޮޑައިވަރސް ރެއިންފޮރެސްޓް ޓްރެކްޓެވެ. ލަފާކުރެވޭ ގޮތުން 16 ހާސް ސްޕީޝީސްއަށް ބެހިގެންވާ 390 މިލިއަން ވައްތަރުގެ ގަސް މިތާގައި ހިމެނެއެވެ`, + }, + ], + ], + [ + "translation", + [ + `އަހަރެންގެ ނަމަކީ އަހުމަދު އަދި އަހަރެން ދިރިއުޅެނީ މާލޭގަ`, + `އަހަރެންގެ ނަމަކީ ސާރާ އަދި އަހަރެން ދިރިއުޅެނީ އުތީމުގަ`, + ], + ], + [ + "summarization", + [ + `ޓަވަރުގެ އުސްމިނަކީ 324 މީޓަރު، އެއީ ގާތްގަނޑަކަށް 81 ބުރީގެ އިމާރާތަކާއި އެއްވަރެވެ. އެއީ ޕެރިސްގައި ހުރި އެންމެ އުސް އިމާރާތެވެ. އޭގެ ހަތަރެސްކަނަށް ހުރި ބުޑުގެ ދިގުމިނަކީ ކޮންމެ ފަރާތަކުން 125 މީޓަރެވެ. (410 ފޫޓު) އައިފިލް ޓަވަރު ބިނާކުރި އިރު، ވޮޝިންގްޓަން މޮނިއުމެންޓްގެ އުސްމިން ފަހަނައަޅާ ގޮސް، ދުނިޔޭގައި މީހުން އުފެއްދި ތަންތަނުގެ ތެރެއިން އެންމެ އުސް ތަނުގެ ލަގަބު ލިބުނެވެ. އަދި 1930 ގައި ނިއު ޔޯކްގެ ކްރައިސްލަރ ބިލްޑިންގް ބިނާކުރުމާއި ހަމައަށް 41 އަހަރު ވަންދެން މިލަގަބު ހިފެހެއްޓިއެވެ. މިއީ 300 މީޓަރަށް ވުރެ އުސްކޮށް އިމާރާތްކުރެވުނު ފުރަތަމަ ތަނެވެ. 1957 ގައި ޓަވަރުގެ އެންމެ މަތީގައި ހަރުކުރެވުނު ބްރޯޑްކާސްޓިންގ އޭރިއަލްގެ ސަބަބުން މިހާރު މި ޓަވަރު ކްރައިސްލަރ ބިލްޑިންގއަށް ވުރެ 5.2 މީޓަރ (17 ފޫޓު) އުހެވެ. މި ޓްރާންސްމިޓަރު ނުލާ، އައިފިލް ޓަވަރަކީ، މިލާއު ވިއާޑަކްޓަށް ފަހު ފްރާންސްގައި ހުރި 2 ވަނައަށް އެންމެ އުސް ފްރީސްޓޭންޑިންގ އިމާރާތެވެ`, + ], + ], + [ + "text-generation", + [ + `އަހަރެންގެ ނަމަކީ ޔޫސުފް އަދި އަހަރެންގެ މައިގަނޑު`, + `އަހަރެންގެ ނަމަކީ މަރިއަމް، އަހަރެން އެންމެ ގަޔާވާ`, + `އަހަރެންގެ ނަމަކީ ފާތުމަތު އަދި އަހަރެން`, + `،އެއް ޒަމާނެއްގައި`, + ], + ], + ["fill-mask", [`. މާލެ އަކީ ދިވެހިރާއްޖޭގެ`, `ގަރުދިޔައަކީ ދިވެހިންގެ މެދުގައި ކެއުމެއް.`]], +]); + +export const MAPPING_DEFAULT_WIDGET = new Map([ + ["en", MAPPING_EN], + ["zh", MAPPING_ZH], + ["fr", MAPPING_FR], + ["es", MAPPING_ES], + ["ru", MAPPING_RU], + ["uk", MAPPING_UK], + ["it", MAPPING_IT], + ["fa", MAPPING_FA], + ["ar", MAPPING_AR], + ["bn", MAPPING_BN], + ["mn", MAPPING_MN], + ["si", MAPPING_SI], + ["de", MAPPING_DE], + ["dv", MAPPING_DV], +]); diff --git a/packages/widgets/src/lib/interfaces/InferenceDisplayability.ts b/packages/widgets/src/lib/interfaces/InferenceDisplayability.ts new file mode 100644 index 000000000..06f3fd403 --- /dev/null +++ b/packages/widgets/src/lib/interfaces/InferenceDisplayability.ts @@ -0,0 +1,14 @@ +export enum InferenceDisplayability { + /** + * Yes + */ + Yes = "Yes", + /** + * And then, all the possible reasons why it's no: + */ + ExplicitOptOut = "ExplicitOptOut", + CustomCode = "CustomCode", + LibraryNotDetected = "LibraryNotDetected", + PipelineNotDetected = "PipelineNotDetected", + PipelineLibraryPairNotSupported = "PipelineLibraryPairNotSupported", +} diff --git a/packages/widgets/src/lib/interfaces/Libraries.ts b/packages/widgets/src/lib/interfaces/Libraries.ts new file mode 100644 index 000000000..d723b627c --- /dev/null +++ b/packages/widgets/src/lib/interfaces/Libraries.ts @@ -0,0 +1,766 @@ +import type { ModelLibraryKey } from "@huggingface/tasks"; +/* eslint-disable @typescript-eslint/naming-convention */ +import type { ModelData } from "./Types.js"; + +/** + * Elements configurable by a model library. + */ +export interface LibraryUiElement { + /** + * Name displayed on the main + * call-to-action button on the model page. + */ + btnLabel: string; + /** + * Repo name + */ + repoName: string; + /** + * URL to library's repo + */ + repoUrl: string; + /** + * URL to library's docs + */ + docsUrl?: string; + /** + * Code snippet displayed on model page + */ + snippets: (model: ModelData) => string[]; +} + +function nameWithoutNamespace(modelId: string): string { + const splitted = modelId.split("/"); + return splitted.length === 1 ? splitted[0] : splitted[1]; +} + +//#region snippets + +const adapter_transformers = (model: ModelData) => [ + `from transformers import ${model.config?.adapter_transformers?.model_class} + +model = ${model.config?.adapter_transformers?.model_class}.from_pretrained("${model.config?.adapter_transformers?.model_name}") +model.load_adapter("${model.id}", source="hf")`, +]; + +const allennlpUnknown = (model: ModelData) => [ + `import allennlp_models +from allennlp.predictors.predictor import Predictor + +predictor = Predictor.from_path("hf://${model.id}")`, +]; + +const allennlpQuestionAnswering = (model: ModelData) => [ + `import allennlp_models +from allennlp.predictors.predictor import Predictor + +predictor = Predictor.from_path("hf://${model.id}") +predictor_input = {"passage": "My name is Wolfgang and I live in Berlin", "question": "Where do I live?"} +predictions = predictor.predict_json(predictor_input)`, +]; + +const allennlp = (model: ModelData) => { + if (model.tags?.includes("question-answering")) { + return allennlpQuestionAnswering(model); + } + return allennlpUnknown(model); +}; + +const asteroid = (model: ModelData) => [ + `from asteroid.models import BaseModel + +model = BaseModel.from_pretrained("${model.id}")`, +]; + +function get_base_diffusers_model(model: ModelData): string { + return model.cardData?.base_model ?? "fill-in-base-model"; +} + +const bertopic = (model: ModelData) => [ + `from bertopic import BERTopic + +model = BERTopic.load("${model.id}")`, +]; + +const diffusers_default = (model: ModelData) => [ + `from diffusers import DiffusionPipeline + +pipeline = DiffusionPipeline.from_pretrained("${model.id}")`, +]; + +const diffusers_controlnet = (model: ModelData) => [ + `from diffusers import ControlNetModel, StableDiffusionControlNetPipeline + +controlnet = ControlNetModel.from_pretrained("${model.id}") +pipeline = StableDiffusionControlNetPipeline.from_pretrained( + "${get_base_diffusers_model(model)}", controlnet=controlnet +)`, +]; + +const diffusers_lora = (model: ModelData) => [ + `from diffusers import DiffusionPipeline + +pipeline = DiffusionPipeline.from_pretrained("${get_base_diffusers_model(model)}") +pipeline.load_lora_weights("${model.id}")`, +]; + +const diffusers_textual_inversion = (model: ModelData) => [ + `from diffusers import DiffusionPipeline + +pipeline = DiffusionPipeline.from_pretrained("${get_base_diffusers_model(model)}") +pipeline.load_textual_inversion("${model.id}")`, +]; + +const diffusers = (model: ModelData) => { + if (model.tags?.includes("controlnet")) { + return diffusers_controlnet(model); + } else if (model.tags?.includes("lora")) { + return diffusers_lora(model); + } else if (model.tags?.includes("textual_inversion")) { + return diffusers_textual_inversion(model); + } else { + return diffusers_default(model); + } +}; + +const espnetTTS = (model: ModelData) => [ + `from espnet2.bin.tts_inference import Text2Speech + +model = Text2Speech.from_pretrained("${model.id}") + +speech, *_ = model("text to generate speech from")`, +]; + +const espnetASR = (model: ModelData) => [ + `from espnet2.bin.asr_inference import Speech2Text + +model = Speech2Text.from_pretrained( + "${model.id}" +) + +speech, rate = soundfile.read("speech.wav") +text, *_ = model(speech)[0]`, +]; + +const espnetUnknown = () => [`unknown model type (must be text-to-speech or automatic-speech-recognition)`]; + +const espnet = (model: ModelData) => { + if (model.tags?.includes("text-to-speech")) { + return espnetTTS(model); + } else if (model.tags?.includes("automatic-speech-recognition")) { + return espnetASR(model); + } + return espnetUnknown(); +}; + +const fairseq = (model: ModelData) => [ + `from fairseq.checkpoint_utils import load_model_ensemble_and_task_from_hf_hub + +models, cfg, task = load_model_ensemble_and_task_from_hf_hub( + "${model.id}" +)`, +]; + +const flair = (model: ModelData) => [ + `from flair.models import SequenceTagger + +tagger = SequenceTagger.load("${model.id}")`, +]; + +const keras = (model: ModelData) => [ + `from huggingface_hub import from_pretrained_keras + +model = from_pretrained_keras("${model.id}") +`, +]; + +const open_clip = (model: ModelData) => [ + `import open_clip + +model, preprocess_train, preprocess_val = open_clip.create_model_and_transforms('hf-hub:${model.id}') +tokenizer = open_clip.get_tokenizer('hf-hub:${model.id}')`, +]; + +const paddlenlp = (model: ModelData) => { + if (model.config?.architectures?.[0]) { + const architecture = model.config.architectures[0]; + return [ + [ + `from paddlenlp.transformers import AutoTokenizer, ${architecture}`, + "", + `tokenizer = AutoTokenizer.from_pretrained("${model.id}"${ + model.private ? ", use_auth_token=True" : "" + }, from_hf_hub=True)`, + `model = ${architecture}.from_pretrained("${model.id}"${ + model.private ? ", use_auth_token=True" : "" + }, from_hf_hub=True)`, + ].join("\n"), + ]; + } else { + return [ + [ + `# ⚠️ Type of model unknown`, + `from paddlenlp.transformers import AutoTokenizer, AutoModel`, + "", + `tokenizer = AutoTokenizer.from_pretrained("${model.id}"${ + model.private ? ", use_auth_token=True" : "" + }, from_hf_hub=True)`, + `model = AutoModel.from_pretrained("${model.id}"${ + model.private ? ", use_auth_token=True" : "" + }, from_hf_hub=True)`, + ].join("\n"), + ]; + } +}; + +const pyannote_audio_pipeline = (model: ModelData) => [ + `from pyannote.audio import Pipeline + +pipeline = Pipeline.from_pretrained("${model.id}") + +# inference on the whole file +pipeline("file.wav") + +# inference on an excerpt +from pyannote.core import Segment +excerpt = Segment(start=2.0, end=5.0) + +from pyannote.audio import Audio +waveform, sample_rate = Audio().crop("file.wav", excerpt) +pipeline({"waveform": waveform, "sample_rate": sample_rate})`, +]; + +const pyannote_audio_model = (model: ModelData) => [ + `from pyannote.audio import Model, Inference + +model = Model.from_pretrained("${model.id}") +inference = Inference(model) + +# inference on the whole file +inference("file.wav") + +# inference on an excerpt +from pyannote.core import Segment +excerpt = Segment(start=2.0, end=5.0) +inference.crop("file.wav", excerpt)`, +]; + +const pyannote_audio = (model: ModelData) => { + if (model.tags?.includes("pyannote-audio-pipeline")) { + return pyannote_audio_pipeline(model); + } + return pyannote_audio_model(model); +}; + +const tensorflowttsTextToMel = (model: ModelData) => [ + `from tensorflow_tts.inference import AutoProcessor, TFAutoModel + +processor = AutoProcessor.from_pretrained("${model.id}") +model = TFAutoModel.from_pretrained("${model.id}") +`, +]; + +const tensorflowttsMelToWav = (model: ModelData) => [ + `from tensorflow_tts.inference import TFAutoModel + +model = TFAutoModel.from_pretrained("${model.id}") +audios = model.inference(mels) +`, +]; + +const tensorflowttsUnknown = (model: ModelData) => [ + `from tensorflow_tts.inference import TFAutoModel + +model = TFAutoModel.from_pretrained("${model.id}") +`, +]; + +const tensorflowtts = (model: ModelData) => { + if (model.tags?.includes("text-to-mel")) { + return tensorflowttsTextToMel(model); + } else if (model.tags?.includes("mel-to-wav")) { + return tensorflowttsMelToWav(model); + } + return tensorflowttsUnknown(model); +}; + +const timm = (model: ModelData) => [ + `import timm + +model = timm.create_model("hf_hub:${model.id}", pretrained=True)`, +]; + +const skopsPickle = (model: ModelData, modelFile: string) => { + return [ + `import joblib +from skops.hub_utils import download +download("${model.id}", "path_to_folder") +model = joblib.load( + "${modelFile}" +) +# only load pickle files from sources you trust +# read more about it here https://skops.readthedocs.io/en/stable/persistence.html`, + ]; +}; + +const skopsFormat = (model: ModelData, modelFile: string) => { + return [ + `from skops.hub_utils import download +from skops.io import load +download("${model.id}", "path_to_folder") +# make sure model file is in skops format +# if model is a pickle file, make sure it's from a source you trust +model = load("path_to_folder/${modelFile}")`, + ]; +}; + +const skopsJobLib = (model: ModelData) => { + return [ + `from huggingface_hub import hf_hub_download +import joblib +model = joblib.load( + hf_hub_download("${model.id}", "sklearn_model.joblib") +) +# only load pickle files from sources you trust +# read more about it here https://skops.readthedocs.io/en/stable/persistence.html`, + ]; +}; + +const sklearn = (model: ModelData) => { + if (model.tags?.includes("skops")) { + const skopsmodelFile = model.config?.sklearn?.filename; + const skopssaveFormat = model.config?.sklearn?.model_format; + if (!skopsmodelFile) { + return [`# ⚠️ Model filename not specified in config.json`]; + } + if (skopssaveFormat === "pickle") { + return skopsPickle(model, skopsmodelFile); + } else { + return skopsFormat(model, skopsmodelFile); + } + } else { + return skopsJobLib(model); + } +}; + +const fastai = (model: ModelData) => [ + `from huggingface_hub import from_pretrained_fastai + +learn = from_pretrained_fastai("${model.id}")`, +]; + +const sampleFactory = (model: ModelData) => [ + `python -m sample_factory.huggingface.load_from_hub -r ${model.id} -d ./train_dir`, +]; + +const sentenceTransformers = (model: ModelData) => [ + `from sentence_transformers import SentenceTransformer + +model = SentenceTransformer("${model.id}")`, +]; + +const spacy = (model: ModelData) => [ + `!pip install https://huggingface.co/${model.id}/resolve/main/${nameWithoutNamespace(model.id)}-any-py3-none-any.whl + +# Using spacy.load(). +import spacy +nlp = spacy.load("${nameWithoutNamespace(model.id)}") + +# Importing as module. +import ${nameWithoutNamespace(model.id)} +nlp = ${nameWithoutNamespace(model.id)}.load()`, +]; + +const span_marker = (model: ModelData) => [ + `from span_marker import SpanMarkerModel + +model = SpanMarkerModel.from_pretrained("${model.id}")`, +]; + +const stanza = (model: ModelData) => [ + `import stanza + +stanza.download("${nameWithoutNamespace(model.id).replace("stanza-", "")}") +nlp = stanza.Pipeline("${nameWithoutNamespace(model.id).replace("stanza-", "")}")`, +]; + +const speechBrainMethod = (speechbrainInterface: string) => { + switch (speechbrainInterface) { + case "EncoderClassifier": + return "classify_file"; + case "EncoderDecoderASR": + case "EncoderASR": + return "transcribe_file"; + case "SpectralMaskEnhancement": + return "enhance_file"; + case "SepformerSeparation": + return "separate_file"; + default: + return undefined; + } +}; + +const speechbrain = (model: ModelData) => { + const speechbrainInterface = model.config?.speechbrain?.interface; + if (speechbrainInterface === undefined) { + return [`# interface not specified in config.json`]; + } + + const speechbrainMethod = speechBrainMethod(speechbrainInterface); + if (speechbrainMethod === undefined) { + return [`# interface in config.json invalid`]; + } + + return [ + `from speechbrain.pretrained import ${speechbrainInterface} +model = ${speechbrainInterface}.from_hparams( + "${model.id}" +) +model.${speechbrainMethod}("file.wav")`, + ]; +}; + +const transformers = (model: ModelData) => { + const info = model.transformersInfo; + if (!info) { + return [`# ⚠️ Type of model unknown`]; + } + const remote_code_snippet = info.custom_class ? ", trust_remote_code=True" : ""; + + let autoSnippet: string; + if (info.processor) { + const varName = + info.processor === "AutoTokenizer" + ? "tokenizer" + : info.processor === "AutoFeatureExtractor" + ? "extractor" + : "processor"; + autoSnippet = [ + "# Load model directly", + `from transformers import ${info.processor}, ${info.auto_model}`, + "", + `${varName} = ${info.processor}.from_pretrained("${model.id}"` + remote_code_snippet + ")", + `model = ${info.auto_model}.from_pretrained("${model.id}"` + remote_code_snippet + ")", + ].join("\n"); + } else { + autoSnippet = [ + "# Load model directly", + `from transformers import ${info.auto_model}`, + `model = ${info.auto_model}.from_pretrained("${model.id}"` + remote_code_snippet + ")", + ].join("\n"); + } + + if (model.pipeline_tag) { + const pipelineSnippet = [ + "# Use a pipeline as a high-level helper", + "from transformers import pipeline", + "", + `pipe = pipeline("${model.pipeline_tag}", model="${model.id}"` + remote_code_snippet + ")", + ].join("\n"); + return [pipelineSnippet, autoSnippet]; + } + return [autoSnippet]; +}; + +const transformersJS = (model: ModelData) => { + if (!model.pipeline_tag) { + return [`// ⚠️ Unknown pipeline tag`]; + } + + const libName = "@xenova/transformers"; + + return [ + `// npm i ${libName} +import { pipeline } from '${libName}'; + +// Allocate pipeline +const pipe = await pipeline('${model.pipeline_tag}', '${model.id}');`, + ]; +}; + +const peftTask = (peftTaskType?: string) => { + switch (peftTaskType) { + case "CAUSAL_LM": + return "CausalLM"; + case "SEQ_2_SEQ_LM": + return "Seq2SeqLM"; + case "TOKEN_CLS": + return "TokenClassification"; + case "SEQ_CLS": + return "SequenceClassification"; + default: + return undefined; + } +}; + +const peft = (model: ModelData) => { + const { base_model_name: peftBaseModel, task_type: peftTaskType } = model.config?.peft ?? {}; + const pefttask = peftTask(peftTaskType); + if (!pefttask) { + return [`Task type is invalid.`]; + } + if (!peftBaseModel) { + return [`Base model is not found.`]; + } + + return [ + `from peft import PeftModel, PeftConfig +from transformers import AutoModelFor${pefttask} + +config = PeftConfig.from_pretrained("${model.id}") +model = AutoModelFor${pefttask}.from_pretrained("${peftBaseModel}") +model = PeftModel.from_pretrained(model, "${model.id}")`, + ]; +}; + +const fasttext = (model: ModelData) => [ + `from huggingface_hub import hf_hub_download +import fasttext + +model = fasttext.load_model(hf_hub_download("${model.id}", "model.bin"))`, +]; + +const stableBaselines3 = (model: ModelData) => [ + `from huggingface_sb3 import load_from_hub +checkpoint = load_from_hub( + repo_id="${model.id}", + filename="{MODEL FILENAME}.zip", +)`, +]; + +const nemoDomainResolver = (domain: string, model: ModelData): string[] | undefined => { + switch (domain) { + case "ASR": + return [ + `import nemo.collections.asr as nemo_asr +asr_model = nemo_asr.models.ASRModel.from_pretrained("${model.id}") + +transcriptions = asr_model.transcribe(["file.wav"])`, + ]; + default: + return undefined; + } +}; + +const mlAgents = (model: ModelData) => [`mlagents-load-from-hf --repo-id="${model.id}" --local-dir="./downloads"`]; + +const nemo = (model: ModelData) => { + let command: string[] | undefined = undefined; + // Resolve the tag to a nemo domain/sub-domain + if (model.tags?.includes("automatic-speech-recognition")) { + command = nemoDomainResolver("ASR", model); + } + + return command ?? [`# tag did not correspond to a valid NeMo domain.`]; +}; + +const pythae = (model: ModelData) => [ + `from pythae.models import AutoModel + +model = AutoModel.load_from_hf_hub("${model.id}")`, +]; + +//#endregion + +export const MODEL_LIBRARIES_UI_ELEMENTS: Partial> = { + "adapter-transformers": { + btnLabel: "Adapter Transformers", + repoName: "adapter-transformers", + repoUrl: "https://github.com/Adapter-Hub/adapter-transformers", + docsUrl: "https://huggingface.co/docs/hub/adapter-transformers", + snippets: adapter_transformers, + }, + allennlp: { + btnLabel: "AllenNLP", + repoName: "AllenNLP", + repoUrl: "https://github.com/allenai/allennlp", + docsUrl: "https://huggingface.co/docs/hub/allennlp", + snippets: allennlp, + }, + asteroid: { + btnLabel: "Asteroid", + repoName: "Asteroid", + repoUrl: "https://github.com/asteroid-team/asteroid", + docsUrl: "https://huggingface.co/docs/hub/asteroid", + snippets: asteroid, + }, + bertopic: { + btnLabel: "BERTopic", + repoName: "BERTopic", + repoUrl: "https://github.com/MaartenGr/BERTopic", + snippets: bertopic, + }, + diffusers: { + btnLabel: "Diffusers", + repoName: "🤗/diffusers", + repoUrl: "https://github.com/huggingface/diffusers", + docsUrl: "https://huggingface.co/docs/hub/diffusers", + snippets: diffusers, + }, + espnet: { + btnLabel: "ESPnet", + repoName: "ESPnet", + repoUrl: "https://github.com/espnet/espnet", + docsUrl: "https://huggingface.co/docs/hub/espnet", + snippets: espnet, + }, + fairseq: { + btnLabel: "Fairseq", + repoName: "fairseq", + repoUrl: "https://github.com/pytorch/fairseq", + snippets: fairseq, + }, + flair: { + btnLabel: "Flair", + repoName: "Flair", + repoUrl: "https://github.com/flairNLP/flair", + docsUrl: "https://huggingface.co/docs/hub/flair", + snippets: flair, + }, + keras: { + btnLabel: "Keras", + repoName: "Keras", + repoUrl: "https://github.com/keras-team/keras", + docsUrl: "https://huggingface.co/docs/hub/keras", + snippets: keras, + }, + nemo: { + btnLabel: "NeMo", + repoName: "NeMo", + repoUrl: "https://github.com/NVIDIA/NeMo", + snippets: nemo, + }, + open_clip: { + btnLabel: "OpenCLIP", + repoName: "OpenCLIP", + repoUrl: "https://github.com/mlfoundations/open_clip", + snippets: open_clip, + }, + paddlenlp: { + btnLabel: "paddlenlp", + repoName: "PaddleNLP", + repoUrl: "https://github.com/PaddlePaddle/PaddleNLP", + docsUrl: "https://huggingface.co/docs/hub/paddlenlp", + snippets: paddlenlp, + }, + peft: { + btnLabel: "PEFT", + repoName: "PEFT", + repoUrl: "https://github.com/huggingface/peft", + snippets: peft, + }, + "pyannote-audio": { + btnLabel: "pyannote.audio", + repoName: "pyannote-audio", + repoUrl: "https://github.com/pyannote/pyannote-audio", + snippets: pyannote_audio, + }, + "sentence-transformers": { + btnLabel: "sentence-transformers", + repoName: "sentence-transformers", + repoUrl: "https://github.com/UKPLab/sentence-transformers", + docsUrl: "https://huggingface.co/docs/hub/sentence-transformers", + snippets: sentenceTransformers, + }, + sklearn: { + btnLabel: "Scikit-learn", + repoName: "Scikit-learn", + repoUrl: "https://github.com/scikit-learn/scikit-learn", + snippets: sklearn, + }, + fastai: { + btnLabel: "fastai", + repoName: "fastai", + repoUrl: "https://github.com/fastai/fastai", + docsUrl: "https://huggingface.co/docs/hub/fastai", + snippets: fastai, + }, + spacy: { + btnLabel: "spaCy", + repoName: "spaCy", + repoUrl: "https://github.com/explosion/spaCy", + docsUrl: "https://huggingface.co/docs/hub/spacy", + snippets: spacy, + }, + "span-marker": { + btnLabel: "SpanMarker", + repoName: "SpanMarkerNER", + repoUrl: "https://github.com/tomaarsen/SpanMarkerNER", + docsUrl: "https://huggingface.co/docs/hub/span_marker", + snippets: span_marker, + }, + speechbrain: { + btnLabel: "speechbrain", + repoName: "speechbrain", + repoUrl: "https://github.com/speechbrain/speechbrain", + docsUrl: "https://huggingface.co/docs/hub/speechbrain", + snippets: speechbrain, + }, + stanza: { + btnLabel: "Stanza", + repoName: "stanza", + repoUrl: "https://github.com/stanfordnlp/stanza", + docsUrl: "https://huggingface.co/docs/hub/stanza", + snippets: stanza, + }, + tensorflowtts: { + btnLabel: "TensorFlowTTS", + repoName: "TensorFlowTTS", + repoUrl: "https://github.com/TensorSpeech/TensorFlowTTS", + snippets: tensorflowtts, + }, + timm: { + btnLabel: "timm", + repoName: "pytorch-image-models", + repoUrl: "https://github.com/rwightman/pytorch-image-models", + docsUrl: "https://huggingface.co/docs/hub/timm", + snippets: timm, + }, + transformers: { + btnLabel: "Transformers", + repoName: "🤗/transformers", + repoUrl: "https://github.com/huggingface/transformers", + docsUrl: "https://huggingface.co/docs/hub/transformers", + snippets: transformers, + }, + "transformers.js": { + btnLabel: "Transformers.js", + repoName: "transformers.js", + repoUrl: "https://github.com/xenova/transformers.js", + docsUrl: "https://huggingface.co/docs/hub/transformers-js", + snippets: transformersJS, + }, + fasttext: { + btnLabel: "fastText", + repoName: "fastText", + repoUrl: "https://fasttext.cc/", + snippets: fasttext, + }, + "sample-factory": { + btnLabel: "sample-factory", + repoName: "sample-factory", + repoUrl: "https://github.com/alex-petrenko/sample-factory", + docsUrl: "https://huggingface.co/docs/hub/sample-factory", + snippets: sampleFactory, + }, + "stable-baselines3": { + btnLabel: "stable-baselines3", + repoName: "stable-baselines3", + repoUrl: "https://github.com/huggingface/huggingface_sb3", + docsUrl: "https://huggingface.co/docs/hub/stable-baselines3", + snippets: stableBaselines3, + }, + "ml-agents": { + btnLabel: "ml-agents", + repoName: "ml-agents", + repoUrl: "https://github.com/huggingface/ml-agents", + docsUrl: "https://huggingface.co/docs/hub/ml-agents", + snippets: mlAgents, + }, + pythae: { + btnLabel: "pythae", + repoName: "pythae", + repoUrl: "https://github.com/clementchadebec/benchmark_VAE", + snippets: pythae, + }, +} as const; diff --git a/packages/widgets/src/lib/interfaces/LibrariesToTasks.ts b/packages/widgets/src/lib/interfaces/LibrariesToTasks.ts new file mode 100644 index 000000000..780323f9f --- /dev/null +++ b/packages/widgets/src/lib/interfaces/LibrariesToTasks.ts @@ -0,0 +1,46 @@ +import type { ModelLibraryKey, PipelineType } from "@huggingface/tasks"; + +/** + * Mapping from library name (excluding Transformers) to its supported tasks. + * Inference API should be disabled for all other (library, task) pairs beyond this mapping. + * As an exception, we assume Transformers supports all inference tasks. + * This mapping is generated automatically by "python-api-export-tasks" action in huggingface/api-inference-community repo upon merge. + * Ref: https://github.com/huggingface/api-inference-community/pull/158 + */ +export const LIBRARY_TASK_MAPPING_EXCLUDING_TRANSFORMERS: Partial> = { + "adapter-transformers": ["question-answering", "text-classification", "token-classification"], + allennlp: ["question-answering"], + asteroid: [ + // "audio-source-separation", + "audio-to-audio", + ], + bertopic: ["text-classification"], + diffusers: ["image-to-image", "text-to-image"], + doctr: ["object-detection"], + espnet: ["text-to-speech", "automatic-speech-recognition"], + fairseq: ["text-to-speech", "audio-to-audio"], + fastai: ["image-classification"], + fasttext: ["feature-extraction", "text-classification"], + flair: ["token-classification"], + k2: ["automatic-speech-recognition"], + keras: ["image-classification"], + nemo: ["automatic-speech-recognition"], + open_clip: ["zero-shot-classification", "zero-shot-image-classification"], + paddlenlp: ["conversational", "fill-mask", "summarization", "zero-shot-classification"], + peft: ["text-generation"], + "pyannote-audio": ["automatic-speech-recognition"], + "sentence-transformers": ["feature-extraction", "sentence-similarity"], + sklearn: ["tabular-classification", "tabular-regression", "text-classification"], + spacy: ["token-classification", "text-classification", "sentence-similarity"], + "span-marker": ["token-classification"], + speechbrain: [ + "audio-classification", + "audio-to-audio", + "automatic-speech-recognition", + "text-to-speech", + "text2text-generation", + ], + stanza: ["token-classification"], + timm: ["image-classification"], + mindspore: ["image-classification"], +}; diff --git a/packages/widgets/src/lib/interfaces/README.md b/packages/widgets/src/lib/interfaces/README.md new file mode 100644 index 000000000..d2de77460 --- /dev/null +++ b/packages/widgets/src/lib/interfaces/README.md @@ -0,0 +1,13 @@ +# Interfaces + +This folder contains the definition files (written in Typescript) for the huggingface.co hub's: + +- **pipeline types** a.k.a. **task types** (used to determine which widget to display on the model page, and which inference API to run) +- **default widget inputs** (when they aren't provided in the model card) +- definitions and UI elements for **third party libraries**. + +Please add to any of those definitions by opening a PR. Thanks 🔥 + +⚠️ The hub's definitive doc is at https://huggingface.co/docs/hub. + +## Feedback (feature requests, bugs, etc.) is super welcome 💙💚💛💜♥️🧡 diff --git a/packages/widgets/src/lib/interfaces/Types.ts b/packages/widgets/src/lib/interfaces/Types.ts new file mode 100644 index 000000000..7c9ef752f --- /dev/null +++ b/packages/widgets/src/lib/interfaces/Types.ts @@ -0,0 +1,111 @@ +import type { PipelineType } from "@huggingface/tasks"; +import type { WidgetExample } from "../components/InferenceWidget/shared/WidgetExample.js"; +import type { InferenceDisplayability } from "./InferenceDisplayability.js"; + +/** + * Public interface for model metadata + */ +export interface ModelData { + /** + * id of model (e.g. 'user/repo_name') + */ + id: string; + /** + * Kept for backward compatibility + */ + modelId?: string; + /** + * Whether or not to enable inference widget for this model + */ + inference: InferenceDisplayability; + /** + * is this model private? + */ + private?: boolean; + /** + * this dictionary has useful information about the model configuration + */ + config?: Record & { + adapter_transformers?: { model_class?: string; model_name?: string }; + architectures?: string[]; + sklearn?: { + filename?: string; + model_format?: string; + }; + speechbrain?: { + interface?: string; + }; + peft?: { + base_model_name?: string; + task_type?: string; + }; + }; + /** + * all the model tags + */ + tags?: string[]; + /** + * transformers-specific info to display in the code sample. + */ + transformersInfo?: TransformersInfo; + /** + * Pipeline type + */ + pipeline_tag?: PipelineType | undefined; + /** + * for relevant models, get mask token + */ + mask_token?: string | undefined; + /** + * Example data that will be fed into the widget. + * + * can be set in the model card metadata (under `widget`), + * or by default in `DefaultWidget.ts` + */ + widgetData?: WidgetExample[] | undefined; + /** + * Parameters that will be used by the widget when calling Inference API + * https://huggingface.co/docs/api-inference/detailed_parameters + * + * can be set in the model card metadata (under `inference/parameters`) + * Example: + * inference: + * parameters: + * key: val + */ + cardData?: { + inference?: + | boolean + | { + parameters?: Record; + }; + base_model?: string; + }; + /** + * Library name + * Example: transformers, SpeechBrain, Stanza, etc. + */ + library_name?: string; +} + +/** + * transformers-specific info to display in the code sample. + */ +export interface TransformersInfo { + /** + * e.g. AutoModelForSequenceClassification + */ + auto_model: string; + /** + * if set in config.json's auto_map + */ + custom_class?: string; + /** + * e.g. text-classification + */ + pipeline_tag?: PipelineType; + /** + * e.g. "AutoTokenizer" | "AutoFeatureExtractor" | "AutoProcessor" + */ + processor?: string; +} diff --git a/packages/widgets/src/lib/utils/ViewUtils.ts b/packages/widgets/src/lib/utils/ViewUtils.ts new file mode 100644 index 000000000..86cdd0df1 --- /dev/null +++ b/packages/widgets/src/lib/utils/ViewUtils.ts @@ -0,0 +1,138 @@ +import type { PipelineType } from "@huggingface/tasks"; + +const ESCAPED = { + '"': """, + "'": "'", + "&": "&", + "<": "<", + ">": ">", +}; + +/** + * Returns a function that clamps input value to range [min <= x <= max]. + */ +export function clamp(x: number, min: number, max: number): number { + return Math.max(min, Math.min(x, max)); +} + +/** + * Similar to lodash's uniqBy. In case of multiple items with the same key, + * only the first one is kept. + */ +export function uniqBy(items: T[], itemToKey: (item: T) => K): T[] { + const keys = new Set(items.map((item) => itemToKey(item))); + + return items.filter((item) => { + // Will return true if was in set - e.g. was the first item with its key. + return keys.delete(itemToKey(item)); + }); +} + +export function typedKeys(obj: { [k in K]: V }): K[] { + return Object.keys(obj) as K[]; +} + +/** + * HTML escapes the passed string + */ +export function escape(html: unknown): string { + return String(html).replace(/["'&<>]/g, (match) => ESCAPED[match as keyof typeof ESCAPED]); +} + +/** + * Returns a promise that will resolve after the specified time + * @param ms Number of ms to wait + */ +export function delay(ms: number): Promise { + return new Promise((resolve) => { + setTimeout(() => resolve(), ms); + }); +} + +/** + * "Real" modulo (always >= 0), not remainder. + */ +export function mod(a: number, n: number): number { + return ((a % n) + n) % n; +} + +/** + * Sum of elements in array + */ +export function sum(arr: number[]): number { + return arr.reduce((a, b) => a + b, 0); +} + +/** + * Return a random item from an array + */ +export function randomItem(arr: T[]): T { + return arr[Math.floor(Math.random() * arr.length)]; +} + +/** + * Safely parse JSON + */ +export function parseJSON(x: unknown): T | undefined { + if (!x || typeof x !== "string") { + return undefined; + } + try { + return JSON.parse(x); + } catch (e) { + if (e instanceof SyntaxError) { + console.error(e.name); + } else if (e instanceof Error) { + console.error(e.message); + } else { + console.error(e); + } + return undefined; + } +} + +/** + * Return true if an HTML element is scrolled all the way + */ +export function isFullyScrolled(elt: HTMLElement): boolean { + return elt.scrollHeight - Math.abs(elt.scrollTop) === elt.clientHeight; +} + +/** + * Smoothly scroll an element all the way + */ +export function scrollToMax(elt: HTMLElement, axis: "x" | "y" = "y"): void { + elt.scroll({ + behavior: "smooth", + left: axis === "x" ? elt.scrollWidth : undefined, + top: axis === "y" ? elt.scrollHeight : undefined, + }); +} + +/** + * Converts hex string to rgb array (i.e. [r,g,b]) + * original from https://stackoverflow.com/a/39077686/6558628 + */ +export function hexToRgb(hex: string): number[] { + return ( + hex + .replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, (_, r, g, b) => "#" + r + r + g + g + b + b) + .substring(1) + .match(/.{2}/g) + ?.map((x) => parseInt(x, 16)) || [0, 0, 0] + ); +} + +// Get the Task id corresponding to the modelPipeline (should be === in 99% cases) +export function getPipelineTask(modelPipeline: PipelineType): PipelineType { + return modelPipeline === "text2text-generation" ? "text-generation" : modelPipeline; +} + +/** +* For Tailwind: +bg-blue-100 border-blue-100 dark:bg-blue-800 dark:border-blue-800 +bg-green-100 border-green-100 dark:bg-green-800 dark:border-green-800 +bg-yellow-100 border-yellow-100 dark:bg-yellow-800 dark:border-yellow-800 +bg-purple-100 border-purple-100 dark:bg-purple-800 dark:border-purple-800 +bg-red-100 border-red-100 dark:bg-red-800 dark:border-red-800 +*/ diff --git a/packages/widgets/src/routes/+layout.svelte b/packages/widgets/src/routes/+layout.svelte new file mode 100644 index 000000000..fd328954f --- /dev/null +++ b/packages/widgets/src/routes/+layout.svelte @@ -0,0 +1,7 @@ + + +
+ +
diff --git a/packages/widgets/src/routes/+page.svelte b/packages/widgets/src/routes/+page.svelte new file mode 100644 index 000000000..ad261bedd --- /dev/null +++ b/packages/widgets/src/routes/+page.svelte @@ -0,0 +1,581 @@ + + +
+ + + + +
+

Showcase of all types of inference widgets running

+
+ {#each models as model} + + {/each} +
+
+ +
+

Showcase of all types of disabled inference

+
+ {#each modelsDisabled as model} + + {/each} +
+
+ +
+

Showcase of all types of disabled inference with example outputs

+
+ {#each modelsDisabledWithExamples as model} + + {/each} +
+
+
diff --git a/packages/widgets/src/routes/[...model]/+page.svelte b/packages/widgets/src/routes/[...model]/+page.svelte new file mode 100644 index 000000000..c63519c95 --- /dev/null +++ b/packages/widgets/src/routes/[...model]/+page.svelte @@ -0,0 +1,28 @@ + + +← Back to index + + +
+ {#if data.model} + + +
+			{JSON.stringify(data.model, null, 2)}
+		
+ {:else} +
Error. Probably non existent model. {data.message}
+ {/if} +
diff --git a/packages/widgets/src/routes/[...model]/+page.ts b/packages/widgets/src/routes/[...model]/+page.ts new file mode 100644 index 000000000..ac2edfd7d --- /dev/null +++ b/packages/widgets/src/routes/[...model]/+page.ts @@ -0,0 +1,17 @@ +import type { WidgetProps } from "$lib/components/InferenceWidget/shared/types.js"; +import type { Load } from "@sveltejs/kit"; + +export const load: Load = async ({ params, fetch }): Promise<{ model?: WidgetProps["model"]; message?: string }> => { + const url = `https://huggingface.co/api/models/${params.model}`; + try { + const model = await (await fetch(url)).json(); + return { + model, + }; + } catch { + // todo: throw error() instead + return { + message: `Model ${params.model} not found (probably)`, + }; + } +}; diff --git a/packages/widgets/src/tailwind.css b/packages/widgets/src/tailwind.css new file mode 100644 index 000000000..8f335baed --- /dev/null +++ b/packages/widgets/src/tailwind.css @@ -0,0 +1,226 @@ +@tailwind base; + +@layer base { + html.dark { + --scrollbarBG: #020011; + --thumbBG: #374151; + } + .dark *::-webkit-scrollbar { + width: 11px; + height: 11px; + } + .dark * { + scrollbar-width: thin; + scrollbar-color: var(--thumbBG) var(--scrollbarBG); + } + + .dark input, + .dark textarea, + .dark [contenteditable] { + caret-color: white !important; + } + + .dark *::-webkit-scrollbar-track { + background: var(--scrollbarBG); + } + .dark *::-webkit-scrollbar-thumb { + background-color: var(--thumbBG); + border-radius: 6px; + border: 3px solid var(--scrollbarBG); + } + /* .dark input:-internal-autofill-selected { + @apply bg-gray-925; + } */ + .dark .bg-white { + @apply bg-gray-950; + } + .dark .text-black { + @apply text-gray-200; + } + .dark .text-gray-900 { + @apply text-gray-200; + } + .dark .text-gray-800 { + @apply text-gray-300; + } + .dark .text-gray-700 { + @apply text-gray-300; + } + .dark .text-gray-600 { + @apply text-gray-350; + } + .dark .text-gray-500 { + @apply text-gray-400; + } + .dark .border-gray-200, + .dark .border-gray-100, + .dark .border, + .dark .border-b { + @apply border-gray-850; + } +} + +@tailwind components; + +@layer components { + .btn, + .btn-widget { + @apply inline-flex cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-lg border bg-gradient-to-b px-3 py-1 focus:outline-none focus:ring; + } + .btn { + @apply border-gray-200 from-white to-gray-100 text-gray-800 hover:shadow-inner dark:border-gray-900 dark:from-gray-800 dark:to-gray-950 dark:text-gray-200 dark:hover:from-gray-700; + } + .btn-widget { + @apply h-8 from-gray-50 to-gray-200 hover:from-gray-100 dark:border-gray-900 dark:from-gray-800 dark:to-gray-950 dark:hover:from-gray-700; + } + .btn:disabled, + .btn-widget:disabled { + @apply cursor-not-allowed opacity-50; + } + .btn.btn-lg { + @apply px-4 py-1.5 font-semibold; + } + .overview-card-wrapper { + @apply from-gray-50-to-white rounded-lg border border-gray-100 bg-gradient-to-r via-white text-base shadow-sm hover:via-gray-50 hover:to-gray-100 dark:border-gray-900 dark:via-gray-950 dark:hover:from-gray-950 dark:hover:via-gray-925 dark:hover:to-gray-925; + } + .overview-card-wrapper.white { + @apply from-white to-white dark:from-gray-925 dark:to-gray-950; + } + .tab { + @apply -mb-px flex cursor-pointer select-none items-center border-r border-gray-200 px-4 text-center; + } + .tab:not(.active) { + @apply hover:text-gray-700; + } + .tab.active { + @apply flex items-center border-r border-gray-200 bg-white px-4 text-center font-semibold; + } + .tab-alternate { + @apply flex h-full items-center whitespace-nowrap border-b-2 border-transparent px-2.5 font-medium text-gray-600 dark:text-gray-400 sm:px-3.5; + } + .tab-alternate:not(.active) { + @apply hover:border-gray-200 dark:hover:border-gray-800; + } + .tab-alternate.active { + @apply border-gray-700 font-semibold text-gray-800 dark:border-gray-400; + } + .tag { + @apply mr-1 mb-1 inline-flex h-7 max-w-full flex-none items-center overflow-hidden truncate rounded-lg border border-transparent bg-gradient-to-b text-sm dark:border-gray-900 md:mr-1.5 md:mb-1.5; + } + .tag > span { + @apply px-2; + } + .tag.inactive { + @apply filter-grayscale opacity-50; + } + .tag-blue { + @apply from-blue-50 to-blue-50 text-blue-800 hover:to-blue-100 dark:from-gray-925 dark:to-gray-925 dark:text-gray-300 dark:hover:to-gray-950; + } + .tag-ghost { + @apply from-transparent to-transparent text-gray-400 hover:from-gray-100 hover:to-gray-100 hover:text-gray-600; + } + .tag-green { + @apply from-green-50 to-green-50 text-green-800 hover:to-green-100 dark:from-gray-925 dark:to-gray-925 dark:text-gray-300 dark:hover:to-gray-950; + } + .tag-indigo { + @apply from-indigo-50 to-indigo-50 text-indigo-800 hover:to-indigo-100 dark:from-gray-925 dark:to-gray-925 dark:text-gray-300 dark:hover:to-gray-950; + } + .tag-orange { + @apply from-orange-50 to-orange-50 text-orange-800 hover:to-orange-100 dark:from-gray-925 dark:to-gray-925 dark:text-gray-300 dark:hover:to-gray-950; + } + .tag-purple { + @apply from-purple-50 to-purple-50 text-purple-800 hover:to-purple-100 dark:from-gray-925 dark:to-gray-925 dark:text-gray-300 dark:hover:to-gray-950; + } + .tag-red { + @apply from-red-50 to-red-50 text-red-800 hover:to-red-100 dark:from-gray-925 dark:to-gray-925 dark:text-gray-300 dark:hover:to-gray-950; + } + .tag-yellow { + @apply from-yellow-50 text-yellow-800 hover:to-yellow-100 dark:from-gray-925 dark:to-gray-925 dark:text-gray-300 dark:hover:to-gray-950; + } + .tag-white { + @apply border-gray-100 from-white to-white text-gray-700 hover:to-gray-100 dark:border-gray-900 dark:from-gray-925 dark:to-gray-925 dark:text-gray-300 dark:hover:to-gray-950; + } + .tag-ico { + @apply flex h-7 w-8 flex-none items-center bg-gradient-to-t to-white pl-2 dark:to-gray-950; + } + .tag-ico-blue { + @apply from-blue-50 text-blue-500 dark:from-gray-925; + } + .tag-ico-green { + @apply from-green-50 text-green-500 dark:from-gray-925; + } + .tag-ico-indigo { + @apply from-indigo-50 text-indigo-500 dark:from-gray-925; + } + .tag-ico-orange { + @apply from-orange-50 text-orange-500 dark:from-gray-925; + } + .tag-ico-purple { + @apply from-purple-50 text-purple-500 dark:from-gray-925; + } + .tag-ico-red { + @apply from-red-50 text-red-500 dark:from-gray-925; + } + .tag-ico-yellow { + @apply from-yellow-50 text-yellow-500 dark:from-gray-925; + } + .form-input:not([type="checkbox"]) { + @apply border-2 border-gray-200 shadow-sm + focus:border-blue-300 focus:ring focus:ring-blue-200 + focus:ring-opacity-50 dark:border-gray-700 dark:bg-gray-950; + } + .form-input:not([type="radio"]):not([type="checkbox"]) { + @apply mt-1 block w-full rounded-md; + } + .form-input[type="radio"] { + @apply mt-2 mr-1.5 h-3.5 w-3.5; + } + .form-input[type="checkbox"] { + @apply rounded border-transparent bg-gray-200 text-blue-500 focus:border-transparent focus:ring-1 focus:ring-gray-200 focus:ring-offset-2; + } + .form-input[type="checkbox"]:checked { + @apply bg-blue-500; + } + .form-input:disabled { + @apply cursor-not-allowed opacity-50; + } + .form-input-alt { + @apply h-10 rounded-lg border border-gray-200 px-3 placeholder-gray-400 shadow-inner outline-none focus:shadow-inner focus:ring-1 focus:ring-inset focus:ring-indigo-200 dark:bg-gray-925 dark:focus:ring-indigo-50; + } +} + +@tailwind utilities; + +@layer utilities { + .filter-none { + filter: none; + } + .filter-grayscale { + filter: grayscale(100%); + } + .from-gray-50-to-white { + @apply from-gray-50 to-white dark:from-gray-925 dark:to-gray-950; + } + + .from-gray-100-to-white { + @apply from-gray-100 to-white dark:from-gray-925 dark:to-gray-925; + } + .min-h-main { + min-height: calc(100vh - theme(spacing.16) - 1px); + } +} +.alert { + @apply rounded-md border border-blue-100 bg-blue-50 py-2 px-3 text-blue-900 dark:border-blue-700 dark:bg-blue-800 dark:text-blue-200; +} +.alert a { + @apply underline; +} +.alert-error { + @apply border-red-100 bg-red-50 text-red-900 dark:border-red-700 dark:bg-red-800 dark:text-red-200; +} +.alert-success { + @apply border-green-100 bg-green-50 text-green-900; +} +.alert-warning { + @apply border-yellow-100 bg-yellow-50 text-yellow-900; +} diff --git a/packages/widgets/static/audioProcessor.js b/packages/widgets/static/audioProcessor.js new file mode 100644 index 000000000..f1cde75a5 --- /dev/null +++ b/packages/widgets/static/audioProcessor.js @@ -0,0 +1,39 @@ +// for js/src/lib/components/InferenceWidget/shared/WidgetRealtimeRecorder/Recorder.ts +class AudioDataExtractor extends AudioWorkletProcessor { + _updateIntervalInMS; + _sampleInFrames; + _index; + _buffer; + + constructor() { + super(); + this._updateIntervalInMS = 50; + this._sampleInFrames = parseInt((this._updateIntervalInMS / 1000.0) * sampleRate); + this._index = 0; + this._buffer = new Float32Array(this._sampleInFrames); + } + + process(inputs, outputs, parameters) { + // Note that the input will be down-mixed to mono; however, if no inputs are + // connected then zero channels will be passed in. + if (inputs.length > 0 && inputs[0].length > 0) { + const rest = this._buffer.length - this._index; + if (rest < inputs[0][0].length) { + this._buffer.set(inputs[0][0].slice(0, rest), this._index); + this.port.postMessage({ + buffer: this._buffer.slice(0), + sampling_rate: sampleRate, + }); + this._buffer.fill(0); + this._index = inputs[0][0].length - rest; + } else { + this._buffer.set(inputs[0][0], this._index); + this._index += inputs[0][0].length; + } + } + + return true; + } +} + +registerProcessor("AudioDataExtractor", AudioDataExtractor); diff --git a/packages/widgets/static/cats.jpg b/packages/widgets/static/cats.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e131e8ecdf32c3f751ab0f7b2e5f002683babda2 GIT binary patch literal 173131 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 literal 0 HcmV?d00001 diff --git a/packages/widgets/static/favicon.png b/packages/widgets/static/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..825b9e65af7c104cfb07089bb28659393b4f2097 GIT binary patch literal 1571 zcmV+;2Hg3HP)Px)-AP12RCwC$UE6KzI1p6{F2N z1VK2vi|pOpn{~#djwYcWXTI_im_u^TJgMZ4JMOsSj!0ma>B?-(Hr@X&W@|R-$}W@Z zgj#$x=!~7LGqHW?IO8+*oE1MyDp!G=L0#^lUx?;!fXv@l^6SvTnf^ac{5OurzC#ZMYc20lI%HhX816AYVs1T3heS1*WaWH z%;x>)-J}YB5#CLzU@GBR6sXYrD>Vw(Fmt#|JP;+}<#6b63Ike{Fuo!?M{yEffez;| zp!PfsuaC)>h>-AdbnwN13g*1LowNjT5?+lFVd#9$!8Z9HA|$*6dQ8EHLu}U|obW6f z2%uGv?vr=KNq7YYa2Roj;|zooo<)lf=&2yxM@e`kM$CmCR#x>gI>I|*Ubr({5Y^rb zghxQU22N}F51}^yfDSt786oMTc!W&V;d?76)9KXX1 z+6Okem(d}YXmmOiZq$!IPk5t8nnS{%?+vDFz3BevmFNgpIod~R{>@#@5x9zJKEHLHv!gHeK~n)Ld!M8DB|Kfe%~123&Hz1Z(86nU7*G5chmyDe ziV7$pB7pJ=96hpxHv9rCR29%bLOXlKU<_13_M8x)6;P8E1Kz6G<&P?$P^%c!M5`2` zfY2zg;VK5~^>TJGQzc+33-n~gKt{{of8GzUkWmU110IgI0DLxRIM>0US|TsM=L|@F z0Bun8U!cRB7-2apz=y-7*UxOxz@Z0)@QM)9wSGki1AZ38ceG7Q72z5`i;i=J`ILzL z@iUO?SBBG-0cQuo+an4TsLy-g-x;8P4UVwk|D8{W@U1Zi z!M)+jqy@nQ$p?5tsHp-6J304Q={v-B>66$P0IDx&YT(`IcZ~bZfmn11#rXd7<5s}y zBi9eim&zQc0Dk|2>$bs0PnLmDfMP5lcXRY&cvJ=zKxI^f0%-d$tD!`LBf9^jMSYUA zI8U?CWdY@}cRq6{5~y+)#h1!*-HcGW@+gZ4B};0OnC~`xQOyH19z*TA!!BJ%9s0V3F?CAJ{hTd#*tf+ur-W9MOURF-@B77_-OshsY}6 zOXRY=5%C^*26z?l)1=$bz30!so5tfABdSYzO+H=CpV~aaUefmjvfZ3Ttu9W&W3Iu6 zROlh0MFA5h;my}8lB0tAV-Rvc2Zs_CCSJnx@d`**$idgy-iMob4dJWWw|21b4NB=LfsYp0Aeh{Ov)yztQi;eL4y5 zMi>8^SzKqk8~k?UiQK^^-5d8c%bV?$F8%X~czyiaKCI2=UH=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 + dev: false + /@babel/code-frame@7.18.6: resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} engines: {node: '>=6.9.0'} @@ -74,7 +92,6 @@ packages: engines: {node: '>=12'} dependencies: '@jridgewell/trace-mapping': 0.3.9 - dev: true /@esbuild/android-arm64@0.16.17: resolution: {integrity: sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==} @@ -459,6 +476,16 @@ packages: dev: true optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.35.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.35.0 + eslint-visitor-keys: 3.3.0 + dev: false + /@eslint/eslintrc@2.0.0: resolution: {integrity: sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -508,39 +535,32 @@ packages: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.15 '@jridgewell/trace-mapping': 0.3.18 - dev: true /@jridgewell/resolve-uri@3.1.0: resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} engines: {node: '>=6.0.0'} - dev: true /@jridgewell/set-array@1.1.2: resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} engines: {node: '>=6.0.0'} - dev: true /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} - dev: true /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true /@jridgewell/trace-mapping@0.3.18: resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} dependencies: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 - dev: true /@jridgewell/trace-mapping@0.3.9: resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} dependencies: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.15 - dev: true /@jspm/core@2.0.0-beta.24: resolution: {integrity: sha512-a4Bo/80Z6CoJNor5ldgs6002utmmbttP4JYd/FJ0Ob2fVdf6O6ha5SORBCqrnDnBvMc1TlrHY7dCfat5+H0a6A==} @@ -605,19 +625,15 @@ packages: /@tsconfig/node10@1.0.9: resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - dev: true /@tsconfig/node12@1.0.11: resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true /@tsconfig/node14@1.0.3: resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true /@tsconfig/node16@1.0.4: resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: true /@types/chai-subset@1.3.3: resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} @@ -633,6 +649,10 @@ packages: resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} dev: true + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: false + /@types/http-cache-semantics@4.0.1: resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} dev: true @@ -670,7 +690,7 @@ packages: dev: true optional: true - /@typescript-eslint/eslint-plugin@5.54.0(@typescript-eslint/parser@5.54.0)(eslint@8.35.0)(typescript@4.9.5): + /@typescript-eslint/eslint-plugin@5.54.0(@typescript-eslint/parser@5.54.0)(eslint@8.35.0)(typescript@5.0.2): resolution: {integrity: sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -681,10 +701,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.54.0(eslint@8.35.0)(typescript@4.9.5) + '@typescript-eslint/parser': 5.54.0(eslint@8.35.0)(typescript@5.0.2) '@typescript-eslint/scope-manager': 5.54.0 - '@typescript-eslint/type-utils': 5.54.0(eslint@8.35.0)(typescript@4.9.5) - '@typescript-eslint/utils': 5.54.0(eslint@8.35.0)(typescript@4.9.5) + '@typescript-eslint/type-utils': 5.54.0(eslint@8.35.0)(typescript@5.0.2) + '@typescript-eslint/utils': 5.54.0(eslint@8.35.0)(typescript@5.0.2) debug: 4.3.4 eslint: 8.35.0 grapheme-splitter: 1.0.4 @@ -692,13 +712,13 @@ packages: natural-compare-lite: 1.4.0 regexpp: 3.2.0 semver: 7.5.0 - tsutils: 3.21.0(typescript@4.9.5) - typescript: 4.9.5 + tsutils: 3.21.0(typescript@5.0.2) + typescript: 5.0.2 transitivePeerDependencies: - supports-color dev: false - /@typescript-eslint/parser@5.54.0(eslint@8.35.0)(typescript@4.9.5): + /@typescript-eslint/parser@5.54.0(eslint@8.35.0)(typescript@5.0.2): resolution: {integrity: sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -710,10 +730,10 @@ packages: dependencies: '@typescript-eslint/scope-manager': 5.54.0 '@typescript-eslint/types': 5.54.0 - '@typescript-eslint/typescript-estree': 5.54.0(typescript@4.9.5) + '@typescript-eslint/typescript-estree': 5.54.0(typescript@5.0.2) debug: 4.3.4 eslint: 8.35.0 - typescript: 4.9.5 + typescript: 5.0.2 transitivePeerDependencies: - supports-color dev: false @@ -726,7 +746,7 @@ packages: '@typescript-eslint/visitor-keys': 5.54.0 dev: false - /@typescript-eslint/type-utils@5.54.0(eslint@8.35.0)(typescript@4.9.5): + /@typescript-eslint/type-utils@5.54.0(eslint@8.35.0)(typescript@5.0.2): resolution: {integrity: sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -736,12 +756,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.54.0(typescript@4.9.5) - '@typescript-eslint/utils': 5.54.0(eslint@8.35.0)(typescript@4.9.5) + '@typescript-eslint/typescript-estree': 5.54.0(typescript@5.0.2) + '@typescript-eslint/utils': 5.54.0(eslint@8.35.0)(typescript@5.0.2) debug: 4.3.4 eslint: 8.35.0 - tsutils: 3.21.0(typescript@4.9.5) - typescript: 4.9.5 + tsutils: 3.21.0(typescript@5.0.2) + typescript: 5.0.2 transitivePeerDependencies: - supports-color dev: false @@ -751,7 +771,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false - /@typescript-eslint/typescript-estree@5.54.0(typescript@4.9.5): + /@typescript-eslint/typescript-estree@5.54.0(typescript@5.0.2): resolution: {integrity: sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -766,13 +786,13 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.0 - tsutils: 3.21.0(typescript@4.9.5) - typescript: 4.9.5 + tsutils: 3.21.0(typescript@5.0.2) + typescript: 5.0.2 transitivePeerDependencies: - supports-color dev: false - /@typescript-eslint/utils@5.54.0(eslint@8.35.0)(typescript@4.9.5): + /@typescript-eslint/utils@5.54.0(eslint@8.35.0)(typescript@5.0.2): resolution: {integrity: sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -782,7 +802,7 @@ packages: '@types/semver': 7.3.13 '@typescript-eslint/scope-manager': 5.54.0 '@typescript-eslint/types': 5.54.0 - '@typescript-eslint/typescript-estree': 5.54.0(typescript@4.9.5) + '@typescript-eslint/typescript-estree': 5.54.0(typescript@5.0.2) eslint: 8.35.0 eslint-scope: 5.1.1 eslint-utils: 3.0.0(eslint@8.35.0) @@ -908,7 +928,12 @@ packages: /acorn-walk@8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} - dev: true + + /acorn@8.11.2: + resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: false /acorn@8.8.2: resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} @@ -1009,7 +1034,6 @@ packages: /arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1021,6 +1045,12 @@ packages: deep-equal: 2.2.0 dev: true + /aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + dependencies: + dequal: 2.0.3 + dev: false + /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -1038,6 +1068,12 @@ packages: engines: {node: '>= 0.4'} dev: true + /axobject-query@3.2.1: + resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} + dependencies: + dequal: 2.0.3 + dev: false + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1220,6 +1256,16 @@ packages: string-width: 5.1.2 dev: true + /code-red@1.0.4: + resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + '@types/estree': 1.0.5 + acorn: 8.11.2 + estree-walker: 3.0.3 + periscopic: 3.1.0 + dev: false + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -1279,7 +1325,6 @@ packages: /create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true /cross-fetch@3.1.5: resolution: {integrity: sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==} @@ -1301,6 +1346,14 @@ packages: resolution: {integrity: sha512-Md+Juc7M3uOdbAFwOYlTrccIZ7oCFuzrhKYQjdeUEW/sE1hv17Jp/Bws+ReOPpGVBTYCBoYo+G17V5Qo8QQ75A==} dev: true + /css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.0.2 + dev: false + /css-value@0.0.1: resolution: {integrity: sha512-FUV3xaJ63buRLgHrLQVlVgQnQdR4yqdLGaDu7g8CQcWjInDfM9plBTPI9FRfpahju1UBSaMckeb2/46ApS/V1Q==} dev: true @@ -1390,6 +1443,11 @@ packages: object-keys: 1.1.1 dev: true + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: false + /devtools-protocol@0.0.1094867: resolution: {integrity: sha512-pmMDBKiRVjh0uKK6CT1WqZmM3hBVSgD+N2MrgyV1uNizAZMw4tx6i/RTc+/uCsKSCmg0xXx7arCP/OFcIwTsiQ==} dev: true @@ -1398,7 +1456,7 @@ packages: resolution: {integrity: sha512-ewXoFOkLIpKqsiZ19Rm8l46FqDlj+yACbysDIKlUWqTbZ4BBovWmoCegkLHbfTSjGrrLdaXkD1EKA4VF0O9q3g==} dev: true - /devtools@8.6.6(typescript@4.9.5): + /devtools@8.6.6(typescript@5.0.2): resolution: {integrity: sha512-ea6a7XqflRSVe/eJ28eaJJtjrpoqP3OeZ5fyI7SIGGYvyuw9Ha7ZTL9aMYB9TBDw15iNXjIa1a/wuOjQVd80jA==} engines: {node: ^16.13 || >=18} dependencies: @@ -1411,7 +1469,7 @@ packages: chrome-launcher: 0.15.1 edge-paths: 3.0.5 import-meta-resolve: 2.2.2 - puppeteer-core: 19.7.5(typescript@4.9.5) + puppeteer-core: 19.7.5(typescript@5.0.2) query-selector-shadow-dom: 1.0.1 ua-parser-js: 1.0.34 uuid: 9.0.0 @@ -1427,7 +1485,6 @@ packages: /diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} - dev: true /diff@5.1.0: resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} @@ -1766,8 +1823,8 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - /eslint-config-prettier@8.6.0(eslint@8.35.0): - resolution: {integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==} + /eslint-config-prettier@9.0.0(eslint@8.35.0): + resolution: {integrity: sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==} hasBin: true peerDependencies: eslint: '>=7.0.0' @@ -1775,7 +1832,7 @@ packages: eslint: 8.35.0 dev: false - /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.6.0)(eslint@8.35.0)(prettier@2.8.4): + /eslint-plugin-prettier@4.2.1(eslint-config-prettier@9.0.0)(eslint@8.35.0)(prettier@3.0.0): resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1787,11 +1844,37 @@ packages: optional: true dependencies: eslint: 8.35.0 - eslint-config-prettier: 8.6.0(eslint@8.35.0) - prettier: 2.8.4 + eslint-config-prettier: 9.0.0(eslint@8.35.0) + prettier: 3.0.0 prettier-linter-helpers: 1.0.0 dev: false + /eslint-plugin-svelte@2.30.0(eslint@8.35.0)(svelte@4.2.5)(ts-node@10.9.1): + resolution: {integrity: sha512-2/qj0BJsfM0U2j4EjGb7iC/0nbUvXx1Gn78CdtyuXpi/rSomLPCPwnsZsloXMzlt6Xwe8LBlpRvZObSKEHLP5A==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0-0 + svelte: ^3.37.0 || ^4.0.0-0 + peerDependenciesMeta: + svelte: + optional: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.35.0) + '@jridgewell/sourcemap-codec': 1.4.15 + debug: 4.3.4 + eslint: 8.35.0 + esutils: 2.0.3 + known-css-properties: 0.27.0 + postcss: 8.4.31 + postcss-load-config: 3.1.4(postcss@8.4.31)(ts-node@10.9.1) + postcss-safe-parser: 6.0.0(postcss@8.4.31) + svelte: 4.2.5 + svelte-eslint-parser: 0.30.0(svelte@4.2.5) + transitivePeerDependencies: + - supports-color + - ts-node + dev: false + /eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} @@ -1922,6 +2005,12 @@ packages: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} dev: true + /estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + dependencies: + '@types/estree': 1.0.5 + dev: false + /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -2065,6 +2154,10 @@ packages: /function-bind@1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} /functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} @@ -2223,6 +2316,13 @@ packages: engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 + dev: true + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 /hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} @@ -2351,6 +2451,12 @@ packages: resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} dependencies: has: 1.0.3 + dev: true + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.0 /is-date-object@1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} @@ -2405,6 +2511,12 @@ packages: engines: {node: '>=12'} dev: true + /is-reference@3.0.2: + resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} + dependencies: + '@types/estree': 1.0.5 + dev: false + /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -2528,6 +2640,10 @@ packages: json-buffer: 3.0.1 dev: true + /known-css-properties@0.27.0: + resolution: {integrity: sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==} + dev: false + /ky@0.33.3: resolution: {integrity: sha512-CasD9OCEQSFIam2U8efFK81Yeg8vNMTBUqtMOHlrcWQHqUX3HeCl9Dr31u4toV7emlH8Mymk5+9p0lL6mKb/Xw==} engines: {node: '>=14.16'} @@ -2560,7 +2676,6 @@ packages: /lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} - dev: true /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -2576,6 +2691,10 @@ packages: engines: {node: '>=14'} dev: true + /locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + dev: false + /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -2663,14 +2782,24 @@ packages: sourcemap-codec: 1.4.8 dev: true + /magic-string@0.30.5: + resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false + /make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true /marky@1.2.5: resolution: {integrity: sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==} dev: true + /mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + dev: false + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true @@ -2773,8 +2902,8 @@ packages: thenify-all: 1.6.0 dev: true - /nanoid@3.3.4: - resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -2981,6 +3110,14 @@ packages: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} dev: true + /periscopic@3.1.0: + resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + dependencies: + '@types/estree': 1.0.5 + estree-walker: 3.0.3 + is-reference: 3.0.2 + dev: false + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} @@ -3001,7 +3138,7 @@ packages: pathe: 1.1.0 dev: true - /postcss-load-config@3.1.4(ts-node@10.9.1): + /postcss-load-config@3.1.4(postcss@8.4.31)(ts-node@10.9.1): resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} engines: {node: '>= 10'} peerDependencies: @@ -3014,15 +3151,24 @@ packages: optional: true dependencies: lilconfig: 2.1.0 - ts-node: 10.9.1(@types/node@18.14.6)(typescript@4.9.5) + postcss: 8.4.31 + ts-node: 10.9.1(@types/node@18.14.6)(typescript@5.0.2) yaml: 1.10.2 - dev: true - /postcss@8.4.21: - resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} + /postcss-safe-parser@6.0.0(postcss@8.4.31): + resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.3.3 + dependencies: + postcss: 8.4.31 + dev: false + + /postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} dependencies: - nanoid: 3.3.4 + nanoid: 3.3.7 picocolors: 1.0.0 source-map-js: 1.0.2 @@ -3038,9 +3184,19 @@ packages: fast-diff: 1.2.0 dev: false - /prettier@2.8.4: - resolution: {integrity: sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==} - engines: {node: '>=10.13.0'} + /prettier-plugin-svelte@3.1.0(prettier@3.0.0)(svelte@4.2.5): + resolution: {integrity: sha512-96+AZxs2ESqIFA9j+o+DHqY+BsUglezfl553LQd6VOtTyJq5GPuBEb3ElxF2cerFzKlYKttlH/VcVmRNj5oc3A==} + peerDependencies: + prettier: ^3.0.0 + svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 + dependencies: + prettier: 3.0.0 + svelte: 4.2.5 + dev: false + + /prettier@3.0.0: + resolution: {integrity: sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==} + engines: {node: '>=14'} hasBin: true dev: false @@ -3072,7 +3228,7 @@ packages: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} - /puppeteer-core@19.7.5(typescript@4.9.5): + /puppeteer-core@19.7.5(typescript@5.0.2): resolution: {integrity: sha512-EJuNha+SxPfaYFbkoWU80H3Wb1SiQH5fFyb2xdbWda0ziax5mhV63UMlqNfPeTDIWarwtR4OIcq/9VqY8HPOsg==} engines: {node: '>=14.14.0'} peerDependencies: @@ -3090,7 +3246,7 @@ packages: proxy-from-env: 1.1.0 rimraf: 4.4.0 tar-fs: 2.1.1 - typescript: 4.9.5 + typescript: 5.0.2 unbzip2-stream: 1.4.3 ws: 8.12.1 transitivePeerDependencies: @@ -3197,11 +3353,11 @@ packages: engines: {node: '>=8'} dev: true - /resolve@1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true dependencies: - is-core-module: 2.11.0 + is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -3276,6 +3432,14 @@ packages: hasBin: true optionalDependencies: fsevents: 2.3.2 + dev: true + + /rollup@3.29.4: + resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -3491,6 +3655,40 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + /svelte-eslint-parser@0.30.0(svelte@4.2.5): + resolution: {integrity: sha512-H0Cn2TKr70DU9p/Gb04CfwtS7eK28MYumrHYPaDNkIFbfwGDLADpbERBn7u8G1Rcm2RMr2/mL6mq0J2e8iKFlA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + svelte: ^3.37.0 || ^4.0.0-0 + peerDependenciesMeta: + svelte: + optional: true + dependencies: + eslint-scope: 7.1.1 + eslint-visitor-keys: 3.3.0 + espree: 9.4.1 + svelte: 4.2.5 + dev: false + + /svelte@4.2.5: + resolution: {integrity: sha512-P9YPKsGkNdw4OJbtpd1uzimQHPj7Ai2sPcOHmmD6VgkFhFDmcYevQi7vE4cQ1g8/Vs64aL2TwMoCNFAzv7TPaQ==} + engines: {node: '>=16'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.18 + acorn: 8.11.2 + aria-query: 5.3.0 + axobject-query: 3.2.1 + code-red: 1.0.4 + css-tree: 2.3.1 + estree-walker: 3.0.3 + is-reference: 3.0.2 + locate-character: 3.0.0 + magic-string: 0.30.5 + periscopic: 3.1.0 + dev: false + /tar-fs@2.1.1: resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} dependencies: @@ -3576,7 +3774,7 @@ packages: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} dev: true - /ts-node@10.9.1(@types/node@18.14.6)(typescript@4.9.5): + /ts-node@10.9.1(@types/node@18.14.6)(typescript@5.0.2): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -3602,16 +3800,15 @@ packages: create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 4.9.5 + typescript: 5.0.2 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - dev: true /tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} dev: false - /tsup@6.7.0(ts-node@10.9.1)(typescript@4.9.5): + /tsup@6.7.0(postcss@8.4.31)(ts-node@10.9.1)(typescript@5.0.2): resolution: {integrity: sha512-L3o8hGkaHnu5TdJns+mCqFsDBo83bJ44rlK7e6VdanIvpea4ArPcU3swWGsLVbXak1PqQx/V+SSmFPujBK+zEQ==} engines: {node: '>=14.18'} hasBin: true @@ -3635,26 +3832,27 @@ packages: execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 3.1.4(ts-node@10.9.1) + postcss: 8.4.31 + postcss-load-config: 3.1.4(postcss@8.4.31)(ts-node@10.9.1) resolve-from: 5.0.0 rollup: 3.18.0 source-map: 0.8.0-beta.0 sucrase: 3.32.0 tree-kill: 1.2.2 - typescript: 4.9.5 + typescript: 5.0.2 transitivePeerDependencies: - supports-color - ts-node dev: true - /tsutils@3.21.0(typescript@4.9.5): + /tsutils@3.21.0(typescript@5.0.2): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' dependencies: tslib: 1.14.1 - typescript: 4.9.5 + typescript: 5.0.2 dev: false /type-check@0.4.0: @@ -3678,9 +3876,9 @@ packages: engines: {node: '>=12.20'} dev: true - /typescript@4.9.5: - resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} - engines: {node: '>=4.2.0'} + /typescript@5.0.2: + resolution: {integrity: sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==} + engines: {node: '>=12.20'} hasBin: true /ua-parser-js@1.0.34: @@ -3715,7 +3913,6 @@ packages: /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true /validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -3772,9 +3969,9 @@ packages: dependencies: '@types/node': 18.14.6 esbuild: 0.16.17 - postcss: 8.4.21 - resolve: 1.22.1 - rollup: 3.18.0 + postcss: 8.4.31 + resolve: 1.22.8 + rollup: 3.29.4 optionalDependencies: fsevents: 2.3.2 @@ -3830,7 +4027,7 @@ packages: tinyspy: 1.1.1 vite: 4.1.4(@types/node@18.14.6) vite-node: 0.29.7(@types/node@18.14.6) - webdriverio: 8.6.7(typescript@4.9.5) + webdriverio: 8.6.7(typescript@5.0.2) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -3861,7 +4058,7 @@ packages: - utf-8-validate dev: true - /webdriverio@8.6.7(typescript@4.9.5): + /webdriverio@8.6.7(typescript@5.0.2): resolution: {integrity: sha512-uaBovfcJQ+g5olfveeku2GT6kGx8qZ74fVvxZVRM/6FYWK6eMT//MPVnmM9UducYHApcxXFULrA+UTtOY5EEag==} engines: {node: ^16.13 || >=18} dependencies: @@ -3876,7 +4073,7 @@ packages: aria-query: 5.1.3 css-shorthand-properties: 1.1.1 css-value: 0.0.1 - devtools: 8.6.6(typescript@4.9.5) + devtools: 8.6.6(typescript@5.0.2) devtools-protocol: 0.0.1119014 grapheme-splitter: 1.0.4 import-meta-resolve: 2.2.2 @@ -3884,7 +4081,7 @@ packages: lodash.clonedeep: 4.5.0 lodash.zip: 4.2.0 minimatch: 7.4.2 - puppeteer-core: 19.7.5(typescript@4.9.5) + puppeteer-core: 19.7.5(typescript@5.0.2) query-selector-shadow-dom: 1.0.1 resq: 1.11.0 rgb2hex: 0.2.5 @@ -4016,7 +4213,6 @@ packages: /yaml@1.10.2: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} - dev: true /yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} @@ -4028,7 +4224,6 @@ packages: /yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} - dev: true /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 8991ef9f1..24042e0d7 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -6,3 +6,4 @@ packages: - "packages/agents" - "packages/languages" - "packages/tasks" + - "packages/widgets"