Skip to content

feat(web): agent 控制台重构 — i18n/主题/探活/slashcmd/配置热重载#56

Open
wuchulonly wants to merge 68 commits into
masterfrom
feat/agent-console-aligned
Open

feat(web): agent 控制台重构 — i18n/主题/探活/slashcmd/配置热重载#56
wuchulonly wants to merge 68 commits into
masterfrom
feat/agent-console-aligned

Conversation

@wuchulonly

Copy link
Copy Markdown
Contributor

概述

Agent 控制台重构分支:前端去 chatbot 味 + i18n + 主题系统,后端新增探活/本地 agent/统一命令目录/配置热重载/结构化评估。共 9 个逻辑提交。

改动分组

提交 内容
chore 移除 cyber-ui submodule,收敛 .gitignore
fix(provider) LLM 协议推断 / model 覆盖(AISCAN_MODEL)/ 能力对齐
feat(probe) pkg/probe 连接与 LLM 主动探活
feat(slashcmd) 统一 slash 命令目录 + TUI 固定盒子渲染
refactor(agent) 评估器结构化断言 / 事件 JSON / 上下文截断
refactor(tools) 扫描采集 / spray / gogo / zombie + 输出精简
feat(web) 后端会话 / SSE / sqlite store / 配置热重载 / webagent
feat(web-ui) 前端重构:i18n / 主题 / viewer / 原子组件
chore(web) 重建内嵌静态资源 web/static

规模

  • 全部:395 文件,+13674 / −4619
  • 手写代码(排除 web/static 构建产物 + lock):183 文件,+12980 / −4033
  • 后端 Go:+4243(其中测试 +1831,占 43%)

备注

  • 本分支为大重构「事后拆分」,中间提交不保证单独可编译;最终 HEAD 完整一致。
  • scratch/临时文件(preview.html 等)已排除,未提交。

🤖 Generated with Claude Code

Nathaniel Leonardjoi and others added 27 commits July 7, 2026 02:58
cyber-ui 已 vendored 进 src/{ui,markdown,viewer,terminal-view,lib/theme},
删除 submodule 引用;整理忽略规则(运营产物、静态构建残留、泄漏配置)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- base_url 空 provider 时按 host 推断 anthropic/openai 协议,避免误走
  openai 协议对 Anthropic-only 网关空体 404
- ANTHROPIC_MODEL 等 provider-env 降级为 fallback-only,新增 AISCAN_MODEL
  自有命名空间覆盖,避免 prod env 静默盖过 web 配置
- endpoint hint + provider 能力对齐,补充 parity/hint 测试

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
新增 pkg/probe(conn/llm)做真实可达性探测:llm_available 只表示
client 建好,不查 404;顶栏 LLMHealth 主动 testLLM 才真正探活。
web 侧 probe 端点 + 回归测试。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 新增 pkg/slashcmd 单一目录,驱动 REPL + web + 菜单;hub 按 Scope 路由;
  /shell 退役改 !bash
- TUI /spaces /nodes /messages 改 renderFixedBox(定宽 + ANSI 裁剪 +
  runewidth CJK 对齐);/status 的 IOA URL 走 redactIOAURL 脱敏
- 补 banner/catalog 渲染回归测试

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- evaluator 结构化断言(criteria→count/exists 确定性 Go + judge 有据判定)
- event_json 评估事件序列化 + provider 热切换测试
- truncate/clip 上下文裁剪调整与测试

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- scan collector/jsonl_writer、spray、gogo、zombie、toolargs 调整
- core/output 颜色/格式精简,移除 tool_data
- headless request、tavily 搜索小改

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- SSE hub 终端事件可靠投递、config 热重载(ReloadProvider 热切换 provider)
- store 迁移到 sqlite(删除内存 store),会话/scan 级联删除、agent 稳定身份
- webagent 上传路径注入 LLM、eval 转发 extractEventData 修复
- slashcmd web 端点、localagent 本地启动;补 config_reload/command/sse/
  eval_forward/upload 回归测试

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 中英 i18n(i18n/locales,MiSans CJK 字体),LanguageToggle/主题系统
- vendored cyber-ui 进 src/{ui,markdown,viewer,terminal-view,lib/theme};
  手搓原子组件收敛(Button/Badge/Callout/Field/StatTile…)
