{"id":"8a0f63de-6ed7-4f8f-bb71-7ba39216231a","entityType":"agent","slug":"clawhub-blackbeans-yunitalk-beta","name":"Yunitalk Beta","canonicalUrl":"https://www.xpersona.co/agent/clawhub-blackbeans-yunitalk-beta","canonicalPath":"/agent/clawhub-blackbeans-yunitalk-beta","generatedAt":"2026-10-12T01:42:44.276Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T19:28:30.094Z","emptyReason":null},"description":"该技能用于 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s17c6hq8b7g3z7avckvcz849td85cgne:yunitalk-beta","sourceUrl":"https://clawhub.ai/blackbeans/yunitalk-beta","homepage":"https://clawhub.ai/blackbeans/skills/yunitalk-beta","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/blackbeans/yunitalk-beta","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/blackbeans/skills/yunitalk-beta","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Yunitalk Beta technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T19:28:30.094Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T19:28:30.094Z","emptyReason":null},"stars":null,"forks":null,"downloads":1003,"likes":null,"task":null,"library":null,"packageName":null,"latestVersion":"0.8.5","tractionLabel":"1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T19:28:30.025Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T19:28:30.094Z","lastCrawledAt":"2026-10-11T19:28:30.025Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T19:28:30.025Z","lastVerifiedAt":null,"highlights":[{"version":"0.8.5","createdAt":"2026-06-23T10:03:46.984Z","changelog":"yunitalk-beta 0.8.5 - 改用 Talk Robots 机器人配置页扫码保存 `/openclaw --init <base64-json>` 完成初始化，简化用户流程。 - `cvs_id` 参数改为可选，不传时默认发给机器人与创建者的点对点会话，相关说明同步调整。 - 新增推荐使用 npm 包 `yntalk-openclaw-init` 生成初始化指令及二维码，并删去对 shell/util.sh 的引用。 - 删除 shell/util.sh 脚本及 skill-card.md 文件，原流程相关内容已从文档移除。","fileCount":11,"zipByteSize":25762},{"version":"0.8.4","createdAt":"2026-06-13T04:23:50.600Z","changelog":"yunitalk-beta 0.8.4 - 更新版本号至 0.8.4，并同步 build 日期。 - 移除 skill-card.md，精简文档结构。 - 部分文档微调和补充，提升说明一致性与准确性。 - 保持原有的集成与使用流程未改变。","fileCount":12,"zipByteSize":27345},{"version":"0.8.3","createdAt":"2026-06-12T11:28:59.069Z","changelog":"- 添加对 OPENCLAW_LAN_URL 的支持，初始化指令 JSON 中现在包含该可选字段。 - 更新文档，说明 init 阶段可传递 OPENCLAW_LAN_URL 并由机器人保存。 - 移除 skill-card.md 文件。 - 进一步完善和明确初始化及配置流程说明。","fileCount":12,"zipByteSize":26899},{"version":"0.8.2","createdAt":"2026-06-12T05:27:43.325Z","changelog":"更新 yunitalk-beta：补充机器人消息发送文档、curl 调用示例、OpenClaw 初始化二维码 CLI 与 qrcode 配置支持。","fileCount":12,"zipByteSize":24815},{"version":"0.8.1","createdAt":"2026-05-20T08:50:20.790Z","changelog":"yunitalk-beta v0.8.1 - 改进初始化流程，采用单一 `/openclaw --init <base64-json>` 指令，提升易用性和安全性。 - 新增辅助脚本 `shell/util.sh`，用于生成初始化指令。 - 配置回传逻辑与环境变量命名更加清晰，字段采用统一表述。 - README 与文档（SKILL.md）内容优化，简化说明，强调安全及操作规范。 - 细化消息发送与回传流程，明确禁止明文展示敏感信息。","fileCount":7,"zipByteSize":12702},{"version":"0.8.0","createdAt":"2026-05-15T04:22:18.520Z","changelog":"与你聊聊龙虾技能首发","fileCount":5,"zipByteSize":11656}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17c6hq8b7g3z7avckvcz849td85cgne:yunitalk-beta","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17c6hq8b7g3z7avckvcz849td85cgne:yunitalk-beta` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/blackbeans/yunitalk-beta before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-blackbeans-yunitalk-beta/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-blackbeans-yunitalk-beta/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-blackbeans-yunitalk-beta/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-blackbeans-yunitalk-beta/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-blackbeans-yunitalk-beta/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-blackbeans-yunitalk-beta/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-12T01:42:44.272Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-blackbeans-yunitalk-beta/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-blackbeans-yunitalk-beta/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-blackbeans-yunitalk-beta/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-blackbeans-yunitalk-beta/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T19:28:30.094Z","emptyReason":null},"readme":"Skill: Yunitalk Beta\n\nOwner: blackbeans\n\nSummary: 该技能用于 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\n\nTags: latest:0.8.5\n\nVersion history:\n\nv0.8.5 | 2026-06-23T10:03:46.984Z | auto\n\nyunitalk-beta 0.8.5\n\n- 改用 Talk Robots 机器人配置页扫码保存 `/openclaw --init <base64-json>` 完成初始化，简化用户流程。\n- `cvs_id` 参数改为可选，不传时默认发给机器人与创建者的点对点会话，相关说明同步调整。\n- 新增推荐使用 npm 包 `yntalk-openclaw-init` 生成初始化指令及二维码，并删去对 shell/util.sh 的引用。\n- 删除 shell/util.sh 脚本及 skill-card.md 文件，原流程相关内容已从文档移除。\n\nv0.8.4 | 2026-06-13T04:23:50.600Z | auto\n\nyunitalk-beta 0.8.4\n\n- 更新版本号至 0.8.4，并同步 build 日期。\n- 移除 skill-card.md，精简文档结构。\n- 部分文档微调和补充，提升说明一致性与准确性。\n- 保持原有的集成与使用流程未改变。\n\nv0.8.3 | 2026-06-12T11:28:59.069Z | auto\n\n- 添加对 OPENCLAW_LAN_URL 的支持，初始化指令 JSON 中现在包含该可选字段。\n- 更新文档，说明 init 阶段可传递 OPENCLAW_LAN_URL 并由机器人保存。\n- 移除 skill-card.md 文件。\n- 进一步完善和明确初始化及配置流程说明。\n\nv0.8.2 | 2026-06-12T05:27:43.325Z | user\n\n更新 yunitalk-beta：补充机器人消息发送文档、curl 调用示例、OpenClaw 初始化二维码 CLI 与 qrcode 配置支持。\n\nv0.8.1 | 2026-05-20T08:50:20.790Z | auto\n\nyunitalk-beta v0.8.1\n\n- 改进初始化流程，采用单一 `/openclaw --init <base64-json>` 指令，提升易用性和安全性。\n- 新增辅助脚本 `shell/util.sh`，用于生成初始化指令。\n- 配置回传逻辑与环境变量命名更加清晰，字段采用统一表述。\n- README 与文档（SKILL.md）内容优化，简化说明，强调安全及操作规范。\n- 细化消息发送与回传流程，明确禁止明文展示敏感信息。\n\nv0.8.0 | 2026-05-15T04:22:18.520Z | user\n\n与你聊聊龙虾技能首发\n\nArchive index:\n\nArchive v0.8.5: 11 files, 25762 bytes\n\nFiles: config.yaml (5316b), npm/yntalk-openclaw-init/bin/yntalk-openclaw-init.js (22192b), npm/yntalk-openclaw-init/package.json (362b), npm/yntalk-openclaw-init/README.md (5128b), README.md (8160b), ROBOT_SEND_API.md (7977b), ROBOT_SEND_CURL_API.md (4724b), shell/robot_send.sh (6392b), skill-card.md (2501b), SKILL.md (3520b), _meta.json (132b)\n\nFile v0.8.5:SKILL.md\n\n---\nname: yunitalk-beta\ndescription: 该技能用于 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\nversion: 0.8.5\nbuild: 20260613\n---\n\n# OpenClaw 会话技能\n\n你可以通过 Talk Robots `/robot/send` 把文本或文件事件投递给当前聊聊机器人。`cvs_id` 是可选目标会话 ID；不传时默认投递到机器人与创建者的点对点会话。\n\n## 初始化流程\n\n本集成通过 Talk Robots 机器人配置页完成初始化。\n\n请让用户在机器人配置页找到 `OpenClaw连接信息` 参数，扫描或粘贴 OpenClaw 生成的初始化指令。初始化指令格式为：\n\n```text\n/openclaw --init <base64-json>\n```\n\n其中 `<base64-json>` 是对下面 JSON 做 UTF-8 Base64 编码后的内容：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}\n```\n\n安装完成后，请提示用户通过 npm CLI 读取本机 OpenClaw 配置并生成连接信息二维码，然后在 Talk Robots 机器人配置页的 `OpenClaw连接信息` 中扫码保存。推荐使用：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n`yntalk-openclaw-init` 默认无参数运行即可输出可扫码保存到 `OpenClaw连接信息` 的 `/openclaw --init <base64-json>` 和命令行二维码。\n\n不要明文展示 `OPENCLAW_TOKEN`。Base64 不是加密，不要把连接信息或二维码发送到不可信渠道。\n\n## 连接信息保存\n\nTalk Robots 机器人在配置页扫码保存连接信息后，会：\n\n1. 从 `/openclaw --init <base64-json>` 中提取 `<base64-json>`。\n2. Base64 decode 连接 JSON，保存 `OPENCLAW_URL`、`OPENCLAW_TOKEN` 和可选 `OPENCLAW_LAN_URL`。\n\n如需使用本 skill 主动发送文本或文件，以下配置必须由 OpenClaw 运行环境或管理员提供：\n\n| 字段 | 环境变量 | 说明 |\n|------|----------|------|\n| `robot_endpoint` | `TALK_ROBOT_ENDPOINT` | Talk Robots `/v1/robot/send` 地址 |\n| `robot_id` | `TALK_ROBOT_ID` | 机器人 ID |\n| `robot_key` | `TALK_ROBOT_KEY` | 机器人签名密钥 |\n| `cvs_id` | `TALK_ROBOT_CVS_ID` | 可选目标会话 ID；不传时默认投递到机器人与创建者的点对点会话 |\n\n不要回显 `robot_key`。\n\n## 发送消息\n\n优先使用 `shell/robot_send.sh`，不要手写签名。\n\n### 文本\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 文件\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n不确定参数是否正确时先加 `--dry-run`。\n\n## Rules\n\n1. 只引导用户在 Talk Robots 机器人配置页的 `OpenClaw连接信息` 中扫码保存 `/openclaw --init <base64-json>`。\n2. 发送前必须确认 `robot_endpoint`、`robot_id`、`robot_key` 都存在。\n3. `cvs_id` 是可选参数；只有明确要投递到指定会话时才传入，并保持大小写原样。不传时默认投递到机器人与创建者的点对点会话。\n4. 文本消息使用完整 `imx.Msg` JSON，`cmd=msg`，文本放 `body.content`。\n5. 文件消息使用 `multipart/form-data`，通过 `file` 字段上传。\n6. `/robot/send` 只是把事件投递给目标 robot，最终是否回发由机器人脚本决定。\n7. 不要明文展示 `OPENCLAW_TOKEN` 或 `robot_key`，不要虚构配置或用户资料。\n\nFile v0.8.5:npm/yntalk-openclaw-init/README.md\n\n# yntalk-openclaw-init\n\n`yntalk-openclaw-init` 用于生成 Talk Robots OpenClaw 机器人配置页可扫码保存的初始化指令和命令行二维码。\n\n它会读取本机 OpenClaw 的 `openclaw.json`，从 Gateway 配置中获取端口、绑定模式和 `gateway.auth.token`，再探测本机局域网 IPv4 与公网 IP，生成可直接扫码写入机器人 `OpenClaw连接信息` 配置项的 `/openclaw --init <base64-json>` 初始化指令。\n\n该工具没有运行时依赖，二维码使用终端黑白字符块绘制。\n\n## 二维码内容\n\n二维码内容是机器人配置页可识别的初始化指令：\n\n```text\n/openclaw --init <base64-json>\n```\n\n其中 `<base64-json>` 是下面 JSON 的 UTF-8 Base64 编码：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}\n```\n\n`docs/openclaw-robot.js` 可以识别这个格式。请在机器人配置页的 `OpenClaw连接信息` 字段中扫码保存；保存后回到聊聊会话发送普通消息即可触发自动连通。\n\n## 安装\n\n不安装，直接运行：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n全局安装后运行：\n\n```bash\nnpm install -g yntalk-openclaw-init\nyntalk-openclaw-init\n```\n\n在本仓库中调试本地版本：\n\n```bash\nnpx ./docs/skills/yunitalk-beta/npm/yntalk-openclaw-init\n```\n\n## 使用\n\n默认无参数运行：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n无参数运行会自动获取当前 OpenClaw 连接信息，并输出：\n\n- 局域网访问地址\n- 局域网 OpenAI Base URL\n- 公网访问地址\n- 公网 OpenAI Base URL\n- Gateway 状态\n- `/openclaw --init <base64-json>` 初始化指令\n- 1x1 scale 命令行二维码\n\n命令行参数只支持：\n\n```bash\nnpx yntalk-openclaw-init -h\nnpx yntalk-openclaw-init -v\n```\n\n全局安装后也可以这样运行：\n\n```bash\nyntalk-openclaw-init\nyntalk-openclaw-init -h\nyntalk-openclaw-init -v\n```\n\n参数说明：\n\n- `-h` / `--help`：显示帮助\n- `-v` / `--verbose`：打印配置查找、Gateway 推导和公网 IP 探测日志\n\n## 默认读取逻辑\n\n工具默认会：\n\n- 查找并读取本地 `openclaw.json`\n- 从 `gateway.port` 读取 Gateway 端口，缺省为 `18789`\n- 从 `gateway.bind` 读取 Gateway 绑定模式\n- 从 `gateway.auth.token` 读取 `OPENCLAW_TOKEN`\n- 检查 `gateway.http.endpoints.chatCompletions.enabled`\n- 探测本机局域网 IPv4 和公网 IP\n- 使用公网 Gateway 根地址作为初始化 JSON 中的 `OPENCLAW_URL`\n- 使用局域网 Gateway 根地址作为初始化 JSON 中的 `OPENCLAW_LAN_URL`\n- 额外打印以 `/v1` 结尾的 OpenAI Base URL，方便核对接口地址\n\n注意：初始化 JSON 中的 `OPENCLAW_URL` 不带 `/v1`。`docs/openclaw-robot.js` 会在请求时自动拼接 `/v1/chat/completions`，同时也兼容扫码内容本身已经带 `/v1` 的情况。\n\n## 配置文件位置\n\n工具会按以下位置查找 `openclaw.json`：\n\n- `OPENCLAW_CONFIG` 环境变量指定的路径\n- 当前目录及父目录下的 `openclaw.json`\n- 当前目录及父目录下的 `.openclaw/openclaw.json`\n- `~/openclaw.json`\n- `~/.openclaw/openclaw.json`\n- `~/.config/openclaw/openclaw.json`\n- macOS: `~/Library/Application Support/OpenClaw/openclaw.json`\n\n## 输出示例\n\n```text\n局域网访问地址:\nhttp://192.168.1.10:18789\n\n局域网 OpenAI Base URL:\nhttp://192.168.1.10:18789/v1\n\n公网访问地址:\nhttp://203.0.113.10:18789\n\n公网 OpenAI Base URL:\nhttp://203.0.113.10:18789/v1\n\nGateway:\nbind: all\nport: 18789\nauth_mode: bearer\nchatCompletions: enabled\n\n扫码连接内容:\n/openclaw --init eyJPUEVOQ0xBV19VUkw...\n\n二维码(1x1):\n████...\n```\n\n如果公网 IP 探测失败，工具会回退到局域网地址，并在 stderr 中打印 warning。此时生成的公网访问地址并不是真正的公网地址。\n\n如果 `gateway.bind` 不是 `lan`、`all`、`0.0.0.0` 或 `::`，工具也会打印 warning，提示公网访问可能失败。\n\n## 常见问题\n\n### 找不到 `openclaw.json`\n\n确认 OpenClaw 已在本机初始化，并且配置文件位于默认查找路径之一。也可以用环境变量显式指定：\n\n```bash\nOPENCLAW_CONFIG=/path/to/openclaw.json npx yntalk-openclaw-init\n```\n\n### Token 为空\n\n确认 `openclaw.json` 中存在：\n\n```json\n{\n  \"gateway\": {\n    \"auth\": {\n      \"token\": \"your-token\"\n    }\n  }\n}\n```\n\n### Chat API 未启用\n\n确认配置中开启了 OpenAI 兼容接口：\n\n```json\n{\n  \"gateway\": {\n    \"http\": {\n      \"endpoints\": {\n        \"chatCompletions\": {\n          \"enabled\": true\n        }\n      }\n    }\n  }\n}\n```\n\n### 二维码扫码后机器人仍访问失败\n\n优先检查输出里的 `公网 OpenAI Base URL` 是否能从 Talk Robots 运行环境访问。`OPENCLAW_URL` 最终会请求：\n\n```text\n<OPENCLAW_URL>/v1/chat/completions\n```\n\n如果你传入的是以 `/v1` 结尾的 OpenAI Base URL，`docs/openclaw-robot.js` 会自动去重，不会拼出重复的 `/v1/v1/chat/completions`。\n\n## 安全提示\n\n`OPENCLAW_TOKEN` 会被编码进扫码初始化指令中。Base64 不是加密，不要把生成的初始化指令、连接内容或二维码发送到不可信渠道。\n\nFile v0.8.5:README.md\n\n# OpenClaw 与 Talk Robots 集成指南\n\n本 Skill 用于将 OpenClaw 接入与你聊聊 (Talk Robots)。初始化流程通过 Talk Robots 机器人配置页的 `OpenClaw连接信息` 扫码项完成，不需要用户在聊聊会话输入任何命令。\n\n二维码内容是初始化指令，格式为：\n\n```text\n/openclaw --init <base64-json>\n```\n\n其中 `<base64-json>` 是对 JSON 做 UTF-8 Base64 编码后的内容，JSON 包含：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}\n```\n\nTalk Robots 机器人配置页扫码保存后，机器人会 Base64 decode 并保存 OpenClaw 连接信息。用户随后在聊聊会话中发送普通消息，即可通过 OpenClaw 进行对话。\n\n## 功能概述\n\n- **双向通信**：用户可以通过聊聊与 OpenClaw 对话。\n- **自动初始化**：通过机器人配置页 `OpenClaw连接信息` 扫码导入 OpenClaw URL/Token。\n- **连接自检**：将同一条 `/openclaw --init <base64-json>` 发送到会话时，Talk Robots 机器人会向 OpenClaw 发送“我发送 ping，你帮我回复 pong”验证配置。\n- **事件投递**：OpenClaw 可调用 `/robot/send` 将文本或文件事件投递给指定机器人。\n\n## 快速开始\n\n### 1. 安装 Skill\n\n使用 `clawhub` 安装：\n\n```bash\nclawhub install yunitalk-beta\n```\n\n`shell/robot_send.sh` 依赖 `curl`、`openssl` 和 `python3`。如果 OpenClaw 运行环境是容器，请确认镜像内已安装这些命令。\n\n本地开发调试未发布版本时，才需要使用本仓库中的 `docs/skills/yunitalk-beta/` 目录。\n\n### 2. 生成扫码连接内容\n\n推荐使用 npm CLI 直接读取本机 OpenClaw 连接信息并生成可扫码的连接内容：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n也可以先全局安装后运行：\n\n```bash\nnpm install -g yntalk-openclaw-init\nyntalk-openclaw-init\n```\n\n在本仓库内调试未发布版本时，可以直接运行本地包：\n\n```bash\nnpx ./docs/skills/yunitalk-beta/npm/yntalk-openclaw-init\n```\n\n本仓库内的 CLI 源码位于 `npm/yntalk-openclaw-init/`；发布到 npm 后即可直接通过上面的 `npx` 命令使用。CLI 默认读取本机 `openclaw.json` 的 `gateway.port`、`gateway.bind`、`gateway.auth.token` 和 `gateway.http.endpoints.chatCompletions.enabled`，使用本机局域网 IPv4 生成局域网访问地址，并探测公网 IP 生成公网访问地址，最后输出完整 `/openclaw --init <base64-json>` 初始化指令和 1x1 scale 命令行二维码。\nCLI 只支持 `-h/--help` 和 `-v/--verbose` 两个参数；默认无参数运行即可输出局域网访问地址、公网访问地址、初始化指令和 1x1 scale 二维码。生成的初始化 JSON 中 `OPENCLAW_URL` 使用公网访问地址，`OPENCLAW_LAN_URL` 保存局域网访问地址。\n提交 `docs/openclaw-robot.js` 后，在机器人配置页的 `OpenClaw连接信息` 参数中扫码保存该二维码内容，脚本会自动解析并写入 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN`。\n\n输出示例：\n\n```text\n局域网访问地址:\nhttp://192.168.1.10:3000\n\n公网访问地址:\nhttp://203.0.113.10:3000\n\n扫码连接内容:\n/openclaw --init eyJPUEVOQ0xBV19VUkw...\n\n二维码(1x1):\n████...\n```\n\nnpx CLI 默认会自动读取本地 `openclaw.json` 的 Gateway 配置，探测公网 IP 生成公网访问地址，并从 `gateway.auth.token` 获取 Token，不需要手动传入这些配置。Base64 不是加密，不要把 `OPENCLAW_TOKEN` 明文、初始化指令、扫码连接内容或二维码发送到不可信渠道。\n\n### 3. 在机器人配置页扫码保存\n\n打开 Talk Robots 机器人配置页，找到 `OpenClaw连接信息` 参数，扫描或粘贴上一步生成的 `/openclaw --init <base64-json>` 并保存。保存后回到聊聊会话，发送任意普通消息即可开始对话。\n\n机器人会自动执行：\n\n1. 从扫码保存的初始化指令中提取 `<base64-json>` 并执行 Base64 decode，得到包含 `OPENCLAW_URL`、`OPENCLAW_TOKEN` 和可选 `OPENCLAW_LAN_URL` 的 JSON。\n2. 写入 `OPENCLAW_URL`、`OPENCLAW_TOKEN` 和可选 `OPENCLAW_LAN_URL`。\n\n初始化完成后，用户在聊聊里直接发送普通消息即可开始对话。\n\n## OpenClaw Skill 环境变量\n\n如需让 OpenClaw 通过本 Skill 主动调用 `/robot/send` 发送文本或文件，需要在 OpenClaw 中配置以下变量：\n\n| 环境变量 | 对应配置项 | 必填 | 说明 |\n|----------|-----------|------|------|\n| `TALK_ROBOT_ENDPOINT` | `robot_endpoint` | 是 | Talk Robots `/v1/robot/send` 服务端点 |\n| `TALK_ROBOT_ID` | `robot_id` | 是 | 机器人 ID，用于签名鉴权 |\n| `TALK_ROBOT_KEY` | `robot_key` | 是 | 机器人密钥，用于签名鉴权 |\n| `TALK_ROBOT_CVS_ID` | `cvs_id` | 否 | 可选目标会话 ID；不传时默认投递到机器人与创建者的点对点会话 |\n\n也可以在 OpenClaw 配置文件 `openclaw.json` 的 `skills.entries` 中持久化：\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"yunitalk-beta\": {\n        \"enabled\": true,\n        \"env\": {\n          \"TALK_ROBOT_ENDPOINT\": \"https://api-talk.yuniapp.cn/v1/robot/send\",\n          \"TALK_ROBOT_ID\": \"your-robot-id\",\n          \"TALK_ROBOT_KEY\": \"your-robot-key\",\n          \"TALK_ROBOT_CVS_ID\": \"optional-cvs-id\"\n        }\n      }\n    }\n  }\n}\n```\n\n这些变量需要由 OpenClaw 运行环境或管理员配置。不要在普通回复中回显 `TALK_ROBOT_KEY`。\n\n## Talk Robots 机器人脚本配置\n\n将 `docs/openclaw-robot.js` 提交到 Talk Robots。脚本会在机器人配置页扫码保存 `OpenClaw连接信息` 后写入以下 KV：\n\n| 配置项 | 必填 | 说明 |\n|--------|------|------|\n| `OPENCLAW_URL` | 是 | OpenClaw Gateway 地址，例如 `https://your-openclaw-domain`；也兼容以 `/v1` 结尾的 OpenAI Base URL |\n| `OPENCLAW_TOKEN` | 是 | OpenClaw Gateway Token |\n| `TALK_ROBOT_ENDPOINT` | 否 | `/v1/robot/send` 地址，默认 `https://api-talk.yuniapp.cn/v1/robot/send` |\n\n## 机器人消息发送接口\n\nOpenClaw 可以调用 Talk Robots `/robot/send` 将文本或文件事件投递给指定机器人。发送消息时推荐优先使用本 Skill 内置脚本 `shell/robot_send.sh`，它会自动生成 `msg_id`、`noncestr`、`timestamp` 和 HMAC-SHA256 `sign`。\n\n完整的文本消息、文件消息、签名规则和 `curl` 示例见独立文档：\n\n- [ROBOT_SEND_API.md](./ROBOT_SEND_API.md) - 机器人消息发送接口\n\n## 故障排查\n\n### 问题：无法生成扫码连接内容\n\n- 确认本机可以读取 OpenClaw 配置文件 `openclaw.json`。\n- 确认配置中存在 `gateway.auth.token`。\n- 使用 `npx yntalk-openclaw-init -v` 查看运行日志，或使用 `npx yntalk-openclaw-init -h` 查看帮助。\n\n### 问题：初始化 ping/pong 失败\n\n- 检查 `OPENCLAW_URL` 是否能访问 `/v1/chat/completions`。\n- 检查 `OPENCLAW_TOKEN` 是否有效。\n- 确认 OpenClaw 模型收到 ping 时能只回复 `pong`。\n\n### 问题：无法发送消息\n\n1. 检查 `TALK_ROBOT_ENDPOINT`、`TALK_ROBOT_ID`、`TALK_ROBOT_KEY` 是否完整。\n2. 如需投递到指定会话，确认 `cvs_id` 使用当前目标会话 ID，且大小写未被改变；不传时默认投递到机器人与创建者的点对点会话。\n3. 使用 `shell/robot_send.sh --dry-run` 检查签名 URL 和请求体。\n4. 确认 `/robot/send` 的返回状态和错误信息。\n\n## 注意事项\n\n1. **安全性**：`OPENCLAW_TOKEN` 和 `TALK_ROBOT_KEY` 是敏感信息，请勿提交到代码仓库或普通聊天回复。\n2. **会话 ID 可选**：`cvs_id` 用于指定目标会话；不传时默认投递到机器人与创建者的点对点会话。\n3. **投递语义**：`/robot/send` 只表示事件已投递给机器人；是否最终回消息由机器人脚本决定。\n4. **会话隔离**：每个用户的会话是独立的，OpenClaw 不应跨会话共享上下文。\n\n## 参考文档\n\n- [SKILL.md](./SKILL.md) - OpenClaw 技能详细说明\n- [ROBOT_SEND_API.md](./ROBOT_SEND_API.md) - 机器人消息发送接口\n- [ROBOT_SEND_CURL_API.md](./ROBOT_SEND_CURL_API.md) - 机器人消息 curl 调用示例\n- [config.yaml](./config.yaml) - 技能配置文件\n\nFile v0.8.5:_meta.json\n\n{\n  \"ownerId\": \"kn78g6avmt6xsvd4c2acd7sd5h85dqx6\",\n  \"slug\": \"yunitalk-beta\",\n  \"version\": \"0.8.5\",\n  \"publishedAt\": 1782209026984\n}\n\nFile v0.8.5:ROBOT_SEND_API.md\n\n# Talk Robots 机器人消息发送接口\n\n本文档说明 OpenClaw 通过 Talk Robots `/robot/send` 向与你聊聊机器人投递消息的方式，覆盖文本消息和文件消息两类请求。\n\n`/robot/send` 的语义是把事件投递给目标机器人；机器人是否最终向会话回复，由机器人脚本决定。\n\n## 推荐调用方式\n\n优先使用本 Skill 内置脚本 `shell/robot_send.sh`。脚本会自动生成 `msg_id`、`noncestr`、`timestamp` 和 HMAC-SHA256 `sign`，避免业务侧重复实现签名逻辑。\n\n### 发送文本\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 发送文件\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n### 发送前预检\n\n使用 `--dry-run` 可以查看签名 URL 和请求体，不会实际发送消息。\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --content \"测试消息\" \\\n  --dry-run\n```\n\n脚本常用参数：\n\n| 参数 | 必填 | 说明 |\n|------|------|------|\n| `--base-url` | 是 | Talk Robots `/v1/robot/send` 地址，即 `TALK_ROBOT_ENDPOINT` |\n| `--robot-id` | 是 | 机器人 ID |\n| `--robot-key` | 是 | 机器人 Key，用于签名 |\n| `--cvs-id` | 否 | 可选目标会话 ID，应保持大小写原样；不传时默认投递到机器人与创建者的点对点会话 |\n| `--content` | 文本必填，文件可选 | 文本消息内容，或文件说明文本 |\n| `--file` | 文件必填 | 待上传文件路径 |\n| `--refer-msg-id` | 否 | 引用的消息 ID |\n| `--msg-id` | 否 | 指定消息 ID；不传时脚本自动生成 |\n| `--noncestr` | 否 | 指定随机串；不传时脚本自动生成 |\n| `--timestamp` | 否 | 指定 Unix 秒级时间戳；不传时脚本自动生成 |\n| `--at` | 否 | 文本消息的 `at_uid_list`，多个 UID 用英文逗号分隔 |\n| `--mentioned` | 否 | 文本消息的 `mentioned_list`，多个 UID 用英文逗号分隔 |\n| `--dry-run` | 否 | 只打印请求信息，不实际发送 |\n\n## 直接使用 curl\n\n不使用 `shell/robot_send.sh` 时，可以直接用 `curl` 调用 `/robot/send`。完整的签名生成、文本消息和文件消息示例见：\n\n- [ROBOT_SEND_CURL_API.md](./ROBOT_SEND_CURL_API.md) - 机器人消息 curl 调用示例\n\n## 接口总览\n\n**请求方法**：`POST`\n\n**基础地址**：`{robot_endpoint}`\n\n`robot_endpoint` 通常来自 `TALK_ROBOT_ENDPOINT`，例如：\n\n```text\nhttps://api-talk.yuniapp.cn/v1/robot/send\n```\n\n**鉴权参数**放在 URL 查询参数中：\n\n| 参数 | 必填 | 说明 |\n|------|------|------|\n| `robot_id` | 是 | 机器人 ID |\n| `noncestr` | 是 | 请求随机串 |\n| `timestamp` | 是 | Unix 秒级时间戳 |\n| `msg_id` | 是 | 消息 ID；请求体或表单中的 `msg_id` 必须与 URL 中一致 |\n| `sign` | 是 | 使用 `robot_key` 计算得到的 HMAC-SHA256 签名 |\n\n完整 URL 形态：\n\n```text\n{robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\n```\n\n## 签名规则\n\n签名参数为 `msg_id`、`noncestr`、`robot_id`、`timestamp`。生成 `sign` 时：\n\n1. 按参数 key 字典序排序。\n2. 每个 value 使用 URL encode。\n3. 按 `key=value` 拼接，并用 `&` 连接。\n4. 使用 `robot_key` 对签名原文做 HMAC-SHA256。\n5. 将结果编码为小写十六进制字符串。\n\n签名原文示例：\n\n```text\nmsg_id=<msg_id>&noncestr=<noncestr>&robot_id=<robot_id>&timestamp=<timestamp>\n```\n\nShell 示例：\n\n```bash\nsigning_text=\"msg_id=${msg_id}&noncestr=${noncestr}&robot_id=${robot_id}&timestamp=${timestamp}\"\nsign=\"$(printf '%s' \"$signing_text\" | openssl dgst -sha256 -hmac \"$robot_key\" | awk '{print $2}')\"\n```\n\n实际实现时，`signing_text` 里的 value 需要先 URL encode。推荐直接使用 `shell/robot_send.sh`。\n\n## 发送文本消息\n\n文本消息使用 `application/json`，请求体是完整 `imx.Msg` JSON 结构，`cmd` 固定为 `msg`，文本内容放在 `body.content`。\n\n```http\nPOST {robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\nContent-Type: application/json\n\n{\n  \"cmd\": \"msg\",\n  \"head\": {\n    \"msg_id\": \"消息ID，需与 URL 中 msg_id 一致\",\n    \"cvs_id\": \"可选，目标会话ID\",\n    \"refer_msg_id\": \"可选，引用消息ID\"\n  },\n  \"body\": {\n    \"content\": \"消息内容\",\n    \"at_uid_list\": [\"可选，被 @ 的用户 ID\"],\n    \"mentioned_list\": [\"可选，兼容企业微信类命名\"]\n  }\n}\n```\n\n字段说明：\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `cmd` | 是 | 固定为 `msg` |\n| `head.msg_id` | 是 | 消息 ID，需与 URL 查询参数 `msg_id` 一致 |\n| `head.cvs_id` | 否 | 可选目标会话 ID；不传时默认投递到机器人与创建者的点对点会话 |\n| `head.refer_msg_id` | 否 | 引用消息 ID |\n| `body.content` | 是 | 文本、Markdown 或文件说明 |\n| `body.at_uid_list` | 否 | @ 用户列表 |\n| `body.mentioned_list` | 否 | 兼容企业微信类命名的提及列表 |\n\n`curl` 示例：\n\n```bash\ncurl -X POST \"$request_url\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary '{\n    \"cmd\": \"msg\",\n    \"head\": {\n      \"msg_id\": \"'\"$msg_id\"'\"\n    },\n    \"body\": {\n      \"content\": \"你好，任务已经处理完成。\"\n    }\n  }'\n```\n\n## 发送文件消息\n\n文件消息使用 `multipart/form-data`，文件内容必须通过 `file` 字段上传，不要用 JSON 传文件二进制内容。\n\n```http\nPOST {robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\nContent-Type: multipart/form-data\n\nmsg_id: 消息ID，需与 URL 中 msg_id 一致\ncvs_id: 可选，目标会话ID\nfile: <二进制文件内容>\ncontent: <可选，文件说明文本>\nrefer_msg_id: <可选，引用消息ID>\n```\n\n表单字段说明：\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `msg_id` | 是 | 消息 ID，需与 URL 查询参数 `msg_id` 一致 |\n| `cvs_id` | 否 | 可选目标会话 ID；不传时默认投递到机器人与创建者的点对点会话 |\n| `file` | 是 | 待上传文件 |\n| `content` | 否 | 文件说明文本 |\n| `refer_msg_id` | 否 | 引用消息 ID |\n\n`curl` 示例：\n\n```bash\ncurl -X POST \"$request_url\" \\\n  -F \"msg_id=$msg_id\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\"\n```\n\n服务端会把 multipart 文件转换为机器人消息中的 `file_list`，并把文件内容编码为 `data:<content-type>;base64,<payload>` 后投递给目标机器人脚本。\n\n## 响应\n\n成功响应：\n\n```json\n{\n  \"success\": true,\n  \"message\": \"ok\"\n}\n```\n\n常见失败响应：\n\n| HTTP 状态码 | message | 说明 |\n|-------------|---------|------|\n| `400` | `签名参数错误` | 缺少签名查询参数 |\n| `400` | `签名错误` | `sign` 校验失败 |\n| `400` | `msg_id 错误` | 请求体或表单中的 `msg_id` 与 URL 中不一致 |\n| `400` | `参数格式错误` | JSON 结构或字段格式不合法 |\n| `400` | `文件处理错误` | multipart 文件读取失败 |\n| `400` | `参数错误` | 投递给机器人时参数不符合要求 |\n| `404` | `机器人不存在` | `robot_id` 不存在 |\n| `500` | `内部错误` | 服务端处理异常 |\n\n## 注意事项\n\n1. `TALK_ROBOT_KEY` 是敏感信息，不要写入日志、提交到仓库或回显给用户。\n2. `cvs_id` 是可选目标会话 ID；不传时默认投递到机器人与创建者的点对点会话，传入时保持大小写不变。\n3. 文本消息使用 JSON，文件消息使用 multipart，不要混用。\n4. `msg_id` 是本次投递的幂等标识之一，URL 和请求体中的值必须一致。\n5. `/robot/send` 只表示事件已投递给目标机器人，不保证机器人脚本一定会回复。\n\nFile v0.8.5:ROBOT_SEND_CURL_API.md\n\n# Talk Robots 机器人消息 curl 调用示例\n\n本文档说明不使用 `shell/robot_send.sh` 时，如何直接用 `curl` 调用 Talk Robots `/robot/send` 投递文本消息和文件消息。\n\n示例依赖 `curl`、`openssl` 和 `python3`。\n\n## 准备公共变量\n\n```bash\nTALK_ROBOT_ENDPOINT=\"https://api-talk.yuniapp.cn/v1/robot/send\"\nTALK_ROBOT_ID=\"your-robot-id\"\nTALK_ROBOT_KEY=\"your-robot-key\"\n# 可选：指定目标会话；不设置时默认投递到机器人与创建者的点对点会话\nTALK_ROBOT_CVS_ID=\"\"\n```\n\n字段说明：\n\n| 变量 | 说明 |\n|------|------|\n| `TALK_ROBOT_ENDPOINT` | Talk Robots `/v1/robot/send` 地址 |\n| `TALK_ROBOT_ID` | 机器人 ID |\n| `TALK_ROBOT_KEY` | 机器人 Key，用于 HMAC-SHA256 签名 |\n| `TALK_ROBOT_CVS_ID` | 可选目标会话 ID，传入时必须保持大小写原样；不传时默认投递到机器人与创建者的点对点会话 |\n\n## 生成签名 URL\n\n```bash\ntimestamp=\"$(date +%s)\"\nmsg_id=\"msg_${timestamp}_$(python3 -c 'import uuid; print(uuid.uuid4().hex)')\"\nnoncestr=\"nonce_${timestamp}_$(python3 -c 'import uuid; print(uuid.uuid4().hex)')\"\n\nurlencode() {\n  python3 -c 'import sys, urllib.parse; print(urllib.parse.quote_plus(sys.argv[1]))' \"$1\"\n}\n\nsigning_text=\"msg_id=$(urlencode \"$msg_id\")&noncestr=$(urlencode \"$noncestr\")&robot_id=$(urlencode \"$TALK_ROBOT_ID\")&timestamp=$(urlencode \"$timestamp\")\"\nsign=\"$(printf '%s' \"$signing_text\" | openssl dgst -sha256 -hmac \"$TALK_ROBOT_KEY\" | awk '{print $2}')\"\n\nrequest_url=\"${TALK_ROBOT_ENDPOINT}?robot_id=$(urlencode \"$TALK_ROBOT_ID\")&noncestr=$(urlencode \"$noncestr\")&timestamp=$(urlencode \"$timestamp\")&msg_id=$(urlencode \"$msg_id\")&sign=$(urlencode \"$sign\")\"\n```\n\n签名原文由 `msg_id`、`noncestr`、`robot_id`、`timestamp` 按 key 字典序排序后拼接，且每个 value 都需要先 URL encode：\n\n```text\nmsg_id=<msg_id>&noncestr=<noncestr>&robot_id=<robot_id>&timestamp=<timestamp>\n```\n\n## curl 发送文本消息\n\n文本消息使用 `application/json`，请求体是完整 `imx.Msg` JSON 结构，`cmd` 固定为 `msg`，文本内容放在 `body.content`。\n\n```bash\ncurl -sS -X POST \"$request_url\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary \"$(python3 - <<PY\nimport json\n\npayload = {\n    \"cmd\": \"msg\",\n    \"head\": {\n        \"msg_id\": \"${msg_id}\"\n    },\n    \"body\": {\n        \"content\": \"你好，任务已经处理完成。\"\n    }\n}\nprint(json.dumps(payload, ensure_ascii=False, separators=(\",\", \":\")))\nPY\n)\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n带引用消息的文本请求：\n\n```bash\nREFER_MSG_ID=\"source-msg-id\"\n\ncurl -sS -X POST \"$request_url\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary \"$(python3 - <<PY\nimport json\n\npayload = {\n    \"cmd\": \"msg\",\n    \"head\": {\n        \"msg_id\": \"${msg_id}\",\n        \"refer_msg_id\": \"${REFER_MSG_ID}\"\n    },\n    \"body\": {\n        \"content\": \"这是引用回复。\"\n    }\n}\nprint(json.dumps(payload, ensure_ascii=False, separators=(\",\", \":\")))\nPY\n)\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n## curl 发送文件消息\n\n文件消息使用 `multipart/form-data`，文件内容必须通过 `file` 字段上传，不要用 JSON 传文件二进制内容。\n\n```bash\ncurl -sS -X POST \"$request_url\" \\\n  -F \"msg_id=$msg_id\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n带引用消息的文件请求：\n\n```bash\ncurl -sS -X POST \"$request_url\" \\\n  -F \"msg_id=$msg_id\" \\\n  -F \"refer_msg_id=source-msg-id\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n## 响应示例\n\n成功响应：\n\n```json\n{\n  \"success\": true,\n  \"message\": \"ok\"\n}\n```\n\n常见失败响应：\n\n| HTTP 状态码 | message | 说明 |\n|-------------|---------|------|\n| `400` | `签名参数错误` | 缺少签名查询参数 |\n| `400` | `签名错误` | `sign` 校验失败 |\n| `400` | `msg_id 错误` | 请求体或表单中的 `msg_id` 与 URL 中不一致 |\n| `400` | `参数格式错误` | JSON 结构或字段格式不合法 |\n| `400` | `文件处理错误` | multipart 文件读取失败 |\n| `404` | `机器人不存在` | `robot_id` 不存在 |\n| `500` | `内部错误` | 服务端处理异常 |\n\n## 注意事项\n\n1. `TALK_ROBOT_KEY` 是敏感信息，不要写入日志、提交到仓库或回显给用户。\n2. `msg_id` 必须同时出现在 URL 查询参数和请求体或表单中，并保持一致。\n3. `cvs_id` 是可选目标会话 ID；不传时默认投递到机器人与创建者的点对点会话，传入时保持大小写不变。\n4. 文本消息使用 JSON，文件消息使用 multipart，不要混用。\n5. `/robot/send` 只表示事件已投递给目标机器人，不保证机器人脚本一定会回复。\n\nFile v0.8.5:skill-card.md\n\n## Description:\n\nConnects OpenClaw with Talk Robots so users can chat with OpenClaw through the Talk Robots conversation flow.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[blackbeans](https://clawhub.ai/user/blackbeans)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and OpenClaw operators use this skill to initialize a Talk Robots connection, route chat messages to OpenClaw, and optionally send text or file events back through the robot send API.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The initialization command and QR code contain a reusable OpenClaw gateway token encoded with Base64, which is not encryption.\n\nMitigation: Share the command and QR code only through trusted channels, avoid exposing them in logs or shared terminals, and rotate the gateway token if exposure is possible.\n\nRisk: The robot send flow depends on robot signing credentials such as TALK_ROBOT_KEY.\n\nMitigation: Keep robot credentials out of ordinary chat responses, repositories, and debug logs; verify required environment variables before sending messages.\n\nRisk: Running an unpinned npx initializer can execute code fetched at install time.\n\nMitigation: Prefer a pinned version or a locally reviewed copy of the initializer, and avoid running it in CI or other shared environments.\n\n## Reference(s):\n\n- [ClawHub release page](https://clawhub.ai/blackbeans/skills/yunitalk-beta)\n- [README.md](artifact/README.md)\n- [SKILL.md](artifact/SKILL.md)\n- [ROBOT_SEND_API.md](artifact/ROBOT_SEND_API.md)\n- [ROBOT_SEND_CURL_API.md](artifact/ROBOT_SEND_CURL_API.md)\n- [config.yaml](artifact/config.yaml)\n- [yntalk-openclaw-init README](artifact/npm/yntalk-openclaw-init/README.md)\n\n## Skill Output:\n\n**Output Type(s):** [guidance, shell commands, configuration, code]\n\n**Output Format:** [Markdown guidance with shell commands, JSON examples, and configuration snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include generated initialization commands, QR-code terminal output, signed robot-send requests, and text or file event payloads.]\n\n## Skill Version(s):\n\n0.8.5 (source: server release evidence, SKILL.md frontmatter, config.yaml)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v0.8.5:npm/yntalk-openclaw-init/package.json\n\n{\n  \"name\": \"yntalk-openclaw-init\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Generate Talk Robots OpenClaw connection config and QR code.\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"bin\": {\n    \"yntalk-openclaw-init\": \"./bin/yntalk-openclaw-init.js\"\n  },\n  \"files\": [\n    \"bin\",\n    \"README.md\"\n  ],\n  \"engines\": {\n    \"node\": \">=18\"\n  },\n  \"dependencies\": {}\n}\n\nFile v0.8.5:config.yaml\n\nversion: 1\nmode: prompt\n\nskill:\n  name: yunitalk-beta\n  display_name: OpenClaw 与你聊聊对话\n  description: 使用 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\n  version: 0.8.5\n  build: 20260613\n\n# OpenClaw 侧由 Talk Robots 机器人配置页扫码流程写入连接信息\nconfig:\n  # Talk Robots 服务端点\n  robot_endpoint:\n    type: string\n    required: false\n    description: Talk Robots 服务端点地址，用于发送消息；默认值为 https://api-talk.yuniapp.cn/v1/robot/send，可通过环境变量 TALK_ROBOT_ENDPOINT 覆盖\n    default: \"https://api-talk.yuniapp.cn/v1/robot/send\"\n\n  # 机器人 ID\n  robot_id:\n    type: string\n    required: false\n    description: 机器人 ID，用于签名鉴权；初始化成功后从环境变量 TALK_ROBOT_ID 读取\n    default: \"${TALK_ROBOT_ID}\"\n\n  # 机器人密钥\n  robot_key:\n    type: string\n    required: false\n    description: 机器人密钥，用于 /robot/send 签名鉴权；初始化成功后从环境变量 TALK_ROBOT_KEY 读取\n    default: \"${TALK_ROBOT_KEY}\"\n\n  # 可选：默认 agent ID\n  default_agent_id:\n    type: string\n    required: false\n    description: 默认使用的 OpenClaw Agent ID\n    default: main\n\n# 运行时变量（由 Talk Robots 调用时注入）\nvariables:\n  cvs_id:\n    type: string\n    required: false\n    description: 可选目标会话ID；不传时默认投递到机器人与创建者的点对点会话\n\n# 能力声明（用于 MCP 模式，prompt 模式下可忽略）\ncapabilities:\n  send_text:\n    enabled: true\n    description: 通过 Robot 消息接口投递文本事件给指定机器人；JSON 请求体使用完整 imx.Msg 结构\n    endpoint: \"{{config.robot_endpoint}}?robot_id={{config.robot_id}}&noncestr={{nonce}}&timestamp={{timestamp}}&msg_id={{msg_id}}&sign={{sign}}\"\n    method: POST\n    content_type: application/json\n    payload_schema:\n      type: object\n      properties:\n        cmd:\n          type: string\n          const: msg\n          description: 固定为 msg\n        head:\n          type: object\n          properties:\n            msg_id:\n              type: string\n              description: 消息 ID，需与 URL 中 msg_id 一致\n            cvs_id:\n              type: string\n              description: 可选目标会话 ID；不传时默认投递到机器人与创建者的点对点会话\n            refer_msg_id:\n              type: string\n              description: 可选，引用消息 ID\n          required: [msg_id]\n        body:\n          type: object\n          properties:\n            content:\n              type: string\n              description: 文本内容、Markdown 内容或文件说明\n            file_list:\n              type: array\n              description: 文件数组，元素为 RobotFile\n            at_uid_list:\n              type: array\n              description: \"@ 用户列表\"\n            mentioned_list:\n              type: array\n              description: 兼容企业微信类命名\n          required: [content]\n      required: [cmd, head, body]\n\n  send_file:\n    enabled: true\n    description: 通过 Robot 消息接口投递文件事件给指定机器人\n    endpoint: \"{{config.robot_endpoint}}?robot_id={{config.robot_id}}&noncestr={{nonce}}&timestamp={{timestamp}}&msg_id={{msg_id}}&sign={{sign}}\"\n    method: POST\n    content_type: multipart/form-data\n    form_fields:\n      msg_id:\n        type: string\n        required: true\n        description: 消息ID，需与 URL 中 msg_id 一致\n      cvs_id:\n        type: string\n        required: false\n        description: 可选目标会话ID；不传时默认投递到机器人与创建者的点对点会话\n      file:\n        type: binary\n        required: true\n        description: 文件二进制内容\n      content:\n        type: string\n        required: false\n        description: 可选，文件说明文本\n      refer_msg_id:\n        type: string\n        required: false\n        description: 可选，引用消息 ID\n\n# 规则（用于 AI 遵循）\nrules:\n  - OpenClaw 会自动管理当前会话的身份标识\n  - 初始化入口使用 Talk Robots 机器人配置页的 OpenClaw连接信息 扫码项\n  - 安装后应提示用户运行 yntalk-openclaw-init 读取本地 OpenClaw 配置，并输出可扫码保存到 OpenClaw连接信息 的初始化指令\n  - 初始化指令必须是 /openclaw --init <base64-json>，其中 <base64-json> 是对 {\"OPENCLAW_URL\":\"...\",\"OPENCLAW_TOKEN\":\"...\",\"OPENCLAW_LAN_URL\":\"...\"} 做 UTF-8 Base64 编码后的结果；不得明文展示 OPENCLAW_TOKEN 或 robot_key\n  - 如需主动投递消息，robot_endpoint、robot_id 和 robot_key 必须由 OpenClaw 运行环境或管理员提供，并且不要回显 robot_key\n  - cvs_id 是可选目标会话 ID；不传 cvs_id 时，/robot/send 默认投递到机器人与创建者的点对点会话\n  - 投递文本事件时必须使用完整 imx.Msg JSON 结构，cmd 固定为 msg，文本放在 body.content\n  - 发送文件时必须使用 multipart/form-data，不得使用 JSON 传文件\n  - /robot/send 只负责把事件投递给目标 robot，最终是否回发由机器人脚本决定\n  - 如果缺少 robot_endpoint、robot_id 或 robot_key，则不能投递消息，应明确提示缺失项\n\n# 默认设置\ndefaults:\n  language: zh-CN\n  message_type: text\n\nArchive v0.8.4: 12 files, 27345 bytes\n\nFiles: config.yaml (5429b), npm/yntalk-openclaw-init/bin/yntalk-openclaw-init.js (22173b), npm/yntalk-openclaw-init/package.json (389b), npm/yntalk-openclaw-init/README.md (4999b), README.md (9240b), ROBOT_SEND_API.md (7867b), ROBOT_SEND_CURL_API.md (4654b), shell/robot_send.sh (6438b), shell/util.sh (2626b), skill-card.md (2313b), SKILL.md (3420b), _meta.json (132b)\n\nFile v0.8.4:SKILL.md\n\n---\nname: yunitalk-beta\ndescription: 该技能用于 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\nversion: 0.8.4\nbuild: 20260613\n---\n\n# OpenClaw 会话技能\n\n你可以通过 Talk Robots `/robot/send` 把文本或文件事件投递给当前聊聊机器人。OpenClaw 会管理用户身份，但每次发送都必须使用当前会话的 `cvs_id`，并保持大小写原样。\n\n## 初始化流程\n\n本集成只使用一条初始化指令：\n\n```text\n/openclaw --init <base64-json>\n```\n\n`<base64-json>` 是对下面 JSON 做 UTF-8 Base64 编码后的内容：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}\n```\n\n安装或首次加载完成后，如果 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN` 都可用，请生成并输出这条指令，让用户发送到聊聊 OpenClaw 机器人会话。推荐使用：\n\n```bash\n./shell/util.sh --openclaw-init \\\n  --openclaw-url \"${OPENCLAW_URL}\" \\\n  --openclaw-token \"${OPENCLAW_TOKEN}\"\n```\n\n本 skill 的 `config.yaml` 已声明 `install.post_install.command`，OpenClaw 安装器应在安装完成后执行该命令并展示 stdout；stdout 默认就是完整初始化指令。\n\n不要明文展示 `OPENCLAW_TOKEN`。Base64 不是加密，不要把初始化指令发送到不可信渠道。\n\n## Talk Robots 回传配置\n\nTalk Robots 机器人收到 init 指令后会：\n\n1. Base64 decode init JSON，保存 `OPENCLAW_URL`、`OPENCLAW_TOKEN` 和可选 `OPENCLAW_LAN_URL`。\n2. 向 OpenClaw 发送 ping/pong 自检。\n3. 自检成功后，把 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 组成 JSON，并以 Base64(JSON UTF-8) 回传给 OpenClaw。\n\n收到回传后，先 Base64 decode，再保存为本 skill 配置：\n\n| 字段 | 环境变量 | 说明 |\n|------|----------|------|\n| `robot_endpoint` | `TALK_ROBOT_ENDPOINT` | Talk Robots `/v1/robot/send` 地址 |\n| `robot_id` | `TALK_ROBOT_ID` | 机器人 ID |\n| `robot_key` | `TALK_ROBOT_KEY` | 机器人签名密钥 |\n| `cvs_id` | `TALK_ROBOT_CVS_ID` | 当前会话 ID |\n\n配置成功后只简短确认，不要回显 `robot_key`。\n\n## 发送消息\n\n优先使用 `shell/robot_send.sh`，不要手写签名。\n\n### 文本\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 文件\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n不确定参数是否正确时先加 `--dry-run`。\n\n## Rules\n\n1. 只使用 `/openclaw --init <base64-json>` 完成初始化，不再引导用户使用其他配置命令。\n2. 发送前必须确认 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 都存在。\n3. `cvs_id` 必须来自当前会话上下文，严禁猜测、改大小写或从 session key 推导。\n4. 文本消息使用完整 `imx.Msg` JSON，`cmd=msg`，文本放 `body.content`。\n5. 文件消息使用 `multipart/form-data`，通过 `file` 字段上传。\n6. `/robot/send` 只是把事件投递给目标 robot，最终是否回发由机器人脚本决定。\n7. 不要明文展示 `OPENCLAW_TOKEN` 或 `robot_key`，不要虚构配置或用户资料。\n\nFile v0.8.4:npm/yntalk-openclaw-init/README.md\n\n# yntalk-openclaw-init\n\n`yntalk-openclaw-init` 用于生成 Talk Robots OpenClaw 机器人的初始化指令和命令行二维码。\n\n它会读取本机 OpenClaw 的 `openclaw.json`，从 Gateway 配置中获取端口、绑定模式和 `gateway.auth.token`，再探测本机局域网 IPv4 与公网 IP，生成可直接发送到聊聊机器人的连接字符串。\n\n该工具没有运行时依赖，二维码使用终端黑白字符块绘制。\n\n## 二维码内容\n\n二维码内容就是一条初始化命令：\n\n```text\n/openclaw --init <base64-json>\n```\n\n`<base64-json>` 是下面 JSON 的 UTF-8 Base64 编码：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}\n```\n\n`docs/openclaw-robot.js` 可以识别这个格式。你可以把完整命令发送到 Talk Robots 的 OpenClaw 机器人会话，也可以在机器人配置页的 `OpenClaw连接信息` 字段中扫码保存。\n\n## 安装\n\n不安装，直接运行：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n全局安装后运行：\n\n```bash\nnpm install -g yntalk-openclaw-init\nyntalk-openclaw-init\n```\n\n在本仓库中调试本地版本：\n\n```bash\nnpx ./docs/skills/yunitalk-beta/npm/yntalk-openclaw-init\n```\n\n## 使用\n\n默认无参数运行：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n无参数运行会自动获取当前 OpenClaw 连接信息，并输出：\n\n- 局域网访问地址\n- 局域网 OpenAI Base URL\n- 公网访问地址\n- 公网 OpenAI Base URL\n- Gateway 状态\n- `/openclaw --init <base64-json>` 连接字符串\n- 1x1 scale 命令行二维码\n\n命令行参数只支持：\n\n```bash\nnpx yntalk-openclaw-init -h\nnpx yntalk-openclaw-init -v\n```\n\n全局安装后也可以这样运行：\n\n```bash\nyntalk-openclaw-init\nyntalk-openclaw-init -h\nyntalk-openclaw-init -v\n```\n\n参数说明：\n\n- `-h` / `--help`：显示帮助\n- `-v` / `--verbose`：打印配置查找、Gateway 推导和公网 IP 探测日志\n\n## 默认读取逻辑\n\n工具默认会：\n\n- 查找并读取本地 `openclaw.json`\n- 从 `gateway.port` 读取 Gateway 端口，缺省为 `18789`\n- 从 `gateway.bind` 读取 Gateway 绑定模式\n- 从 `gateway.auth.token` 读取 `OPENCLAW_TOKEN`\n- 检查 `gateway.http.endpoints.chatCompletions.enabled`\n- 探测本机局域网 IPv4 和公网 IP\n- 使用公网 Gateway 根地址作为初始化 JSON 中的 `OPENCLAW_URL`\n- 使用局域网 Gateway 根地址作为初始化 JSON 中的 `OPENCLAW_LAN_URL`\n- 额外打印以 `/v1` 结尾的 OpenAI Base URL，方便核对接口地址\n\n注意：初始化 JSON 中的 `OPENCLAW_URL` 不带 `/v1`。`docs/openclaw-robot.js` 会在请求时自动拼接 `/v1/chat/completions`，同时也兼容扫码内容本身已经带 `/v1` 的情况。\n\n## 配置文件位置\n\n工具会按以下位置查找 `openclaw.json`：\n\n- `OPENCLAW_CONFIG` 环境变量指定的路径\n- 当前目录及父目录下的 `openclaw.json`\n- 当前目录及父目录下的 `.openclaw/openclaw.json`\n- `~/openclaw.json`\n- `~/.openclaw/openclaw.json`\n- `~/.config/openclaw/openclaw.json`\n- macOS: `~/Library/Application Support/OpenClaw/openclaw.json`\n\n## 输出示例\n\n```text\n局域网访问地址:\nhttp://192.168.1.10:18789\n\n局域网 OpenAI Base URL:\nhttp://192.168.1.10:18789/v1\n\n公网访问地址:\nhttp://203.0.113.10:18789\n\n公网 OpenAI Base URL:\nhttp://203.0.113.10:18789/v1\n\nGateway:\nbind: all\nport: 18789\nauth_mode: bearer\nchatCompletions: enabled\n\n连接字符串:\n/openclaw --init eyJPUEVOQ0xBV19VUkw...\n\n二维码(1x1):\n████...\n```\n\n如果公网 IP 探测失败，工具会回退到局域网地址，并在 stderr 中打印 warning。此时生成的公网访问地址并不是真正的公网地址。\n\n如果 `gateway.bind` 不是 `lan`、`all`、`0.0.0.0` 或 `::`，工具也会打印 warning，提示公网访问可能失败。\n\n## 常见问题\n\n### 找不到 `openclaw.json`\n\n确认 OpenClaw 已在本机初始化，并且配置文件位于默认查找路径之一。也可以用环境变量显式指定：\n\n```bash\nOPENCLAW_CONFIG=/path/to/openclaw.json npx yntalk-openclaw-init\n```\n\n### Token 为空\n\n确认 `openclaw.json` 中存在：\n\n```json\n{\n  \"gateway\": {\n    \"auth\": {\n      \"token\": \"your-token\"\n    }\n  }\n}\n```\n\n### Chat API 未启用\n\n确认配置中开启了 OpenAI 兼容接口：\n\n```json\n{\n  \"gateway\": {\n    \"http\": {\n      \"endpoints\": {\n        \"chatCompletions\": {\n          \"enabled\": true\n        }\n      }\n    }\n  }\n}\n```\n\n### 二维码扫码后机器人仍访问失败\n\n优先检查输出里的 `公网 OpenAI Base URL` 是否能从 Talk Robots 运行环境访问。`OPENCLAW_URL` 最终会请求：\n\n```text\n<OPENCLAW_URL>/v1/chat/completions\n```\n\n如果你传入的是以 `/v1` 结尾的 OpenAI Base URL，`docs/openclaw-robot.js` 会自动去重，不会拼出重复的 `/v1/v1/chat/completions`。\n\n## 安全提示\n\n`OPENCLAW_TOKEN` 会被编码进初始化指令中。Base64 不是加密，不要把生成的连接字符串或二维码发送到不可信渠道。\n\nFile v0.8.4:README.md\n\n# OpenClaw 与 Talk Robots 集成指南\n\n本 Skill 用于将 OpenClaw 接入与你聊聊 (Talk Robots)。初始化流程只依赖一条由 OpenClaw 生成、用户发送到聊聊机器人的指令：\n\n```text\n/openclaw --init <base64-json>\n```\n\n`<base64-json>` 是对 JSON 做 UTF-8 Base64 编码后的内容，JSON 包含：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}\n```\n\nTalk Robots 机器人收到指令后会 Base64 decode 并保存 OpenClaw 连接信息，执行 ping/pong 连接自检，然后把当前 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 组成 JSON 并以 Base64(JSON UTF-8) 回传给 OpenClaw，使本 Skill 完成环境配置。\n\n## 功能概述\n\n- **双向通信**：用户可以通过聊聊与 OpenClaw 对话。\n- **自动初始化**：通过 `/openclaw --init <base64-json>` 导入 OpenClaw URL/Token。\n- **连接自检**：Talk Robots 机器人会向 OpenClaw 发送“我发送 ping，你帮我回复 pong”验证配置。\n- **环境回传**：自检成功后，机器人会把 `robot_id`、`robot_key`、`cvs_id` 等信息以 Base64(JSON UTF-8) 回传给 OpenClaw。\n- **事件投递**：OpenClaw 可调用 `/robot/send` 将文本或文件事件投递给指定机器人。\n\n## 快速开始\n\n### 1. 安装 Skill\n\n将本 skill 目录（`yunitalk-beta/`）复制到 OpenClaw 的 skills 目录中：\n\n```bash\n# 假设 OpenClaw 安装在 ~/openclaw\nmkdir -p ~/openclaw/skills/yunitalk-beta\ncp config.yaml ~/openclaw/skills/yunitalk-beta/\ncp SKILL.md ~/openclaw/skills/yunitalk-beta/\ncp -R shell ~/openclaw/skills/yunitalk-beta/\nchmod +x ~/openclaw/skills/yunitalk-beta/shell/robot_send.sh\nchmod +x ~/openclaw/skills/yunitalk-beta/shell/util.sh\n```\n\n`shell/robot_send.sh` 和 `shell/util.sh` 依赖 `curl`、`openssl` 和 `python3`。如果 OpenClaw 运行环境是容器，请确认镜像内已安装这些命令。\n\n`config.yaml` 已声明最小安装后钩子：\n\n```yaml\ninstall:\n  post_install:\n    command: [\"./shell/util.sh\", \"--openclaw-init\"]\n    required_env:\n      - OPENCLAW_URL\n      - OPENCLAW_TOKEN\n```\n\nOpenClaw 安装器只需要在安装完成后执行该命令，并把 stdout 原样展示给用户；默认输出就是可发送到聊聊机器人的 `/openclaw --init <base64-json>`。如果客户端需要二维码，建议由安装器对这条 stdout 文本生成二维码，skill 本身不引入额外二维码依赖。\n\n### 2. 生成 `/openclaw --init` 指令\n\n使用 `shell/util.sh` 生成前必须具备：\n\n| 配置项 | 用途 |\n|--------|------|\n| `OPENCLAW_URL` | OpenClaw Gateway 地址 |\n| `OPENCLAW_TOKEN` | OpenClaw Gateway Token |\n\n推荐使用辅助脚本：\n\n```bash\n./shell/util.sh --openclaw-init \\\n  --openclaw-url \"$OPENCLAW_URL\" \\\n  --openclaw-token \"$OPENCLAW_TOKEN\"\n```\n\n如果需要二维码，可以使用 npm CLI 直接读取本机 OpenClaw 连接信息并生成可扫码的初始化指令：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n也可以先全局安装后运行：\n\n```bash\nnpm install -g yntalk-openclaw-init\nyntalk-openclaw-init\n```\n\n在本仓库内调试未发布版本时，可以直接运行本地包：\n\n```bash\nnpx ./docs/skills/yunitalk-beta/npm/yntalk-openclaw-init\n```\n\n本仓库内的 CLI 源码位于 `npm/yntalk-openclaw-init/`；发布到 npm 后即可直接通过上面的 `npx` 命令使用。CLI 默认读取本机 `openclaw.json` 的 `gateway.port`、`gateway.bind`、`gateway.auth.token` 和 `gateway.http.endpoints.chatCompletions.enabled`，使用本机局域网 IPv4 生成局域网访问地址，并探测公网 IP 生成公网访问地址，最后输出完整 `/openclaw --init <base64-json>` 指令和 1x1 scale 命令行二维码。\nCLI 只支持 `-h/--help` 和 `-v/--verbose` 两个参数；默认无参数运行即可输出局域网访问地址、公网访问地址、连接字符串和 1x1 scale 二维码。生成的连接字符串中 `OPENCLAW_URL` 使用公网访问地址，`OPENCLAW_LAN_URL` 保存局域网访问地址。\n提交 `docs/openclaw-robot.js` 后，也可以在机器人配置页的 `OpenClaw连接信息` 参数中扫码保存该二维码内容，脚本会自动解析并写入 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN`。\n\n输出示例：\n\n```text\n局域网访问地址:\nhttp://192.168.1.10:3000\n\n公网访问地址:\nhttp://203.0.113.10:3000\n\n连接字符串:\n/openclaw --init eyJPUEVOQ0xBV19VUkw...\n\n二维码(1x1):\n████...\n```\n\n使用 `shell/util.sh` 时如果缺少 `OPENCLAW_URL` 或 `OPENCLAW_TOKEN`，不要猜测，也不要输出占位符；请先补齐配置。Base64 不是加密，不要把 `OPENCLAW_TOKEN` 明文或初始化指令发送到不可信渠道。\nnpx CLI 默认会自动读取本地 `openclaw.json` 的 Gateway 配置，探测公网 IP 生成公网访问地址，并从 `gateway.auth.token` 获取 Token，不需要手动传入这些配置。\n\n### 3. 在聊聊机器人中执行初始化\n\n把完整指令发送到 Talk Robots 的 OpenClaw 机器人会话：\n\n```text\n/openclaw --init <base64-json>\n```\n\n机器人会自动执行：\n\n1. 对 `<base64-json>` 执行 Base64 decode，得到包含 `OPENCLAW_URL`、`OPENCLAW_TOKEN` 和可选 `OPENCLAW_LAN_URL` 的 JSON。\n2. 写入 `OPENCLAW_URL`、`OPENCLAW_TOKEN` 和可选 `OPENCLAW_LAN_URL`。\n3. 请求 OpenClaw，发送“我发送 ping，你帮我回复 pong”并期待只返回 `pong`。\n4. 自检成功后，向 OpenClaw 发送当前 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 的 Base64(JSON UTF-8)。\n5. OpenClaw Base64 decode 回传信息后完成 `yunitalk-beta` 环境配置。\n\n初始化完成后，用户在聊聊里直接发送普通消息即可开始对话。\n\n## OpenClaw Skill 环境变量\n\n初始化成功后，OpenClaw 应保存以下配置供本 Skill 使用：\n\n| 环境变量 | 对应配置项 | 必填 | 说明 |\n|----------|-----------|------|------|\n| `TALK_ROBOT_ENDPOINT` | `robot_endpoint` | 是 | Talk Robots `/v1/robot/send` 服务端点 |\n| `TALK_ROBOT_ID` | `robot_id` | 是 | 机器人 ID，用于签名鉴权 |\n| `TALK_ROBOT_KEY` | `robot_key` | 是 | 机器人密钥，用于签名鉴权 |\n| `TALK_ROBOT_CVS_ID` | `cvs_id` | 是 | 当前会话 ID，用于主动投递消息 |\n\n也可以在 OpenClaw 配置文件 `openclaw.json` 的 `skills.entries` 中持久化：\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"yunitalk-beta\": {\n        \"enabled\": true,\n        \"env\": {\n          \"TALK_ROBOT_ENDPOINT\": \"https://yunitalk-im-dev.yuni.vip/v1/robot/send\",\n          \"TALK_ROBOT_ID\": \"your-robot-id\",\n          \"TALK_ROBOT_KEY\": \"your-robot-key\",\n          \"TALK_ROBOT_CVS_ID\": \"current-cvs-id\"\n        }\n      }\n    }\n  }\n}\n```\n\n不要在普通回复中回显 `TALK_ROBOT_KEY`。\n\n## Talk Robots 机器人脚本配置\n\n将 `docs/openclaw-robot.js` 提交到 Talk Robots。脚本会在收到 `/openclaw --init <base64-json>` 后写入以下 KV：\n\n| 配置项 | 必填 | 说明 |\n|--------|------|------|\n| `OPENCLAW_URL` | 是 | OpenClaw Gateway 地址，例如 `https://your-openclaw-domain`；也兼容以 `/v1` 结尾的 OpenAI Base URL |\n| `OPENCLAW_TOKEN` | 是 | OpenClaw Gateway Token |\n| `TALK_ROBOT_ENDPOINT` | 否 | 回传给 OpenClaw 的 `/v1/robot/send` 地址，默认 `https://yunitalk-im-dev.yuni.vip/v1/robot/send` |\n\n## 机器人消息发送接口\n\nOpenClaw 可以调用 Talk Robots `/robot/send` 将文本或文件事件投递给指定机器人。发送消息时推荐优先使用本 Skill 内置脚本 `shell/robot_send.sh`，它会自动生成 `msg_id`、`noncestr`、`timestamp` 和 HMAC-SHA256 `sign`。\n\n完整的文本消息、文件消息、签名规则和 `curl` 示例见独立文档：\n\n- [ROBOT_SEND_API.md](./ROBOT_SEND_API.md) - 机器人消息发送接口\n\n## 故障排查\n\n### 问题：无法生成 `/openclaw --init`\n\n- 检查 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN` 是否存在。\n- 使用 `./shell/util.sh --openclaw-init --help` 查看参数。\n\n### 问题：初始化 ping/pong 失败\n\n- 检查 `OPENCLAW_URL` 是否能访问 `/v1/chat/completions`。\n- 检查 `OPENCLAW_TOKEN` 是否有效。\n- 确认 OpenClaw 模型收到 ping 时能只回复 `pong`。\n\n### 问题：无法发送消息\n\n1. 检查 `TALK_ROBOT_ENDPOINT`、`TALK_ROBOT_ID`、`TALK_ROBOT_KEY`、`TALK_ROBOT_CVS_ID` 是否完整。\n2. 确认 `cvs_id` 大小写未被改变。\n3. 使用 `shell/robot_send.sh --dry-run` 检查签名 URL 和请求体。\n4. 确认 `/robot/send` 的返回状态和错误信息。\n\n## 注意事项\n\n1. **安全性**：`OPENCLAW_TOKEN` 和 `TALK_ROBOT_KEY` 是敏感信息，请勿提交到代码仓库或普通聊天回复。\n2. **会话 ID 必填**：`cvs_id` 用于指定目标会话，缺失会导致 `/robot/send` 返回参数错误。\n3. **投递语义**：`/robot/send` 只表示事件已投递给机器人；是否最终回消息由机器人脚本决定。\n4. **会话隔离**：每个用户的会话是独立的，OpenClaw 不应跨会话共享上下文。\n\n## 参考文档\n\n- [SKILL.md](./SKILL.md) - OpenClaw 技能详细说明\n- [ROBOT_SEND_API.md](./ROBOT_SEND_API.md) - 机器人消息发送接口\n- [ROBOT_SEND_CURL_API.md](./ROBOT_SEND_CURL_API.md) - 机器人消息 curl 调用示例\n- [config.yaml](./config.yaml) - 技能配置文件\n\nFile v0.8.4:_meta.json\n\n{\n  \"ownerId\": \"kn78g6avmt6xsvd4c2acd7sd5h85dqx6\",\n  \"slug\": \"yunitalk-beta\",\n  \"version\": \"0.8.4\",\n  \"publishedAt\": 1781324630600\n}\n\nFile v0.8.4:ROBOT_SEND_API.md\n\n# Talk Robots 机器人消息发送接口\n\n本文档说明 OpenClaw 通过 Talk Robots `/robot/send` 向与你聊聊机器人投递消息的方式，覆盖文本消息和文件消息两类请求。\n\n`/robot/send` 的语义是把事件投递给目标机器人；机器人是否最终向会话回复，由机器人脚本决定。\n\n## 推荐调用方式\n\n优先使用本 Skill 内置脚本 `shell/robot_send.sh`。脚本会自动生成 `msg_id`、`noncestr`、`timestamp` 和 HMAC-SHA256 `sign`，避免业务侧重复实现签名逻辑。\n\n### 发送文本\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"$TALK_ROBOT_CVS_ID\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 发送文件\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"$TALK_ROBOT_CVS_ID\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n### 发送前预检\n\n使用 `--dry-run` 可以查看签名 URL 和请求体，不会实际发送消息。\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"$TALK_ROBOT_CVS_ID\" \\\n  --content \"测试消息\" \\\n  --dry-run\n```\n\n脚本常用参数：\n\n| 参数 | 必填 | 说明 |\n|------|------|------|\n| `--base-url` | 是 | Talk Robots `/v1/robot/send` 地址，即 `TALK_ROBOT_ENDPOINT` |\n| `--robot-id` | 是 | 机器人 ID |\n| `--robot-key` | 是 | 机器人 Key，用于签名 |\n| `--cvs-id` | 是 | 目标会话 ID，应保持大小写原样 |\n| `--content` | 文本必填，文件可选 | 文本消息内容，或文件说明文本 |\n| `--file` | 文件必填 | 待上传文件路径 |\n| `--refer-msg-id` | 否 | 引用的消息 ID |\n| `--msg-id` | 否 | 指定消息 ID；不传时脚本自动生成 |\n| `--noncestr` | 否 | 指定随机串；不传时脚本自动生成 |\n| `--timestamp` | 否 | 指定 Unix 秒级时间戳；不传时脚本自动生成 |\n| `--at` | 否 | 文本消息的 `at_uid_list`，多个 UID 用英文逗号分隔 |\n| `--mentioned` | 否 | 文本消息的 `mentioned_list`，多个 UID 用英文逗号分隔 |\n| `--dry-run` | 否 | 只打印请求信息，不实际发送 |\n\n## 直接使用 curl\n\n不使用 `shell/robot_send.sh` 时，可以直接用 `curl` 调用 `/robot/send`。完整的签名生成、文本消息和文件消息示例见：\n\n- [ROBOT_SEND_CURL_API.md](./ROBOT_SEND_CURL_API.md) - 机器人消息 curl 调用示例\n\n## 接口总览\n\n**请求方法**：`POST`\n\n**基础地址**：`{robot_endpoint}`\n\n`robot_endpoint` 通常来自 `TALK_ROBOT_ENDPOINT`，例如：\n\n```text\nhttps://yunitalk-im-dev.yuni.vip/v1/robot/send\n```\n\n**鉴权参数**放在 URL 查询参数中：\n\n| 参数 | 必填 | 说明 |\n|------|------|------|\n| `robot_id` | 是 | 机器人 ID |\n| `noncestr` | 是 | 请求随机串 |\n| `timestamp` | 是 | Unix 秒级时间戳 |\n| `msg_id` | 是 | 消息 ID；请求体或表单中的 `msg_id` 必须与 URL 中一致 |\n| `sign` | 是 | 使用 `robot_key` 计算得到的 HMAC-SHA256 签名 |\n\n完整 URL 形态：\n\n```text\n{robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\n```\n\n## 签名规则\n\n签名参数为 `msg_id`、`noncestr`、`robot_id`、`timestamp`。生成 `sign` 时：\n\n1. 按参数 key 字典序排序。\n2. 每个 value 使用 URL encode。\n3. 按 `key=value` 拼接，并用 `&` 连接。\n4. 使用 `robot_key` 对签名原文做 HMAC-SHA256。\n5. 将结果编码为小写十六进制字符串。\n\n签名原文示例：\n\n```text\nmsg_id=<msg_id>&noncestr=<noncestr>&robot_id=<robot_id>&timestamp=<timestamp>\n```\n\nShell 示例：\n\n```bash\nsigning_text=\"msg_id=${msg_id}&noncestr=${noncestr}&robot_id=${robot_id}&timestamp=${timestamp}\"\nsign=\"$(printf '%s' \"$signing_text\" | openssl dgst -sha256 -hmac \"$robot_key\" | awk '{print $2}')\"\n```\n\n实际实现时，`signing_text` 里的 value 需要先 URL encode。推荐直接使用 `shell/robot_send.sh`。\n\n## 发送文本消息\n\n文本消息使用 `application/json`，请求体是完整 `imx.Msg` JSON 结构，`cmd` 固定为 `msg`，文本内容放在 `body.content`。\n\n```http\nPOST {robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\nContent-Type: application/json\n\n{\n  \"cmd\": \"msg\",\n  \"head\": {\n    \"msg_id\": \"消息ID，需与 URL 中 msg_id 一致\",\n    \"cvs_id\": \"目标会话ID\",\n    \"refer_msg_id\": \"可选，引用消息ID\"\n  },\n  \"body\": {\n    \"content\": \"消息内容\",\n    \"at_uid_list\": [\"可选，被 @ 的用户 ID\"],\n    \"mentioned_list\": [\"可选，兼容企业微信类命名\"]\n  }\n}\n```\n\n字段说明：\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `cmd` | 是 | 固定为 `msg` |\n| `head.msg_id` | 是 | 消息 ID，需与 URL 查询参数 `msg_id` 一致 |\n| `head.cvs_id` | 是 | 目标会话 ID |\n| `head.refer_msg_id` | 否 | 引用消息 ID |\n| `body.content` | 是 | 文本、Markdown 或文件说明 |\n| `body.at_uid_list` | 否 | @ 用户列表 |\n| `body.mentioned_list` | 否 | 兼容企业微信类命名的提及列表 |\n\n`curl` 示例：\n\n```bash\ncurl -X POST \"$request_url\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary '{\n    \"cmd\": \"msg\",\n    \"head\": {\n      \"msg_id\": \"'\"$msg_id\"'\",\n      \"cvs_id\": \"'\"$TALK_ROBOT_CVS_ID\"'\"\n    },\n    \"body\": {\n      \"content\": \"你好，任务已经处理完成。\"\n    }\n  }'\n```\n\n## 发送文件消息\n\n文件消息使用 `multipart/form-data`，文件内容必须通过 `file` 字段上传，不要用 JSON 传文件二进制内容。\n\n```http\nPOST {robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\nContent-Type: multipart/form-data\n\nmsg_id: 消息ID，需与 URL 中 msg_id 一致\ncvs_id: 目标会话ID\nfile: <二进制文件内容>\ncontent: <可选，文件说明文本>\nrefer_msg_id: <可选，引用消息ID>\n```\n\n表单字段说明：\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `msg_id` | 是 | 消息 ID，需与 URL 查询参数 `msg_id` 一致 |\n| `cvs_id` | 是 | 目标会话 ID |\n| `file` | 是 | 待上传文件 |\n| `content` | 否 | 文件说明文本 |\n| `refer_msg_id` | 否 | 引用消息 ID |\n\n`curl` 示例：\n\n```bash\ncurl -X POST \"$request_url\" \\\n  -F \"msg_id=$msg_id\" \\\n  -F \"cvs_id=$TALK_ROBOT_CVS_ID\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\"\n```\n\n服务端会把 multipart 文件转换为机器人消息中的 `file_list`，并把文件内容编码为 `data:<content-type>;base64,<payload>` 后投递给目标机器人脚本。\n\n## 响应\n\n成功响应：\n\n```json\n{\n  \"success\": true,\n  \"message\": \"ok\"\n}\n```\n\n常见失败响应：\n\n| HTTP 状态码 | message | 说明 |\n|-------------|---------|------|\n| `400` | `签名参数错误` | 缺少签名查询参数 |\n| `400` | `签名错误` | `sign` 校验失败 |\n| `400` | `msg_id 错误` | 请求体或表单中的 `msg_id` 与 URL 中不一致 |\n| `400` | `参数格式错误` | JSON 结构或字段格式不合法 |\n| `400` | `文件处理错误` | multipart 文件读取失败 |\n| `400` | `参数错误` | 投递给机器人时参数不符合要求 |\n| `404` | `机器人不存在` | `robot_id` 不存在 |\n| `500` | `内部错误` | 服务端处理异常 |\n\n## 注意事项\n\n1. `TALK_ROBOT_KEY` 是敏感信息，不要写入日志、提交到仓库或回显给用户。\n2. `cvs_id` 必须使用初始化时回传的原值，保持大小写不变。\n3. 文本消息使用 JSON，文件消息使用 multipart，不要混用。\n4. `msg_id` 是本次投递的幂等标识之一，URL 和请求体中的值必须一致。\n5. `/robot/send` 只表示事件已投递给目标机器人，不保证机器人脚本一定会回复。\n\nFile v0.8.4:ROBOT_SEND_CURL_API.md\n\n# Talk Robots 机器人消息 curl 调用示例\n\n本文档说明不使用 `shell/robot_send.sh` 时，如何直接用 `curl` 调用 Talk Robots `/robot/send` 投递文本消息和文件消息。\n\n示例依赖 `curl`、`openssl` 和 `python3`。\n\n## 准备公共变量\n\n```bash\nTALK_ROBOT_ENDPOINT=\"https://yunitalk-im-dev.yuni.vip/v1/robot/send\"\nTALK_ROBOT_ID=\"your-robot-id\"\nTALK_ROBOT_KEY=\"your-robot-key\"\nTALK_ROBOT_CVS_ID=\"your-cvs-id\"\n```\n\n字段说明：\n\n| 变量 | 说明 |\n|------|------|\n| `TALK_ROBOT_ENDPOINT` | Talk Robots `/v1/robot/send` 地址 |\n| `TALK_ROBOT_ID` | 机器人 ID |\n| `TALK_ROBOT_KEY` | 机器人 Key，用于 HMAC-SHA256 签名 |\n| `TALK_ROBOT_CVS_ID` | 目标会话 ID，必须保持大小写原样 |\n\n## 生成签名 URL\n\n```bash\ntimestamp=\"$(date +%s)\"\nmsg_id=\"msg_${timestamp}_$(python3 -c 'import uuid; print(uuid.uuid4().hex)')\"\nnoncestr=\"nonce_${timestamp}_$(python3 -c 'import uuid; print(uuid.uuid4().hex)')\"\n\nurlencode() {\n  python3 -c 'import sys, urllib.parse; print(urllib.parse.quote_plus(sys.argv[1]))' \"$1\"\n}\n\nsigning_text=\"msg_id=$(urlencode \"$msg_id\")&noncestr=$(urlencode \"$noncestr\")&robot_id=$(urlencode \"$TALK_ROBOT_ID\")&timestamp=$(urlencode \"$timestamp\")\"\nsign=\"$(printf '%s' \"$signing_text\" | openssl dgst -sha256 -hmac \"$TALK_ROBOT_KEY\" | awk '{print $2}')\"\n\nrequest_url=\"${TALK_ROBOT_ENDPOINT}?robot_id=$(urlencode \"$TALK_ROBOT_ID\")&noncestr=$(urlencode \"$noncestr\")&timestamp=$(urlencode \"$timestamp\")&msg_id=$(urlencode \"$msg_id\")&sign=$(urlencode \"$sign\")\"\n```\n\n签名原文由 `msg_id`、`noncestr`、`robot_id`、`timestamp` 按 key 字典序排序后拼接，且每个 value 都需要先 URL encode：\n\n```text\nmsg_id=<msg_id>&noncestr=<noncestr>&robot_id=<robot_id>&timestamp=<timestamp>\n```\n\n## curl 发送文本消息\n\n文本消息使用 `application/json`，请求体是完整 `imx.Msg` JSON 结构，`cmd` 固定为 `msg`，文本内容放在 `body.content`。\n\n```bash\ncurl -sS -X POST \"$request_url\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary \"$(python3 - <<PY\nimport json\n\npayload = {\n    \"cmd\": \"msg\",\n    \"head\": {\n        \"msg_id\": \"${msg_id}\",\n        \"cvs_id\": \"${TALK_ROBOT_CVS_ID}\"\n    },\n    \"body\": {\n        \"content\": \"你好，任务已经处理完成。\"\n    }\n}\nprint(json.dumps(payload, ensure_ascii=False, separators=(\",\", \":\")))\nPY\n)\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n带引用消息的文本请求：\n\n```bash\nREFER_MSG_ID=\"source-msg-id\"\n\ncurl -sS -X POST \"$request_url\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary \"$(python3 - <<PY\nimport json\n\npayload = {\n    \"cmd\": \"msg\",\n    \"head\": {\n        \"msg_id\": \"${msg_id}\",\n        \"cvs_id\": \"${TALK_ROBOT_CVS_ID}\",\n        \"refer_msg_id\": \"${REFER_MSG_ID}\"\n    },\n    \"body\": {\n        \"content\": \"这是引用回复。\"\n    }\n}\nprint(json.dumps(payload, ensure_ascii=False, separators=(\",\", \":\")))\nPY\n)\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n## curl 发送文件消息\n\n文件消息使用 `multipart/form-data`，文件内容必须通过 `file` 字段上传，不要用 JSON 传文件二进制内容。\n\n```bash\ncurl -sS -X POST \"$request_url\" \\\n  -F \"msg_id=$msg_id\" \\\n  -F \"cvs_id=$TALK_ROBOT_CVS_ID\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n带引用消息的文件请求：\n\n```bash\ncurl -sS -X POST \"$request_url\" \\\n  -F \"msg_id=$msg_id\" \\\n  -F \"cvs_id=$TALK_ROBOT_CVS_ID\" \\\n  -F \"refer_msg_id=source-msg-id\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n## 响应示例\n\n成功响应：\n\n```json\n{\n  \"success\": true,\n  \"message\": \"ok\"\n}\n```\n\n常见失败响应：\n\n| HTTP 状态码 | message | 说明 |\n|-------------|---------|------|\n| `400` | `签名参数错误` | 缺少签名查询参数 |\n| `400` | `签名错误` | `sign` 校验失败 |\n| `400` | `msg_id 错误` | 请求体或表单中的 `msg_id` 与 URL 中不一致 |\n| `400` | `参数格式错误` | JSON 结构或字段格式不合法 |\n| `400` | `文件处理错误` | multipart 文件读取失败 |\n| `404` | `机器人不存在` | `robot_id` 不存在 |\n| `500` | `内部错误` | 服务端处理异常 |\n\n## 注意事项\n\n1. `TALK_ROBOT_KEY` 是敏感信息，不要写入日志、提交到仓库或回显给用户。\n2. `msg_id` 必须同时出现在 URL 查询参数和请求体或表单中，并保持一致。\n3. `cvs_id` 必须使用初始化时回传的原值，保持大小写不变。\n4. 文本消息使用 JSON，文件消息使用 multipart，不要混用。\n5. `/robot/send` 只表示事件已投递给目标机器人，不保证机器人脚本一定会回复。\n\nFile v0.8.4:skill-card.md\n\n## Description: <br>\nYunitalk Beta connects OpenClaw to Talk Robots so users can exchange messages through a Talk Robots bot. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[blackbeans](https://clawhub.ai/user/blackbeans) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and OpenClaw users use this skill to initialize a Talk Robots bridge, receive robot connection settings, and send text or file events back to the current Talk Robots conversation. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill requires sensitive OpenClaw and Talk Robots credentials, and initialization data can include an OpenClaw gateway token. <br>\nMitigation: Use the skill only with trusted Talk Robots endpoints, keep generated init commands and QR codes out of untrusted channels, and rotate credentials if they were exposed. <br>\nRisk: The send script can expose signed request details during message sends or dry runs. <br>\nMitigation: Avoid running it in terminals, CI jobs, supervisors, or logs that capture stdout when sensitive request details may be visible. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/blackbeans/yunitalk-beta) <br>\n- [SKILL.md](artifact/SKILL.md) <br>\n- [README.md](artifact/README.md) <br>\n- [ROBOT_SEND_API.md](artifact/ROBOT_SEND_API.md) <br>\n- [ROBOT_SEND_CURL_API.md](artifact/ROBOT_SEND_CURL_API.md) <br>\n- [yntalk-openclaw-init README](artifact/npm/yntalk-openclaw-init/README.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Text, Markdown, Shell commands, Configuration, Guidance] <br>\n**Output Format:** [Markdown guidance with shell commands, JSON snippets, and initialization text] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [May produce an /openclaw --init command containing Base64-encoded OpenClaw connection data.] <br>\n\n## Skill Version(s): <br>\n0.8.4 (source: server release metadata and SKILL.md frontmatter) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v0.8.4:npm/yntalk-openclaw-init/package.json\n\n{\n  \"name\": \"yntalk-openclaw-init\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Generate Talk Robots /openclaw init command and QR code for OpenClaw connection config.\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"bin\": {\n    \"yntalk-openclaw-init\": \"./bin/yntalk-openclaw-init.js\"\n  },\n  \"files\": [\n    \"bin\",\n    \"README.md\"\n  ],\n  \"engines\": {\n    \"node\": \">=18\"\n  },\n  \"dependencies\": {}\n}\n\nFile v0.8.4:config.yaml\n\nversion: 1\nmode: prompt\n\nskill:\n  name: yunitalk-beta\n  display_name: OpenClaw 与你聊聊对话\n  description: 使用 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\n  version: 0.8.4\n  build: 20260613\n\n# 安装完成后由 OpenClaw 安装器执行，并把 stdout 原样展示给用户。\n# 最小闭环：输出一条可直接发给 Talk Robots 机器人的初始化指令。\ninstall:\n  post_install:\n    command: [\"./shell/util.sh\", \"--openclaw-init\"]\n    required_env:\n      - OPENCLAW_URL\n      - OPENCLAW_TOKEN\n    output:\n      type: text\n      description: Talk Robots 初始化指令，格式为 /openclaw --init <base64-json>\n\n# OpenClaw 侧由 /openclaw --init 流程写入 Talk Robots 连接信息\nconfig:\n  # Talk Robots 服务端点\n  robot_endpoint:\n    type: string\n    required: false\n    description: Talk Robots 服务端点地址，用于发送消息；默认值为 https://yunitalk-im-dev.yuni.vip/v1/robot/send，可通过环境变量 TALK_ROBOT_ENDPOINT 覆盖\n    default: \"https://yunitalk-im-dev.yuni.vip/v1/robot/send\"\n\n  # 机器人 ID\n  robot_id:\n    type: string\n    required: false\n    description: 机器人 ID，用于签名鉴权；初始化成功后从环境变量 TALK_ROBOT_ID 读取\n    default: \"${TALK_ROBOT_ID}\"\n\n  # 机器人密钥\n  robot_key:\n    type: string\n    required: false\n    description: 机器人密钥，用于 /robot/send 签名鉴权；初始化成功后从环境变量 TALK_ROBOT_KEY 读取\n    default: \"${TALK_ROBOT_KEY}\"\n\n  # 可选：默认 agent ID\n  default_agent_id:\n    type: string\n    required: false\n    description: 默认使用的 OpenClaw Agent ID\n    default: main\n\n# 运行时变量（由 Talk Robots 调用时注入）\nvariables:\n  cvs_id:\n    type: string\n    description: 当前会话ID，由 Talk Robots 在调用时注入\n\n# 能力声明（用于 MCP 模式，prompt 模式下可忽略）\ncapabilities:\n  send_text:\n    enabled: true\n    description: 通过 Robot 消息接口投递文本事件给指定机器人；JSON 请求体使用完整 imx.Msg 结构\n    endpoint: \"{{config.robot_endpoint}}?robot_id={{config.robot_id}}&noncestr={{nonce}}&timestamp={{timestamp}}&msg_id={{msg_id}}&sign={{sign}}\"\n    method: POST\n    content_type: application/json\n    payload_schema:\n      type: object\n      properties:\n        cmd:\n          type: string\n          const: msg\n          description: 固定为 msg\n        head:\n          type: object\n          properties:\n            msg_id:\n              type: string\n              description: 消息 ID，需与 URL 中 msg_id 一致\n            cvs_id:\n              type: string\n              description: 目标会话 ID\n            refer_msg_id:\n              type: string\n              description: 可选，引用消息 ID\n          required: [msg_id, cvs_id]\n        body:\n          type: object\n          properties:\n            content:\n              type: string\n              description: 文本内容、Markdown 内容或文件说明\n            file_list:\n              type: array\n              description: 文件数组，元素为 RobotFile\n            at_uid_list:\n              type: array\n              description: \"@ 用户列表\"\n            mentioned_list:\n              type: array\n              description: 兼容企业微信类命名\n          required: [content]\n      required: [cmd, head, body]\n\n  send_file:\n    enabled: true\n    description: 通过 Robot 消息接口投递文件事件给指定机器人\n    endpoint: \"{{config.robot_endpoint}}?robot_id={{config.robot_id}}&noncestr={{nonce}}&timestamp={{timestamp}}&msg_id={{msg_id}}&sign={{sign}}\"\n    method: POST\n    content_type: multipart/form-data\n    form_fields:\n      msg_id:\n        type: string\n        required: true\n        description: 消息ID，需与 URL 中 msg_id 一致\n      cvs_id:\n        type: string\n        required: true\n        description: 目标会话ID\n      file:\n        type: binary\n        required: true\n        description: 文件二进制内容\n      content:\n        type: string\n        required: false\n        description: 可选，文件说明文本\n      refer_msg_id:\n        type: string\n        required: false\n        description: 可选，引用消息 ID\n\n# 规则（用于 AI 遵循）\nrules:\n  - OpenClaw 会自动管理当前会话的身份标识\n  - 初始化入口只使用 /openclaw --init <base64-json>；不要再引导用户使用其他配置命令\n  - 安装或首次加载完成后，如 OPENCLAW_URL、OPENCLAW_TOKEN 均可用，应输出 /openclaw --init <base64-json>\n  - <base64-json> 必须是对 {\"OPENCLAW_URL\":\"...\",\"OPENCLAW_TOKEN\":\"...\",\"OPENCLAW_LAN_URL\":\"...\"} 做 UTF-8 Base64 编码后的结果；不得明文展示 OPENCLAW_TOKEN 或 robot_key\n  - 收到 Talk Robots 机器人回传的 Base64(JSON UTF-8) 配置后，应先 decode 得到 robot_endpoint、robot_id、robot_key、cvs_id，完成 yunitalk-beta 环境配置，并且不要回显 robot_key\n  - 投递文本事件时必须使用完整 imx.Msg JSON 结构，cmd 固定为 msg，文本放在 body.content\n  - 发送文件时必须使用 multipart/form-data，不得使用 JSON 传文件\n  - /robot/send 只负责把事件投递给目标 robot，最终是否回发由机器人脚本决定\n  - 如果缺少 robot_endpoint、robot_id、robot_key 或 cvs_id，则不能投递消息，应明确提示缺失项\n\n# 默认设置\ndefaults:\n  language: zh-CN\n  message_type: text\n\nArchive v0.8.3: 12 files, 26899 bytes\n\nFiles: config.yaml (5429b), npm/yntalk-openclaw-init/bin/yntalk-openclaw-init.js (23050b), npm/yntalk-openclaw-init/package.json (389b), npm/yntalk-openclaw-init/README.md (2571b), README.md (9301b), ROBOT_SEND_API.md (7867b), ROBOT_SEND_CURL_API.md (4654b), shell/robot_send.sh (6438b), shell/util.sh (2626b), skill-card.md (2771b), SKILL.md (3420b), _meta.json (132b)\n\nFile v0.8.3:SKILL.md\n\n---\nname: yunitalk-beta\ndescription: 该技能用于 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\nversion: 0.8.3\nbuild: 20260612\n---\n\n# OpenClaw 会话技能\n\n你可以通过 Talk Robots `/robot/send` 把文本或文件事件投递给当前聊聊机器人。OpenClaw 会管理用户身份，但每次发送都必须使用当前会话的 `cvs_id`，并保持大小写原样。\n\n## 初始化流程\n\n本集成只使用一条初始化指令：\n\n```text\n/openclaw --init <base64-json>\n```\n\n`<base64-json>` 是对下面 JSON 做 UTF-8 Base64 编码后的内容：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}\n```\n\n安装或首次加载完成后，如果 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN` 都可用，请生成并输出这条指令，让用户发送到聊聊 OpenClaw 机器人会话。推荐使用：\n\n```bash\n./shell/util.sh --openclaw-init \\\n  --openclaw-url \"${OPENCLAW_URL}\" \\\n  --openclaw-token \"${OPENCLAW_TOKEN}\"\n```\n\n本 skill 的 `config.yaml` 已声明 `install.post_install.command`，OpenClaw 安装器应在安装完成后执行该命令并展示 stdout；stdout 默认就是完整初始化指令。\n\n不要明文展示 `OPENCLAW_TOKEN`。Base64 不是加密，不要把初始化指令发送到不可信渠道。\n\n## Talk Robots 回传配置\n\nTalk Robots 机器人收到 init 指令后会：\n\n1. Base64 decode init JSON，保存 `OPENCLAW_URL`、`OPENCLAW_TOKEN` 和可选 `OPENCLAW_LAN_URL`。\n2. 向 OpenClaw 发送 ping/pong 自检。\n3. 自检成功后，把 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 组成 JSON，并以 Base64(JSON UTF-8) 回传给 OpenClaw。\n\n收到回传后，先 Base64 decode，再保存为本 skill 配置：\n\n| 字段 | 环境变量 | 说明 |\n|------|----------|------|\n| `robot_endpoint` | `TALK_ROBOT_ENDPOINT` | Talk Robots `/v1/robot/send` 地址 |\n| `robot_id` | `TALK_ROBOT_ID` | 机器人 ID |\n| `robot_key` | `TALK_ROBOT_KEY` | 机器人签名密钥 |\n| `cvs_id` | `TALK_ROBOT_CVS_ID` | 当前会话 ID |\n\n配置成功后只简短确认，不要回显 `robot_key`。\n\n## 发送消息\n\n优先使用 `shell/robot_send.sh`，不要手写签名。\n\n### 文本\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 文件\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n不确定参数是否正确时先加 `--dry-run`。\n\n## Rules\n\n1. 只使用 `/openclaw --init <base64-json>` 完成初始化，不再引导用户使用其他配置命令。\n2. 发送前必须确认 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 都存在。\n3. `cvs_id` 必须来自当前会话上下文，严禁猜测、改大小写或从 session key 推导。\n4. 文本消息使用完整 `imx.Msg` JSON，`cmd=msg`，文本放 `body.content`。\n5. 文件消息使用 `multipart/form-data`，通过 `file` 字段上传。\n6. `/robot/send` 只是把事件投递给目标 robot，最终是否回发由机器人脚本决定。\n7. 不要明文展示 `OPENCLAW_TOKEN` 或 `robot_key`，不要虚构配置或用户资料。\n\nFile v0.8.3:npm/yntalk-openclaw-init/README.md\n\n# yntalk-openclaw-init\n\nGenerate the Talk Robots OpenClaw initialization command and QR code.\nThe CLI reads the OpenClaw dashboard URL by running the local `openclaw dashboard` command, detects the public IP with `https://api64.ipify.org`, and reads `gateway.auth.token` from local `openclaw.json`.\nIt has no runtime dependencies; the terminal QR code is rendered as a 1x1 scale black and white block mosaic.\n\nThe QR code content is:\n\n```text\n/openclaw --init <base64-json>\n```\n\n`<base64-json>` is UTF-8 Base64 of:\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}\n```\n\nThis is the format recognized by `docs/openclaw-robot.js`.\nYou can send the command to the Talk Robots OpenClaw robot conversation, or scan the QR code into the robot config field named `OpenClaw连接信息`.\n\n## Install\n\nRun directly with npm without installing:\n\n```bash\nnpx yntalk-openclaw-init\n```\n\nOr install globally:\n\n```bash\nnpm install -g yntalk-openclaw-init\nyntalk-openclaw-init\n```\n\nIn this repository, you can also run the local package:\n\n```bash\nnpx ./docs/skills/yunitalk-beta/npm/yntalk-openclaw-init\n```\n\n## Usage\n\nDefault:\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n无参数运行会自动获取当前 OpenClaw 连接信息，并直接输出局域网访问地址、公网访问地址、连接字符串和命令行二维码。\n命令行参数只支持：\n\n```bash\nnpx yntalk-openclaw-init -h\nnpx yntalk-openclaw-init -v\n```\n\nIf installed globally:\n\n```bash\nyntalk-openclaw-init\nyntalk-openclaw-init -h\nyntalk-openclaw-init -v\n```\n\n`-h` 显示帮助；`-v` 会在读取本机 OpenClaw 信息时打印 dashboard 命令、配置查找和公网 IP 探测日志。\n\nBy default it:\n\n- runs the local `openclaw dashboard` command to get the LAN dashboard URL\n- replaces loopback hosts such as `localhost`, `127.0.0.1`, and `0.0.0.0` with the local LAN IPv4 address\n- calls `https://api64.ipify.org` to detect the public IP\n- builds the public dashboard URL from the LAN dashboard URL and public IP\n- reads local `openclaw.json`\n- reads `OPENCLAW_TOKEN` from `gateway.auth.token`\n- uses the public dashboard URL as `OPENCLAW_URL` in the generated `/openclaw --init` command\n- writes the LAN dashboard URL into `OPENCLAW_LAN_URL`\n\n## Output\n\nBy default the CLI prints the LAN URL, public URL, connection string, and 1x1 scale terminal QR code to stdout.\n\nSend the generated command in the Talk Robots OpenClaw robot conversation, or scan the QR code into the `OpenClaw连接信息` config field.\n\nFile v0.8.3:README.md\n\n# OpenClaw 与 Talk Robots 集成指南\n\n本 Skill 用于将 OpenClaw 接入与你聊聊 (Talk Robots)。初始化流程只依赖一条由 OpenClaw 生成、用户发送到聊聊机器人的指令：\n\n```text\n/openclaw --init <base64-json>\n```\n\n`<base64-json>` 是对 JSON 做 UTF-8 Base64 编码后的内容，JSON 包含：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}\n```\n\nTalk Robots 机器人收到指令后会 Base64 decode 并保存 OpenClaw 连接信息，执行 ping/pong 连接自检，然后把当前 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 组成 JSON 并以 Base64(JSON UTF-8) 回传给 OpenClaw，使本 Skill 完成环境配置。\n\n## 功能概述\n\n- **双向通信**：用户可以通过聊聊与 OpenClaw 对话。\n- **自动初始化**：通过 `/openclaw --init <base64-json>` 导入 OpenClaw URL/Token。\n- **连接自检**：Talk Robots 机器人会向 OpenClaw 发送“我发送 ping，你帮我回复 pong”验证配置。\n- **环境回传**：自检成功后，机器人会把 `robot_id`、`robot_key`、`cvs_id` 等信息以 Base64(JSON UTF-8) 回传给 OpenClaw。\n- **事件投递**：OpenClaw 可调用 `/robot/send` 将文本或文件事件投递给指定机器人。\n\n## 快速开始\n\n### 1. 安装 Skill\n\n将本 skill 目录（`yunitalk-beta/`）复制到 OpenClaw 的 skills 目录中：\n\n```bash\n# 假设 OpenClaw 安装在 ~/openclaw\nmkdir -p ~/openclaw/skills/yunitalk-beta\ncp config.yaml ~/openclaw/skills/yunitalk-beta/\ncp SKILL.md ~/openclaw/skills/yunitalk-beta/\ncp -R shell ~/openclaw/skills/yunitalk-beta/\nchmod +x ~/openclaw/skills/yunitalk-beta/shell/robot_send.sh\nchmod +x ~/openclaw/skills/yunitalk-beta/shell/util.sh\n```\n\n`shell/robot_send.sh` 和 `shell/util.sh` 依赖 `curl`、`openssl` 和 `python3`。如果 OpenClaw 运行环境是容器，请确认镜像内已安装这些命令。\n\n`config.yaml` 已声明最小安装后钩子：\n\n```yaml\ninstall:\n  post_install:\n    command: [\"./shell/util.sh\", \"--openclaw-init\"]\n    required_env:\n      - OPENCLAW_URL\n      - OPENCLAW_TOKEN\n```\n\nOpenClaw 安装器只需要在安装完成后执行该命令，并把 stdout 原样展示给用户；默认输出就是可发送到聊聊机器人的 `/openclaw --init <base64-json>`。如果客户端需要二维码，建议由安装器对这条 stdout 文本生成二维码，skill 本身不引入额外二维码依赖。\n\n### 2. 生成 `/openclaw --init` 指令\n\n使用 `shell/util.sh` 生成前必须具备：\n\n| 配置项 | 用途 |\n|--------|------|\n| `OPENCLAW_URL` | OpenClaw Gateway 地址 |\n| `OPENCLAW_TOKEN` | OpenClaw Gateway Token |\n\n推荐使用辅助脚本：\n\n```bash\n./shell/util.sh --openclaw-init \\\n  --openclaw-url \"$OPENCLAW_URL\" \\\n  --openclaw-token \"$OPENCLAW_TOKEN\"\n```\n\n如果需要二维码，可以使用 npm CLI 直接读取本机 OpenClaw 连接信息并生成可扫码的初始化指令：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n也可以先全局安装后运行：\n\n```bash\nnpm install -g yntalk-openclaw-init\nyntalk-openclaw-init\n```\n\n在本仓库内调试未发布版本时，可以直接运行本地包：\n\n```bash\nnpx ./docs/skills/yunitalk-beta/npm/yntalk-openclaw-init\n```\n\n本仓库内的 CLI 源码位于 `npm/yntalk-openclaw-init/`；发布到 npm 后即可直接通过上面的 `npx` 命令使用。CLI 默认直接运行本机 `openclaw dashboard` 获取局域网访问地址；如果地址是 `localhost`、`127.0.0.1` 或 `0.0.0.0`，会自动替换为本机局域网 IPv4；再通过 `https://api64.ipify.org` 探测公网 IP 并生成公网访问地址，从本地 `openclaw.json` 的 `gateway.auth.token` 解析 Token，最后输出完整 `/openclaw --init <base64-json>` 指令和 1x1 scale 命令行二维码。\nCLI 只支持 `-h/--help` 和 `-v/--verbose` 两个参数；默认无参数运行即可输出局域网访问地址、公网访问地址、连接字符串和 1x1 scale 二维码。生成的连接字符串中 `OPENCLAW_URL` 使用公网访问地址，`OPENCLAW_LAN_URL` 保存局域网访问地址。\n提交 `docs/openclaw-robot.js` 后，也可以在机器人配置页的 `OpenClaw连接信息` 参数中扫码保存该二维码内容，脚本会自动解析并写入 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN`。\n\n输出示例：\n\n```text\n局域网访问地址:\nhttp://192.168.1.10:3000\n\n公网访问地址:\nhttp://203.0.113.10:3000\n\n连接字符串:\n/openclaw --init eyJPUEVOQ0xBV19VUkw...\n\n二维码(1x1):\n████...\n```\n\n使用 `shell/util.sh` 时如果缺少 `OPENCLAW_URL` 或 `OPENCLAW_TOKEN`，不要猜测，也不要输出占位符；请先补齐配置。Base64 不是加密，不要把 `OPENCLAW_TOKEN` 明文或初始化指令发送到不可信渠道。\nnpx CLI 默认会自动运行 `openclaw dashboard` 获取局域网访问地址，探测公网 IP 生成公网访问地址，并读取本地 `openclaw.json` 的 `gateway.auth.token` 获取 Token，不需要手动传入这些配置。\n\n### 3. 在聊聊机器人中执行初始化\n\n把完整指令发送到 Talk Robots 的 OpenClaw 机器人会话：\n\n```text\n/openclaw --init <base64-json>\n```\n\n机器人会自动执行：\n\n1. 对 `<base64-json>` 执行 Base64 decode，得到包含 `OPENCLAW_URL`、`OPENCLAW_TOKEN` 和可选 `OPENCLAW_LAN_URL` 的 JSON。\n2. 写入 `OPENCLAW_URL`、`OPENCLAW_TOKEN` 和可选 `OPENCLAW_LAN_URL`。\n3. 请求 OpenClaw，发送“我发送 ping，你帮我回复 pong”并期待只返回 `pong`。\n4. 自检成功后，向 OpenClaw 发送当前 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 的 Base64(JSON UTF-8)。\n5. OpenClaw Base64 decode 回传信息后完成 `yunitalk-beta` 环境配置。\n\n初始化完成后，用户在聊聊里直接发送普通消息即可开始对话。\n\n## OpenClaw Skill 环境变量\n\n初始化成功后，OpenClaw 应保存以下配置供本 Skill 使用：\n\n| 环境变量 | 对应配置项 | 必填 | 说明 |\n|----------|-----------|------|------|\n| `TALK_ROBOT_ENDPOINT` | `robot_endpoint` | 是 | Talk Robots `/v1/robot/send` 服务端点 |\n| `TALK_ROBOT_ID` | `robot_id` | 是 | 机器人 ID，用于签名鉴权 |\n| `TALK_ROBOT_KEY` | `robot_key` | 是 | 机器人密钥，用于签名鉴权 |\n| `TALK_ROBOT_CVS_ID` | `cvs_id` | 是 | 当前会话 ID，用于主动投递消息 |\n\n也可以在 OpenClaw 配置文件 `openclaw.json` 的 `skills.entries` 中持久化：\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"yunitalk-beta\": {\n        \"enabled\": true,\n        \"env\": {\n          \"TALK_ROBOT_ENDPOINT\": \"https://yunitalk-im-dev.yuni.vip/v1/robot/send\",\n          \"TALK_ROBOT_ID\": \"your-robot-id\",\n          \"TALK_ROBOT_KEY\": \"your-robot-key\",\n          \"TALK_ROBOT_CVS_ID\": \"current-cvs-id\"\n        }\n      }\n    }\n  }\n}\n```\n\n不要在普通回复中回显 `TALK_ROBOT_KEY`。\n\n## Talk Robots 机器人脚本配置\n\n将 `docs/openclaw-robot.js` 提交到 Talk Robots。脚本会在收到 `/openclaw --init <base64-json>` 后写入以下 KV：\n\n| 配置项 | 必填 | 说明 |\n|--------|------|------|\n| `OPENCLAW_URL` | 是 | OpenClaw Gateway 地址，例如 `https://your-openclaw-domain` |\n| `OPENCLAW_TOKEN` | 是 | OpenClaw Gateway Token |\n| `TALK_ROBOT_ENDPOINT` | 否 | 回传给 OpenClaw 的 `/v1/robot/send` 地址，默认 `https://yunitalk-im-dev.yuni.vip/v1/robot/send` |\n\n## 机器人消息发送接口\n\nOpenClaw 可以调用 Talk Robots `/robot/send` 将文本或文件事件投递给指定机器人。发送消息时推荐优先使用本 Skill 内置脚本 `shell/robot_send.sh`，它会自动生成 `msg_id`、`noncestr`、`timestamp` 和 HMAC-SHA256 `sign`。\n\n完整的文本消息、文件消息、签名规则和 `curl` 示例见独立文档：\n\n- [ROBOT_SEND_API.md](./ROBOT_SEND_API.md) - 机器人消息发送接口\n\n## 故障排查\n\n### 问题：无法生成 `/openclaw --init`\n\n- 检查 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN` 是否存在。\n- 使用 `./shell/util.sh --openclaw-init --help` 查看参数。\n\n### 问题：初始化 ping/pong 失败\n\n- 检查 `OPENCLAW_URL` 是否能访问 `/v1/chat/completions`。\n- 检查 `OPENCLAW_TOKEN` 是否有效。\n- 确认 OpenClaw 模型收到 ping 时能只回复 `pong`。\n\n### 问题：无法发送消息\n\n1. 检查 `TALK_ROBOT_ENDPOINT`、`TALK_ROBOT_ID`、`TALK_ROBOT_KEY`、`TALK_ROBOT_CVS_ID` 是否完整。\n2. 确认 `cvs_id` 大小写未被改变。\n3. 使用 `shell/robot_send.sh --dry-run` 检查签名 URL 和请求体。\n4. 确认 `/robot/send` 的返回状态和错误信息。\n\n## 注意事项\n\n1. **安全性**：`OPENCLAW_TOKEN` 和 `TALK_ROBOT_KEY` 是敏感信息，请勿提交到代码仓库或普通聊天回复。\n2. **会话 ID 必填**：`cvs_id` 用于指定目标会话，缺失会导致 `/robot/send` 返回参数错误。\n3. **投递语义**：`/robot/send` 只表示事件已投递给机器人；是否最终回消息由机器人脚本决定。\n4. **会话隔离**：每个用户的会话是独立的，OpenClaw 不应跨会话共享上下文。\n\n## 参考文档\n\n- [SKILL.md](./SKILL.md) - OpenClaw 技能详细说明\n- [ROBOT_SEND_API.md](./ROBOT_SEND_API.md) - 机器人消息发送接口\n- [ROBOT_SEND_CURL_API.md](./ROBOT_SEND_CURL_API.md) - 机器人消息 curl 调用示例\n- [config.yaml](./config.yaml) - 技能配置文件\n\nFile v0.8.3:_meta.json\n\n{\n  \"ownerId\": \"kn78g6avmt6xsvd4c2acd7sd5h85dqx6\",\n  \"slug\": \"yunitalk-beta\",\n  \"version\": \"0.8.3\",\n  \"publishedAt\": 1781263739069\n}\n\nFile v0.8.3:ROBOT_SEND_API.md\n\n# Talk Robots 机器人消息发送接口\n\n本文档说明 OpenClaw 通过 Talk Robots `/robot/send` 向与你聊聊机器人投递消息的方式，覆盖文本消息和文件消息两类请求。\n\n`/robot/send` 的语义是把事件投递给目标机器人；机器人是否最终向会话回复，由机器人脚本决定。\n\n## 推荐调用方式\n\n优先使用本 Skill 内置脚本 `shell/robot_send.sh`。脚本会自动生成 `msg_id`、`noncestr`、`timestamp` 和 HMAC-SHA256 `sign`，避免业务侧重复实现签名逻辑。\n\n### 发送文本\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"$TALK_ROBOT_CVS_ID\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 发送文件\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"$TALK_ROBOT_CVS_ID\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n### 发送前预检\n\n使用 `--dry-run` 可以查看签名 URL 和请求体，不会实际发送消息。\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"$TALK_ROBOT_CVS_ID\" \\\n  --content \"测试消息\" \\\n  --dry-run\n```\n\n脚本常用参数：\n\n| 参数 | 必填 | 说明 |\n|------|------|------|\n| `--base-url` | 是 | Talk Robots `/v1/robot/send` 地址，即 `TALK_ROBOT_ENDPOINT` |\n| `--robot-id` | 是 | 机器人 ID |\n| `--robot-key` | 是 | 机器人 Key，用于签名 |\n| `--cvs-id` | 是 | 目标会话 ID，应保持大小写原样 |\n| `--content` | 文本必填，文件可选 | 文本消息内容，或文件说明文本 |\n| `--file` | 文件必填 | 待上传文件路径 |\n| `--refer-msg-id` | 否 | 引用的消息 ID |\n| `--msg-id` | 否 | 指定消息 ID；不传时脚本自动生成 |\n| `--noncestr` | 否 | 指定随机串；不传时脚本自动生成 |\n| `--timestamp` | 否 | 指定 Unix 秒级时间戳；不传时脚本自动生成 |\n| `--at` | 否 | 文本消息的 `at_uid_list`，多个 UID 用英文逗号分隔 |\n| `--mentioned` | 否 | 文本消息的 `mentioned_list`，多个 UID 用英文逗号分隔 |\n| `--dry-run` | 否 | 只打印请求信息，不实际发送 |\n\n## 直接使用 curl\n\n不使用 `shell/robot_send.sh` 时，可以直接用 `curl` 调用 `/robot/send`。完整的签名生成、文本消息和文件消息示例见：\n\n- [ROBOT_SEND_CURL_API.md](./ROBOT_SEND_CURL_API.md) - 机器人消息 curl 调用示例\n\n## 接口总览\n\n**请求方法**：`POST`\n\n**基础地址**：`{robot_endpoint}`\n\n`robot_endpoint` 通常来自 `TALK_ROBOT_ENDPOINT`，例如：\n\n```text\nhttps://yunitalk-im-dev.yuni.vip/v1/robot/send\n```\n\n**鉴权参数**放在 URL 查询参数中：\n\n| 参数 | 必填 | 说明 |\n|------|------|------|\n| `robot_id` | 是 | 机器人 ID |\n| `noncestr` | 是 | 请求随机串 |\n| `timestamp` | 是 | Unix 秒级时间戳 |\n| `msg_id` | 是 | 消息 ID；请求体或表单中的 `msg_id` 必须与 URL 中一致 |\n| `sign` | 是 | 使用 `robot_key` 计算得到的 HMAC-SHA256 签名 |\n\n完整 URL 形态：\n\n```text\n{robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\n```\n\n## 签名规则\n\n签名参数为 `msg_id`、`noncestr`、`robot_id`、`timestamp`。生成 `sign` 时：\n\n1. 按参数 key 字典序排序。\n2. 每个 value 使用 URL encode。\n3. 按 `key=value` 拼接，并用 `&` 连接。\n4. 使用 `robot_key` 对签名原文做 HMAC-SHA256。\n5. 将结果编码为小写十六进制字符串。\n\n签名原文示例：\n\n```text\nmsg_id=<msg_id>&noncestr=<noncestr>&robot_id=<robot_id>&timestamp=<timestamp>\n```\n\nShell 示例：\n\n```bash\nsigning_text=\"msg_id=${msg_id}&noncestr=${noncestr}&robot_id=${robot_id}&timestamp=${timestamp}\"\nsign=\"$(printf '%s' \"$signing_text\" | openssl dgst -sha256 -hmac \"$robot_key\" | awk '{print $2}')\"\n```\n\n实际实现时，`signing_text` 里的 value 需要先 URL encode。推荐直接使用 `shell/robot_send.sh`。\n\n## 发送文本消息\n\n文本消息使用 `application/json`，请求体是完整 `imx.Msg` JSON 结构，`cmd` 固定为 `msg`，文本内容放在 `body.content`。\n\n```http\nPOST {robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\nContent-Type: application/json\n\n{\n  \"cmd\": \"msg\",\n  \"head\": {\n    \"msg_id\": \"消息ID，需与 URL 中 msg_id 一致\",\n    \"cvs_id\": \"目标会话ID\",\n    \"refer_msg_id\": \"可选，引用消息ID\"\n  },\n  \"body\": {\n    \"content\": \"消息内容\",\n    \"at_uid_list\": [\"可选，被 @ 的用户 ID\"],\n    \"mentioned_list\": [\"可选，兼容企业微信类命名\"]\n  }\n}\n```\n\n字段说明：\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `cmd` | 是 | 固定为 `msg` |\n| `head.msg_id` | 是 | 消息 ID，需与 URL 查询参数 `msg_id` 一致 |\n| `head.cvs_id` | 是 | 目标会话 ID |\n| `head.refer_msg_id` | 否 | 引用消息 ID |\n| `body.content` | 是 | 文本、Markdown 或文件说明 |\n| `body.at_uid_list` | 否 | @ 用户列表 |\n| `body.mentioned_list` | 否 | 兼容企业微信类命名的提及列表 |\n\n`curl` 示例：\n\n```bash\ncurl -X POST \"$request_url\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary '{\n    \"cmd\": \"msg\",\n    \"head\": {\n      \"msg_id\": \"'\"$msg_id\"'\",\n      \"cvs_id\": \"'\"$TALK_ROBOT_CVS_ID\"'\"\n    },\n    \"body\": {\n      \"content\": \"你好，任务已经处理完成。\"\n    }\n  }'\n```\n\n## 发送文件消息\n\n文件消息使用 `multipart/form-data`，文件内容必须通过 `file` 字段上传，不要用 JSON 传文件二进制内容。\n\n```http\nPOST {robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\nContent-Type: multipart/form-data\n\nmsg_id: 消息ID，需与 URL 中 msg_id 一致\ncvs_id: 目标会话ID\nfile: <二进制文件内容>\ncontent: <可选，文件说明文本>\nrefer_msg_id: <可选，引用消息ID>\n```\n\n表单字段说明：\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `msg_id` | 是 | 消息 ID，需与 URL 查询参数 `msg_id` 一致 |\n| `cvs_id` | 是 | 目标会话 ID |\n| `file` | 是 | 待上传文件 |\n| `content` | 否 | 文件说明文本 |\n| `refer_msg_id` | 否 | 引用消息 ID |\n\n`curl` 示例：\n\n```bash\ncurl -X POST \"$request_url\" \\\n  -F \"msg_id=$msg_id\" \\\n  -F \"cvs_id=$TALK_ROBOT_CVS_ID\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\"\n```\n\n服务端会把 multipart 文件转换为机器人消息中的 `file_list`，并把文件内容编码为 `data:<content-type>;base64,<payload>` 后投递给目标机器人脚本。\n\n## 响应\n\n成功响应：\n\n```json\n{\n  \"success\": true,\n  \"message\": \"ok\"\n}\n```\n\n常见失败响应：\n\n| HTTP 状态码 | message | 说明 |\n|-------------|---------|------|\n| `400` | `签名参数错误` | 缺少签名查询参数 |\n| `400` | `签名错误` | `sign` 校验失败 |\n| `400` | `msg_id 错误` | 请求体或表单中的 `msg_id` 与 URL 中不一致 |\n| `400` | `参数格式错误` | JSON 结构或字段格式不合法 |\n| `400` | `文件处理错误` | multipart 文件读取失败 |\n| `400` | `参数错误` | 投递给机器人时参数不符合要求 |\n| `404` | `机器人不存在` | `robot_id` 不存在 |\n| `500` | `内部错误` | 服务端处理异常 |\n\n## 注意事项\n\n1. `TALK_ROBOT_KEY` 是敏感信息，不要写入日志、提交到仓库或回显给用户。\n2. `cvs_id` 必须使用初始化时回传的原值，保持大小写不变。\n3. 文本消息使用 JSON，文件消息使用 multipart，不要混用。\n4. `msg_id` 是本次投递的幂等标识之一，URL 和请求体中的值必须一致。\n5. `/robot/send` 只表示事件已投递给目标机器人，不保证机器人脚本一定会回复。\n\nFile v0.8.3:ROBOT_SEND_CURL_API.md\n\n# Talk Robots 机器人消息 curl 调用示例\n\n本文档说明不使用 `shell/robot_send.sh` 时，如何直接用 `curl` 调用 Talk Robots `/robot/send` 投递文本消息和文件消息。\n\n示例依赖 `curl`、`openssl` 和 `python3`。\n\n## 准备公共变量\n\n```bash\nTALK_ROBOT_ENDPOINT=\"https://yunitalk-im-dev.yuni.vip/v1/robot/send\"\nTALK_ROBOT_ID=\"your-robot-id\"\nTALK_ROBOT_KEY=\"your-robot-key\"\nTALK_ROBOT_CVS_ID=\"your-cvs-id\"\n```\n\n字段说明：\n\n| 变量 | 说明 |\n|------|------|\n| `TALK_ROBOT_ENDPOINT` | Talk Robots `/v1/robot/send` 地址 |\n| `TALK_ROBOT_ID` | 机器人 ID |\n| `TALK_ROBOT_KEY` | 机器人 Key，用于 HMAC-SHA256 签名 |\n| `TALK_ROBOT_CVS_ID` | 目标会话 ID，必须保持大小写原样 |\n\n## 生成签名 URL\n\n```bash\ntimestamp=\"$(date +%s)\"\nmsg_id=\"msg_${timestamp}_$(python3 -c 'import uuid; print(uuid.uuid4().hex)')\"\nnoncestr=\"nonce_${timestamp}_$(python3 -c 'import uuid; print(uuid.uuid4().hex)')\"\n\nurlencode() {\n  python3 -c 'import sys, urllib.parse; print(urllib.parse.quote_plus(sys.argv[1]))' \"$1\"\n}\n\nsigning_text=\"msg_id=$(urlencode \"$msg_id\")&noncestr=$(urlencode \"$noncestr\")&robot_id=$(urlencode \"$TALK_ROBOT_ID\")&timestamp=$(urlencode \"$timestamp\")\"\nsign=\"$(printf '%s' \"$signing_text\" | openssl dgst -sha256 -hmac \"$TALK_ROBOT_KEY\" | awk '{print $2}')\"\n\nrequest_url=\"${TALK_ROBOT_ENDPOINT}?robot_id=$(urlencode \"$TALK_ROBOT_ID\")&noncestr=$(urlencode \"$noncestr\")&timestamp=$(urlencode \"$timestamp\")&msg_id=$(urlencode \"$msg_id\")&sign=$(urlencode \"$sign\")\"\n```\n\n签名原文由 `msg_id`、`noncestr`、`robot_id`、`timestamp` 按 key 字典序排序后拼接，且每个 value 都需要先 URL encode：\n\n```text\nmsg_id=<msg_id>&noncestr=<noncestr>&robot_id=<robot_id>&timestamp=<timestamp>\n```\n\n## curl 发送文本消息\n\n文本消息使用 `application/json`，请求体是完整 `imx.Msg` JSON 结构，`cmd` 固定为 `msg`，文本内容放在 `body.content`。\n\n```bash\ncurl -sS -X POST \"$request_url\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary \"$(python3 - <<PY\nimport json\n\npayload = {\n    \"cmd\": \"msg\",\n    \"head\": {\n        \"msg_id\": \"${msg_id}\",\n        \"cvs_id\": \"${TALK_ROBOT_CVS_ID}\"\n    },\n    \"body\": {\n        \"content\": \"你好，任务已经处理完成。\"\n    }\n}\nprint(json.dumps(payload, ensure_ascii=False, separators=(\",\", \":\")))\nPY\n)\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n带引用消息的文本请求：\n\n```bash\nREFER_MSG_ID=\"source-msg-id\"\n\ncurl -sS -X POST \"$request_url\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary \"$(python3 - <<PY\nimport json\n\npayload = {\n    \"cmd\": \"msg\",\n    \"head\": {\n        \"msg_id\": \"${msg_id}\",\n        \"cvs_id\": \"${TALK_ROBOT_CVS_ID}\",\n        \"refer_msg_id\": \"${REFER_MSG_ID}\"\n    },\n    \"body\": {\n        \"content\": \"这是引用回复。\"\n    }\n}\nprint(json.dumps(payload, ensure_ascii=False, separators=(\",\", \":\")))\nPY\n)\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n## curl 发送文件消息\n\n文件消息使用 `multipart/form-data`，文件内容必须通过 `file` 字段上传，不要用 JSON 传文件二进制内容。\n\n```bash\ncurl -sS -X POST \"$request_url\" \\\n  -F \"msg_id=$msg_id\" \\\n  -F \"cvs_id=$TALK_ROBOT_CVS_ID\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n带引用消息的文件请求：\n\n```bash\ncurl -sS -X POST \"$request_url\" \\\n  -F \"msg_id=$msg_id\" \\\n  -F \"cvs_id=$TALK_ROBOT_CVS_ID\" \\\n  -F \"refer_msg_id=source-msg-id\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n## 响应示例\n\n成功响应：\n\n```json\n{\n  \"success\": true,\n  \"message\": \"ok\"\n}\n```\n\n常见失败响应：\n\n| HTTP 状态码 | message | 说明 |\n|-------------|---------|------|\n| `400` | `签名参数错误` | 缺少签名查询参数 |\n| `400` | `签名错误` | `sign` 校验失败 |\n| `400` | `msg_id 错误` | 请求体或表单中的 `msg_id` 与 URL 中不一致 |\n| `400` | `参数格式错误` | JSON 结构或字段格式不合法 |\n| `400` | `文件处理错误` | multipart 文件读取失败 |\n| `404` | `机器人不存在` | `robot_id` 不存在 |\n| `500` | `内部错误` | 服务端处理异常 |\n\n## 注意事项\n\n1. `TALK_ROBOT_KEY` 是敏感信息，不要写入日志、提交到仓库或回显给用户。\n2. `msg_id` 必须同时出现在 URL 查询参数和请求体或表单中，并保持一致。\n3. `cvs_id` 必须使用初始化时回传的原值，保持大小写不变。\n4. 文本消息使用 JSON，文件消息使用 multipart，不要混用。\n5. `/robot/send` 只表示事件已投递给目标机器人，不保证机器人脚本一定会回复。\n\nFile v0.8.3:skill-card.md\n\n## Description: <br>\nYunitalk Beta connects OpenClaw to Talk Robots so users can exchange messages between the two systems. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[blackbeans](https://clawhub.ai/user/blackbeans) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and OpenClaw operators use this skill to initialize a Talk Robots bridge, save robot connection settings, and send text or file events back into the current Talk Robots conversation. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The setup flow handles OPENCLAW_TOKEN, TALK_ROBOT_KEY, QR codes, and initialization commands that can grant access if exposed. <br>\nMitigation: Treat those values as secrets, avoid logging or screen sharing them, and send initialization commands only through trusted channels. <br>\nRisk: The optional npm auto-discovery helper runs local OpenClaw commands, reads local OpenClaw configuration, and contacts api64.ipify.org to detect a public IP. <br>\nMitigation: Avoid the npm helper in privacy-sensitive or locked-down environments; use the documented manual initialization command when local discovery is not acceptable. <br>\nRisk: Sending to the wrong or altered cvs_id can route messages to the wrong Talk Robots conversation or fail delivery. <br>\nMitigation: Use the current conversation's server-provided cvs_id exactly as received, and verify required robot endpoint, ID, key, and cvs_id values before sending. <br>\n\n\n## Reference(s): <br>\n- [ClawHub release page](https://clawhub.ai/blackbeans/yunitalk-beta) <br>\n- [Publisher profile](https://clawhub.ai/user/blackbeans) <br>\n- [OpenClaw and Talk Robots integration guide](artifact/README.md) <br>\n- [Talk Robots message sending API](artifact/ROBOT_SEND_API.md) <br>\n- [Talk Robots curl examples](artifact/ROBOT_SEND_CURL_API.md) <br>\n- [yntalk-openclaw-init CLI README](artifact/npm/yntalk-openclaw-init/README.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance] <br>\n**Output Format:** [Markdown guidance with inline shell commands, JSON examples, and configuration snippets] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [May produce an /openclaw --init Base64 JSON command and signed Talk Robots send-command examples.] <br>\n\n## Skill Version(s): <br>\n0.8.3 (source: frontmatter and server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v0.8.3:npm/yntalk-openclaw-init/package.json\n\n{\n  \"name\": \"yntalk-openclaw-init\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Generate Talk Robots /openclaw init command and QR code for OpenClaw connection config.\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"bin\": {\n    \"yntalk-openclaw-init\": \"./bin/yntalk-openclaw-init.js\"\n  },\n  \"files\": [\n    \"bin\",\n    \"README.md\"\n  ],\n  \"engines\": {\n    \"node\": \">=18\"\n  },\n  \"dependencies\": {}\n}\n\nFile v0.8.3:config.yaml\n\nversion: 1\nmode: prompt\n\nskill:\n  name: yunitalk-beta\n  display_name: OpenClaw 与你聊聊对话\n  description: 使用 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\n  version: 0.8.3\n  build: 20260612\n\n# 安装完成后由 OpenClaw 安装器执行，并把 stdout 原样展示给用户。\n# 最小闭环：输出一条可直接发给 Talk Robots 机器人的初始化指令。\ninstall:\n  post_install:\n    command: [\"./shell/util.sh\", \"--openclaw-init\"]\n    required_env:\n      - OPENCLAW_URL\n      - OPENCLAW_TOKEN\n    output:\n      type: text\n      description: Talk Robots 初始化指令，格式为 /openclaw --init <base64-json>\n\n# OpenClaw 侧由 /openclaw --init 流程写入 Talk Robots 连接信息\nconfig:\n  # Talk Robots 服务端点\n  robot_endpoint:\n    type: string\n    required: false\n    description: Talk Robots 服务端点地址，用于发送消息；默认值为 https://yunitalk-im-dev.yuni.vip/v1/robot/send，可通过环境变量 TALK_ROBOT_ENDPOINT 覆盖\n    default: \"https://yunitalk-im-dev.yuni.vip/v1/robot/send\"\n\n  # 机器人 ID\n  robot_id:\n    type: string\n    required: false\n    description: 机器人 ID，用于签名鉴权；初始化成功后从环境变量 TALK_ROBOT_ID 读取\n    default: \"${TALK_ROBOT_ID}\"\n\n  # 机器人密钥\n  robot_key:\n    type: string\n    required: false\n    description: 机器人密钥，用于 /robot/send 签名鉴权；初始化成功后从环境变量 TALK_ROBOT_KEY 读取\n    default: \"${TALK_ROBOT_KEY}\"\n\n  # 可选：默认 agent ID\n  default_agent_id:\n    type: string\n    required: false\n    description: 默认使用的 OpenClaw Agent ID\n    default: main\n\n# 运行时变量（由 Talk Robots 调用时注入）\nvariables:\n  cvs_id:\n    type: string\n    description: 当前会话ID，由 Talk Robots 在调用时注入\n\n# 能力声明（用于 MCP 模式，prompt 模式下可忽略）\ncapabilities:\n  send_text:\n    enabled: true\n    description: 通过 Robot 消息接口投递文本事件给指定机器人；JSON 请求体使用完整 imx.Msg 结构\n    endpoint: \"{{config.robot_endpoint}}?robot_id={{config.robot_id}}&noncestr={{nonce}}&timestamp={{timestamp}}&msg_id={{msg_id}}&sign={{sign}}\"\n    method: POST\n    content_type: application/json\n    payload_schema:\n      type: object\n      properties:\n        cmd:\n          type: string\n          const: msg\n          description: 固定为 msg\n        head:\n          type: object\n          properties:\n            msg_id:\n              type: string\n              description: 消息 ID，需与 URL 中 msg_id 一致\n            cvs_id:\n              type: string\n              description: 目标会话 ID\n            refer_msg_id:\n              type: string\n              description: 可选，引用消息 ID\n          required: [msg_id, cvs_id]\n        body:\n          type: object\n          properties:\n            content:\n              type: string\n              description: 文本内容、Markdown 内容或文件说明\n            file_list:\n              type: array\n              description: 文件数组，元素为 RobotFile\n            at_uid_list:\n              type: array\n              description: \"@ 用户列表\"\n            mentioned_list:\n              type: array\n              description: 兼容企业微信类命名\n          required: [content]\n      required: [cmd, head, body]\n\n  send_file:\n    enabled: true\n    description: 通过 Robot 消息接口投递文件事件给指定机器人\n    endpoint: \"{{config.robot_endpoint}}?robot_id={{config.robot_id}}&noncestr={{nonce}}&timestamp={{timestamp}}&msg_id={{msg_id}}&sign={{sign}}\"\n    method: POST\n    content_type: multipart/form-data\n    form_fields:\n      msg_id:\n        type: string\n        required: true\n        description: 消息ID，需与 URL 中 msg_id 一致\n      cvs_id:\n        type: string\n        required: true\n        description: 目标会话ID\n      file:\n        type: binary\n        required: true\n        description: 文件二进制内容\n      content:\n        type: string\n        required: false\n        description: 可选，文件说明文本\n      refer_msg_id:\n        type: string\n        required: false\n        description: 可选，引用消息 ID\n\n# 规则（用于 AI 遵循）\nrules:\n  - OpenClaw 会自动管理当前会话的身份标识\n  - 初始化入口只使用 /openclaw --init <base64-json>；不要再引导用户使用其他配置命令\n  - 安装或首次加载完成后，如 OPENCLAW_URL、OPENCLAW_TOKEN 均可用，应输出 /openclaw --init <base64-json>\n  - <base64-json> 必须是对 {\"OPENCLAW_URL\":\"...\",\"OPENCLAW_TOKEN\":\"...\",\"OPENCLAW_LAN_URL\":\"...\"} 做 UTF-8 Base64 编码后的结果；不得明文展示 OPENCLAW_TOKEN 或 robot_key\n  - 收到 Talk Robots 机器人回传的 Base64(JSON UTF-8) 配置后，应先 decode 得到 robot_endpoint、robot_id、robot_key、cvs_id，完成 yunitalk-beta 环境配置，并且不要回显 robot_key\n  - 投递文本事件时必须使用完整 imx.Msg JSON 结构，cmd 固定为 msg，文本放在 body.content\n  - 发送文件时必须使用 multipart/form-data，不得使用 JSON 传文件\n  - /robot/send 只负责把事件投递给目标 robot，最终是否回发由机器人脚本决定\n  - 如果缺少 robot_endpoint、robot_id、robot_key 或 cvs_id，则不能投递消息，应明确提示缺失项\n\n# 默认设置\ndefaults:\n  language: zh-CN\n  message_type: text\n\nArchive v0.8.2: 12 files, 24815 bytes\n\nFiles: config.yaml (5404b), npm/yntalk-openclaw-init/bin/yntalk-openclaw-init.js (20355b), npm/yntalk-openclaw-init/package.json (389b), npm/yntalk-openclaw-init/README.md (1841b), README.md (8048b), ROBOT_SEND_API.md (7867b), ROBOT_SEND_CURL_API.md (4654b), shell/robot_send.sh (6438b), shell/util.sh (2626b), skill-card.md (2447b), SKILL.md (3346b), _meta.json (132b)\n\nFile v0.8.2:SKILL.md\n\n---\nname: yunitalk-beta\ndescription: 该技能用于 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\nversion: 0.8.2\nbuild: 20260612\n---\n\n# OpenClaw 会话技能\n\n你可以通过 Talk Robots `/robot/send` 把文本或文件事件投递给当前聊聊机器人。OpenClaw 会管理用户身份，但每次发送都必须使用当前会话的 `cvs_id`，并保持大小写原样。\n\n## 初始化流程\n\n本集成只使用一条初始化指令：\n\n```text\n/openclaw --init <base64-json>\n```\n\n`<base64-json>` 是对下面 JSON 做 UTF-8 Base64 编码后的内容：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\"}\n```\n\n安装或首次加载完成后，如果 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN` 都可用，请生成并输出这条指令，让用户发送到聊聊 OpenClaw 机器人会话。推荐使用：\n\n```bash\n./shell/util.sh --openclaw-init \\\n  --openclaw-url \"${OPENCLAW_URL}\" \\\n  --openclaw-token \"${OPENCLAW_TOKEN}\"\n```\n\n本 skill 的 `config.yaml` 已声明 `install.post_install.command`，OpenClaw 安装器应在安装完成后执行该命令并展示 stdout；stdout 默认就是完整初始化指令。\n\n不要明文展示 `OPENCLAW_TOKEN`。Base64 不是加密，不要把初始化指令发送到不可信渠道。\n\n## Talk Robots 回传配置\n\nTalk Robots 机器人收到 init 指令后会：\n\n1. Base64 decode init JSON，保存 `OPENCLAW_URL`、`OPENCLAW_TOKEN`。\n2. 向 OpenClaw 发送 ping/pong 自检。\n3. 自检成功后，把 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 组成 JSON，并以 Base64(JSON UTF-8) 回传给 OpenClaw。\n\n收到回传后，先 Base64 decode，再保存为本 skill 配置：\n\n| 字段 | 环境变量 | 说明 |\n|------|----------|------|\n| `robot_endpoint` | `TALK_ROBOT_ENDPOINT` | Talk Robots `/v1/robot/send` 地址 |\n| `robot_id` | `TALK_ROBOT_ID` | 机器人 ID |\n| `robot_key` | `TALK_ROBOT_KEY` | 机器人签名密钥 |\n| `cvs_id` | `TALK_ROBOT_CVS_ID` | 当前会话 ID |\n\n配置成功后只简短确认，不要回显 `robot_key`。\n\n## 发送消息\n\n优先使用 `shell/robot_send.sh`，不要手写签名。\n\n### 文本\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 文件\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n不确定参数是否正确时先加 `--dry-run`。\n\n## Rules\n\n1. 只使用 `/openclaw --init <base64-json>` 完成初始化，不再引导用户使用其他配置命令。\n2. 发送前必须确认 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 都存在。\n3. `cvs_id` 必须来自当前会话上下文，严禁猜测、改大小写或从 session key 推导。\n4. 文本消息使用完整 `imx.Msg` JSON，`cmd=msg`，文本放 `body.content`。\n5. 文件消息使用 `multipart/form-data`，通过 `file` 字段上传。\n6. `/robot/send` 只是把事件投递给目标 robot，最终是否回发由机器人脚本决定。\n7. 不要明文展示 `OPENCLAW_TOKEN` 或 `robot_key`，不要虚构配置或用户资料。\n\nFile v0.8.2:npm/yntalk-openclaw-init/README.md\n\n# yntalk-openclaw-init\n\nGenerate the Talk Robots OpenClaw initialization command and QR code.\nThe CLI reads OpenClaw connection information from the local `openclaw` command by default.\nIt has no runtime dependencies; the terminal QR code is rendered as black and white block characters.\n\nThe QR code content is:\n\n```text\n/openclaw --init <base64-json>\n```\n\n`<base64-json>` is UTF-8 Base64 of:\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\"}\n```\n\nThis is the format recognized by `docs/openclaw-robot.js`.\nYou can send the command to the Talk Robots OpenClaw robot conversation, or scan the QR code into the robot config field named `OpenClaw连接信息`.\n\n## Usage\n\nDefault:\n\n```bash\nnpx yntalk-openclaw-init\n```\n\nBy default it tries these OpenClaw commands until one returns usable connection info:\n\n```text\nopenclaw yntalk init --json\nopenclaw yunitalk init --json\nopenclaw config export --json\nopenclaw config --json\nopenclaw env --json\n```\n\nThe OpenClaw command output can be JSON, `.env` style lines, or an existing `/openclaw --init <base64-json>` command.\n\nWith an explicit OpenClaw command:\n\n```bash\nnpx yntalk-openclaw-init \\\n  --openclaw-command \"openclaw yntalk init --json\"\n```\n\nDebug override only when the local OpenClaw command is unavailable:\n\n```bash\nnpx yntalk-openclaw-init \\\n  --url \"$OPENCLAW_URL\" \\\n  --token \"$OPENCLAW_TOKEN\"\n```\n\nWrite an SVG file:\n\n```bash\nnpx yntalk-openclaw-init \\\n  --svg ./openclaw-init.svg\n```\n\n## Output\n\nBy default the CLI:\n\n- prints the `/openclaw --init <base64-json>` command to stdout\n- prints a terminal QR code mosaic to stderr\n\nUse `--svg ./openclaw-init.svg` if you also need a file.\n\nSend the generated command in the Talk Robots OpenClaw robot conversation, or scan the QR code into the `OpenClaw连接信息` config field.\n\nFile v0.8.2:README.md\n\n# OpenClaw 与 Talk Robots 集成指南\n\n本 Skill 用于将 OpenClaw 接入与你聊聊 (Talk Robots)。初始化流程只依赖一条由 OpenClaw 生成、用户发送到聊聊机器人的指令：\n\n```text\n/openclaw --init <base64-json>\n```\n\n`<base64-json>` 是对 JSON 做 UTF-8 Base64 编码后的内容，JSON 只包含：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\"}\n```\n\nTalk Robots 机器人收到指令后会 Base64 decode 并保存 OpenClaw 连接信息，执行 ping/pong 连接自检，然后把当前 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 组成 JSON 并以 Base64(JSON UTF-8) 回传给 OpenClaw，使本 Skill 完成环境配置。\n\n## 功能概述\n\n- **双向通信**：用户可以通过聊聊与 OpenClaw 对话。\n- **自动初始化**：通过 `/openclaw --init <base64-json>` 导入 OpenClaw URL/Token。\n- **连接自检**：Talk Robots 机器人会向 OpenClaw 发送“我发送 ping，你帮我回复 pong”验证配置。\n- **环境回传**：自检成功后，机器人会把 `robot_id`、`robot_key`、`cvs_id` 等信息以 Base64(JSON UTF-8) 回传给 OpenClaw。\n- **事件投递**：OpenClaw 可调用 `/robot/send` 将文本或文件事件投递给指定机器人。\n\n## 快速开始\n\n### 1. 安装 Skill\n\n将本 skill 目录（`yunitalk-beta/`）复制到 OpenClaw 的 skills 目录中：\n\n```bash\n# 假设 OpenClaw 安装在 ~/openclaw\nmkdir -p ~/openclaw/skills/yunitalk-beta\ncp config.yaml ~/openclaw/skills/yunitalk-beta/\ncp SKILL.md ~/openclaw/skills/yunitalk-beta/\ncp -R shell ~/openclaw/skills/yunitalk-beta/\nchmod +x ~/openclaw/skills/yunitalk-beta/shell/robot_send.sh\nchmod +x ~/openclaw/skills/yunitalk-beta/shell/util.sh\n```\n\n`shell/robot_send.sh` 和 `shell/util.sh` 依赖 `curl`、`openssl` 和 `python3`。如果 OpenClaw 运行环境是容器，请确认镜像内已安装这些命令。\n\n`config.yaml` 已声明最小安装后钩子：\n\n```yaml\ninstall:\n  post_install:\n    command: [\"./shell/util.sh\", \"--openclaw-init\"]\n    required_env:\n      - OPENCLAW_URL\n      - OPENCLAW_TOKEN\n```\n\nOpenClaw 安装器只需要在安装完成后执行该命令，并把 stdout 原样展示给用户；默认输出就是可发送到聊聊机器人的 `/openclaw --init <base64-json>`。如果客户端需要二维码，建议由安装器对这条 stdout 文本生成二维码，skill 本身不引入额外二维码依赖。\n\n### 2. 生成 `/openclaw --init` 指令\n\n使用 `shell/util.sh` 生成前必须具备：\n\n| 配置项 | 用途 |\n|--------|------|\n| `OPENCLAW_URL` | OpenClaw Gateway 地址 |\n| `OPENCLAW_TOKEN` | OpenClaw Gateway Token |\n\n推荐使用辅助脚本：\n\n```bash\n./shell/util.sh --openclaw-init \\\n  --openclaw-url \"$OPENCLAW_URL\" \\\n  --openclaw-token \"$OPENCLAW_TOKEN\"\n```\n\n如果需要二维码，可以使用 npm CLI 生成可扫码的初始化指令：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n本仓库内的 CLI 源码位于 `npm/yntalk-openclaw-init/`；发布到 npm 后即可直接通过上面的 `npx` 命令使用。CLI 默认调用本机 `openclaw` 命令获取 OpenClaw 连接地址和 Token，并生成完整 `/openclaw --init <base64-json>` 指令。\n提交 `docs/openclaw-robot.js` 后，也可以在机器人配置页的 `OpenClaw连接信息` 参数中扫码保存该二维码内容，脚本会自动解析并写入 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN`。\n\n输出示例：\n\n```text\n/openclaw --init eyJPUEVOQ0xBV19VUkw...\n```\n\n如果缺少 `OPENCLAW_URL` 或 `OPENCLAW_TOKEN`，不要猜测，也不要输出占位符；请先补齐配置。Base64 不是加密，不要把 `OPENCLAW_TOKEN` 明文或初始化指令发送到不可信渠道。\nnpx CLI 默认会调用本机 `openclaw` 命令自动获取连接地址和 Token，不需要手动传入这些配置。\n\n### 3. 在聊聊机器人中执行初始化\n\n把完整指令发送到 Talk Robots 的 OpenClaw 机器人会话：\n\n```text\n/openclaw --init <base64-json>\n```\n\n机器人会自动执行：\n\n1. 对 `<base64-json>` 执行 Base64 decode，得到只包含 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN` 的 JSON。\n2. 写入 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN`。\n3. 请求 OpenClaw，发送“我发送 ping，你帮我回复 pong”并期待只返回 `pong`。\n4. 自检成功后，向 OpenClaw 发送当前 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 的 Base64(JSON UTF-8)。\n5. OpenClaw Base64 decode 回传信息后完成 `yunitalk-beta` 环境配置。\n\n初始化完成后，用户在聊聊里直接发送普通消息即可开始对话。\n\n## OpenClaw Skill 环境变量\n\n初始化成功后，OpenClaw 应保存以下配置供本 Skill 使用：\n\n| 环境变量 | 对应配置项 | 必填 | 说明 |\n|----------|-----------|------|------|\n| `TALK_ROBOT_ENDPOINT` | `robot_endpoint` | 是 | Talk Robots `/v1/robot/send` 服务端点 |\n| `TALK_ROBOT_ID` | `robot_id` | 是 | 机器人 ID，用于签名鉴权 |\n| `TALK_ROBOT_KEY` | `robot_key` | 是 | 机器人密钥，用于签名鉴权 |\n| `TALK_ROBOT_CVS_ID` | `cvs_id` | 是 | 当前会话 ID，用于主动投递消息 |\n\n也可以在 OpenClaw 配置文件 `openclaw.json` 的 `skills.entries` 中持久化：\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"yunitalk-beta\": {\n        \"enabled\": true,\n        \"env\": {\n          \"TALK_ROBOT_ENDPOINT\": \"https://yunitalk-im-dev.yuni.vip/v1/robot/send\",\n          \"TALK_ROBOT_ID\": \"your-robot-id\",\n          \"TALK_ROBOT_KEY\": \"your-robot-key\",\n          \"TALK_ROBOT_CVS_ID\": \"current-cvs-id\"\n        }\n      }\n    }\n  }\n}\n```\n\n不要在普通回复中回显 `TALK_ROBOT_KEY`。\n\n## Talk Robots 机器人脚本配置\n\n将 `docs/openclaw-robot.js` 提交到 Talk Robots。脚本会在收到 `/openclaw --init <base64-json>` 后写入以下 KV：\n\n| 配置项 | 必填 | 说明 |\n|--------|------|------|\n| `OPENCLAW_URL` | 是 | OpenClaw Gateway 地址，例如 `https://your-openclaw-domain` |\n| `OPENCLAW_TOKEN` | 是 | OpenClaw Gateway Token |\n| `TALK_ROBOT_ENDPOINT` | 否 | 回传给 OpenClaw 的 `/v1/robot/send` 地址，默认 `https://yunitalk-im-dev.yuni.vip/v1/robot/send` |\n\n## 机器人消息发送接口\n\nOpenClaw 可以调用 Talk Robots `/robot/send` 将文本或文件事件投递给指定机器人。发送消息时推荐优先使用本 Skill 内置脚本 `shell/robot_send.sh`，它会自动生成 `msg_id`、`noncestr`、`timestamp` 和 HMAC-SHA256 `sign`。\n\n完整的文本消息、文件消息、签名规则和 `curl` 示例见独立文档：\n\n- [ROBOT_SEND_API.md](./ROBOT_SEND_API.md) - 机器人消息发送接口\n\n## 故障排查\n\n### 问题：无法生成 `/openclaw --init`\n\n- 检查 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN` 是否存在。\n- 使用 `./shell/util.sh --openclaw-init --help` 查看参数。\n\n### 问题：初始化 ping/pong 失败\n\n- 检查 `OPENCLAW_URL` 是否能访问 `/v1/chat/completions`。\n- 检查 `OPENCLAW_TOKEN` 是否有效。\n- 确认 OpenClaw 模型收到 ping 时能只回复 `pong`。\n\n### 问题：无法发送消息\n\n1. 检查 `TALK_ROBOT_ENDPOINT`、`TALK_ROBOT_ID`、`TALK_ROBOT_KEY`、`TALK_ROBOT_CVS_ID` 是否完整。\n2. 确认 `cvs_id` 大小写未被改变。\n3. 使用 `shell/robot_send.sh --dry-run` 检查签名 URL 和请求体。\n4. 确认 `/robot/send` 的返回状态和错误信息。\n\n## 注意事项\n\n1. **安全性**：`OPENCLAW_TOKEN` 和 `TALK_ROBOT_KEY` 是敏感信息，请勿提交到代码仓库或普通聊天回复。\n2. **会话 ID 必填**：`cvs_id` 用于指定目标会话，缺失会导致 `/robot/send` 返回参数错误。\n3. **投递语义**：`/robot/send` 只表示事件已投递给机器人；是否最终回消息由机器人脚本决定。\n4. **会话隔离**：每个用户的会话是独立的，OpenClaw 不应跨会话共享上下文。\n\n## 参考文档\n\n- [SKILL.md](./SKILL.md) - OpenClaw 技能详细说明\n- [ROBOT_SEND_API.md](./ROBOT_SEND_API.md) - 机器人消息发送接口\n- [ROBOT_SEND_CURL_API.md](./ROBOT_SEND_CURL_API.md) - 机器人消息 curl 调用示例\n- [config.yaml](./config.yaml) - 技能配置文件\n\nFile v0.8.2:_meta.json\n\n{\n  \"ownerId\": \"kn78g6avmt6xsvd4c2acd7sd5h85dqx6\",\n  \"slug\": \"yunitalk-beta\",\n  \"version\": \"0.8.2\",\n  \"publishedAt\": 1781242063325\n}\n\nFile v0.8.2:ROBOT_SEND_API.md\n\n# Talk Robots 机器人消息发送接口\n\n本文档说明 OpenClaw 通过 Talk Robots `/robot/send` 向与你聊聊机器人投递消息的方式，覆盖文本消息和文件消息两类请求。\n\n`/robot/send` 的语义是把事件投递给目标机器人；机器人是否最终向会话回复，由机器人脚本决定。\n\n## 推荐调用方式\n\n优先使用本 Skill 内置脚本 `shell/robot_send.sh`。脚本会自动生成 `msg_id`、`noncestr`、`timestamp` 和 HMAC-SHA256 `sign`，避免业务侧重复实现签名逻辑。\n\n### 发送文本\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"$TALK_ROBOT_CVS_ID\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 发送文件\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"$TALK_ROBOT_CVS_ID\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n### 发送前预检\n\n使用 `--dry-run` 可以查看签名 URL 和请求体，不会实际发送消息。\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"$TALK_ROBOT_CVS_ID\" \\\n  --content \"测试消息\" \\\n  --dry-run\n```\n\n脚本常用参数：\n\n| 参数 | 必填 | 说明 |\n|------|------|------|\n| `--base-url` | 是 | Talk Robots `/v1/robot/send` 地址，即 `TALK_ROBOT_ENDPOINT` |\n| `--robot-id` | 是 | 机器人 ID |\n| `--robot-key` | 是 | 机器人 Key，用于签名 |\n| `--cvs-id` | 是 | 目标会话 ID，应保持大小写原样 |\n| `--content` | 文本必填，文件可选 | 文本消息内容，或文件说明文本 |\n| `--file` | 文件必填 | 待上传文件路径 |\n| `--refer-msg-id` | 否 | 引用的消息 ID |\n| `--msg-id` | 否 | 指定消息 ID；不传时脚本自动生成 |\n| `--noncestr` | 否 | 指定随机串；不传时脚本自动生成 |\n| `--timestamp` | 否 | 指定 Unix 秒级时间戳；不传时脚本自动生成 |\n| `--at` | 否 | 文本消息的 `at_uid_list`，多个 UID 用英文逗号分隔 |\n| `--mentioned` | 否 | 文本消息的 `mentioned_list`，多个 UID 用英文逗号分隔 |\n| `--dry-run` | 否 | 只打印请求信息，不实际发送 |\n\n## 直接使用 curl\n\n不使用 `shell/robot_send.sh` 时，可以直接用 `curl` 调用 `/robot/send`。完整的签名生成、文本消息和文件消息示例见：\n\n- [ROBOT_SEND_CURL_API.md](./ROBOT_SEND_CURL_API.md) - 机器人消息 curl 调用示例\n\n## 接口总览\n\n**请求方法**：`POST`\n\n**基础地址**：`{robot_endpoint}`\n\n`robot_endpoint` 通常来自 `TALK_ROBOT_ENDPOINT`，例如：\n\n```text\nhttps://yunitalk-im-dev.yuni.vip/v1/robot/send\n```\n\n**鉴权参数**放在 URL 查询参数中：\n\n| 参数 | 必填 | 说明 |\n|------|------|------|\n| `robot_id` | 是 | 机器人 ID |\n| `noncestr` | 是 | 请求随机串 |\n| `timestamp` | 是 | Unix 秒级时间戳 |\n| `msg_id` | 是 | 消息 ID；请求体或表单中的 `msg_id` 必须与 URL 中一致 |\n| `sign` | 是 | 使用 `robot_key` 计算得到的 HMAC-SHA256 签名 |\n\n完整 URL 形态：\n\n```text\n{robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\n```\n\n## 签名规则\n\n签名参数为 `msg_id`、`noncestr`、`robot_id`、`timestamp`。生成 `sign` 时：\n\n1. 按参数 key 字典序排序。\n2. 每个 value 使用 URL encode。\n3. 按 `key=value` 拼接，并用 `&` 连接。\n4. 使用 `robot_key` 对签名原文做 HMAC-SHA256。\n5. 将结果编码为小写十六进制字符串。\n\n签名原文示例：\n\n```text\nmsg_id=<msg_id>&noncestr=<noncestr>&robot_id=<robot_id>&timestamp=<timestamp>\n```\n\nShell 示例：\n\n```bash\nsigning_text=\"msg_id=${msg_id}&noncestr=${noncestr}&robot_id=${robot_id}&timestamp=${timestamp}\"\nsign=\"$(printf '%s' \"$signing_text\" | openssl dgst -sha256 -hmac \"$robot_key\" | awk '{print $2}')\"\n```\n\n实际实现时，`signing_text` 里的 value 需要先 URL encode。推荐直接使用 `shell/robot_send.sh`。\n\n## 发送文本消息\n\n文本消息使用 `application/json`，请求体是完整 `imx.Msg` JSON 结构，`cmd` 固定为 `msg`，文本内容放在 `body.content`。\n\n```http\nPOST {robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\nContent-Type: application/json\n\n{\n  \"cmd\": \"msg\",\n  \"head\": {\n    \"msg_id\": \"消息ID，需与 URL 中 msg_id 一致\",\n    \"cvs_id\": \"目标会话ID\",\n    \"refer_msg_id\": \"可选，引用消息ID\"\n  },\n  \"body\": {\n    \"content\": \"消息内容\",\n    \"at_uid_list\": [\"可选，被 @ 的用户 ID\"],\n    \"mentioned_list\": [\"可选，兼容企业微信类命名\"]\n  }\n}\n```\n\n字段说明：\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `cmd` | 是 | 固定为 `msg` |\n| `head.msg_id` | 是 | 消息 ID，需与 URL 查询参数 `msg_id` 一致 |\n| `head.cvs_id` | 是 | 目标会话 ID |\n| `head.refer_msg_id` | 否 | 引用消息 ID |\n| `body.content` | 是 | 文本、Markdown 或文件说明 |\n| `body.at_uid_list` | 否 | @ 用户列表 |\n| `body.mentioned_list` | 否 | 兼容企业微信类命名的提及列表 |\n\n`curl` 示例：\n\n```bash\ncurl -X POST \"$request_url\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary '{\n    \"cmd\": \"msg\",\n    \"head\": {\n      \"msg_id\": \"'\"$msg_id\"'\",\n      \"cvs_id\": \"'\"$TALK_ROBOT_CVS_ID\"'\"\n    },\n    \"body\": {\n      \"content\": \"你好，任务已经处理完成。\"\n    }\n  }'\n```\n\n## 发送文件消息\n\n文件消息使用 `multipart/form-data`，文件内容必须通过 `file` 字段上传，不要用 JSON 传文件二进制内容。\n\n```http\nPOST {robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\nContent-Type: multipart/form-data\n\nmsg_id: 消息ID，需与 URL 中 msg_id 一致\ncvs_id: 目标会话ID\nfile: <二进制文件内容>\ncontent: <可选，文件说明文本>\nrefer_msg_id: <可选，引用消息ID>\n```\n\n表单字段说明：\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `msg_id` | 是 | 消息 ID，需与 URL 查询参数 `msg_id` 一致 |\n| `cvs_id` | 是 | 目标会话 ID |\n| `file` | 是 | 待上传文件 |\n| `content` | 否 | 文件说明文本 |\n| `refer_msg_id` | 否 | 引用消息 ID |\n\n`curl` 示例：\n\n```bash\ncurl -X POST \"$request_url\" \\\n  -F \"msg_id=$msg_id\" \\\n  -F \"cvs_id=$TALK_ROBOT_CVS_ID\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\"\n```\n\n服务端会把 multipart 文件转换为机器人消息中的 `file_list`，并把文件内容编码为 `data:<content-type>;base64,<payload>` 后投递给目标机器人脚本。\n\n## 响应\n\n成功响应：\n\n```json\n{\n  \"success\": true,\n  \"message\": \"ok\"\n}\n```\n\n常见失败响应：\n\n| HTTP 状态码 | message | 说明 |\n|-------------|---------|------|\n| `400` | `签名参数错误` | 缺少签名查询参数 |\n| `400` | `签名错误` | `sign` 校验失败 |\n| `400` | `msg_id 错误` | 请求体或表单中的 `msg_id` 与 URL 中不一致 |\n| `400` | `参数格式错误` | JSON 结构或字段格式不合法 |\n| `400` | `文件处理错误` | multipart 文件读取失败 |\n| `400` | `参数错误` | 投递给机器人时参数不符合要求 |\n| `404` | `机器人不存在` | `robot_id` 不存在 |\n| `500` | `内部错误` | 服务端处理异常 |\n\n## 注意事项\n\n1. `TALK_ROBOT_KEY` 是敏感信息，不要写入日志、提交到仓库或回显给用户。\n2. `cvs_id` 必须使用初始化时回传的原值，保持大小写不变。\n3. 文本消息使用 JSON，文件消息使用 multipart，不要混用。\n4. `msg_id` 是本次投递的幂等标识之一，URL 和请求体中的值必须一致。\n5. `/robot/send` 只表示事件已投递给目标机器人，不保证机器人脚本一定会回复。\n\nFile v0.8.2:ROBOT_SEND_CURL_API.md\n\n# Talk Robots 机器人消息 curl 调用示例\n\n本文档说明不使用 `shell/robot_send.sh` 时，如何直接用 `curl` 调用 Talk Robots `/robot/send` 投递文本消息和文件消息。\n\n示例依赖 `curl`、`openssl` 和 `python3`。\n\n## 准备公共变量\n\n```bash\nTALK_ROBOT_ENDPOINT=\"https://yunitalk-im-dev.yuni.vip/v1/robot/send\"\nTALK_ROBOT_ID=\"your-robot-id\"\nTALK_ROBOT_KEY=\"your-robot-key\"\nTALK_ROBOT_CVS_ID=\"your-cvs-id\"\n```\n\n字段说明：\n\n| 变量 | 说明 |\n|------|------|\n| `TALK_ROBOT_ENDPOINT` | Talk Robots `/v1/robot/send` 地址 |\n| `TALK_ROBOT_ID` | 机器人 ID |\n| `TALK_ROBOT_KEY` | 机器人 Key，用于 HMAC-SHA256 签名 |\n| `TALK_ROBOT_CVS_ID` | 目标会话 ID，必须保持大小写原样 |\n\n## 生成签名 URL\n\n```bash\ntimestamp=\"$(date +%s)\"\nmsg_id=\"msg_${timestamp}_$(python3 -c 'import uuid; print(uuid.uuid4().hex)')\"\nnoncestr=\"nonce_${timestamp}_$(python3 -c 'import uuid; print(uuid.uuid4().hex)')\"\n\nurlencode() {\n  python3 -c 'import sys, urllib.parse; print(urllib.parse.quote_plus(sys.argv[1]))' \"$1\"\n}\n\nsigning_text=\"msg_id=$(urlencode \"$msg_id\")&noncestr=$(urlencode \"$noncestr\")&robot_id=$(urlencode \"$TALK_ROBOT_ID\")&timestamp=$(urlencode \"$timestamp\")\"\nsign=\"$(printf '%s' \"$signing_text\" | openssl dgst -sha256 -hmac \"$TALK_ROBOT_KEY\" | awk '{print $2}')\"\n\nrequest_url=\"${TALK_ROBOT_ENDPOINT}?robot_id=$(urlencode \"$TALK_ROBOT_ID\")&noncestr=$(urlencode \"$noncestr\")&timestamp=$(urlencode \"$timestamp\")&msg_id=$(urlencode \"$msg_id\")&sign=$(urlencode \"$sign\")\"\n```\n\n签名原文由 `msg_id`、`noncestr`、`robot_id`、`timestamp` 按 key 字典序排序后拼接，且每个 value 都需要先 URL encode：\n\n```text\nmsg_id=<msg_id>&noncestr=<noncestr>&robot_id=<robot_id>&timestamp=<timestamp>\n```\n\n## curl 发送文本消息\n\n文本消息使用 `application/json`，请求体是完整 `imx.Msg` JSON 结构，`cmd` 固定为 `msg`，文本内容放在 `body.content`。\n\n```bash\ncurl -sS -X POST \"$request_url\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary \"$(python3 - <<PY\nimport json\n\npayload = {\n    \"cmd\": \"msg\",\n    \"head\": {\n        \"msg_id\": \"${msg_id}\",\n        \"cvs_id\": \"${TALK_ROBOT_CVS_ID}\"\n    },\n    \"body\": {\n        \"content\": \"你好，任务已经处理完成。\"\n    }\n}\nprint(json.dumps(payload, ensure_ascii=False, separators=(\",\", \":\")))\nPY\n)\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n带引用消息的文本请求：\n\n```bash\nREFER_MSG_ID=\"source-msg-id\"\n\ncurl -sS -X POST \"$request_url\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary \"$(python3 - <<PY\nimport json\n\npayload = {\n    \"cmd\": \"msg\",\n    \"head\": {\n        \"msg_id\": \"${msg_id}\",\n        \"cvs_id\": \"${TALK_ROBOT_CVS_ID}\",\n        \"refer_msg_id\": \"${REFER_MSG_ID}\"\n    },\n    \"body\": {\n        \"content\": \"这是引用回复。\"\n    }\n}\nprint(json.dumps(payload, ensure_ascii=False, separators=(\",\", \":\")))\nPY\n)\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n## curl 发送文件消息\n\n文件消息使用 `multipart/form-data`，文件内容必须通过 `file` 字段上传，不要用 JSON 传文件二进制内容。\n\n```bash\ncurl -sS -X POST \"$request_url\" \\\n  -F \"msg_id=$msg_id\" \\\n  -F \"cvs_id=$TALK_ROBOT_CVS_ID\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n带引用消息的文件请求：\n\n```bash\ncurl -sS -X POST \"$request_url\" \\\n  -F \"msg_id=$msg_id\" \\\n  -F \"cvs_id=$TALK_ROBOT_CVS_ID\" \\\n  -F \"refer_msg_id=source-msg-id\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\" \\\n  -w '\\nHTTP_STATUS=%{http_code}\\n'\n```\n\n## 响应示例\n\n成功响应：\n\n```json\n{\n  \"success\": true,\n  \"message\": \"ok\"\n}\n```\n\n常见失败响应：\n\n| HTTP 状态码 | message | 说明 |\n|-------------|---------|------|\n| `400` | `签名参数错误` | 缺少签名查询参数 |\n| `400` | `签名错误` | `sign` 校验失败 |\n| `400` | `msg_id 错误` | 请求体或表单中的 `msg_id` 与 URL 中不一致 |\n| `400` | `参数格式错误` | JSON 结构或字段格式不合法 |\n| `400` | `文件处理错误` | multipart 文件读取失败 |\n| `404` | `机器人不存在` | `robot_id` 不存在 |\n| `500` | `内部错误` | 服务端处理异常 |\n\n## 注意事项\n\n1. `TALK_ROBOT_KEY` 是敏感信息，不要写入日志、提交到仓库或回显给用户。\n2. `msg_id` 必须同时出现在 URL 查询参数和请求体或表单中，并保持一致。\n3. `cvs_id` 必须使用初始化时回传的原值，保持大小写不变。\n4. 文本消息使用 JSON，文件消息使用 multipart，不要混用。\n5. `/robot/send` 只表示事件已投递给目标机器人，不保证机器人脚本一定会回复。\n\nFile v0.8.2:skill-card.md\n\n## Description: <br>\nConnects OpenClaw to Yunitalk/Talk Robots so a Talk Robots chat can converse with OpenClaw. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[blackbeans](https://clawhub.ai/user/blackbeans) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and operators use this skill to initialize an OpenClaw connection with Talk Robots, receive robot session configuration, and send text or file events through the robot message API. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The generated init command or QR code contains a live OpenClaw gateway token. <br>\nMitigation: Generate and share it only in trusted channels, avoid screenshots or shared terminals, and rotate the token if it is exposed. <br>\nRisk: The skill relies on the Talk Robots environment to handle OpenClaw and robot credentials. <br>\nMitigation: Install it only where that environment is trusted with those credentials and review configuration before enabling the integration. <br>\nRisk: Message-send commands can expose signed request material or robot secrets in logs. <br>\nMitigation: Keep dry-run and command output out of shared logs, do not echo robot keys, and verify required environment variables before sending. <br>\n\n\n## Reference(s): <br>\n- [ClawHub release page](https://clawhub.ai/blackbeans/yunitalk-beta) <br>\n- [OpenClaw and Talk Robots integration guide](README.md) <br>\n- [Talk Robots message send API](ROBOT_SEND_API.md) <br>\n- [Talk Robots curl examples](ROBOT_SEND_CURL_API.md) <br>\n- [Yunitalk OpenClaw init CLI](npm/yntalk-openclaw-init/README.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Text, Files, Shell commands, API Calls, Configuration, Guidance] <br>\n**Output Format:** [Markdown guidance with shell commands, JSON payloads, and multipart/API request examples] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Uses OpenClaw and Talk Robots credentials; dry-run mode is available for message-send checks.] <br>\n\n## Skill Version(s): <br>\n0.8.2 (source: frontmatter and server release metadata) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v0.8.2:npm/yntalk-openclaw-init/package.json\n\n{\n  \"name\": \"yntalk-openclaw-init\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Generate Talk Robots /openclaw init command and QR code for OpenClaw connection config.\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"bin\": {\n    \"yntalk-openclaw-init\": \"./bin/yntalk-openclaw-init.js\"\n  },\n  \"files\": [\n    \"bin\",\n    \"README.md\"\n  ],\n  \"engines\": {\n    \"node\": \">=18\"\n  },\n  \"dependencies\": {}\n}\n\nFile v0.8.2:config.yaml\n\nversion: 1\nmode: prompt\n\nskill:\n  name: yunitalk-beta\n  display_name: OpenClaw 与你聊聊对话\n  description: 使用 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\n  version: 0.8.2\n  build: 20260612\n\n# 安装完成后由 OpenClaw 安装器执行，并把 stdout 原样展示给用户。\n# 最小闭环：输出一条可直接发给 Talk Robots 机器人的初始化指令。\ninstall:\n  post_install:\n    command: [\"./shell/util.sh\", \"--openclaw-init\"]\n    required_env:\n      - OPENCLAW_URL\n      - OPENCLAW_TOKEN\n    output:\n      type: text\n      description: Talk Robots 初始化指令，格式为 /openclaw --init <base64-json>\n\n# OpenClaw 侧由 /openclaw --init 流程写入 Talk Robots 连接信息\nconfig:\n  # Talk Robots 服务端点\n  robot_endpoint:\n    type: string\n    required: false\n    description: Talk Robots 服务端点地址，用于发送消息；默认值为 https://yunitalk-im-dev.yuni.vip/v1/robot/send，可通过环境变量 TALK_ROBOT_ENDPOINT 覆盖\n    default: \"https://yunitalk-im-dev.yuni.vip/v1/robot/send\"\n\n  # 机器人 ID\n  robot_id:\n    type: string\n    required: false\n    description: 机器人 ID，用于签名鉴权；初始化成功后从环境变量 TALK_ROBOT_ID 读取\n    default: \"${TALK_ROBOT_ID}\"\n\n  # 机器人密钥\n  robot_key:\n    type: string\n    required: false\n    description: 机器人密钥，用于 /robot/send 签名鉴权；初始化成功后从环境变量 TALK_ROBOT_KEY 读取\n    default: \"${TALK_ROBOT_KEY}\"\n\n  # 可选：默认 agent ID\n  default_agent_id:\n    type: string\n    required: false\n    description: 默认使用的 OpenClaw Agent ID\n    default: main\n\n# 运行时变量（由 Talk Robots 调用时注入）\nvariables:\n  cvs_id:\n    type: string\n    description: 当前会话ID，由 Talk Robots 在调用时注入\n\n# 能力声明（用于 MCP 模式，prompt 模式下可忽略）\ncapabilities:\n  send_text:\n    enabled: true\n    description: 通过 Robot 消息接口投递文本事件给指定机器人；JSON 请求体使用完整 imx.Msg 结构\n    endpoint: \"{{config.robot_endpoint}}?robot_id={{config.robot_id}}&noncestr={{nonce}}&timestamp={{timestamp}}&msg_id={{msg_id}}&sign={{sign}}\"\n    method: POST\n    content_type: application/json\n    payload_schema:\n      type: object\n      properties:\n        cmd:\n          type: string\n          const: msg\n          description: 固定为 msg\n        head:\n          type: object\n          properties:\n            msg_id:\n              type: string\n              description: 消息 ID，需与 URL 中 msg_id 一致\n            cvs_id:\n              type: string\n              description: 目标会话 ID\n            refer_msg_id:\n              type: string\n              description: 可选，引用消息 ID\n          required: [msg_id, cvs_id]\n        body:\n          type: object\n          properties:\n            content:\n              type: string\n              description: 文本内容、Markdown 内容或文件说明\n            file_list:\n              type: array\n              description: 文件数组，元素为 RobotFile\n            at_uid_list:\n              type: array\n              description: \"@ 用户列表\"\n            mentioned_list:\n              type: array\n              description: 兼容企业微信类命名\n          required: [content]\n      required: [cmd, head, body]\n\n  send_file:\n    enabled: true\n    description: 通过 Robot 消息接口投递文件事件给指定机器人\n    endpoint: \"{{config.robot_endpoint}}?robot_id={{config.robot_id}}&noncestr={{nonce}}&timestamp={{timestamp}}&msg_id={{msg_id}}&sign={{sign}}\"\n    method: POST\n    content_type: multipart/form-data\n    form_fields:\n      msg_id:\n        type: string\n        required: true\n        description: 消息ID，需与 URL 中 msg_id 一致\n      cvs_id:\n        type: string\n        required: true\n        description: 目标会话ID\n      file:\n        type: binary\n        required: true\n        description: 文件二进制内容\n      content:\n        type: string\n        required: false\n        description: 可选，文件说明文本\n      refer_msg_id:\n        type: string\n        required: false\n        description: 可选，引用消息 ID\n\n# 规则（用于 AI 遵循）\nrules:\n  - OpenClaw 会自动管理当前会话的身份标识\n  - 初始化入口只使用 /openclaw --init <base64-json>；不要再引导用户使用其他配置命令\n  - 安装或首次加载完成后，如 OPENCLAW_URL、OPENCLAW_TOKEN 均可用，应输出 /openclaw --init <base64-json>\n  - <base64-json> 必须是对 {\"OPENCLAW_URL\":\"...\",\"OPENCLAW_TOKEN\":\"...\"} 做 UTF-8 Base64 编码后的结果；不得明文展示 OPENCLAW_TOKEN 或 robot_key\n  - 收到 Talk Robots 机器人回传的 Base64(JSON UTF-8) 配置后，应先 decode 得到 robot_endpoint、robot_id、robot_key、cvs_id，完成 yunitalk-beta 环境配置，并且不要回显 robot_key\n  - 投递文本事件时必须使用完整 imx.Msg JSON 结构，cmd 固定为 msg，文本放在 body.content\n  - 发送文件时必须使用 multipart/form-data，不得使用 JSON 传文件\n  - /robot/send 只负责把事件投递给目标 robot，最终是否回发由机器人脚本决定\n  - 如果缺少 robot_endpoint、robot_id、robot_key 或 cvs_id，则不能投递消息，应明确提示缺失项\n\n# 默认设置\ndefaults:\n  language: zh-CN\n  message_type: text\n\nArchive v0.8.1: 7 files, 12702 bytes\n\nFiles: config.yaml (5404b), README.md (9204b), shell/robot_send.sh (6438b), shell/util.sh (2626b), skill-card.md (2512b), SKILL.md (3346b), _meta.json (132b)\n\nFile v0.8.1:SKILL.md\n\n---\nname: yunitalk-beta\ndescription: 该技能用于 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\nversion: 0.8.1\nbuild: 20260520\n---\n\n# OpenClaw 会话技能\n\n你可以通过 Talk Robots `/robot/send` 把文本或文件事件投递给当前聊聊机器人。OpenClaw 会管理用户身份，但每次发送都必须使用当前会话的 `cvs_id`，并保持大小写原样。\n\n## 初始化流程\n\n本集成只使用一条初始化指令：\n\n```text\n/openclaw --init <base64-json>\n```\n\n`<base64-json>` 是对下面 JSON 做 UTF-8 Base64 编码后的内容：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\"}\n```\n\n安装或首次加载完成后，如果 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN` 都可用，请生成并输出这条指令，让用户发送到聊聊 OpenClaw 机器人会话。推荐使用：\n\n```bash\n./shell/util.sh --openclaw-init \\\n  --openclaw-url \"${OPENCLAW_URL}\" \\\n  --openclaw-token \"${OPENCLAW_TOKEN}\"\n```\n\n本 skill 的 `config.yaml` 已声明 `install.post_install.command`，OpenClaw 安装器应在安装完成后执行该命令并展示 stdout；stdout 默认就是完整初始化指令。\n\n不要明文展示 `OPENCLAW_TOKEN`。Base64 不是加密，不要把初始化指令发送到不可信渠道。\n\n## Talk Robots 回传配置\n\nTalk Robots 机器人收到 init 指令后会：\n\n1. Base64 decode init JSON，保存 `OPENCLAW_URL`、`OPENCLAW_TOKEN`。\n2. 向 OpenClaw 发送 ping/pong 自检。\n3. 自检成功后，把 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 组成 JSON，并以 Base64(JSON UTF-8) 回传给 OpenClaw。\n\n收到回传后，先 Base64 decode，再保存为本 skill 配置：\n\n| 字段 | 环境变量 | 说明 |\n|------|----------|------|\n| `robot_endpoint` | `TALK_ROBOT_ENDPOINT` | Talk Robots `/v1/robot/send` 地址 |\n| `robot_id` | `TALK_ROBOT_ID` | 机器人 ID |\n| `robot_key` | `TALK_ROBOT_KEY` | 机器人签名密钥 |\n| `cvs_id` | `TALK_ROBOT_CVS_ID` | 当前会话 ID |\n\n配置成功后只简短确认，不要回显 `robot_key`。\n\n## 发送消息\n\n优先使用 `shell/robot_send.sh`，不要手写签名。\n\n### 文本\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 文件\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n不确定参数是否正确时先加 `--dry-run`。\n\n## Rules\n\n1. 只使用 `/openclaw --init <base64-json>` 完成初始化，不再引导用户使用其他配置命令。\n2. 发送前必须确认 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 都存在。\n3. `cvs_id` 必须来自当前会话上下文，严禁猜测、改大小写或从 session key 推导。\n4. 文本消息使用完整 `imx.Msg` JSON，`cmd=msg`，文本放 `body.content`。\n5. 文件消息使用 `multipart/form-data`，通过 `file` 字段上传。\n6. `/robot/send` 只是把事件投递给目标 robot，最终是否回发由机器人脚本决定。\n7. 不要明文展示 `OPENCLAW_TOKEN` 或 `robot_key`，不要虚构配置或用户资料。\n\nFile v0.8.1:README.md\n\n# OpenClaw 与 Talk Robots 集成指南\n\n本 Skill 用于将 OpenClaw 接入与你聊聊 (Talk Robots)。初始化流程只依赖一条由 OpenClaw 生成、用户发送到聊聊机器人的指令：\n\n```text\n/openclaw --init <base64-json>\n```\n\n`<base64-json>` 是对 JSON 做 UTF-8 Base64 编码后的内容，JSON 只包含：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\"}\n```\n\nTalk Robots 机器人收到指令后会 Base64 decode 并保存 OpenClaw 连接信息，执行 ping/pong 连接自检，然后把当前 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 组成 JSON 并以 Base64(JSON UTF-8) 回传给 OpenClaw，使本 Skill 完成环境配置。\n\n## 功能概述\n\n- **双向通信**：用户可以通过聊聊与 OpenClaw 对话。\n- **自动初始化**：通过 `/openclaw --init <base64-json>` 导入 OpenClaw URL/Token。\n- **连接自检**：Talk Robots 机器人会向 OpenClaw 发送“我发送 ping，你帮我回复 pong”验证配置。\n- **环境回传**：自检成功后，机器人会把 `robot_id`、`robot_key`、`cvs_id` 等信息以 Base64(JSON UTF-8) 回传给 OpenClaw。\n- **事件投递**：OpenClaw 可调用 `/robot/send` 将文本或文件事件投递给指定机器人。\n\n## 快速开始\n\n### 1. 安装 Skill\n\n将本 skill 目录（`yunitalk-beta/`）复制到 OpenClaw 的 skills 目录中：\n\n```bash\n# 假设 OpenClaw 安装在 ~/openclaw\nmkdir -p ~/openclaw/skills/yunitalk-beta\ncp config.yaml ~/openclaw/skills/yunitalk-beta/\ncp SKILL.md ~/openclaw/skills/yunitalk-beta/\ncp -R shell ~/openclaw/skills/yunitalk-beta/\nchmod +x ~/openclaw/skills/yunitalk-beta/shell/robot_send.sh\nchmod +x ~/openclaw/skills/yunitalk-beta/shell/util.sh\n```\n\n`shell/robot_send.sh` 和 `shell/util.sh` 依赖 `curl`、`openssl` 和 `python3`。如果 OpenClaw 运行环境是容器，请确认镜像内已安装这些命令。\n\n`config.yaml` 已声明最小安装后钩子：\n\n```yaml\ninstall:\n  post_install:\n    command: [\"./shell/util.sh\", \"--openclaw-init\"]\n    required_env:\n      - OPENCLAW_URL\n      - OPENCLAW_TOKEN\n```\n\nOpenClaw 安装器只需要在安装完成后执行该命令，并把 stdout 原样展示给用户；默认输出就是可发送到聊聊机器人的 `/openclaw --init <base64-json>`。如果客户端需要二维码，建议由安装器对这条 stdout 文本生成二维码，skill 本身不引入额外二维码依赖。\n\n### 2. 生成 `/openclaw --init` 指令\n\n生成前必须具备：\n\n| 配置项 | 用途 |\n|--------|------|\n| `OPENCLAW_URL` | OpenClaw Gateway 地址 |\n| `OPENCLAW_TOKEN` | OpenClaw Gateway Token |\n\n推荐使用辅助脚本：\n\n```bash\n./shell/util.sh --openclaw-init \\\n  --openclaw-url \"$OPENCLAW_URL\" \\\n  --openclaw-token \"$OPENCLAW_TOKEN\"\n```\n\n输出示例：\n\n```text\n/openclaw --init eyJPUEVOQ0xBV19VUkw...\n```\n\n如果缺少 `OPENCLAW_URL` 或 `OPENCLAW_TOKEN`，不要猜测，也不要输出占位符；请先补齐配置。Base64 不是加密，不要把 `OPENCLAW_TOKEN` 明文或初始化指令发送到不可信渠道。\n\n### 3. 在聊聊机器人中执行初始化\n\n把完整指令发送到 Talk Robots 的 OpenClaw 机器人会话：\n\n```text\n/openclaw --init <base64-json>\n```\n\n机器人会自动执行：\n\n1. 对 `<base64-json>` 执行 Base64 decode，得到只包含 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN` 的 JSON。\n2. 写入 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN`。\n3. 请求 OpenClaw，发送“我发送 ping，你帮我回复 pong”并期待只返回 `pong`。\n4. 自检成功后，向 OpenClaw 发送当前 `robot_endpoint`、`robot_id`、`robot_key`、`cvs_id` 的 Base64(JSON UTF-8)。\n5. OpenClaw Base64 decode 回传信息后完成 `yunitalk-beta` 环境配置。\n\n初始化完成后，用户在聊聊里直接发送普通消息即可开始对话。\n\n## OpenClaw Skill 环境变量\n\n初始化成功后，OpenClaw 应保存以下配置供本 Skill 使用：\n\n| 环境变量 | 对应配置项 | 必填 | 说明 |\n|----------|-----------|------|------|\n| `TALK_ROBOT_ENDPOINT` | `robot_endpoint` | 是 | Talk Robots `/v1/robot/send` 服务端点 |\n| `TALK_ROBOT_ID` | `robot_id` | 是 | 机器人 ID，用于签名鉴权 |\n| `TALK_ROBOT_KEY` | `robot_key` | 是 | 机器人密钥，用于签名鉴权 |\n| `TALK_ROBOT_CVS_ID` | `cvs_id` | 是 | 当前会话 ID，用于主动投递消息 |\n\n也可以在 OpenClaw 配置文件 `openclaw.json` 的 `skills.entries` 中持久化：\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"yunitalk-beta\": {\n        \"enabled\": true,\n        \"env\": {\n          \"TALK_ROBOT_ENDPOINT\": \"https://yunitalk-im-dev.yuni.vip/v1/robot/send\",\n          \"TALK_ROBOT_ID\": \"your-robot-id\",\n          \"TALK_ROBOT_KEY\": \"your-robot-key\",\n          \"TALK_ROBOT_CVS_ID\": \"current-cvs-id\"\n        }\n      }\n    }\n  }\n}\n```\n\n不要在普通回复中回显 `TALK_ROBOT_KEY`。\n\n## Talk Robots 机器人脚本配置\n\n将 `docs/openclaw-robot.js` 提交到 Talk Robots。脚本会在收到 `/openclaw --init <base64-json>` 后写入以下 KV：\n\n| 配置项 | 必填 | 说明 |\n|--------|------|------|\n| `OPENCLAW_URL` | 是 | OpenClaw Gateway 地址，例如 `https://your-openclaw-domain` |\n| `OPENCLAW_TOKEN` | 是 | OpenClaw Gateway Token |\n| `TALK_ROBOT_ENDPOINT` | 否 | 回传给 OpenClaw 的 `/v1/robot/send` 地址，默认 `https://yunitalk-im-dev.yuni.vip/v1/robot/send` |\n\n## 辅助脚本：`shell/robot_send.sh`\n\n本 skill 内置 `shell/robot_send.sh`，用于辅助 OpenClaw 发送与你聊聊文本消息和文件消息。推荐在 skill 中优先使用该脚本，而不是手动计算签名或手写 `curl` 请求。\n\n脚本会自动完成：\n\n- 生成 `msg_id`、`noncestr`、`timestamp`\n- 按 `/robot/send` 规则生成 HMAC-SHA256 `sign`\n- 文本模式发送完整 `imx.Msg` JSON\n- 文件模式发送 `multipart/form-data`\n- 支持 `--refer-msg-id`、`--at`、`--mentioned`、`--dry-run`\n\n### 发送文本消息\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"$TALK_ROBOT_CVS_ID\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 发送文件消息\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"$TALK_ROBOT_CVS_ID\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n### 发送前预检\n\n使用 `--dry-run` 可以查看签名 URL 和请求体，不会实际发送消息：\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"$TALK_ROBOT_CVS_ID\" \\\n  --content \"测试消息\" \\\n  --dry-run\n```\n\n## Robot 消息接口\n\n**基础地址**：`{robot_endpoint}`\n\n**鉴权方式**：URL 参数 `robot_id`、`noncestr`、`timestamp`、`msg_id`、`sign`；`sign` 使用 `robot_key` 对按 key 字典序排序且 value URL encode 后的签名原文做 HMAC-SHA256。\n\n签名原文示例：\n\n```text\nmsg_id=<msg_id>&noncestr=<noncestr>&robot_id=<robot_id>&timestamp=<timestamp>\n```\n\n**发送文本事件**：\n\n```http\nPOST {robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\nContent-Type: application/json\n\n{\n  \"cmd\": \"msg\",\n  \"head\": {\n    \"msg_id\": \"消息ID（需与 URL 中 msg_id 一致）\",\n    \"cvs_id\": \"目标会话ID\",\n    \"refer_msg_id\": \"可选，引用消息ID\"\n  },\n  \"body\": {\n    \"content\": \"消息内容\"\n  }\n}\n```\n\n**发送文件事件**：\n\n```http\nPOST {robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\nContent-Type: multipart/form-data\n\nmsg_id: 消息ID（需与 URL 中 msg_id 一致）\ncvs_id: 目标会话ID\nfile: <二进制文件内容>\ncontent: <可选，文件说明文本>\nrefer_msg_id: <可选，引用消息ID>\n```\n\n## 故障排查\n\n### 问题：无法生成 `/openclaw --init`\n\n- 检查 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN` 是否存在。\n- 使用 `./shell/util.sh --openclaw-init --help` 查看参数。\n\n### 问题：初始化 ping/pong 失败\n\n- 检查 `OPENCLAW_URL` 是否能访问 `/v1/chat/completions`。\n- 检查 `OPENCLAW_TOKEN` 是否有效。\n- 确认 OpenClaw 模型收到 ping 时能只回复 `pong`。\n\n### 问题：无法发送消息\n\n1. 检查 `TALK_ROBOT_ENDPOINT`、`TALK_ROBOT_ID`、`TALK_ROBOT_KEY`、`TALK_ROBOT_CVS_ID` 是否完整。\n2. 确认 `cvs_id` 大小写未被改变。\n3. 使用 `shell/robot_send.sh --dry-run` 检查签名 URL 和请求体。\n4. 确认 `/robot/send` 的返回状态和错误信息。\n\n## 注意事项\n\n1. **安全性**：`OPENCLAW_TOKEN` 和 `TALK_ROBOT_KEY` 是敏感信息，请勿提交到代码仓库或普通聊天回复。\n2. **会话 ID 必填**：`cvs_id` 用于指定目标会话，缺失会导致 `/robot/send` 返回参数错误。\n3. **投递语义**：`/robot/send` 只表示事件已投递给机器人；是否最终回消息由机器人脚本决定。\n4. **会话隔离**：每个用户的会话是独立的，OpenClaw 不应跨会话共享上下文。\n\n## 参考文档\n\n- [SKILL.md](./SKILL.md) - OpenClaw 技能详细说明\n- [config.yaml](./config.yaml) - 技能配置文件\n\nFile v0.8.1:_meta.json\n\n{\n  \"ownerId\": \"kn78g6avmt6xsvd4c2acd7sd5h85dqx6\",\n  \"slug\": \"yunitalk-beta\",\n  \"version\": \"0.8.1\",\n  \"publishedAt\": 1779267020790\n}\n\nFile v0.8.1:skill-card.md\n\n## Description: <br>\nConnects OpenClaw with Talk Robots so a Talk Robots conversation can exchange text and file events with an OpenClaw agent. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[blackbeans](https://clawhub.ai/user/blackbeans) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and OpenClaw operators use this skill to initialize a Talk Robots connection, store returned robot credentials, and send text or file events back to the active conversation. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The generated /openclaw --init command contains Base64-encoded OpenClaw connection details, including the gateway token. <br>\nMitigation: Send the init command only to the intended Talk Robots OpenClaw conversation, and do not paste it into public or untrusted channels. <br>\nRisk: Message send troubleshooting can print signed request URLs and request metadata. <br>\nMitigation: Use dry-run and send logs only in trusted terminals, CI jobs, or support channels where logs are protected or redacted. <br>\nRisk: The integration depends on robot credentials and the current conversation ID being accurate for the active session. <br>\nMitigation: Confirm robot_endpoint, robot_id, robot_key, and cvs_id are present and session-specific before sending text or file events. <br>\n\n\n## Reference(s): <br>\n- [ClawHub Skill Page](https://clawhub.ai/blackbeans/yunitalk-beta) <br>\n- [Publisher Profile](https://clawhub.ai/user/blackbeans) <br>\n- [README](README.md) <br>\n- [Skill Instructions](SKILL.md) <br>\n- [Skill Configuration](config.yaml) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance] <br>\n**Output Format:** [Markdown guidance with bash commands, JSON snippets, YAML configuration, and plain-text setup commands.] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [The post-install helper can emit an /openclaw --init command, and the send helper can print signed request metadata for dry-run or troubleshooting.] <br>\n\n## Skill Version(s): <br>\n0.8.1 (source: server release evidence and SKILL.md frontmatter) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v0.8.1:config.yaml\n\nversion: 1\nmode: prompt\n\nskill:\n  name: yunitalk-beta\n  display_name: OpenClaw 与你聊聊对话\n  description: 使用 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\n  version: 0.8.1\n  build: 20260520\n\n# 安装完成后由 OpenClaw 安装器执行，并把 stdout 原样展示给用户。\n# 最小闭环：输出一条可直接发给 Talk Robots 机器人的初始化指令。\ninstall:\n  post_install:\n    command: [\"./shell/util.sh\", \"--openclaw-init\"]\n    required_env:\n      - OPENCLAW_URL\n      - OPENCLAW_TOKEN\n    output:\n      type: text\n      description: Talk Robots 初始化指令，格式为 /openclaw --init <base64-json>\n\n# OpenClaw 侧由 /openclaw --init 流程写入 Talk Robots 连接信息\nconfig:\n  # Talk Robots 服务端点\n  robot_endpoint:\n    type: string\n    required: false\n    description: Talk Robots 服务端点地址，用于发送消息；默认值为 https://yunitalk-im-dev.yuni.vip/v1/robot/send，可通过环境变量 TALK_ROBOT_ENDPOINT 覆盖\n    default: \"https://yunitalk-im-dev.yuni.vip/v1/robot/send\"\n\n  # 机器人 ID\n  robot_id:\n    type: string\n    required: false\n    description: 机器人 ID，用于签名鉴权；初始化成功后从环境变量 TALK_ROBOT_ID 读取\n    default: \"${TALK_ROBOT_ID}\"\n\n  # 机器人密钥\n  robot_key:\n    type: string\n    required: false\n    description: 机器人密钥，用于 /robot/send 签名鉴权；初始化成功后从环境变量 TALK_ROBOT_KEY 读取\n    default: \"${TALK_ROBOT_KEY}\"\n\n  # 可选：默认 agent ID\n  default_agent_id:\n    type: string\n    required: false\n    description: 默认使用的 OpenClaw Agent ID\n    default: main\n\n# 运行时变量（由 Talk Robots 调用时注入）\nvariables:\n  cvs_id:\n    type: string\n    description: 当前会话ID，由 Talk Robots 在调用时注入\n\n# 能力声明（用于 MCP 模式，prompt 模式下可忽略）\ncapabilities:\n  send_text:\n    enabled: true\n    description: 通过 Robot 消息接口投递文本事件给指定机器人；JSON 请求体使用完整 imx.Msg 结构\n    endpoint: \"{{config.robot_endpoint}}?robot_id={{config.robot_id}}&noncestr={{nonce}}&timestamp={{timestamp}}&msg_id={{msg_id}}&sign={{sign}}\"\n    method: POST\n    content_type: application/json\n    payload_schema:\n      type: object\n      properties:\n        cmd:\n          type: string\n          const: msg\n          description: 固定为 msg\n        head:\n          type: object\n          properties:\n            msg_id:\n              type: string\n              description: 消息 ID，需与 URL 中 msg_id 一致\n            cvs_id:\n              type: string\n              description: 目标会话 ID\n            refer_msg_id:\n              type: string\n              description: 可选，引用消息 ID\n          required: [msg_id, cvs_id]\n        body:\n          type: object\n          properties:\n            content:\n              type: string\n              description: 文本内容、Markdown 内容或文件说明\n            file_list:\n              type: array\n              description: 文件数组，元素为 RobotFile\n            at_uid_list:\n              type: array\n              description: \"@ 用户列表\"\n            mentioned_list:\n              type: array\n              description: 兼容企业微信类命名\n          required: [content]\n      required: [cmd, head, body]\n\n  send_file:\n    enabled: true\n    description: 通过 Robot 消息接口投递文件事件给指定机器人\n    endpoint: \"{{config.robot_endpoint}}?robot_id={{config.robot_id}}&noncestr={{nonce}}&timestamp={{timestamp}}&msg_id={{msg_id}}&sign={{sign}}\"\n    method: POST\n    content_type: multipart/form-data\n    form_fields:\n      msg_id:\n        type: string\n        required: true\n        description: 消息ID，需与 URL 中 msg_id 一致\n      cvs_id:\n        type: string\n        required: true\n        description: 目标会话ID\n      file:\n        type: binary\n        required: true\n        description: 文件二进制内容\n      content:\n        type: string\n        required: false\n        description: 可选，文件说明文本\n      refer_msg_id:\n        type: string\n        required: false\n        description: 可选，引用消息 ID\n\n# 规则（用于 AI 遵循）\nrules:\n  - OpenClaw 会自动管理当前会话的身份标识\n  - 初始化入口只使用 /openclaw --init <base64-json>；不要再引导用户使用其他配置命令\n  - 安装或首次加载完成后，如 OPENCLAW_URL、OPENCLAW_TOKEN 均可用，应输出 /openclaw --init <base64-json>\n  - <base64-json> 必须是对 {\"OPENCLAW_URL\":\"...\",\"OPENCLAW_TOKEN\":\"...\"} 做 UTF-8 Base64 编码后的结果；不得明文展示 OPENCLAW_TOKEN 或 robot_key\n  - 收到 Talk Robots 机器人回传的 Base64(JSON UTF-8) 配置后，应先 decode 得到 robot_endpoint、robot_id、robot_key、cvs_id，完成 yunitalk-beta 环境配置，并且不要回显 robot_key\n  - 投递文本事件时必须使用完整 imx.Msg JSON 结构，cmd 固定为 msg，文本放在 body.content\n  - 发送文件时必须使用 multipart/form-data，不得使用 JSON 传文件\n  - /robot/send 只负责把事件投递给目标 robot，最终是否回发由机器人脚本决定\n  - 如果缺少 robot_endpoint、robot_id、robot_key 或 cvs_id，则不能投递消息，应明确提示缺失项\n\n# 默认设置\ndefaults:\n  language: zh-CN\n  message_type: text\n\nArchive v0.8.0: 5 files, 11656 bytes\n\nFiles: config.yaml (4289b), README.md (11415b), shell/robot_send.sh (6438b), SKILL.md (7115b), _meta.json (132b)\n\nFile v0.8.0:SKILL.md\n\n---\nname: openclaw-yunitalk\ndescription: 该技能用于 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\n---\n\n# OpenClaw 会话技能\n\n你现在拥有在 Talk Robots 会话中识别当前用户身份，并通过 Robot 消息接口把文本或文件事件投递给指定聊聊机器人的能力。当用户要求“记住我是谁”、“给我发个消息”、“通知我”、“给我发送文件”，或者你在后台完成了一项长耗时任务需要回推结果时，请使用此技能。\n\nOpenClaw 会自动管理会话身份标识，但发送 Robot 消息时仍必须使用当前会话的 `cvs_id`。\n\n**⚠️ 重要**: 发送消息时必须使用用户上下文中明确指出的 `cvs_id`（严格区分大小写），不要从 session key 中提取（session key 会被小写化，导致投递失败）。\n\n## 推荐发送方式：`shell/robot_send.sh`\n\n本技能目录提供了辅助脚本 `shell/robot_send.sh`。当运行环境允许执行 shell 时，**优先使用该脚本发送与你聊聊文本消息或文件消息**，不要手写签名或手动拼接 `/robot/send` 请求。\n\n该脚本会自动完成：\n\n- 生成 `msg_id`、`noncestr`、`timestamp`\n- 按 Talk Robots `/robot/send` 规则生成 HMAC-SHA256 `sign`\n- 文本消息使用完整 `imx.Msg` JSON 结构\n- 文件消息使用 `multipart/form-data`\n- 支持 `--refer-msg-id`、`--at`、`--mentioned`、`--dry-run`\n\n发送前必须确认以下值均有效：\n\n- `robot_endpoint` / `TALK_ROBOT_ENDPOINT`\n- `robot_id` / `TALK_ROBOT_ID`\n- `robot_key` / `TALK_ROBOT_KEY`\n- 当前会话 `cvs_id`\n\n### 使用脚本发送文本消息\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"你好，你交代的任务已经处理完成。\"\n```\n\n### 使用脚本发送文件消息\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n### 发送前预检\n\n不确定参数或签名是否正确时，先使用 `--dry-run` 查看请求内容，不要实际发送：\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"测试消息\" \\\n  --dry-run\n```\n\n## Robot 消息接口说明\n\n如果不能使用 `shell/robot_send.sh`，再按下面的协议直接调用 Robot 消息接口。\n\n**配置项**：\n- `robot_endpoint` - Talk Robots 服务端点地址（在 OpenClaw 技能配置中设置）\n- `robot_id` - 机器人 ID（在 OpenClaw 技能配置中设置）\n- `robot_key` - 机器人密钥（在 OpenClaw 技能配置中设置）\n\n发送消息时，系统需要生成 `msg_id`、`noncestr`、`timestamp`，并将 `msg_id`、`noncestr`、`robot_id`、`timestamp` 按 key 字典序排序、value URL encode 后拼接成签名原文，再使用 `robot_key` 做 HMAC-SHA256 生成 `sign`。最终 URL 形如：`{{robot_endpoint}}?robot_id=...&noncestr=...&timestamp=...&msg_id=...&sign=...`。\n\n## 发送文本事件\n\n- **Endpoint**: `{{robot_endpoint}}`\n- **Method**: `POST`\n- **Content-Type**: `application/json`\n- **Payload (JSON)**:\n  - `cmd`: 固定为 `msg`\n  - `head.msg_id`: 消息 ID，需与 URL 中 `msg_id` 一致\n  - `head.cvs_id`: 目标会话 ID，必填\n  - `head.refer_msg_id`: 可选，引用消息 ID\n  - `body.content`: 要投递的文本内容\n\n请求体示例：\n\n```json\n{\n  \"cmd\": \"msg\",\n  \"head\": {\n    \"msg_id\": \"msg-001\",\n    \"cvs_id\": \"cvs-123\",\n    \"refer_msg_id\": \"refer-msg-id\"\n  },\n  \"body\": {\n    \"content\": \"你好，你交代的任务已经处理完成。\"\n  }\n}\n```\n\n## 发送文件事件\n\n- **Endpoint**: `{{robot_endpoint}}`\n- **Method**: `POST`\n- **Content-Type**: `multipart/form-data`\n- **Form Fields**:\n  - `msg_id`: 消息 ID，需与 URL 中 `msg_id` 一致\n  - `cvs_id`: 目标会话 ID，必填\n  - `file`: 文件二进制内容\n  - `content`: 可选，文件说明文本\n  - `refer_msg_id`: 可选，引用消息 ID\n\n注意：文件上传必须使用 `multipart/form-data`，不能使用 JSON 直接嵌入文件内容。\n\n## 操作规范 (Rules)\n\n1. **身份约束**：OpenClaw 会自动管理当前用户的身份标识；引用历史上下文时，只能基于当前会话，不能混用其他会话记忆。\n2. **前置检查**：在投递消息前，务必先确认技能配置中已提供有效的 `robot_endpoint`、`robot_id`、`robot_key` 和当前会话 `cvs_id`。如果没有，请直接告知调用方当前缺少配置。\n3. **优先脚本**：当 shell 可用时，优先使用 `shell/robot_send.sh` 发送文本或文件；只有脚本不可用时才手动构造 `/robot/send` 请求。\n4. **文本发送**：发送纯文本时，请严格使用完整 `imx.Msg` JSON 结构：`cmd=msg`、`head.msg_id`、`head.cvs_id`、`body.content`。\n5. **文件发送**：发送文件时，请严格使用 `multipart/form-data`，并通过 `file` 字段上传文件，不要用 JSON 嵌入文件内容。\n6. **会话 ID**：无论用脚本还是手动请求，都必须显式传入当前会话 `cvs_id`，且大小写必须保持原样。\n7. **投递语义**：`/robot/send` 是把事件投递给目标 robot，不是直接绕过机器人给聊聊会话发消息；最终是否回发由机器人脚本逻辑决定。\n8. **内容风格**：默认使用自然、简洁的中文与用户沟通，除非用户明确要求其他语言。\n9. **错误处理**：如果缺少必要上下文、robot 消息配置无效，或调用协议不明确，请明确指出缺失项，不要自行猜测。\n10. **禁止事项**：不要虚构用户资料、历史记忆、robot 消息参数或接口协议。\n\n## 示例 (Example)\n\n当你需要在任务完成后通知当前用户时，推荐直接调用辅助脚本。\n\n### 文本消息示例\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"{{config.robot_endpoint}}\" \\\n  --robot-id \"{{config.robot_id}}\" \\\n  --robot-key \"{{config.robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"你好，你交代的任务已经处理完成，我现在把结果同步给你。\"\n```\n\n### 文件消息示例\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"{{config.robot_endpoint}}\" \\\n  --robot-id \"{{config.robot_id}}\" \\\n  --robot-key \"{{config.robot_key}}\" \\\n  --cvs-id \"{{cvs_id}}\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n### 手动文本请求示例（脚本不可用时）\n\n```json\n{\n  \"cmd\": \"msg\",\n  \"head\": {\n    \"msg_id\": \"msg-001\",\n    \"cvs_id\": \"cvs-123\"\n  },\n  \"body\": {\n    \"content\": \"你好，你交代的任务已经处理完成，我现在把结果同步给你。\"\n  }\n}\n```\n\n### 手动文件请求示例（脚本不可用时）\n\n```bash\ncurl -X POST \"{{config.robot_endpoint}}?robot_id={{config.robot_id}}&noncestr={{nonce}}&timestamp={{timestamp}}&msg_id={{msg_id}}&sign={{sign}}\" \\\n  -F \"msg_id={{msg_id}}\" \\\n  -F \"cvs_id={{cvs_id}}\" \\\n  -F \"content=请查看附件\" \\\n  -F \"file=@./report.pdf\"\n```\n\nFile v0.8.0:README.md\n\n# OpenClaw 与 Talk Robots 集成指南\n\n本 Skill 用于将 OpenClaw 接入与你聊聊 (Talk Robots)，让 OpenClaw 可以通过 Talk Robots 的 Robot 消息接口把消息事件投递给指定机器人，再由机器人脚本处理并回发到聊聊会话。\n\n## 功能概述\n\n- **双向通信**：用户可以通过聊聊与 OpenClaw 对话\n- **事件投递**：OpenClaw 可以调用 `/robot/send` 将文本或文件事件投递给指定机器人\n- **辅助发送脚本**：内置 `shell/robot_send.sh`，自动生成签名并发送文本或文件消息\n- **会话管理**：通过 `cvs_id` 识别目标会话，保持会话上下文\n\n## 快速开始\n\n### 1. 环境变量配置\n\n在启动 OpenClaw 之前，设置以下环境变量：\n\n```bash\n# 必填：机器人 ID，用于签名鉴权\nexport TALK_ROBOT_ID=\"your-robot-id\"\n\n# 必填：机器人密钥，创建机器人后返回的 body.key\nexport TALK_ROBOT_KEY=\"your-robot-key\"\n\n# 可选：Talk Robots 服务端点地址（默认使用开发环境）\nexport TALK_ROBOT_ENDPOINT=\"https://yunitalk-im-dev.yuni.vip/v1/robot/send\"\n```\n\n#### 在 openclaw.json 中配置（推荐）\n\n也可以在 OpenClaw 配置文件 `openclaw.json` 的 `skills.entries` 中配置：\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"openclaw-yunitalk\": {\n        \"enabled\": true,\n        \"env\": {\n          \"TALK_ROBOT_ID\": \"your-robot-id\",\n          \"TALK_ROBOT_KEY\": \"your-robot-key\",\n          \"TALK_ROBOT_ENDPOINT\": \"https://yunitalk-im-dev.yuni.vip/v1/robot/send\"\n        }\n      }\n    }\n  }\n}\n```\n\n**配置说明：**\n- `enabled`: 是否启用该 skill\n- `env.TALK_ROBOT_ID`: 机器人 ID（必填）\n- `env.TALK_ROBOT_KEY`: 机器人密钥（必填）\n- `env.TALK_ROBOT_ENDPOINT`: 服务端点地址（可选，默认使用开发环境地址）\n\n### 2. 安装 Skill\n\n将本 skill 目录（`openclaw-yunitalk/`）复制到 OpenClaw 的 skills 目录中：\n\n```bash\n# 假设 OpenClaw 安装在 ~/openclaw\nmkdir -p ~/openclaw/skills/openclaw-yunitalk\ncp config.yaml ~/openclaw/skills/openclaw-yunitalk/\ncp SKILL.md ~/openclaw/skills/openclaw-yunitalk/\ncp -R shell ~/openclaw/skills/openclaw-yunitalk/\nchmod +x ~/openclaw/skills/openclaw-yunitalk/shell/robot_send.sh\n```\n\n`shell/robot_send.sh` 依赖 `curl`、`openssl` 和 `python3`。如果 OpenClaw 运行环境是容器，请确认镜像内已安装这些命令。\n\n### 3. 重启 OpenClaw\n\n```bash\n# 重启 OpenClaw 服务以加载新 skill\n# 具体命令取决于你的 OpenClaw 部署方式\n```\n\n### 4. 配置 Talk Robots 机器人脚本\n\n将 `docs/openclaw-robot.js` 提交到 Talk Robots，并在该机器人中配置 OpenClaw 连接信息。脚本会通过 `kvstore.get()` 读取以下配置：\n\n| 配置项 | 必填 | 说明 |\n|--------|------|------|\n| `OPENCLAW_URL` | 是 | OpenClaw Gateway 地址，例如 `https://your-openclaw-domain` |\n| `OPENCLAW_TOKEN` | 是 | OpenClaw Gateway Token |\n\n可以在聊聊会话中通过内置 `/env` 命令配置：\n\n```text\n/env set OPENCLAW_URL https://your-openclaw-domain\n/env set OPENCLAW_TOKEN your-openclaw-gateway-token\n/env list\n```\n\n也可以在 Talk Robots 管理界面或其他 KV 配置入口写入同名配置项。\n\n### 5. 在聊聊中启动 OpenClaw 会话\n\n部署机器人脚本并完成配置后，在聊聊中对该机器人发送：\n\n```text\n/start\n```\n\n机器人会调用 OpenClaw 的 `/v1/chat/completions`，并指定加载 `openclaw-yunitalk` skill。之后用户在聊聊里发送普通消息，机器人脚本会把消息转发给 OpenClaw，并把 OpenClaw 的回复回发到当前会话。\n\n### 最小配置清单\n\n| 配置位置 | 必填项 | 用途 |\n|----------|--------|------|\n| OpenClaw skill | `TALK_ROBOT_ID`、`TALK_ROBOT_KEY`、`TALK_ROBOT_ENDPOINT` | 让 OpenClaw 可以调用 `/robot/send` 投递事件给 Talk Robots 机器人 |\n| Talk Robots 机器人脚本 | `OPENCLAW_URL`、`OPENCLAW_TOKEN` | 让 Talk Robots 机器人可以调用 OpenClaw Gateway |\n\n## 配置说明\n\n### 环境变量详情\n\n| 环境变量 | 对应配置项 | 必填 | 说明 | 默认值 |\n|----------|-----------|------|------|--------|\n| `TALK_ROBOT_ID` | `robot_id` | **是** | 机器人 ID，用于签名鉴权 | 无 |\n| `TALK_ROBOT_KEY` | `robot_key` | **是** | 机器人密钥，用于签名鉴权 | 无 |\n| `TALK_ROBOT_ENDPOINT` | `robot_endpoint` | 否 | 服务端点地址，用于覆盖默认值 | `https://yunitalk-im-dev.yuni.vip/v1/robot/send` |\n\n**优先级**：环境变量 > 硬编码默认值\n\n### 配置文件中的配置项\n\n| 配置项 | 说明 |\n|--------|------|\n| `robot_endpoint` | Talk Robots 服务端点地址 |\n| `robot_id` | 机器人 ID，用于签名鉴权 |\n| `robot_key` | 机器人密钥，用于签名鉴权 |\n| `default_agent_id` | 默认使用的 OpenClaw Agent ID（可选，默认 main） |\n\n### 如何获取 `TALK_ROBOT_ID` 和 `TALK_ROBOT_KEY`\n\n1. 登录 Talk Robots 管理界面\n2. 创建或选择一个机器人\n3. 在机器人详情页找到 `robot_id` 和 `key` 字段\n4. 复制 `robot_id` 作为 `TALK_ROBOT_ID` 的值\n5. 复制 `key` 作为 `TALK_ROBOT_KEY` 的值\n\n## 辅助脚本：`shell/robot_send.sh`\n\n本 skill 内置 `shell/robot_send.sh`，用于辅助 OpenClaw 发送与你聊聊文本消息和文件消息。推荐在 skill 中优先使用该脚本，而不是手动计算签名或手写 `curl` 请求。\n\n脚本会自动完成：\n\n- 生成 `msg_id`、`noncestr`、`timestamp`\n- 按 `/robot/send` 规则生成 HMAC-SHA256 `sign`\n- 文本模式发送完整 `imx.Msg` JSON\n- 文件模式发送 `multipart/form-data`\n- 支持 `--refer-msg-id`、`--at`、`--mentioned`、`--dry-run`\n\n> 注意：脚本默认 `--base-url` 是本地开发地址。生产或远程环境中请显式传入 `--base-url \"$TALK_ROBOT_ENDPOINT\"`，避免发到错误地址。\n\n### 发送文本消息\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"目标会话ID\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 发送文件消息\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"目标会话ID\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n### 发送前预检\n\n使用 `--dry-run` 可以查看签名 URL 和请求体，不会实际发送消息：\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --cvs-id \"目标会话ID\" \\\n  --content \"测试消息\" \\\n  --dry-run\n```\n\n## 使用场景\n\n### 场景 1：用户主动询问\n\n用户直接在聊聊中发送消息，Talk Robots 脚本接收消息后调用 OpenClaw，并把 OpenClaw 回复回发到聊聊会话。\n\n### 场景 2：OpenClaw 投递事件给机器人\n\n当 OpenClaw 完成耗时任务或需要通知用户时，可以调用 `/robot/send`，将事件投递给指定机器人和会话：\n\n```\n用户：帮我监控服务器状态，有问题通知我\n\n[一段时间后]\n\nOpenClaw -> /robot/send -> Talk Robots 脚本 -> 聊聊用户：\"检测到服务器 CPU 使用率超过 90%，请注意\"\n```\n\n> 注意：`/robot/send` 的语义是“把事件投递给目标 robot”，不是直接绕过机器人向聊聊会话发消息。机器人脚本仍需要处理收到的 `msg` 事件，并决定是否通过 `robot.sendMessage()` 回发。\n\n### 场景 3：身份识别\n\n用户可以要求 OpenClaw 记住自己：\n\n```\n用户：记住我是张三，我的邮箱是 zhangsan@example.com\n\nOpenClaw：已记录，我会记住您的身份信息。\n```\n\n## 配置示例\n\n### 本地开发环境\n\n```bash\nexport TALK_ROBOT_ENDPOINT=\"http://localhost:28080/v1/robot/send\"\nexport TALK_ROBOT_ID=\"robot-dev-id\"\nexport TALK_ROBOT_KEY=\"robot-dev-key\"\n```\n\n### 生产环境\n\n```bash\nexport TALK_ROBOT_ENDPOINT=\"https://yunitalk-im.yuni.vip/v1/robot/send\"\nexport TALK_ROBOT_ID=\"robot-prod-id\"\nexport TALK_ROBOT_KEY=\"robot-prod-key\"\n```\n\n### Docker 部署\n\n```yaml\n# docker-compose.yml\nservices:\n  openclaw:\n    image: openclaw:latest\n    environment:\n      - TALK_ROBOT_ENDPOINT=https://yunitalk-im.yuni.vip/v1/robot/send\n      - TALK_ROBOT_ID=${TALK_ROBOT_ID}\n      - TALK_ROBOT_KEY=${TALK_ROBOT_KEY}\n```\n\n## 故障排查\n\n### 问题：无法发送消息\n\n**检查清单：**\n1. 环境变量是否正确设置？\n   ```bash\n   echo $TALK_ROBOT_ID\n   echo $TALK_ROBOT_KEY\n   echo $TALK_ROBOT_ENDPOINT\n   ```\n\n2. 机器人 ID 和密钥是否有效？\n   - 在 Talk Robots 中检查机器人是否存在\n   - 确认 `robot_id` 和 `key` 没有额外的空格或引号\n\n3. 是否传入目标会话 ID？\n   - JSON 请求必须包含 `head.cvs_id`\n   - 文件上传表单必须包含 `cvs_id`\n\n4. 网络连接是否正常？\n   ```bash\n   curl -I $TALK_ROBOT_ENDPOINT\n   ```\n\n### 问题：用户身份无法识别\n\n- 确保用户在聊聊中已经与机器人建立会话\n- 检查 `cvs_id` 是否正确传递到 `head.cvs_id` 或 multipart 表单字段 `cvs_id`\n\n## 技术细节\n\n### Robot 消息接口\n\n**基础地址**：`{robot_endpoint}` （对应配置项 `robot_endpoint`）\n\n**鉴权方式**：URL 参数 `robot_id`、`noncestr`、`timestamp`、`msg_id`、`sign`；`sign` 使用 `robot_key` 对按 key 字典序排序且 value URL encode 后的签名原文做 HMAC-SHA256。\n\n签名原文示例：\n\n```text\nmsg_id=<msg_id>&noncestr=<noncestr>&robot_id=<robot_id>&timestamp=<timestamp>\n```\n\n**发送文本事件**：\n```http\nPOST {robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\nContent-Type: application/json\n\n{\n  \"cmd\": \"msg\",\n  \"head\": {\n    \"msg_id\": \"消息ID（需与 URL 中 msg_id 一致）\",\n    \"cvs_id\": \"目标会话ID\",\n    \"refer_msg_id\": \"可选，引用消息ID\"\n  },\n  \"body\": {\n    \"content\": \"消息内容\"\n  }\n}\n```\n\n**发送文件事件**：\n```http\nPOST {robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\nContent-Type: multipart/form-data\n\nmsg_id: 消息ID（需与 URL 中 msg_id 一致）\ncvs_id: 目标会话ID\nfile: <二进制文件内容>\ncontent: <可选，文件说明文本>\nrefer_msg_id: <可选，引用消息ID>\n```\n\n### RobotMessage 结构\n\nJSON 请求的 `body` 使用 `RobotMessage` 结构：\n\n| 字段 | 说明 |\n|------|------|\n| `content` | 文本内容、Markdown 内容或文件说明 |\n| `file_list` | 文件数组，元素为 `RobotFile` |\n| `at_uid_list` | @ 用户列表 |\n| `mentioned_list` | 兼容企业微信类命名 |\n\n`file_list[]` 中常用字段包括 `res_id`、`fid`、`dir_id`、`file_name`、`content_type`、`file_size`、`url`、`base64`。外部调用方不需要再使用 `TextMsg`、`ImageMsg`、`FileMsg`、`MarkdownMsg` 或 `msg_type`。\n\n## 注意事项\n\n1. **安全性**：`TALK_ROBOT_KEY` 是敏感信息，请勿提交到代码仓库\n2. **会话 ID 必填**：`cvs_id` 用于指定目标会话，缺失会导致 `/robot/send` 返回参数错误\n3. **投递语义**：`/robot/send` 只表示事件已投递给机器人；是否最终回消息由机器人脚本决定\n4. **并发限制**：大量消息推送可能触发限流，建议合理控制发送频率\n5. **会话隔离**：每个用户的会话是独立的，OpenClaw 不应跨会话共享上下文\n\n## 参考文档\n\n- [SKILL.md](./SKILL.md) - OpenClaw 技能详细说明\n- [config.yaml](./config.yaml) - 技能配置文件\n\nFile v0.8.0:_meta.json\n\n{\n  \"ownerId\": \"kn78g6avmt6xsvd4c2acd7sd5h85dqx6\",\n  \"slug\": \"yunitalk-beta\",\n  \"version\": \"0.8.0\",\n  \"publishedAt\": 1778818938520\n}\n\nFile v0.8.0:config.yaml\n\nversion: 1\nmode: prompt\n\nskill:\n  name: openclaw-yunitalk\n  display_name: OpenClaw 与 与你聊聊对话\n  description: 使用 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\n\n# OpenClaw 侧需要用户配置 Talk Robots 的连接信息\nconfig:\n  # Talk Robots 服务端点\n  robot_endpoint:\n    type: string\n    required: false\n    description: Talk Robots 服务端点地址，用于发送消息；默认值为 https://yunitalk-im-dev.yuni.vip/v1/robot/send，可通过环境变量 TALK_ROBOT_ENDPOINT 覆盖\n    default: \"https://yunitalk-im-dev.yuni.vip/v1/robot/send\"\n\n  # 机器人 ID\n  robot_id:\n    type: string\n    required: true\n    description: 机器人 ID，用于签名鉴权；默认从环境变量 TALK_ROBOT_ID 读取\n    default: \"${TALK_ROBOT_ID}\"\n\n  # 机器人密钥\n  robot_key:\n    type: string\n    required: true\n    description: 机器人密钥，用于签名鉴权；默认从环境变量 TALK_ROBOT_KEY 读取\n    default: \"${TALK_ROBOT_KEY}\"\n\n  # 可选：默认 agent ID\n  default_agent_id:\n    type: string\n    required: false\n    description: 默认使用的 OpenClaw Agent ID\n    default: main\n\n# 运行时变量（由 Talk Robots 调用时注入）\nvariables:\n  cvs_id:\n    type: string\n    description: 当前会话ID，由 Talk Robots 在调用时注入\n\n# 能力声明（用于 MCP 模式，prompt 模式下可忽略）\ncapabilities:\n  send_text:\n    enabled: true\n    description: 通过 Robot 消息接口投递文本事件给指定机器人；JSON 请求体使用完整 imx.Msg 结构\n    endpoint: \"{{config.robot_endpoint}}?robot_id={{config.robot_id}}&noncestr={{nonce}}&timestamp={{timestamp}}&msg_id={{msg_id}}&sign={{sign}}\"\n    method: POST\n    content_type: application/json\n    payload_schema:\n      type: object\n      properties:\n        cmd:\n          type: string\n          const: msg\n          description: 固定为 msg\n        head:\n          type: object\n          properties:\n            msg_id:\n              type: string\n              description: 消息 ID，需与 URL 中 msg_id 一致\n            cvs_id:\n              type: string\n              description: 目标会话 ID\n            refer_msg_id:\n              type: string\n              description: 可选，引用消息 ID","readmeExcerpt":"Skill: Yunitalk Beta Owner: blackbeans Summary: 该技能用于 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话 Tags: latest:0.8.5 Version history: v0.8.5 | 2026-06-23T10:03:46.984Z | auto yunitalk-beta 0.8.5 - 改用 Talk Robots 机器人配置页扫码保存 /openclaw --init <base64-json> 完成初始化，简化用户流程。 - cvs_id 参数改为可选，不传时默认发给机器人与创建者的点对点会话，相关说明同步调整。 - 新增推荐使用 npm 包 yntalk-openclaw-init 生成初始化指令及二维码，并删去对 shell/util.sh 的引用。 - 删除 shell/util.sh 脚本及 skill-card.md 文件，原流","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"/openclaw --init <base64-json>"},{"language":"json","snippet":"{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}"},{"language":"bash","snippet":"npx yntalk-openclaw-init"},{"language":"bash","snippet":"./shell/robot_send.sh text \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --content \"你好，任务已经处理完成。\""},{"language":"bash","snippet":"./shell/robot_send.sh file \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\""},{"language":"text","snippet":"/openclaw --init <base64-json>"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: yunitalk-beta\ndescription: 该技能用于 OpenClaw 接入与你聊聊，实现聊聊与 OpenClaw 的对话\nversion: 0.8.5\nbuild: 20260613\n---\n\n# OpenClaw 会话技能\n\n你可以通过 Talk Robots `/robot/send` 把文本或文件事件投递给当前聊聊机器人。`cvs_id` 是可选目标会话 ID；不传时默认投递到机器人与创建者的点对点会话。\n\n## 初始化流程\n\n本集成通过 Talk Robots 机器人配置页完成初始化。\n\n请让用户在机器人配置页找到 `OpenClaw连接信息` 参数，扫描或粘贴 OpenClaw 生成的初始化指令。初始化指令格式为：\n\n```text\n/openclaw --init <base64-json>\n```\n\n其中 `<base64-json>` 是对下面 JSON 做 UTF-8 Base64 编码后的内容：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}\n```\n\n安装完成后，请提示用户通过 npm CLI 读取本机 OpenClaw 配置并生成连接信息二维码，然后在 Talk Robots 机器人配置页的 `OpenClaw连接信息` 中扫码保存。推荐使用：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n`yntalk-openclaw-init` 默认无参数运行即可输出可扫码保存到 `OpenClaw连接信息` 的 `/openclaw --init <base64-json>` 和命令行二维码。\n\n不要明文展示 `OPENCLAW_TOKEN`。Base64 不是加密，不要把连接信息或二维码发送到不可信渠道。\n\n## 连接信息保存\n\nTalk Robots 机器人在配置页扫码保存连接信息后，会：\n\n1. 从 `/openclaw --init <base64-json>` 中提取 `<base64-json>`。\n2. Base64 decode 连接 JSON，保存 `OPENCLAW_URL`、`OPENCLAW_TOKEN` 和可选 `OPENCLAW_LAN_URL`。\n\n如需使用本 skill 主动发送文本或文件，以下配置必须由 OpenClaw 运行环境或管理员提供：\n\n| 字段 | 环境变量 | 说明 |\n|------|----------|------|\n| `robot_endpoint` | `TALK_ROBOT_ENDPOINT` | Talk Robots `/v1/robot/send` 地址 |\n| `robot_id` | `TALK_ROBOT_ID` | 机器人 ID |\n| `robot_key` | `TALK_ROBOT_KEY` | 机器人签名密钥 |\n| `cvs_id` | `TALK_ROBOT_CVS_ID` | 可选目标会话 ID；不传时默认投递到机器人与创建者的点对点会话 |\n\n不要回显 `robot_key`。\n\n## 发送消息\n\n优先使用 `shell/robot_send.sh`，不要手写签名。\n\n### 文本\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 文件\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"{{robot_endpoint}}\" \\\n  --robot-id \"{{robot_id}}\" \\\n  --robot-key \"{{robot_key}}\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n不确定参数是否正确时先加 `--dry-run`。\n\n## Rules\n\n1. 只引导用户在 Talk Robots 机器人配置页的 `OpenClaw连接信息` 中扫码保存 `/openclaw --init <base64-json>`。\n2. 发送前必须确认 `robot_endpoint`、`robot_id`、`robot_key` 都存在。\n3. `cvs_id` 是可选参数；只有明确要投递到指定会话时才传入，并保持大小写原样。不传时默认投递到机器人与创建者的点对点会话。\n4. 文本消息使用完整 `imx.Msg` JSON，`cmd=msg`，文本放 `body.content`。\n5. 文件消息使用 `multipart/form-data`，通过 `file` 字段上传。\n6. `/robot/send` 只是把事件投递给目标 robot，最终是否回发由机器人脚本决定。\n7. 不要明文展示 `OPENCLAW_TOKEN` 或 `robot_key`，不要虚构配置或用户资料。"},{"path":"npm/yntalk-openclaw-init/README.md","content":"# yntalk-openclaw-init\n\n`yntalk-openclaw-init` 用于生成 Talk Robots OpenClaw 机器人配置页可扫码保存的初始化指令和命令行二维码。\n\n它会读取本机 OpenClaw 的 `openclaw.json`，从 Gateway 配置中获取端口、绑定模式和 `gateway.auth.token`，再探测本机局域网 IPv4 与公网 IP，生成可直接扫码写入机器人 `OpenClaw连接信息` 配置项的 `/openclaw --init <base64-json>` 初始化指令。\n\n该工具没有运行时依赖，二维码使用终端黑白字符块绘制。\n\n## 二维码内容\n\n二维码内容是机器人配置页可识别的初始化指令：\n\n```text\n/openclaw --init <base64-json>\n```\n\n其中 `<base64-json>` 是下面 JSON 的 UTF-8 Base64 编码：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}\n```\n\n`docs/openclaw-robot.js` 可以识别这个格式。请在机器人配置页的 `OpenClaw连接信息` 字段中扫码保存；保存后回到聊聊会话发送普通消息即可触发自动连通。\n\n## 安装\n\n不安装，直接运行：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n全局安装后运行：\n\n```bash\nnpm install -g yntalk-openclaw-init\nyntalk-openclaw-init\n```\n\n在本仓库中调试本地版本：\n\n```bash\nnpx ./docs/skills/yunitalk-beta/npm/yntalk-openclaw-init\n```\n\n## 使用\n\n默认无参数运行：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n无参数运行会自动获取当前 OpenClaw 连接信息，并输出：\n\n- 局域网访问地址\n- 局域网 OpenAI Base URL\n- 公网访问地址\n- 公网 OpenAI Base URL\n- Gateway 状态\n- `/openclaw --init <base64-json>` 初始化指令\n- 1x1 scale 命令行二维码\n\n命令行参数只支持：\n\n```bash\nnpx yntalk-openclaw-init -h\nnpx yntalk-openclaw-init -v\n```\n\n全局安装后也可以这样运行：\n\n```bash\nyntalk-openclaw-init\nyntalk-openclaw-init -h\nyntalk-openclaw-init -v\n```\n\n参数说明：\n\n- `-h` / `--help`：显示帮助\n- `-v` / `--verbose`：打印配置查找、Gateway 推导和公网 IP 探测日志\n\n## 默认读取逻辑\n\n工具默认会：\n\n- 查找并读取本地 `openclaw.json`\n- 从 `gateway.port` 读取 Gateway 端口，缺省为 `18789`\n- 从 `gateway.bind` 读取 Gateway 绑定模式\n- 从 `gateway.auth.token` 读取 `OPENCLAW_TOKEN`\n- 检查 `gateway.http.endpoints.chatCompletions.enabled`\n- 探测本机局域网 IPv4 和公网 IP\n- 使用公网 Gateway 根地址作为初始化 JSON 中的 `OPENCLAW_URL`\n- 使用局域网 Gateway 根地址作为初始化 JSON 中的 `OPENCLAW_LAN_URL`\n- 额外打印以 `/v1` 结尾的 OpenAI Base URL，方便核对接口地址\n\n注意：初始化 JSON 中的 `OPENCLAW_URL` 不带 `/v1`。`docs/openclaw-robot.js` 会在请求时自动拼接 `/v1/chat/completions`，同时也兼容扫码内容本身已经带 `/v1` 的情况。\n\n## 配置文件位置\n\n工具会按以下位置查找 `openclaw.json`：\n\n- `OPENCLAW_CONFIG` 环境变量指定的路径\n- 当前目录及父目录下的 `openclaw.json`\n- 当前目录及父目录下的 `.openclaw/openclaw.json`\n- `~/openclaw.json`\n- `~/.openclaw/openclaw.json`\n- `~/.config/openclaw/openclaw.json`\n- macOS: `~/Library/Application Support/OpenClaw/openclaw.json`\n\n## 输出示例\n\n```text\n局域网访问地址:\nhttp://192.168.1.10:18789\n\n局域网 OpenAI Base URL:\nhttp://192.168.1.10:18789/v1\n\n公网访问地址:\nhttp://203.0.113.10:18789\n\n公网 OpenAI Base URL:\nhttp://203.0.113.10:18789/v1\n\nGateway:\nbind: all\nport: 18789\nauth_mode: bearer\nchatCompletions: enabled\n\n扫码连接内容:\n/openclaw --init eyJPUEVOQ0xBV19VUkw...\n\n二维码(1x1):\n████...\n```\n\n如果公网 IP 探测失败，工具会回退到局域网地址，并在 stderr 中打印 warning。此时生成的公网访问地址并不是真正的公网地址。\n\n如果 `gateway.bind` 不是 `lan`、`all`、`0.0.0.0` 或 `::`，工具也会打印 warning，提示公网访问可能失败。\n\n## 常见问题\n\n### 找不到 `openclaw.json`\n\n确认 OpenClaw 已在本机初始化，并且配置文件位于默认查找路径之一。也可以用环境变量显式指定：\n\n```bash\nOPENCLAW_CONFIG=/path/to/openclaw.json npx yntalk-openclaw-init\n```\n\n### Token 为空\n\n确认 `openclaw.json` 中存在：\n\n```json\n{\n  \"gateway\": {\n    \"auth\": {\n      \"token\": \"your-token\"\n    }\n  }\n}\n```\n\n### Chat API 未启用\n\n确认配置中开启了 OpenAI 兼容接口：\n\n```json\n{"},{"path":"README.md","content":"# OpenClaw 与 Talk Robots 集成指南\n\n本 Skill 用于将 OpenClaw 接入与你聊聊 (Talk Robots)。初始化流程通过 Talk Robots 机器人配置页的 `OpenClaw连接信息` 扫码项完成，不需要用户在聊聊会话输入任何命令。\n\n二维码内容是初始化指令，格式为：\n\n```text\n/openclaw --init <base64-json>\n```\n\n其中 `<base64-json>` 是对 JSON 做 UTF-8 Base64 编码后的内容，JSON 包含：\n\n```json\n{\"OPENCLAW_URL\":\"https://your-openclaw-domain\",\"OPENCLAW_TOKEN\":\"your-openclaw-gateway-token\",\"OPENCLAW_LAN_URL\":\"http://your-lan-ip:port\"}\n```\n\nTalk Robots 机器人配置页扫码保存后，机器人会 Base64 decode 并保存 OpenClaw 连接信息。用户随后在聊聊会话中发送普通消息，即可通过 OpenClaw 进行对话。\n\n## 功能概述\n\n- **双向通信**：用户可以通过聊聊与 OpenClaw 对话。\n- **自动初始化**：通过机器人配置页 `OpenClaw连接信息` 扫码导入 OpenClaw URL/Token。\n- **连接自检**：将同一条 `/openclaw --init <base64-json>` 发送到会话时，Talk Robots 机器人会向 OpenClaw 发送“我发送 ping，你帮我回复 pong”验证配置。\n- **事件投递**：OpenClaw 可调用 `/robot/send` 将文本或文件事件投递给指定机器人。\n\n## 快速开始\n\n### 1. 安装 Skill\n\n使用 `clawhub` 安装：\n\n```bash\nclawhub install yunitalk-beta\n```\n\n`shell/robot_send.sh` 依赖 `curl`、`openssl` 和 `python3`。如果 OpenClaw 运行环境是容器，请确认镜像内已安装这些命令。\n\n本地开发调试未发布版本时，才需要使用本仓库中的 `docs/skills/yunitalk-beta/` 目录。\n\n### 2. 生成扫码连接内容\n\n推荐使用 npm CLI 直接读取本机 OpenClaw 连接信息并生成可扫码的连接内容：\n\n```bash\nnpx yntalk-openclaw-init\n```\n\n也可以先全局安装后运行：\n\n```bash\nnpm install -g yntalk-openclaw-init\nyntalk-openclaw-init\n```\n\n在本仓库内调试未发布版本时，可以直接运行本地包：\n\n```bash\nnpx ./docs/skills/yunitalk-beta/npm/yntalk-openclaw-init\n```\n\n本仓库内的 CLI 源码位于 `npm/yntalk-openclaw-init/`；发布到 npm 后即可直接通过上面的 `npx` 命令使用。CLI 默认读取本机 `openclaw.json` 的 `gateway.port`、`gateway.bind`、`gateway.auth.token` 和 `gateway.http.endpoints.chatCompletions.enabled`，使用本机局域网 IPv4 生成局域网访问地址，并探测公网 IP 生成公网访问地址，最后输出完整 `/openclaw --init <base64-json>` 初始化指令和 1x1 scale 命令行二维码。\nCLI 只支持 `-h/--help` 和 `-v/--verbose` 两个参数；默认无参数运行即可输出局域网访问地址、公网访问地址、初始化指令和 1x1 scale 二维码。生成的初始化 JSON 中 `OPENCLAW_URL` 使用公网访问地址，`OPENCLAW_LAN_URL` 保存局域网访问地址。\n提交 `docs/openclaw-robot.js` 后，在机器人配置页的 `OpenClaw连接信息` 参数中扫码保存该二维码内容，脚本会自动解析并写入 `OPENCLAW_URL` 和 `OPENCLAW_TOKEN`。\n\n输出示例：\n\n```text\n局域网访问地址:\nhttp://192.168.1.10:3000\n\n公网访问地址:\nhttp://203.0.113.10:3000\n\n扫码连接内容:\n/openclaw --init eyJPUEVOQ0xBV19VUkw...\n\n二维码(1x1):\n████...\n```\n\nnpx CLI 默认会自动读取本地 `openclaw.json` 的 Gateway 配置，探测公网 IP 生成公网访问地址，并从 `gateway.auth.token` 获取 Token，不需要手动传入这些配置。Base64 不是加密，不要把 `OPENCLAW_TOKEN` 明文、初始化指令、扫码连接内容或二维码发送到不可信渠道。\n\n### 3. 在机器人配置页扫码保存\n\n打开 Talk Robots 机器人配置页，找到 `OpenClaw连接信息` 参数，扫描或粘贴上一步生成的 `/openclaw --init <base64-json>` 并保存。保存后回到聊聊会话，发送任意普通消息即可开始对话。\n\n机器人会自动执行：\n\n1. 从扫码保存的初始化指令中提取 `<base64-json>` 并执行 Base64 decode，得到包含 `OPENCLAW_URL`、`OPENCLAW_TOKEN` 和可选 `OPENCLAW_LAN_URL` 的 JSON。\n2. 写入 `OPENCLAW_URL`、`OPENCLAW_TOKEN` 和可选 `OPENCLAW_LAN_URL`。\n\n初始化完成后，用户在聊聊里直接发送普通消息即可开始对话。\n\n## OpenClaw Skill 环境变量\n\n如需让 OpenClaw 通过本 Skill 主动调用 `/robot/send` 发送文本或文件，需要在 OpenClaw 中配置以下变量：\n\n| 环境变量 | 对应配置项 | 必填 | 说明 |\n|----------|-----------|------|------|\n| `TALK_ROBOT_ENDPOINT` | `robot_endpoint` | 是 | Talk Robots `/v1/robot/send` 服务端点 |\n| `TALK_ROBOT_ID` | `robot_id` | 是 | 机器人 ID，用于签名鉴权 |\n| `TALK_ROBOT_KEY` | `robot_key` | 是 | 机器人密钥，用于签名鉴权 |\n| `TALK_ROBOT_CVS_ID` | `cvs_id` | 否 | 可选目标会话 ID；不传时默认投递到机器人与创建者的点对点"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn78g6avmt6xsvd4c2acd7sd5h85dqx6\",\n  \"slug\": \"yunitalk-beta\",\n  \"version\": \"0.8.5\",\n  \"publishedAt\": 1782209026984\n}"},{"path":"ROBOT_SEND_API.md","content":"# Talk Robots 机器人消息发送接口\n\n本文档说明 OpenClaw 通过 Talk Robots `/robot/send` 向与你聊聊机器人投递消息的方式，覆盖文本消息和文件消息两类请求。\n\n`/robot/send` 的语义是把事件投递给目标机器人；机器人是否最终向会话回复，由机器人脚本决定。\n\n## 推荐调用方式\n\n优先使用本 Skill 内置脚本 `shell/robot_send.sh`。脚本会自动生成 `msg_id`、`noncestr`、`timestamp` 和 HMAC-SHA256 `sign`，避免业务侧重复实现签名逻辑。\n\n### 发送文本\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --content \"你好，任务已经处理完成。\"\n```\n\n### 发送文件\n\n```bash\n./shell/robot_send.sh file \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --content \"请查看附件\" \\\n  --file \"./report.pdf\"\n```\n\n### 发送前预检\n\n使用 `--dry-run` 可以查看签名 URL 和请求体，不会实际发送消息。\n\n```bash\n./shell/robot_send.sh text \\\n  --base-url \"$TALK_ROBOT_ENDPOINT\" \\\n  --robot-id \"$TALK_ROBOT_ID\" \\\n  --robot-key \"$TALK_ROBOT_KEY\" \\\n  --content \"测试消息\" \\\n  --dry-run\n```\n\n脚本常用参数：\n\n| 参数 | 必填 | 说明 |\n|------|------|------|\n| `--base-url` | 是 | Talk Robots `/v1/robot/send` 地址，即 `TALK_ROBOT_ENDPOINT` |\n| `--robot-id` | 是 | 机器人 ID |\n| `--robot-key` | 是 | 机器人 Key，用于签名 |\n| `--cvs-id` | 否 | 可选目标会话 ID，应保持大小写原样；不传时默认投递到机器人与创建者的点对点会话 |\n| `--content` | 文本必填，文件可选 | 文本消息内容，或文件说明文本 |\n| `--file` | 文件必填 | 待上传文件路径 |\n| `--refer-msg-id` | 否 | 引用的消息 ID |\n| `--msg-id` | 否 | 指定消息 ID；不传时脚本自动生成 |\n| `--noncestr` | 否 | 指定随机串；不传时脚本自动生成 |\n| `--timestamp` | 否 | 指定 Unix 秒级时间戳；不传时脚本自动生成 |\n| `--at` | 否 | 文本消息的 `at_uid_list`，多个 UID 用英文逗号分隔 |\n| `--mentioned` | 否 | 文本消息的 `mentioned_list`，多个 UID 用英文逗号分隔 |\n| `--dry-run` | 否 | 只打印请求信息，不实际发送 |\n\n## 直接使用 curl\n\n不使用 `shell/robot_send.sh` 时，可以直接用 `curl` 调用 `/robot/send`。完整的签名生成、文本消息和文件消息示例见：\n\n- [ROBOT_SEND_CURL_API.md](./ROBOT_SEND_CURL_API.md) - 机器人消息 curl 调用示例\n\n## 接口总览\n\n**请求方法**：`POST`\n\n**基础地址**：`{robot_endpoint}`\n\n`robot_endpoint` 通常来自 `TALK_ROBOT_ENDPOINT`，例如：\n\n```text\nhttps://api-talk.yuniapp.cn/v1/robot/send\n```\n\n**鉴权参数**放在 URL 查询参数中：\n\n| 参数 | 必填 | 说明 |\n|------|------|------|\n| `robot_id` | 是 | 机器人 ID |\n| `noncestr` | 是 | 请求随机串 |\n| `timestamp` | 是 | Unix 秒级时间戳 |\n| `msg_id` | 是 | 消息 ID；请求体或表单中的 `msg_id` 必须与 URL 中一致 |\n| `sign` | 是 | 使用 `robot_key` 计算得到的 HMAC-SHA256 签名 |\n\n完整 URL 形态：\n\n```text\n{robot_endpoint}?robot_id={robot_id}&noncestr={nonce}&timestamp={timestamp}&msg_id={msg_id}&sign={sign}\n```\n\n## 签名规则\n\n签名参数为 `msg_id`、`noncestr`、`robot_id`、`timestamp`。生成 `sign` 时：\n\n1. 按参数 key 字典序排序。\n2. 每个 value 使用 URL encode。\n3. 按 `key=value` 拼接，并用 `&` 连接。\n4. 使用 `robot_key` 对签名原文做 HMAC-SHA256。\n5. 将结果编码为小写十六进制字符串。\n\n签名原文示例：\n\n```text\nmsg_id=<msg_id>&noncestr=<noncestr>&robot_id=<robot_id>&timestamp=<timestamp>\n```\n\nShell 示例：\n\n```bash\nsigning_text=\"msg_id=${msg_id}&noncestr=${noncestr}&robot_id=${robot_id}&timestamp=${timestamp}\"\nsign=\"$(printf '%s' \"$signing_text\" | openssl dgst -sha256 -hmac \"$robot_key\" | awk '{print $2}')\"\n```\n\n实际实现时，`signing_text` 里的 value 需要先 URL encode。推荐直接使用 `shell/robot_send.sh`。\n\n## 发送文本消息\n\n文本消息使用 `application/json`，请求体是完整 `imx.Msg` JSON 结构，`cmd` 固定为 `msg`，文本内容放在 `body.content`。\n\n```http\nPOST {robot_endpoint}?robo"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":900,"uniquenessScore":40,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T19:28:30.094Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T19:28:30.094Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-12T01:42:44.276Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}