Skip to content

[codex] add nali ip annotation mode#167

Merged
tsosunchia merged 7 commits intomainfrom
codex/nali-mode
Apr 19, 2026
Merged

[codex] add nali ip annotation mode#167
tsosunchia merged 7 commits intomainfrom
codex/nali-mode

Conversation

@tsosunchia
Copy link
Copy Markdown
Member

@tsosunchia tsosunchia commented Apr 19, 2026

Summary

  • add full-build-only --nali mode for annotating IPv4/IPv6 literals in text streams
  • reuse existing NextTrace GeoIP providers, DoT handling, DN42 mode, and local IP filters
  • document the feature and credit zu1k/nali without copying nali source, regexes, databases, or path/update logic

Behavior

  • nexttrace --nali 1.1.1.1 annotates one line and exits
  • stdin is processed line-by-line, preserving newlines and stopping on quit/exit
  • nexttrace-tiny and ntr do not register --nali
  • --json and traceroute/MTR/MTU/Web/probe/source output flags conflict with --nali

Validation

  • go test ./...
  • go test -tags flavor_tiny ./cmd
  • go test -tags flavor_ntr ./cmd
  • go build ./...
  • go build -tags flavor_tiny ./...
  • go build -tags flavor_ntr ./...
  • printf 'A 1.1.1.1\\n' | /tmp/nexttrace-nali --nali --data-provider disable-geoip\n- /tmp/nexttrace-nali --nali --data-provider IPInfo --language en --timeout 3000 1.1.1.1\n- /tmp/nexttrace-tiny-nali --help and /tmp/ntr-nali --help checked for absence of --nali\n\n## Copyright\nNo nali source files, regex implementations, databases, config paths, or update logic were copied. The README credits zu1k/nali and links to its MIT license because this mode is feature-inspired by nali.

Summary by CodeRabbit

  • 新功能
    • 添加顶层 CLI 选项 --nali 与对应“文本 IP 标注”功能(仅完整版 nexttrace 可用),并新增内部 nali 注释实现以在文本中为 IPv4/IPv6 字面量追加地理/提供者标注。
  • 文档
    • 更新中/英文 README、使用说明与特性对比矩阵,加入 --nali 说明、示例与可用性约束。
  • 测试
    • 增加覆盖 --nali 注册、参数兼容性、运行时行为与注释输出的单元/集成测试。

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 19, 2026

Warning

Rate limit exceeded

@tsosunchia has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 40 minutes and 54 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 40 minutes and 54 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 11b8acaf-fc15-491a-898b-1de1bbb3e721

📥 Commits

Reviewing files that changed from the base of the PR and between f4f8f82 and 8453afb.

📒 Files selected for processing (2)
  • internal/nali/nali.go
  • internal/nali/nali_test.go

Walkthrough

新增 Nali 模式:通过 --nali CLI 标志启用,对输入文本流或单个目标中的 IPv4/IPv6 字面量执行地理/提供商标注,包含标志注册、参数验证、运行时查找与标注引擎实现,并以构建风格特性开关控制可用性(full/tiny/ntr)。

Changes

Cohort / File(s) Summary
文档与帮助
README.md, README_zh_CN.md
新增 --nali 使用说明、示例、行为约束与功能矩阵,更新 Usage/Arguments 同步,说明仅完整版 nexttrace 注册该选项。
构建风格开关
cmd/flavor_full.go, cmd/flavor_tiny.go, cmd/flavor_ntr.go
新增 enableNali 常量:完整版为 truetinyntrfalse,将 Nali 功能纳入构建选择集。
命令分发与集成
cmd/cmd.go
Execute() 中新增 Nali 分支:处理 --nali(强制 color/version 行为)、校验参数并调用 runNaliMode,成功后提前返回以绕过主流程。
CLI Nali 模式实现
cmd/nali_mode.go
新增 Nali 模式实现:按可用性注册标志,定义选项/运行时结构,提供 validateNaliModeOptions(广泛排除不兼容标志)、buildNaliModeOptionsrunNaliMode(GeoDNS/Leo ws 初始化、family 选择并调用 nali.Run)。
Nali 引擎(实现)
internal/nali/nali.go
新增文本 IP 标注包:IP 检测(FindIPSpans)、行级注入(AnnotateLine)、格式化(FormatGeo)、缓存、外部/内置 geo 查询、Run/Annotator 构造与取消支持;导出 Family 常量与核心接口。
测试
cmd/cmd_test.go, cmd/nali_mode_test.go, internal/nali/nali_test.go
更新/新增测试:调整 help 测试条件,新增 Nali 模式注册/验证/构建及运行时行为测试,覆盖家族过滤、格式化、缓存与 stdin/target 行为与取消路径。

