8000 GitHub - chenyuantao/Hola: Hola · 言好 · GitHub
[go: up one dir, main page]

Skip to content
chenyuantaoPublic

About

Hola · 言好

Resources

Stars

4 stars

Watchers

0 watching

Forks

Repository files navigation

Hola · 言好

支持平台:macOS 12+

简体中文 · English

你的意思,更好的表达。

一个轻巧的 macOS 菜单栏助手,在消息发送前,帮你把话说得更自然、得体。

Swift / AppKit · 自备 API 凭据 · 无第三方依赖

快速开始 · 使用方式 · 界面语言 · 模型配置 · 兼容性与数据


言好演示:在输入框中润色文字

让每次发送,多一点妥帖

想法已经打出来了,只是还想把语气调整一下。言好就在你正在使用的输入框里,帮你完成这一步。

照常输入,按下回车。需要调整时,润色后的文字会回到原输入框;你看过后,再按一次回车发送。

输入:这个方案不行,你再改改,明天给我。

表达示意:这个方案还需要调整,麻烦你再修改一下,明天发给我。

默认提示词要求保留原意、不添加新信息。实际结果取决于所选模型和提示词。

言好带来的体验
原地润色 在当前输入框完成调整,省去复制到另一个工具再粘回来的步骤
回车触发 将润色接在发送之前,修改后的内容由你确认
快速判断 可启用 Jev 模型先快速判断是否需要润色;无需调整时直接发送原文,省去润色模型的调用和等待
按应用开启 拖入想使用的应用,自行选择生效范围
自由配置 接入 OpenAI 兼容接口,设置模型和表达偏好
轻巧常驻 收在菜单栏,通过状态提示和调用历史查看结果

快速开始

1. 安装与打开

下载发布版(无需安装开发工具)

  1. 在 GitHub Releases 下载 Hola-v版本号-macOS-universal.dmg,适用于 Apple Silicon 和 Intel Mac。
  2. 双击打开 DMG,在出现的安装窗口中将 Hola.app 拖到「应用程序」图标上。复制完成后,从「应用程序」打开 Hola,并推出安装磁盘映像。ZIP 仍可作为备用格式下载。
  3. 发布版使用 固定自签证书签名,未经过 Apple 公证。如果提示“无法验证开发者”或“Apple 无法检查其是否包含恶意软件”,先关闭提示,再按下表操作:
系统版本 允许打开的位置
macOS 13 及更新版本 系统设置 → 隐私与安全性 → 安全性,找到 Hola 被阻止的提示,点击 仍要打开
macOS 12 系统偏好设置 → 安全性与隐私 → 通用,找到 Hola 被阻止的提示,点击 仍要打开;如需修改设置,先解锁左下角的锁

按系统提示输入密码或使用 Touch ID,再确认打开。请先确认安装包来自上面的项目 Releases;此操作只为 Hola 添加例外,无需允许所有未知应用,也无需安装或信任额外证书。若没有出现按钮,先尝试打开 Hola 一次,再返回设置查看。Apple 官方说明

允许打开与下方的辅助功能、输入监控授权是两件事,两者都需要完成。应用运行后显示在菜单栏。

升级发布版:先退出 Hola,再用新版替换「应用程序」中的旧版。发布版持续复用同一张自签证书及应用标识,以保持签名身份;从旧的 ad-hoc 版本升级时签名身份会变化。系统仍可能再次要求允许打开或授予权限。如果权限已勾选但功能仍不可用,在对应权限列表中移除旧 Hola,再添加 /Applications/Hola.app 并开启,最后退出并重新打开应用。

从源码构建

准备 macOS 12 或更新版本,以及 Xcode Command Line Tools。尚未安装开发工具时,先运行:

xcode-select --install

在项目目录中一键构建并重启应用:

bash scripts/build-and-restart.sh

脚本会先完成构建和签名,再退出正在运行的开发版,打开并验证仓库中的 build/HolaDev.app。点击菜单栏图标会直接打开面板,默认停在「通用」。分区依次是通用、模型、人设、指令、日志。构建失败时不会退出旧版;已安装的发布版 Hola.app 可以继续运行,不会被替换。首次启动开发版时会复制一次现有配置,之后两版分别保存。由于开发版使用独立的应用 ID,macOS 需要为 HolaDev.app 单独授予辅助功能和输入监控权限。

