release: v0.2.37 — zero-argument startup, first-run wizard, real download progress

Startup no longer needs arguments: the config is created on first launch, a busy
port is swapped for a free one, the console is open by default, and the browser
lands on a setup wizard that downloads a ready-made .cmf model and wires it into
routing (managed server + routing.default) when you press Finish.

Download progress was reported from curl's own meter, which prints a full
0→100% bar for the -L redirect hop before the transfer starts — so every job
showed 100% and then hung. Progress now comes from bytes on disk against the
size from the HuggingFace tree (or a HEAD request).

The UI and the gateway also disagreed about the output file name, so a finished
download never marked its card as downloaded; the gateway now returns the exact
stem and the UI sends it back verbatim for download, progress and delete.

Featured models are read live from the infosave HF account in both the wizard
and Import, and all 432 UI strings now exist in every one of the 7 languages.
This commit is contained in:
infosave2007
2026-08-06 17:56:42 +03:00
parent ad438a5dcb
commit 9ec8861464
25 changed files with 3154 additions and 234 deletions
+191 -3
View File
@@ -30,7 +30,7 @@ export default {
"nav.routing": "Routage",
"nav.protocols": "Protocoles",
"nav.keys": "Clés API",
"nav.playground": "Playground",
"nav.playground": "Bac à sable",
"nav.settings": "Paramètres",
"nav.foot": "Gateway · v{v}",
"nav.billing": "Clé routeur & facturation",
@@ -76,7 +76,7 @@ export default {
"dash.groupby.label": "par tâche",
"dash.groupby.account": "par compte",
"dash.recent.title": "Requêtes récentes",
"dash.recent.empty": "Aucune requête enregistrée. Essayez le Playground.",
"dash.recent.empty": "Aucune requête enregistrée. Essayez le Bac à sable.",
"dash.col.time": "Heure",
"dash.col.model": "Modèle",
"dash.col.tier": "Niveau",
@@ -189,7 +189,7 @@ export default {
"keys.allowAll": "tous",
// playground
"pg.title": "Playground",
"pg.title": "Bac à sable",
"pg.subtitle": "Envoyez une invite via le pipeline en direct et inspectez la décision de routage.",
"pg.system": "Invite système",
"pg.systemPlaceholder": "message système optionnel",
@@ -280,4 +280,192 @@ export default {
"settings.cache.ttl": "TTL d'entrée",
"settings.cache.embed": "Modèle d'embeddings",
"settings.cache.note": "Les paramètres du cache prennent effet après un redémarrage.",
// ── translated from en.js (previously falling back to English) ──
// nav
"nav.import": "Importer un modèle",
// dash
"dash.clear": "Effacer les journaux",
"dash.clearConfirm": "Effacer toutes les statistiques et les journaux enregistrés ? Action irréversible.",
"dash.cleared": "Journaux effacés",
// models
"models.form.idOrModel": "Saisissez un identifiant ou un nom de modèle",
"models.form.apiKey": "Clé API",
"models.form.apiKeyPlaceholder": "collez votre clé API",
"models.form.apiKeyNotNeeded": "non requise (serveur local)",
"models.form.apiKeyHint": "Stockée de façon sécurisée sur la passerelle ; elle n'est plus affichée ensuite.",
"models.form.keyStored": "Une clé est enregistrée — laissez vide pour la conserver, ou collez-en une nouvelle.",
"models.form.keyFromEnv": "Une clé issue d'une variable d'environnement est utilisée.",
"models.form.paramsTitle": "Paramètres de génération et de raisonnement (O(1), MTP, température)",
"models.form.temperature": "Température",
"models.form.temperatureHint": "Température de génération (0.0 = déterministe, 1.0+ = créatif).",
"models.form.topP": "Top-P (échantillonnage nucleus)",
"models.form.topPHint": "Seuil d'échantillonnage (0.0 .. 1.0).",
"models.form.maxTokens": "Tokens max.",
"models.form.maxTokensHint": "Nombre maximal de tokens générés.",
"models.form.thinkBudget": "Mode raisonnement / budget de réflexion",
"models.form.thinkBudgetHint": "Budget de tokens de raisonnement (0 = désactivé, N > 0 = maximum de tokens de raisonnement).",
"models.form.systemPrompt": "Prompt système par défaut",
"models.form.systemPromptHint": "Ajouté automatiquement si la requête ne contient pas de prompt système.",
"models.form.systemPromptPlaceholder": "Vous êtes un assistant utile…",
"models.form.testKey": "Tester et charger les modèles",
"models.form.testing": "vérification…",
"models.form.foundModels": "{n} modèles chargés",
"models.form.modelPlaceholder": "tapez pour rechercher…",
"models.form.modelHint": "Cliquez sur « Tester et charger les modèles » pour récupérer la liste liée à votre clé, puis choisissez-en un.",
"models.managed": "géré",
"models.managedHint": "Fourni par le serveur CMF géré (Paramètres → Modèles locaux). Configurez-le là-bas.",
// settings
"settings.router.enabled": "Utiliser le routeur (désactivé = modèles locaux uniquement)",
"settings.cmf": "Modèles locaux (CMF)",
"settings.cmf.localOnly": "Utiliser uniquement les modèles locaux",
"settings.cmf.manage": "Lancer un serveur de modèle local",
"settings.cmf.autoInstall": "Installer cortiq automatiquement (crates.io)",
"settings.cmf.autoUpdate": "Mettre cortiq à jour automatiquement",
"settings.cmf.model": "Chemin du modèle .cmf local",
"settings.cmf.port": "Port du serveur local",
"settings.cmf.modelId": "Identifiant du modèle dans le pool",
"settings.cmf.note": "Sert un .cmf local via cortiq (github.com/infosave2007/cmf). Fonctionne même quand le routeur est indisponible.",
"settings.cmf.threads": "Threads de travail",
"settings.cmf.gpu": "Utiliser le GPU (Metal / wgpu)",
"settings.cmf.speedNote": "Les threads parallélisent les matvecs de décodage (~3× plus rapide ; 0 = valeur par défaut du runtime). Le déport GPU aide surtout au prefill des longs prompts — le décodage est limité par la bande passante mémoire, donc sur Apple Silicon l'effet est à peu près neutre.",
"settings.cmf.pick": "choisir un modèle",
"settings.cmf.models": "Modèles locaux",
"settings.cmf.modelsHelp": "Chaque ligne est un modèle que la passerelle exécute (son propre cortiq serve sur son propre port) et enregistre dans le pool. Ajoutez-en autant que vous avez de fichiers .cmf et de ports libres.",
"settings.cmf.rowHint": "id · fichier .cmf · port · threads · GPU. Les changements prennent effet au redémarrage ; supprimer une ligne arrête ce serveur.",
"settings.cmf.addServer": "+ Ajouter un modèle local",
"settings.cmf.checkPort": "Vérifier le port",
"settings.cmf.portFree": "port libre",
"settings.cmf.portBusy": "port occupé",
"settings.cmf.useSuggested": "utiliser {port}",
"settings.cmf.serving": "{model} servi sur :{port}",
"settings.cmf.intro": "Exécutez des modèles en local avec le moteur cortiq — fonctionne même hors ligne ou quand le routeur est en panne.",
"settings.cmf.runtime": "Runtime cortiq",
"settings.cmf.runtimeHelp": "L'outil en ligne de commande `cortiq` qui charge et exécute les modèles .cmf. Installez-le une fois avant de démarrer un serveur local.",
"settings.cmf.install": "Installer cortiq",
"settings.cmf.reinstall": "Réinstaller / mettre à jour",
"settings.cmf.installing": "installation… (compilation, quelques minutes)",
"settings.cmf.installedOk": "cortiq installé",
"settings.cmf.notInstalled": "non installé",
"settings.cmf.addModel": "Ajouter un modèle",
"settings.cmf.addModelHelp": "Les modèles se téléchargent et se convertissent dans l'onglet Importer (HuggingFace → .cmf). Faites ensuite pointer le serveur local vers le fichier .cmf ci-dessous.",
"settings.cmf.importNote": "Pas encore de modèle ? Importez-en un :",
"settings.cmf.importLink": "Ouvrir Importer",
"settings.cmf.modelHelp": "Chemin du fichier .cmf à servir (par ex. models/qwen.cmf), produit par l'onglet Importer. Plusieurs modèles pour des tâches différentes ? Importez-les et changez ce chemin.",
"settings.cmf.portHelp": "Port TCP sur lequel écoute le serveur de modèle local (8081 par défaut). À changer seulement en cas de conflit avec un autre service.",
"settings.cmf.threadsHelp": "Nombre de cœurs CPU utilisés pour la génération. Plus = plus rapide (~3× par rapport à un seul cœur) ; 0 laisse le runtime décider.",
"settings.cmf.gpuHelp": "Déporter les calculs matriciels sur le GPU (Metal/wgpu). Sur Apple Silicon, cela accélère surtout les longs prompts — le décodage est limité par la bande passante mémoire.",
"settings.cmf.localOnlyHelp": "Router chaque requête vers le modèle local, en ignorant le routeur et tous les fournisseurs cloud.",
"settings.cmf.manageHelp": "Au démarrage, la passerelle lance `cortiq serve` pour le .cmf ci-dessous et y route les requêtes. Nécessite cortiq installé (étape 1). Prend effet au redémarrage.",
"settings.cmf.autoInstallHelp": "Si cortiq est absent au démarrage, l'installer automatiquement depuis crates.io.",
"settings.cmf.autoUpdateHelp": "Au démarrage, mettre cortiq à niveau vers la dernière version si elle est plus récente.",
"settings.router.enabledHelp": "Laisser le routeur cortiq classer chaque requête (type de tâche + complexité) et choisir un modèle. Désactivé = utiliser uniquement la table de routage locale.",
"settings.router.verifyTlsHelp": "Vérifier le certificat TLS du routeur. À désactiver uniquement pour un certificat auto-signé ou lié à une IP.",
"settings.telemetry.metricsHelp": "Exposer les métriques Prometheus sur GET /metrics.",
"settings.cortiq.echoHelp": "Ajouter un champ `cortiq` (tâche, modèle, coût) au corps de chaque réponse. Les en-têtes de réponse sont toujours envoyés.",
"settings.stats.enabledHelp": "Enregistrer les requêtes récentes pour alimenter le tableau de bord et les graphiques.",
"settings.cache.enabledHelp": "Cache sémantique : renvoyer une réponse enregistrée quand un nouveau prompt ressemble beaucoup à un précédent, en évitant l'appel au modèle. Nécessite un modèle d'embedding dans le pool.",
"settings.log.bodiesHelp": "Journaliser le corps complet des messages de requête et de réponse. Désactivé par défaut pour la confidentialité.",
"settings.router.saveKey": "Enregistrer la clé",
"settings.router.keySaved": "Clé du routeur enregistrée",
"settings.router.keyEmpty": "Collez d'abord la clé",
"settings.router.secretHelp": "Collez la clé reçue par e-mail depuis api.allaigate.com, puis cliquez sur Enregistrer la clé. Ce n'est PAS une valeur de « Clés API » — celles-ci servent aux clients qui appellent votre passerelle.",
"settings.router.keyStoredMask": "•••••••••••• — clé enregistrée (recollez-en une pour la remplacer)",
"settings.route.strategyHelp": "Texte envoyé au routeur pour la classification : last_user = uniquement le dernier message utilisateur ; last_user_plus_system = dernier message utilisateur + prompt système ; concat_all = toute la conversation.",
"settings.route.maxCharsHelp": "Nombre maximal de caractères de ce texte envoyés au routeur (au-delà, il est tronqué). Plus = classification plus précise, mais appels au routeur plus lents et plus coûteux.",
"settings.route.cacheTtlHelp": "Durée de mise en cache d'une décision de routage pour une requête identique avant de réinterroger le routeur (par ex. 60s, 5m).",
"settings.route.profileHelp": "Profil de routage par défaut quand la requête n'en précise aucun : cost-saver (le moins cher), balanced ou quality-first (meilleur modèle). Influence le modèle choisi par le routeur.",
// import
"import.subtitle": "Cherchez sur HuggingFace, convertissez en .cmf local et servez-le.",
"import.searchPlaceholder": "Rechercher des modèles HuggingFace (par ex. qwen3, llama)…",
"import.searching": "Recherche…",
"import.noResults": "Aucun modèle trouvé.",
"import.configure": "Configurer la conversion",
"import.outName": "Nom de sortie",
"import.outNameHint": "Nom du fichier .cmf (lettres, chiffres, - et _).",
"import.quant": "Quantification",
"import.convert": "Convertir et charger",
"import.converting": "Conversion",
"import.started": "Conversion lancée",
"import.failed": "Échec de la conversion — voir le journal.",
"import.register": "Enregistrer comme modèle local",
"import.registered": "Enregistré sous « {id} ». Lancez cortiq-server pour le servir.",
"import.jobs": "Téléchargements et conversions",
"import.cancel": "Annuler",
"import.cancelling": "Annulation — nettoyage du fichier incomplet…",
"import.delete": "Supprimer",
"import.deleteConfirm": "Supprimer ce modèle et son fichier .cmf converti du disque ?",
"import.deleted": "Supprimé avec ses fichiers",
"import.state.running": "en cours",
"import.state.done": "terminé",
"import.state.error": "erreur",
"import.state.cancelled": "annulé",
"import.featuredTitle": "Modèles .cmf prêts à l'emploi",
"import.featuredSub": "Modèles .cmf déjà convertis du compte infosave sur HuggingFace — la liste est lue en direct, les nouveaux modèles apparaissent d'eux-mêmes.",
"import.readyCmfBadge": ".cmf prêt",
"import.directDownload": "Télécharger",
"import.q.q8_2f": "8 bits à deux champs (𝒲×θ) — recommandé : meilleur rapport qualité/taille.",
"import.q.q8_row": "8 bits par ligne — simple et robuste.",
"import.q.q4": "4 bits par bloc — le plus compact, qualité moindre.",
"import.q.q4_tiled": "4 bits en tuiles (Q4_TILED) — 1,66× plus rapide sur GPU Metal.",
"import.q.vbit": "Variable 3–8 bits — budget de bits par expert.",
"import.q.q1t": "Ternaire 1,58 bit (Q1T) — BitNet b1.58 avec valeurs aberrantes éparses.",
"import.q.q1s": "1 bit épars (Q1S) — base 1 bit avec valeurs aberrantes holographiques.",
"import.q.q1p": "1 bit PTQ (Q1P) — 1 bit avec diffusion d'erreur.",
"import.q.q1": "1 bit (Q1) — format purement binaire.",
"import.q.f16": "16 bits — sans quantification.",
"import.q.f32": "32 bits — pleine précision (fichier volumineux).",
"import.adv.title": "Paramètres avancés",
"import.adv.auto": "auto",
"import.adv.linearCore": "Cœur linéaire",
"import.adv.linearHint": "Comment les couches d'attention linéaire sont reportées ou fusionnées.",
"import.adv.nphase": "vmf_phase phases/tête",
"import.adv.vbitShape": "Forme du budget VBIT",
"import.adv.meanBits": "Bits moyens VBIT",
"import.adv.shard": "Taille max. des shards (Go)",
"import.adv.noShard": "pas de découpage",
"import.adv.skipMtp": "ignorer la tête MTP",
"import.adv.o1": "Attention O(1)",
"import.adv.o1Hint": "Attention en flux à mémoire constante : le cache KV est libéré après le prefill, la mémoire ne croît donc pas avec de longs contextes. Les poids restent identiques octet pour octet — seule une indication de chargement est enregistrée ; vous pouvez revenir en arrière à tout moment (servir avec --o1 off). Validé sur Qwen3-0.6B : toutes couches ≈ ×1,18 de perplexité.",
"import.adv.o1Off": "désactivé — attention exacte (par défaut)",
"import.adv.o1All": "all — convertir chaque couche softmax",
"import.adv.o1Deep": "deep N — seulement les N couches les plus profondes",
"import.adv.o1Custom": "personnalisé — liste explicite de couches",
"import.adv.o1DeepN": "N couches profondes",
"import.adv.o1Layers": "Couches (séparées par des virgules)",
"import.adv.o1mHint": "budget de landmarks (32 par défaut)",
"import.adv.o1windowHint": "largeur de la fenêtre exacte (128 par défaut)",
"import.adv.o1sinkHint": "clés sink exactes permanentes (4 par défaut)",
// onboarding
"onboarding.title": "Configuration initiale",
"onboarding.welcome": "Bienvenue dans Cortiq Gateway",
"onboarding.welcomeSub": "Choisissez votre langue — vous pourrez la changer à tout moment dans l'en-tête.",
"onboarding.next": "Suivant",
"onboarding.back": "Retour",
"onboarding.skip": "Passer pour l'instant",
"onboarding.skipSetup": "Passer",
"onboarding.finish": "Terminer la configuration",
"onboarding.featuredTitle": "Modèles prêts à l'emploi (en un clic)",
"onboarding.featuredSub": "Ce sont des modèles .cmf déjà convertis, publiés par infosave sur HuggingFace — il suffit de les télécharger, aucune conversion nécessaire. Choisissez-en un ou plusieurs pour démarrer immédiatement.",
"onboarding.download": "Télécharger",
"onboarding.hfTitle": "N'importe quel modèle HuggingFace — conversion automatique",
"onboarding.hfSub": "Cherchez un modèle, choisissez une quantification, et nous le convertissons automatiquement en .cmf. Aucune modification manuelle de la configuration.",
"onboarding.noJobs": "Aucun téléchargement pour l'instant.",
"onboarding.doneTitle": "Tout est prêt",
"onboarding.doneSub": "Les modèles téléchargés seront enregistrés automatiquement. Vous pourrez en ajouter d'autres dans Importer ou Modèles.",
"onboarding.doneHint": "« Terminer la configuration » connecte chaque téléchargement achevé comme modèle local, démarre son serveur .cmf et y dirige le routage. Tout cela reste modifiable ensuite dans Modèles.",
"onboarding.willRegister": "Seront connectés comme modèles locaux",
"onboarding.nothingToRegister": "Aucun téléchargement terminé — rien à connecter. Revenez à l'étape précédente pour choisir un modèle.",
"onboarding.registeredN": "{n} modèle(s) connecté(s) : {ids}",
"onboarding.runtimeMissing": "Le runtime cortiq n'est pas installé — installez-le dans Paramètres → Modèles locaux pour les servir.",
"onboarding.downloaded": "téléchargé",
"onboarding.update": "Mettre à jour",
"onboarding.deleteFile": "Supprimer le fichier .cmf du disque",
"onboarding.confirmDelete": "Supprimer « {id} » ? Le fichier .cmf sera retiré du disque.",
"onboarding.unregistered": "Également désenregistré : {ids}",
};