149 lines
4.4 KiB
Markdown
149 lines
4.4 KiB
Markdown
# TOOLS.md - Local Notes
|
||
|
||
Skills define _how_ tools work. This file is for _your_ specifics — the stuff that's unique to your setup.
|
||
|
||
## What Goes Here
|
||
|
||
Things like:
|
||
|
||
- Camera names and locations
|
||
- SSH hosts and aliases
|
||
- Preferred voices for TTS
|
||
- Speaker/room names
|
||
- Device nicknames
|
||
- Anything environment-specific
|
||
|
||
## Examples
|
||
|
||
```markdown
|
||
### Cameras
|
||
|
||
- living-room → Main area, 180° wide angle
|
||
- front-door → Entrance, motion-triggered
|
||
|
||
### SSH
|
||
|
||
- home-server → 192.168.1.100, user: admin
|
||
|
||
### TTS
|
||
|
||
- Preferred voice: "Nova" (warm, slightly British)
|
||
- Default speaker: Kitchen HomePod
|
||
```
|
||
|
||
## Why Separate?
|
||
|
||
Skills are shared. Your setup is yours. Keeping them apart means you can update skills without losing your notes, and share skills without leaking your infrastructure.
|
||
|
||
---
|
||
|
||
## DingTalk Configuration
|
||
|
||
- **AppKey**: ding4ursdp0l2giat4bj
|
||
- **AppSecret**: J0gBicjKiIHoKla7WfKKhRs1Tv8L6Xd5UhW3EVQByF16G7Vn7UUcRhP6u-PBCQNo
|
||
- **robotCode**: ding4ursdp0l2giat4bj
|
||
- **OpenConversationId**: cidcjYshXVtKck5LfOO9AqOJg==
|
||
|
||
## DingTalk成功发送的关键配置
|
||
|
||
### Token获取(必须使用GET + URL参数)
|
||
```javascript
|
||
// ✓ 正确方式
|
||
const tokenUrl = `https://oapi.dingtalk.com/gettoken?appkey=${APP_KEY}&appsecret=${APP_SECRET}`;
|
||
const token = await axios.get(tokenUrl).data.access_token;
|
||
|
||
// ✗ 错误方式(会失败)
|
||
const tokenUrl = "https://oapi.dingtalk.com/gettoken";
|
||
const token = await axios.get(tokenUrl, {
|
||
params: {appkey: APP_KEY, appsecret: APP_SECRET}
|
||
}).data.access_token;
|
||
```
|
||
|
||
### v1.0 API发送消息(成功方式)
|
||
```javascript
|
||
// API端点
|
||
const url = "https://api.dingtalk.com/v1.0/robot/groupMessages/send";
|
||
|
||
// Headers(关键:包含access_token)
|
||
const headers = {
|
||
"x-acs-dingtalk-access-token": accessToken,
|
||
"Content-Type": "application/json"
|
||
};
|
||
|
||
// Body格式
|
||
const body = {
|
||
robotCode: ROBOT_CODE,
|
||
openConversationId: OPEN_CONVERSATION_ID,
|
||
msgKey: "sampleFile", // 或 "sampleMarkdown"
|
||
msgParam: JSON.stringify({ // ← 必须是字符串!
|
||
mediaId: media_id,
|
||
fileName: "file.txt"
|
||
})
|
||
};
|
||
|
||
await axios.post(url, body, { headers });
|
||
```
|
||
|
||
### 关键msgKey对应关系
|
||
|
||
| 媒体类型 | msgKey | 说明 |
|
||
|---------|--------|------|
|
||
| **文件** | `sampleFile` | 发送.txt, .docx, .pdf等文件 |
|
||
| **图片** | `sampleMarkdown` | 使用Markdown格式嵌入图片 |
|
||
| **视频** | `sampleVideo` | 发送.mp4等视频文件(待测试) |
|
||
|
||
### 重要注意事项
|
||
|
||
1. **msgParam必须是字符串**
|
||
```javascript
|
||
// ✓ 正确
|
||
msgParam: JSON.stringify({mediaId: "@xxx", fileName: "test.txt"})
|
||
|
||
// ✗ 错误
|
||
msgParam: {mediaId: "@xxx", fileName: "test.txt"}
|
||
```
|
||
|
||
2. **直接调用API会失败于OpenClaw环境**
|
||
- OpenClaw的DingTalk插件会拦截所有API请求
|
||
- 直接调用`robot/send`会返回"token is not exist"或"缺少参数 access_token"
|
||
- 必须使用v1.0 API + Headers中的access_token
|
||
|
||
3. **文件上传API**
|
||
```javascript
|
||
// 上传(GET方式获取token已经验证有效)
|
||
const uploadUrl = `https://oapi.dingtalk.com/media/upload?access_token=${accessToken}`;
|
||
const form = new FormData();
|
||
form.append('media', fs.createReadStream(filePath));
|
||
form.append('type', 'file');
|
||
await axios.post(uploadUrl, form, {headers: form.getHeaders()});
|
||
```
|
||
|
||
### OpenClaw Runtime 环境说明
|
||
|
||
- 系统 Node 由 **nvm** 管理。
|
||
- OpenClaw 与 Skill 执行使用独立 Node:`F:/openclaw-runtime`,不受 nvm 切换影响。
|
||
- 系统 Python 由 **pyenv-win** 管理。
|
||
- OpenClaw 也使用独立 Python 运行环境,不受系统 pyenv 切换影响。
|
||
|
||
### 成功案例记录
|
||
|
||
**2026-03-05 18:44** - 成功发送database_analysis_summary.txt
|
||
- 文件: database_analysis_summary.txt (3,155 bytes)
|
||
- media_id: @lAjPM2GaR32g2U3OC2pNq84Clg_0
|
||
- msgKey: sampleFile
|
||
- API: /v1.0/robot/groupMessages/send
|
||
- ProcessQueryKey: lXs/uLRd0YxJVk1x0VyTLfSdY2YKCE1yrGn2vGlQ+GM=
|
||
|
||
### 默认发图稳定流程(柏方确认)
|
||
|
||
当用户说“发图”时,默认按以下顺序执行:
|
||
|
||
1. `GET https://oapi.dingtalk.com/gettoken?appkey=...&appsecret=...` 获取 token
|
||
2. `POST https://oapi.dingtalk.com/media/upload?access_token=...` 上传图片,获取 `media_id`
|
||
3. `POST https://api.dingtalk.com/v1.0/robot/groupMessages/send` 发送消息
|
||
- Header: `x-acs-dingtalk-access-token: <token>`
|
||
- `msgKey = sampleMarkdown`
|
||
- `msgParam` 必须是 JSON 字符串(内嵌图片)
|
||
|
||
Add whatever helps you do your job. This is your cheat sheet.
|