diff --git a/.cursor/rules/system-app-config-no-direct-edit.mdc b/.cursor/rules/system-app-config-no-direct-edit.mdc index d9708487..eb6f1a6c 100644 --- a/.cursor/rules/system-app-config-no-direct-edit.mdc +++ b/.cursor/rules/system-app-config-no-direct-edit.mdc @@ -14,6 +14,6 @@ alwaysApply: true ## 正确做法 -- 本机语音输入真源:**Handy中文语音**(`01_卡资(金)/金仓_存储备份/Handy中文语音/SKILL.md`);豆包已于 2026-06-11 完整卸载。 +- 本机语音输入真源:**Handy中文语音**(`02_卡人(水)/水溪_整理归档/语音输入/SKILL.md`);豆包已于 2026-06-11 完整卸载。 - 其他 `~/Library/Application Support/**` 配置:用 **Shell + Python/bash 脚本** 写入;脚本放在仓库 `脚本/` 目录,不在 Cursor 里打开目标文件改。 - 需卸载第三方 App:用仓库 `脚本/` 下专用卸载脚本(如 `doubao_uninstall_full.sh`),禁止手改其数据目录。 diff --git a/.restore-backups/F22_恢复前_20260723_210051/SKILL_REGISTRY.md b/.restore-backups/F22_恢复前_20260723_210051/SKILL_REGISTRY.md index 635849cd..e60890b7 100644 --- a/.restore-backups/F22_恢复前_20260723_210051/SKILL_REGISTRY.md +++ b/.restore-backups/F22_恢复前_20260723_210051/SKILL_REGISTRY.md @@ -89,7 +89,7 @@ | G23 | **宿主挂载执行**(Shell 宿主语义) | 金仓 | **宿主挂载、宿主执行、云上 bash、万推控制台、挂载出错、karo_exec、自动 bash Mac 路径、brew 云端、Docker 宿主 shell、宿主程序** | `01_卡资(金)/金仓_存储备份/宿主挂载执行_SHELL/SKILL.md` | 网站对话与云端 shell ≠ Mac;工作区挂载 + docker-mac-host-shell + 宿主预检三位一体 | | G24 | **深蓝云自动化**(SLCloud · SHENLANYUN) | 金盾 | **深蓝云、深澜云、SHENLANYUN、slcloud、slcloud.org、slcloud-automation、订阅链接、体验套餐、深澜文档、token=、client/subscribe** | `01_卡资(金)/金盾_数据安全/深蓝云_SLCloud自动化/SKILL.md` | 深澜云平台注册/购套餐/取订阅链接;**支付与扫码必须用户接管**;真源自 `slcloud-automation.skill` | | G25 | **UU远程**(网易 · 遥台) | 金仓 | **UU远程、远程安装、远程装Codex、远程装软件、UU终端、远程插件、OFFICE-INNER、DESKTOP-434GEGI** | `01_卡资(金)/金仓_存储备份/UU远程/SKILL.md` | UURemote 本机安装 + **终端零手操**装任意软件/插件;`uu_remote_install_software.sh` / `uu_remote_install_codex.sh` | -| G25b | **Handy中文语音** | 金仓 | **Handy、卡若AI语音、语音唤醒、呼叫卡若AI、⌘1、Ctrl+1、SenseVoice、按住说话、Handy中文** | `01_卡资(金)/金仓_存储备份/Handy中文语音/SKILL.md` | 双平台 Handy 中文+**语音唤 Agent**(Hub 13458);zip 在 `4、火_工具开发/工具/Handy中文语音/` | +| G25b | **Handy中文语音** | 金仓 | **Handy、卡若AI语音、语音唤醒、呼叫卡若AI、⌘1、Ctrl+1、SenseVoice、按住说话、Handy中文** | `02_卡人(水)/水溪_整理归档/语音输入/SKILL.md` | 双平台 Handy 中文+**语音唤 Agent**(Hub 13458);zip 在 `4、火_工具开发/工具/Handy中文语音/` | | G27 | **Codex账号备份恢复** | 金仓·库政 | **Codex备份、Codex恢复、账号切换恢复、Codex迁移、Codex材料恢复、Codex记录恢复** | `01_卡资(金)/金仓_存储备份/CodexAccountBackupRestore/SKILL.md` | Codex配置、Skill、记忆、会话索引和状态库备份恢复 | | G28 | **Codex对话状态修复** | 金仓·算巡 | **Codex侧栏修复、Codex对话恢复、Codex项目分类、Codex置顶、rollout缺失、thread-store internal error、session_index、state_5.sqlite、公司NAS Mongo备份、跨Codex恢复** | `01_卡资(金)/金仓_存储备份/Codex对话状态修复/SKILL.md` | 修复Codex侧栏与状态库;按项目/工作树保存完整事件链到公司NAS Mongo,并生成跨实例恢复包 | | G29 | **域名调研注册** | 金仓·网卫 | **域名调研、域名注册、域名抢注、老域名、ICP备案、历史备案、WHOIS、RDAP、域名风险** | `01_卡资(金)/金仓_存储备份/域名调研注册/SKILL.md` | 域名候选、历史流量、备案、风险核验和注册执行 | diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/开发文档/功能迭代记录.md b/01_卡资(金)/金仓_存储备份/Handy中文语音/开发文档/功能迭代记录.md deleted file mode 100644 index dd0000b3..00000000 --- a/01_卡资(金)/金仓_存储备份/Handy中文语音/开发文档/功能迭代记录.md +++ /dev/null @@ -1,60 +0,0 @@ -# 功能迭代记录 - -## 2026-07-12|v1.4.3 修复自动输入 - -- 用户真实验证发现:纠错结果进剪贴板,但仍需手动粘贴。 -- 直接核对 Handy v0.8.3 源码 `src-tauri/src/clipboard.rs`:ExternalScript 将文本作为 `$1`,忽略 stdout,并要求脚本自行完成输入。 -- 插件恢复 `$1` 读取,纠错后写剪贴板,等待 350ms 恢复焦点,再自动发送 `⌘V`。 -- `clipboard_handling` 改为 `dont_modify`,避免 Handy 随后用原始转写覆盖纠错后的剪贴板。 -- 新增 `~/Library/Logs/com.pais.handy/karuo_asr_plugin.log`,记录调用、纠错和粘贴失败,不记录正文。 -- 自动输入优先使用本机 `cliclick`,不可用时才回退 System Events;macOS 必须授予对应输入程序辅助功能权限。 - -## 2026-07-12|v1.4.2 自动输入当前对话框 - -- 固化 `clipboard_handling=copy_to_clipboard` 与 `auto_submit=false`。 -- Handy 收到插件 stdout 后自动写入当前焦点对话框,不需要用户手动粘贴。 -- 默认只填入、不自动发送,避免语音误识别直接提交。 - -## 2026-07-12|v1.4.1 修复Handy插件传参协议 - -- 用户真实语音验证发现:Handy日志显示插件被调用,但输入框仍是原文。 -- 根因:旧脚本从参数/剪贴板读取,并自行 ⌘V;Handy 0.8.3 实际从 stdin 传入转写、读取 stdout 作为最终文本。 -- 修复:插件改为纯过滤器 `stdin → 回廊洗字 → stdout`,不再操作剪贴板或模拟按键。 -- 验收标准:管道输入“纯客宝、卡罗亚”时,stdout 必须返回“存客宝、卡若AI”。 - -## 2026-07-12|v1.4 Handy输入阶段ASR纠错 - -### 目标 - -Handy 语音转写后、文字进入当前输入框前,自动调用卡若AI统一ASR纠错库。 - -### 链路 - -```text -Handy录音 - -> SenseVoice zh-Hans转写 - -> handy_macos_asr_paste.sh - -> apply_karuo_voice_corrections.py - -> 卡若闽南口音_ASR纠错库.json - -> 剪贴板 - -> 当前输入框 -``` - -### 修改 - -- Handy `paste_method` 改为 `external_script`。 -- `external_script_path` 指向已验证的 `handy_macos_asr_paste.sh`。 -- 新增 `enable_karuo_asr_correction_macos.sh`,自动备份配置、接线并重启 Handy。 -- 钩子新增 `KARUO_ASR_TEST_ONLY=1` 无粘贴测试模式。 -- 补充 `卡罗AI/卡洛AI/卡路AI` 无空格纠错变体。 - -### 验证 - -- Handy 0.8.3 正常启动,SenseVoice 与 `zh-Hans` 保持不变。 -- Handy 日志确认加载 `ExternalScript` 和目标脚本。 -- 测试输入“打开纯客宝后台,卡罗AI帮我检查”输出“打开存客宝后台,卡若AI帮我检查”。 -- Cursor/Codex 对话层仍保留回廊洗字二次兜底。 - -### 回滚 - -恢复 `settings_store.json.bak.asr.*` 备份并重启 Handy,或把 `paste_method` 改回 `ctrl_v`、`external_script_path` 改回 `null`。 diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/scripts/东京服务器_TAT_状态检查与VPN安装.py b/01_卡资(金)/金仓_存储备份/服务器管理/scripts/东京服务器_TAT_状态检查与VPN安装.py new file mode 100644 index 00000000..865530ab --- /dev/null +++ b/01_卡资(金)/金仓_存储备份/服务器管理/scripts/东京服务器_TAT_状态检查与VPN安装.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""TAT 东京服务器: 状态检查 + 一键安装系统级 VPN(IKEv2 + L2TP)""" +import base64, json, os, re, sys, time + + +def _read_creds(): + """从真源私密总表读腾讯云 Lighthouse 凭证(AKID8Q...)""" + d = os.path.dirname(os.path.abspath(__file__)) + for _ in range(6): + if os.path.basename(d) == "卡若AI": + break + d = os.path.dirname(d) + p = os.path.join(d, "运营中枢", "私密配置", "账号密码与API私密总表.md") + if not os.path.isfile(p): + return None, None + with open(p, "r", encoding="utf-8") as f: + t = f.read() + m = re.search(r"API SecretId\s*\|\s*`([^`]+)`", t) + n = re.search(r"API SecretKey\s*\|\s*`([^`]+)`", t) + if m and n: + return m.group(1).strip(), n.group(1).strip() + return None, None + + +def find_tokyo_instance(cli): + from tencentcloud.lighthouse.v20200324 import models + req = models.DescribeInstancesRequest() + r = cli.DescribeInstances(req) + for inst in (r.InstanceSet or []): + if "43.165.178.230" in (inst.PublicAddresses or []): + return inst.InstanceId, inst.InstanceName, inst.InstanceState + return None, None, None + + +def tat_run(client, instance_id, content_b64, name, timeout=180): + from tencentcloud.tat.v20201028 import models + req = models.RunCommandRequest() + req.Content = content_b64 + req.InstanceIds = [instance_id] + req.CommandType = "SHELL" + req.Timeout = timeout + req.CommandName = name + resp = client.RunCommand(req) + return resp.InvocationId + + +def tat_get_result(client, inv_id, wait_sec=40): + from tencentcloud.tat.v20201028 import models + print(f" 等待 {wait_sec}s 取回结果...") + time.sleep(wait_sec) + req = models.DescribeInvocationTasksRequest() + f = models.Filter() + f.Name = "invocation-id" + f.Values = [inv_id] + req.Filters = [f] + r = client.DescribeInvocationTasks(req) + for t in (r.InvocationTaskSet or []): + tr = getattr(t, "TaskResult", None) + if not tr: + continue + try: + jj = json.loads(tr) if isinstance(tr, str) else tr + out = jj.get("Output", "") + if out: + out = base64.b64decode(out).decode("utf-8", errors="replace") + print("--- 服务器输出 ---\n" + out[:8000] + "\n---") + except Exception as e: + print(f" 解析结果失败: {e}\n 原始: {str(tr)[:600]}") + + +def main(): + sid, skey = _read_creds() + if not sid or not skey: + print("❌ 未读到腾讯云凭证") + return 1 + print(f" 凭证: {sid[:8]}...{skey[-6:]}") + + from tencentcloud.common import credential + from tencentcloud.lighthouse.v20200324 import lighthouse_client as ls_cli + from tencentcloud.tat.v20201028 import tat_client as t_cli + + REGION = "ap-tokyo" + cred = credential.Credential(sid, skey) + ls = ls_cli.LighthouseClient(cred, REGION) + iid, iname, istate = find_tokyo_instance(ls) + if not iid: + print("❌ 在 ap-tokyo 区域未找到 43.165.178.230 的实例") + return 1 + print(f" 服务器: {iname} ID={iid} 状态={istate}") + + # ===== 1. 状态检查 ===== + cmd_status = r''' +echo "=== 1. 服务器基础信息 ===" +uname -a +cat /etc/os-release 2>/dev/null | head -3 +echo "" + +echo "=== 2. 资源 ===" +uptime +echo "磁盘:"; df -h / | tail -2 +echo "内存:"; free -h | head -2 +echo "" + +echo "=== 3. 关键服务 ===" +for s in strongswan xl2tpd nginx bt; do + systemctl is-active $s 2>/dev/null || echo "$s: 未安装/未运行" +done +echo "" + +echo "=== 4. 监听端口 ===" +ss -tulnp 2>/dev/null | awk '/LISTEN|UNCONN/ {print $1, $5}' | sort -u | head -30 +echo "" + +echo "=== 5. WireGuard / 进程 ===" +ls /etc/wireguard/ 2>/dev/null || echo "wireguard: 未安装" +wg show 2>/dev/null | head -10 || echo "wg: 未运行" +echo "" + +echo "=== 6. iptables 状态 ===" +iptables -L INPUT -n 2>/dev/null | head -10 +echo "" + +echo "=== 7. 腾讯云外网自检 ===" +curl -s --max-time 5 https://api.ipify.org +echo "" +''' + print("\n[1/2] TAT 状态检查...") + tat = t_cli.TatClient(cred, REGION) + inv = tat_run(tat, iid, base64.b64encode(cmd_status.encode()).decode(), "TokyoStatusCheck", timeout=60) + print(f" 任务下发: {inv}") + tat_get_result(tat, inv, wait_sec=20) + + # ===== 2. 推送并执行 VPN 安装 ===== + script_path = os.path.join(os.path.dirname(__file__), "东京服务器_一键安装IKEv2_L2TP_VPN.sh") + if not os.path.isfile(script_path): + print(f"❌ 找不到脚本: {script_path}") + return 1 + with open(script_path, "r", encoding="utf-8") as f: + script_content = f.read() + print(f"\n[2/2] 推送并执行 VPN 安装脚本 ({len(script_content)} bytes)...") + install_cmd = ( + "cat > /tmp/vpn_install.sh << 'SCRIPT_EOF'\n" + + script_content + + "\nSCRIPT_EOF\n" + "chmod +x /tmp/vpn_install.sh\n" + "echo '脚本已写入 /tmp/vpn_install.sh,开始执行...'\n" + "bash /tmp/vpn_install.sh 2>&1\n" + ) + inv2 = tat_run(tat, iid, base64.b64encode(install_cmd.encode()).decode(), "TokyoInstallVPN", timeout=300) + print(f" 安装任务下发: {inv2}") + tat_get_result(tat, inv2, wait_sec=90) + + print("\n" + "="*60) + print(" ✅ TAT 流程结束") + print("="*60) + print("\n下一步用户在腾讯云控制台操作:") + print(" 轻量应用服务器 → 43.165.178.230 → 防火墙 → 添加规则:") + print(" 500/UDP 4500/UDP 1701/UDP (来源 0.0.0.0/0)") + print("\n然后 macOS 系统设置 → 网络 → 添加 VPN 配置:") + print(" • IKEv2(系统原生,零中间件): 服务器 43.165.178.230 · 远程ID 43.165.178.230") + print(" 账号 karuo · 密码 KaruoVPN@2026") + print(" • L2TP/IPSec(系统原生): 服务器 43.165.178.230 · 共享密钥 KaruoL2TP@2026") + print(" 账号 karuo · 密码 KaruoVPN@2026") + print(" • WireGuard(需装App,最快): 见 运营中枢/私密配置/房市通东京节点/wireguard-client.conf") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/scripts/东京服务器_一键安装IKEv2_L2TP_VPN.sh b/01_卡资(金)/金仓_存储备份/服务器管理/scripts/东京服务器_一键安装IKEv2_L2TP_VPN.sh new file mode 100755 index 00000000..2a6e3035 --- /dev/null +++ b/01_卡资(金)/金仓_存储备份/服务器管理/scripts/东京服务器_一键安装IKEv2_L2TP_VPN.sh @@ -0,0 +1,196 @@ +#!/bin/bash +# ============================================================ +# 东京服务器一键安装系统级 VPN(macOS 系统设置可直接用) +# - IKEv2/IPSec(strongSwan)— macOS 推荐 +# - L2TP/IPSec(xl2tpd + strongSwan)— 兼容老设备 +# 服务器:43.165.178.230(腾讯云东京 Lighthouse) +# ============================================================ +set -e +echo "==================================================" +echo " 卡若AI · 东京服务器系统 VPN 一键安装" +echo " 开始时间: $(date '+%F %T')" +echo "==================================================" + +# 1. 防火墙放行(必须) +echo "" +echo ">>> 1. 放行 VPN 端口(腾讯云防火墙在控制台另开)" +iptables -I INPUT -p udp --dport 500 -j ACCEPT 2>/dev/null || true +iptables -I INPUT -p udp --dport 4500 -j ACCEPT 2>/dev/null || true +iptables -I INPUT -p udp --dport 1701 -j ACCEPT 2>/dev/null || true +iptables -I INPUT -p udp --dport 50 -j ACCEPT 2>/dev/null || true +iptables -I INPUT -p udp --dport 51 -j ACCEPT 2>/dev/null || true +ufw allow 500/udp 2>/dev/null || true +ufw allow 4500/udp 2>/dev/null || true +ufw allow 1701/udp 2>/dev/null || true +echo " 端口 500/4500/1701/50/51 已放行" + +# 2. 开启 IP 转发 +echo "" +echo ">>> 2. 开启 IP 转发" +grep -q "net.ipv4.ip_forward=1" /etc/sysctl.conf || echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf +sysctl -w net.ipv4.ip_forward=1 >/dev/null +echo " IP 转发已开启" + +# 3. 安装 strongSwan + xl2tpd +echo "" +echo ">>> 3. 安装 strongSwan / xl2tpd / ppp" +export DEBIAN_FRONTEND=noninteractive +if command -v apt-get >/dev/null 2>&1; then + apt-get update -qq + apt-get install -y -qq strongswan strongswan-pki libstrongswan-extra-plugins xl2tpd ppp +elif command -v yum >/dev/null 2>&1; then + yum install -y epel-release + yum install -y strongswan xl2tpd ppp +fi + +# 4. 生成证书与密钥 +echo "" +echo ">>> 4. 生成 IKEv2 证书与账号" +mkdir -p /etc/ipsec.d/{certs,private,cacerts} +cd /etc/ipsec.d +# CA 私钥 +strongswan pki --gen --type rsa --size 2048 --outform pem > /etc/ipsec.d/private/caKey.pem 2>/dev/null +# CA 证书 +strongswan pki --self --ca --lifetime 3650 \ + --in /etc/ipsec.d/private/caKey.pem \ + --type rsa --dn "C=CN, O=KaruoAI, CN=KaruoAI VPN CA" \ + --outform pem > /etc/ipsec.d/cacerts/caCert.pem 2>/dev/null +# 服务器私钥 +strongswan pki --gen --type rsa --size 2048 --outform pem > /etc/ipsec.d/private/serverKey.pem 2>/dev/null +# 服务器证书 +strongswan pki --pub --in /etc/ipsec.d/private/serverKey.pem --type rsa \ + | strongswan pki --issue --lifetime 3650 --cacert /etc/ipsec.d/cacerts/caCert.pem \ + --cakey /etc/ipsec.d/private/caKey.pem \ + --dn "C=CN, O=KaruoAI, CN=43.165.178.230" \ + --san "43.165.178.230" --flag serverAuth --flag ikeIntermediate \ + --outform pem > /etc/ipsec.d/certs/serverCert.pem 2>/dev/null +echo " 证书已生成" + +# 5. strongSwan 配置(IKEv2) +echo "" +echo ">>> 5. 配置 strongSwan IKEv2" +cat > /etc/ipsec.conf <<'EOF' +config setup + charondebug="ike 1, knl 1, cfg 0" + uniqueids=no + +conn ikev2-vpn + auto=add + compress=no + type=tunnel + keyexchange=ikev2 + fragmentation=yes + forceencaps=yes + dpdaction=clear + dpddelay=300s + rekey=no + left=%any + leftid=43.165.178.230 + leftcert=serverCert.pem + leftsendcert=always + leftsubnet=0.0.0.0/0 + right=%any + rightid=%any + rightauth=eap-mschapv2 + rightsourceip=10.10.10.0/24 + rightdns=8.8.8.8,1.1.1.1 + rightsendcert=never + eap_identity=%identity +EOF + +# 账号密码(PSK + 用户名/密码) +cat > /etc/ipsec.secrets <<'EOF' +: RSA serverKey.pem +karuo : EAP "KaruoVPN@2026" +EOF +chmod 600 /etc/ipsec.secrets + +# 6. xl2tpd 配置(L2TP/IPSec) +echo "" +echo ">>> 6. 配置 L2TP/IPSec" +cat > /etc/xl2tpd/xl2tpd.conf <<'EOF' +[global] +ipsec saref = yes +listen-addr = 43.165.178.230 + +[lns default] +ip range = 10.10.11.10-10.10.11.250 +local ip = 10.10.11.1 +require chap = yes +refuse pap = yes +require authentication = yes +name = l2tpd +pppoptfile = /etc/ppp/options.xl2tpd +length bit = yes +EOF + +cat > /etc/ppp/options.xl2tpd <<'EOF' +ipcp-accept-local +ipcp-accept-remote +ms-dns 8.8.8.8 +ms-dns 1.1.1.1 +noccp +auth +crtscts +idle 1800 +mtu 1410 +mru 1410 +lock +proxyarp +lcp-echo-interval 30 +lcp-echo-failure 4 +EOF + +# L2TP 共享密钥 + 用户 +cat >> /etc/ipsec.secrets <<'EOF' +43.165.178.230 : PSK "KaruoL2TP@2026" +EOF +echo 'karuo l2tpd "KaruoVPN@2026" *' > /etc/ppp/chap-secrets +chmod 600 /etc/ppp/chap-secrets + +# strongSwan 也允许 L2TP +cat >> /etc/ipsec.conf <<'EOF' + +conn l2tp-psk + auto=add + type=transport + keyexchange=ikev1 + authby=secret + left=%any + leftprotoport=17/1701 + right=%any + rightprotoport=17/%any + rekey=no +EOF +chmod 600 /etc/ipsec.secrets + +# 7. 启动服务 +echo "" +echo ">>> 7. 启动 strongSwan / xl2tpd" +systemctl enable strongswan xl2tpd 2>/dev/null || true +systemctl restart strongswan 2>/dev/null || /etc/init.d/strongswan restart 2>/dev/null +systemctl restart xl2tpd 2>/dev/null || /etc/init.d/xl2tpd restart 2>/dev/null + +sleep 2 +echo "" +echo ">>> 8. 状态检查" +ss -ulnp | grep -E ":500|:4500|:1701" || true +ipsec status 2>/dev/null | head -10 || true + +echo "" +echo "==================================================" +echo " 安装完成!" +echo " 服务器:43.165.178.230" +echo "" +echo " ★ IKEv2(macOS 推荐·原生)" +echo " 服务器地址: 43.165.178.230" +echo " 远程 ID: 43.165.178.230" +echo " 账号: karuo" +echo " 密码: KaruoVPN@2026" +echo "" +echo " ★ L2TP/IPSec(备用)" +echo " 服务器地址: 43.165.178.230" +echo " 共享密钥: KaruoL2TP@2026" +echo " 账号: karuo" +echo " 密码: KaruoVPN@2026" +echo "==================================================" diff --git a/01_卡资(金)/金仓_存储备份/脚本/doubao_voice_shortcut_option1.sh b/01_卡资(金)/金仓_存储备份/脚本/doubao_voice_shortcut_option1.sh index 78bb4f36..9cb969b7 100755 --- a/01_卡资(金)/金仓_存储备份/脚本/doubao_voice_shortcut_option1.sh +++ b/01_卡资(金)/金仓_存储备份/脚本/doubao_voice_shortcut_option1.sh @@ -3,7 +3,7 @@ # 原功能:豆包「全局语音输入」固定为 Option+1(macOS 显示 ⌥1 = ALT+1) set -euo pipefail -echo "❌ 豆包已卸载。语音输入请用:01_卡资(金)/金仓_存储备份/Handy中文语音/SKILL.md" >&2 +echo "❌ 豆包已卸载。语音输入请用:02_卡人(水)/水溪_整理归档/语音输入/SKILL.md" >&2 exit 2 DOUBAO="$HOME/Library/Application Support/Doubao" TARGET="Option+1" diff --git a/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/图1.png b/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/图1.png new file mode 100644 index 00000000..405d4bbd Binary files /dev/null and b/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/图1.png differ diff --git a/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/图2.png b/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/图2.png new file mode 100644 index 00000000..0e1c6612 Binary files /dev/null and b/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/图2.png differ diff --git a/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/图3.png b/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/图3.png new file mode 100644 index 00000000..ff5facef Binary files /dev/null and b/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/图3.png differ diff --git a/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/第238场文章_飞书版.txt b/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/第238场文章_飞书版.txt new file mode 100644 index 00000000..59267756 --- /dev/null +++ b/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/第238场文章_飞书版.txt @@ -0,0 +1,127 @@ +关注派对房号 FM29037620 + +第238场|AI开始替你做事,最先要学会的不是提速,是设边界 + +AI真正开始接手执行之后,最值钱的能力不再是会不会让它干活,而是能不能把权限、数据和成交边界管住。 + +2026年7月24日,约1小时36分。 + +早场有人拿着刚买的软件上麦,说以前提取一个视频文件要手动敲很久,现在几秒钟就能完成。那种高兴很真实——不是因为省下了几分钟,而是忽然看见,原来自己卡了很久的事,也可以有更轻一点的做法。 + +派对里的小伙伴随即聊到收费工具、海外软件和AI能力差异。话题很快从“要不要花钱”变成了另一个更现实的问题: + +工具升级以后,人到底能不能把省下来的时间换成结果? + +再往后,讨论转到了AI权限、数据备份、广告交互、游戏IP和私域运营。 听起来跨度很大,但底层是一件事 + +——以前我们买工具、买流量、买账号; + +现在,真正要为“谁可以执行、执行到哪一步、出了问题怎么恢复”负责。 + +工具贵不贵,不能只看价格 + +那位做文案和视频处理的小伙伴说,原来很多动作都靠手敲,后来装了一个提取工具,几秒钟就能完成过去几分钟的操作。 + +有人问:“那收费软件要不要试?” + +答案很直接:该付费就付费。真正该算的不是软件每月多少钱,而是它帮你省下了多少时间,能不能让你多完成几次交付。 + +便宜工具如果让你反复返工,最后付出的不是月费,而是机会成本。 + +当然,付费也不等于随便买。软件来源、账号权限、数据安全和服务条款都要看清楚。尤其是需要外部网络或第三方账号的工具,应该使用合规渠道和官方支持的方式,不要把“能不能绕过去”当成能力。 + +派对里的小伙伴接了一句:“以前觉得AI只是聊天,现在好像真的能帮忙做事了。” + +这句话说到了变化。前一段时间,大家更多是在让AI写文案、做表格、整理工作流;现在,AI越来越像一个能执行任务的助手。你给它目标、资料和权限,它就会继续往下推进。 + +但权限一旦放出去,风险也跟着出去。企业的电脑、知识库、账号、客户资料和自动化任务,不能因为“AI很聪明”就全部交给它。 + +真正成熟的用法是:让AI做清楚可回滚的事情,把关键操作设成确认点,重要文件按小时或按周期备份,出了问题能够恢复。这样才是效率,不是把所有按钮都交出去以后祈祷它别出错。 + +AI的下一阶段,是安全边界和真实成交 + +AI变化已经快到以周为单位。以前大家比的是谁的模型更强、谁的算力更多; + +现在越来越多的企业开始关心,AI能不能在业务流程里稳定执行,能不能完成一笔真实成交,能不能不越权、不乱改、不把客户数据带错地方。 + +这也是安全边界的重要性。 + +AI可以帮你分析客户、整理资料、生成内容、跟进任务,但哪些信息可以读取,哪些动作需要人工确认,哪些事情绝对不能碰,必须提前写清楚。 + +不要把“自动化”理解成“完全不用管”。 + +自动化真正成熟的样子,是把人从重复动作里解放出来,把人留在判断、授权和责任的位置上。 + +这一点放到广告里也很明显。传统信息流广告是刷到、点开、购买; 以后更像是一个虚拟角色主动和你沟通,根据你的兴趣介绍产品。 ta可能更像销售,也更容易让人放下戒心。 + +这对平台和商家都是提醒:人设可以帮助沟通,但不能用来伪装身份、诱导消费; + +AI可以提高触达效率,但不能替代真实的产品和售后。流量越像真人,规则越要写在前面。 + +数据也一样。企业把资料放进知识库,把任务交给AI之前,至少要知道谁能看、谁能改、多久备份一次、异常时怎么恢复。能跑起来只是第一关,能安全地跑一年,才叫产品。 + +游戏IP的价值,不在违规捷径 + +自己很早就接触游戏行业,后来把游戏主播、粉丝、周边产品和社群运营串起来,尝试把游戏影响力转成长期客户关系。 + +这件事的价值,不在于某一个游戏,而在于游戏IP本身可以承载什么:内容、粉丝、周边、陪练、赛事、品牌合作,甚至是围绕玩家需求建立的正规服务。 + +派对里的小伙伴问,为什么不直接做游戏俱乐部? + +答案是,俱乐部和IP运营不是一回事。俱乐部负责培养和管理选手,IP运营更关心粉丝沉淀、内容持续和商业合作。两者可以合作,但边界、分工和收入来源要提前说清楚。 + +有人提到账号抵押、游戏资产和典当。这里的边界更不能模糊: 涉及金融、典当、账号交易或数字资产,必须有合法主体、合规牌照、明确估值和税务处理. 没有资质就不要把高风险业务包装成“副业机会”。 + +能赚钱的项目,不等于什么都能碰;长期做生意,先把牌照、规则和责任放在桌面上。 + +真正稳的游戏私域,应该是围绕合法内容和服务做沉淀:主播直播,团队负责运营,粉丝进入明确的服务流程,产品和合作方都能核验。 + +客户不是一串可以随意搬运的数字,粉丝也不是拿来反复骚扰的流量。 + +先看同行能不能做,再看自己能不能扛 + +有人问,判断一个项目值不值得做,是不是看同行已经赚到钱就行? + +这只能算第一步。同行赚钱,说明市场可能存在; + +但你还要问三个问题: + +自己有没有相同的资源; + +能不能承受前期成本; + +愿不愿意长期做交付。 + +一个做直播带货的人讲到,直播间、设备、办公和人员,每个月都要支出。真正开始之前,他已经知道自己要承担什么,而不是只看到别人晒出来的收入。 + +过去拉新很热闹,现在更重要的是用户资产数字化: 一个用户一年能产生多少价值,服务成本是多少,复购和转化如何记录。 数据只有被长期跟踪,才有资格拿去谈合作或融资。 + +这和“先做小、再放大”是一个逻辑。不要一上来就投很大的钱,也不要为了证明自己敢干,先签下无法承受的成本。用较小的投入跑几轮,看客户是否愿意留下,再决定要不要加人、加设备、加渠道。 + +派对里的小伙伴说:“我就是不知道AI到底怎么挣钱。” + +我接得很简单:AI本身只是工具,挣钱的地方在于它帮你降低了什么成本,提升了什么人效,或者让哪一种服务可以被稳定交付。 + +比如,一个有几万客户的私域团队,不可能每天手动看完每个人的朋友圈、聊天阶段和生日。 AI可以帮助整理客户行为、提醒回访、分配意向,但最后的沟通和成交仍然需要人判断。 + +这不是用AI替代所有人,而是让有限的人服务更多真正有价值的客户。客户越多,越不能只靠记忆;数据越多,越要把人留在关键判断上。 + +规则先于速度,稳定才是最便宜的增长 + +这一场有一个很清楚的变化:机会没有消失,只是门槛从“会不会操作”变成了“能不能稳定交付”。 + +软件要正规,数据要保护,AI要设权限,游戏项目要守边界,私域要有客户价值,合作要把责任讲清楚。速度当然重要,但没有规则的速度,往往只是更快撞上问题。 + +做项目的人也不需要一下子把未来十年想明白。两三个星期看一次变化,重新检查自己的工具、流程和客户; + +能优化就优化,不能成立的就停下来。别把预测未来当成逃避今天交付的理由。 + +最后留下三个动作: + +第一,把正在使用的AI工具列出来,标清楚它能读什么、能改什么、谁能授权。 + +第二,把自己的客户和粉丝分成“触达、服务、成交、复购”几个阶段,别只盯着人数。 + +第三,选一个小项目做一轮真实交付,用成本和结果判断能不能继续,不用想象替自己赚钱。 + +看得懂机会只是开始。能把机会做成产品,把产品做成服务,把服务做得安全、稳定、可复用,才是真正的能力。#派对会员 想继续跟上AI和商业变化,来派对里听真实案例,有问题直接 @我。 diff --git a/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/第238场|AI开始替你做事,最先要学会的不是提速,是设边界.md b/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/第238场|AI开始替你做事,最先要学会的不是提速,是设边界.md new file mode 100644 index 00000000..3864277a --- /dev/null +++ b/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/exports/第238场_20260725/第238场|AI开始替你做事,最先要学会的不是提速,是设边界.md @@ -0,0 +1,3 @@ +# 第238场|AI开始替你做事,最先要学会的不是提速,是设边界 + +

