From 9aa9bf5956f3592ccdc92cae09e569b29c123325 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Thu, 04 Jun 2026 15:16:48 +0800
Subject: [PATCH] Add x86_64 App Store sandbox artifact records

---
 privatevoice.src/internal/model/registry.go |  183 +++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 175 insertions(+), 8 deletions(-)

diff --git a/privatevoice.src/internal/model/registry.go b/privatevoice.src/internal/model/registry.go
index 9314941..f561172 100644
--- a/privatevoice.src/internal/model/registry.go
+++ b/privatevoice.src/internal/model/registry.go
@@ -1,9 +1,15 @@
 package model
 
-import "fmt"
+import (
+	"fmt"
+	"sort"
+)
 
 const (
-	BackendSenseVoice = "sensevoice"
+	BackendSenseVoice     = "sensevoice"
+	BackendMoonshine      = "moonshine"
+	BackendNemoTransducer = "nemo_transducer"
+	BackendQwen3ASR       = "qwen3_asr"
 )
 
 var modelProfiles = map[string]ModelProfile{
@@ -23,6 +29,10 @@
 		},
 		RecommendedFor: []string{"zh-CN"},
 		Description:    "轻量中文模型,适合中文和中英混输。",
+		DownloadURLs: []string{
+			"http://www.maikami.com/voicesnap/sensevoice.zip",
+			"https://modelscope.cn/models/sherpa-onnx/sherpa-onnx-sense-voice-zh-en-ja-ko-yue/resolve/master/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2",
+		},
 		InstallDirName: "sensevoice-zh",
 		LegacyDirNames: []string{"sensevoice"},
 		RequiredFiles: []RequiredFileRule{
@@ -40,15 +50,156 @@
 		ProviderOrder: []string{"coreml", "cpu"},
 		NumThreads:    4,
 	},