Sequence Diagram(s)

sequenceDiagram
    participant User as 用户
    participant CLI as CLI 解析 / 分发<br/>(cmd/cmd.go)
    participant Nali as Nali 控制器<br/>(cmd/nali_mode.go)
    participant Annot as 标注引擎<br/>(internal/nali)
    participant Geo as 地理信息源 / Leo/ws / IPGeo

    User->>CLI: 运行 nexttrace --nali [选项] [目标]
    CLI->>CLI: 识别 --nali 标志
    alt enableNali 为 true
        CLI->>Nali: 调用 runNaliMode(...)
        Nali->>Nali: validateNaliModeOptions(...)
        Nali->>Nali: 初始化 GeoDNS / Leo websocket
        alt 有目标参数
            Nali->>Annot: Run(ctx, cfg, stdin, stdout, target)
        else 无目标参数
            Nali->>Annot: Run(ctx, cfg, stdin, stdout, "")
        end
        loop 每行或每个目标
            Annot->>Annot: FindIPSpans / 过滤 family
            loop 每个检测到的 IP
                Annot->>Geo: 查询 IP 地理/提供商(带超时)
                Geo-->>Annot: 返回 IPGeoData
                Annot->>Annot: FormatGeo -> 在文本中插入 " [label]"
            end
            Annot-->>User: 输出已标注的行
        end
    else
        CLI->>CLI: 继续默认追踪流程
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 分钟

Poem

🐰 轻跃草丛细数行,
IP 星点逐字明,
Nali 画框添出处,
小兔微笑记入名,
一行接一行,标注成景。

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题清晰准确地概括了主要变更:添加 nali IP 文本标注功能模式。标题简洁明了,能让团队成员快速理解核心改动。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/nali-mode

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@tsosunchia tsosunchia marked this pull request as ready for review April 19, 2026 02:25
Copilot AI review requested due to automatic review settings April 19, 2026 02:25
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new full-build-only --nali mode to NextTrace to annotate IPv4/IPv6 literals in text (single target argument or stdin stream), reusing existing GeoIP providers and related runtime setup, and documents the feature in both English and Chinese READMEs.

Changes:

  • Introduce internal/nali annotator (IP span detection, Geo formatting, streaming runner) plus unit tests.
  • Add CLI integration for --nali in the full flavor only, including option conflict validation and cmd-level tests.
  • Update README feature matrices and usage docs to include --nali.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
internal/nali/nali.go Core IP-literal scanning + annotation logic and streaming runner (Run).
internal/nali/nali_test.go Unit tests for span detection, geo formatting, caching, and stdin/target behavior.
cmd/nali_mode.go Registers --nali, validates conflicts, and wires mode execution to internal/nali.
cmd/nali_mode_test.go Tests for flag availability by flavor, parser behavior, conflict validation, and mode execution.
cmd/flavor_full.go Enables --nali in the full build.
cmd/flavor_tiny.go Explicitly disables --nali in tiny build.
cmd/flavor_ntr.go Explicitly disables --nali in ntr build.
cmd/cmd.go Hooks --nali into main Execute flow and routes to runNaliMode.
cmd/cmd_test.go Adjusts help/output-flag tests for the ntr flavor behavior.
README.md Documents --nali feature and updates the feature matrix + usage snippet.
README_zh_CN.md Same documentation updates as README.md (Chinese).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/nali/nali.go
Comment on lines +41 to +45
type Annotator struct {
cfg Config
cache map[string]string
}

Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Annotator caches every looked-up IP label for the lifetime of the process, but the cache map is unbounded. When annotating large streams/logs with many unique IPs this can grow without limit and increase memory usage. Consider bounding the cache (size cap + eviction), or at least providing a way to disable caching / periodically clear it in streaming mode.

