126 lines
5.1 KiB
Bash
Executable File
126 lines
5.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# macOS Handy 中文 + 回廊洗字粘贴(external_script 仅做洗字后 ⌘V,stdout 为空)
|
||
set -euo pipefail
|
||
|
||
KARUO_AI_ROOT="${KARUO_AI_ROOT:-/Users/karuo/Documents/个人/卡若AI}"
|
||
SETTINGS="$HOME/Library/Application Support/com.pais.handy/settings_store.json"
|
||
HANDY_DATA="$HOME/Library/Application Support/com.pais.handy"
|
||
HOOKS_DIR="${HANDY_DATA}/hooks"
|
||
MODELS="${HANDY_DATA}/models"
|
||
LOG="$HOME/Library/Logs/com.pais.handy/handy.log"
|
||
ASR_PASTE="${KARUO_AI_ROOT}/01_卡资(金)/金仓_存储备份/脚本/handy_macos_asr_paste.sh"
|
||
TRAN_HOOK="${KARUO_AI_ROOT}/01_卡资(金)/金仓_存储备份/脚本/handy_transcription_hook.sh"
|
||
|
||
echo "① 结束 handy 进程(可执行文件名为 handy 小写)"
|
||
killall -9 handy 2>/dev/null || true
|
||
sleep 2
|
||
|
||
if [[ ! -f "$SETTINGS" ]]; then
|
||
echo "首次使用:请先 open -a Handy 一次生成配置后重跑本脚本" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ ! -d "$MODELS/sense-voice-int8" ]]; then
|
||
echo "缺少 sense-voice-int8,下载:" >&2
|
||
echo " curl -fL -o /tmp/sv.tgz https://blob.handy.computer/sense-voice-int8.tar.gz" >&2
|
||
echo " tar -xzf /tmp/sv.tgz -C \"$MODELS\"" >&2
|
||
exit 1
|
||
fi
|
||
|
||
pk="${MODELS}/parakeet-tdt-0.6b-v3-int8"
|
||
off="${MODELS}/_disabled_parakeet-tdt-0.6b-v3-int8"
|
||
[[ -d "$pk" && ! -d "$off" ]] && mv "$pk" "$off"
|
||
|
||
export ASR_PASTE
|
||
python3 << PY
|
||
import json
|
||
import os
|
||
from pathlib import Path
|
||
|
||
p = Path(os.path.expanduser("~/Library/Application Support/com.pais.handy/settings_store.json"))
|
||
d = json.loads(p.read_text())
|
||
s = d["settings"]
|
||
|
||
s["selected_language"] = "zh-Hans"
|
||
s["app_language"] = "zh-Hans"
|
||
s["selected_model"] = "sense-voice-int8"
|
||
s["translate_to_english"] = False
|
||
s["post_process_enabled"] = False
|
||
s["ort_accelerator"] = "coreml"
|
||
s["whisper_accelerator"] = "coreml"
|
||
s["push_to_talk"] = True
|
||
s["autostart_enabled"] = False
|
||
s["mute_while_recording"] = False
|
||
# 勿用 external_script(0.8.3 启动会回滚为 auto+英文);洗字由剪贴板守护进程完成
|
||
s["paste_method"] = "ctrl_v"
|
||
s["external_script_path"] = None
|
||
s["clipboard_handling"] = "copy_to_clipboard"
|
||
|
||
b = s.setdefault("bindings", {}).setdefault("transcribe", {"id": "transcribe"})
|
||
b["current_binding"] = "command_left+1"
|
||
b["name"] = "语音转写"
|
||
b["description"] = "简体中文转写(SenseVoice)"
|
||
|
||
p.write_text(json.dumps(d, indent=2, ensure_ascii=False) + "\n")
|
||
print("OK 已写入: zh-Hans + sense-voice-int8 + ⌘1 + ctrl_v + copy_to_clipboard")
|
||
PY
|
||
|
||
chmod +x "$ASR_PASTE" "$TRAN_HOOK" 2>/dev/null || true
|
||
mkdir -p "$HOOKS_DIR"
|
||
ln -sf "$TRAN_HOOK" "${HOOKS_DIR}/transcription" 2>/dev/null || cp -f "$TRAN_HOOK" "${HOOKS_DIR}/transcription"
|
||
chmod +x "${HOOKS_DIR}/transcription" 2>/dev/null || true
|
||
echo " hooks/transcription → 新版 Handy 用"
|
||
|
||
echo "④ 安装剪贴板回廊洗字守护(Handy 写入剪贴板后、⌘V 前替换)"
|
||
chmod +x "${KARUO_AI_ROOT}/01_卡资(金)/金仓_存储备份/脚本/karuo_handy_clipboard_wash.py"
|
||
python3 "${KARUO_AI_ROOT}/01_卡资(金)/金仓_存储备份/脚本/karuo_handy_clipboard_wash.py" --install || echo " ⚠️ LaunchAgent 安装失败,可手动: python3 …/karuo_handy_clipboard_wash.py --install"
|
||
|
||
echo "② 启动 Handy"
|
||
open -a Handy
|
||
sleep 8
|
||
|
||
echo "②b 二次写入(避免 Handy 首次启动覆盖 ⌘1 / 剪贴板 / 语言)"
|
||
killall -9 handy 2>/dev/null || true
|
||
sleep 2
|
||
export ASR_PASTE
|
||
python3 << PY
|
||
import json, os
|
||
from pathlib import Path
|
||
p = Path(os.path.expanduser("~/Library/Application Support/com.pais.handy/settings_store.json"))
|
||
d = json.loads(p.read_text())
|
||
s = d["settings"]
|
||
s["selected_language"] = "zh-Hans"
|
||
s["app_language"] = "zh-Hans"
|
||
s["selected_model"] = "sense-voice-int8"
|
||
s["paste_method"] = "ctrl_v"
|
||
s["external_script_path"] = None
|
||
s["clipboard_handling"] = "copy_to_clipboard"
|
||
b = s.setdefault("bindings", {}).setdefault("transcribe", {"id": "transcribe"})
|
||
b["current_binding"] = "command_left+1"
|
||
p.write_text(json.dumps(d, indent=2, ensure_ascii=False) + "\n")
|
||
print("OK 二次写入 ⌘1 + zh-Hans + copy_to_clipboard")
|
||
PY
|
||
open -a Handy
|
||
sleep 6
|
||
|
||
echo "③ 校验(磁盘配置 + 日志)"
|
||
sleep 2
|
||
python3 -c "import json;s=json.load(open('$SETTINGS'))['settings'];print(' 磁盘:',s['selected_language'],s['selected_model'],s['paste_method'],s['bindings']['transcribe']['current_binding'])"
|
||
if [[ "$(python3 -c "import json;s=json.load(open('$SETTINGS'))['settings'];print(s['selected_language'])")" != "zh-Hans" ]]; then
|
||
echo " ⚠️ 语言被改回 auto:请在 Handy 设置 → 语言 选手动「简体中文 zh-Hans」后勿再改" >&2
|
||
fi
|
||
if rg -q 'selected_language: "zh-Hans"' "$LOG" 2>/dev/null; then
|
||
echo " 日志: 已加载 zh-Hans ✓"
|
||
else
|
||
echo " 日志: 未见到 zh-Hans,请把 handy.log 末 30 行发卡若AI" >&2
|
||
fi
|
||
if rg -q "sense-voice-int8" "$LOG" 2>/dev/null; then
|
||
echo " 日志: sense-voice 已出现 ✓"
|
||
fi
|
||
|
||
echo ""
|
||
echo "请按住 ⌘1 说:「卡若帮我改一下 skill」"
|
||
echo "粘贴应为中文且已洗字(守护进程在 ⌘V 前改剪贴板,如 科室→Cursor)。"
|
||
echo "洗字日志: ~/Library/Logs/karuo/handy_clipboard_wash.log"
|
||
echo "语音唤 Agent:pbpaste | python3 \"${KARUO_AI_ROOT}/运营中枢/工作台/脚本/karuo_voice_agent_plugin.py\""
|