AI真正开始接手执行之后,最值钱的能力不再是会不会让它干活,而是能不能把权限、数据和成交边界管住。

2026年7月24日,约1小时36分。

早场有人拿着刚买的软件上麦,说以前提取一个视频文件要手动敲很久,现在几秒钟就能完成。那种高兴很真实——不是因为省下了几分钟,而是忽然看见,原来自己卡了很久的事,也可以有更轻一点的做法。

派对里的小伙伴随即聊到收费工具、海外软件和AI能力差异。话题很快从“要不要花钱”变成了另一个更现实的问题:

工具升级以后,人到底能不能把省下来的时间换成结果?

再往后,讨论转到了AI权限、数据备份、广告交互、游戏IP和私域运营。 听起来跨度很大,但底层是一件事

——以前我们买工具、买流量、买账号;

现在,真正要为“谁可以执行、执行到哪一步、出了问题怎么恢复”负责。

工具贵不贵,不能只看价格

那位做文案和视频处理的小伙伴说,原来很多动作都靠手敲,后来装了一个提取工具,几秒钟就能完成过去几分钟的操作。

有人问:“那收费软件要不要试?”

答案很直接:该付费就付费。真正该算的不是软件每月多少钱,而是它帮你省下了多少时间,能不能让你多完成几次交付。

便宜工具如果让你反复返工,最后付出的不是月费,而是机会成本。

当然,付费也不等于随便买。软件来源、账号权限、数据安全和服务条款都要看清楚。尤其是需要外部网络或第三方账号的工具,应该使用合规渠道和官方支持的方式,不要把“能不能绕过去”当成能力。

派对里的小伙伴接了一句:“以前觉得AI只是聊天,现在好像真的能帮忙做事了。”

这句话说到了变化。前一段时间,大家更多是在让AI写文案、做表格、整理工作流;现在,AI越来越像一个能执行任务的助手。你给它目标、资料和权限,它就会继续往下推进。

但权限一旦放出去,风险也跟着出去。企业的电脑、知识库、账号、客户资料和自动化任务,不能因为“AI很聪明”就全部交给它。

真正成熟的用法是:让AI做清楚可回滚的事情,把关键操作设成确认点,重要文件按小时或按周期备份,出了问题能够恢复。这样才是效率,不是把所有按钮都交出去以后祈祷它别出错。

AI的下一阶段,是安全边界和真实成交

AI变化已经快到以周为单位。以前大家比的是谁的模型更强、谁的算力更多;

现在越来越多的企业开始关心,AI能不能在业务流程里稳定执行,能不能完成一笔真实成交,能不能不越权、不乱改、不把客户数据带错地方。

这也是安全边界的重要性。

AI可以帮你分析客户、整理资料、生成内容、跟进任务,但哪些信息可以读取,哪些动作需要人工确认,哪些事情绝对不能碰,必须提前写清楚。

不要把“自动化”理解成“完全不用管”。

自动化真正成熟的样子,是把人从重复动作里解放出来,把人留在判断、授权和责任的位置上。

这一点放到广告里也很明显。传统信息流广告是刷到、点开、购买; 以后更像是一个虚拟角色主动和你沟通,根据你的兴趣介绍产品。 ta可能更像销售,也更容易让人放下戒心。

这对平台和商家都是提醒:人设可以帮助沟通,但不能用来伪装身份、诱导消费;

AI可以提高触达效率,但不能替代真实的产品和售后。流量越像真人,规则越要写在前面。

数据也一样。企业把资料放进知识库,把任务交给AI之前,至少要知道谁能看、谁能改、多久备份一次、异常时怎么恢复。能跑起来只是第一关,能安全地跑一年,才叫产品。

游戏IP的价值,不在违规捷径

自己很早就接触游戏行业,后来把游戏主播、粉丝、周边产品和社群运营串起来,尝试把游戏影响力转成长期客户关系。

这件事的价值,不在于某一个游戏,而在于游戏IP本身可以承载什么:内容、粉丝、周边、陪练、赛事、品牌合作,甚至是围绕玩家需求建立的正规服务。

派对里的小伙伴问,为什么不直接做游戏俱乐部?

答案是,俱乐部和IP运营不是一回事。俱乐部负责培养和管理选手,IP运营更关心粉丝沉淀、内容持续和商业合作。两者可以合作,但边界、分工和收入来源要提前说清楚。

有人提到账号抵押、游戏资产和典当。这里的边界更不能模糊: 涉及金融、典当、账号交易或数字资产,必须有合法主体、合规牌照、明确估值和税务处理. 没有资质就不要把高风险业务包装成“副业机会”。

能赚钱的项目,不等于什么都能碰;长期做生意,先把牌照、规则和责任放在桌面上。

真正稳的游戏私域,应该是围绕合法内容和服务做沉淀:主播直播,团队负责运营,粉丝进入明确的服务流程,产品和合作方都能核验。

客户不是一串可以随意搬运的数字,粉丝也不是拿来反复骚扰的流量。

先看同行能不能做,再看自己能不能扛

有人问,判断一个项目值不值得做,是不是看同行已经赚到钱就行?

这只能算第一步。同行赚钱,说明市场可能存在;

但你还要问三个问题:

自己有没有相同的资源;

能不能承受前期成本;

愿不愿意长期做交付。

一个做直播带货的人讲到,直播间、设备、办公和人员,每个月都要支出。真正开始之前,他已经知道自己要承担什么,而不是只看到别人晒出来的收入。

过去拉新很热闹,现在更重要的是用户资产数字化: 一个用户一年能产生多少价值,服务成本是多少,复购和转化如何记录。 数据只有被长期跟踪,才有资格拿去谈合作或融资。

这和“先做小、再放大”是一个逻辑。不要一上来就投很大的钱,也不要为了证明自己敢干,先签下无法承受的成本。用较小的投入跑几轮,看客户是否愿意留下,再决定要不要加人、加设备、加渠道。

派对里的小伙伴说:“我就是不知道AI到底怎么挣钱。”

我接得很简单:AI本身只是工具,挣钱的地方在于它帮你降低了什么成本,提升了什么人效,或者让哪一种服务可以被稳定交付。

比如,一个有几万客户的私域团队,不可能每天手动看完每个人的朋友圈、聊天阶段和生日。 AI可以帮助整理客户行为、提醒回访、分配意向,但最后的沟通和成交仍然需要人判断。

这不是用AI替代所有人,而是让有限的人服务更多真正有价值的客户。客户越多,越不能只靠记忆;数据越多,越要把人留在关键判断上。

规则先于速度,稳定才是最便宜的增长

这一场有一个很清楚的变化:机会没有消失,只是门槛从“会不会操作”变成了“能不能稳定交付”。

软件要正规,数据要保护,AI要设权限,游戏项目要守边界,私域要有客户价值,合作要把责任讲清楚。速度当然重要,但没有规则的速度,往往只是更快撞上问题。

做项目的人也不需要一下子把未来十年想明白。两三个星期看一次变化,重新检查自己的工具、流程和客户;

能优化就优化,不能成立的就停下来。别把预测未来当成逃避今天交付的理由。

最后留下三个动作:

第一,把正在使用的AI工具列出来,标清楚它能读什么、能改什么、谁能授权。

第二,把自己的客户和粉丝分成“触达、服务、成交、复购”几个阶段,别只盯着人数。

第三,选一个小项目做一轮真实交付,用成本和结果判断能不能继续,不用想象替自己赚钱。

看得懂机会只是开始。能把机会做成产品,把产品做成服务,把服务做得安全、稳定、可复用,才是真正的能力。#派对会员 想继续跟上AI和商业变化,来派对里听真实案例,有问题直接 @我。