应用名称为 Hola,中文品牌名为 言好。从旧应用标识升级后,请为 Hola 重新授予系统权限;首次启动会迁移旧版配置和调用历史。

构建脚本会在登录钥匙串中创建或复用 Hola Local 本机签名身份,并完成签名校验。默认生成 HolaDev.app(ID local.holadev),菜单栏图标显示黄色;发布流水线生成 Hola.app(ID local.hola),使用普通模板图标。当前使用本机自签名,尚未进行 Developer ID 公证。

2. 授予权限

打开 系统设置 → 隐私与安全性,为实际运行的 Hola 应用授予:

权限 用途
辅助功能 读取当前草稿,将润色结果写回输入框
输入监控 在选定应用中接管回车,触发润色流程

授权后退出并重新打开应用。言好常驻菜单栏,点击 Hola 图标 直接打开面板。

3. 选择应用与模型

  1. 点击菜单栏图标,在 通用 里授予辅助功能和输入监控权限。
  2. 在 模型 里填写 OpenAI 兼容接口的 地址、Token 和模型名称。修改会立即生效。权限、这份配置和至少一个目标应用都完成后,开启拦截 才会可用。Jev 也在这一页,默认关闭。
  3. 从「应用程序」目录拖入一个或多个 .app,选择言好的生效范围。
  4. 打开 开启拦截。判断提示词和润色提示词在 人设。

回到目标应用,先用一段非敏感草稿体验回车润色。

使用方式

照常输入 → 按下回车 → 检查与润色
                         │
                         ├─ 无需修改 → 补发回车,交给原应用处理
                         │
                         └─ 有所修改 → 回填草稿 → 你确认后再次回车
情况 会发生什么
润色结果与原文一致(忽略首尾空白) 补发回车;在回车发送的聊天应用中,即发送原文
润色结果有所调整 回填到原输入框,等待你再次按回车确认
回填后你又修改了文字 下次回车重新触发润色
接口请求失败 不自动发送,显示失败状态,可再次回车重试
读取输入框失败 拦截本次回车并显示错误
写回失败或无法核验 不自动发送;检查输入框中的实际内容后再操作
使用 Shift / Command 等修饰键加回车 保持原应用行为

每个目标应用可以选择劫持范围。新添加的应用默认是 部分劫持。

部分劫持 时,某个输入框第一次按回车,输入框旁会询问:

选择 这次回车 以后
不劫持 已经拦截,不会发送 这一类输入框不再询问,之后的回车保持原应用行为
允许劫持 进入润色流程 之后这一类输入框按回车都会接管
全部劫持 进入润色流程 该应用改为全部劫持,之后所有输入框都会接管
放弃 已经拦截,不会发送 不记住,下次仍会询问

还没决定是否劫持的输入框,输入时以及弹出询问时都会显示黄色边框。选不劫持后边框消失。已经允许、或应用是全部劫持时,输入框同样显示黄色边框。草稿已经命中任意一条指令时,边框改为蓝色。

记住的是输入框的种类,不是它在会话列表里的序号。种类路径里只有 AXTextArea 保留序号,其余组件的序号都去掉,再拼上子角色和占位符。同一应用里,占位符相同的各个会话输入框共用一次选择。标题、当前草稿和 identifier 不参与匹配。选择重启后仍然有效,并显示在设置里对应应用的下方。可以改成另一种,或选 下次再问 后重新询问。改成全部劫持后,这些选择会保留,但当前会接管该应用的所有输入框。范围修改后立即生效。已经添加的应用会保留原先保存的范围。按旧路径记住的选择对不上新种类,那些输入框会再问一次。

每个目标应用可以点 选择组件,在该应用里连续点选多个界面组件作为上下文。已选项会列在选择面板和设置里,可以逐个移除,也可以填写备注。输入框也能选,和它是否已经允许劫持、或不劫持无关;设置里每个输入框旁边也有 加入上下文。按 Esc 或 完成选择 结束。之后每次回车,言好读取这些组件的当前文字,用 <context tag="备注">文字</context> 加在交给模型的正文前面。备注末尾的冒号会去掉,所以备注「单聊:」会写成 tag="单聊"。没有备注时写成 <context>文字</context>。没有读到文字的组件不会写入上下文。标记只供模型理解,不会写回输入框;模型若改写标记,这次不会写回。指令脚本的 input 仍然是输入框里的原文,读到的上下文从第二个参数 context 传入。