+	MoonshineModelID: {
+		ID:                   MoonshineModelID,
+		DisplayName:          "Moonshine English",
+		BackendKind:          BackendMoonshine,
+		Tier:                 "default",
+		SupportedLanguageIDs: []string{EnglishLanguageID},
+		RecommendedFor:       []string{EnglishLanguageID},
+		Description:          "轻量英文离线模型,适合英文听写和英文日常输入。",
+		ApproxSize:           "约 239 MiB 下载包,解压后约 270-280 MiB",
+		DownloadURLs: []string{
+			"https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-moonshine-base-en-int8.tar.bz2",
+		},
+		InstallDirName: "moonshine-en",
+		RequiredFiles: []RequiredFileRule{
+			{
+				Role:     "preprocessor",
+				AllOf:    []string{"preprocess.onnx"},
+				Required: true,
+			},
+			{
+				Role:     "encoder",
+				AllOf:    []string{"encode.int8.onnx"},
+				Required: true,
+			},
+			{
+				Role:     "uncached_decoder",
+				AllOf:    []string{"uncached_decode.int8.onnx"},
+				Required: true,
+			},
+			{
+				Role:     "cached_decoder",
+				AllOf:    []string{"cached_decode.int8.onnx"},
+				Required: true,
+			},
+			{
+				Role:     "tokens",
+				AllOf:    []string{"tokens.txt"},
+				Required: true,
+			},
+		},
+		ProviderOrder: []string{"cpu"},
+		NumThreads:    4,
+	},
+	ParakeetModelID: {
+		ID:                   ParakeetModelID,
+		DisplayName:          "Parakeet English",
+		BackendKind:          BackendNemoTransducer,
+		Tier:                 "advanced",
+		SupportedLanguageIDs: []string{EnglishLanguageID},
+		RecommendedFor:       []string{EnglishLanguageID},
+		Description:          "高质量英文离线模型,适合英文长句、技术词和更高准确率需求。",
+		ApproxSize:           "约 478 MiB 下载包",
+		DownloadURLs: []string{
+			"https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-nemo-parakeet-unified-en-0.6b-int8-non-streaming.tar.bz2",
+		},
+		InstallDirName: "parakeet-en",
+		RequiredFiles: []RequiredFileRule{
+			{
+				Role:     "encoder",
+				AllOf:    []string{"encoder.int8.onnx"},
+				Required: true,
+			},
+			{
+				Role:     "decoder",
+				AllOf:    []string{"decoder.int8.onnx"},
+				Required: true,
+			},
+			{
+				Role:     "joiner",
+				AllOf:    []string{"joiner.int8.onnx"},
+				Required: true,
+			},
+			{
+				Role:     "tokens",
+				AllOf:    []string{"tokens.txt"},
+				Required: true,
+			},
+		},
+		ProviderOrder: []string{"cpu"},
+		NumThreads:    4,
+	},
+	Qwen3ASRModelID: {
+		ID:                   Qwen3ASRModelID,
+		DisplayName:          "Qwen3-ASR",
+		BackendKind:          BackendQwen3ASR,
+		Tier:                 "advanced",
+		SupportedLanguageIDs: []string{DefaultLanguageID, "zh-Hans", "zh-Hant", "yue"},
+		RecommendedFor:       []string{DefaultLanguageID},
+		Description:          "高质量中文离线模型,适合中文长句、技术词和中英混输准确率需求。",
+		ApproxSize:           "约 838 MiB 下载包,解压后约 1.9 GiB",
+		DownloadURLs: []string{
+			"https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-qwen3-asr-0.6B-int8-2026-03-25.tar.bz2",
+		},
+		InstallDirName: "qwen3-asr-0.6b",
+		RequiredFiles: []RequiredFileRule{
+			{
+				Role:     "conv_frontend",
+				AllOf:    []string{"conv_frontend.onnx"},
+				Required: true,
+			},
+			{
+				Role:     "encoder",
+				AllOf:    []string{"encoder.int8.onnx"},
+				Required: true,
+			},
+			{
+				Role:     "decoder",
+				AllOf:    []string{"decoder.int8.onnx"},
+				Required: true,
+			},
+			{
+				Role:      "tokenizer",
+				AllOf:     []string{"tokenizer"},
+				Required:  true,
+				Directory: true,
+			},
+			{
+				Role:     "tokenizer_merges",
+				AllOf:    []string{"tokenizer/merges.txt"},
+				Required: true,
+			},
+			{
+				Role:     "tokenizer_vocab",
+				AllOf:    []string{"tokenizer/vocab.json"},
+				Required: true,
+			},
+		},
+		ProviderOrder: []string{"cpu"},
+		NumThreads:    4,
+	},
 }
 
 var languageProfiles = map[string]LanguageProfile{
-	"zh-CN": {
-		ID:             "zh-CN",
-		DisplayName:    "中文",
-		UILocale:       "zh-CN",
-		SystemMatchers: []string{"zh", "zh-CN", "zh-Hans", "zh-Hant"},
-		DefaultModelID: DefaultModelID,
+	DefaultLanguageID: {
+		ID:              DefaultLanguageID,
+		DisplayName:     "Chinese",
+		NativeName:      "中文",
+		UILocale:        "zh",
+		SystemMatchers:  []string{"zh", "zh-CN", "zh-Hans", "zh-Hant"},
+		DefaultModelID:  DefaultModelID,
+		UpgradeModelIDs: []string{Qwen3ASRModelID},
+	},
+	EnglishLanguageID: {
+		ID:              EnglishLanguageID,
+		DisplayName:     "English",
+		NativeName:      "English",
+		UILocale:        "en",
+		SystemMatchers:  []string{"en", "en-US", "en-GB", "en-AU", "en-CA"},
+		DefaultModelID:  MoonshineModelID,
+		UpgradeModelIDs: []string{ParakeetModelID},
 	},
 }
 
@@ -95,5 +246,21 @@
 	for _, profile := range languageProfiles {
 		profiles = append(profiles, profile)
 	}
+	sort.Slice(profiles, func(i, j int) bool {
+		if profiles[i].ID == DefaultLanguageID {
+			return true
+		}
+		if profiles[j].ID == DefaultLanguageID {
+			return false
+		}
+		return profiles[i].ID < profiles[j].ID
+	})
 	return profiles
 }
+
+func NormalizeLanguageID(id string) string {
+	if _, err := GetLanguageProfile(id); err != nil {
+		return DefaultLanguageID
+	}
+	return id
+}

--
Gitblit v1.9.3