diff --git a/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/state.json b/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/state.json index a8b9416e..fd244a3f 100644 --- a/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/state.json +++ b/02_卡人(水)/水岸_项目管理/卡若创业派对/每日文章飞书分发/state.json @@ -1,6 +1,6 @@ { - "last_sent_field": 237, - "chapter_id": "10.96", - "title": "第237场|洛杉矶做数据中心的人,回到教育AI先算清成本", - "sent_at": "2026-07-23T12:01:35" + "last_sent_field": 238, + "chapter_id": "10.97", + "title": "第238场|AI开始替你做事,最先要学会的不是提速,是设边界", + "sent_at": "2026-07-25T06:23:25" } diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/feishu_wiki_download_images.py b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/feishu_wiki_download_images.py index 28a010ac..84218fee 100644 --- a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/feishu_wiki_download_images.py +++ b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/feishu_wiki_download_images.py @@ -27,6 +27,7 @@ from urllib.parse import urlparse from datetime import datetime import requests +from typing import Optional SCRIPT_DIR = Path(__file__).resolve().parent CONFIG = { @@ -77,7 +78,7 @@ def refresh_user_token(tokens): return None -def get_token(node_token: str) -> str | None: +def get_token(node_token: str) -> Optional[str]: """优先 FEISHU_TOKEN,否则用 .feishu_tokens.json 的 user access_token(必要时刷新)。""" env_token = os.environ.get("FEISHU_TOKEN", "").strip() if env_token: @@ -111,14 +112,14 @@ def get_token(node_token: str) -> str | None: return None -def wiki_url_to_node_token(url: str) -> str | None: +def wiki_url_to_node_token(url: str) -> Optional[str]: """从 Wiki 页面 URL 解析 node_token。""" # .../wiki/NAMUwdbuFiAy2GkmMZ3clXynnwc 或 .../wiki/xxx?... m = re.search(r"/wiki/([A-Za-z0-9_-]+)", url) return m.group(1) if m else None -def get_wiki_node(token: str, node_token: str) -> dict | None: +def get_wiki_node(token: str, node_token: str) -> Optional[dict]: """获取 wiki 节点信息,返回 node 字典(含 obj_token, obj_type)。""" r = requests.get( f"https://open.feishu.cn/open-apis/wiki/v2/spaces/get_node?token={node_token}", @@ -165,7 +166,7 @@ def get_wiki_child_nodes(token: str, space_id: str, parent_node_token: str) -> l return out -def collect_file_tokens_from_sheet(token: str, spreadsheet_token: str) -> list[str]: +def collect_file_tokens_from_sheet(token: str, spreadsheet_token: str) -> list: """从电子表格中收集浮动图片的 file_token / float_image_token。""" headers = {"Authorization": f"Bearer {token}"} file_tokens = [] @@ -247,7 +248,7 @@ def _extract_file_tokens(obj, out: list): _extract_file_tokens(x, out) -def collect_file_tokens_from_docx(token: str, document_id: str) -> list[str]: +def collect_file_tokens_from_docx(token: str, document_id: str) -> list: """从 docx 文档拉取全部 blocks,收集图片/文件的 file_token。""" headers = {"Authorization": f"Bearer {token}"} file_tokens = [] @@ -332,7 +333,7 @@ def download_file(url: str, save_path: Path, token: str) -> bool: return ret == 0 -def _collect_from_node(token: str, obj_token: str, obj_type: str) -> list[str]: +def _collect_from_node(token: str, obj_token: str, obj_type: str) -> list: """从单个节点(docx/sheet)收集 file_tokens。""" if obj_type == "sheet": return collect_file_tokens_from_sheet(token, obj_token) diff --git a/02_卡人(水)/水溪_整理归档/语音转写纠错/SKILL.md b/02_卡人(水)/水溪_整理归档/语音转写纠错/SKILL.md index 3000b1fd..11791314 100644 --- a/02_卡人(水)/水溪_整理归档/语音转写纠错/SKILL.md +++ b/02_卡人(水)/水溪_整理归档/语音转写纠错/SKILL.md @@ -5,10 +5,10 @@ description: 卡若记忆宫殿命名体系 · 间名「回廊洗字」:口述 group: 水 memory_palace_path: 卡若记忆宫殿/水殿/水溪厢/回廊洗字 memory_palace_slot: 口述与 ASR 杂声在此洗净,再入记忆与字幕流水线 -triggers: **回廊洗字、卡若记忆宫殿命名体系、记忆宫殿、记忆空间、语音转写纠错、语音输入、闽南话、闽南口音、听写、ASR、转写纠错、纠错库、误听、卡罗拉、卡罗伊**、口述、嘴瓢、**网页CLI、终端浏览器、命令行看网页、browsh** +triggers: **回廊洗字、卡若记忆宫殿命名体系、记忆宫殿、记忆空间、语音转写纠错、闽南话、闽南口音、听写、ASR、转写纠错、纠错库、误听、卡罗拉、卡罗伊**、口述、嘴瓢、**网页CLI、终端浏览器、命令行看网页、browsh** owner: 水溪 -version: "1.7.0" -updated: "2026-07-18" +version: "1.8.0" +updated: "2026-07-24" --- # 回廊洗字(W03b · 卡若记忆宫殿命名体系) @@ -34,7 +34,7 @@ updated: "2026-07-18" 1. **在推理与执行前**,将用户本轮自然语言视为可能含 ASR 噪声;在心中或用下述脚本对**整段或关键片段**做一次纠正后再定意图(不必改用户原文展示,**内部理解**以纠正后为准)。 2. **统一过滤**:不仅「卡路 / 卡罗 / 卡洛」类,**Skill / Codex / GitHub / Firecrawl / Handy / Webhook / MongoDB / ASR / Cursor / Claude / Soul / 私域 / 存客宝 / 流量池** 等表中近音一并处理;以 `卡若闽南口音_ASR纠错库.json` 为**唯一**词条源。 -3. **产品用词(存客宝/触客宝)**:口述或 ASR 写出 **「纯客宝」「纯课宝」** 时,一律理解为 **「存客宝」**;写出 **「流量词」** 时,一律理解为 **「流量池」**(旧称已废弃;技术字段 `poolKeywords` 不变)。 +3. **产品用词(存客宝/触客宝)**:口述或 ASR 写出 **「纯客宝」「纯课宝」** 时,一律理解为 **「存客宝」**;写出 **「流量词」** 时,一律理解为 **「流量池」**(旧称已废弃;技术字段 `poolKeywords` 不变)。 **该归一必须在每轮会话的理解、路由、工具参数整理与新增文档写入前完成;历史原文保持原样。** 4. 替换顺序:**按 key 长度降序**全文替换,避免短词截断长词(与 `soul_enhance.py`、`apply_karuo_voice_corrections.py` 一致)。 5. **上下文**:若替换后与句义冲突(食物热量、受伤、西游记原著等),以语义为准,见 JSON `notes` 与下文「终端网页 CLI」段。 6. 专有名词:Cursor、Claude、Soul、卡若AI、**流量池**(非「流量词」)等按表中写法对齐。 @@ -54,7 +54,7 @@ echo "卡罗拉更新 skill" | python3 ".../apply_karuo_voice_corrections.py" | 项 | 路径 / 值 | |:---|:---| -| **Skill 真源** | `01_卡资(金)/金仓_存储备份/Handy中文语音/SKILL.md`(**G25b**) | +| **Skill 真源** | `02_卡人(水)/水溪_整理归档/语音输入/SKILL.md`(**W03h**) | | 一键总装 | `…/Handy中文语音/脚本/install_all.sh` | | macOS 写配置 | `…/脚本/handy_apply_chinese_macos.sh` | | 粘贴 | `paste_method=ctrl_v`(剪贴板 Cmd+V) | diff --git a/02_卡人(水)/水溪_整理归档/语音转写纠错/参考资料/近期对话ASR纠错清单_20260724.md b/02_卡人(水)/水溪_整理归档/语音转写纠错/参考资料/近期对话ASR纠错清单_20260724.md new file mode 100644 index 00000000..a99f9560 --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音转写纠错/参考资料/近期对话ASR纠错清单_20260724.md @@ -0,0 +1,13 @@ +# 近期对话 ASR 纠错清单(2026-07-24) + +## 本轮加固 + +| 误听/转写 | 正写 | 固化位置 | 验收 | +|---|---|---|---| +| 纯客宝、纯课宝 | 存客宝 | 唯一 JSON 词库、W03b、Codex 入口 | 命令行回归通过 | + +## 执行约束 + +- 每轮用户输入在意图理解、Skill 路由、工具参数整理与持久文档写入前执行一次内部 ASR 滤真。 +- 历史聊天原文不重写;新增文档与执行产物统一使用“存客宝”。 +- 词条按长度降序替换;词库仍是唯一真源。 diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/SKILL.md b/02_卡人(水)/水溪_整理归档/语音输入/SKILL.md similarity index 79% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/SKILL.md rename to 02_卡人(水)/水溪_整理归档/语音输入/SKILL.md index aa483162..2bf92e81 100644 --- a/01_卡资(金)/金仓_存储备份/Handy中文语音/SKILL.md +++ b/02_卡人(水)/水溪_整理归档/语音输入/SKILL.md @@ -1,13 +1,13 @@ --- -name: Handy中文语音 -description: macOS/Windows Handy 中文语音+语音唤醒卡若AI Agent(⌘1/Ctrl+1)。触发词:Handy、卡若AI语音、语音唤醒、呼叫卡若AI、全局语音、⌘1、Ctrl+1、SenseVoice、按住说话。 -group: 金 -memory_palace_path: 卡若记忆宫殿/金殿/金仓厢/听写台 -memory_palace_slot: 本机按住说话,中文落字;纠错在 Cursor 回廊洗字 -triggers: Handy、全局语音、卡若AI语音、语音唤醒、呼叫卡若AI、喊卡若AI、Windows Handy、⌘1、Ctrl+1、语音输入、SenseVoice、按住说话、Handy中文、handy_apply、语音Agent -owner: 金仓 -version: "1.4" -updated: "2026-07-12" +name: 语音输入 +description: 卡水·水溪语音输入:Handy 中文转写、日常输入、配置基线、验收与排障。触发词:语音输入、Handy、卡若AI语音、Fn语音、SenseVoice。 +group: 水 +memory_palace_path: 卡若记忆宫殿/水殿/水溪厢/语音输入台 +memory_palace_slot: 本机语音转写、输入与配置基线;纠错交由回廊洗字 +triggers: 语音输入、Handy、卡若AI语音、Fn语音、Command+1、结合屏幕、免按住说话、SenseVoice、中文听写、语音唤醒、语音配置、Handy中文、语音Agent +owner: 水溪 +version: "1.5" +updated: "2026-07-26" related: - 01_卡资(金)/金仓_存储备份/Cursor持久对话/SKILL.md - 02_卡人(水)/水溪_整理归档/语音转写纠错/SKILL.md @@ -15,9 +15,9 @@ related: - 运营中枢/参考资料/卡若闽南口音_ASR纠错库.json --- -# Handy中文语音(G25b · 金仓) +# 语音输入(W03h · 水溪) -> **一句话**:**macOS**(Apple Silicon · ⌘1 · CoreML)与 **Windows**(x64/ARM64 · Ctrl+1 · DirectML)用 **Handy 0.8.3** + **SenseVoice** 按住说话→**先回廊洗字再自动输入**(如 纯客宝→存客宝);五笔输入法不变。 +> **一句话**:**macOS** 当前使用 **Fn 开始录音、再按 Fn 结束录音**,无需按住;Handy 0.8.3 + SenseVoice 输出中文并自动填入当前输入框。ASR 纠错由 W03b「回廊洗字」在对话理解层统一处理。 ## 适用场景 @@ -30,10 +30,17 @@ related: | **语音唤 Agent** | 说「**卡若AI** + 任务」或「**火炬/金仓** + 任务」→ pipeline 静默 Hub / 官网(见下) | | **语音 · 需求整理** | 先说 **小乖/乖乖/小宝**,再说「整理需求 …」→ 直投 Hub **语音·需求整理**(**不粘贴**输入框;见 `setup_handy_voice_exec_wake.sh`) | + +## 结合屏幕(Command+1) + +- **Fn**:普通输入,保持现有“按一次开始、再按一次结束”。 +- **Command+1**:截取一张当前主屏后开始/结束语音;转写完成会填入截图路径与洗字后的上下文指令。 +- 使用、权限、验收、回滚见:[结合屏幕本地部署与使用.md](references/结合屏幕本地部署与使用.md)。 + ## 一键安装(Agent / 终端) ```bash -bash "/Users/karuo/Documents/个人/卡若AI/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/install_all.sh" +bash "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水溪_整理归档/语音输入/脚本/install_all.sh" ``` **可分发安装包**(`4、火_工具开发/工具/Handy中文语音/`): @@ -45,7 +52,7 @@ bash "/Users/karuo/Documents/个人/卡若AI/01_卡资(金)/金仓_存储备 打包(Mac 上执行,产出双平台 zip):`bash …/Handy中文语音/脚本/build_package.sh` -## 语音唤醒 · 卡若AI Agent 插件(G25b+) +## 语音唤醒 · 卡若AI Agent 插件(W03h+) 口述 **「卡若AI …」** 或 **成员名 + 任务**(如「火炬 查 Agent 接口」)→ **不粘贴**,改为: @@ -116,8 +123,8 @@ pbpaste | python3 "/Users/karuo/Documents/个人/卡若AI/运营中枢/工作台 |:---|:---|:---| | **模型** | 已下载 → **SenseVoice** 卡片 | **活跃** | | **通用** | **SenseVoice 设置 → 语言** | **简体中文**(勿「自动」) | -| **通用** | **转录快捷键** | **⌘1**(点框后按 ⌘+1) | -| **通用** | **按住说话** | **开** | +| **通用** | **转录快捷键** | **Fn**(按一次开始、再按一次结束) | +| **通用** | **按住说话** | **关**(Fn 切换录音) | | **高级 → 应用** | **开机启动** | **关**(防双实例冲配置) | | **高级 → 输出** | **粘贴方式** | **剪贴板 (Cmd+V)**(勿外部脚本) | | **高级 → 应用** | **实验性功能** | **开** → **实验性 → ONNX 加速** | **CoreML** | @@ -132,9 +139,9 @@ pbpaste | python3 "/Users/karuo/Documents/个人/卡若AI/运营中枢/工作台 | `selected_language` | `zh-Hans` | | `paste_method` | `ctrl_v` | | `external_script_path` | `null` | -| `bindings.transcribe.current_binding` | `command_left+1` | -| `push_to_talk` | `true` | -| `autostart_enabled` | `false` | +| `bindings.transcribe.current_binding` | `fn` | +| `push_to_talk` | `false` | +| `autostart_enabled` | `true` | | `ort_accelerator` | `coreml` | 模型目录:`~/Library/Application Support/com.pais.handy/models/sense-voice-int8/` @@ -152,14 +159,14 @@ pbpaste | python3 "/Users/karuo/Documents/个人/卡若AI/运营中枢/工作台 ## 验收 1. `tail -30 ~/Library/Logs/com.pais.handy/handy.log` 含 `zh-Hans`、`sense-voice-int8` -2. 记事本按住 **⌘1** 说「卡若语音输入测试」→ 松开 → 粘贴为**中文** +2. 记事本按 **Fn** 开始说「卡若语音输入测试」→ 再按 **Fn** 结束 → 自动填入中文 3. 五笔输入法未被 Handy 修改 ## 排障速查 | 现象 | 处理 | |:---|:---| -| 英文乱码 / yu pizza yin | 语言被改回 **auto** → UI 改简体中文 + 重跑 `handy_apply_chinese_macos.sh` | +| 英文乱码 / yu pizza yin | 语言被改回 **auto** → UI 改简体中文;修改配置前先备份并确认 | | 转录为空 | 多为 **x86 Handy** → 重装 `handy_install_arm64.sh` | | 配置写了又变 | `killall -9 handy`(进程名小写 **handy**);关开机启动;勿开外部脚本 | | 两个 Handy | 活动监视器只留一个;`autostart_enabled=false` | @@ -171,7 +178,7 @@ pbpaste | python3 "/Users/karuo/Documents/个人/卡若AI/运营中枢/工作台 - **禁止** `brew install --cask handy`(易 x86) - macOS 仅允许使用已验证的 `handy_macos_asr_paste.sh`;Handy 0.8.3 ExternalScript 只传 `$1` 且忽略 stdout,插件必须自行输入 -## 2026-07-12 输入阶段纠错 +## 历史方案:2026-07-12 输入阶段纠错 Handy 已可在文字进入当前输入框前调用卡若AI统一词库: diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/evolution/gotchas.md b/02_卡人(水)/水溪_整理归档/语音输入/evolution/gotchas.md similarity index 100% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/evolution/gotchas.md rename to 02_卡人(水)/水溪_整理归档/语音输入/evolution/gotchas.md diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/references/Handy设置界面速查.md b/02_卡人(水)/水溪_整理归档/语音输入/references/Handy设置界面速查.md similarity index 100% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/references/Handy设置界面速查.md rename to 02_卡人(水)/水溪_整理归档/语音输入/references/Handy设置界面速查.md diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/references/Handy设置界面速查_Windows.md b/02_卡人(水)/水溪_整理归档/语音输入/references/Handy设置界面速查_Windows.md similarity index 100% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/references/Handy设置界面速查_Windows.md rename to 02_卡人(水)/水溪_整理归档/语音输入/references/Handy设置界面速查_Windows.md diff --git a/02_卡人(水)/水溪_整理归档/语音输入/references/Handy语音输入_KI_本机实测_20260726.md b/02_卡人(水)/水溪_整理归档/语音输入/references/Handy语音输入_KI_本机实测_20260726.md new file mode 100644 index 00000000..f1d3afce --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音输入/references/Handy语音输入_KI_本机实测_20260726.md @@ -0,0 +1,89 @@ +# Handy 语音输入 KI|本机实测基线(2026-07-26) + +> 归属:金仓 · G25b「Handy中文语音」 +> 目标:让卡若AI在电脑上稳定获得“说话 → 中文转写 → 回廊洗字 → 填入当前对话框”的能力。 +> 词库唯一真源:[卡若闽南口音_ASR纠错库.json](../../../../运营中枢/参考资料/卡若闽南口音_ASR纠错库.json) + +## 1. 当前可用结论 + +| 项目 | 本机实测结果 | +|---|---| +| 应用 | `/Applications/Handy.app`,v0.8.3,Apple Silicon 版本 | +| 输入设备 | MacBook Pro 麦克风,44.1kHz、单声道 | +| 识别模型 | `sense-voice-int8`,中文 `zh-Hans` | +| 操作 | 按 `Fn` 开始录音,再按 `Fn` 结束;转写后自动填进当前焦点输入框 | +| 发送策略 | `auto_submit=false`:只填入,不自动发送;无需持续按住热键 | +| 识别速度 | 最近实测 90–471ms(不含录音时长) | +| 文本纠正 | 词库回归 3/3 通过;当前输入保留原有 Handy 行为,对话层继续进行语义级回廊洗字 | +| 语音Hub | `http://127.0.0.1:13458/api/health` 返回 `ok=true` | + +## 2. 当前固定链路 + +```text +按 Fn 开始录音 → 再按 Fn 结束录音 + → Handy 0.8.3 / SenseVoice(zh-Hans) + → 剪贴板(copy_to_clipboard) + → Handy Cmd+V 填入当前输入框 + → Codex/卡若AI 对话层进行语义级回廊洗字兜底 +``` + +## 3. 本机配置基线 + +配置文件:`~/Library/Application Support/com.pais.handy/settings_store.json` 的 `settings`。 + +| 键 | 目标值 | 2026-07-26 回读 | +|---|---|---| +| `selected_language` | `zh-Hans` | 通过 | +| `selected_model` | `sense-voice-int8` | 通过 | +| `bindings.transcribe.current_binding` | `fn` | 通过 | +| `push_to_talk` | `false`(无需按住) | 通过 | +| `paste_method` | `ctrl_v` | 通过 | +| `clipboard_handling` | `copy_to_clipboard` | 通过 | +| `auto_submit` | `false` | 通过 | +| `autostart_enabled` | `true` | 通过 | +| `ort_accelerator` | `auto` | 通过 | + +> 当前按用户确认的原配置运行:`external_script_path` 保持原路径,剪贴板守护不启用。 + +## 4. 已发现问题 → 根因 → 固化处理 + +| 现象 | 根因 | 固化处理 | +|---|---|---| +| 口述“卡路AI / 卡罗AI / hand of”等误听 | ASR 固有近音 | 保留原始 `Fn` 输入方式;由卡若AI对话层回廊洗字理解与词库迭代处理 | +| 中文变英文或乱码 | `selected_language=auto` | 固定 `zh-Hans`,必要时在 Handy 设置页确认“简体中文” | +| 转写为空 | 误装 x86 版 Handy | 仅使用 Apple Silicon / aarch64 安装包 | +| 配置反复变化 | 双实例或手工脚本覆盖 | 保持用户确认的 `autostart_enabled=true`;修改前先备份并得到确认 | +| 纠错后还要手动粘贴 | 输入焦点变化 | 保持 Handy 原有 CtrlV 自动填入;不额外安装洗字守护 | +| CoreML 未实际启用 | v0.8.3 启动后把该项规范化为 `auto` | 当前不升级;若速度异常,再在隔离副本验证 v0.9.4 | + +完整历史见 [gotchas.md](../evolution/gotchas.md)。 + +## 5. 日常使用 + +1. 把光标放到 Codex、网页、备忘录等输入框。 +2. **按 `Fn` 开始说话,再按 `Fn` 结束。** +3. 检查洗后的文本后,再手动发送。 +4. 发现新误听:只向唯一 JSON 词库追加“误听→正写”,再跑回归测试。 + +## 6. 快速验收与诊断 + +```bash +# 仅查看当前配置(不修改) +python3 -c 'import json,pathlib; print(json.loads((pathlib.Path.home()/"Library/Application Support/com.pais.handy/settings_store.json").read_text())["settings"]["bindings"]["transcribe"]["current_binding"])' + +# 词库回归 +python3 "/Users/karuo/Documents/个人/卡若AI/运营中枢/工作台/脚本/test_karuo_asr_corrections.py" + +# 日志 +tail -60 "$HOME/Library/Logs/com.pais.handy/handy.log" +tail -60 "$HOME/Library/Logs/karuo/handy_clipboard_wash.log" +``` + +手工验收句:**“打开纯客宝后台,卡罗AI检查流量词。”** +预期:文本自动填入;卡若AI在对话理解层将“纯客宝、卡罗AI、流量词”识别为“存客宝、卡若AI、流量池”。 + +## 7. 当前配置保护 + +- 当前用户确认基线:`Fn + 无需按住 + 中文 SenseVoice + CtrlV 自动填入`。 +- 配置修改前先创建 `settings_store.json.bak.*` 备份,并先向用户说明具体变更。 +- 本轮新增的 `com.karuo.handy-asr-wash` 已卸载。 diff --git a/02_卡人(水)/水溪_整理归档/语音输入/references/heyclicky调研与语音输入迭代方案_20260726.md b/02_卡人(水)/水溪_整理归档/语音输入/references/heyclicky调研与语音输入迭代方案_20260726.md new file mode 100644 index 00000000..c06264ce --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音输入/references/heyclicky调研与语音输入迭代方案_20260726.md @@ -0,0 +1,102 @@ +# HeyClicky 调研与卡若AI语音输入迭代方案(2026-07-26) + +> 归属:卡水·水溪 · W03h「语音输入」 +> 结论:保留当前 Handy 输入法,不替换;在其上叠加“上下文问答”和“任务投递”两条可选能力。 + +## 1. 调研真源 + +- 开源基础:[farzaa/clicky(MIT)](https://github.com/farzaa/clicky) +- 产品现状:[heyclicky 官网](https://www.heyclicky.com/) +- 数据边界:[heyclicky 隐私说明](https://www.heyclicky.com/privacy-policy) + +开源 Clicky 的基础结构是:菜单栏应用、控制面板、透明屏幕叠层;热键触发后进行实时转写,再把“转写文本 + 当前截图”发给模型,结果以文字、TTS 和屏幕指针反馈。官方仓库说明其开源代码已冻结,后续产品功能在 HeyClicky 私有版本持续迭代。 + +## 2. HeyClicky 的运行模式 + +```text +热键触发 + ├─ 采集当前语音 + ├─ 同一时刻抓取当前屏幕(仅触发时) + ├─ 意图分流:Talk / Agent + ├─ Talk:模型流式回复 → TTS + 指针标注 + └─ Agent:后台执行任务 → 回执与进度 +``` + +其产品核心不是“更快转写”,而是三个体验层: + +1. **听写**:将语音写入当前文本框。 +2. **屏幕上下文问答**:用户正在看什么,助手就围绕什么解释、指路或生成内容。 +3. **任务代理**:用户明确说出 Agent 意图后,才投递后台任务。 + +## 3. 卡若AI当前链路 + +```text +Fn 开始录音 → Fn 结束录音 + → Handy / SenseVoice 中文转写 + → CtrlV 自动填入当前输入框 + → 卡若AI 对话层 W03b 回廊洗字 + → Skill 路由 / Hub / Codex 执行 +``` + +当前优势:本机中文转写快、使用方式固定、无需按住、输入行为稳定。 +当前缺口:语音一律当作文本输入,缺少“我要问当前屏幕”与“我要派任务”的明确分流;没有统一的回执卡、上下文采集开关和效果指标。 + +## 4. 建议的目标运行模式 + +```text +Fn 普通输入(保留原样) + └─ 语音 → Handy → 当前输入框 → W03b 洗字 + +语音前缀「卡若AI,结合屏幕:…」(新增,可选) + └─ 转写 → 单次屏幕快照 → 本机脱敏 → W03b 洗字 + → 上下文问答 → 文本/可选朗读答复 + +语音前缀「卡若AI,执行:…」(新增,可选) + └─ 转写 → W03b 洗字 → Skill 路由 + → Hub 创建任务 → 进度回执 → 完成结果 +``` + +### 不变项 + +- **Fn 切换录音、无需按住**不变。 +- 继续使用 Handy + SenseVoice;不强制安装 Clicky,也不替换输入法。 +- 不开启常驻截屏;只在“结合屏幕”明确前缀下采一张当前屏幕。 +- 现有 W03b 仍是唯一 ASR 纠错源,W03h 仍是唯一语音输入入口。 + +## 5. 分期迭代 + +| 优先级 | 内容 | 验收标准 | 配置影响 | +|---|---|---|---| +| P0 | 语音三态识别:普通输入 / 结合屏幕 / 执行任务 | 20 条固定口令分流正确率≥95%;普通 Fn 行为不变 | 无,先做离线识别与日志 | +| P1 | 单次屏幕上下文桥接 | 仅明确口令时截图;截图不落盘;问答回执含“已使用当前屏幕” | 新增明确开关,默认关闭 | +| P1 | 统一语音回执卡 | 输入、纠错、路由、任务状态都能查看 | 无 | +| P2 | 可选 TTS 与屏幕标注 | 可随时停止;只在结合屏幕模式启用 | 新增默认关闭开关 | +| P2 | 语音质量看板 | 统计转写耗时、纠错命中率、分流正确率、失败原因 | 本机只存脱敏指标 | + +## 6. 第一轮建议:只做 P0 + +先不动 Handy 配置,先加一个**本地语音意图分流器**: + +- 没有前缀:继续原样填入输入框。 +- `卡若AI,结合屏幕`:标记为 `screen_question`,等待用户确认屏幕权限开关。 +- `卡若AI,执行` 或 `水溪/火炬/金仓` + 任务:标记为 `agent_task`,交给既有 Hub 和 Skill 路由。 +- 每次生成结构化回执:`原转写 / 洗字结果 / 意图 / 路由 / 耗时 / 结果`。 + +这一步复用已有 `karuo_voice_pipeline.py`、W03b 词库和 Hub `13458`,不引入新的桌面应用。 + +## 7. 与 HeyClicky 的取舍 + +| HeyClicky 做法 | 卡若AI采用方式 | +|---|---| +| 热键同时带屏幕截图 | 仅“结合屏幕”前缀下单次截图,默认关闭 | +| Talk 与 Agent 分开计量 | 普通输入、结合屏幕、执行任务分三条逻辑链 | +| TTS + 指针叠层 | 放到 P2,先验证真实使用频次 | +| 云端代理处理音频与截图 | 先本机转写、词库与路由;截图仅按需传递 | +| 通用 Mac 助手 | 保持卡若AI五行 Skill 与业务上下文优势 | + +## 8. 验收样例 + +1. `Fn` 输入“打开纯客宝后台” → 正常填入;对话层理解为“打开存客宝后台”。 +2. `卡若AI,结合屏幕:这个报错是什么` → 仅一次截图、返回问题解释,不创建任务。 +3. `卡若AI,执行:整理今天的语音问题` → 路由 W03h/W03b 后创建任务,返回任务编号和进度。 +4. 不带前缀的任意语音 → 不截图、不启动 Agent、不改变当前输入行为。 diff --git a/02_卡人(水)/水溪_整理归档/语音输入/references/结合屏幕本地部署与使用.md b/02_卡人(水)/水溪_整理归档/语音输入/references/结合屏幕本地部署与使用.md new file mode 100644 index 00000000..9fc6ac09 --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音输入/references/结合屏幕本地部署与使用.md @@ -0,0 +1,54 @@ +# 结合屏幕|本地部署与使用(W03h) + +## 已部署运行模式 + +- 应用图标:`资源/卡若AI·屏语.png`,部署时自动生成并装入 macOS 原生 `.icns`。 + +```text +Fn:普通语音输入(原行为不变) +Command+1:结合屏幕模式 + 第一次 Command+1(或菜单“开始结合屏幕”)→ 显示“正在截图 / 正在听你说话”悬浮状态 + 第二次 Command+1(或菜单“结束并提交”)→ 显示“正在转写并提交” + 转写钩子 → 回廊洗字 → 生成「截图路径 + 指令」上下文包 → 自动提交给当前 AI → 直接获得回答 +``` + +## 语音区分 + +| 方式 | 含义 | 行为 | +|---|---|---| +| `Fn` 后直接说内容 | 普通输入 | 保持原有 Handy 自动填入 | +| `Command+1` 后说“结合屏幕,……” | 结合屏幕 | 将单次截图与洗字指令一起发送到当前 AI 输入框 | +| `Command+1` 后说“结合屏幕,执行……” | 结合屏幕任务 | 上下文包会要求当前 AI 先看截图,再执行指令 | + +> Command+1 已经表示结合屏幕;说“结合屏幕”是为了让转写结果和后续 AI 语义更清晰。 + +## 首次启用 + +在 **系统设置 → 隐私与安全性 → 录屏与系统录音** 中开启 `卡若AI·屏语`。 + +`Command+1` 已改用 macOS 系统级热键注册,不需要“输入监控”权限。应用提供常驻控制台,也可以直接点击“开始结合屏幕 / 结束并提交”。 + +## 验收 + +1. 将光标放到 Codex 输入框。 +2. 按 `Command+1`,应出现“结合屏幕”提示。 +3. 说:`结合屏幕,这个页面有什么问题。` +4. 再按 `Command+1`。 +5. 输入框应出现 `【卡若AI·结合屏幕】`、截图图片、截图路径和洗字后的语音指令。 + +截图和本次上下文包保存在: + +`/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水溪_整理归档/语音输入/截图归档/`(仅保留最新100张截图;截图超出时只清理最早图片,上下文 `.md` 永久保留) + +## 维护与回滚 + +- 可见应用:`/Applications/卡若AI·屏语.app` +- 热键守护:`com.karuo.voice-screen-hotkey` +- Handy 钩子:`~/Library/Application Support/com.pais.handy/hooks/transcription` +- 重新部署: + +```bash +bash "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水溪_整理归档/语音输入/脚本/部署结合屏幕.sh" +``` + +- 停用:卸载 `com.karuo.voice-screen-hotkey` 并把 Handy 钩子改回 `01_卡资(金)/金仓_存储备份/脚本/handy_transcription_hook.sh`。 diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/references/语音唤醒卡若AI.md b/02_卡人(水)/水溪_整理归档/语音输入/references/语音唤醒卡若AI.md similarity index 100% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/references/语音唤醒卡若AI.md rename to 02_卡人(水)/水溪_整理归档/语音输入/references/语音唤醒卡若AI.md diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/references/语音唤醒需求整理.md b/02_卡人(水)/水溪_整理归档/语音输入/references/语音唤醒需求整理.md similarity index 94% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/references/语音唤醒需求整理.md rename to 02_卡人(水)/水溪_整理归档/语音输入/references/语音唤醒需求整理.md index 924f8237..aab4d8a4 100644 --- a/01_卡资(金)/金仓_存储备份/Handy中文语音/references/语音唤醒需求整理.md +++ b/02_卡人(水)/水溪_整理归档/语音输入/references/语音唤醒需求整理.md @@ -25,7 +25,7 @@ ## 接线(推荐 · macOS) ```bash -bash "/Users/karuo/Documents/个人/卡若AI/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/setup_handy_voice_exec_wake.sh" +bash "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水溪_整理归档/语音输入/脚本/setup_handy_voice_exec_wake.sh" ``` 使用 `hooks/transcription` + **stdout 空**,不启用 `external_script`(避免 0.8.3 回滚英文)。 diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/references/语音桌面对接卡若AI网站.md b/02_卡人(水)/水溪_整理归档/语音输入/references/语音桌面对接卡若AI网站.md similarity index 93% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/references/语音桌面对接卡若AI网站.md rename to 02_卡人(水)/水溪_整理归档/语音输入/references/语音桌面对接卡若AI网站.md index 5b3cde1d..d39ab20f 100644 --- a/01_卡资(金)/金仓_存储备份/Handy中文语音/references/语音桌面对接卡若AI网站.md +++ b/02_卡人(水)/水溪_整理归档/语音输入/references/语音桌面对接卡若AI网站.md @@ -47,7 +47,7 @@ ## 接线(不改 Handy 设置) ```bash -bash "/Users/karuo/Documents/个人/卡若AI/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/setup_handy_voice_exec_wake.sh" +bash "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水溪_整理归档/语音输入/脚本/setup_handy_voice_exec_wake.sh" ``` **禁止**为接线而运行 `handy_apply_chinese_macos.sh`(会覆盖你的快捷键/语言等设置)。 diff --git a/02_卡人(水)/水溪_整理归档/语音输入/开发文档/功能迭代记录.md b/02_卡人(水)/水溪_整理归档/语音输入/开发文档/功能迭代记录.md new file mode 100644 index 00000000..a2c0aff3 --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音输入/开发文档/功能迭代记录.md @@ -0,0 +1,219 @@ +# 功能迭代记录 + +## 2026-07-12|v1.4.3 修复自动输入 + +- 用户真实验证发现:纠错结果进剪贴板,但仍需手动粘贴。 +- 直接核对 Handy v0.8.3 源码 `src-tauri/src/clipboard.rs`:ExternalScript 将文本作为 `$1`,忽略 stdout,并要求脚本自行完成输入。 +- 插件恢复 `$1` 读取,纠错后写剪贴板,等待 350ms 恢复焦点,再自动发送 `⌘V`。 +- `clipboard_handling` 改为 `dont_modify`,避免 Handy 随后用原始转写覆盖纠错后的剪贴板。 +- 新增 `~/Library/Logs/com.pais.handy/karuo_asr_plugin.log`,记录调用、纠错和粘贴失败,不记录正文。 +- 自动输入优先使用本机 `cliclick`,不可用时才回退 System Events;macOS 必须授予对应输入程序辅助功能权限。 + +## 2026-07-12|v1.4.2 自动输入当前对话框 + +- 固化 `clipboard_handling=copy_to_clipboard` 与 `auto_submit=false`。 +- Handy 收到插件 stdout 后自动写入当前焦点对话框,不需要用户手动粘贴。 +- 默认只填入、不自动发送,避免语音误识别直接提交。 + +## 2026-07-12|v1.4.1 修复Handy插件传参协议 + +- 用户真实语音验证发现:Handy日志显示插件被调用,但输入框仍是原文。 +- 根因:旧脚本从参数/剪贴板读取,并自行 ⌘V;Handy 0.8.3 实际从 stdin 传入转写、读取 stdout 作为最终文本。 +- 修复:插件改为纯过滤器 `stdin → 回廊洗字 → stdout`,不再操作剪贴板或模拟按键。 +- 验收标准:管道输入“纯客宝、卡罗亚”时,stdout 必须返回“存客宝、卡若AI”。 + +## 2026-07-12|v1.4 Handy输入阶段ASR纠错 + +### 目标 + +Handy 语音转写后、文字进入当前输入框前,自动调用卡若AI统一ASR纠错库。 + +### 链路 + +```text +Handy录音 + -> SenseVoice zh-Hans转写 + -> handy_macos_asr_paste.sh + -> apply_karuo_voice_corrections.py + -> 卡若闽南口音_ASR纠错库.json + -> 剪贴板 + -> 当前输入框 +``` + +### 修改 + +- Handy `paste_method` 改为 `external_script`。 +- `external_script_path` 指向已验证的 `handy_macos_asr_paste.sh`。 +- 新增 `enable_karuo_asr_correction_macos.sh`,自动备份配置、接线并重启 Handy。 +- 钩子新增 `KARUO_ASR_TEST_ONLY=1` 无粘贴测试模式。 +- 补充 `卡罗AI/卡洛AI/卡路AI` 无空格纠错变体。 + +### 验证 + +- Handy 0.8.3 正常启动,SenseVoice 与 `zh-Hans` 保持不变。 +- Handy 日志确认加载 `ExternalScript` 和目标脚本。 +- 测试输入“打开纯客宝后台,卡罗AI帮我检查”输出“打开存客宝后台,卡若AI帮我检查”。 +- Cursor/Codex 对话层仍保留回廊洗字二次兜底。 + +### 回滚 + +恢复 `settings_store.json.bak.asr.*` 备份并重启 Handy,或把 `paste_method` 改回 `ctrl_v`、`external_script_path` 改回 `null`。 + +## 2026-07-26|v1.4.4 本机语音链路复核与 KI 沉淀 + +- **实测结论**:Handy v0.8.3 + 内置麦克风 + SenseVoice 中文可正常识别;日志显示最近转写耗时 90–471ms,自动粘贴成功。 +- **发现并修复**:实际运行配置遗留为 `Fn`、`push_to_talk=false`、`autostart_enabled=true`、未启用回廊洗字守护,导致“卡路AI / 卡罗AI”等误听原样落入对话。 +- **已统一基线**:`⌘1`、`zh-Hans`、`sense-voice-int8`、`push_to_talk=true`、`ctrl_v`、`copy_to_clipboard`、`auto_submit=false`、`autostart_enabled=false`;已安装 `com.karuo.handy-asr-wash`。 +- **验证**:`test_karuo_asr_corrections.py` 3/3 通过;纠错示例“纯客宝、卡罗AI、流量词”→“存客宝、卡若AI、流量池”。 +- **已知约束**:Handy 0.8.3 启动后会把 `ort_accelerator` 归一成 `auto`;当前识别正常,未升级到 0.9.4,待隔离兼容性验证后再决定。 +- **知识沉淀**:[Handy语音输入_KI_本机实测_20260726.md](../references/Handy语音输入_KI_本机实测_20260726.md)。 + +## 2026-07-26|v1.4.5 按用户确认恢复原始 Handy 配置 + +- 已恢复并由启动日志确认:热键 `Fn`、`push_to_talk=false`(无需按住)、`autostart_enabled=true`、`CtrlV` 自动填入。 +- 已卸载本轮新增 `com.karuo.handy-asr-wash`,不再在输入前额外修改剪贴板。 +- 后续以用户确认的原配置为唯一基线;修改前先备份并明确说明改动项。 + +## 2026-07-26|v1.5 能力包迁移至卡水·语音输入 + +- 按用户确认,原 `金仓/Handy中文语音` **整体迁移并重命名**为 `水溪/语音输入`,未创建并行重复 Skill。 +- Skill 元数据统一为:`name=语音输入`、`group=水`、`owner=水溪`、`编号=W03h`。 +- 路由职责已拆分:W03h 管日常语音输入、配置、验收与排障;W03b「回廊洗字」只管 ASR 词库和语义纠错。 +- 当前用户确认的电脑基线:`Fn` 开始录音、再按 `Fn` 结束,`push_to_talk=false`,不安装剪贴板洗字守护。 + +## 2026-07-26|HeyClicky 调研与 W03h 优化方案 + +- 调研 [farzaa/clicky](https://github.com/farzaa/clicky) 与 [heyclicky 官网](https://www.heyclicky.com/)。可借鉴核心是“听写 / 屏幕上下文问答 / Agent 任务”三条独立链路。 +- 卡若AI采用增量方案:保留当前 `Fn` 切换录音、Handy、SenseVoice 和 W03b 洗字;P0 先建立本地语音意图分流与结构化回执,不改 Handy 配置。 +- 完整方案:[heyclicky调研与语音输入迭代方案_20260726.md](../references/heyclicky调研与语音输入迭代方案_20260726.md)。 + +## 2026-07-26|v1.6 Home+1「结合屏幕」本地模式 + +- 新增本地 `Home+1` 热键守护:首次按键单次截取主屏并启动 Handy 后处理录音;再次按键结束。 +- 新增转写钩子:将截图绝对路径、W03b 洗字结果和语音指令组装为上下文包,填入当前 AI 输入框。 +- `Fn`、`push_to_talk=false` 未改动;结合屏幕只在 `Home+1` 下工作,无常驻截屏。 +- 运行服务 `com.karuo.voice-screen-hotkey` 已加载;首次使用需授予 macOS 输入监控权限。 +- 使用说明:[结合屏幕本地部署与使用.md](../references/结合屏幕本地部署与使用.md)。 + +## 2026-07-26|v1.6.1 结合屏幕热键改为 Command+1 + +- 按用户指定,热键从 Home+1 切换为 `Command+1`;本地 LaunchAgent 已重编译并重启。 +- `Fn` 普通语音输入与“无需按住说话”保持不变。 +- 已通过命令直达 macOS「输入监控」授权页;该系统级权限由当前登录用户最后确认一次。 + + +## 2026-07-26|v1.6.2 可见应用与输入监控修复 + +- 根因:原热键守护是无界面二进制,macOS「输入监控」列表不会显示可选择项目。 +- 已改为可见的 `/Applications/卡若AI结合屏幕.app`(bundle id `com.karuo.voice-screen`),菜单栏显示“屏幕语音”,包含“打开输入监控设置”和“测试截图”。 +- LaunchAgent 已改为启动该应用包内可执行文件;部署脚本同步改为应用化安装与注册。 +- 保持不变:`Fn` 普通语音、`push_to_talk=false`、Handy 原始配置。 + + +## 2026-07-26|v1.6.3 卡若AI·屏语命名与本地截图归档 + +- 应用重命名为 **卡若AI·屏语**:语义为“屏幕 + 语音”,与卡若AI产品命名统一,菜单栏也显示该名称。 +- 截图归档改至 `02_卡人(水)/水溪_整理归档/语音输入/截图归档/`,即卡若AI主目录内。 +- 新增上限:仅保留最新 **100 张** `screen-*.png`;生成第101张时自动删除最早截图及同名 `.md` 上下文文件。 +- 归档文件被 `.gitignore` 排除,仅本机保留,不同步到版本库。 + + +## 2026-07-26|v1.6.4 屏语截图清理与上下文留存分离 + +- 按用户确认,超出100张时**只删除最早 `screen-*.png` 截图**。 +- 同名 `.md` 语音上下文包不再随图片清理,作为本地历史记录持续保留。 + + +## 2026-07-26|v1.6.5 卡若AI·屏语原生应用图标 + +- 新增“水感屏幕 + 声波”应用图标源文件:`资源/卡若AI·屏语.png`。 +- 部署脚本自动生成 macOS `.icns` 并写入 App Bundle,Finder、Dock 与输入监控均使用同一图标。 + + +## 2026-07-26|v1.6.6 屏语可视状态与直接输出 + +- 新增菜单入口、浮动状态窗与完整状态:正在截图 → 正在说话 → 正在转写并提交 → 当前 AI 正在回答。 +- `Command+1` 与菜单均可启动/结束;若截屏权限缺失,应用自动打开“屏幕录制”设置。 +- 屏语专用转写通过 Handy ExternalScript 自动提交给当前 AI;普通 `Fn` 仍按一次开始、再按一次结束,仍然只填入不自动发送。 + + +## 2026-07-26|v1.6.7 屏语控制台与系统级快捷键 + +- 根因修复:原 `Command+1` 全局监听依赖输入监控且无授权记录,已改为 Carbon `RegisterEventHotKey` 系统级注册,不再依赖输入监控。 +- 新增常驻屏语控制台:开始结合屏幕、结束并提交、开启录屏权限三个直接按钮。 +- 状态窗改为非激活浮窗,不抢走当前 AI 输入框焦点,避免转写结果粘贴到错误位置。 +- 首次唯一权限为“录屏与系统录音”;权限关闭时控制台明确提示并直达设置页。 + + +## 2026-07-26|v1.6.8 移除录屏权限误判 + +- 用户截图确认“卡若AI·屏语”录屏开关已开启;旧版 `CGPreflightScreenCaptureAccess()` 在当前 LaunchAgent 启动上下文返回假阴性。 +- 已移除启动前权限预检,改为直接执行真实截图,以截图文件和返回码作为唯一成功标准。 +- 控制台不再错误提示重复开启权限。 + + +## 2026-07-26|v1.6.9 原生进程截图 + +- 实测确认录屏开关已开启,但 `/usr/sbin/screencapture` 子进程未继承应用 TCC 身份。 +- 截图改由 `卡若AI·屏语` Swift 主进程通过 CoreGraphics 直接生成,再使用 `--arm-existing` 登记并启动 Handy。 +- 权限归属、界面状态与截图执行统一到同一 App Bundle。 + + +## 2026-07-26|v1.6.10 LaunchServices应用身份启动 + +- 根因:LaunchAgent 直接执行 App 包内二进制,TCC录屏权限虽然界面开启,但运行进程未按 Bundle 身份归属。 +- LaunchAgent 改为 `/usr/bin/open -g /Applications/卡若AI·屏语.app`,由 LaunchServices 以完整 Bundle ID 启动。 + + +## 2026-07-26|v1.6.11 本地截图助手兜底 + +- 系统设置显示录屏已开启,但ScreenCaptureKit返回TCC拒绝(设置界面与TCC内部状态冲突)。 +- 新增 `屏语截图助手.py`,经本机已授权执行链路实测截图成功;主应用不再显示重复授权提示。 +- 屏语按钮统一通过助手生成截图,再进入Handy录音与自动提交。 + + +## 2026-07-26|v1.6.12 运行时与用户归档分离 + +- 修复App子进程读取Documents脚本时阻塞:运行脚本和IPC迁至 `~/Library/Application Support/karuo-ai/pingyu/`。 +- 截图与上下文仍保存到卡若AI `语音输入/截图归档/`,用户目录结构不变。 + + +## 2026-07-26|v1.6.13 屏语只粘贴不自动发送 + +- 按用户确认,屏语结束后仅把“截图路径 + 洗字语音指令”粘贴到当前输入框。 +- 移除 `--submit` 调用,不再模拟回车;发送动作始终由用户确认。 +- 控制台文案统一改为“结束并粘贴 / 已粘贴到输入框”。 + + +## 2026-07-26|v1.6.14 Handy式无弹窗交互 + +- 移除屏语启动、截图、说话、处理、粘贴过程中的浮动控制窗。 +- 状态仅显示在菜单栏:`屏语·截图中 → 屏语·说话中 → 屏语·处理中 → 屏语·已粘贴`。 +- 操作保持 `Command+1` 开始、再次 `Command+1` 结束并只粘贴,不自动回车。 + + +## 2026-07-26|v1.6.15 真实图片附件粘贴 + +- 屏语结束后不再只粘贴图片路径;新增 `屏语图片粘贴.swift`,将 PNG 图片和上下文文字一起写入剪贴板。 +- 当前 AI 输入框会显示真实截图附件;仍然只粘贴、不自动回车。 + +## v1.6.16 真实图片附件+语音文字同次粘贴(2026-07-26) +- **目标**:Command+1 流程不再只粘贴截图路径,而是将真实 PNG 图片与洗字后的语音文字一次写入当前 AI 输入框;保持不自动回车。 +- **实现**:截图助手把归档 PNG 同步到 `$HOME/Library/Application Support/karuo-ai/pingyu/latest-screen.png`;`屏语图片粘贴.swift` 通过 NSPasteboard 同时登记 `PNGf` 与 `string`,再仅模拟 Command+V。 +- **验证**:`osascript -e 'clipboard info'` 已显示 `«class PNGf»` 与 `«class utf8»`;`结合屏幕.py --consume --paste` 返回 0,pending 状态已清理。 +- **架构**:Command+1 → 截图助手 → runtime 图片副本 → Handy 转写 → 图片+文字剪贴板 → 当前输入框;上下文 `.md` 与归档图片继续保留。 + +## v1.6.17 双粘贴链路分流(2026-07-26) +- **Fn/Handy**:恢复 `paste_method=ctrl_v`、`external_script_path=null`,保持原生语音文字粘贴。 +- **Command+1/屏语**:屏语应用记录录音前剪贴板版本,结束时等待 Handy 原生转写完成,再单独调用 `结合屏幕.py --consume --paste`,将 PNG+文字一次粘贴,不改变 Fn 链路。 +- **验证**:应用已重新编译签名并启动;配置读取为 `ctrl_v / null`;两种模式互不调用同一外部钩子。 + +## v1.6.18 屏语分步附件粘贴(2026-07-26) +- **问题**:部分 AI 输入框对同一剪贴板中的 PNG+文字只取文字,用户看不到图片。 +- **修复**:屏语助手改为同一任务内先粘贴 PNG 图片,再粘贴语音文字;Fn/Handy 仍只走原生文字 `ctrl_v`。 +- **验证**:运行目录助手编译成功;`clipboard info` 在图片阶段显示 `PNGf`,无自动回车。 + +## v1.6.19 输入焦点恢复(2026-07-26) +- **问题**:Command+1 结束录音后,系统焦点可能仍停留在 Handy/屏语状态栏,导致图片粘贴位置不可见。 +- **修复**:开始屏语时记录当前前台输入应用;收到 Handy 转写后先恢复该应用焦点,再执行“图片→文字”两段粘贴。 +- **验证**:最近日志已持续记录截图生成与转写消费;新版本应用已重新编译、签名并启动。 diff --git a/02_卡人(水)/水溪_整理归档/语音输入/截图归档/.gitignore b/02_卡人(水)/水溪_整理归档/语音输入/截图归档/.gitignore new file mode 100644 index 00000000..0b6d837c --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音输入/截图归档/.gitignore @@ -0,0 +1,3 @@ +# 本机屏语截图与上下文不进入版本库 +* +!.gitignore diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/build_package.sh b/02_卡人(水)/水溪_整理归档/语音输入/脚本/build_package.sh similarity index 95% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/build_package.sh rename to 02_卡人(水)/水溪_整理归档/语音输入/脚本/build_package.sh index 18422926..c8bd4f27 100755 --- a/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/build_package.sh +++ b/02_卡人(水)/水溪_整理归档/语音输入/脚本/build_package.sh @@ -48,7 +48,7 @@ chmod +x "${PKG_DIR}/脚本/install_all.sh" cat > "${PKG_DIR}/卡若AI技能路径.txt" << EOF 本包对应卡若AI Skill(安装后 Agent 自动识别): -/Users/karuo/Documents/个人/卡若AI/01_卡资(金)/金仓_存储备份/Handy中文语音/SKILL.md +/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水溪_整理归档/语音输入/SKILL.md 编号:G25b · 金仓 · Handy中文语音 关联:回廊洗字 W03b(Cursor 内 ASR 纠错) @@ -99,7 +99,7 @@ cat > "${TOOL_ROOT}/README.md" << 'TOOLREADME' | **Windows** | `Handy中文语音-安装包-Windows-v1.1/` → `双击安装Handy中文语音.bat` | `Handy中文语音_Windows_安装包_YYYYMMDD.zip` | | **语音唤 Agent** | 包内 `语音唤醒卡若AI.md` + `setup_voice_agent_plugin.*` | 说「卡若AI …」或「火炬 …」 | -卡若AI Skill:`卡若AI/01_卡资(金)/金仓_存储备份/Handy中文语音/SKILL.md`(G25b) +卡若AI Skill:`卡若AI/02_卡人(水)/水溪_整理归档/语音输入/SKILL.md`(G25b) 归类:`4、火_工具开发/工具/`(黑曜石10_归类总册 · tool_release) TOOLREADME diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/build_package_windows.sh b/02_卡人(水)/水溪_整理归档/语音输入/脚本/build_package_windows.sh similarity index 97% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/build_package_windows.sh rename to 02_卡人(水)/水溪_整理归档/语音输入/脚本/build_package_windows.sh index d6ab3cb2..d1ddb932 100755 --- a/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/build_package_windows.sh +++ b/02_卡人(水)/水溪_整理归档/语音输入/脚本/build_package_windows.sh @@ -53,7 +53,7 @@ PS1 cat > "${PKG_DIR}/卡若AI技能路径.txt" << EOF 卡若AI Skill(G25b · Handy中文语音): -/Users/karuo/Documents/个人/卡若AI/01_卡资(金)/金仓_存储备份/Handy中文语音/SKILL.md +/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水溪_整理归档/语音输入/SKILL.md Windows 安装包目录(五行 · 火 · 工具): ${TOOL_ROOT}/${PKG_NAME}/ diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/enable_karuo_asr_correction_macos.sh b/02_卡人(水)/水溪_整理归档/语音输入/脚本/enable_karuo_asr_correction_macos.sh similarity index 100% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/enable_karuo_asr_correction_macos.sh rename to 02_卡人(水)/水溪_整理归档/语音输入/脚本/enable_karuo_asr_correction_macos.sh diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/handy_apply_chinese_windows.ps1 b/02_卡人(水)/水溪_整理归档/语音输入/脚本/handy_apply_chinese_windows.ps1 similarity index 100% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/handy_apply_chinese_windows.ps1 rename to 02_卡人(水)/水溪_整理归档/语音输入/脚本/handy_apply_chinese_windows.ps1 diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/handy_download_sensevoice.ps1 b/02_卡人(水)/水溪_整理归档/语音输入/脚本/handy_download_sensevoice.ps1 similarity index 100% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/handy_download_sensevoice.ps1 rename to 02_卡人(水)/水溪_整理归档/语音输入/脚本/handy_download_sensevoice.ps1 diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/handy_download_sensevoice.sh b/02_卡人(水)/水溪_整理归档/语音输入/脚本/handy_download_sensevoice.sh similarity index 100% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/handy_download_sensevoice.sh rename to 02_卡人(水)/水溪_整理归档/语音输入/脚本/handy_download_sensevoice.sh diff --git a/02_卡人(水)/水溪_整理归档/语音输入/脚本/handy_结合屏幕钩子.sh b/02_卡人(水)/水溪_整理归档/语音输入/脚本/handy_结合屏幕钩子.sh new file mode 100755 index 00000000..da5efc03 --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音输入/脚本/handy_结合屏幕钩子.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# Handy 0.8.3 ExternalScript:屏语已武装则提交屏幕任务;否则完全沿用原 Fn 输入脚本。 +set -euo pipefail +ROOT="/Users/karuo/Documents/个人/卡若AI" +SCREEN="$HOME/Library/Application Support/karuo-ai/pingyu/结合屏幕.py" +LEGACY="$ROOT/01_卡资(金)/金仓_存储备份/脚本/handy_macos_asr_paste.sh" +RAW="${1:-}" +if [[ -z "${RAW//[[:space:]]/}" ]]; then RAW="$(cat)"; fi +if [[ -n "${RAW//[[:space:]]/}" ]] && python3 "$SCREEN" --consume --paste "$RAW" >/dev/null 2>&1; then + exit 0 +fi +exec "$LEGACY" "$RAW" diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/install_all.sh b/02_卡人(水)/水溪_整理归档/语音输入/脚本/install_all.sh similarity index 100% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/install_all.sh rename to 02_卡人(水)/水溪_整理归档/语音输入/脚本/install_all.sh diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/setup_handy_voice_exec_wake.sh b/02_卡人(水)/水溪_整理归档/语音输入/脚本/setup_handy_voice_exec_wake.sh similarity index 100% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/setup_handy_voice_exec_wake.sh rename to 02_卡人(水)/水溪_整理归档/语音输入/脚本/setup_handy_voice_exec_wake.sh diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/setup_voice_agent_plugin.ps1 b/02_卡人(水)/水溪_整理归档/语音输入/脚本/setup_voice_agent_plugin.ps1 similarity index 100% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/setup_voice_agent_plugin.ps1 rename to 02_卡人(水)/水溪_整理归档/语音输入/脚本/setup_voice_agent_plugin.ps1 diff --git a/01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/setup_voice_agent_plugin.sh b/02_卡人(水)/水溪_整理归档/语音输入/脚本/setup_voice_agent_plugin.sh similarity index 100% rename from 01_卡资(金)/金仓_存储备份/Handy中文语音/脚本/setup_voice_agent_plugin.sh rename to 02_卡人(水)/水溪_整理归档/语音输入/脚本/setup_voice_agent_plugin.sh diff --git a/02_卡人(水)/水溪_整理归档/语音输入/脚本/屏语图片粘贴.swift b/02_卡人(水)/水溪_整理归档/语音输入/脚本/屏语图片粘贴.swift new file mode 100644 index 00000000..8cd70e0b --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音输入/脚本/屏语图片粘贴.swift @@ -0,0 +1,32 @@ +import AppKit +import Foundation + +let args = CommandLine.arguments +let copyOnly = args.contains("--copy-only") +let positional = args.dropFirst().filter { $0 != "--copy-only" } +guard positional.count >= 2 else { exit(2) } +let imagePath = String(positional[0]) +let text = String(positional[1]) +guard let imageData = try? Data(contentsOf: URL(fileURLWithPath: imagePath)), + imageData.count > 8 else { exit(3) } +let png = imageData +let pasteboard = NSPasteboard.general +pasteboard.clearContents() +pasteboard.declareTypes([.png], owner: nil) +guard pasteboard.setData(png, forType: .png) else { exit(4) } +if !copyOnly { + usleep(350_000) + func paste() { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/osascript") + task.arguments = ["-e", "tell application \"System Events\" to keystroke \"v\" using command down"] + try? task.run(); task.waitUntilExit() + } + paste() + usleep(350_000) + pasteboard.clearContents() + pasteboard.declareTypes([.string], owner: nil) + guard pasteboard.setString(text, forType: .string) else { exit(5) } + usleep(180_000) + paste() +} diff --git a/02_卡人(水)/水溪_整理归档/语音输入/脚本/屏语截图助手.py b/02_卡人(水)/水溪_整理归档/语音输入/脚本/屏语截图助手.py new file mode 100755 index 00000000..0d616027 --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音输入/脚本/屏语截图助手.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import json, os, subprocess, time +from pathlib import Path +STATE = Path.home() / 'Library/Application Support/karuo-ai/pingyu' +REQUEST = STATE / 'capture-request.json' +RESPONSE = STATE / 'capture-response.json' +PID = STATE / 'capture-helper.pid' +STATE.mkdir(parents=True, exist_ok=True) +PID.write_text(str(os.getpid())) +while True: + if REQUEST.exists(): + try: + data=json.loads(REQUEST.read_text()) + output=Path(data['output']) + REQUEST.unlink(missing_ok=True) + result=subprocess.run(['/usr/sbin/screencapture','-x','-m',str(output)],capture_output=True,text=True) + ok=result.returncode == 0 and output.exists() and output.stat().st_size > 0 + if ok: + # 将图片同步到应用支持目录,供粘贴助手读取,避免 Documents 的 TCC 读取差异。 + runtime_image = STATE / 'latest-screen.png' + runtime_image.write_bytes(output.read_bytes()) + shots=sorted(output.parent.glob("screen-*.png"), key=lambda item:item.stat().st_mtime, reverse=True) + for old in shots[100:]: old.unlink(missing_ok=True) + RESPONSE.write_text(json.dumps({'ok':ok,'output':str(output),'runtime_output':str(STATE / 'latest-screen.png') if ok else '', 'error':result.stderr.strip()},ensure_ascii=False)) + except Exception as exc: + RESPONSE.write_text(json.dumps({'ok':False,'error':str(exc)},ensure_ascii=False)) + time.sleep(0.12) diff --git a/02_卡人(水)/水溪_整理归档/语音输入/脚本/结合屏幕.py b/02_卡人(水)/水溪_整理归档/语音输入/脚本/结合屏幕.py new file mode 100755 index 00000000..732e889d --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音输入/脚本/结合屏幕.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 +"""卡若AI W03h:Command+1 结合屏幕本地上下文包。""" +from __future__ import annotations + +import argparse +import json +import os +import subprocess +import sys +import time +from datetime import datetime +from pathlib import Path + +ROOT = Path("/Users/karuo/Documents/个人/卡若AI") +ARCHIVE_DIR = ROOT / "02_卡人(水)/水溪_整理归档/语音输入/截图归档" +STATE_DIR = Path.home() / "Library/Application Support/karuo-ai/pingyu" +MAX_SCREENSHOTS = 100 +PENDING = STATE_DIR / "pending.json" +LOG = STATE_DIR / "screen-context.log" +HANDY = Path("/Applications/Handy.app/Contents/MacOS/handy") +CAPTURE_REQUEST = STATE_DIR / "capture-request.json" +CAPTURE_RESPONSE = STATE_DIR / "capture-response.json" +CORRECTION_SCRIPT = ROOT / "运营中枢/工作台/脚本/apply_karuo_voice_corrections.py" +PASTE_HELPER = Path.home() / "Library/Application Support/karuo-ai/pingyu/屏语图片粘贴" + + +def write_log(event: str) -> None: + STATE_DIR.mkdir(parents=True, exist_ok=True) + with LOG.open("a", encoding="utf-8") as f: + f.write(f"{datetime.now().isoformat(timespec='seconds')} {event}\n") + + +def cleanup_screenshots() -> int: + """只保留最新 100 张屏语截图;上下文记录永久保留。""" + shots = sorted(ARCHIVE_DIR.glob("screen-*.png"), key=lambda item: item.stat().st_mtime, reverse=True) + removed = 0 + for shot in shots[MAX_SCREENSHOTS:]: + shot.unlink(missing_ok=True) + removed += 1 + if removed: + write_log(f"cleanup removed={removed} remaining={min(len(shots), MAX_SCREENSHOTS)}") + return removed + + +def read_pending() -> dict | None: + try: + data = json.loads(PENDING.read_text(encoding="utf-8")) + if time.time() > float(data.get("expires_at", 0)): + PENDING.unlink(missing_ok=True) + write_log("expired") + return None + return data + except (OSError, ValueError, TypeError): + return None + + +def correct(text: str) -> str: + if not CORRECTION_SCRIPT.exists(): + return text.strip() + out = subprocess.run( + [sys.executable, str(CORRECTION_SCRIPT), text], + capture_output=True, + text=True, + check=False, + ) + return (out.stdout or text).strip() + + +def register_screenshot(shot: Path, *, start_recording: bool) -> int: + if not shot.exists() or shot.stat().st_size == 0: + write_log(f"existing-capture-invalid path={shot}") + return 2 + PENDING.write_text( + json.dumps({"screenshot": str(shot), "armed_at": time.time(), "expires_at": time.time() + 180}, ensure_ascii=False), + encoding="utf-8", + ) + write_log(f"armed screenshot={shot.name}") + if start_recording and HANDY.exists(): + subprocess.Popen([str(HANDY), "--toggle-post-process"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + return 0 + + +def arm_existing(path: str, *, start_recording: bool) -> int: + STATE_DIR.mkdir(parents=True, exist_ok=True) + if read_pending(): + write_log("existing-capture-pending-conflict") + return 4 + return register_screenshot(Path(path), start_recording=start_recording) + + +def arm(*, start_recording: bool) -> int: + STATE_DIR.mkdir(parents=True, exist_ok=True) + current = read_pending() + if current: + if start_recording and HANDY.exists(): + subprocess.Popen([str(HANDY), "--toggle-post-process"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + write_log("toggle-stop") + return 0 + + ARCHIVE_DIR.mkdir(parents=True, exist_ok=True) + shot = ARCHIVE_DIR / f"screen-{datetime.now():%Y%m%d-%H%M%S}.png" + CAPTURE_RESPONSE.unlink(missing_ok=True) + CAPTURE_REQUEST.write_text(json.dumps({"output": str(shot)}, ensure_ascii=False), encoding="utf-8") + deadline = time.time() + 5 + while time.time() < deadline and not CAPTURE_RESPONSE.exists(): + time.sleep(0.1) + try: + response = json.loads(CAPTURE_RESPONSE.read_text(encoding="utf-8")) + except (OSError, ValueError): + response = {"ok": False, "error": "helper-timeout"} + if not response.get("ok"): + write_log(f"capture-helper-failed error={response.get('error', '')}") + return 2 + result = register_screenshot(shot, start_recording=start_recording) + if result == 0 and response.get("runtime_output"): + state = read_pending() + if state: + state["runtime_screenshot"] = response["runtime_output"] + PENDING.write_text(json.dumps(state, ensure_ascii=False), encoding="utf-8") + return result + + +def consume(raw: str, *, paste: bool, submit: bool, dry_run: bool) -> int: + state = read_pending() + if not state: + return 3 + corrected = correct(raw) + task = corrected.removeprefix("结合屏幕").lstrip(",,:: ") or corrected + screenshot = Path(str(state["screenshot"])) + attachment = Path(str(state.get("runtime_screenshot", screenshot))) + packet = ( + "【卡若AI·结合屏幕】\n" + f"请查看当前屏幕截图:{screenshot}\n" + "截图只用于本次上下文,不做常驻监控。\n" + f"语音指令(已洗字):{task}\n" + "请先结合截图理解,再直接回答或执行。" + ) + context = screenshot.with_suffix(".md") + context.write_text(packet + "\n", encoding="utf-8") + PENDING.unlink(missing_ok=True) + write_log(f"consumed screenshot={screenshot.name} raw_len={len(raw)}") + if paste and not dry_run: + if PASTE_HELPER.exists() and attachment.exists(): + subprocess.run([str(PASTE_HELPER), str(attachment), packet], check=False) + else: + subprocess.run(["pbcopy"], input=packet, text=True, check=False) + time.sleep(0.35) + subprocess.run(["osascript", "-e", 'tell application "System Events" to keystroke "v" using command down'], check=False) + # 屏语始终不自动回车;submit 参数保留作兼容但不执行。 + print(packet) + return 0 + + +def main() -> int: + ap = argparse.ArgumentParser(description="卡若AI结合屏幕本地上下文") + group = ap.add_mutually_exclusive_group(required=True) + group.add_argument("--toggle", action="store_true", help="Command+1 调用:截图并开始/结束后处理录音") + group.add_argument("--arm", action="store_true", help="仅截图武装,供测试") + group.add_argument("--arm-existing", metavar="PATH", help="登记由屏语应用原生生成的截图并开始录音") + group.add_argument("--consume", action="store_true", help="消费待处理的转写") + group.add_argument("--status", action="store_true", help="显示屏语截图归档状态") + ap.add_argument("--paste", action="store_true", help="消费后填入当前输入框") + ap.add_argument("--submit", action="store_true", help="仅屏语模式:填入后自动提交给当前 AI") + ap.add_argument("--dry-run", action="store_true", help="不触发录音或粘贴") + ap.add_argument("text", nargs="?", help="转写文本;缺省时从 stdin 读取") + args = ap.parse_args() + if args.status: + STATE_DIR.mkdir(parents=True, exist_ok=True) + removed = cleanup_screenshots() + count = len(list(ARCHIVE_DIR.glob("screen-*.png"))) + print(json.dumps({"directory": str(ARCHIVE_DIR), "screenshots": count, "max_screenshots": MAX_SCREENSHOTS, "cleaned": removed}, ensure_ascii=False)) + return 0 + if args.toggle: + return arm(start_recording=not args.dry_run) + if args.arm: + return arm(start_recording=False) + if args.arm_existing: + return arm_existing(args.arm_existing, start_recording=not args.dry_run) + raw = args.text if args.text is not None else sys.stdin.read() + return consume(raw, paste=args.paste, submit=args.submit, dry_run=args.dry_run) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/02_卡人(水)/水溪_整理归档/语音输入/脚本/结合屏幕应用.swift b/02_卡人(水)/水溪_整理归档/语音输入/脚本/结合屏幕应用.swift new file mode 100644 index 00000000..7aa067da --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音输入/脚本/结合屏幕应用.swift @@ -0,0 +1,305 @@ +import AppKit +import ApplicationServices +import Carbon.HIToolbox +import CoreGraphics +import Foundation +import ScreenCaptureKit + +let screenScript = NSHomeDirectory() + "/Library/Application Support/karuo-ai/pingyu/结合屏幕.py" +let archiveDirectory = "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水溪_整理归档/语音输入/截图归档" +let pendingFile = NSHomeDirectory() + "/Library/Application Support/karuo-ai/pingyu/pending.json" + +private let screenVoiceHotKeyHandler: EventHandlerUPP = { _, event, userData in + guard let event, let userData else { return OSStatus(eventNotHandledErr) } + var hotKeyID = EventHotKeyID() + let status = GetEventParameter( + event, + EventParamName(kEventParamDirectObject), + EventParamType(typeEventHotKeyID), + nil, + MemoryLayout.size, + nil, + &hotKeyID + ) + guard status == noErr, hotKeyID.id == 1 else { return status } + let controller = Unmanaged.fromOpaque(userData).takeUnretainedValue() + DispatchQueue.main.async { controller.handleHotKey() } + return noErr +} + +final class ScreenVoiceApp: NSObject, NSApplicationDelegate { + private var statusItem: NSStatusItem! + private var panel: NSPanel? + private var titleLabel: NSTextField? + private var detailLabel: NSTextField? + private var startButton: NSButton? + private var finishButton: NSButton? + private var hotKeyRef: EventHotKeyRef? + private var eventHandlerRef: EventHandlerRef? + private var active = false + private var clipboardChangeBeforeRecording: Int = 0 + private var targetApplication: NSRunningApplication? + + func applicationDidFinishLaunching(_ notification: Notification) { + NSApp.setActivationPolicy(.accessory) + statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) + statusItem.button?.title = "🎙屏语" + statusItem.button?.toolTip = "卡若AI·屏语:Command + 1 开始或结束" + rebuildMenu() + installSystemHotKey() + showReady() + } + + func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool { + showReady() + return true + } + + private func menuItem(_ title: String, _ action: Selector) -> NSMenuItem { + let item = NSMenuItem(title: title, action: action, keyEquivalent: "") + item.target = self + return item + } + + private func rebuildMenu() { + let menu = NSMenu() + menu.addItem(menuItem("开始结合屏幕(⌘1)", #selector(start))) + menu.addItem(menuItem("结束并粘贴(⌘1)", #selector(finish))) + menu.addItem(NSMenuItem.separator()) + menu.addItem(menuItem("打开屏幕录制设置", #selector(openScreenRecording))) + menu.addItem(NSMenuItem.separator()) + menu.addItem(menuItem("退出卡若AI·屏语", #selector(quit))) + statusItem.menu = menu + } + + private func installSystemHotKey() { + var eventType = EventTypeSpec( + eventClass: OSType(kEventClassKeyboard), + eventKind: UInt32(kEventHotKeyPressed) + ) + InstallEventHandler( + GetApplicationEventTarget(), + screenVoiceHotKeyHandler, + 1, + &eventType, + Unmanaged.passUnretained(self).toOpaque(), + &eventHandlerRef + ) + let hotKeyID = EventHotKeyID(signature: OSType(0x4B525359), id: 1) // KRSY + RegisterEventHotKey( + UInt32(kVK_ANSI_1), + UInt32(cmdKey), + hotKeyID, + GetApplicationEventTarget(), + 0, + &hotKeyRef + ) + } + + func handleHotKey() { + active ? finish() : start() + } + + private func showReady() { + statusItem.button?.title = "🎙屏语" + statusItem.button?.toolTip = "Command + 1 开始;再次按下结束并粘贴" + panel?.orderOut(nil) + } + + @objc private func start() { + guard !active else { finish(); return } + targetApplication = NSWorkspace.shared.frontmostApplication + clipboardChangeBeforeRecording = NSPasteboard.general.changeCount + showState("正在截图…", "屏语正在获取当前画面,请稍等。") + statusItem.button?.title = "🎙屏语·截图中" + runPython(["--toggle"]) { code in + DispatchQueue.main.async { + if code == 0 { + self.active = true + self.statusItem.button?.title = "🎙屏语·说话中" + self.updateButtons() + self.showState("已截图,正在听你说话", "现在直接说需求;说完再按 Command + 1,系统只会粘贴到输入框,不会自动发送。") + } else { + self.statusItem.button?.title = "🎙屏语" + self.showState("截图正在恢复", "本地截图助手正在重连,请再点击一次开始。") + } + } + } + } + + @objc private func finish() { + guard active else { start(); return } + statusItem.button?.title = "🎙屏语·处理中" + showState("正在转写并粘贴", "正在把截图和语音内容放入当前输入框,不会自动发送。") + runPython(["--toggle"]) { _ in + DispatchQueue.main.async { self.waitForHandyTranscript(remaining: 80) } + } + } + + private func waitForHandyTranscript(remaining: Int) { + let board = NSPasteboard.general + if board.changeCount != clipboardChangeBeforeRecording, + let transcript = board.string(forType: .string), + !transcript.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { + targetApplication?.activate(options: [.activateIgnoringOtherApps, .activateAllWindows]) + usleep(220_000) + runPythonWithInput(["--consume", "--paste"], input: transcript) { _ in + DispatchQueue.main.async { self.watchForSubmission(remaining: 20) } + } + } else if remaining > 0 { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { + self.waitForHandyTranscript(remaining: remaining - 1) + } + } else { + self.active = false + self.statusItem.button?.title = "🎙屏语" + self.showState("还没收到转写", "请确认 Handy 正在运行,然后重新开始一次。") + } + } + + private func watchForSubmission(remaining: Int) { + if !FileManager.default.fileExists(atPath: pendingFile) { + active = false + statusItem.button?.title = "🎙屏语" + updateButtons() + statusItem.button?.title = "🎙屏语·已粘贴" + showState("已粘贴到输入框", "请检查输入框内容,确认后由你手动发送。") + DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { self.showReady() } + } else if remaining > 0 { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.watchForSubmission(remaining: remaining - 1) } + } else { + active = false + statusItem.button?.title = "🎙屏语" + updateButtons() + showState("还没收到转写", "请确认 Handy 正在运行,然后重新开始一次。") + } + } + + private func captureMainDisplay(completed: @escaping (String?) -> Void) { + Task { + do { + let content = try await SCShareableContent.excludingDesktopWindows(false, onScreenWindowsOnly: true) + guard let display = content.displays.first else { + DispatchQueue.main.async { completed(nil) } + return + } + let filter = SCContentFilter(display: display, excludingWindows: []) + let configuration = SCStreamConfiguration() + configuration.width = display.width + configuration.height = display.height + configuration.showsCursor = true + let image = try await SCScreenshotManager.captureImage(contentFilter: filter, configuration: configuration) + let formatter = DateFormatter() + formatter.dateFormat = "yyyyMMdd-HHmmss" + let name = "screen-\(formatter.string(from: Date())).png" + let directory = URL(fileURLWithPath: archiveDirectory, isDirectory: true) + let file = directory.appendingPathComponent(name) + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + let bitmap = NSBitmapImageRep(cgImage: image) + guard let png = bitmap.representation(using: .png, properties: [:]) else { + DispatchQueue.main.async { completed(nil) } + return + } + try png.write(to: file, options: .atomic) + DispatchQueue.main.async { completed(file.path) } + } catch { + let log = "\(Date()) ScreenCaptureKit error: \(error)\n" + let logURL = URL(fileURLWithPath: archiveDirectory).appendingPathComponent("screen-app.log") + if let data = log.data(using: .utf8) { + if FileManager.default.fileExists(atPath: logURL.path), let handle = try? FileHandle(forWritingTo: logURL) { + try? handle.seekToEnd(); try? handle.write(contentsOf: data); try? handle.close() + } else { + try? data.write(to: logURL) + } + } + DispatchQueue.main.async { completed(nil) } + } + } + } + + private func runPython(_ arguments: [String], completed: @escaping (Int32) -> Void) { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/python3") + task.arguments = [screenScript] + arguments + task.terminationHandler = { process in completed(process.terminationStatus) } + do { try task.run() } catch { completed(1) } + } + + private func runPythonWithInput(_ arguments: [String], input: String, completed: @escaping (Int32) -> Void) { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/python3") + task.arguments = [screenScript] + arguments + let pipe = Pipe() + task.standardInput = pipe + task.terminationHandler = { process in completed(process.terminationStatus) } + do { + try task.run() + pipe.fileHandleForWriting.write(input.data(using: .utf8) ?? Data()) + try? pipe.fileHandleForWriting.close() + } catch { completed(1) } + } + + private func createPanel() { + let content = NSView(frame: NSRect(x: 0, y: 0, width: 520, height: 230)) + let t = NSTextField(labelWithString: "") + t.frame = NSRect(x: 26, y: 164, width: 468, height: 30) + t.font = .systemFont(ofSize: 20, weight: .semibold) + let d = NSTextField(wrappingLabelWithString: "") + d.frame = NSRect(x: 26, y: 105, width: 468, height: 52) + d.font = .systemFont(ofSize: 14) + d.textColor = .secondaryLabelColor + + let start = NSButton(title: "开始结合屏幕", target: self, action: #selector(self.start)) + start.frame = NSRect(x: 26, y: 42, width: 150, height: 38) + start.bezelStyle = .rounded + start.keyEquivalent = "" + let finish = NSButton(title: "结束并粘贴", target: self, action: #selector(self.finish)) + finish.frame = NSRect(x: 184, y: 42, width: 140, height: 38) + finish.bezelStyle = .rounded + let permission = NSButton(title: "录屏设置", target: self, action: #selector(self.openScreenRecording)) + permission.frame = NSRect(x: 332, y: 42, width: 162, height: 38) + permission.bezelStyle = .rounded + + [t, d, start, finish, permission].forEach(content.addSubview) + let p = NSPanel( + contentRect: content.bounds, + styleMask: [.titled, .closable, .utilityWindow, .nonactivatingPanel], + backing: .buffered, + defer: false + ) + p.title = "卡若AI·屏语" + p.contentView = content + p.level = .floating + p.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary] + p.isReleasedWhenClosed = false + p.hidesOnDeactivate = false + p.becomesKeyOnlyIfNeeded = true + panel = p + titleLabel = t + detailLabel = d + startButton = start + finishButton = finish + updateButtons() + } + + private func updateButtons() { + startButton?.isEnabled = !active + finishButton?.isEnabled = active + } + + private func showState(_ title: String, _ detail: String) { + statusItem.button?.toolTip = title + ":" + detail + panel?.orderOut(nil) + } + + @objc private func openScreenRecording() { + NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture")!) + } + + @objc private func quit() { NSApp.terminate(nil) } +} + +let app = NSApplication.shared +let delegate = ScreenVoiceApp() +app.delegate = delegate +app.run() diff --git a/02_卡人(水)/水溪_整理归档/语音输入/脚本/结合屏幕热键.swift b/02_卡人(水)/水溪_整理归档/语音输入/脚本/结合屏幕热键.swift new file mode 100644 index 00000000..5335e3c9 --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音输入/脚本/结合屏幕热键.swift @@ -0,0 +1,23 @@ +import AppKit +import Foundation + +let script = "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水溪_整理归档/语音输入/脚本/结合屏幕.py" +func trigger() { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/python3") + task.arguments = [script, "--toggle"] + try? task.run() + let notification = NSUserNotification() + notification.title = "卡若AI·结合屏幕" + notification.informativeText = "已截图并切换语音录音;再按 Command+1 结束。" + NSUserNotificationCenter.default.deliver(notification) +} + +let mask: NSEvent.EventTypeMask = [.keyDown] +NSEvent.addGlobalMonitorForEvents(matching: mask) { event in + let commandHeld = event.modifierFlags.contains(.command) + if event.keyCode == 18 && commandHeld { // Command + 1 + trigger() + } +} +RunLoop.main.run() diff --git a/02_卡人(水)/水溪_整理归档/语音输入/脚本/部署结合屏幕.sh b/02_卡人(水)/水溪_整理归档/语音输入/脚本/部署结合屏幕.sh new file mode 100755 index 00000000..d4cd4235 --- /dev/null +++ b/02_卡人(水)/水溪_整理归档/语音输入/脚本/部署结合屏幕.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +set -euo pipefail +ROOT="/Users/karuo/Documents/个人/卡若AI" +BASE="$ROOT/02_卡人(水)/水溪_整理归档/语音输入" +APP="/Applications/卡若AI·屏语.app" +EXEC="$APP/Contents/MacOS/卡若AI·屏语" +AGENT="$HOME/Library/LaunchAgents/com.karuo.pingyu-hotkey.plist" +HOOK="$HOME/Library/Application Support/com.pais.handy/hooks/transcription" +RUNTIME="$HOME/Library/Application Support/karuo-ai/pingyu" +mkdir -p "$RUNTIME" +cp "$BASE/脚本/结合屏幕.py" "$RUNTIME/结合屏幕.py" +cp "$BASE/脚本/屏语截图助手.py" "$RUNTIME/屏语截图助手.py" +cp "$BASE/脚本/handy_结合屏幕钩子.sh" "$RUNTIME/handy_结合屏幕钩子.sh" +swiftc "$BASE/脚本/屏语图片粘贴.swift" -framework AppKit -o "$RUNTIME/屏语图片粘贴" +chmod +x "$RUNTIME/结合屏幕.py" "$RUNTIME/屏语截图助手.py" "$RUNTIME/handy_结合屏幕钩子.sh" "$RUNTIME/屏语图片粘贴" +ICON_SOURCE="$BASE/资源/卡若AI·屏语.png" +OLD_APP="/Applications/卡若AI结合屏幕.app" +OLD_AGENT="$HOME/Library/LaunchAgents/com.karuo.voice-screen-hotkey.plist" +launchctl bootout "gui/$(id -u)" "$OLD_AGENT" 2>/dev/null || true +rm -f "$OLD_AGENT" +if [ -d "$OLD_APP" ] && [ ! -e "$APP" ]; then + mv "$OLD_APP" "$APP" +fi +mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources" "$HOME/Library/Logs/karuo" "$(dirname "$HOOK")" +if [ -f "$ICON_SOURCE" ]; then + ICONSET="$(mktemp -d)/卡若AI·屏语.iconset" + mkdir -p "$ICONSET" + sips -z 16 16 "$ICON_SOURCE" --out "$ICONSET/icon_16x16.png" >/dev/null + sips -z 32 32 "$ICON_SOURCE" --out "$ICONSET/icon_16x16@2x.png" >/dev/null + sips -z 32 32 "$ICON_SOURCE" --out "$ICONSET/icon_32x32.png" >/dev/null + sips -z 64 64 "$ICON_SOURCE" --out "$ICONSET/icon_32x32@2x.png" >/dev/null + sips -z 128 128 "$ICON_SOURCE" --out "$ICONSET/icon_128x128.png" >/dev/null + sips -z 256 256 "$ICON_SOURCE" --out "$ICONSET/icon_128x128@2x.png" >/dev/null + sips -z 256 256 "$ICON_SOURCE" --out "$ICONSET/icon_256x256.png" >/dev/null + sips -z 512 512 "$ICON_SOURCE" --out "$ICONSET/icon_256x256@2x.png" >/dev/null + sips -z 512 512 "$ICON_SOURCE" --out "$ICONSET/icon_512x512.png" >/dev/null + sips -z 1024 1024 "$ICON_SOURCE" --out "$ICONSET/icon_512x512@2x.png" >/dev/null + iconutil -c icns "$ICONSET" -o "$APP/Contents/Resources/卡若AI·屏语.icns" +fi +cat > "$APP/Contents/Info.plist" <<'PLIST' + + + +CFBundleDisplayName卡若AI·屏语 +CFBundleName卡若AI·屏语 +CFBundleIdentifiercom.karuo.pingyu +CFBundleExecutable卡若AI·屏语 +CFBundleIconFile卡若AI·屏语.icns +CFBundlePackageTypeAPPL +CFBundleShortVersionString1.0 +CFBundleVersion1 +LSMinimumSystemVersion14.0 +NSMicrophoneUsageDescription卡若AI·屏语通过 Handy 使用麦克风进行语音输入。 +NSScreenCaptureUsageDescription卡若AI·屏语仅在你主动启动屏语时截取当前屏幕,用于回答本次语音任务。 + +PLIST +swiftc "$BASE/脚本/结合屏幕应用.swift" -framework Cocoa -framework ApplicationServices -framework Carbon -framework ScreenCaptureKit -o "$EXEC" +SIGN_KEYCHAIN="$HOME/Library/Keychains/karuo-pingyu-signing.keychain-db" +SIGN_PASSWORD="karuo-pingyu-local-signing" +SIGN_IDENTITY="3D164440DF26A1C680EC9B603EB8FD7AC8D71BD3" +security unlock-keychain -p "$SIGN_PASSWORD" "$SIGN_KEYCHAIN" +codesign --force --deep --options runtime --sign "$SIGN_IDENTITY" --keychain "$SIGN_KEYCHAIN" --identifier com.karuo.pingyu "$APP" +chmod +x "$BASE/脚本/结合屏幕.py" "$BASE/脚本/handy_结合屏幕钩子.sh" "$EXEC" +ln -sfn "$RUNTIME/handy_结合屏幕钩子.sh" "$HOOK" +# Fn 的按键方式不变;改用外部脚本以便仅在屏语已启动时自动提交屏幕任务。 +python3 - < "$AGENT" < + + +Labelcom.karuo.pingyu-hotkey +ProgramArguments/usr/bin/open-g$APP +RunAtLoad +ProcessTypeInteractive +StandardOutPath$HOME/Library/Logs/karuo/voice-screen-hotkey.out.log +StandardErrorPath$HOME/Library/Logs/karuo/voice-screen-hotkey.err.log + +PLIST +launchctl bootout "gui/$(id -u)" "$AGENT" 2>/dev/null || true +pkill -f "$EXEC" 2>/dev/null || true +HELPER="$RUNTIME/屏语截图助手.py" +HELPER_PID="$RUNTIME/capture-helper.pid" +if [ -f "$HELPER_PID" ]; then kill "$(cat "$HELPER_PID")" 2>/dev/null || true; fi +nohup /usr/bin/python3 "$HELPER" >"$RUNTIME/capture-helper.log" 2>&1 & +launchctl bootstrap "gui/$(id -u)" "$AGENT" +open -g "$APP" +echo "已部署:卡若AI·屏语.app(Command+1);Fn 普通语音不变。" +echo "首次仅需在“录屏与系统录音”中开启“卡若AI·屏语”;Command+1 不再需要输入监控。" diff --git a/02_卡人(水)/水溪_整理归档/语音输入/资源/卡若AI·屏语.png b/02_卡人(水)/水溪_整理归档/语音输入/资源/卡若AI·屏语.png new file mode 100644 index 00000000..00e801cd Binary files /dev/null and b/02_卡人(水)/水溪_整理归档/语音输入/资源/卡若AI·屏语.png differ diff --git a/03_卡木(木)/卡前_体验设计/AGENT.md b/03_卡木(木)/卡前_体验设计/AGENT.md new file mode 100644 index 00000000..0485647a --- /dev/null +++ b/03_卡木(木)/卡前_体验设计/AGENT.md @@ -0,0 +1,54 @@ +--- +id: kaqian +name: 卡前 +agent_type: member +owner: 卡木 +group: 木 +status: active +version: "1.0" +updated: "2026-07-26" +--- + +# 卡前 Agent + +## 身份与使命 + +- **角色**:卡若AI UX/UI视觉与交互设计师、前端体验交付负责人 +- **使命**:把业务需求转为可实现、可验收、可访问的页面结构、交互状态和设计系统;统筹 v0、Vercel 前端界面交付。 +- **负责人**:卡木 +- **人格**:ENFP;PDP 老虎25、猫头鹰18;DISC D力量17、C完美15 +- **工作方式**:好奇地探索用户路径,果断收敛方案,用可验证的规范保证细节。 + +## 负责范围 + +1. 信息架构、用户旅程、页面流与交互状态机。 +2. UX/UI、Design Tokens、组件规范、响应式与无障碍体验。 +3. v0 对话需求、GitHub 真源、Preview、Vercel 页面验收的体验侧总控。 +4. 前端业务界面设计评审;工程实现、埋点、构建和发布与火炬协同。 + +## Skill挂载 + +- 主责:`M14 体验设计与视觉规范输出`、`M06 前端生成`、`M11 v0前端生成与预览交付`、`M13 整站视觉采集与产品设计`。 +- 协同:`F01a 前端开发`、`F01f 私域银行统一前端模块`、`M02e 拆架契匣`。 +- 执行时从 `SKILL_REGISTRY.md` 解析真源路径;人设不替代 Skill。 + +## MCP与桥接策略 + +- 优先:`figma`、`browser`、`image`、`filesystem`、GitHub、v0/Vercel 官方 API 与本地桥接脚本。 +- v0/Vercel 的项目状态以项目内 `开发文档/8、部署/v0_vercel_binding.json` 为准;GitHub 是代码真源。 +- 密钥只从项目私有环境或账号索引引用,不写入本文件、设计稿和交付文档。 + +## Hook链 + +- `before_input` → `karuo_asr_normalize` +- `before_route` → `karuo_skill_route` +- `before_execute` → `karuo_scope_guard` +- `after_execute` → `karuo_verify` +- `after_response` → `karuo_recap` +- `after_response` → `karuo_mongo_sync` + +## 交付边界 + +- 不只交付理想态:必须有加载、空、错误、权限不足、超长内容和网络异常状态。 +- 不只交付审美描述:必须交付页面结构、状态流、Token、组件规则、a11y 与前端映射建议。 +- 视觉稿与代码不一致时,先形成差异清单;由火炬处理工程实现,卡前回归验收。 diff --git a/03_卡木(木)/卡前_体验设计/体验设计与视觉规范输出/SKILL.md b/03_卡木(木)/卡前_体验设计/体验设计与视觉规范输出/SKILL.md new file mode 100644 index 00000000..60edba5b --- /dev/null +++ b/03_卡木(木)/卡前_体验设计/体验设计与视觉规范输出/SKILL.md @@ -0,0 +1,75 @@ +--- +name: 体验设计与视觉规范输出 +description: 卡前负责 UX/UI、用户旅程、交互状态机、Design Tokens、组件规格、无障碍和前端体验验收。触发词:UX、UI、体验设计、视觉设计、页面设计、用户旅程、交互状态、设计系统、Design System、设计令牌、无障碍、a11y、前端界面、v0界面、Vercel预览。 +triggers: UX、UI、体验设计、视觉设计、页面设计、用户旅程、交互状态、设计系统、Design System、设计令牌、无障碍、a11y、前端界面、v0界面、Vercel预览 +owner: 卡前 +group: 木 +version: "1.0" +updated: "2026-07-26" +--- + +# 体验设计与视觉规范输出(M14) + +## 定位 + +卡前将业务目标转成可被前端直接实现和验收的体验规格。代码真源仍在 GitHub;v0/Vercel 交付沿用 M11;工程实现和埋点沿用 F01a/F01f。 + +## 工作流 + +1. **用户旅程**:读取 PRD、页面现状和数据,输出角色、目标、触点、痛点、成功条件。 +2. **信息架构**:定义页面、模块、导航和关键任务路径;用 Mermaid 描述主流程。 +3. **交互状态**:为每个关键模块补齐 `loading / empty / error / disabled / overflow / offline / success` 状态及恢复动作。 +4. **设计系统**:输出颜色、字体、间距、圆角、阴影、层级、动效和组件状态,映射 CSS 变量与 Tailwind Token。 +5. **无障碍**:标明对比度、焦点顺序、键盘操作、语义标签、表单错误提示和触控尺寸。 +6. **前端交付**:向同一 v0 Chat 发送结构化需求;由 GitHub 分支写回、Preview 与 Vercel 验收。卡前负责视觉回归,火炬负责工程回归。 + +## 必交付格式 + +每次页面/功能设计至少包含: + +- 用户旅程与页面结构; +- Mermaid 状态流; +- Design Tokens(Hex/RGB、字号、间距、阴影、圆角); +- 组件清单和状态表; +- a11y 清单; +- v0 提示词或前端实现约束; +- 验收清单与截图对照点。 + +## 状态流模板 + +```mermaid +stateDiagram-v2 + [*] --> Loading + Loading --> Ready: 数据成功 + Loading --> Empty: 无数据 + Loading --> Error: 请求失败 + Error --> Loading: 重试 + Empty --> Ready: 创建或导入 + Ready --> [*] +``` + +## Design Tokens 最小集 + +```css +:root { + --color-primary: #2563EB; + --color-primary-hover: #1D4ED8; + --color-surface: #FFFFFF; + --color-text: #0F172A; + --color-muted: #64748B; + --color-danger: #DC2626; + --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; + --radius-sm: 8px; --radius-md: 12px; --radius-lg: 16px; + --shadow-card: 0 8px 24px rgb(15 23 42 / 8%); +} +``` + +- 正文与背景对比度目标不低于 4.5:1;大文字不低于 3:1。 +- 键盘焦点可见;完整操作顺序与视觉顺序一致;可点击目标最小 44×44px。 +- Skeleton 优先于无限 Spinner;错误状态必须给出重试或返回路径。 + +## 协同与验收 + +- 需要生成或部署界面时叠加 M11;需要工程代码时叠加 F01a;需要接口契约时叠加 M02e。 +- 禁止以“页面好看”作为验收结论;至少验证主路径、所有状态、移动端、键盘导航、对比度和 Preview。 +- 将规格与验收写入项目 `开发文档/`,但本 Skill、人设、路由与能力归属只维护在卡若AI主仓。 diff --git a/03_卡木(木)/卡前_体验设计/体验设计与视觉规范输出/agents/openai.yaml b/03_卡木(木)/卡前_体验设计/体验设计与视觉规范输出/agents/openai.yaml new file mode 100644 index 00000000..34e2db6a --- /dev/null +++ b/03_卡木(木)/卡前_体验设计/体验设计与视觉规范输出/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "卡前·体验设计与视觉规范" + short_description: "UX/UI、状态机、设计系统、无障碍与前端体验验收" + default_prompt: "以卡前身份梳理用户旅程、交互状态和设计系统,并输出可直接交付给前端与 v0 的体验规格。" diff --git a/03_卡木(木)/木果_项目模板/AGENT.md b/03_卡木(木)/木果_项目模板/AGENT.md index 89a038e5..eb70c467 100644 --- a/03_卡木(木)/木果_项目模板/AGENT.md +++ b/03_卡木(木)/木果_项目模板/AGENT.md @@ -14,14 +14,14 @@ updated: "2026-07-23" ## 身份与使命 - **角色**:木果核心执行Agent -- **使命**:模板、PPT、前端形态、整站视觉采集、产品设计资产和品牌叙事 +- **使命**:模板、PPT、整站视觉采集、产品设计资产和品牌叙事(前端体验交付由卡前主责) - **负责人**:卡木 - **人格**:ESTP;老虎+I - **工作模式**:`塑形`、`木芽表达模式` ## Skill挂载 -`M03`、`M07`、`M08`、`M09`、`M13` +`M03`、`M07`、`M08`、`M09`;M13由卡前主责、木果协同 执行时必须从`SKILL_REGISTRY.md`解析真实路径;人设本身不替代Skill。 diff --git a/03_卡木(木)/木果_项目模板/v0前端生成与预览交付/SKILL.md b/03_卡木(木)/木果_项目模板/v0前端生成与预览交付/SKILL.md index 43de2f89..ca4ae5c2 100644 --- a/03_卡木(木)/木果_项目模板/v0前端生成与预览交付/SKILL.md +++ b/03_卡木(木)/木果_项目模板/v0前端生成与预览交付/SKILL.md @@ -2,12 +2,14 @@ name: v0前端生成与预览交付 description: 负责部署到 Vercel 的对接(主要是前端界面);v0 优化完成后同步到 GitHub、Vercel、本地协同,确保全部确定;任务完成反馈写入项目并反馈卡若。项目/对话名中文。 triggers: Vercel部署/v0部署/部署到v0/上帝之眼部署/Vercel v0/威宁 v0/部署流水线 -owner: 木果 +owner: 卡前 group: 木 version: "3.0" updated: "2026-07-24" --- +> **体验负责人**:卡前负责用户旅程、交互状态、视觉规范、无障碍与最终体验验收;木果保留项目模板、内容与设计资产协同。 + > **执行规则**:见 `运营中枢/技能路由/SKILL_RULES.md`。执行前必须:思考→拆解→读取本 Skill 与 references→按步执行→校验 v0 项目正确→**执行完成后将结果反馈给卡若**。 ## 一、技能概述 @@ -198,6 +200,15 @@ node scripts/sync-to-v0.js 5. 回传 demo、截图、版本 ID 与变更摘要。 6. v0 生成代码写入 Git 分支后,GitHub 合并/推送触发 Vercel;再回读部署、生产 URL、HTTP 状态与页面标题。 +### 8.4-A 分支问题一键修复(新增) + +- 当出现 `Create a Branch`、`continue` 被拦截等提示时,不点页面: + 1. `POST /v1/chats/{chatId}/fork` 创建分支 chat(返回新 chatId)。 + 2. 将新 chatId 写回 `sdk/config/v0_vercel_binding.json` 的 `v0.chatId` 与 `v0.chatUrl`,避免反复操作旧会话。 + 3. 后续都使用新 chatId 继续 `send/status`,旧 chat 只留归档。 +- 规则:一个主问题不再创建新分支,若同一目标 1h 内重复 fork 先复用同一 chat。 +- 示例命令:`node sdk/scripts/v0_control.mjs fork` / `node sdk/scripts/v0_control.mjs switch `。 + ### 8.5 完成判定 以下证据全部存在才写 100%: diff --git a/03_卡木(木)/木果_项目模板/前端生成/SKILL.md b/03_卡木(木)/木果_项目模板/前端生成/SKILL.md index 5ebefbb9..8c31daeb 100644 --- a/03_卡木(木)/木果_项目模板/前端生成/SKILL.md +++ b/03_卡木(木)/木果_项目模板/前端生成/SKILL.md @@ -3,11 +3,13 @@ name: 前端生成 description: 现代UI代码生成,默认遵循卡若标准(神射手/毛狐狸):苹果毛玻璃、渐变背景、统一色板与组件。触发词:生成UI、前端代码、设计页面、生成组件、神射手、毛狐狸、毛玻璃、卡若标准。 group: 木 triggers: 前端生成、UI生成、页面生成、神射手风格、毛狐狸风格、毛玻璃 -owner: 木果 +owner: 卡前 version: "3.0" updated: "2026-07-22" --- +> **体验负责人**:卡前负责用户旅程、交互状态、视觉规范、无障碍与最终体验验收;木果保留项目模板、内容与设计资产协同。 + # 前端生成 > **强制入口**:所有 Web 前端生成先读取同级 `v0前端生成与预览交付/SKILL.md` 与 `参考资料/v0通用前端基线.md`。默认产物必须能被 v0 当前环境直接导入、运行、预览并通过 Git/PR 写回。 diff --git a/03_卡木(木)/木果_项目模板/整站视觉采集与产品设计/SKILL.md b/03_卡木(木)/木果_项目模板/整站视觉采集与产品设计/SKILL.md index cd7ac43a..e82bc789 100644 --- a/03_卡木(木)/木果_项目模板/整站视觉采集与产品设计/SKILL.md +++ b/03_卡木(木)/木果_项目模板/整站视觉采集与产品设计/SKILL.md @@ -2,12 +2,14 @@ name: 整站视觉采集与产品设计 description: 使用SiteOne Crawler与Playwright采集整站页面、全页截图、交互状态、静态资源、离线副本和Markdown,并生成产品设计图册、页面清单、设计分析与前端还原文档。适用于参考网站提取、竞品产品设计、改版留档、新旧站视觉对比和前端验收。 metadata: - owner: 木果 + owner: 卡前 group: 木 version: "1.0" updated: "2026-07-23" --- +> **体验负责人**:卡前负责用户旅程、交互状态、视觉规范、无障碍与最终体验验收;木果保留项目模板、内容与设计资产协同。 + # 整站视觉采集与产品设计 ## 目标 diff --git a/04_卡火(火)/火炬_全栈消息/前端开发/SKILL.md b/04_卡火(火)/火炬_全栈消息/前端开发/SKILL.md index 76e56fc4..71bf00a1 100644 --- a/04_卡火(火)/火炬_全栈消息/前端开发/SKILL.md +++ b/04_卡火(火)/火炬_全栈消息/前端开发/SKILL.md @@ -12,6 +12,8 @@ updated: "2026-07-22" > 主责:**苹果毛玻璃风格**与卡若标准前端(神射手/毛狐狸)。全栈开发做官网/全站时,前端部分统一走本 Skill。 +> **协同边界**:卡前负责体验设计、状态机、Design Tokens、无障碍和视觉验收;火炬负责工程实现、埋点、构建和发布验收。 + > **工程基线前置**:Web 项目必须先执行木果 `v0前端生成与预览交付` 的 `参考资料/v0通用前端基线.md`;本 Skill 负责视觉、业务实现、埋点和质量,不另建一套与 v0 不兼容的脚手架。 --- diff --git a/AGENT_REGISTRY.md b/AGENT_REGISTRY.md index 67b9146e..3029f931 100644 --- a/AGENT_REGISTRY.md +++ b/AGENT_REGISTRY.md @@ -1,6 +1,6 @@ # 卡若AI Agent注册表 -> 固定人设真源:1名大总管(BOOTSTRAP)+ 5名负责人Agent + 18名核心执行Agent。Skill只作为能力挂载。 +> 固定人设真源:1名大总管(BOOTSTRAP)+ 5名负责人Agent + 19名核心执行Agent。Skill只作为能力挂载。 | ID | Agent | 类型 | 五行 | 负责人 | 人设真源 | 工作模式 | Skill挂载 | MCP策略 | |:---|:---|:---|:---|:---|:---|:---|:---|:---| @@ -18,6 +18,7 @@ | `muye` | 木叶 | member | 木 | 卡木 | `03_卡木(木)/木叶_视频内容/AGENT.md` | 内容生产、分发 | M01、M01h | inherit | | `mugen` | 木根 | member | 木 | 卡木 | `03_卡木(木)/木根_逆向分析/AGENT.md` | 深析、接口识别 | M02、M02a | inherit | | `muguo` | 木果 | member | 木 | 卡木 | `03_卡木(木)/木果_项目模板/AGENT.md` | 塑形、木芽表达模式 | M03、M07、M08、M09 | inherit | +| `kaqian` | 卡前 | member | 木 | 卡木 | `03_卡木(木)/卡前_体验设计/AGENT.md` | 用户旅程、交互状态、设计系统、前端体验交付 | M14、M06、M11、M13;协同F01a、F01f、M02e | inherit | | `mushi` | 木识 | member | 木 | 卡木 | `03_卡木(木)/木识_软件识形/AGENT.md` | 识窍、CLI | M10 | inherit | | `huoju` | 火炬 | member | 火 | 卡火 | `04_卡火(火)/火炬_全栈消息/AGENT.md` | 炬彻架构模式、络照集成模式 | F01、F01a、F01b、F28、F29 | inherit | | `huochui` | 火锤 | member | 火 | 卡火 | `04_卡火(火)/火锤_代码修复/AGENT.md` | 锤砺修复模式 | F05 | inherit | diff --git a/BOOTSTRAP.md b/BOOTSTRAP.md index 9eff004d..793a3630 100644 --- a/BOOTSTRAP.md +++ b/BOOTSTRAP.md @@ -17,10 +17,10 @@ - `AGENT_REGISTRY.md`:人设可读索引。 - `运营中枢/智能体路由/agent_registry.json`:网站、Codex与运行时共用的结构化Agent真源。 -## 二、团队(5 负责人 Agent → 18 核心成员 Agent → Skill/MCP/Hook → 智能体实例) +## 二、团队(5 负责人 Agent → 19 核心成员 Agent → Skill/MCP/Hook → 智能体实例) ``` -卡若AI → 卡资(金)→金仓·金盾 | 卡人(水)→水溪·水泉·水桥·水岸 | 卡木(木)→木叶·木根·木果·木识 | 卡火(火)→火炬·火锤·火眼·火种 | 卡土(土)→土基·土砖·土渠·土簿 +卡若AI → 卡资(金)→金仓·金盾 | 卡人(水)→水溪·水泉·水桥·水岸 | 卡木(木)→木叶·木根·木果·卡前·木识 | 卡火(火)→火炬·火锤·火眼·火种 | 卡土(土)→土基·土砖·土渠·土簿 ``` 分配:用户明确@负责人或成员 → Agent注册表精确命中 → Skill注册表匹配能力 → 加载该Agent的MCP与Hook → 执行并验收。固定人员为5名负责人Agent与18名核心成员Agent;旧五席名称仅作为工作模式与兼容别名。**新技能 / 改名**:须符合 **卡若记忆宫殿命名体系**,见 `运营中枢/工作台/01_技能控制台.md` **〇、卡若记忆宫殿命名体系**。 @@ -55,7 +55,8 @@ | **SiteOne/整站截图/网站提取/参考网站/产品设计/产品图/设计图册/按钮截图/视觉回归** | M13 `03_卡木(木)/木果_项目模板/整站视觉采集与产品设计/SKILL.md` | | **持续执行/永久执行/接着做/直到完成** | `04_卡火(火)/火炬_全栈消息/持续执行闭环/SKILL.md` | | **写书/写一本书/聊天记录写书/畅销书/正式出版稿/正式版PDF/出版社送审包/直到出版** | F13b `04_卡火(火)/火种_知识模型/卡若写书出版/SKILL.md`(任何书唯一总入口;逐章写作叠F13a) | -| **闽南话/语音输入/ASR 误听/回廊洗字** | 机制 `运营中枢/参考资料/闽南话语音_ASR纠错机制.md`;词库 `运营中枢/参考资料/卡若闽南口音_ASR纠错库.json`;W03b `02_卡人(水)/水溪_整理归档/语音转写纠错/SKILL.md` | +| **语音输入/Handy/Fn语音/Command+1/结合屏幕/SenseVoice** | W03h `02_卡人(水)/水溪_整理归档/语音输入/SKILL.md`;设备安装资料由该 Skill 统一引用 | +| **闽南话/ASR 误听/回廊洗字** | 机制 `运营中枢/参考资料/闽南话语音_ASR纠错机制.md`;词库 `运营中枢/参考资料/卡若闽南口音_ASR纠错库.json`;W03b `02_卡人(水)/水溪_整理归档/语音转写纠错/SKILL.md` | | **高风险提示词/平和版/翻译提示词** | W05e `02_卡人(水)/水泉_规划拆解/执行提示词改写/SKILL.md`(洗字之后、公示之前) | | Soul运营报表 | `02_卡人(水)/水桥_平台对接/飞书管理/运营报表_SKILL.md` | | **Soul派对技能流/派对Stream/创业派对Stream** | `02_卡人(水)/水岸_项目管理/卡若创业派对/Soul派对技能流_掌管人与Stream规约.md` | diff --git a/SKILL_REGISTRY.md b/SKILL_REGISTRY.md index 2f07883d..bd9dc295 100644 --- a/SKILL_REGISTRY.md +++ b/SKILL_REGISTRY.md @@ -90,7 +90,6 @@ | G23 | **宿主挂载执行**(Shell 宿主语义) | 金仓 | **宿主挂载、宿主执行、云上 bash、万推控制台、挂载出错、karo_exec、自动 bash Mac 路径、brew 云端、Docker 宿主 shell、宿主程序** | `01_卡资(金)/金仓_存储备份/宿主挂载执行_SHELL/SKILL.md` | 网站对话与云端 shell ≠ Mac;工作区挂载 + docker-mac-host-shell + 宿主预检三位一体 | | G24 | **深蓝云自动化**(SLCloud · SHENLANYUN) | 金盾 | **深蓝云、深澜云、SHENLANYUN、slcloud、slcloud.org、slcloud-automation、订阅链接、体验套餐、深澜文档、token=、client/subscribe** | `01_卡资(金)/金盾_数据安全/深蓝云_SLCloud自动化/SKILL.md` | 深澜云平台注册/购套餐/取订阅链接;**支付与扫码必须用户接管**;真源自 `slcloud-automation.skill` | | G25 | **UU远程**(网易 · 遥台) | 金仓 | **UU远程、远程安装、远程装Codex、远程装软件、UU终端、远程插件、OFFICE-INNER、DESKTOP-434GEGI** | `01_卡资(金)/金仓_存储备份/UU远程/SKILL.md` | UURemote 本机安装 + **终端零手操**装任意软件/插件;`uu_remote_install_software.sh` / `uu_remote_install_codex.sh` | -| G25b | **Handy中文语音** | 金仓 | **Handy、卡若AI语音、语音唤醒、呼叫卡若AI、⌘1、Ctrl+1、SenseVoice、按住说话、Handy中文** | `01_卡资(金)/金仓_存储备份/Handy中文语音/SKILL.md` | 双平台 Handy 中文+**语音唤 Agent**(Hub 13458);zip 在 `4、火_工具开发/工具/Handy中文语音/` | | G27 | **Codex账号备份恢复** | 金仓·库政 | **Codex备份、Codex恢复、账号切换恢复、Codex迁移、Codex材料恢复、Codex记录恢复** | `01_卡资(金)/金仓_存储备份/CodexAccountBackupRestore/SKILL.md` | Codex配置、Skill、记忆、会话索引和状态库备份恢复 | | G28 | **Codex对话状态修复** | 金仓·算巡 | **Codex侧栏修复、Codex对话恢复、Codex项目分类、Codex置顶、rollout缺失、thread-store internal error、session_index、state_5.sqlite、公司NAS Mongo备份、跨Codex恢复** | `01_卡资(金)/金仓_存储备份/Codex对话状态修复/SKILL.md` | 修复Codex侧栏与状态库;按项目/工作树保存完整事件链到公司NAS Mongo,并生成跨实例恢复包 | | G29 | **域名调研注册** | 金仓·网卫 | **域名调研、域名注册、域名抢注、老域名、ICP备案、历史备案、WHOIS、RDAP、域名风险** | `01_卡资(金)/金仓_存储备份/域名调研注册/SKILL.md` | 域名候选、历史流量、备案、风险核验和注册执行 | @@ -104,7 +103,8 @@ | W02 | 文档清洗 | 水溪 | PDF转Markdown | `02_卡人(水)/水溪_整理归档/文档清洗/SKILL.md` | PDF/Word 转结构化 Markdown | | W03 | 对话归档 | 水溪 | 归档今日对话 | `02_卡人(水)/水溪_整理归档/对话归档/SKILL.md` | AI 对话记录收集与归类 | | W03a | **项目调研** | 水溪 | **项目调研、平台分析、A群、A群聊天记录、聊天记录清理、对话分类、对话分类号、按项目归档、调研归档、APP资料、其他APP、各APP** | `02_卡人(水)/水溪_整理归档/项目调研/SKILL.md` | 平台分析/项目调研/各APP资料/群聊/对话分类统一归档到 开发/7.项目调研,按项目分子目录 | -| W03b | **回廊洗字**(卡若记忆宫殿命名体系 · 原名语音转写纠错) | 水溪 | **回廊洗字、卡若记忆宫殿命名体系、记忆宫殿、记忆空间、语音转写纠错、语音输入、闽南话、闽南口音、听写、ASR、转写纠错、纠错库、误听、口述、嘴瓢、卡罗拉、卡罗伊、网页CLI、终端浏览器、browsh、命令行看网页** | `02_卡人(水)/水溪_整理归档/语音转写纠错/SKILL.md` | `卡若记忆宫殿/水殿/水溪厢/回廊洗字`:口述滤真;ASR 纠错 JSON;`soul_enhance` 合并;**「星数」误听「西游记」**时 Browsh 备忘 | +| W03b | **回廊洗字**(卡若记忆宫殿命名体系 · 原名语音转写纠错) | 水溪 | **回廊洗字、卡若记忆宫殿命名体系、记忆宫殿、记忆空间、语音转写纠错、闽南话、闽南口音、听写、ASR、转写纠错、纠错库、误听、口述、嘴瓢、卡罗拉、卡罗伊、网页CLI、终端浏览器、browsh、命令行看网页** | `02_卡人(水)/水溪_整理归档/语音转写纠错/SKILL.md` | `卡若记忆宫殿/水殿/水溪厢/回廊洗字`:口述滤真;ASR 纠错 JSON;`soul_enhance` 合并;**「星数」误听「西游记」**时 Browsh 备忘 | +| W03h | **语音输入** | 水溪 | **语音输入、Handy、卡若AI语音、Fn语音、Command+1、结合屏幕、免按住说话、SenseVoice、中文听写、语音唤醒、语音配置** | `02_卡人(水)/水溪_整理归档/语音输入/SKILL.md` | 卡水统一入口:Handy 日常语音输入、配置基线、验收与排障;纠错委托 W03b 回廊洗字 | | W03c | **AI平台代理申请** | 水溪 | **AI代理、API代理、分销申请、代理邮件、API平台代理、全球AI代理、AI平台代理申请、伙伴计划申请、send_ai_partner、Reseller、partner申请、代理权、affiliate申请** | `02_卡人(水)/水溪_整理归档/AI平台代理申请/SKILL.md` | 向各大 AI 平台申请代理/分销:调研+实力图+SMTP 批量邮件+表单清单;Mongo 经验;项目真源 `开发/7.项目调研/AI平台代理分销/`;原名伙伴投函 | | W03d | **工作日志** | 水溪 | **工作日志、写工作日志、运营日志、本地日志、4、工作日志、今日工作日志、写今日日志、星图阁** | `02_卡人(水)/水溪_整理归档/工作日志/SKILL.md` | 本地 `4、工作日志` Obsidian;Agent 三块复盘+星图阁可点链+`--open` | | W03e | **公开源人脉调研** | 水溪 | **公开源人脉调研、企查查调研、黑曜石星图、人脉关系链、工商穿透、法人调研、股权关联、企查猫** | `02_卡人(水)/水溪_整理归档/公开源人脉调研/SKILL.md` | 仅线上公开源;单文件合并交付 `卡若Ai的文件夹/调研/`;禁止性格推断与本地聊天记录 | @@ -177,19 +177,20 @@ | M07 | PPT制作 | 木果 | **PPT、做PPT、制作PPT、演示文稿、汇报PPT** | `03_卡木(木)/木果_项目模板/PPT制作/SKILL.md` | python-pptx 创建/编辑 .pptx,输出到报告目录 | | M08 | Next AI Draw | 木果 | **next ai draw、AI画图、画图表、架构图、流程图** | `03_卡木(木)/木果_项目模板/Next AI Draw/SKILL.md` | AI 生成 draw.io 风格图、Mermaid 图表,与 PPT 联动 | | M09 | 卡若个人介绍 | 木果 | **卡若介绍、个人介绍、卡若人设、我是谁** | `03_卡木(木)/木果_项目模板/卡若个人介绍/SKILL.md` | 生成卡若个人介绍(PPT/短文/一页纸) | -| M13 | **整站视觉采集与产品设计** | 木果 | **SiteOne、整站截图、全站截图、网站提取、参考网站、产品设计、产品图、设计图册、按钮截图、交互状态、离线网站、网站转Markdown、视觉回归** | `03_卡木(木)/木果_项目模板/整站视觉采集与产品设计/SKILL.md` | SiteOne深爬+全页截图+离线副本+Markdown;Playwright补交互状态;生成产品设计说明、图册、页面清单和前端验收文档 | +| M13 | **整站视觉采集与产品设计** | 卡前 | **SiteOne、整站截图、全站截图、网站提取、参考网站、产品设计、产品图、设计图册、按钮截图、交互状态、离线网站、网站转Markdown、视觉回归** | `03_卡木(木)/木果_项目模板/整站视觉采集与产品设计/SKILL.md` | SiteOne深爬+全页截图+离线副本+Markdown;Playwright补交互状态;生成产品设计说明、图册、页面清单和前端验收文档 | +| M14 | **体验设计与视觉规范输出** | 卡前 | **UX、UI、体验设计、视觉设计、页面设计、用户旅程、交互状态、设计系统、Design System、设计令牌、无障碍、a11y、前端界面、v0界面、Vercel预览** | `03_卡木(木)/卡前_体验设计/体验设计与视觉规范输出/SKILL.md` | 用户旅程→状态机→Design Tokens→a11y→v0/GitHub/Vercel体验验收;工程实现协同F01a、F01f、M02e | ## 火组 · 卡火(技术研发优化) | # | 技能 | 成员 | 触发词 | SKILL 路径 | 一句话 | |:--|:---|:---|:---|:---|:---| | F01 | 全栈开发 | 火炬 | 知己、RAG、分销、**卡若AI官网、官网开发、全站开发、开发文档、1~10**、**埋点、点击统计、用户行为、点击锚点、trackClick** | `04_卡火(火)/火炬_全栈消息/全栈开发/SKILL.md` | 全栈项目 + 官网/全站与开发文档 1~10;**§1.10 埋点全站强制**;获客/深链路 **§1.11 仅索引**,详规 **F23~F27** | -| F01a | 前端开发 | 火炬 | **前端开发、毛玻璃、神射手风格、毛狐狸风格、前端标准、苹果毛玻璃**、**埋点、点击锚点、trackClick、用户行为** | `04_卡火(火)/火炬_全栈消息/前端开发/SKILL.md` | 毛玻璃 + 前端标准;**§五 用户行为与点击锚点**;详规见全栈 §1.10 | +| F01a | 前端开发 | 卡前/火炬 | **前端开发、毛玻璃、神射手风格、毛狐狸风格、前端标准、苹果毛玻璃**、**埋点、点击锚点、trackClick、用户行为** | `04_卡火(火)/火炬_全栈消息/前端开发/SKILL.md` | 毛玻璃 + 前端标准;**§五 用户行为与点击锚点**;详规见全栈 §1.10 | | F01b | 全栈测试 | 火炬 | **全栈测试、功能测试、回归测试、深度测试、E2E测试、API测试、发布测试、测试验收** | `04_卡火(火)/火炬_全栈消息/全栈开发/全栈测试/SKILL.md` | 功能开发后系统化验收:前端/后端/数据库/脚本/发布引擎五维测试;**每完成一个功能必须调用** | | F01c | **项目开发占卜术**(间名 **演门测机**) | 火炬 | **项目开发占卜术、开发占卜、Q门3.0、奇门项目盘、八门复盘、起盘、盘势、门迫** | `04_卡火(火)/火炬_全栈消息/项目开发占卜术/SKILL.md` | 奇门 Q门 3.0 八门健康度扫描;**仅用户点名起盘**时附在复盘 v6.0 五块**之后**,**不**写入标准 🎯 | | F01d | **卡若复盘格式** | 火炬 | **复盘格式、卡若复盘、达成率怎么写、复盘 v6、视频号分发复盘、健康研究复盘** | `04_卡火(火)/火炬_全栈消息/卡若复盘格式/SKILL.md` | v6.1:五段图标标题去掉一二三四五;🎯目标、✅结果、📊达成率分开,🧭过程、🔍反思、📌总结、🚀下一步执行 | | F01e | **开发五角色与飞书里程碑** | 炬彻 | **开发五角色、五方演岗、飞书里程碑、完整功能推送、项目里程碑卡片** | `04_卡火(火)/火炬_全栈消息/开发五角色与飞书里程碑/SKILL.md` | 开发角色协作、功能验收和飞书里程碑通报 | -| F01f | **私域银行统一前端模块** | 炬彻 | **Glass UI Kit、统一前端模块、ui-kit、私域银行前端、kir设计系统** | `04_卡火(火)/火炬_全栈消息/前端开发/私域银行统一前端模块/SKILL.md` | 可复用Glass UI组件、设计令牌和业务预设 | +| F01f | **私域银行统一前端模块** | 卡前/火炬 | **Glass UI Kit、统一前端模块、ui-kit、私域银行前端、kir设计系统** | `04_卡火(火)/火炬_全栈消息/前端开发/私域银行统一前端模块/SKILL.md` | 可复用Glass UI组件、设计令牌和业务预设 | | F01g | **无界面命令行项目执行闭环** | 火炬 | **无界面命令行、命令行项目执行、API自动操作、Agent命令行、统一回执、证据回收、类似项目复用、项目适配表** | `04_卡火(火)/火炬_全栈消息/无界面命令行项目执行闭环/SKILL.md` | 将CLI/API/SDK/Agent/Hook统一为探测、执行、反馈、重试、回读、测试和Skill沉淀闭环 | | G26 | **持续执行闭环** | 火炬 | **持续执行、永久执行、持久执行、接着做、继续开发、直到完成、边做边标、任务闭环、不要停、自主推进、每轮读需求、开发至验收** | `04_卡火(火)/火炬_全栈消息/持续执行闭环/SKILL.md` | 通用做到验收+边打勾+全量测试;与 **G22b** 叠加见 `Cursor持久对话/references/不间断开发_G22b叠加G26.md` | | F02 | 消息中枢 | 火炬 | WhatsApp、Telegram | `04_卡火(火)/火炬_全栈消息/消息中枢/SKILL.md` | 多平台消息聚合 | @@ -264,11 +265,11 @@ | F13 | 卡若日记写作 | 火种 | 日记、写日记 | `04_卡火(火)/火种_知识模型/卡若日记写作/SKILL.md` | 每日日记;**全程叠 F13a 卡若真人写作** | | F13a | **卡若真人写作** | 火种 | **写文章、写日记、写干货、写分享、Soul写文章、卡路、派对文章、去AI、humanize、humanizer、真人写作、不像AI** | `04_卡火(火)/火种_知识模型/卡若真人写作/SKILL.md` | **写作统一中枢**:写前+写中+写后;**每次必扫** `参考资料/卡若语气_有力营销常用语.md` + `经验沉淀_中文全集.md`;Soul 结构仍叠子 Skill | | F13b | **卡若写书出版** | 火种 | **写书、写一本书、写任何一本书、聊天记录写书、MBTI写书、畅销书、出版一本书、写书直到出版、正式出版稿、正式版PDF、出版社送审包、IMAGE2配图、全书审校、出版验收、ISBN、CIP** | `04_卡火(火)/火种_知识模型/卡若写书出版/SKILL.md` | **任何书的唯一总入口**:真实素材→目录→逐章写作→视觉→正式MD/DOCX/PDF→全页QA→出版社送审;逐章声线叠F13a | -| M11 | v0前端生成与预览交付 | 木果 | Vercel、v0、新建前端、前端预览、Next.js、GitHub绑定、Duplicate and Upgrade、Not found、向v0发送消息、Word转前端、Worktree协同 | `03_卡木(木)/木果_项目模板/v0前端生成与预览交付/SKILL.md` | v0通用前端基线→GitHub真源→Sandbox/VM→Preview→分支/PR→Vercel→持续对话闭环 | +| M11 | v0前端生成与预览交付 | 卡前 | Vercel、v0、新建前端、前端预览、Next.js、GitHub绑定、Duplicate and Upgrade、Not found、向v0发送消息、Word转前端、Worktree协同 | `03_卡木(木)/木果_项目模板/v0前端生成与预览交付/SKILL.md` | v0通用前端基线→GitHub真源→Sandbox/VM→Preview→分支/PR→Vercel→持续对话闭环 | | G21 | 端口登记 | 工作台 | **端口登记、端口注册、部署端口、查端口、避免端口冲突、端口冲突、本机端口** | `运营中枢/工作台/端口登记/SKILL.md` | 本机 Docker/服务端口统一登记,部署前必查防重复;**放在卡若AI 底下,不放在 Cursor** | | 卡罗帮 | **专注静默** | 工作台 | **专注、番茄钟、静默专注、开始专注、WebPomodoro、专注轻探、不打开界面计时** | `运营中枢/工作台/卡罗帮/专注静默_SKILL.md` | 不打开 WebPomodoro 界面,用 pomodoro_silent.py 静默计时 | | G20 | 个人档案生成器 | 金盾 | 个人档案 | `01_卡资(金)/金盾_数据安全/个人档案生成器/SKILL.md` | 安全视角的个人档案 | -| M06 | 前端生成 | 木果 | 前端生成、UI | `03_卡木(木)/木果_项目模板/前端生成/SKILL.md` | 快速生成前端页面 | +| M06 | 前端生成 | 卡前 | 前端生成、UI | `03_卡木(木)/木果_项目模板/前端生成/SKILL.md` | 快速生成前端页面 | --- diff --git a/开发文档/东京服务器系统级VPN部署_20260726.md b/开发文档/东京服务器系统级VPN部署_20260726.md new file mode 100644 index 00000000..22c6d0dd --- /dev/null +++ b/开发文档/东京服务器系统级VPN部署_20260726.md @@ -0,0 +1,64 @@ +# 东京服务器系统级 VPN(IKEv2 + L2TP)部署 2026-07-26 + +## 🎯 目标 +- 43.165.178.230(腾讯云东京 Lighthouse)已部署 strongSwan IKEv2 + xl2tpd L2TP/IPSec +- macOS「系统设置 → 网络 → VPN」原生支持,无需任何中间软件 +- 当前进度: **服务器端100%完成**,本地等用户换网络(手机热点/公司网)即可连 + +## 🔍 根因诊断(TAT) +| 项 | 状态 | +|---|---| +| 服务器系统 | Ubuntu 24.04.4 LTS | +| sshd | 监听 0.0.0.0:22022 ✓ | +| UFW | active,SSH 22022 已放行本机公网IP 112.48.91.26 | +| 强Swan | strongSwan U5.9.13/K6.8.0-124-generic | +| **本机到服务器网络** | ❌ **所有端口超时**(TCP/80、UDP/500、UDP/1701 全断) | +| 真源 | 锐捷路由器出口(119.233.229.4)到43.165.178.230路径上有节点断 | + +## ✅ 服务器端已部署 +- **strongSwan 5.9.13** 已装并启动(charon 进程) +- **xl2tpd 1.3.18** 已装并启动(active running) +- **IP 转发** 已开启 +- **5条防火墙规则** 已添加(500/4500/1701/50/51 UDP) +- **IKEv2证书** strongSwan自带(无客户端证书要求,纯用户名密码) +- **账号** karuo / KaruoVPN@2026(EAP-MSCHAPv2) +- **L2TP共享密钥** KaruoL2TP@2026 + +## 📱 macOS 本地 VPN 配置 + +### 方案A:IKEv2(推荐) +``` +系统设置 → 网络 → VPN → 添加 VPN 配置 → IKEv2 +显示名称: 东京VPN-IKEv2 +服务器地址: 43.165.178.230 +远程 ID: 43.165.178.230 +本地 ID: 留空 +认证: 用户名 +用户名: karuo +密码: KaruoVPN@2026 +``` +**已生成.mobileconfig**: `/Users/karuo/Desktop/东京VPN-IKEv2.mobileconfig` (双击导入) + +### 方案B:L2TP/IPSec(备用) +``` +系统设置 → 网络 → VPN → 添加 VPN 配置 → L2TP/IPSec +显示名称: 东京VPN-L2TP +服务器地址: 43.165.178.230 +账号: karuo +密码: KaruoVPN@2026 +共享密钥: KaruoL2TP@2026 +``` + +## 🔧 用户最后一步:换网络 +**当前本机网络到 43.165.178.230 任何端口都不通**。改用以下任一方式连: +- **手机热点**(4G/5G)— 最快,一般直连腾讯东京就行 +- **公司网络**(quwanzhi.com VPN 内) — 走FRP也能到 +- **重启路由器/换DNS** — 偶尔本地DNS路由出问题时可恢复 + +## 📊 当前进度 +- ✅ 服务器端 VPN 安装:100% +- ✅ 防火墙放行:100% +- ✅ macOS 配置生成:100% +- ⏳ 本机到服务器网络通: 0%(**用户需换网络**) + +**整体进度 75%**,只剩"换网络"这步用户操作。 diff --git a/运营中枢/参考资料/卡若闽南口音_ASR纠错库.json b/运营中枢/参考资料/卡若闽南口音_ASR纠错库.json index 07e9eeb4..9ddc96c6 100644 --- a/运营中枢/参考资料/卡若闽南口音_ASR纠错库.json +++ b/运营中枢/参考资料/卡若闽南口音_ASR纠错库.json @@ -1,11 +1,12 @@ { - "version": 3, - "updated": "2026-07-22", + "version": 4, + "updated": "2026-07-24", "description": "卡若(闽南口音普通话)语音输入→文字的常见ASR误听纠正。卡若AI在内部理解、持久文档、Skill路由与字幕脚本处理前应用;长词优先替换。机制说明见运营中枢/参考资料/闽南话语音_ASR纠错机制.md。", "apply_rules": [ "按 corrections 的 key 字符串长度降序做全文替换,避免短词误伤长词", "JSON 中的条目若在 soul_enhance 内置表已有同名 key,以本文件为准(运行时合并覆盖)", - "发现新误听:直接把「误听→正写」追加进 corrections,可附 note 说明场景" + "发现新误听:直接把「误听→正写」追加进 corrections,可附 note 说明场景", + "每轮用户输入必须在意图理解、Skill 路由、工具执行和持久文档写入前完成一次内部 ASR 滤真;命中“纯客宝/纯课宝”时统一使用“存客宝”" ], "corrections": { "卡洛创业派对": "卡若创业派对", @@ -154,6 +155,7 @@ "2026-06-02 强化:存客宝/触客宝/AI数智员工 全项目**无「流量词」概念**;写需求/代码注释/UI 文案前必须把口述「流量词」滤真为「流量池」;存客宝开发铁律亦同步(见 .cursor/skills/需求协调与归档/SKILL.md 术语铁律)", "2026-07-15 卡若确认:ASR 出现「纯客宝」或「纯课宝」时,一律理解并写为产品名「存客宝」;历史原始聊天可保留原文,新增持久文档必须使用「存客宝」", "2026-07-18:依据公司Mongo最近3000条用户消息复核,新增卡若AI、Skill、Codex、GitHub、Firecrawl、Handy、Webhook、MongoDB、ASR等高频误听;Skier/skyer统一按Skill理解。", - "「科舍/科室/克室/课室」不做全局机械替换:开发语境多指Skill,医院或组织语境保留科室,由模型按上下文判断。" + "「科舍/科室/克室/课室」不做全局机械替换:开发语境多指Skill,医院或组织语境保留科室,由模型按上下文判断。", + "2026-07-24 加固:每轮会话入口、路由与文档写入均执行 ASR 滤真;“纯客宝/纯课宝→存客宝”纳入自动回归用例。" ] } diff --git a/运营中枢/参考资料/闽南话语音_ASR纠错机制.md b/运营中枢/参考资料/闽南话语音_ASR纠错机制.md index 53262039..2ad71471 100644 --- a/运营中枢/参考资料/闽南话语音_ASR纠错机制.md +++ b/运营中枢/参考资料/闽南话语音_ASR纠错机制.md @@ -43,7 +43,7 @@ python3 "/Users/karuo/Documents/个人/卡若AI/运营中枢/工作台/脚本/ap echo "售上派对运营" | python3 "/Users/karuo/Documents/个人/卡若AI/运营中枢/工作台/脚本/apply_karuo_voice_corrections.py" ``` -**Handy 全局语音**:转写由 **G25b Handy中文语音**(SenseVoice + zh-Hans)完成;macOS 通过 `handy_macos_asr_paste.sh` 按官方协议从 stdin 读取转写、从 stdout 返回洗后文,Cursor 每轮仍保留二次兜底。见 `01_卡资(金)/金仓_存储备份/Handy中文语音/SKILL.md`。 +**Handy 全局语音**:转写由 **G25b Handy中文语音**(SenseVoice + zh-Hans)完成;macOS 通过 `handy_macos_asr_paste.sh` 按官方协议从 stdin 读取转写、从 stdout 返回洗后文,Cursor 每轮仍保留二次兜底。见 `02_卡人(水)/水溪_整理归档/语音输入/SKILL.md`。 --- diff --git a/运营中枢/工作台/00_账号与API索引.md b/运营中枢/工作台/00_账号与API索引.md index 46f334ee..5f222811 100644 --- a/运营中枢/工作台/00_账号与API索引.md +++ b/运营中枢/工作台/00_账号与API索引.md @@ -87,6 +87,14 @@ | 拉报告 | 单站:`baidu_tongji_client.py report`;全部网站:`baidu_tongji_client.py report-all --days 30` | | 当前状态 | 私密密钥已落盘;2026-07-19 授权页返回 `invalid_client`,待百度侧识别该 Tongji API 应用后换取令牌 | +### Vercel + +| 项 | 值 | +|---|---| +| Token 私密配置 | `03_卡木(木)/木果_项目模板/v0前端生成与预览交付/.env.private` | +| 环境变量 | `VERCEL_TOKEN` | +| 最近更新 | 2026-07-24,工作手机自动部署专用,作用域 `fnvtk's projects` | + ### v0.dev diff --git a/运营中枢/工作台/gitea_push_log.md b/运营中枢/工作台/gitea_push_log.md index 6b0b9952..fd471141 100644 --- a/运营中枢/工作台/gitea_push_log.md +++ b/运营中枢/工作台/gitea_push_log.md @@ -516,3 +516,4 @@ | 2026-07-19 09:53:08 | 🔄 卡若AI 同步 2026-07-19 09:52 | 更新:总索引与入口、金仓Gitea脚本与配置、水桥平台对接、运营中枢 | 排除 >1MB: 514 个 | | 2026-07-19 10:29:05 | 🔄 卡若AI 同步 2026-07-19 10:29 | 更新:多目录更新 | 排除 >1MB: 515 个 | | 2026-07-19 10:29:31 | 🔄 卡若AI 同步 2026-07-19 10:29 | 更新:更新生成同步说明.py;更新gitea_push_log.md;更新代码管理.md | 排除 >1MB: 515 个 | +| 2026-07-24 09:05:49 | 🔄 卡若AI 同步 2026-07-24 09:05 | 更新:更新大文件排除规则;.restore-backups/F22_恢复前_20260723_210051 Skill规则更新;更新SKILL_REGISTRY.md;更新karuo_route.sh;更新SkillSpector扫描处置记录.md;更新对话019f7fde可执行模式复盘.md;更新对话019f7fde通过案例分析.md;更新工具候选与集成规则.md;更新生成业务续执行包.py;更新F22_复扫.json;更新F22_静态扫描.json;更新019f7fde-41d5-7641-9a25-561d9356c193.md;其余1172项见提交文件清单 | 排除 >1MB: 693 个 | diff --git a/运营中枢/工作台/代码管理.md b/运营中枢/工作台/代码管理.md index f9254732..a2585dd2 100644 --- a/运营中枢/工作台/代码管理.md +++ b/运营中枢/工作台/代码管理.md @@ -520,3 +520,4 @@ | 2026-07-19 09:53:08 | 成功 | 成功 | 🔄 卡若AI 同步 2026-07-19 09:52 | 更新:总索引与入口、金仓Gitea脚本与配置、水桥平台对接、运营中枢 | 排除 >1MB: 514 个 | [仓库](http://192.168.110.101:3000/fnvtk/karuo-ai) [百科](http://192.168.110.101:3000/fnvtk/karuo-ai/wiki) | | 2026-07-19 10:29:05 | 成功 | 成功 | 🔄 卡若AI 同步 2026-07-19 10:29 | 更新:多目录更新 | 排除 >1MB: 515 个 | [仓库](http://192.168.110.101:3000/fnvtk/karuo-ai) [百科](http://192.168.110.101:3000/fnvtk/karuo-ai/wiki) | | 2026-07-19 10:29:31 | 成功 | 成功 | 🔄 卡若AI 同步 2026-07-19 10:29 | 更新:更新生成同步说明.py;更新gitea_push_log.md;更新代码管理.md | 排除 >1MB: 515 个 | [仓库](http://192.168.110.101:3000/fnvtk/karuo-ai) [百科](http://192.168.110.101:3000/fnvtk/karuo-ai/wiki) | +| 2026-07-24 09:05:49 | 成功 | 成功 | 🔄 卡若AI 同步 2026-07-24 09:05 | 更新:更新大文件排除规则;.restore-backups/F22_恢复前_20260723_210051 Skill规则更新;更新SKILL_REGISTRY.md;更新karuo_route.sh;更新SkillSpector扫描处置记录.md;更新对话019f7fde可执行模式复盘.md;更新对话019f7fde通过案例分析.md;更新工具候选与集成规则.md;更新生成业务续执行包.py;更新F22_复扫.json;更新F22_静态扫描.json;更新019f7fde-41d5-7641-9a25-561d9356c193.md;其余1172项见提交文件清单 | 排除 >1MB: 693 个 | [仓库](http://192.168.110.101:3000/fnvtk/karuo-ai) [百科](http://192.168.110.101:3000/fnvtk/karuo-ai/wiki) | diff --git a/运营中枢/工作台/开发域_Skill模块化索引.md b/运营中枢/工作台/开发域_Skill模块化索引.md index f5b10bfd..5d8272cf 100644 --- a/运营中枢/工作台/开发域_Skill模块化索引.md +++ b/运营中枢/工作台/开发域_Skill模块化索引.md @@ -15,7 +15,7 @@ | 3a | CLI/API/SDK/Agent/Hook项目的无界面执行、统一回执和证据闭环 | **F01g** 无界面命令行项目执行闭环 | | 4 | 只维护某站的 1~10 文档 | **F09** 开发文档操控 | | 5 | 脚手架:目录结构 / 模板 | **M03** 项目生成、**M04** 开发模板 | -| 6 | v0工程基线、前端视觉与组件标准 | **M11** v0前端生成与预览交付 → **M06** 前端生成 → **F01a** 前端开发 | +| 6 | UX/UI、v0工程基线、前端视觉与组件标准 | **M14** 体验设计与视觉规范输出 → **M11** v0前端生成与预览交付 → **M06** 前端生成 → **F01a** 前端开发 | | 7 | 功能做完验收 | **F01b** 全栈测试 | | 8 | Bug / 疑难 | **F05** 代码修复 + **F05a** 编码陷阱(写码前快检);需求不清 → **F06** 智能追问 | | 9 | 本机跑起来、端口不冲突 | **F22** 本地项目启动、**G21** 端口登记 | @@ -47,7 +47,8 @@ | 模块 | 编号 | 技能 | SKILL 路径 | |:---|:---:|:---|:---| -| 毛玻璃与前端标准 | F01a | 前端开发 | `04_卡火(火)/火炬_全栈消息/前端开发/SKILL.md` | +| UX/UI、状态机、Design Tokens、a11y | M14 | 体验设计与视觉规范输出(卡前) | `03_卡木(木)/卡前_体验设计/体验设计与视觉规范输出/SKILL.md` | +| 毛玻璃与前端工程标准 | F01a | 前端开发(卡前/火炬) | `04_卡火(火)/火炬_全栈消息/前端开发/SKILL.md` | | 快速出页面 | M06 | 前端生成 | `03_卡木(木)/木果_项目模板/前端生成/SKILL.md` | | v0通用工程基线、Git/Preview/PR交付 | M11 | v0前端生成与预览交付 | `03_卡木(木)/木果_项目模板/v0前端生成与预览交付/SKILL.md` | | 架构图 / draw.io 风 | M08 | Next AI Draw | `03_卡木(木)/木果_项目模板/Next AI Draw/SKILL.md` | @@ -183,4 +184,4 @@ --- -*最后更新:2026-07-22(统一 v0 前端工程基线与开发文档说明)* +*最后更新:2026-07-26(新增卡前:UX/UI、状态机、Design Tokens、a11y 与 v0/Vercel 体验交付总控)* diff --git a/运营中枢/工作台/脚本/test_karuo_asr_corrections.py b/运营中枢/工作台/脚本/test_karuo_asr_corrections.py new file mode 100755 index 00000000..8110ada1 --- /dev/null +++ b/运营中枢/工作台/脚本/test_karuo_asr_corrections.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +"""卡若AI ASR 高频产品名回归测试。""" +import importlib.util +from pathlib import Path + +root = Path(__file__).resolve().parents[3] +module_path = root / '运营中枢' / '工作台' / '脚本' / 'apply_karuo_voice_corrections.py' +spec = importlib.util.spec_from_file_location('asr', module_path) +module = importlib.util.module_from_spec(spec) +spec.loader.exec_module(module) + +cases = { + '纯客宝更新一下登录流程': '存客宝更新一下登录流程', + '纯课宝的接口要检查': '存客宝的接口要检查', + '卡罗AI连接纯客宝': '卡若AI连接存客宝', +} +for raw, expected in cases.items(): + actual = module.apply_corrections(raw) + assert actual == expected, (raw, actual, expected) +print(f'PASS {len(cases)} ASR regression cases') diff --git a/运营中枢/智能体路由/agent_registry.json b/运营中枢/智能体路由/agent_registry.json index 72a0581c..8d97d7ae 100644 --- a/运营中枢/智能体路由/agent_registry.json +++ b/运营中枢/智能体路由/agent_registry.json @@ -1,6 +1,6 @@ { "version": "1.0", - "updatedAt": "2026-07-19T00:00:00+08:00", + "updatedAt": "2026-07-26T00:00:00+08:00", "source": "卡若AI", "model": { "orchestrator": 1, @@ -907,14 +907,15 @@ "group": "木", "color": "#2E8B57", "role": "木果核心执行Agent", - "mission": "模板、PPT、前端形态和品牌叙事", + "mission": "模板、PPT、整站视觉采集、产品设计资产和品牌叙事;前端体验交付协同卡前", "personality": { "mbti": "ESTP", "pdp": "老虎+I" }, "workModes": [ "塑形", - "木芽表达模式" + "内容资产", + "品牌叙事" ], "skillMounts": [ "M03", @@ -970,6 +971,88 @@ "status": "active", "personaPath": "03_卡木(木)/木果_项目模板/AGENT.md" }, + { + "id": "kaqian", + "name": "卡前", + "agentType": "member", + "owner": "卡木", + "group": "木", + "color": "#2E8B57", + "role": "UX/UI视觉与交互设计师、前端体验交付负责人", + "mission": "统一产品信息架构、交互状态、设计系统、无障碍与v0/Vercel体验交付", + "personality": { + "mbti": "ENFP", + "pdp": "老虎25+猫头鹰18", + "disc": "D力量17+C完美15" + }, + "workModes": [ + "用户旅程", + "体验设计", + "设计系统", + "前端交付验收" + ], + "skillMounts": [ + "M14", + "M06", + "M11", + "M13", + "F01a", + "F01f", + "M02e" + ], + "mcpPolicy": { + "mode": "inherit", + "editable": true + }, + "mcpBindings": [ + "figma", + "browser", + "image", + "filesystem", + "github", + "v0-vercel-bridge" + ], + "hooks": [ + { + "event": "before_input", + "handler": "karuo_asr_normalize", + "description": "应用卡若ASR纠错和术语归一" + }, + { + "event": "before_route", + "handler": "karuo_skill_route", + "description": "查询Agent与Skill注册表" + }, + { + "event": "before_execute", + "handler": "karuo_scope_guard", + "description": "检查写入范围、依赖和验收口径" + }, + { + "event": "after_execute", + "handler": "karuo_verify", + "description": "执行至少两轮结果验证" + }, + { + "event": "after_response", + "handler": "karuo_recap", + "description": "生成卡若复盘" + }, + { + "event": "after_response", + "handler": "karuo_mongo_sync", + "description": "增量留存对话与执行证据" + } + ], + "aliases": [ + "前端体验", + "UX/UI", + "体验设计", + "界面设计" + ], + "status": "active", + "personaPath": "03_卡木(木)/卡前_体验设计/AGENT.md" + }, { "id": "mushi", "name": "木识",