润色期间,输入框边框会以黄色呼吸;这次草稿命中了指令时改为蓝色呼吸。菜单栏仍显示进度。润色并回填后边框变为绿色,再次回车发出或按下其它键后结束。完成后,菜单栏 绿点 表示成功,红点 表示失败;打开面板的 日志 可查看原文、结果、提示词和处理详情。

启动设置

设置中可开启“开机自启动(登录后启动)”(macOS 13+);如果系统要求批准,请在系统登录项设置中允许 Hola。macOS 12 可在系统偏好设置 → 用户与群组 → 登录项中手动添加应用。

每次打开应用后,只要辅助功能权限、输入监控权限、已保存的 OpenAI 配置和目标应用都可用,就会自动开启回车处理;手动停止只对当前这次运行有效。无法开启时,把指针停在底部的拦截开关上可以看到原因。未开启时,菜单栏图标右下角显示黄色圆点。

界面语言

言好在启动时跟随系统首选语言,也支持 macOS 为 App 单独设置的语言:

首选语言 界面显示
中文(包括简体、繁体及地区变体) 简体中文
英语及其他语言 English

菜单、设置、状态提示、错误信息和调用历史界面均支持中英文。修改系统或 App 语言后,退出并重新打开 Hola 即可生效。

默认提示词跟随界面语言,但会要求模型保留草稿原有语言,不会因为界面是英文就要求把中文草稿翻译为英文。已保存的自定义提示词、草稿及历史记录内容保持原样;历史中的处理说明保留记录时的语言。README 可通过顶部链接手动切换语言。

模型配置

润色接口

支持 OpenAI 兼容的 chat/completions 接口,可填写 Base URL 或完整接口地址。

配置项 说明
接口地址 服务商提供的 Base URL,例如 https://api.openai.com/v1
Token 对应服务商的 API 凭据
模型 该接口支持的模型名称
额外请求参数 可选的 JSON 对象,合并进 Chat Completions 请求体;例如 {"reasoning_effort":"high","stream":false}。不能覆盖 model 或 messages,当前仅支持 stream: false
润色提示词 定义表达风格,例如更自然、更简洁或更适合工作沟通

请求默认使用 stream: false。使用已识别的推理模型时,默认加入 {"reasoning_effort":"low"};其他模型不自动添加推理参数。额外请求参数中的值优先于默认值。

默认润色提示词:

你是文字润色助手。保持原文语言,在不改变原意、不添加新信息的前提下,让这段话更通顺、得体。只输出润色后的文本本身,不要加引号或任何解释。

可选的 Jev 判断

Jev 默认关闭。启用后,会先判断草稿是否需要润色,再决定是否调用润色模型。

模式 处理流程
默认:关闭 Jev 每轮都请求润色接口,根据返回结果决定直接发送或回填
开启 Jev 先判断;无需润色时直接补发回车,需要时才请求润色接口

指令配置

在面板的 指令 分区添加规则。规则按顺序匹配用户输入的完整原文;例如正则 ^# 匹配以 # 开头的草稿。脚本是一个函数表达式,言好会以原始草稿 input 和 context 调用它。context 是 JSON 数组,每项为 { tag, text },对应这次读到的上下文;没有读到时是 []。返回结果对象或 Promise 均可:

async (input, context) => {
  return { interrupt: true, replacement: input.slice(1) };
}

interrupt: true 会拦截本次回车;有非空 replacement 时写回草稿,确认后再次按回车发送。interrupt: false 会继续原有润色流程,并忽略 replacement。脚本失败或替换失败时不会发送。指令只在已选择目标应用的输入框中执行。

规则按从上到下的顺序匹配,拖动左侧手柄可以调整优先级。面板底部 导出 右侧的 测试 会打开测试窗口:先按当前指令匹配,没有拦截时再用当前人设试跑润色。测试使用正在编辑的规则和提示词,不记入历史,也不会发送。文稿可以手写,也可以从历史记录里选择曾经出现的原文、调整后结果或未采用的润色结果。

