Skip to main content
Glama
README.md
# agent-pulse

**AI Agent 会话可观测性 CLI + 只读 MCP 巡检服务。** 零依赖、纯本地、Node 18+ 直接跑,不需要 npm install,不需要 API key,不上传任何日志。

```
  agent-pulse
  ├─ analyze   JSONL 会话日志 → 成功率 / 耗时 / token / 成本 / 循环与失败检测 → HTML 报告
  └─ mcp       5 个只读工具,让 AI Agent 能安全地检查一台机器
```

---

## 为什么是这个功能

不是拍脑袋想出来的产品,需求来自真实公开信息(2026-11-14 检索):

- **Hacker News《Ask HN: Who is hiring? (November 2026)》**([原帖 id 50338728](https://news.ycombinator.com/item?id=50338728))里,Stratirus 的初/中级 AI 开发岗给了一道实操考卷:修好一台出问题的 Ubuntu 服务器、写自动修复脚本,再「build a small **read-only MCP tool** so an AI agent can check on it」。岗位明确写了 *early-career and career-switchers welcome*、不考 LeetCode、看重 work samples。
  - 注意:该岗位限 **US only + 美国工作许可**,本项目**没有**替任何人申请,只是把被真实雇主验证过的能力标尺做成了可复用的成品。
- **Upwork 在招的 AI Agent Developer**([职位页](https://www.upwork.com/freelance-jobs/apply/Agent-Developer-Needed-for-Custom-Agents-LangGraph-LangChain-Integrations_~022110776769352188799),$15–40/hr,Intermediate)要求「至少有一个真实用户在用的已上线 Agent」,并且看重 **logging / evals / guardrails**。可观测性正好是这个方向里最容易被忽略、又最容易做出差异的一块。
- **市场量级**:[Jobbi 2026-10-14 悬赏指数](https://jobbi.org/news/what-agent-gigs-paid-this-week-2026-10-14) 记录 749 个开放付费任务、中位 $20、151 个 ≥$50、68% 资金已托管;[2026 接单平台选型](https://juejin.cn/post/7682232112121675828) 里,AI Agent / LLM 定制是国内远程兼职的高频品类。

一句话:**Agent 用得越多,越没人知道它到底干了什么、慢在哪、钱花在哪。** 这个工具就是回答这三个问题的。

---

## 快速开始

```bash
cd agent-pulse

# 1. 跑内置示例:终端摘要 + 生成 dist/demo-report.html
node bin/agent-pulse.mjs demo

# 2. 跑内置断言(解析 / 分析 / MCP 安全边界)
node bin/agent-pulse.mjs selftest

# 3. 分析自己的日志,并导出 HTML 与 JSON
node bin/agent-pulse.mjs analyze ~/path/to/session.jsonl \
  --html report.html --json report.json --price-in 3 --price-out 15
```

`dist/demo-report.html` 是单文件报告,直接双击就能看,不联网、无外部资源,适合放进作品集或发给客户。

## MCP 服务

```bash
# stdio JSON-RPC,每行一个请求
node bin/agent-pulse.mjs mcp

# 限定允许读取的根目录(强烈建议)
AGENT_PULSE_ALLOWED_ROOT=/var/log node bin/agent-pulse.mjs mcp
```

接入 Claude Code / Cursor 之类的客户端时,配置形如:

```json
{
  "mcpServers": {
    "agent-pulse": {
      "command": "node",
      "args": ["/absolute/path/to/agent-pulse/bin/agent-pulse.mjs", "mcp"],
      "env": { "AGENT_PULSE_ALLOWED_ROOT": "/absolute/path/to/allowed/root" }
    }
  }
}
```

5 个工具,全部只读:

| 工具 | 作用 |
| --- | --- |
| `system_info` | 主机名、OS、CPU、内存、负载、运行时长、允许根目录 |
| `memory_status` | 内存占用率、load average、CPU 逻辑核数 |
| `disk_usage` | 指定路径的容量、剩余空间、使用率 |
| `log_tail` | 读取日志文件末尾 N 行(1–200) |
| `health_check` | 汇总磁盘 / 内存 / 负载,输出 `ok / warn / critical` 与逐项结果 |

### 安全边界(这是设计重点,不是附带说明)

- **不执行任何 shell 命令**:全项目没有 `child_process`,只调用 Node 内置 `os` / `fs` API。
- **不写任何文件、不发起任何网络请求**。
- **路径白名单**:所有路径先 `resolve` 到 `AGENT_PULSE_ALLOWED_ROOT`(默认 cwd)内部,越界直接报错。
- **拒绝凭证类文件**:文件名含 `.env` / `id_rsa` / `.pem` / `secret` / `token` 等模式时拒绝读取。
- **日志读取上限 2 MiB**,单次最多 200 行,避免把大文件塞进上下文。
- **只诊断、不修复**:`health_check` 给结论,不重启服务、不删文件、不改配置。生产环境的修复动作应由人决定。

`selftest` 里对「路径越界」和「凭证文件」两条都做了断言,改代码后请务必重跑。

---

## 支持的日志格式

不要求严格 schema,按字段别名尽力归一化,无法解析的行会跳过并计数,不会中断:

1. **通用 JSONL**:`{ type: "tool_call"|"tool_result"|"error", name, timestamp, duration_ms, ok, is_error, tokens: {...} }`
2. **Claude Code 风格**:`{ type: "assistant"|"user", timestamp, message: { content: [{ type: "tool_use"|"tool_result", ... }], usage } }`
3. **OpenCode / 自定义风格**:`ts` / `tool` / `durationMs` / `sessionId` 等常见别名均可识别

当日志没有 `duration_ms` 时,会用配对的调用与结果时间戳差推导耗时。`callTool` 之外的所有逻辑都只做读取与计算。

### 输出指标

工具调用数、成功率、失败数、avg / p50 / p95 / max 耗时、每个工具的调用与失败排行、token 输入/输出、估算成本、疑似循环(连续 ≥3 次同名调用)、失败明细、最慢调用 Top 8、按分钟的时间线。

> **成本口径**:日志里若有 `cost_usd` 就汇总显示;否则按 `$3 / $15 per 1M tokens` 估算(可用 `--price-in` / `--price-out` 或环境变量改)。这是趋势参考,**不是账单**,报告里也明确标注了。

---

## 这个成品可以怎么用

| 路径 | 怎么用 | 仍然需要本人做的部分 |
| --- | --- | --- |
| 求职作品集 | 把 `demo-report.html` 和仓库链接放进简历 / 申请邮件,作为「交付过的work sample」 | 写申请、投简历、回答问题(雇主明确要求本人作答) |
| 独立工具售卖 | 以 MIT 开源 Community 版引流,做 Pro 版(多会话对比、CI 集成、告警)走 Gumroad / Lemon Squeezy | 开店、实名、收款、定价决策 |
| 接单交付物 | 给 AI Agent 客户附带一份运行报告,作为 logging / evals 能力的证明 | 与客户沟通、签合同、确认交付范围 |

**重要**:这是一个已经能运行的资产,不代表已经接到单、投出简历或产生收入。任何对外的注册、投标、沟通、收款动作都需要账号实名与本人确认,本项目不含、也不会代替这些环节。

---

## 已知限制

- 配对是「同名的先进先出」,并发同名工具调用可能错配;需要精确归因时建议在日志里带上 `tool_use_id`(后续版本可支持)。
- 时间线按 UTC 分钟分桶,跨时区阅读时请自行换算。
- `statfsSync` 在个别平台不可用时会返回 `available: false`,不推断数值。
- macOS 的 `os.freemem()` 不把可回收缓存计入空闲内存,`health_check` 的内存占用率可能偏高,判断时请以磁盘与负载项为主。
- `session` 缺失的结果事件会继承上一个显式会话;多会话交错写入同一文件时属于启发式推断,需要精确归因请带 `session_id`。
- 目前只做离线分析,不做实时流式监控。

## 许可

MIT,见 [LICENSE](./LICENSE)。