← Back to Plugins
Voice

Plugin Tool Trace

ffexis By ffexis 👁 107 views ▲ 0 votes

A universal tool call metrics and tracing plugin for OpenClaw. Offers plug-and-play auditing for standard channels (Telegram, Discord, Webchat) via native lifecycle hooks, and features an integrated pre-boot AST patcher to fully support Feishu/Lark by bypassing custom reply dispatcher isolation and ESM cache locks.

GitHub

Configuration Example

{
  "plugins": {
    "entries": {
      "tool-trace": { "enabled": true }
    },
    "load": {
      "paths": ["/path/to/openclaw-plugin-tool-trace"]
    }
  }
}

README

# 🛠️ OpenClaw Plugin: Tool Trace

Automatically append tool call statistics to the end of each reply.
Supports **Telegram / Webchat / Slack** text channels and **Feishu (Lark)** card channels.

---

## ✨ Example Output

**Telegram / Webchat:**
```
...reply content...

Tools used: web_search(3), academic_search(2)
```

**Feishu Card:**
```
...reply content...

Tools used: amap-mcp__maps_weather(1)
Agent: main | Model: deepseek-v4-flash | Provider: volcengine coding plan
```

---

## 📦 Installation

### 1. Clone to local

```bash
git clone https://github.com/ffexis/openclaw-plugin-tool-trace.git
# Or symlink to OpenClaw's plugins path
ln -s /path/to/openclaw-plugin-tool-trace /path/to/openclaw/plugins/tool-trace
```

### 2. Enable the plugin

Configure in `openclaw.json`:

```json
{
  "plugins": {
    "entries": {
      "tool-trace": { "enabled": true }
    },
    "load": {
      "paths": ["/path/to/openclaw-plugin-tool-trace"]
    }
  }
}
```

### 3. Restart Gateway

```bash
# Find gateway PID and restart
kill -9 $(pgrep -f openclaw-gateway)
```

### 4. Verify

Send a tool-triggering message from TG / Webchat. The reply should end with `Tools used: xxx(y)`.

---

## 🦜 Feishu (Lark) Support

Feishu plugin uses a separate bundle for card message sending, requiring an extra step.

### How it works

```mermaid
flowchart LR
  Plugin["Plugin after_tool_call"] -->|"Write globalThis.__FEISHU_TOOL_STATS"| Map[Map<targetId, counts>]
  Map -->|"Consume"| Patch["sendCardFeishu (patched)"]
  Patch -->|"Append to card.body.elements[].content"| Card["Feishu Card"]
```

### Run Patch

```bash
cd /path/to/openclaw-plugin-tool-trace
node patch-feishu.mjs
```

The script auto-locates the Feishu plugin's dist directory and injects interception code into the `sendCardFeishu` function.
Idempotent — safe to run multiple times.

**If auto-location fails, specify manually:**

```bash
# Find Feishu plugin location
find / -path "*/@openclaw/feishu/dist" -type d 2>/dev/null
# Then patch manually
node -e "
const fs = require('fs');
const path = '/path/to/@openclaw/feishu/dist/send-*.js';
// ... manual modification
"
```

### Restart Gateway

After patching, restart Gateway:

```bash
kill -9 $(pgrep -f openclaw-gateway)
```

### Verify

Send a tool-triggering message from Feishu. The reply should end with `Tools used: xxx(y)`.

---

## 🏗️ Architecture

### Text Channels (TG / Webchat / Slack)

```
after_tool_call → runToolCounts Map → reply_payload_sending hook → inject at text end
```

### Feishu Card Channel

```
after_tool_call → globalThis.__FEISHU_TOOL_STATS[targetId]
                        ↓
sendCardFeishu (patched) → read statsMap.has(params.to)
                        ↓
                append to card.body.elements[0].content
                        ↓
                call original sendCardFeishu to send
```

### Cross-turn Contamination Prevention

`before_dispatch` hook auto-clears previous turn's residual stats on Feishu inbound.

---

## ⚙️ Customizing Exec Script Name Detection

The plugin detects `script.js`, `task.js`, and similar patterns by default.
To add custom scripts, modify the `EXEC_SCRIPT_PATTERNS` array in `index.mjs`:

```javascript
const EXEC_SCRIPT_PATTERNS = [
  { re: /my-script\.js/, name: "my-script.js" },
];
```

---

## 🤖 Special Thanks (AI Workforce)

While the project repository is single-authored, the grueling warfare against Feishu's nested JSON serialization and custom dispatcher isolation was fought alongside two tireless digital collaborators:

| DeepSeek-V4-Flash | Gemini Pro (LLM) |
| :--- | :--- |
| **The Resident Bootstrapper** <br>• Excavated the native `plugin-sdk`<br>• Monitored standard hook pipelines<br>• Executed localized code patching | **The Remote Think-Tank** <br>• Decoded Feishu's internal AST routing<br>• Formulated the pull-based injection strategy<br>• Blind-solved the fallback interactive card bug |