Copilot uses AI. Check for mistakes.
Comment thread internal/nali/nali.go Outdated
Comment on lines +349 to +350
if strings.HasPrefix(strings.ToUpper(asn), "AS") {
return asn
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normalizeASN returns the original string unchanged when it already starts with "AS" (case-insensitive). This can lead to inconsistent formatting (e.g., "as15169" stays lowercase, and inputs like "AS 15169" keep the space). There is already a normalizeASN implementation in internal/speedtest/runner that strips any existing prefix and re-adds a canonical "AS"; mirroring that logic here would keep output consistent across the project.

Suggested change
if strings.HasPrefix(strings.ToUpper(asn), "AS") {
return asn
asn = strings.TrimSpace(asn)
if len(asn) >= 2 && strings.EqualFold(asn[:2], "AS") {
asn = strings.TrimSpace(asn[2:])

Copilot uses AI. Check for mistakes.
Comment thread internal/nali/nali.go
Comment on lines +187 to +189
func isIPStart(b byte) bool {
return isHexByte(b) || b == ':'
}
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FindIPSpans currently treats any hex letter (a-f/A-F) as a potential IP start (isIPStart uses isHexByte), which means many ordinary words will trigger netip.ParseAddr attempts. In text-stream mode this can add significant overhead on non-IP-heavy input. Consider adding a cheap pre-check before ParseAddr (e.g., require the candidate to contain '.' or ':'; and for hex-letter starts require at least one ':'), or tighten isIPStart to reduce false positives while still matching IPv6 like "fe80::1".

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
cmd/nali_mode_test.go (1)

59-63: 按仓库规则避免新增匿名 struct 表项。

这里用匿名 struct 定义测试用例 shape;如果要严格遵循当前仓库规则,请改为项目约定的 interface{}/共享接口形式,或为测试文件明确豁免该规则。

As per coding guidelines, **/*.{ts,tsx,go}: Use interface{} for defining object shapes instead of struct types in TypeScript/Go code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/nali_mode_test.go` around lines 59 - 63, The test slice currently uses an
anonymous struct (tests := []struct{ name string; opts naliModeOptions; want
string }) which violates the repo rule; replace it with a slice of interface{}
(tests := []interface{}{}) where each case is a map[string]interface{} with keys
"name", "opts", and "want", and update the test loop to type-assert each entry
(e.g., m := tc.(map[string]interface{}); name := m["name"].(string); opts :=
m["opts"].(naliModeOptions); want := m["want"].(string)) so you avoid anonymous
struct literals while keeping the same values and using the existing
naliModeOptions type and the tests identifier.
internal/nali/nali.go (1)

41-54: 提醒:Annotator.cache 未加锁,不支持并发调用 AnnotateLine

Annotator 是一个导出类型,AnnotateLine/lookupLabel 会在同一个 map[string]string 上进行读/写。当前通过 Run 的单协程循环调用没有问题,但既然 New/Annotator/AnnotateLine 都是包外 API,一旦未来有并发使用场景(比如批量注解多条流)就会触发 data race。

建议二选一:

  • 在 doc comment 中显式声明"not safe for concurrent use";
  • 或给 cache 加一把 sync.RWMutex(查询走读锁,miss 后升级写锁),让类型本身并发安全。
♻️ 建议的并发安全修改
 type Annotator struct {
 	cfg   Config
+	mu    sync.RWMutex
 	cache map[string]string
 }
@@
 func (a *Annotator) lookupLabel(ctx context.Context, ip string) string {
 	if ip == "" {
 		return ""
 	}
-	if label, ok := a.cache[ip]; ok {
+	a.mu.RLock()
+	label, ok := a.cache[ip]
+	a.mu.RUnlock()
+	if ok {
 		return label
 	}
 
-	label := ""
+	label = ""
 	if geo, ok := ipgeo.Filter(ip); ok {
 		label = FormatGeo(geo, a.cfg.Lang)
 	} else if a.cfg.Source != nil && ctx.Err() == nil {
 		if geo, err := a.cfg.Source(ip, a.cfg.Timeout, a.cfg.Lang, false); err == nil {
 			label = FormatGeo(geo, a.cfg.Lang)
 		}
 	}
-	a.cache[ip] = label
+	a.mu.Lock()
+	a.cache[ip] = label
+	a.mu.Unlock()
 	return label
 }

需同步 import "sync"

Also applies to: 139-157

cmd/nali_mode.go (2)

132-187: 建议:buildNaliModeOptions 参数过多,考虑用选项聚合结构体传参。

当前 buildNaliModeOptions 以位置参数形式接收近 20 个值(包含混合类型 bool/string/int/effectiveMTRModes),调用方很容易把顺序写错,编译器也无法帮助发现。可以把相关的源字段(outputPathfromlistenfilesrcAddrsrcPortsrcDev、各布尔 flag 与 mtrModes)打包到一个已有的/新的"CLI 原始参数"结构里,或者让 validateNaliModeOptions 直接在 Execute() 里基于已经解析好的字段做检查,避免在此处重复展开。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/nali_mode.go` around lines 132 - 187, The buildNaliModeOptions function
currently accepts ~20 positional params which is error-prone; refactor it to
take a single options struct (e.g., CLIArgs or RawCLIOptions) that aggregates
fields like outputPath, from, listen, file, srcAddr, srcPort, srcDev, the
boolean flags, and mtrModes; update the call sites to construct and pass that
struct (or pass the parser plus the struct) and move any validation logic into
validateNaliModeOptions or into Execute() to operate on the aggregated struct,
keeping buildNaliModeOptions signatures and internal mapping
(icmpMode/port/queries/.../sourceDevice) unchanged except reading from the new
struct.

27-78: 编码规范提醒:Go 文件应使用 interface{} 而非 struct 定义对象形状。

新增的 naliModeOptions / naliRunOptions 采用 struct 定义。若严格依据项目规范,这属于违规;不过这条规范对 Go 而言并不符合惯用风格,是否需要实际调整请与维护者确认后再定。

As per coding guidelines: "Use interface{} for defining object shapes instead of struct types in TypeScript/Go code".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/nali_mode.go` around lines 27 - 78, The new concrete structs
naliModeOptions and naliRunOptions violate the stated project guideline to use
interface{}-shaped types; confirm with the maintainers and, if the guideline
must be applied, replace those struct type definitions (naliModeOptions,
naliRunOptions) with interface{}-based types (e.g., type naliModeOptions
interface{} and type naliRunOptions interface{}) and update all call
sites/constructors to supply map[string]interface{} or appropriate concrete
maps/values that satisfy the interface{} shape so consumers expect a generic
object rather than concrete struct fields.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/nali_mode_test.go`:
- Around line 3-8: Tests use testing.T.Context() which requires Go 1.24; replace
its usage with context.Background() to retain Go 1.22+ compatibility: add
"context" to the import block and change any call sites that pass t.Context()
(in the test functions in cmd/nali_mode_test.go) to use context.Background()
instead.

In `@internal/nali/nali.go`:
- Around line 222-253: Add a regression test that asserts how
parseCandidate/splitIPv4Port/parseAddr handle the IPv4-mapped-IPv6-with-port
case "::ffff:1.2.3.4:53" (e.g. in the same table as
TestAnnotateLineBracketPortCIDRZoneAndPunctuation); specifically encode the
expected behavior (currently the token is not parsed as host:port and is
dropped) so future refactors have a clear contract — add a test case comparing
input "::ffff:1.2.3.4:53" to the expected output (dropped/unchanged as per
existing behavior) and reference parseCandidate, splitIPv4Port, and parseAddr in
the test comment.

---

Nitpick comments:
In `@cmd/nali_mode_test.go`:
- Around line 59-63: The test slice currently uses an anonymous struct (tests :=
[]struct{ name string; opts naliModeOptions; want string }) which violates the
repo rule; replace it with a slice of interface{} (tests := []interface{}{})
where each case is a map[string]interface{} with keys "name", "opts", and
"want", and update the test loop to type-assert each entry (e.g., m :=
tc.(map[string]interface{}); name := m["name"].(string); opts :=
m["opts"].(naliModeOptions); want := m["want"].(string)) so you avoid anonymous
struct literals while keeping the same values and using the existing
naliModeOptions type and the tests identifier.

In `@cmd/nali_mode.go`:
- Around line 132-187: The buildNaliModeOptions function currently accepts ~20
positional params which is error-prone; refactor it to take a single options
struct (e.g., CLIArgs or RawCLIOptions) that aggregates fields like outputPath,
from, listen, file, srcAddr, srcPort, srcDev, the boolean flags, and mtrModes;
update the call sites to construct and pass that struct (or pass the parser plus
the struct) and move any validation logic into validateNaliModeOptions or into
Execute() to operate on the aggregated struct, keeping buildNaliModeOptions
signatures and internal mapping (icmpMode/port/queries/.../sourceDevice)
unchanged except reading from the new struct.
- Around line 27-78: The new concrete structs naliModeOptions and naliRunOptions
violate the stated project guideline to use interface{}-shaped types; confirm
with the maintainers and, if the guideline must be applied, replace those struct
type definitions (naliModeOptions, naliRunOptions) with interface{}-based types
(e.g., type naliModeOptions interface{} and type naliRunOptions interface{}) and
update all call sites/constructors to supply map[string]interface{} or
appropriate concrete maps/values that satisfy the interface{} shape so consumers
expect a generic object rather than concrete struct fields.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 12a8acd4-fdcc-45a7-a03b-f45866dc6a85

📥 Commits

Reviewing files that changed from the base of the PR and between 6dc90ef and 0f85a28.

📒 Files selected for processing (11)
  • README.md
  • README_zh_CN.md
  • cmd/cmd.go
  • cmd/cmd_test.go
  • cmd/flavor_full.go
  • cmd/flavor_ntr.go
  • cmd/flavor_tiny.go
  • cmd/nali_mode.go
  • cmd/nali_mode_test.go
  • internal/nali/nali.go
  • internal/nali/nali_test.go

Comment thread cmd/nali_mode_test.go
Comment thread internal/nali/nali.go Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0f85a28200

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cmd/nali_mode.go Outdated
Comment on lines +180 to +182
packetInterval: parsedFlag(parser, "send-time"),
packetSize: parsedFlag(parser, "psize"),
tos: parsedFlag(parser, "tos"),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject explicit --ttl-time in nali mode

--nali is documented to conflict with probe/traceroute tuning flags, but this option builder never records whether --ttl-time/-i was explicitly provided. In practice nexttrace --nali -i 500 ... is accepted and -i is silently ignored, which can hide misconfigured automation and produce unexpected behavior. Please track ttl-time as an explicit conflict so validateNaliModeOptions fails fast.

Useful? React with 👍 / 👎.

@tsosunchia tsosunchia requested a review from Copilot April 19, 2026 08:51
@tsosunchia
Copy link
Copy Markdown
Member Author

@codex review

@tsosunchia
Copy link
Copy Markdown
Member Author

@coderabbitai review ,已针对review进行了修改

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/nali/nali.go Outdated
Comment on lines +179 to +184
if len(a.cacheOrder) >= maxCacheEntries {
oldest := a.cacheOrder[0]
delete(a.cache, oldest)
copy(a.cacheOrder, a.cacheOrder[1:])
a.cacheOrder = a.cacheOrder[:len(a.cacheOrder)-1]
}
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cache eviction shifts the entire cacheOrder slice on every insert once maxCacheEntries is reached (copy(a.cacheOrder, a.cacheOrder[1:])). For large streams with mostly-unique IPs this becomes O(maxCacheEntries) work per new IP and can significantly slow --nali mode. Consider replacing cacheOrder with a ring buffer (maintaining an eviction index) or a small LRU/list implementation to make eviction O(1).

Copilot uses AI. Check for mistakes.
Comment thread cmd/nali_mode.go
Comment on lines +28 to +64
ipv4Only bool
ipv6Only bool
tcp bool
udp bool
mtu bool
mtr bool
raw bool
table bool
classic bool
json bool
output bool
outputDefault bool
routePath bool
maptraceFlag bool
from bool
deploy bool
listen bool
fastTrace bool
file bool
disableMPLS bool
noRDNS bool
alwaysRDNS bool
init bool
icmpMode bool
port bool
queries bool
maxAttempts bool
parallelRequests bool
maxHops bool
beginHop bool
packetInterval bool
ttlInterval bool
packetSize bool
tos bool
source bool
sourcePort bool
sourceDevice bool
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naliModeOptions.maptraceFlag is populated from disableMaptrace (the -M/--map flag that disables trace-map printing). The current field name reads like it represents enabling maptrace, which makes the option builder and conflict list harder to reason about. Renaming this field (and the corresponding input name) to something like disableMaptrace/disableMaptraceFlag would better reflect the actual semantics.

Suggested change
ipv4Only bool
ipv6Only bool
tcp bool
udp bool
mtu bool
mtr bool
raw bool
table bool
classic bool
json bool
output bool
outputDefault bool
routePath bool
maptraceFlag bool
from bool
deploy bool
listen bool
fastTrace bool
file bool
disableMPLS bool
noRDNS bool
alwaysRDNS bool
init bool
icmpMode bool
port bool
queries bool
maxAttempts bool
parallelRequests bool
maxHops bool
beginHop bool
packetInterval bool
ttlInterval bool
packetSize bool
tos bool
source bool
sourcePort bool
sourceDevice bool
ipv4Only bool
ipv6Only bool
tcp bool
udp bool
mtu bool
mtr bool
raw bool
table bool
classic bool
json bool
output bool
outputDefault bool
routePath bool
disableMaptraceFlag bool
from bool
deploy bool
listen bool
fastTrace bool
file bool
disableMPLS bool
noRDNS bool
alwaysRDNS bool
init bool
icmpMode bool
port bool
queries bool
maxAttempts bool
parallelRequests bool
maxHops bool
beginHop bool
packetInterval bool
ttlInterval bool
packetSize bool
tos bool
source bool
sourcePort bool
sourceDevice bool

Copilot uses AI. Check for mistakes.
Comment thread cmd/nali_mode.go
Comment on lines +128 to +131
{"--output-default", opts.outputDefault},
{"--route-path", opts.routePath},
{"--map", opts.maptraceFlag},
{"--from", opts.from},
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateNaliModeOptions currently treats --map (which in this CLI is the disable trace map output flag) as a hard conflict for --nali. Since --nali mode doesn't produce trace-map output at all, rejecting --map seems unnecessary and diverges from the documented list of --nali conflicts in the PR description. Consider allowing --map (ignore it in --nali mode) or update the documented behavior if this is intentionally disallowed.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f92c4d4965

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/nali/nali.go
return spans
}

func isIPStart(b byte) bool {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enforce token boundaries before parsing IP candidates

isIPStart treats any hex byte as a valid start, so FindIPSpans can begin in the middle of words and mis-parse common key:value text. For example, src:2001:db8::1 is scanned from the trailing c in src and interpreted as c:2001:db8::1, which produces incorrect annotations (often [INVALID]) or misses the actual IP entirely. This breaks --nali accuracy on typical log formats unless a left-boundary delimiter check is added before starting a candidate.

Useful? React with 👍 / 👎.

Comment thread cmd/nali_mode.go Outdated
packetSize: parsedFlag(input.parser, "psize"),
tos: parsedFlag(input.parser, "tos"),
source: strings.TrimSpace(input.srcAddr) != "",
sourcePort: input.srcPort != 0,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Detect explicit --source-port 0 as a nali conflict

Conflict detection for --source-port is based on input.srcPort != 0, so an explicitly provided --source-port 0 bypasses validation and --nali runs instead of rejecting an unsupported flag combination. Since validateNaliModeOptions declares --source-port incompatible with --nali, this should use parsed-state detection (like other probe flags) rather than value-based detection.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/cmd.go`:
- Around line 1184-1189: The current error handling after calling runNaliMode
treats context.Canceled as suppressed but still does os.Exit(1), causing
SIGINT/SIGTERM exits to appear as failures; change the branch so that if
errors.Is(err, context.Canceled) you return (or otherwise allow Execute to
return normally) instead of calling os.Exit(1) or printing the error, matching
how runTraceOnce/Execute handle cancellations and yielding exit code 0 for user
interrupts. Locate the block handling the error from runNaliMode and adjust it
to early-return on context.Canceled while preserving the existing behavior for
other errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 629dfb49-be70-4f9a-b673-c59308406927

📥 Commits

Reviewing files that changed from the base of the PR and between 0f85a28 and 2a32a17.

📒 Files selected for processing (5)
  • cmd/cmd.go
  • cmd/nali_mode.go
  • cmd/nali_mode_test.go
  • internal/nali/nali.go
  • internal/nali/nali_test.go
✅ Files skipped from review due to trivial changes (2)
  • internal/nali/nali_test.go
  • internal/nali/nali.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • cmd/nali_mode_test.go
  • cmd/nali_mode.go

Comment thread cmd/cmd.go
@tsosunchia tsosunchia requested a review from Copilot April 19, 2026 09:20
@tsosunchia
Copy link
Copy Markdown
Member Author

tsosunchia commented Apr 19, 2026

@coderabbitai help

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 19, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@tsosunchia
Copy link
Copy Markdown
Member Author

@codex review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 19, 2026

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

CodeRabbit commands

These commands are invoked using PR/Issue comments.

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai evaluate custom pre-merge check --instructions <custom-checks-instructions> --name <custom-checks-title> [--mode <error|warning>] to validate the custom pre-merge checks instructions. Defaults to error when --mode is omitted.
  • @coderabbitai ignore pre-merge checks to override pre-merge checks and get an approval on PR.
  • @coderabbitai run pre-merge checks to run pre-merge checks on the pull request.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve merge conflict to automatically resolve merge conflicts.
  • @coderabbitai autofix to automatically fix issues identified in unresolved review comments.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai generate configuration to create a PR that adds the current resolved configuration as .coderabbit.yaml (or show it if already present).
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit configuration file (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, support, documentation and community

  • Visit our status page to check the current availability of CodeRabbit.
  • Create a ticket on our support page for assistance with any issues or questions.
  • Visit our documentation site for detailed information on how to use CodeRabbit.
  • Join our Discord community to connect with other users and get help from the community.
  • Follow us on X/Twitter for updates and announcements.

@tsosunchia
Copy link
Copy Markdown
Member Author

@coderabbitai run pre-merge checks

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 19, 2026

✅ Actions performed

Running Pre-merge checks. Results will be posted in the summary comment once complete.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread cmd/nali_mode.go
Comment on lines +108 to +152
func validateNaliModeOptions(opts naliModeOptions) error {
if opts.json {
return fmt.Errorf("--nali 不支持 --json")
}
if opts.ipv4Only && opts.ipv6Only {
return fmt.Errorf("-4/--ipv4 不能与 -6/--ipv6 同时使用")
}
for _, conflict := range []struct {
name string
enabled bool
}{
{"--mtu", opts.mtu},
{"--mtr/-r/--report/-w/--wide", opts.mtr},
{"--raw", opts.raw},
{"--table", opts.table},
{"--classic", opts.classic},
{"--output", opts.output},
{"--output-default", opts.outputDefault},
{"--route-path", opts.routePath},
{"--from", opts.from},
{"--deploy", opts.deploy},
{"--listen", opts.listen},
{"--fast-trace", opts.fastTrace},
{"--file", opts.file},
{"--tcp", opts.tcp},
{"--udp", opts.udp},
{"--port", opts.port},
{"--icmp-mode", opts.icmpMode},
{"--queries", opts.queries},
{"--max-attempts", opts.maxAttempts},
{"--parallel-requests", opts.parallelRequests},
{"--max-hops", opts.maxHops},
{"--first", opts.beginHop},
{"--send-time", opts.packetInterval},
{"--ttl-time", opts.ttlInterval},
{"--psize", opts.packetSize},
{"--tos", opts.tos},
{"--source", opts.source},
{"--source-port", opts.sourcePort},
{"--dev", opts.sourceDevice},
{"--disable-mpls", opts.disableMPLS},
{"--no-rdns", opts.noRDNS},
{"--always-rdns", opts.alwaysRDNS},
{"--init", opts.init},
} {
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateNaliModeOptions doesn't reject some CLI flags that are still registered in the full build but are ignored in --nali mode (e.g. --map/-M, --show-ips, and --ipinfo). This means users can pass them with --nali and get silently ignored behavior, which conflicts with the documented “conflict with traceroute/MTR flags” behavior. Consider extending naliModeOptions/buildNaliModeOptions to detect these flags (via parsedFlag or passed pointers) and add them to the conflict list so they error out consistently.

Copilot uses AI. Check for mistakes.
Comment thread internal/nali/nali.go Outdated
Comment on lines +154 to +161
if geo, ok := ipgeo.Filter(ip); ok {
label = FormatGeo(geo, a.cfg.Lang)
} else if a.cfg.Source != nil && ctx.Err() == nil {
if geo, err := a.cfg.Source(ip, a.cfg.Timeout, a.cfg.Lang, false); err == nil {
label = FormatGeo(geo, a.cfg.Lang)
}
}
a.storeLabel(ip, label)
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lookupLabel caches empty labels even when the GeoIP source returns an error. A transient lookup failure will therefore permanently suppress annotation for that IP for the lifetime of the process, because the empty string is treated as a cache hit. Consider only caching non-empty labels, or distinguishing error/negative-cache cases (e.g., skip storeLabel when Source returns a non-nil error, while still caching successful results and ipgeo.Filter hits).

Suggested change
if geo, ok := ipgeo.Filter(ip); ok {
label = FormatGeo(geo, a.cfg.Lang)
} else if a.cfg.Source != nil && ctx.Err() == nil {
if geo, err := a.cfg.Source(ip, a.cfg.Timeout, a.cfg.Lang, false); err == nil {
label = FormatGeo(geo, a.cfg.Lang)
}
}
a.storeLabel(ip, label)
shouldCache := false
if geo, ok := ipgeo.Filter(ip); ok {
label = FormatGeo(geo, a.cfg.Lang)
shouldCache = true
} else if a.cfg.Source != nil && ctx.Err() == nil {
if geo, err := a.cfg.Source(ip, a.cfg.Timeout, a.cfg.Lang, false); err == nil {
label = FormatGeo(geo, a.cfg.Lang)
shouldCache = true
}
}
if shouldCache {
a.storeLabel(ip, label)
}

Copilot uses AI. Check for mistakes.
Comment thread internal/nali/nali.go
Comment on lines +34 to +42
type Span struct {
Start int
End int
InsertEnd int
ScanEnd int
Text string
LookupIP string
Family Family
}
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Span.ScanEnd is stored in parseAddr but is not used anywhere else in this package. Keeping unused fields increases surface area and makes the code harder to reason about. Consider removing it (and the corresponding parameter plumb-through) unless it’s needed for an imminent follow-up.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e6a937ebbf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/nali/nali.go
if err := ctx.Err(); err != nil {
return err
}
line, err := reader.ReadString('\n')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Make nali stdin loop cancellable while waiting for input

In Run, the loop checks ctx.Err() before calling ReadString, but ReadString('\n') can block indefinitely on stdin and does not observe context cancellation. In nexttrace --nali interactive use (no immediate newline from stdin), pressing Ctrl-C cancels the context yet the process remains stuck waiting for input, so the mode cannot exit promptly on signal. This should be changed so the read path can be interrupted when the context is canceled.

Useful? React with 👍 / 👎.

@tsosunchia tsosunchia requested a review from Copilot April 19, 2026 09:46
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/nali/nali.go Outdated
Comment on lines +113 to +129
func readLines(ctx context.Context, input io.Reader) <-chan lineReadResult {
results := make(chan lineReadResult, 1)
go func() {
defer close(results)
reader := bufio.NewReader(input)
for {
line, err := reader.ReadString('\n')
select {
case results <- lineReadResult{line: line, err: err}:
case <-ctx.Done():
return
}
if err != nil {
return
}
}
}()
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

readLines runs a goroutine that blocks on reader.ReadString('\n') and cannot be interrupted by ctx cancellation. When Run returns early (e.g., user types quit/exit or ctx is canceled), the goroutine can remain blocked indefinitely on readers that are not closed, leaking a goroutine.

Consider avoiding the extra goroutine and accepting that reads are blocking, or (if you want cancellation to work) detect io.ReadCloser and close it on exit/cancel, or pass a closer/stop hook into Run so the read can be unblocked deterministically.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/nali/nali.go`:
- Around line 263-266: The parse loop currently sets i = end when
parseCandidate(line[i:end], i) fails, which skips the rest of the candidate and
can miss literals like "dead:8.8.8.8"; change the failure path in the loop
around parseCandidate so it advances i by at least 1 byte (e.g., i++ or i = i+1)
instead of i = end to allow the scanner to resync on the separator and reattempt
matching, and add a regression test that feeds input like "dead:8.8.8.8" and
asserts the IP literal is detected; update the code paths referencing
parseCandidate, i and end accordingly.
- Around line 27-49: The three newly added concrete structs (Config, Span,
Annotator) should follow the repository convention of using interface-based
object shapes: replace type Config struct{...}, type Span struct{...}, and type
Annotator struct{...} with interface types (e.g., type Config interface {
Timeout() time.Duration; Source() ipgeo.Source; Lang() string; Family() Family }
and similar getter methods for Span and Annotator) and implement those
interfaces in a private concrete type (e.g., configImpl, spanImpl,
annotatorImpl); update all call sites to use the interface methods instead of
direct field access (or add the repo guideline exception to documentation if
changing to interfaces is not feasible). Ensure unique symbols to touch: Config,
Span, Annotator, and any methods that currently read fields like cfg.Timeout or
span.LookupIP are updated to use the new accessors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fc13bfa6-0d32-4eb0-ab85-ffbb91862624

📥 Commits

Reviewing files that changed from the base of the PR and between 2a32a17 and f4f8f82.

📒 Files selected for processing (11)
  • README.md
  • README_zh_CN.md
  • cmd/cmd.go
  • cmd/cmd_test.go
  • cmd/flavor_full.go
  • cmd/flavor_ntr.go
  • cmd/flavor_tiny.go
  • cmd/nali_mode.go
  • cmd/nali_mode_test.go
  • internal/nali/nali.go
  • internal/nali/nali_test.go
✅ Files skipped from review due to trivial changes (2)
  • cmd/flavor_ntr.go
  • README.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • cmd/flavor_tiny.go
  • cmd/flavor_full.go
  • cmd/nali_mode_test.go
  • cmd/nali_mode.go

Comment thread internal/nali/nali.go
Comment on lines +27 to +49
type Config struct {
Source ipgeo.Source
Timeout time.Duration
Lang string
Family Family
}

type Span struct {
Start int
End int
InsertEnd int
Text string
LookupIP string
Family Family
}

type Annotator struct {
cfg Config
cacheMu sync.RWMutex
cache map[string]string
cacheRing []string
cacheNext int
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

按仓库约定处理新增对象形状类型。

ConfigSpanAnnotator 是本包新增的对象形状,但当前以 struct 定义;如果该规则适用于本包,请改成项目约定的 interface{}/接口抽象,或在规范中补充 Go 例外。As per coding guidelines, **/*.{ts,tsx,go}: Use interface{} for defining object shapes instead of struct types in TypeScript/Go code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/nali/nali.go` around lines 27 - 49, The three newly added concrete
structs (Config, Span, Annotator) should follow the repository convention of
using interface-based object shapes: replace type Config struct{...}, type Span
struct{...}, and type Annotator struct{...} with interface types (e.g., type
Config interface { Timeout() time.Duration; Source() ipgeo.Source; Lang()
string; Family() Family } and similar getter methods for Span and Annotator) and
implement those interfaces in a private concrete type (e.g., configImpl,
spanImpl, annotatorImpl); update all call sites to use the interface methods
instead of direct field access (or add the repo guideline exception to
documentation if changing to interfaces is not feasible). Ensure unique symbols
to touch: Config, Span, Annotator, and any methods that currently read fields
like cfg.Timeout or span.LookupIP are updated to use the new accessors.

Comment thread internal/nali/nali.go Outdated
@tsosunchia tsosunchia merged commit 510c374 into main Apr 19, 2026
46 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants