Files
OSGKeyboard/project.yml
T
Rocky df1c5ff32c feat: migrate on-device Qwen3 ASR to CoreML for background Flow dictation
Replace MLX GPU inference with CoreML bundles so transcription continues
while the host app is backgrounded. Adds model download and warm-up,
vendored Qwen3Speech, and updates onboarding, settings, and copy for the
~1.6 GB CoreML package (iOS 18+).
2026-06-23 00:46:58 +08:00

308 lines
12 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# XcodeGen configuration for OSGKeyboard
# Run `./Scripts/generate-xcodeproj.sh` to create OSGKeyboard.xcodeproj.
# App home-screen icon: OSGKeyboard/AppIcon.icon (Icon Composer, iOS 26).
# Repo only tracks project.yml; .xcodeproj is gitignored.
name: OSGKeyboard
options:
bundleIdPrefix: com.osgkeyboard
# Xcode 26 Icon Composer bundles must be treated as a single file,
# not expanded into icon.json + SVG children (see XcodeGen #1556).
fileTypes:
icon:
file: true
# Minimum OS: iOS 26. We dropped older iOS support so the
# legacy speech + AVAudioSession branching could be removed in
# favour of iOS 26's `SpeechAnalyzer` (always on-device) and
# `AVAudioApplication.requestRecordPermission` (iOS 17+). iPhone
# only — no Mac Catalyst, no visionOS.
deploymentTarget:
iOS: "26.0"
developmentLanguage: en
createIntermediateGroups: true
generateEmptyDirectories: true
groupSortPosition: top
# Local package: `Qwen3Speech`. Vendored fork of
# `soniqo/speech-swift`'s Qwen3-ASR + Qwen3-Chat modules (plus the
# AudioCommon / MLXCommon / SpeechVAD slices they depend on).
# Upstream's `Package.swift` references a `CSpeechCore` binary
# target whose URL doesn't match its declared filename (the file
# is `SpeechCore.xcframework.zip`, the target is `CSpeechCore`),
# which breaks SwiftPM resolve on a clean checkout. Vendoring
# lets us ship the four targets we actually link without waiting
# for the upstream fix; the `audio` / `audio-server` CLIs and the
# `AudioServer` HTTP backend that needed `CSpeechCore` aren't part
# of OSGKeyboard's build graph. Sources carry their original
# Apache-2.0 copyright headers; the `Package.swift` here adds
# only what we need.
packages:
Qwen3Speech:
path: OSGKeyboard/ThirdParty/Qwen3Speech
settings:
base:
SWIFT_VERSION: "6.0"
IPHONEOS_DEPLOYMENT_TARGET: "26.0"
ENABLE_USER_SCRIPT_SANDBOXING: YES
SWIFT_STRICT_CONCURRENCY: complete
GENERATE_INFOPLIST_FILE: NO
ENABLE_MODULE_VERIFIER: YES
CLANG_CXX_LANGUAGE_STANDARD: c++17
MARKETING_VERSION: "0.2.0"
CURRENT_PROJECT_VERSION: "4"
# 签名配置来自 Signing.local.xcconfiggitignored,不会被覆盖)
# 项目级签名 xcconfig,适用于所有 target
configFiles:
Debug: Signing.local.xcconfig
Release: Signing.local.xcconfig
targets:
# =========================================================
# 主 App
# =========================================================
OSGKeyboard:
type: application
platform: iOS
sources:
- path: OSGKeyboard/AppIcon.icon
type: file
buildPhase: resources
- path: OSGKeyboard
excludes:
- "AppIcon.icon"
- "OSGKeyboard.icon"
# Legacy PNG app icons must not coexist with AppIcon.icon — actool
# crashes when both are passed. iOS 26 uses Icon Composer only.
- "Assets.xcassets/AppIcon.appiconset"
# `ThirdParty/Qwen3Speech` is a local SPM package pulled in
# by `packages:` below — it builds as its own targets
# (`Qwen3ASR`, …) and we link the products.
# If we don't exclude the source folder, xcodegen walks
# into the package's `Sources/*/` directories and pulls
# the swift files straight into the host app target,
# which collides on duplicate type names (e.g. two
# `Configuration.swift` files in `Qwen3ASR` and
# `SpeechVAD`) and on multiple `@main` / top-level
# declarations. Keep the folder as a package; don't
# flatten it into the app.
- "ThirdParty/Qwen3Speech"
entitlements:
path: OSGKeyboard/OSGKeyboard.entitlements
properties:
com.apple.security.application-groups:
- group.com.osgkeyboard.shared
com.apple.security.device.audio-input: true
# Shared Keychain access group: the host app writes the LLM API
# key here in Settings; the keyboard extension reads it before
# each request. The first entry below becomes each process's
# default access group, so the Keychain helper does not need to
# specify kSecAttrAccessGroup explicitly.
keychain-access-groups:
- $(AppIdentifierPrefix)com.osgkeyboard.shared
resources:
- path: OSGKeyboard/Assets.xcassets
- path: OSGKeyboard/en.lproj
- path: OSGKeyboard/zh-Hans.lproj
- path: OSGKeyboard/Resources/Fonts/MaterialIcons-Regular.ttf
- path: OSGKeyboard/Resources/PrivacyPolicy.html
- path: OSGKeyboard/PrivacyInfo.xcprivacy
info:
path: OSGKeyboard/Info.plist
properties:
CFBundleDisplayName: OSGKeyboard
CFBundleShortVersionString: "$(MARKETING_VERSION)"
CFBundleVersion: "$(CURRENT_PROJECT_VERSION)"
LSApplicationCategoryType: public.app-category.utilities
# English is the development language; zh-Hans is the only
# translation right now. The list also tells iOS to surface
# the keyboard in the per-app language picker for both.
CFBundleDevelopmentRegion: en
CFBundleLocalizations:
- en
- zh-Hans
UILaunchScreen:
UIColorName: "BackgroundColor"
UISupportedInterfaceOrientations:
- UIInterfaceOrientationPortrait
UIApplicationSceneManifest:
UIApplicationSupportsMultipleScenes: false
NSMicrophoneUsageDescription: "OSGKeyboard uses the microphone for voice dictation and keeps a background audio session active while a voice session is running."
NSSpeechRecognitionUsageDescription: "OSGKeyboard uses on-device speech recognition to transcribe your voice. Audio is processed on your device and is not uploaded for transcription."
UIBackgroundModes:
- audio
NSAppTransportSecurity:
NSAllowsArbitraryLoads: false
ITSAppUsesNonExemptEncryption: false
CFBundleURLTypes:
- CFBundleURLName: com.osgkeyboard.ios.settings
CFBundleURLSchemes:
- osgkeyboard
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.osgkeyboard.ios
TARGETED_DEVICE_FAMILY: "1"
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents: YES
INFOPLIST_KEY_LSApplicationCategoryType: public.app-category.utilities
SUPPORTS_MACCATALYST: NO
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD: NO
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD: NO
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
dependencies:
- target: OSGKeyboardShared
embed: true
- target: OSGKeyboardExt
# Keyboard Extension is a plugin of the main App; embed it.
- sdk: Speech.framework
# Local fork of soniqo/speech-swift. See the `packages:`
# block at the top of this file for the why-fork rationale.
# Only the two products we actually link are listed; AudioServer
# / AudioCLI (which is what the upstream binary target was
# gating) aren't in our build graph.
- package: Qwen3Speech
product: Qwen3ASR
# =========================================================
# Keyboard Extension
# =========================================================
OSGKeyboardExt:
type: app-extension
platform: iOS
sources:
- path: OSGKeyboardExt
excludes:
- "en.lproj"
- "zh-Hans.lproj"
- path: OSGKeyboardExt/en.lproj/Keyboard.strings
buildPhase: resources
- path: OSGKeyboardExt/zh-Hans.lproj/Keyboard.strings
buildPhase: resources
resources:
- path: OSGKeyboardExt/PrivacyInfo.xcprivacy
settings:
base:
IPHONEOS_DEPLOYMENT_TARGET: "26.0"
entitlements:
path: OSGKeyboardExt/OSGKeyboardExt.entitlements
properties:
com.apple.security.application-groups:
- group.com.osgkeyboard.shared
# Shared with the host app so the keyboard extension can read the
# user's LLM API key. See OSGKeyboard/OSGKeyboard.entitlements
# for the full rationale.
keychain-access-groups:
- $(AppIdentifierPrefix)com.osgkeyboard.shared
info:
path: OSGKeyboardExt/Info.plist
properties:
CFBundleDisplayName: OSGKeyboard
CFBundleShortVersionString: "$(MARKETING_VERSION)"
CFBundleVersion: "$(CURRENT_PROJECT_VERSION)"
CFBundleDevelopmentRegion: en
CFBundleLocalizations:
- en
- zh-Hans
NSMicrophoneUsageDescription: "OSGKeyboard uses the microphone for voice dictation and keeps a background audio session active while a voice session is running."
NSSpeechRecognitionUsageDescription: "OSGKeyboard uses on-device speech recognition to transcribe your voice. Audio is processed on your device and is not uploaded for transcription."
NSExtension:
NSExtensionAttributes:
IsASCIICapable: false
PrefersRightToLeft: false
PrimaryLanguage: "en-US"
RequestsOpenAccess: true
NSExtensionPointIdentifier: com.apple.keyboard-service
NSExtensionPrincipalClass: $(PRODUCT_MODULE_NAME).KeyboardViewController
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.osgkeyboard.ios.keyboard
TARGETED_DEVICE_FAMILY: "1"
SUPPORTS_MACCATALYST: NO
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD: NO
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD: NO
dependencies:
- target: OSGKeyboardShared
embed: false
# =========================================================
# Shared Framework (主 App 与扩展共用)
# =========================================================
OSGKeyboardShared:
type: framework
platform: iOS
sources:
- path: OSGKeyboardShared
excludes:
- "en.lproj"
- "zh-Hans.lproj"
- path: OSGKeyboardShared/en.lproj/Shared.strings
buildPhase: resources
- path: OSGKeyboardShared/zh-Hans.lproj/Shared.strings
buildPhase: resources
info:
path: OSGKeyboardShared/Info.plist
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.osgkeyboard.ios.shared
TARGETED_DEVICE_FAMILY: "1"
DEFINES_MODULE: YES
SKIP_INSTALL: YES
BUILD_LIBRARY_FOR_DISTRIBUTION: NO
DYLIB_INSTALL_NAME_BASE: "@rpath"
APPLICATION_EXTENSION_API_ONLY: YES
ENABLE_MODULE_VERIFIER: YES
dependencies:
- sdk: Speech.framework
- sdk: AVFoundation.framework
# =========================================================
# 单元测试
# =========================================================
OSGKeyboardTests:
type: bundle.unit-test
platform: iOS
sources:
- path: OSGKeyboardTests
info:
path: OSGKeyboardTests/Info.plist
dependencies:
- target: OSGKeyboard
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.osgkeyboard.ios.tests
TARGETED_DEVICE_FAMILY: "1"
# =========================================================
# 键盘扩展单元测试 (TEST-4)
# =========================================================
OSGKeyboardExtTests:
type: bundle.unit-test
platform: iOS
sources:
- path: OSGKeyboardExtTests
info:
path: OSGKeyboardExtTests/Info.plist
dependencies:
- target: OSGKeyboardShared
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.osgkeyboard.ios.ext.tests
TARGETED_DEVICE_FAMILY: "1"
schemes:
OSGKeyboard:
build:
targets:
OSGKeyboard: all
OSGKeyboardExt: all
run:
config: Debug
test:
config: Debug
targets:
- OSGKeyboardTests
- OSGKeyboardExtTests
archive:
config: Release