*Shoutout to the AI workforce for running the repetitive AST extractions and pipeline tracking so the Author didn't have to melt their own bank account on full-scale raw API tokens.*

---

## 📄 License

MIT

---

# 🛠️ OpenClaw 插件:Tool Trace

在每个回复末尾自动附上本轮调用的工具统计。
支持 **Telegram / Webchat / Slack** 等文本通道,以及 **飞书(Feishu / Lark)** 卡片通道。

---

## ✨ 效果

**Telegram / Webchat:**
```
...回复内容...

调用工具:web_search(3),academic_search(2)
```

**飞书卡片:**
```
...回复内容...

调用工具:amap-mcp__maps_weather(1)
Agent: main | Model: deepseek-v4-flash | Provider: volcengine coding plan
```

---

## 📦 安装

### 1. 克隆到本地

```bash
git clone https://github.com/ffexis/openclaw-plugin-tool-trace.git
# 或者放在 OpenClaw 的 plugins 路径下
ln -s /path/to/openclaw-plugin-tool-trace /path/to/openclaw/plugins/tool-trace
```

### 2. 启用插件

在 `openclaw.json` 中配置:

```json
{
  "plugins": {
    "entries": {
      "tool-trace": { "enabled": true }
    },
    "load": {
      "paths": ["/path/to/openclaw-plugin-tool-trace"]
    }
  }
}
```

### 3. 重启 Gateway

```bash
# 找到 gateway PID 并重启
kill -9 $(pgrep -f openclaw-gateway)
```

### 4. 验证

从 TG / Webchat 发一条会调用工具的对话,回复末尾应出现 `调用工具:xxx(y)`。

---

## 🦜 飞书(Feishu / Lark)支持

飞书插件使用独立的 bundle 管理卡片消息发送,因此多了一个额外步骤。

### 原理

```mermaid
flowchart LR
  Plugin["插件 after_tool_call"] -->|"写入 globalThis.__FEISHU_TOOL_STATS"| Map[Map<targetId, counts>]
  Map -->|"消费"| Patch["sendCardFeishu(已 patch)"]
  Patch -->|"追加到 card.body.elements[].content"| Card["飞书卡片"]
```

### 执行 Patch

```bash
cd /path/to/openclaw-plugin-tool-trace
node patch-feishu.mjs
```

脚本会自动定位飞书插件的 dist 目录,在 `sendCardFeishu` 函数入口注入拦截代码。
幂等设计,重复运行安全。

**如脚本未能自动定位飞书路径,可手动指定:**

```bash
# 查看飞书插件实际位置
find / -path "*/@openclaw/feishu/dist" -type d 2>/dev/null
# 然后手动 patch
node -e "
const fs = require('fs');
const path = '/path/to/@openclaw/feishu/dist/send-*.js';
// ... 手动修改
"
```

### 重启 Gateway

Patch 后需要重启 Gateway 使拦截代码生效:

```bash
kill -9 $(pgrep -f openclaw-gateway)
```

### 验证

从飞书发一条会调用工具的对话,回复末尾应出现 `调用工具:xxx(y)`。

---

## 🏗️ 架构

### 文本通道(TG / Webchat / Slack 等)

```
after_tool_call → runToolCounts Map → reply_payload_sending hook → 注入 text 末尾
```

### 飞书卡片通道

```
after_tool_call → globalThis.__FEISHU_TOOL_STATS[targetId]
                        ↓
sendCardFeishu (已 patch) → 读取 statsMap.has(params.to)
                        ↓
                追加到 card.body.elements[0].content
                        ↓
                调用原始 sendCardFeishu 发送
```

### 跨轮防污染

`before_dispatch` hook 在飞书入站阶段自动清理上一轮的残留统计。

---

## ⚙️ 自定义 exec 脚本名识别

插件默认识别 `script.js`、`task.js` 等常见模式。
如需添加自定义脚本,修改 `index.mjs` 中的 `EXEC_SCRIPT_PATTERNS` 数组:

```javascript
const EXEC_SCRIPT_PATTERNS = [
  { re: /my-script\.js/, name: "my-script.js" },
];
```

---

## 🤖 特别致谢(AI 工作组)

虽然项目仓库是单人创作,但对抗飞书嵌套 JSON 序列化和自定义调度器隔离的艰苦战争,是由两位不知疲倦的数字合作者并肩作战:

| DeepSeek-V4-Flash | Gemini Pro (LLM) |
| :--- | :--- |
| **驻场启动器** <br>• 挖掘原生 `plugin-sdk`<br>• 监控标准钩子管道<br>• 执行本地化代码修补 | **远程智囊团** <br>• 解码飞书内部 AST 路由<br>• 制定拉取式注入策略<br>• 盲解回退交互卡片 bug |

*感谢 AI 工作组执行重复的 AST 提取和管道追踪,让作者不用烧掉自己的账户来支付全量原始 API token。*

---

## 📄 License

MIT
voice

Comments

Sign in to leave a comment

Loading comments...