- 聊天页去 chatbot 味:身份归左 rail、AI=蓝、composer 融成单一 well;
  LLMHealth 主动探活、ModelCombobox 模型选择
- 删除独立 scan 页/侧栏/report 视图,scanning 内联进 agent 聊天

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
前端重构后重新构建 web/static(i18n/主题/字体 chunk、MiSans 子集),
更新编译期内嵌的 hash 化资源。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
原子层回归共享库单一真相源:aiscan 贡献的原子已合并进 cyber-ui
(chainreactors/cyber-ui#1),这里改回从子模块消费,删除 vendored 副本。

- 重新引入 web/frontend/cyber-ui 子模块(pin 合并后 6b80eb3)
- vite/tsconfig 恢复 @aspect/ui + @aspect/theme alias → 子模块 packages
- tailwind preset 改指子模块 theme
- 全量改写 import:@/ui→@aspect/ui(16)、@/lib/theme→@aspect/theme(50)
- 删除 vendored src/ui、src/lib/theme(33 文件)
- markdown/viewer/terminal 保持 vendored(aiscan 深度定制的复合组件,
  非原子),仅把其内部引用改指子模块
- ConfirmDialog 已在上游去 i18n 耦合,新增 LocalizedConfirmProvider
  在 main.tsx 注入本地化 labels,保住中文确认框

验证:tsc --noEmit 绿;vite build 全量 2041 模块转换 + emit 成功。
web/static 内嵌产物运行时等价(仅 import 解析路径变化),部署时
npm run build 重生成;本机 web/static/assets 为 root-owned 历史残留未动。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the local replace bridge and pin github.com/chainreactors/sdk to
v0.3.4-0.20260707120839-686d4bfa2b2b (chainreactors/sdk#31, merged), which
populates gogo's pkg.ChainExec when the SDK injects neutron templates. This
fixes the ants "worker exits from panic" nil-pointer that aborted exploit
scanning on every open host.

TestGogoEngineInjectsChainExecutor now passes against the real pinned SDK
(no replace).

Refs #51

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…A1019)

- errcheck: store_sqlite tx.Rollback 两处显式忽略返回值
- nilerr: 上传结果非 JSON 时兜底合并两条重复分支,消除 nil-return(真重构,非 nolint)
- gosec G120: handler 上传先 http.MaxBytesReader 封顶 body,再行级 nolint(这版 gosec sanitizer 列表为空,识别不了缓解)
- misspell: banner_render_test 注释 colour→color
- unused: 删除退役 /shell 遗留的死代码 handleShellCommand
- SA1019+死代码: 端口配置已改走 resource-provider 管道(gogo 自设 utils.PrePort),
  删除冗余且无人读取的 PortPreset / installLocalPortPreset;测试改为断言真正的
  provider 契约 GogoConfig("port")

注:tidy 的 go-runewidth 提为直接依赖已随 64694d7(sdk bump 的 go mod tidy)进入 HEAD。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
删除 64694d7 bump 后不再被引用的旧版 chainreactors/sdk
(v0.3.4-0.20260704194820-4141f24c2bcd)哈希;`go mod tidy` 现已干净,
修复 CI 的 tidy job。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
agent 侧 fenceTerminalOutput 给多行 REPL/shell 输出包 Markdown 代码围栏
(/status /provider /nodes 等盒子画符+列对齐只在定宽保换行下成立);web
聊天按 Markdown 散文渲染会把单换行折成空格+比例字体,面板塌成一行。
前端 MarkdownContent 对含换行的无 info-string fenced block 也判为块级,
避免退化成行内 pill。单行输出仍走散文。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
子模块推进 6b80eb3→4832385(第二刀原子 + terminal 包)。aiscan 接过去:

- 设计系统第二刀收敛:手搓 <button>→@aspect/ui Button(App/SessionList/
  ConfigPanel/ScanProgressInline 等),消费新原子 DisclosureCard/ResultLine/
  Switch;新建 aiscan-local AiPanel(抽「AI 研判」面板签名)、AgentVoiceCard
  (抽「AI 语气」卡壳,viewer 三处共用)
- terminal-view 迁入子模块:删 vendored src/terminal-view(465 行),
  vite/tsconfig 加 @aspect/terminal alias,AgentTerminal/TerminalDetails
  改从 @aspect/terminal 消费

验证:tsc --noEmit 绿。web/static 内嵌产物部署时重建。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cyber-ui 作为源码消费(vite 把 @aspect/* alias 到其 packages),Tailwind
content 必须也扫它,否则仅在子模块内用到的 utility(如 DisclosureCard
的 grid-rows-[0fr]/[1fr] 折叠动画)不会生成、静默失效(展开/折叠不动)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
反映第二刀原子/terminal 迁移(a45e8f5)与 Tailwind cyber-ui 扫描修复,
重新构建 web/static 内嵌产物(hash 化 JS/CSS 更新)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
bump chainreactors/proton 至 471f99e(含预过滤修复):上游 AC 行级
预过滤用非重叠 leftmost-first Find 迭代挑候选模板,长字面量
("begin rsa private key")被其它已加载模板的更短字面量("begin")
遮蔽 → 多密钥文件里 156 条规则只命中约 5 条(private-key/jwt/
stripe/database 全漏)。上游已改用 FindAllOverlapping(chainreactors/proton#3)。

proton -j 输出改用 nuclei-style 连字符键(template-id/template-name),
不再直接 marshal 内部 parsers.Result 泄漏 template_id(该共享类型
被 scan 等其它数据路径依赖,不能改库 tag);新增 jsonFinding 结构体。

修复 pkg/tools/proton 4 个 E2E:DetectsAllCategories / ProtonJSON /
Pipe_CatToProtonWithExpression / Pipe_ShellToPseudoToShell。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
TestMITMCapture_ServerFirst_Fallback 客户端读 deadline(8s)与 MITM
内部 3s peek 超时裕度过小,-race + CI 争用下回退+透传的 goroutine
调度被拖过 8s → 间歇超时(PR #56 CI test job 即挂在此)。放宽到 30s;
该测试断言的是回退正确性(收到 SSH banner + 0 抓流),不是延迟。

webagent readSessionMessage/readSessionUpdate 同类 5s deadline(等异步
pty.sessions 消息,满载下曾超时)一并放宽到 20s。

均为测试侧墙钟裕度调整,不碰任何生产超时。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
架构简化:
- 删除 pkg/slashcmd 包,命令元数据改为从 tui.Command 单一来源提取
- SlashSpec 类型移入 webproto,hub 路由简化为 3 行 map
- 删除 catalog_test.go 同步守卫(不再有两份数据需要同步)

正确性修复:
- generateID 改用 crypto/rand 消除纳秒级碰撞导致的静默丢数据
- sanitizeMessagesForSave else 分支改为全结构拷贝,不再丢新增字段
- proxy truncate 改为 rune-safe,修复多字节字符被切断
- SetDataDir/DataDir 加 sync.Mutex 消除竞态
- Color.Dim 统一使用 ANSIDim 常量
- stringVal 增加 float64/bool 处理,修复 timeline 丢数字参数

去重与简化:
- mustJSON 统一到 webproto.MustJSON
- stripANSI wrapper 删除,直接调用
- dispatch 内联到 dispatchPayload
- runScanViaAgent/runScanLocally 共享 completeJob

性能:
- WebSocket upgrader 缓存到 pool 构造期
- regexp.MustCompile 提升到包级别
- hasTool O(n)→O(1) map 查找
- isTerminalEvent 使用 slices.Contains

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- pkg/probe → pkg/agent/probe (probe 依赖 agent.Provider,归属更自然)
- 合并 LLMTestRequest / LLMModelsRequest → LLMProbeRequest (仅差一个 Model 字段)
- 删除 ConnTestResponse wrapper (单字段 struct,返回 []ConnCheck 即可)
- 删除 ChatPayload.Persist (PersistMaxTurns > 0 已隐含 persist)
- 删除 SlashSpec.WebMenu (构造时始终 true,前端从不读取)
- embed ChatPayload 到 SendMessageRequest,消除 handler 中手工字段拷贝
- parseChatPayload 每条 chat 消息只调一次 (之前 dispatch + run 各调一次)
- extractEventData 在 forwardAgentEvent 中只调一次 (之前每个 case 重复调)
- 内联 snippet / proxyHTTPClient 到唯一调用点

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@M09Ic

M09Ic commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review follow-up: 后端简化与修复 (2 commits)

Commit 1: bbc8f0d — 删除 slashcmd 包 + 修正确性 bug + 去重简化 (-229 行)

架构简化: 删除 pkg/slashcmd

slashcmd 包与 tui.Command 存在数据重复(description、aliases 维护两份,需要 catalog_test.go 守卫同步)。改为从 tui.Command 单一来源提取命令元数据:

  • 新增 tui.WebMenuSpecs() 从已有 Command 定义提取 web 菜单 spec
  • 新增 tui.StaticCommands() 导出零值 receiver 安全的命令列表
  • SlashSpec 类型移入 webproto(与 wire format 同包)
  • hub 路由从 slashcmd.Lookup 简化为 3 行 hubCommands map
  • 删除 catalog_test.go(不再有两份数据需要同步)

正确性修复 (P0)

Bug 修复
generateID 纳秒碰撞 → SQLite INSERT OR IGNORE 静默丢数据 crypto/rand 16 字节 hex
sanitizeMessagesForSave else 分支手工拷贝 4 个字段,新增字段被丢弃 out[i] = m 全结构拷贝
proxy truncate 按字节切断多字节字符 → 无效 UTF-8 改为 rune-safe 版本
SetDataDir / DataDir 无锁读写 resolvedDataDir sync.Mutex
Color.Dim\033[90m(bright black)而非 ANSIDim\033[2m faint) 统一为 ANSIDim
stringVal 忽略 float64/bool → timeline 丢失数字类型工具参数 type switch 处理

去重与简化

  • mustJSON 统一到 webproto.MustJSON(消除 3 处重复定义)
  • stripANSI wrapper 删除,直接调用 output.StripANSI
  • dispatch 内联到 dispatchPayload
  • runScanViaAgent / runScanLocally 共享 completeJob(~24 行重复合并)

性能

  • WebSocket upgrader 缓存到 pool 构造期(消除 per-connection 分配)
  • regexp.MustCompile 提升到包级别(消除 per-call 编译)
  • hasTool O(n) → O(1) map 查找
  • isTerminalEvent 使用 slices.Contains

Commit 2: f4e6db2 — 简化实现 (-575 行)

probe 归位

  • pkg/probepkg/agent/probe(probe 依赖 agent.Provider,归属更自然)

删冗余类型/字段

  • 合并 LLMTestRequest / LLMModelsRequestLLMProbeRequest(仅差一个 Model 字段)
  • 删除 ConnTestResponse wrapper(单字段 struct 包 []ConnCheck,直接返回 slice)
  • 删除 ChatPayload.PersistPersistMaxTurns > 0 已隐含 persist,两者从未独立使用)
  • 删除 SlashSpec.WebMenu(构造时始终 true,前端从不读取)
  • embed ChatPayloadSendMessageRequest,消除 handler 中 5 行手工字段拷贝

消除重复调用

  • parseChatPayload 每条 chat 消息只调一次(之前 dispatch + runChatWithAgent 各调一次)
  • extractEventDataforwardAgentEvent 中只调一次(之前每个 switch case 重复调)
  • 内联 snippet / proxyHTTPClient 到唯一调用点

全量构建通过,全部测试通过。

M09Ic and others added 2 commits July 7, 2026 11:34
类型系统清理:
- 删除 timeline-mapper.ts (纯字段重命名的转换层,内联到 ChatPanel)
- 提取 eventToMessage() 消除 ChatEvent→ChatMessage 手工构造重复 (3处)

死代码删除:
- 删除 streamingText/streamingAgent 状态 (始终为 null,StreamingEntry 从未渲染)
- 简化 busy 计算、滚动效果、空状态守卫中的 streamingText 条件

消除重复:
- AgentPanel 改为接收 agents prop,消除与 useChatSession 的双重轮询
- 提取 lib/format.ts (formatBytes + formatTime),替代 3 处重复实现
- 修复 sendOpts() 在 handleSendWithAttachments 中被调用两次

代码质量:
- ConfigPanel 4 处 catch(err: any) → catch(err: unknown) + 类型守卫
- viewer 组件 MessageBubble/AssistantResponse 硬编码 'Assistant' 改为使用 labels prop

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MiSans (小米开源中文字体) 按 unicode-range 分片后产生 185 个 woff2
文件共 4.2MB,通过 embed.FS 嵌入 Go 二进制。对安全工具场景而言
跨平台字体一致性不是刚需,系统 CJK 字体已经足够好。

- 删除 misans npm 依赖和 main.tsx 中的 import
- font stack 改为 PingFang SC / Microsoft YaHei / Noto Sans SC fallback
- 保留 Inter + JetBrains Mono + Space Grotesk (共 ~300KB)
- 重建 web/static: 6.0MB → 1.6MB, 200 字体文件 → 15

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Nathaniel Leonardjoi and others added 30 commits July 11, 2026 10:56
新增 cmd/wasm:把 pkg/agent 的 loop/evaluator 当"脑"跑进浏览器扩展,
三座 JSON 缝接到 JS host:
- Provider  -> __aiscanLLM(reqJSON)      (host 现有 provider)
- Tools     -> __aiscanTool(name, args)  (host stub,chrome.scripting 在真实 tab 执行)
- eventbus  -> onEvent(eventJSON)
外加 aiscanRunAgent / aiscanCancelAgent 导出 + aiscanAgentReady 就绪标志。

GATE 结论:
- pkg/agent(+evaluator/provider/commands)GOOS=js GOARCH=wasm 直接编过,
  无需剥离(只 import pkg/commands,不碰 pkg/tools)。
- 端到端可跑:cmd/wasm/testdata/smoke.mjs 21/21(LLM↔工具↔事件↔取消)。
- 体积:strip 17MB / gzip 4.2MB < 现网 finger.wasm 29MB,体积可接受。

不含:插件 host 侧(agent-manager.js 等)、session 持久化 host 化、TinyGo 瘦身。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
对齐插件 host (CyberHubCopilot src/offscreen/wasm-agent.ts) 的既有契约,
让编出的 agent.wasm 直接 drop-in 到 public/wasm/,无需改插件:

- 导出 runAgent (host 调用名) + aiscanRunAgent 别名 + aiscanCancelAgent
- payload 改 camelCase:{task, systemPrompt, model, maxTurns, messages,
  tools, context:{tabId,url,runId}};context 原样透传给工具桥
- __aiscanTool(name, args, ctx) 三参,解析 {content,isError,terminate} 信封
- 修复多轮:用 ag.LoadMessages() 注入历史 transcript(Run 从 state 取种子,
  而非 Config.Messages)
- 结果 {output,messages,turns,stop};StopReason 映射到 host 词表(stopped/
  budget -> max_turns)
- smoke.mjs 按真实契约重写(23/23:三缝 + 多轮 hydration + 取消)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
LLM 桥接现在把每次运行的 ctxJSON({tabId,url,runId}) 一并传给宿主 __aiscanLLM(reqJSON, ctxJSON),让宿主能把 LLM fetch 的取消绑定到对应 run;jsProvider 持有 ctxJSON,README 与 smoke 测试(24/24)同步。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Vite 给每个资源打指纹(index-<hash>.js),字节不变故 assets/ 下 immutable 永久缓存;index.html 是唯一未指纹化、且携带每次启动 access key 的文档,改为 no-cache,避免重启后仍加载旧 bundle 或失效的 key。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
hub 的 /api/* 受 access key 保护,此前本地启动的 agent 拨 WS 未带 key 导致 401、卡在"连接中"死循环。现 --web-url 以 userinfo 形式内嵌 token(http://<token>@host),webagent 拨号时把 token 提出来用 Authorization: Bearer 带上、拨无 userinfo 的地址;无 key 时 header 为空、行为不变(鉴权关闭/测试)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
移除按 host(无 scheme)聚合的 canonical key——它会把同一主机的 http 与 https 源、以及裸端口误并成一个资产;现各自独立。addWebProbe 额外记录 content_type 与 redirect_url,供前端呈现内容类型/重定向。新增 aggregate_test 覆盖。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
报告改为运营者口吻:一段像人写的概述 + 资产明细,不再是指标表格,也不泄漏内部扫描器名(gogo_portscan/check);裸存活主机(icmp/裸端口)折叠进"其他存活主机"列表。GetReport 增加 lang 参数,从结构化结果按请求语言(zh/en)重渲染,扫描期只冻结一份兜底。

另 scan_complete 落库一条只含 scan_id 的轻量 system marker(重 Result 仍经 session_scans 反查),修复刷新/切会话/SSE 重连从消息重建时间线时内联扫描卡消失;空 scan_id 不落库。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ScanSummaryCard 重写为内嵌 资产/发现/报告 三 Tab(报告按语言拉取),对话内即可完整查看扫描结果,删除右侧 DetailPanel 抽屉及 detailScanID/showScanDetail 全套接线;时间线渲染器在只有持久化 marker(无内联 Result)时回退到 scanResults map。

scan-result 数据模型去掉 assets/loots/sources 冗余、新增 contentToken/redirectTarget、修非数字端口排序;AssetResultView 呈现内容类型/重定向;文案去"战利品"(→发现项)。App/ChatPanel 一并带入手机端会话外壳(问候能力卡 + 顶栏抽屉)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
100dvh 根高避开手机浏览器工具栏;pt/pb-safe 清刘海与 home 指示条;iOS 16px 输入防聚焦放大;侧栏折叠态在手机隐藏(改由顶栏抽屉打开);触屏无 hover 的删除键常显并放大命中区;QuickConnect 手机改视口内定位;FindingsSummary 手机 3 列。桌面(md+)形态不变。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add telemetry.RecoverAsError helper and defer it in every Command.Execute
so that any panic in a tool is caught, logged, and returned as an error
instead of crashing the process.

Also bumps gogo (which bumps neutron) to pick up the nil-safe
ChainExecutor fix for #58.

Closes #58

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Scan results are now automatically converted to SCO nodes via
utils/cstx at StructuredResult() time. Result.Nodes carries typed
SCO data (ip/port/app/vuln/framework/...) for frontend rendering.

- core/output: add Result.Nodes field ([]json.RawMessage)
- scan/sco.go: buildSCONodes via cstx.Parse (cstx_native build tag)
- scan/sco_stub.go: stub returns nil without cstx
- Frontend: import generated SCONode types from sco_gen.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- wasm/tools: toolEnvelope 从 5 指针字段 + 双格式兼容简化为 3 值字段单格式
  (122→77 行),删除 toolResultFromObject 和 env.result()
- web/service: 报告构建器引入 reportWriter struct 持有 lang,消除 6 层
  lang 参数透传;修正英文 overview "The pass" → "The scan"
- web/ScanSummaryCard: 报告加载从 {key,status,content} 三元组 + 2 effect
  简化为 2 string state + 1 effect;删除 ReportState 类型和 selectTab
- web/AssetResultView: anchorPrefix 从 8 层 prop drilling 改为 React
  context,中间 3 个组件签名不再携带该参数

净减 61 行 (−199/+138)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…er/cstx-easm

Backend:
- Add SCOSidecar (core/output): subscribes to DataBus, transforms tool
  output to SCO nodes via CSTX FFI, deduplicates by cstx_id
- Create DataBus in App, wire through Deps to all scanner tools
- Thread tool_call_id via context → ToolDataEvent.CallID for per-call
  SCO node association
- All 6 scanner tools emit DataBus events: gogo, spray, neutron,
  katana, proton (zombie ready when dep updated)
- Add ListSCONodesByScanID with scan_id filter on /api/sco/nodes

Frontend:
- Update cyber-ui submodule (bfe9809→12d2d4b): @aspect@cyber rename,
  new cstx/graph/cstx-viewer packages
- Migrate all @aspect/* imports to @cyber/* (30+ files)
- New @cyber/cstx-easm package: 8 atomic components for EASM rendering
  (EasmMetrics, EasmHostCard, EasmPortRow, EasmSitemap, EasmVulnCard,
  EasmResultView) + SCO types + buildSCOModel
- ToolCallDisplay: detect scanner pseudo-commands, fetch SCO nodes by
  callID, render with EasmResultFromNodes instead of plain text

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ead code

Remove historical remnants left over from the SCO refactoring:

- Remove serviceView/webView/lootView bridge types in core/output, replace
  with direct use of parsers.GOGOResult/SprayResult/Loot via type switch
- Remove timelineItem interface and renderContext (no longer needed)
- Remove dead type aliases in scan/jsonl_writer (ServiceResult, SprayResult,
  ZombieResult, VulnResult)
- Remove deprecated CLI flags: --ioa-url/token/node-id/node-name,
  --verify-timeout, --port (alias for --ports)
- Remove ApplyDeprecatedAliases() and its call site
- Remove legacy AI bool from ScanJob/ScanRequest and normalizeJobAnalysis()
- Remove unused ScannerConfig fields: EnableAllAISkills, AITimeout
- Remove DefaultVerifyTimeout and DefaultInt() (now dead)
- Remove VerifyTimeout from config chain (webproto, remote, types)
- Remove 8 legacy Verifier methods (ToolUsed, ToolNotUsed, etc.)
- Remove dead package-level ReadBody() and FormatInvocation() in skills
- Remove SplitFrontmatter() backward-compat shim
- Remove generateLegacy() from templates code generator
- Deduplicate dispatchPayload/dispatchMessage in web agent pool

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace github.com/chainreactors/utils/cstx (indirect, heavy .a in
utils monorepo) with github.com/chainreactors/libcstx/go (dedicated
lightweight module). API is identical — only import paths changed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement context compaction as a unified path shared by manual /compact
and eval loop's inherit_context=false. The summarization uses the same
Provider interface, emits compact_start/end/error events through the
eventbus, and the web layer forwards them as ChatEventCompact.

When REPL context usage exceeds 80%, the user is prompted to compact.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Delete local sco_gen.ts (242 lines), import SCO types from @cyber/cstx-easm
- Replace local buildSCOModel with @cyber/cstx-easm's buildSCOModel
- Re-export SCOResultModel/SCOHostGroup/SCOPortNode/SCOMetrics from easm
- Update cyber-ui submodule to 345b9da (adds @cyber/cstx-easm package)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…anel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… help

Move LLM, Scanner, Agent, IOA, and Recon option groups from the
top-level cliOptions into the subcommand structs that actually use them.
MiscOptions stays global. Each subcommand's -h now shows only its own
relevant flags instead of the full flat list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Makefile STANDARD_TAGS and FULL_TAGS now include re2_cgo. All CI jobs
install libre2-dev and pass re2_cgo tag to go build/test/vet/lint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace upstream wasilibs/go-re2 with chainreactors/go-re2 fork that
bundles pre-built libre2_cre2.a static archives. Build tag re2_cgo +
re2_static selects the bundled archive and statically links libstdc++
and libgcc, producing binaries with zero C++ runtime dependencies.

Removes libre2-dev/g++ install steps from CI — no longer needed.

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

3 participants