Skip to content

feat(traffic): AOP traffic namespace over an always-on capture hub - #103

Open
M09Ic wants to merge 2 commits into
masterfrom
feat/traffic-namespace
Open

feat(traffic): AOP traffic namespace over an always-on capture hub#103
M09Ic wants to merge 2 commits into
masterfrom
feat/traffic-namespace

Conversation

@M09Ic

@M09Ic M09Ic commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

这个 PR 做了什么

把 proxy hub 变成所有工具的统一出口,并把「抓包」从启动期开关变成控制面操作。

aop/traffic 承载入站的 Configure(routing + capture)和出站的 State/Flow,于是宿主可以按任务打开录制、流式拿到 hub 看见的每一次交换、并在线切换出口链路——这些在此之前都必须重启 runner 才能改。

归属改为按连接身份,而不是时间窗口。调用方把 tool-call id 注入为代理用户名,ConnContext 记住它,该连接上的每条 flow 都带上这个戳。并发执行不再像游标快照那样互相串。

必须先修的一处缺陷

Dispatch 传给每个 namespace handler 的 SendFunc 是一个丢弃入参的空实现。

内建 namespace 都在闭包里捕获连接自己的 sender、忽略这个参数,所以它一直没被发现;但 ExtraNamespaces 注册的 handler 没有那层闭包,只能通过它回话。结果是:runner 接受 Configure、真的打开了抓包,然后把它产生的每一条 StateFlow 静默丢掉——从控制面看,这和「目标很安静」完全无法区分。

TestExtraNamespaceRepliesReachTheWire 钉住了这条路径。我验证过它确实能抓到这个 bug:把 reply 换回丢弃实现即 FAIL,修复后 PASS。

同分支内的其它改动

这棵工作树上还有几条并行的工作线,一并包含在内:CI 与 release workflow 更新、tmux/前台命令改动、skills 与 docs 编辑,以及 archtest/internal/repositorytest/ 的移动。审阅时可以按目录拆开看。

验证

  • go build:主模块(pkg/tools/core/agent/cmd/internal)与 aop 子模块均通过
  • go test ./pkg/node/ ./tools/proxy/:通过

未包含工作树里的运行产物(app.js/index.js 两个 1.8MB 打包文件、evidence_*.txtport*.jsonprocs.*findings/tmp_t3/login.json 等)。

🤖 Generated with Claude Code

M09Ic and others added 2 commits August 18, 2026 04:22
The proxy hub becomes the single egress every tool routes through, and its
capture becomes a control-plane operation rather than a boot flag. aop/traffic
carries Configure (routing + capture) inbound and State/Flow outbound, so a host
can turn recording on for a task, stream what the hub sees, and steer the egress
chain live — none of which was reachable before without restarting the runner.

Attribution is by connection identity, not by a time window. A caller injects
the tool-call id as the proxy username; ConnContext carries it, and every flow
on that connection is stamped with it. Concurrent executions no longer overlap
the way a cursor snapshot let them.

The reply path is the part that had to be fixed to make any of this work:
Dispatch handed every namespace handler a SendFunc that discarded what it was
given. The built-in namespaces close over the connection's sender and ignore
that argument, so it went unnoticed — but an ExtraNamespaces handler has no such
closure and could only answer through it. A runner would accept Configure,
enable capture, and silently drop every State and Flow it produced, which from
the control plane is indistinguishable from a quiet target.
TestExtraNamespaceRepliesReachTheWire pins it open.

Also in this branch, from adjacent work on the same tree: CI and release
workflow updates, tmux/foreground command changes, skills and docs edits, and
the archtest → internal/repositorytest move.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two directives only worked because of where this repository happens to sit on
disk. `require aop v0.0.0` was a placeholder that nothing but the in-repo
replace could satisfy, so no external consumer could resolve the submodule at
all; it now names the published pseudo-version, and the in-repo replace stays
because consumers ignore it and it keeps local development building against the
tree rather than the proxy.

The mitmproxy replace pointed at ../utils/mitmproxy — a path outside the
repository, satisfiable by no checkout but this one. The fork patch it existed
for is published now, so the requirement names it directly and the replace is
gone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant