Skip to content

[feature] 跨 App 语气适应:把前台 App 注入 LLM polish/translate prompt #116

@appergb

Description

@appergb

背景

参考 Wispr Flow / Superwhisper Super Mode / Typeless(Typeless 文档 明文:"Adapts the tone and style based on the app you're using"),同一段口述在不同 app 应有不同输出风格。

OpenLess 当前所有 polish 走同一档(raw / light / structured / formal),与前台 app 无关 → "在 Slack 写公告"和"在 Mail 写邮件"被同一个 prompt 模板对待。

设计

行为

`begin_session` 捕获当前前台 app 的 `localizedName` + `bundleIdentifier`(macOS)/ window title(Windows),存到 `SessionState.front_app`。`end_session` 调 polish/translate 之前,把 `当前前台应用:{name} ({bundle_id})` 拼到 system prompt 头部 `# 上下文` 块,紧跟在 `working_languages_premise` 之后。

LLM 自行根据 app 调风格——不在 OpenLess 维护硬编码 app→style 表。

例子

前台 app 用户说 LLM 输出(轻度润色)
Mail.app 那个老板我跟你说一下今天发布要推迟测试还没跑完 老板,跟您说一下:今天的发布需要推迟,原因是测试尚未完成。
微信 / Slack 同上 老板,今天发布得推迟下,测试还没跑完。
Xcode / VS Code 同上 Postpone today's release: tests haven't completed yet.

平台实现

  • macOS:用 `objc2-app-kit` 调 NSWorkspace.frontmostApplication,拿 .localizedName + .bundleIdentifier。公开 API,不需要额外权限。
  • Windows:复用现有 `capture_focus_target` 拿 HWND,`GetWindowTextW` 拿窗口标题作为 app label(粗糙但够 v1)。

Rust 改动

  • `coordinator.rs::SessionState` 加 `front_app: Option`
  • `coordinator.rs::begin_session` 调用新 helper `capture_frontmost_app()`
  • `polish.rs::polish/translate_to` 新增可选参数 `front_app: Option<&str>`
  • `polish.rs` 加 `front_app_premise(name) -> String`,跟 `working_languages_premise` 一起拼到 system prompt 头部

Escape hatch

Polish mode = `raw` 时不注入 front_app 上下文(用户选了"原文"明显不希望被风格调整)。

Out of scope(v1 不做)

  • 读 AX 焦点元素的 selectedText(隐私边界 + Electron app 兼容性差,留给 v2)
  • 硬编码 app→style 映射表(让 LLM 自己理解)
  • Linux 实现(rdev 路径跳过)

Test plan

  • macOS:在 Mail / 微信 / Xcode 三个 app 切换录音同一句口述,输出风格应不同
  • Windows:粗糙 window title 注入应该不报错且生效
  • raw 模式跳过注入:日志里看不到 `当前前台应用:` 行
  • 隐私:日志里只有 app 名 + bundle id,无选区文本

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions