fix(release): stop shipping native modules built for the wrong runtime
Some checks failed
deploy-site / deploy (push) Failing after 14m16s

The released installer could not start: it carried a better-sqlite3 build for the
host Node runtime instead of Electron, so the app died immediately with a module
version mismatch when it opened its database.

Packaging now proves the Electron build of every runtime-sensitive native module
before an installer or archive exists, and installers are produced only from that
verified tree, so the mistake cannot pass silently. The release pipelines run the
same check.

The default local model also pointed at a retired model: a *.gguf name that
Ollama cannot serve, while the settings, onboarding, and guide screens
recommended an older model. All of them now use the model the service code
already preferred.
This commit is contained in:
Yun Chan 2026-09-18 15:45:03 +09:00
parent 0fbbbc1756
commit 1af3cf75c7
42 changed files with 473 additions and 83 deletions

View file

@ -3,7 +3,7 @@
"info": {
"title": "D3RO-VOICE Admin API",
"description": "Admin CRM Edge Functions for user management, subscription CRUD, payment history, and audit logs.",
"version": "1.3.2"
"version": "1.3.3"
},
"servers": [
{

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/admin",
"version": "1.3.2",
"version": "1.3.3",
"private": true,
"description": "D3RO Voice Admin CRM — SaaS 관리 도구",
"scripts": {

View file

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Version>1.3.2</Version>
<Version>1.3.3</Version>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

View file

@ -20,6 +20,8 @@ files:
- "!out/**/*.map"
# ffmpeg 정적 바이너리(61MB)는 설치본에 넣지 않는다 — 필요할 때 런타임으로 내려받는다
- "!node_modules/@ffmpeg-installer/**"
# ffmpeg 정적 바이너리(61MB)는 설치본에 넣지 않는다 — 필요할 때 런타임으로 내려받는다
- "!node_modules/@ffmpeg-installer/**"
# ────────────────────────────────────────────────────────────────────
# 자동 업데이트 feed — 이 설정이 있어야 electron-builder가

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/desktop",
"version": "1.3.2",
"version": "1.3.3",
"productName": "d3ro-voice",
"description": "로컬 AI 음성 어시스턴트 (Electron)",
"main": "./out/main/index.js",

View file

@ -42,7 +42,7 @@ const CONFIG_DEFAULTS: AppConfig = {
ttsSpeed: 1.0,
onlineApiUrl: 'http://127.0.0.1:5000',
localModelsDir: '',
llmModelId: 'gemma-2-2b-it.Q4_K_M.gguf',
llmModelId: 'gemma4:e4b',
ollamaServerUrl: 'http://127.0.0.1:11434',
appUsageMode: null,
authToken: null,

View file

@ -663,7 +663,7 @@ class LocalLLMService extends EventEmitter {
return {
connectionState,
serverUrl: getOllamaServerUrl(),
activeModel: configGet('llmModelId') || 'gemma2:2b',
activeModel: configGet('llmModelId') || 'gemma4:e4b',
serverVersion: this._serverVersion
}
}
@ -686,7 +686,7 @@ class LocalLLMService extends EventEmitter {
}
const serverUrl = getOllamaServerUrl()
const model = options?.model ?? configGet('llmModelId') ?? 'gemma2:2b'
const model = options?.model ?? configGet('llmModelId') ?? 'gemma4:e4b'
this._abortController = new AbortController()
this._state = LLMState.Generating

View file

@ -146,7 +146,7 @@ export function OllamaGuideModal({ open, onClose }: OllamaGuideModalProps): Reac
const { t } = useI18n()
const [llmStatus, setLlmStatus] = useState<LLMStatus | null>(null)
const [installedModels, setInstalledModels] = useState<LLMModel[]>([])
const [activeModel, setActiveModel] = useState<string>('gemma2:2b')
const [activeModel, setActiveModel] = useState<string>('gemma4:e4b')
const [checking, setChecking] = useState(false)
const [starting, setStarting] = useState(false)
const [startMessage, setStartMessage] = useState<string | null>(null)
@ -582,7 +582,7 @@ export function OllamaGuideModal({ open, onClose }: OllamaGuideModalProps): Reac
<Typography sx={{ fontSize: '11px', color: d3roPalette.text.dimLabel }}>
:
</Typography>
<CodeBlock code="ollama pull gemma2:2b" />
<CodeBlock code="ollama pull gemma4:e4b" />
</Box>
</Box>

View file

@ -49,7 +49,7 @@ export function OnboardingModal({ open, onClose }: OnboardingModalProps): React.
// Local Ollama State
const [ollamaStatus, setOllamaStatus] = useState<LLMStatus | null>(null)
const [installedModels, setInstalledModels] = useState<LLMModel[]>([])
const [activeModel, setActiveModel] = useState<string>('gemma2:2b')
const [activeModel, setActiveModel] = useState<string>('gemma4:e4b')
const [checkingOllama, setCheckingOllama] = useState(false)
const [startingOllama, setStartingOllama] = useState(false)
const [ollamaMsg, setOllamaMsg] = useState<string | null>(null)
@ -498,7 +498,7 @@ export function OnboardingModal({ open, onClose }: OnboardingModalProps): React.
<Button
variant="contained"
startIcon={<Download size={14} />}
onClick={() => handlePullModel('gemma2:2b')}
onClick={() => handlePullModel('gemma4:e4b')}
disabled={!isOllamaConnected}
sx={{
fontWeight: 500,

View file

@ -723,7 +723,7 @@ export function SettingsModal({ open, initialTab = 0, onClose }: SettingsModalPr
: 'Ollama 오프라인 (서버 실행 필요)'}
</Typography>
<Typography sx={{ fontSize: '11px', color: d3roPalette.text.secondary }}>
: {ollamaModels.length} | : {config.llmModelId ?? 'gemma2:2b'}
: {ollamaModels.length} | : {config.llmModelId ?? 'gemma4:e4b'}
</Typography>
</Box>
</Box>
@ -800,7 +800,7 @@ export function SettingsModal({ open, initialTab = 0, onClose }: SettingsModalPr
<InputLabel> Ollama </InputLabel>
<Select
label="활성 Ollama 모델"
value={config.llmModelId ?? 'gemma2:2b'}
value={config.llmModelId ?? 'gemma4:e4b'}
onChange={(e) => {
const val = e.target.value
updateConfig('llmModelId', val)
@ -815,7 +815,7 @@ export function SettingsModal({ open, initialTab = 0, onClose }: SettingsModalPr
))}
{/* 설치된 모델 목록이 없거나 기본 추천 추가 */}
{ollamaModels.length === 0 && (
<MenuItem value="gemma2:2b">gemma2:2b ()</MenuItem>
<MenuItem value="gemma4:e4b">gemma4:e4b ()</MenuItem>
)}
{!ollamaModels.some((m) => m.name === 'llama3.2:3b') && (
<MenuItem value="llama3.2:3b">llama3.2:3b</MenuItem>

View file

@ -151,8 +151,8 @@ def versionSettingsValid = configuredVersionName != null &&
configuredVersionName ==~ strictSemver &&
configuredVersionCodeValue != null &&
configuredVersionCodeValue <= 2100000000L
def resolvedVersionName = versionSettingsValid ? configuredVersionName : "1.3.2"
def resolvedVersionCode = versionSettingsValid ? configuredVersionCodeValue.toInteger() : 1031002
def resolvedVersionName = versionSettingsValid ? configuredVersionName : "1.3.3"
def resolvedVersionCode = versionSettingsValid ? configuredVersionCodeValue.toInteger() : 1031003
def requiredReleaseSettings = [
D3RO_RELEASE_STORE_FILE: releaseStoreFilePath,

View file

@ -257,7 +257,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1031002;
CURRENT_PROJECT_VERSION = 1031003;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = D3ROVoice/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
@ -265,7 +265,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.3.2;
MARKETING_VERSION = 1.3.3;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@ -287,14 +287,14 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1031002;
CURRENT_PROJECT_VERSION = 1031003;
INFOPLIST_FILE = D3ROVoice/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.3.2;
MARKETING_VERSION = 1.3.3;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",

View file

@ -0,0 +1 @@
Fixed an installer that could not start, and updated the default local model to the current one.

View file

@ -0,0 +1 @@
실행이 안 되던 설치 문제를 고쳤습니다. 로컬 모델 기본값도 최신 모델로 정리했습니다.

View file

@ -1,12 +1,12 @@
{
"name": "@d3ro/mobile-rn",
"version": "1.3.2",
"version": "1.3.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@d3ro/mobile-rn",
"version": "1.3.2",
"version": "1.3.3",
"dependencies": {
"@d3ro/api-client": "file:../../packages/api-client",
"@d3ro/core": "file:../../packages/core",
@ -62,7 +62,7 @@
},
"../..": {
"name": "d3ro-voice-monorepo",
"version": "1.3.2",
"version": "1.3.3",
"license": "MIT",
"workspaces": [
"apps/desktop",
@ -81,7 +81,7 @@
},
"../../packages/api-client": {
"name": "@d3ro/api-client",
"version": "1.3.2",
"version": "1.3.3",
"license": "MIT",
"dependencies": {
"@d3ro/core": "*",
@ -98,7 +98,7 @@
},
"../../packages/core": {
"name": "@d3ro/core",
"version": "1.3.2",
"version": "1.3.3",
"license": "MIT",
"dependencies": {
"docx": "^9.6.1"
@ -109,7 +109,7 @@
},
"../../packages/i18n": {
"name": "@d3ro/i18n",
"version": "1.3.2",
"version": "1.3.3",
"license": "MIT",
"devDependencies": {
"@types/react": "^19.0.0"
@ -120,7 +120,7 @@
},
"../../packages/ui-native": {
"name": "@d3ro/ui-native",
"version": "1.3.2",
"version": "1.3.3",
"license": "MIT",
"devDependencies": {
"@types/react": "*"

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/mobile-rn",
"version": "1.3.2",
"version": "1.3.3",
"private": true,
"scripts": {
"android": "react-native run-android",

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/web",
"version": "1.3.2",
"version": "1.3.3",
"private": true,
"description": "D3RO Voice 웹 앱 — Next.js 기반 SaaS 인터페이스",
"scripts": {

View file

@ -139,7 +139,7 @@ export function Sidebar(): React.ReactElement {
</PhosphorText>
</Box>
<Box sx={{ fontSize: '10px', fontFamily: 'ui-monospace, monospace', color: d3roPalette.text.muted }}>
v1.3.2
v1.3.3
</Box>
</Box>