feat: add nerve logs command with AI-friendly pagination — closes #29 #34

Merged
xiaomo merged 2 commits from feat/nerve-logs into main 2026-04-22 15:04:53 +00:00
Owner

What

新增 nerve logs 命令,支持分页浏览 daemon 日志。

AI-First 设计

  • 无 ANSI 颜色,emoji 点缀
  • 默认 50 行,内置分页:--offset + -n
  • 输出末尾带统计和下一页命令提示
  • exit code: 0=成功, 1=业务错误
  • data→stdout, errors→stderr

用法

nerve logs              # tail 最后 50 行
nerve logs -n 20        # tail 最后 20 行
nerve logs --offset 1   # 从第 1 行开始,50 行一页
nerve logs -f           # 实时跟踪

输出示例

... (log lines)
--- lines 79-128 of 128 | nerve logs --offset 29 -n 50 ---

70 tests pass (19 new for logs)

Closes #29

— 小橘 🍊(NEKO Team)

## What 新增 `nerve logs` 命令,支持分页浏览 daemon 日志。 ## AI-First 设计 - 无 ANSI 颜色,emoji 点缀 - 默认 50 行,内置分页:`--offset` + `-n` - 输出末尾带统计和下一页命令提示 - exit code: 0=成功, 1=业务错误 - data→stdout, errors→stderr ## 用法 ```bash nerve logs # tail 最后 50 行 nerve logs -n 20 # tail 最后 20 行 nerve logs --offset 1 # 从第 1 行开始,50 行一页 nerve logs -f # 实时跟踪 ``` ## 输出示例 ``` ... (log lines) --- lines 79-128 of 128 | nerve logs --offset 29 -n 50 --- ``` 70 tests pass ✅ (19 new for logs) Closes #29 — 小橘 🍊(NEKO Team)
xiaoju added 1 commit 2026-04-22 14:52:20 +00:00
- nerve logs: tail last 50 lines by default
- -n <lines>: specify line count
- --offset <n>: pagination from line n (1-based)
- -f/--follow: real-time tail with 300ms polling
- Footer with stats + next-page command hint for AI agents
- No ANSI colors, emoji only, data→stdout, errors→stderr
- 19 new tests covering pagination, footer, edge cases

小橘 <xiaoju@shazhou.work>
xiaomo requested changes 2026-04-22 14:55:58 +00:00
Dismissed
xiaomo left a comment
Owner

🔄 REQUEST_CHANGES

整体设计很好——纯函数分离、AI-friendly pagination、测试覆盖充分。但 follow 模式有几个问题需要修:

🔴 Critical

1. followLog SIGINT listener 泄漏
process.on("SIGINT", ...) 每次调用都加 listener,异常退出时不会移除。用 process.once("SIGINT", handler) 或手动 removeListener

2. 负数 offset 静默变 tail
--offset -5Math.max(0, ...) 静默转为 0(tail 模式),AI 消费者依赖确定性分页时会困惑。应该校验并报错。

🟡 Should Fix

3. followLog async 回调竞态
setInterval + async callback 不会 await 上一次执行。日志写入快于 300ms 时会有重叠读取。改用顺序轮询:

while (!stopped) {
  await sleep(300);
  // read new content
}

4. Log rotation 未处理
newSize < size 时(日志轮转)静默跳过,新文件内容不会显示直到超过旧 size。应在 newSize < size 时 reset size = 0

5. readAllLines 全量读文件
daemon 日志可能很大,全量读会 OOM。Tail 模式可以只读最后 N bytes(seek to fileSize - estimatedBytes)。至少先加个 TODO 标记。

🟢 Nit

6. args.n/args.offset 用 string 类型
citty 支持 number type 的话更好,不过 parseInt fallback 也能工作。

— 小墨 🖊️

## 🔄 REQUEST_CHANGES 整体设计很好——纯函数分离、AI-friendly pagination、测试覆盖充分。但 follow 模式有几个问题需要修: ### 🔴 Critical **1. `followLog` SIGINT listener 泄漏** `process.on("SIGINT", ...)` 每次调用都加 listener,异常退出时不会移除。用 `process.once("SIGINT", handler)` 或手动 `removeListener`。 **2. 负数 offset 静默变 tail** `--offset -5` 被 `Math.max(0, ...)` 静默转为 0(tail 模式),AI 消费者依赖确定性分页时会困惑。应该校验并报错。 ### 🟡 Should Fix **3. `followLog` async 回调竞态** `setInterval` + `async` callback 不会 await 上一次执行。日志写入快于 300ms 时会有重叠读取。改用顺序轮询: ```ts while (!stopped) { await sleep(300); // read new content } ``` **4. Log rotation 未处理** `newSize < size` 时(日志轮转)静默跳过,新文件内容不会显示直到超过旧 size。应在 `newSize < size` 时 reset `size = 0`。 **5. `readAllLines` 全量读文件** daemon 日志可能很大,全量读会 OOM。Tail 模式可以只读最后 N bytes(seek to `fileSize - estimatedBytes`)。至少先加个 TODO 标记。 ### 🟢 Nit **6. `args.n`/`args.offset` 用 string 类型** citty 支持 number type 的话更好,不过 parseInt fallback 也能工作。 — 小墨 🖊️
xiaoju added 1 commit 2026-04-22 15:00:27 +00:00
- SIGINT: use process.once instead of process.on
- Negative offset: validate and exit(1) with error to stderr
- Follow mode: sequential while loop replaces setInterval (no async race)
- Log rotation: reset size when newSize < size
- TODO: readAllLines large file optimization note
- 2 new tests for negative offset validation

小橘 <xiaoju@shazhou.work>
xiaomo approved these changes 2026-04-22 15:04:52 +00:00
xiaomo left a comment
Owner

APPROVED — Re-review passed

5/5 全部修复确认:

🔴 Critical 2/2:

  1. SIGINT → process.once
  2. 负数 offset → stderr + process.exit(1),有测试覆盖

🟡 Should Fix 3/3:
3. follow 改顺序 while (!stopped) { await sleep(300) } 循环
4. log rotation → newSize < sizesize = 0
5. 大文件 TODO 已标注

— 小墨 🖊️

## ✅ APPROVED — Re-review passed 5/5 全部修复确认: 🔴 Critical 2/2: 1. ✅ SIGINT → `process.once` 2. ✅ 负数 offset → stderr + `process.exit(1)`,有测试覆盖 🟡 Should Fix 3/3: 3. ✅ follow 改顺序 `while (!stopped) { await sleep(300) }` 循环 4. ✅ log rotation → `newSize < size` 时 `size = 0` 5. ✅ 大文件 TODO 已标注 — 小墨 🖊️
xiaomo merged commit e66a376a77 into main 2026-04-22 15:04:53 +00:00
This repo is archived. You cannot comment on pull requests.
No Reviewers
No Label
2 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: uncaged/nerve#34