发起网络请求使用 fetch,用法与 Fetch 标准 一致。脚本里可以直接 await fetch(url, init),同时提供 Headers、Request、Response、AbortController、FormData、Blob 和 URLSearchParams。HTTP 4xx/5xx 不会让 Promise 失败,先看 response.ok;URL 不合法、连不上或完整性校验失败会以 TypeError 拒绝,用 AbortSignal 中止时以 AbortError 或 TimeoutError 拒绝。整段脚本(包括 fetch)需要在 10 秒内返回,超时不会发送。

执行本机命令使用 execute,用法与 Node.js child_process.exec 的 Promise 形式一致。await execute(command, options?) 成功时得到 { stdout, stderr }。command 在当前用户权限下交给 shell,默认 /bin/sh -c。options 可包含 cwd、env、encoding、shell、timeout、maxBuffer、killSignal、signal。encoding 默认 utf8,设为 "buffer" 时 stdout / stderr 是 Uint8Array。env 是完整的环境变量表。非 0 退出、超时或输出超过 maxBuffer(默认 1 MiB)会拒绝 Promise,错误对象上有 code、killed、signal、cmd、stdout、stderr。signal 中止时以 AbortError 拒绝。整段脚本(包括 execute)需要在 10 秒内返回,超时不会发送。

async (input) => {
  const response = await fetch("https://example.com/rewrite", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ text: input }),
  });
  if (!response.ok) throw new Error(String(response.status));
  const data = await response.json();
  return { interrupt: true, replacement: data.text };
}
async (input) => {
  const { stdout } = await execute("printf %s " + JSON.stringify(input));
  return { interrupt: true, replacement: stdout };
}

设置面板支持 导出 / 导入,可迁移目标应用列表、模型配置和指令。导入会替换文件中对应的设置;导出文件包含接口 Token 和指令脚本,请妥善保存。

兼容性与数据

应用支持取决于输入框。 言好通过 macOS Accessibility 读写普通文本输入框的 AXValue。自绘编辑器或未开放相关能力的应用可能无法使用;拖入应用并不代表已经验证兼容。发送行为也取决于目标应用如何处理回车。

含图片等嵌入对象的草稿会以 <object id="…"> 占位符交给模型。模型修改占位符时不会写回;文字发生变化时,仅在目标输入框支持局部文字写回的情况下修改对象两侧的文字,避免整段覆盖附件。

写回或补发回车前,工具会核对前台应用、输入框和草稿内容。AX 读写并非原子操作,也无法保证识别目标应用复用输入框的所有情况;处理期间请等待完成,切换会话后重新触发。使用中文输入法时,先确认候选词已上屏。

  • 处理范围:选定应用当前焦点输入框中的草稿。若为该应用选了上下文组件,回车时还会读取这些组件的文字,加在交给模型的正文前面。不读取密码控件。
  • 模型请求:草稿会发送至你配置的润色服务;开启 Jev 后也会发送至 Jev 服务。选中的上下文会一并放在正文前面。
  • 本地配置:设置及 Token 保存在 UserDefaults,当前未使用 Keychain 保存 Token。
  • 调用历史:最近 100 条记录保存在本地,包含草稿、注入的上下文、结果与提示词,可在调用历史窗口清空。旧记录没有上下文这一项。
本地历史文件位置
~/Library/Application Support/local.hola/round-history.json
~/Library/Application Support/local.holadev/round-history.json (开发版)

开发与验证

项目使用 Swift 和系统框架构建,无第三方源码依赖。

推送到 GitHub 的 main 分支会自动递增补丁版本、构建 Apple Silicon / Intel 通用包并发布到 Releases。配置要求、版本规则和失败重跑方式见自动发布说明。

文件 内容
Sources/main.swift 菜单栏、设置、草稿读写、模型调用与历史记录
Sources/Localization.swift 系统语言选择与本地化文案格式化
Resources 中英语言资源、应用与菜单栏图标
build.sh 编译、应用打包和本机签名
Info.plist 应用标识及系统配置
手工验收 目标应用、接口和输入行为的验收清单
验证记录 已执行的检查与尚未验证的范围

可运行 bash scripts/test-localization.sh 检查语言选择、资源完整性与动态文案(需先构建)。

根据现有验证记录,已在 macOS 环境完成构建与签名校验。真实模型接口与目标应用的端到端流程仍待验证。


Hola · 言好
你的意思,更好的表达。

About

Hola · 言好

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0