呼叫 Miharu · 安装说明
已有签名导入包:下载「呼叫 Miharu」。用 Safari 下载后打开文件,添加时填写设备令牌。下方手动搭建步骤保留作备用。
返回 · 逻辑源文件(非安装包)
# 呼叫 Miharu:文字对话与截图分享
服务地址:https://miharu.linerrofak.men
第一版提供文字对话、发送一张图片、截图分享,以及本次对话内继续追问。沿用现有微信 Miharu 的上下文,回复只在快捷指令显示,不另发微信。iPhone/iPad 的真实交互仍需在设备上验收。
## 安装准备
在 iPhone「快捷指令」中新建,名称为「呼叫 Miharu」。进入快捷指令详细信息,开启「在共享表单中显示」,输入类型只保留「图像」,没有输入时选择「继续」。可添加到主屏幕或快捷指令小组件。
优先使用[签名导入包](https://miharu.linerrofak.men/call-miharu-waitfix.shortcut):Safari下载后打开文件,添加到快捷指令,安装时填写设备令牌。经主人明确授权,模板已由RoutineHub HubSign签名;解包核对确认167个动作、安装问题和功能配置与原模板一致,仅四项导出元数据变化。模板不含设备令牌或聊天内容。首次在iPhone/iPad实际导入及运行仍待设备确认。下方逐动作搭建步骤保留作备用。`shortcuts-public/shortcut-source.json`仍是逻辑源JSON,本身不是安装包。
设备令牌见本机私有文件 `state/SHORTCUTS-SETUP-PRIVATE.md`,不要把带令牌的快捷指令公开分享。手机使用 iphone 令牌;iPad 可复制快捷指令后替换为 ipad 令牌。iCloud 同步的是快捷指令内容;设备使用同一个令牌也能运行,但不能分别撤销。
## 一、准备变量和图片入口
以下反引号中的名字是需要创建的变量名,不是让你输入方括号文字。动作名称因系统版本可能略有区别。
1. 添加「文本」动作,填 `https://miharu.linerrofak.men`,接「设定变量」,命名 `服务器`。
2. 添加「文本」,填私有文件中的设备令牌,接「设定变量」,命名 `令牌`。
3. 添加一个空白「文本」,接「设定变量」为 `图片编码`。如果空文本动作不能添加,用「无」动作,再设定变量。
4. 添加「数字」值 `0`,设定变量 `已经完成`。
5. 添加「如果」:条件为「快捷指令输入」有任何值。
- 添加「计数」,输入明确指定为「快捷指令输入」。如果计数大于 1,显示提醒“每次请分享一张图片”,接「停止此快捷指令」。
- 将「快捷指令输入」设为变量 `待发图片`。
- 「要求输入」:文本,提示“想让 Miharu 看什么?”,默认答案“请帮我看看这张图片。”;输出设为 `问题`。
6. 在第5步的「否则」分支添加「从菜单中选取」,提示“呼叫 Miharu”,两个项目:
- **文字对话**:「要求输入」文本,提示“想和 Miharu 说什么?”,输出设为 `问题`。留空时提醒“请输入问题”并停止。
- **发送图片**:「选择照片」,关闭多选,输出设为 `待发图片`;「要求输入」文本,默认答案“请帮我看看这张图片。”,输出设为 `问题`。
7. 结束菜单和「如果」。添加「如果 待发图片 有任何值」:
- 「调整图像大小」,输入指定为 `待发图片`,宽度 `2560`、高度自动。
- 「转换图像」,转换为 JPEG,质量约 85%,关闭保留元数据。
- 「Base64 编码」,输入指定为转换后的图像;展开设置,换行选择「无」。
- 结果设为变量 `图片编码`。
- 结束「如果」。
服务器接受 PNG、JPEG、WebP;快捷指令统一转换 JPEG,以兼容 iPhone/iPad 照片。服务器上限10 MiB、2000万像素;转换后仍超限时会明确拒绝。
## 二、发送与等待
在以上动作之后添加外层「重复」100次,表示同次启动最多100轮问答;下面所有动作都放在这一层里面。
8. 「生成 UUID」,输出设为 `请求编号`。
9. 「获取 URL 内容」,URL填写 `服务器`变量后接 `/api/requests`:
- 方法 POST。
- 标头:`Authorization` = 文本 `Bearer ` 后插入 `令牌`变量(Bearer 后有一个空格)。
- 请求体 JSON,三个字段都选「文本」类型:`requestId` → `请求编号`变量;`text` → `问题`变量;`imageBase64` → `图片编码`变量。不要把变量名当普通文字输入,不要手拼 JSON。
10. 从响应「获取字典值」,键 `id`,设为 `任务编号`。如果没有值,显示响应中的 `error`(没有error时提示“网络或服务异常”)并停止,避免重复发送。
11. 添加「数字」0,设变量 `已经完成`。添加第二层「重复」100次,作为等待窗口;其内部:
- 添加第三层「重复」30次。第三层内部先判断 `已经完成` 等于0,只有等于0才执行下面查询。
- 「等待」2秒。
- 「获取 URL 内容」,GET `服务器` + `/api/requests/` + `任务编号`;标头同上。
- 获取字典键 `status` → `任务状态`;获取 `reply` → `回答`。
- 如果 `任务状态` 为 `completed`,数字1设为 `已经完成`。
- 如果 `任务状态` 为 `failed`,显示 `回答` 与响应 `error`,然后停止。
- 如果响应有 `error`,显示这个错误并停止。若网络动作本身报错,请结束本次运行;不要反复点击POST。
- 结束第三层「重复」。
- 如果 `已经完成` 仍为0,「从菜单中选取」:“仍在处理中”,选项「继续等待」(不添加动作)、「结束」(停止此快捷指令)。继续等待会查询同一个任务,不会重新提交。
- 如果 `已经完成` 为1:
- 「显示结果」内容为变量 `回答`。
- 「从菜单中选取」:“还想说什么?”,选项「继续追问」「结束」。
- 「继续追问」分支:要求文本输入、输出设为 `问题`;添加空文本或「无」,设 `图片编码` 为空;数字2设为 `已经完成`。
- 「结束」分支:停止此快捷指令。
- 第二层每一轮开头包一层「如果 已经完成 不等于2」;将本层查询和等待、显示回答动作全部放进去。这样已输入追问后剩余空轮次跳过,随后进入外层下一轮提交。
12. 结束第二层、外层「重复」。最后添加「停止此快捷指令」。
这里一分钟是约一分钟的主动等待窗口,网络耗时另计。结束等待不会取消服务器上的任务,也不会执行任何“批准”。第一版不提供任务历史菜单,结束后可在 Rakazo 中查看会话;下次启动仍沿用同一个微信 Miharu 上下文。
## 三、使用与验收
- 点桌面「呼叫 Miharu」→文字对话→问一个问题→看到答案→继续追问,核对能承接上一句。
- 点发送图片,选一张题目图并提问,核对她确实读取了附件。
- 正常截图→打开截图分享菜单→选择「呼叫 Miharu」→补充问题→查看回答。
- 一次分享两张图片应在上传前提示仅支持单图;取消选择或取消输入应终止,不发送空问题。
- 将令牌改错应明确提示鉴权失败;等待结束不应造成重复提交。
- 微信正常聊天后,从快捷指令询问此前话题,核对共用上下文;快捷指令答案不应自动发到微信。
- 在iPad同步/复制配置后重复单图分享测试。设备未实测前不得写成“已在iPhone/iPad验证”。
## API
`GET /health` 返回存活状态。其他业务接口必须带 `Authorization: Bearer <device-token>`。
`POST /api/requests` JSON:
```json
{"requestId":"客户端每轮生成的UUID","text":"问题","imageBase64":"可选的图片Base64,不含data前缀;纯文字时空字符串"}
```
返回HTTP202,包含 `id`、`status`、`reply`、`error`、`retryAfterSeconds`。`GET /api/requests/{id}` 返回相同结构。状态为 `queued`、`processing`、`completed`、`failed`。同一设备、同一请求编号与相同正文重试只返回原任务;正文改变则409。另一个设备令牌不能读取该任务。
提交每设备每分钟12次;查询每设备每分钟180次;总待处理任务上限20。网络断开后不能另生成编号盲目重发。服务器不下载客户端提供的网址,不接受任意 botId、终端命令或审批参数。
## 运维与回退
公网入口使用自有域名的Pages Functions前门及Workers SQLite Durable Object任务队列;仅 `miharu.linerrofak.men` 的CNAME设为DNS-only、指向Pages,域名全局Bot Fight Mode及其他站点代理设置保持开启。Ubuntu通过本机已验证的HTTP代理每3秒主动领取任务并用Ed25519签名回传结果,不经过原域名的Bot Fight Mode。云端图片分块暂存,结果回传成功后清除云端图片副本;会话和附件保留在本机Rakazo。云端保留任务状态及回答以供查询。
本机网关嵌入 `rakazo-ilink-bridge.service`,监听 `127.0.0.1:18083`,用于本机检查和文档;同一进程负责微信与快捷指令任务,串行调用现有 `weixin:owner` bot。状态保存在既有私有SQLite中,上传完成后清掉第二份Base64副本,Rakazo附件仍保留。Ubuntu离线、桥服务停止或本机代理不可用时,云端请求将排队,不会显示成已完成。
`state/shortcuts-devices.json` 只存设备标识与令牌SHA256。将某设备 `revoked` 改为 `true` 后,本机网关立即拒绝;在线中转客户端会在下一轮同步至Workers(通常数秒),无需重启;私有原始令牌只在 `state/shortcuts-setup-private.json` 和私有安装说明中。新设备令牌应重新随机生成并替换哈希,不公开。
只关闭公网快捷指令入口:在Pages中解除本次新增自有域名绑定,并移除本次API域名的DNS记录;如也停用workers.dev路由则Ubuntu取任务会停止,队列数据保留;移走本机 `state/shortcuts-relay.json` 并重启微信桥以停止轮询。只关闭本机网关则移走设备配置文件并重启。取消域名映射时只移除本次新增域名对应的Tunnel ingress/DNS。完整回退用 `../backups/before-shortcuts-*` 的代码和Tunnel配置备份;不要用旧数据库覆盖新聊天。新增SQLite表是兼容性扩展,不需要删除。
```bash
sudo systemctl restart rakazo-ilink-bridge.service
sudo systemctl status rakazo-ilink-bridge.service
curl --fail http://127.0.0.1:18083/health
node --test deploy-local/ilink-bridge/shortcuts.test.mjs
```
微信上下文共享意味着两个入口会看到同一段历史,不是隔离会话。若已有待审批/接管的任务,先到Rakazo处理;不会通过新的快捷指令请求绕过审批。服务重启可恢复已记录run和请求,不自动启用额外定时任务或开机自启。
`state/shortcuts-relay.json`保存中转地址、本机代理地址和私有Ed25519密钥,仅供Ubuntu服务使用;手机不需要这些配置。Ubuntu连接workers.dev时需要既有本机代理;手机仅访问上方自有域名,不要求连接Tailscale。手机端实际菜单、分享与网络可达性仍需在真实设备验收。
`miharu-call` Pages项目承担正式域名前门;正式手机配置使用上方自有域名。workers.dev与pages.dev默认地址都不作为手机安装地址。设备令牌与签名验证均在同一个Durable Object中执行。
等待逻辑修复版:queued/processing 时继续等待,completed 时显示回答;直接截图菜单仍暂停更新。