Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/skit/src/marketplace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ pub struct ModelSpec {
pub source: ModelSource,
pub expected_size_bytes: Option<u64>,
pub sha256: Option<String>,
#[serde(default)]
pub file_checksums: HashMap<String, String>,
pub license: Option<String>,
pub license_url: Option<String>,
#[serde(default)]
Expand Down
11 changes: 9 additions & 2 deletions apps/skit/src/marketplace_installer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1291,8 +1291,6 @@ impl PluginInstaller {
.into());
}
let revision = revision.as_deref().unwrap_or("main");
let expected_sha256 =
if files.len() == 1 { model.sha256.as_deref() } else { None };
for file in files {
if cancel.is_cancelled() {
return Err(InstallError::Cancelled);
Expand All @@ -1301,6 +1299,11 @@ impl PluginInstaller {
if !is_safe_relative_path(file_path) {
return Err(anyhow!("Invalid model file path '{file}'").into());
}
let expected_sha256 = model
.file_checksums
.get(file.as_str())
.map(String::as_str)
.or(if files.len() == 1 { model.sha256.as_deref() } else { None });
let target_path = self.models_dir.join(file_path);
let display_name = file.as_str();
let url = huggingface_model_url(repo_id, revision, file)?;
Expand Down Expand Up @@ -1970,6 +1973,7 @@ fn now_ms() -> u128 {
mod tests {
use super::*;
use anyhow::{anyhow, bail, Context, Result};
use std::collections::HashMap;
use std::sync::Arc;

use crate::plugins::UnifiedPluginManager;
Expand Down Expand Up @@ -2160,6 +2164,7 @@ mod tests {
source: crate::marketplace::ModelSource::Url { url: url.clone() },
expected_size_bytes: Some(payload.len() as u64),
sha256: Some(hash),
file_checksums: HashMap::new(),
license: None,
license_url: None,
gated: false,
Expand Down Expand Up @@ -2256,6 +2261,7 @@ mod tests {
source: crate::marketplace::ModelSource::Url { url: url.clone() },
expected_size_bytes: Some(payload.len() as u64),
sha256: Some(hash),
file_checksums: HashMap::new(),
license: None,
license_url: None,
gated: false,
Expand Down Expand Up @@ -2319,6 +2325,7 @@ mod tests {
},
expected_size_bytes: None,
sha256: None,
file_checksums: HashMap::new(),
license: None,
license_url: None,
gated: true,
Expand Down
10 changes: 6 additions & 4 deletions dist/registry/plugins/helsinki/0.1.0/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
"files": [
"opus-mt-en-es.tar.bz2"
],
"expected_size_bytes": 284844308,
"expected_size_bytes": 297199216,
"license": "Apache-2.0",
"license_url": "https://huggingface.co/Helsinki-NLP/opus-mt-en-es"
"license_url": "https://huggingface.co/Helsinki-NLP/opus-mt-en-es",
"sha256": "6624ec0babce458c0771f493460e62f7e7dc6d4d832e56dbde1621444d4b37cf"
},
{
"id": "opus-mt-es-en",
Expand All @@ -38,9 +39,10 @@
"files": [
"opus-mt-es-en.tar.bz2"
],
"expected_size_bytes": 285443600,
"expected_size_bytes": 296814376,
"license": "Apache-2.0",
"license_url": "https://huggingface.co/Helsinki-NLP/opus-mt-es-en"
"license_url": "https://huggingface.co/Helsinki-NLP/opus-mt-es-en",
"sha256": "01a0ddd203b3343d02c013539d4d8f0dfcd747585c9b26f0c3f90f7a11d7cde9"
}
]
}
4 changes: 4 additions & 0 deletions dist/registry/plugins/matcha/0.1.0/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
"matcha-icefall-en_US-ljspeech/vocos-22khz-univ.onnx"
],
"expected_size_bytes": 130630855,
"file_checksums": {
"matcha-icefall-en_US-ljspeech.tar.bz2": "f7862f5d93b956561ee7aca86bf33504f47726c1d5a559066f3cef8fab6c3e23",
"matcha-icefall-en_US-ljspeech/vocos-22khz-univ.onnx": "0574a135aa1db2de6e181050db2ec528496cacd4a4701fc5d7faf9f9804c0081"
},
"license": "CC-BY-4.0",
"license_url": "https://keithito.com/LJ-Speech-Dataset/"
}
Expand Down
3 changes: 2 additions & 1 deletion dist/registry/plugins/nllb/0.1.0/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
],
"expected_size_bytes": 1135260128,
"license": "CC-BY-NC-4.0",
"license_url": "https://huggingface.co/facebook/nllb-200-distilled-600M"
"license_url": "https://huggingface.co/facebook/nllb-200-distilled-600M",
"sha256": "6c95a9bc42239a189c71d32aeb66b3108a4fef97d194e3360f3a749671a05c35"
}
]
}
10 changes: 6 additions & 4 deletions docs/public/registry/plugins/helsinki/0.1.0/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
"files": [
"opus-mt-en-es.tar.bz2"
],
"expected_size_bytes": 284844308,
"expected_size_bytes": 297199216,
"license": "Apache-2.0",
"license_url": "https://huggingface.co/Helsinki-NLP/opus-mt-en-es"
"license_url": "https://huggingface.co/Helsinki-NLP/opus-mt-en-es",
"sha256": "6624ec0babce458c0771f493460e62f7e7dc6d4d832e56dbde1621444d4b37cf"
},
{
"id": "opus-mt-es-en",
Expand All @@ -38,9 +39,10 @@
"files": [
"opus-mt-es-en.tar.bz2"
],
"expected_size_bytes": 285443600,
"expected_size_bytes": 296814376,
"license": "Apache-2.0",
"license_url": "https://huggingface.co/Helsinki-NLP/opus-mt-es-en"
"license_url": "https://huggingface.co/Helsinki-NLP/opus-mt-es-en",
"sha256": "01a0ddd203b3343d02c013539d4d8f0dfcd747585c9b26f0c3f90f7a11d7cde9"
}
]
}
4 changes: 4 additions & 0 deletions docs/public/registry/plugins/matcha/0.1.0/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
"matcha-icefall-en_US-ljspeech/vocos-22khz-univ.onnx"
],
"expected_size_bytes": 130630855,
"file_checksums": {
"matcha-icefall-en_US-ljspeech.tar.bz2": "f7862f5d93b956561ee7aca86bf33504f47726c1d5a559066f3cef8fab6c3e23",
"matcha-icefall-en_US-ljspeech/vocos-22khz-univ.onnx": "0574a135aa1db2de6e181050db2ec528496cacd4a4701fc5d7faf9f9804c0081"
},
"license": "CC-BY-4.0",
"license_url": "https://keithito.com/LJ-Speech-Dataset/"
}
Expand Down
3 changes: 2 additions & 1 deletion docs/public/registry/plugins/nllb/0.1.0/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
],
"expected_size_bytes": 1135260128,
"license": "CC-BY-NC-4.0",
"license_url": "https://huggingface.co/facebook/nllb-200-distilled-600M"
"license_url": "https://huggingface.co/facebook/nllb-200-distilled-600M",
"sha256": "6c95a9bc42239a189c71d32aeb66b3108a4fef97d194e3360f3a749671a05c35"
}
]
}
17 changes: 12 additions & 5 deletions marketplace/official-plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
"files": [
"opus-mt-en-es.tar.bz2"
],
"expected_size_bytes": 284844308,
"expected_size_bytes": 297199216,
"license": "Apache-2.0",
"license_url": "https://huggingface.co/Helsinki-NLP/opus-mt-en-es"
"license_url": "https://huggingface.co/Helsinki-NLP/opus-mt-en-es",
"sha256": "6624ec0babce458c0771f493460e62f7e7dc6d4d832e56dbde1621444d4b37cf"
},
{
"id": "opus-mt-es-en",
Expand All @@ -35,9 +36,10 @@
"files": [
"opus-mt-es-en.tar.bz2"
],
"expected_size_bytes": 285443600,
"expected_size_bytes": 296814376,
"license": "Apache-2.0",
"license_url": "https://huggingface.co/Helsinki-NLP/opus-mt-es-en"
"license_url": "https://huggingface.co/Helsinki-NLP/opus-mt-es-en",
"sha256": "01a0ddd203b3343d02c013539d4d8f0dfcd747585c9b26f0c3f90f7a11d7cde9"
}
]
},
Expand Down Expand Up @@ -92,6 +94,10 @@
"matcha-icefall-en_US-ljspeech/vocos-22khz-univ.onnx"
],
"expected_size_bytes": 130630855,
"file_checksums": {
"matcha-icefall-en_US-ljspeech.tar.bz2": "f7862f5d93b956561ee7aca86bf33504f47726c1d5a559066f3cef8fab6c3e23",
"matcha-icefall-en_US-ljspeech/vocos-22khz-univ.onnx": "0574a135aa1db2de6e181050db2ec528496cacd4a4701fc5d7faf9f9804c0081"
},
"license": "CC-BY-4.0",
"license_url": "https://keithito.com/LJ-Speech-Dataset/"
}
Expand Down Expand Up @@ -120,7 +126,8 @@
],
"expected_size_bytes": 1135260128,
"license": "CC-BY-NC-4.0",
"license_url": "https://huggingface.co/facebook/nllb-200-distilled-600M"
"license_url": "https://huggingface.co/facebook/nllb-200-distilled-600M",
"sha256": "6c95a9bc42239a189c71d32aeb66b3108a4fef97d194e3360f3a749671a05c35"
}
]
},
Expand Down
6 changes: 4 additions & 2 deletions plugins/native/helsinki/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ models:
revision: main
files:
- opus-mt-en-es.tar.bz2
expected_size_bytes: 284844308
expected_size_bytes: 297199216
license: Apache-2.0
license_url: https://huggingface.co/Helsinki-NLP/opus-mt-en-es
sha256: 6624ec0babce458c0771f493460e62f7e7dc6d4d832e56dbde1621444d4b37cf
- id: opus-mt-es-en
name: OPUS-MT es-en
default: false
Expand All @@ -27,6 +28,7 @@ models:
revision: main
files:
- opus-mt-es-en.tar.bz2
expected_size_bytes: 285443600
expected_size_bytes: 296814376
license: Apache-2.0
license_url: https://huggingface.co/Helsinki-NLP/opus-mt-es-en
sha256: 01a0ddd203b3343d02c013539d4d8f0dfcd747585c9b26f0c3f90f7a11d7cde9
3 changes: 3 additions & 0 deletions plugins/native/matcha/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@ models:
- matcha-icefall-en_US-ljspeech.tar.bz2
- matcha-icefall-en_US-ljspeech/vocos-22khz-univ.onnx
expected_size_bytes: 130630855
file_checksums:
matcha-icefall-en_US-ljspeech.tar.bz2: f7862f5d93b956561ee7aca86bf33504f47726c1d5a559066f3cef8fab6c3e23
matcha-icefall-en_US-ljspeech/vocos-22khz-univ.onnx: 0574a135aa1db2de6e181050db2ec528496cacd4a4701fc5d7faf9f9804c0081
license: CC-BY-4.0
license_url: https://keithito.com/LJ-Speech-Dataset/
1 change: 1 addition & 0 deletions plugins/native/nllb/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ models:
expected_size_bytes: 1135260128
license: CC-BY-NC-4.0
license_url: https://huggingface.co/facebook/nllb-200-distilled-600M
sha256: 6c95a9bc42239a189c71d32aeb66b3108a4fef97d194e3360f3a749671a05c35
1 change: 1 addition & 0 deletions ui/src/types/marketplace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export type ModelSpec = ModelSource & {
default?: boolean;
expected_size_bytes?: number | null;
sha256?: string | null;
file_checksums?: Record<string, string>;
license?: string | null;
license_url?: string | null;
gated?: boolean;
Expand Down
44 changes: 38 additions & 6 deletions ui/src/views/PluginsView.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,19 +335,20 @@ export const StepList = styled.div`

export const StepRow = styled.div`
display: flex;
flex-direction: column;
gap: 4px;
align-items: center;
gap: 8px;
padding: 8px 10px;
border-radius: 8px;
border: 1px solid var(--sk-border);
background: var(--sk-panel-bg);
`;

export const StepHeader = styled.div`
export const StepContent = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
flex-direction: column;
gap: 4px;
flex: 1;
min-width: 0;
`;

export const StepName = styled.div`
Expand All @@ -357,6 +358,9 @@ export const StepName = styled.div`
`;

export const StepStatus = styled.div<{ $status: string }>`
display: flex;
align-items: center;
gap: 4px;
font-size: 11px;
font-weight: 600;
color: ${(props) => {
Expand Down Expand Up @@ -429,3 +433,31 @@ export const ModelMeta = styled.span`
font-size: 11px;
color: var(--sk-text-muted);
`;

export const LicenseLink = styled.a`
font-size: inherit;
color: var(--sk-primary);
text-decoration: none;

&:hover {
text-decoration: underline;
}
`;

export const StepSpinner = styled.span`
display: inline-block;
width: 12px;
height: 12px;
border: 2px solid var(--sk-border);
border-top-color: var(--sk-primary);
border-radius: 50%;
flex-shrink: 0;

@keyframes step-spin {
to {
transform: rotate(360deg);
}
}

animation: step-spin 0.8s linear infinite;
`;
16 changes: 10 additions & 6 deletions ui/src/views/plugins/MarketplaceJobPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ import {
Row,
Section,
SectionTitle,
StepContent,
StepError,
StepHeader,
StepList,
StepMeta,
StepName,
StepRow,
StepSpinner,
StepStatus,
Subtle,
} from '../PluginsView.styles';
Expand Down Expand Up @@ -58,12 +59,15 @@ export const MarketplaceJobPanel: React.FC<MarketplaceJobPanelProps> = ({
const progress = formatStepProgress(step);
return (
<StepRow key={step.name}>
<StepHeader>
<StepContent>
<StepName>{formatStepName(step.name)}</StepName>
<StepStatus $status={step.status}>{step.status}</StepStatus>
</StepHeader>
{progress && <StepMeta>{progress}</StepMeta>}
{step.error && <StepError>{step.error}</StepError>}
{progress && <StepMeta>{progress}</StepMeta>}
{step.error && <StepError>{step.error}</StepError>}
</StepContent>
<StepStatus $status={step.status}>
{step.status}
{step.status === 'running' && <StepSpinner />}
</StepStatus>
</StepRow>
);
})}
Expand Down
13 changes: 12 additions & 1 deletion ui/src/views/plugins/MarketplaceModelsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { CheckboxWithLabel } from '@/components/ui/Checkbox';
import type { MarketplacePluginDetails } from '@/types/marketplace';

import {
LicenseLink,
ModelMeta,
ModelName,
ModelRow,
Expand Down Expand Up @@ -81,7 +82,17 @@ const MarketplaceModelsSelection: React.FC<{
/>
<ModelName>{displayName}</ModelName>
<ModelMeta>{sizeLabel}</ModelMeta>
{model.license && <ModelMeta>{model.license}</ModelMeta>}
{(model.license || model.license_url) && (
<ModelMeta>
{model.license_url ? (
<LicenseLink href={model.license_url} target="_blank" rel="noopener noreferrer">
{model.license || model.license_url}
</LicenseLink>
) : (
model.license
)}
</ModelMeta>
)}
<ModelMeta>
{fileCount} file{fileCount === 1 ? '' : 's'}
</ModelMeta>
Expand Down
Loading
Loading