feat(app): add crash visibility, memory relief, and clipboard reply work
Squashes the working tree that had accumulated on cloud-agent. Two strands of work, kept in one commit at the maintainer's request. Crash and stability (this session): - Subscribe to MetricKit so crash, hang, CPU, and disk-write diagnostics are recorded on device. Keyboard-extension memory kills are the most likely way a user loses the keyboard mid-sentence and iOS does not classify them as crashes, so they never reach App Store Connect. - Upload those reports to POST /v1/analytics/diagnostics from internal builds only (local Debug and TestFlight), reusing the analytics installation identifier and skipping entirely when analytics are off. App Store builds keep everything on device. - Shed the Chinese engine, English lexicon, and in-flight pipeline work at the 40 MiB and 48 MiB budget thresholds instead of waiting for a system memory warning that jetsam often preempts. - Install audio taps with the input node's live format through one shared adaptive resampler, so an audio-route change mid-recording no longer raises an uncatchable format-mismatch exception. Covers the dictation preview and the Mac recorder, which still used the pattern the Flow capture path had already moved away from. - Harden the librime bridge: never pass a nil string across a nonnull boundary when a user dictionary holds malformed UTF-8, null-check the engine API vector, and distrust a candidate count without its array. - Guard the expanded candidate grid against a list that shrinks while the collection view is still laying out against the previous count. - Resolve localized text without the App Group so the screen shown when that container is missing renders its message instead of crashing on launch, which is the one situation it exists to handle. - Gate CI on the App Group and Keychain wiring that the keyboard extension hard-depends on, with a self-test proving the check fails. Clipboard, reply, and semantics (pre-existing working tree): - Unify the reply center, refresh keyboard AI features, and add native event and reminder exporters. - Expand clipboard semantic routing with authored corpora and a product-blind holdout, plus the scripts that build and validate them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -43,7 +43,7 @@
|
||||
<li><strong>Speaking-style learning</strong> — voice history can retain the displayed final text and, when available, the corrected ASR text from before AI polishing plus a deduplicated snapshot of the polish-style prompt used for that take. The pre-polish text is not shown in History. Only after you tap “Generate My Style” are eligible before-and-after pairs and their prior style prompts sent to your configured AI service. Native speech and explicit user edits are used to infer recurring habits; historical prompts are supplied only to distinguish and remove AI-added style. The generated prompt is shown for review and is not saved or activated until you confirm it. When you later invoke a conversational clipboard-reply skill while a reviewed user-created style is active, that style prompt is sent with the copied text so the reply can follow your wording and rhythm; built-in polish personalities are not attached. User-configured requests go directly to that provider; managed-credit requests go through <code>account.osglab.com</code>.</li>
|
||||
<li><strong>AI mode questions</strong> — in AI keyboard mode, your spoken question text—or a question you tap from an idle suggestion—is sent to the selected AI service. User-configured requests go directly to that provider; managed-credit requests go through <code>account.osglab.com</code>. When the selected service supports server-side web search, it may retrieve public web results for time-sensitive answers.</li>
|
||||
<li><strong>AI suggestions and OSGKeyboard web pages</strong> — the main app may request public suggestion titles from <code>key.osglab.com</code>; no voice, transcript, clipboard body, API key, or ordinary keystroke content is included in that request. Opening the update page requests public content from <code>download.osglab.com</code>. As with ordinary HTTPS sites, those hosts and their infrastructure may process connection metadata such as IP address and request time.</li>
|
||||
<li><strong>AI Agent skills, Shortcuts, and maps</strong> — when you deliberately run a skill, the selected or copied text and skill prompt are sent to your configured LLM provider. For Reminders, Calendar, or Notes exports, the generated result is passed on-device to the Apple Shortcut you install; OSGKeyboard does not receive the resulting item. For navigation, an address or route is placed in a URL opened by Apple Maps, Amap, or Baidu Maps, and the selected map provider's policy applies.</li>
|
||||
<li><strong>AI Agent skills, Shortcuts, and maps</strong> — when you deliberately run a skill, the selected or copied text and skill prompt are sent to your configured LLM provider. For Reminders and Calendar exports, the app writes the generated items directly through Apple's EventKit on this device, after iOS asks you for permission; Calendar is requested with write-only access, so the app can add events but never reads your existing ones. Nothing about these items is sent to OSGKeyboard servers. For Notes exports, the generated result is passed on-device to the Apple Shortcut you install; OSGKeyboard does not receive the resulting item. For navigation, an address or route is placed in a URL opened by Apple Maps, Amap, or Baidu Maps, and the selected map provider's policy applies.</li>
|
||||
<li><strong>API credentials</strong> — your user-configured provider keys are stored in the iOS Keychain and shared with the keyboard through a shared Keychain group, never through UserDefaults. When you enable <strong>iCloud settings sync</strong>, API keys replicate through Apple's <strong>iCloud Keychain</strong> to your other signed-in devices — not through iCloud Key-Value Store JSON.</li>
|
||||
<li><strong>Optional OSGKeyboard account and purchases</strong> — no account is required for local transcription or user-configured providers. If you choose Sign in with Apple, the account service processes the Apple identity token, a pseudonymous OSGKeyboard account identifier, optional display name, device-integrity evidence, credit balance, referral state, and StoreKit transaction identifiers needed to verify consumable credit purchases. Account session tokens stay in the main app's private Keychain; the keyboard extension receives only a short-lived, scope-limited managed-service grant. You can sign out or delete the account in the app.</li>
|
||||
<li><strong>App preferences</strong> — engine mode, recognition language, polish intensity, translation target, handedness, and keyboard settings are stored in App Group <code>UserDefaults</code> so the main app and keyboard extension stay in sync. Device-local clipboard consent switches are not activated by iCloud settings sync.</li>
|
||||
@@ -60,7 +60,7 @@
|
||||
<h2>What we do not collect</h2>
|
||||
<ul>
|
||||
<li>We do <strong>not</strong> log or upload ordinary keystrokes. Only the on-device Chinese candidate-learning data described above is retained locally.</li>
|
||||
<li>We do <strong>not</strong> use third-party analytics, crash-reporting, advertising SDKs, ATT, or IDFA.</li>
|
||||
<li>We do <strong>not</strong> use third-party analytics, crash-reporting, advertising SDKs, ATT, or IDFA. OSGKeyboard records Apple <strong>MetricKit</strong> crash and hang diagnostics on your device so you can export them from Settings ▸ Diagnostics; App Store builds never upload them. Beta builds distributed through TestFlight additionally upload these diagnostics to <code>account.osglab.com</code>, and you can turn that off in the same screen. The reports contain crash metadata only — exception type, signal, termination reason, binary names and a truncated call stack — never audio, transcripts, clipboard content, prompts, or API keys.</li>
|
||||
<li>We do <strong>not</strong> upload raw audio on a local engine. Audio leaves the device only after you select a user-configured cloud engine or managed credits.</li>
|
||||
<li>We do <strong>not</strong> sell personal data.</li>
|
||||
</ul>
|
||||
@@ -108,7 +108,7 @@
|
||||
<li><strong>说话风格学习</strong> — 语音历史可同时保留界面展示的最终文本、可用时保留 AI 润色前且已经过确定性纠错的 ASR 文本,以及当次使用的润色风格 Prompt 去重快照;润色前文本不会在历史界面显示。只有当你主动点击「生成我的风格」后,符合条件的润色前后文本对及对应历史 Prompt 才会发送给你配置的 AI 服务。原生口述与用户明确编辑用于归纳反复出现的习惯;历史 Prompt 只用于识别并排除 AI 附加风格。生成结果会先展示供你检查,确认保存前不会写入或启用。之后,当你启用了经检查的用户自定义风格并主动使用口语回复类剪贴板技能时,该风格 Prompt 会随复制文本一起发送,用于贴近你的用词与节奏;内置润色人格不会附加。用户自备请求直达所选服务商;托管积分请求经 <code>account.osglab.com</code> 处理。</li>
|
||||
<li><strong>AI 模式问题</strong> — 在 AI 键盘模式下,语音转写后的问题文字或你点选的建议会发送到当前选择的 AI 服务。用户自备请求直达所选服务商;托管积分请求经 <code>account.osglab.com</code> 处理。所选服务支持联网搜索时,可能检索公开网页结果回答时效性问题。</li>
|
||||
<li><strong>AI 建议与 OSGKeyboard 网页</strong> — 主 App 可能从 <code>key.osglab.com</code> 请求公开建议标题;该请求不包含语音、转写、剪贴板正文、API Key 或普通击键内容。打开更新页时会从 <code>download.osglab.com</code> 请求公开内容。与普通 HTTPS 网站相同,相关主机与基础设施可能处理 IP 地址、请求时间等连接元数据。</li>
|
||||
<li><strong>AI Agent 技能、快捷指令与地图</strong> — 仅在你主动运行技能时,所选或复制的文字及技能提示词才会发送到你配置的 LLM 服务商。导出提醒事项、日历或备忘录时,生成结果会在设备端交给你安装的 Apple 快捷指令;OSGKeyboard 不会收到最终创建的项目。导航时,地址或路线会写入 URL 并交给 Apple 地图、高德地图或百度地图,相应地图服务商的政策适用。</li>
|
||||
<li><strong>AI Agent 技能、快捷指令与地图</strong> — 仅在你主动运行技能时,所选或复制的文字及技能提示词才会发送到你配置的 LLM 服务商。导出提醒事项与日历时,App 在本机经 iOS 授权后通过 Apple EventKit 直接写入;日历仅申请「仅写入」权限,只能新增日程、无法读取你已有的日程,相关内容不会发送到 OSGKeyboard 服务器。导出备忘录时,生成结果会在设备端交给你安装的 Apple 快捷指令;OSGKeyboard 不会收到最终创建的项目。导航时,地址或路线会写入 URL 并交给 Apple 地图、高德地图或百度地图,相应地图服务商的政策适用。</li>
|
||||
<li><strong>API 凭证</strong> — 用户自备服务商的 API Key 保存在设备 Keychain,通过共享 Keychain 组与键盘扩展共享,<strong>不会</strong>写入 <code>UserDefaults</code>。开启<strong>iCloud 设置同步</strong>后,API 密钥经 Apple <strong>iCloud 钥匙串</strong>同步到你其他已登录设备,<strong>不会</strong>写入 iCloud 键值存储 JSON。</li>
|
||||
<li><strong>可选 OSGKeyboard 账号与购买</strong> — 本地转写和用户自备服务商无需账号。若你选择 Apple 登录,账号服务会处理 Apple 身份令牌、匿名化的 OSGKeyboard 账号标识、可选昵称、设备完整性证明、积分余额、邀请状态,以及核验消耗型积分包所需的 StoreKit 交易标识。账号会话令牌只保存在主 App 私有 Keychain;键盘扩展仅获得短时、限权的托管服务凭证。你可以在 App 内退出或注销账号。</li>
|
||||
<li><strong>应用偏好</strong> — 引擎模式、识别语言、润色档位、翻译目标、握持偏好与键盘设置等保存在 App Group <code>UserDefaults</code>,用于主 App 与键盘扩展之间的状态同步。本机剪贴板许可开关不会被 iCloud 设置同步开启。</li>
|
||||
@@ -125,7 +125,7 @@
|
||||
<h2>我们不收集的内容</h2>
|
||||
<ul>
|
||||
<li>我们<strong>不会</strong>记录或上传你平时在键盘上的击键内容。</li>
|
||||
<li>我们<strong>不会</strong>集成第三方分析、崩溃上报或广告 SDK,也不使用 ATT 或 IDFA。</li>
|
||||
<li>我们<strong>不会</strong>集成第三方分析、崩溃上报或广告 SDK,也不使用 ATT 或 IDFA。OSGKeyboard 会在你的设备上记录 Apple <strong>MetricKit</strong> 崩溃与卡顿诊断,供你在「设置 ▸ 诊断」中导出;App Store 版本不会上传。通过 TestFlight 分发的内测版本会额外将这些诊断上传至 <code>account.osglab.com</code>,可在同一页面关闭。报告只包含崩溃元数据——异常类型、信号、终止原因、二进制名称与截断的调用栈——不包含录音、转写文本、剪贴板内容、提示词或 API 密钥。</li>
|
||||
<li>使用本地引擎时,我们<strong>不会</strong>上传原始录音。只有你选择用户自备云端识别或托管积分后,录音才会离开设备。</li>
|
||||
<li>我们<strong>不会</strong>出售个人数据。</li>
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user