Commit Graph
108 Commits
Author SHA1 Message Date
Autumn-27 d95f0d002d feat(web): 播报板节点详情展示上游节点信息与锚定资产
上游/下游节点从只显示 id 改为悬停弹出节点名片(类型/状态/来源/时间/摘要/payload);
展开时顺带展示该节点锚定的资产(类型标签 + 可辨识文本)。

服务端 /exploration/nodes 新增 assets 字段(节点id→资产),读 exploration_anchors
并复用发现列表的资产打标逻辑;同页节点互引时用本页 items 兜底 refs 查找表。
2026-09-17 11:23:53 -04:00
Autumn-27 c03e008d7b feat(web): 任务详情页新增探索链路播报板
按创建时间分页平铺展示探索节点,作为探索链路图的时间轴视图,
复用同一份 exploration_nodes 数据,不影响链路图。

- 后端 NodesPage/NodesByIDs/EdgesTouching:分页下推 SQL,
  支持 kind/state 过滤、payload/origin 搜索、正倒序,
  并补出当页节点的相邻边与对端节点
- 新增 GET /api/exploration/nodes(仅本任务节点,不含继承)
- 播报板:时间轴分行、按天分组、类型快筛、搜索防抖、
  自动刷新、直播位未读提示、展开看上下游与 payload
- 补 mock,NEXT_PUBLIC_MOCK=1 下可无后端预览
2026-09-17 08:42:49 -04:00
Autumn-27 13ce2ea6e3 Merge PR #139: 支持按状态和判定来源筛选审批记录
合并 codex/approval-record-filters,解决与 #133 在
web/src/components/approval-records.tsx 的冲突:

- 导入同时保留 InterceptApprovalFilter 与 InterceptPending。
- load() 采用 #133 的独立待审批队列(Promise.allSettled 拉取
  /intercept/pending),并把 #139 的 filter 参数透传给历史分页调用;
  筛选只作用于历史记录,待处理队列不受 filter 影响,保证跨页/被筛
  记录仍可审批。
- decide() 保留 #133 的乐观更新(移除 pendingRows 对应项)叠加 #139
  决策后重新拉取以对齐筛选后的计数与行。

验证:前端 tsc 通过、Biome 仅剩预存告警;go build/vet 通过;
db TestInterceptApprovalFilters(8 子用例)与 server
TestInterceptFilterHTTP 在本地 dev 库均通过。

Closes #139
2026-09-16 11:16:26 -04:00
Autumn-27 a15285a7ae Merge remote-tracking branch 'origin/main' 2026-09-16 11:07:02 -04:00
Autumn-27 5fbeb35b8c fix(web): 补齐 demo 漏洞详情页关联流量 mock,修白屏
PR #102 给详情页加了 FindingTrafficPanel 并请求
GET /exploration/findings/{id}/traffic,但 demo mock handler 没有
对应路由,请求落到读兜底返回 {},前端读 data.bindings.length 时
因 undefined 崩掉整个概览 Tab —— 漏洞详情页白屏、展示不出信息。

补齐关联流量的全套 mock 路由(列表/绑定/编辑/解绑/排序/报文详情/
正文分页),返回与后端 db.FindingTraffic 一致的结构并维护内存态;
为 5 条代表性漏洞预置语义匹配的流量证据,其余走空状态;列表与详情
接口补上 traffic_count。
2026-09-16 11:05:21 -04:00
RuoJi6 f6b5c11352 feat(chat): 支持多类型记录 @ 引用及滚动分页 (#135) 2026-09-16 22:36:07 +08:00
ji ruo a91c0a7223 feat: filter approval records by status and decision source 2026-09-16 17:24:15 +08:00
Autumn-27 95bcd4ef9c Merge branch 'feat/noa-experimental':noa 实验性上下文压缩 2026-09-15 12:09:24 -04:00
RuoJi6 04d25eb133 精简动作审查输入并支持审批来源定位 (#125)
* fix: 精简审查背景并区分人工消息与调度输入

* fix: 模型审查仅提交当前调用与选定背景

* feat: 审批来源定位原会话并移除 Worker 审查背景
2026-09-15 23:51:37 +08:00
Autumn-27 865d52267d feat(settings): 增加实验功能开关,可开启 noa 上下文压缩
系统设置新增「实验功能」区块,内含 noa 模型驱动上下文压缩开关(默认关)。
开启后平台接入的四类 agent(planner / worker / 主 agent / 对话)由 noa 接管
上下文压缩,取代内置 compaction;关闭即恢复内置压缩。

- agent: 新增 enableNoa 共享接入器(noaadapter.Enable 唯一入口,all-or-nothing),
  四类 agent 各加 noaEnabledFn 解析器 + SetNoaEnabled,每 run 读一次,切换只影响
  之后启动的 run,无需重建 agent。归档落在各 agent 本 run 工作目录下(任务级持久),
  session id 与 transcript 同规则。启用失败经 onWarn 上报并回退内置压缩,不中断任务。
- server: settings key noa_compaction + Manager 读写;8 处 agent 装配点注入平台级
  解析器(server 5 + task_llm 3);GET/PUT /api/settings 增加字段。
- web: 系统设置页新增实验功能卡片与开关(乐观更新、失败回滚),类型与 mock 补字段。

官方默认行为不变:开关默认关闭时 noaadapter.Enable 不被调用,内置 compaction
原样工作。
2026-09-15 09:20:35 -04:00
RuoJi6 c0d1aa6f37 feat(intercept): 模型审查补充任务上下文与裁决说明 (#124)
审查模型改为接收版本化 JSON:任务描述/目标/操作约束、工作目录、Worker 意图、当前轮输入,以及按 tool_use_id 配对的近期工具执行记录;末尾是完整的 tool_name 与 arguments。

- 任务约束每次审查从数据库重新读取;读取失败或约束超预算转人工。
- 历史只保留唯一配对的执行事实,排除 Agent 自述、未完成请求与平台拒绝反馈。
- 裁决改为 JSON decision(allow/ask/deny) + comment,三种结果均须说明实际操作、成功后果与命中规则。
- 所有模型裁决(含自动放行)保存实际模型输入与 SHA-256 指纹,详情页可展开。
- 对话审批卡片支持展开完整请求、模型输入、裁决与执行结果。
- 修复父目录 lockfile 导致的 Turbopack 根目录误判。

官方默认拦截规则、工具范围与优先级不变。
2026-09-15 20:08:12 +08:00
RuoJi6 1a388e3e9e feat: support legacy SSE MCP servers (#117) 2026-09-15 00:56:16 +08:00
RuoJi6 71fa919599 feat: 为审批记录增加翻页 (#115) 2026-09-15 00:52:48 +08:00
Autumn-27 f2589ad47c fix(web): 修复 demo 任务详情页旁路提问历史缺失导致的整页崩溃
mock 模式下 GET /api/tasks/<id>/side-questions 无路由,被读兜底当集合返回
[],data.items 为 undefined,旁路 hook 的 merge() 迭代抛 TypeError: t is not
iterable,异常在 setState updater 中经 render 重抛、catch 接不住,整页被错误
边界接管。mock handler 显式返回空旁路历史,sideAPI.history 同时归一化返回值。
2026-09-14 09:37:08 -04:00
Autumn-27 e4c744a318 feat(search): 网络搜索新增 DeepSeek 官方来源
不单独配置凭据,直接复用当前激活的 LLM 配置(base_url/api_key/model)。

这个来源与 ddgs/brave/tavily 性质不同:DeepSeek 没有可直接调用的搜索接口,
搜索只存在于其 Anthropic 兼容 messages 接口内部,以 web_search_20250305
服务端工具的形式由 DeepSeek 服务端执行。由此带来几个必须让用户知道的差异,
已在设置页写明:

- 仅支持 DeepSeek 官方端点 + anthropic 协议。实测其 OpenAI 协议端点会直接以
  "unknown variant, expected `function`" 拒绝一切服务端工具,web_search_options
  之类的顶层字段则被静默忽略,没有可用的替代写法。
- 每次搜索额外消耗一次模型调用。
- 搜索请求由 DeepSeek 服务端发出,不经过搜索出口代理,也不计入流量留痕。
- 返回结果只有标题与链接,没有摘要(DeepSeek 只给 encrypted_content),需要正文
  时仍由 WebFetch 抓取。

上述条件不做程序校验,仅在界面说明,由用户自行确认——配置不满足时搜索会在实际
调用时报错,与其它来源填错 Key 的反馈路径一致,可用「测试搜索」按钮实跑验证。

依赖 norma v0.3.8。
2026-09-12 07:13:46 -04:00
Autumn-27 44156a0a4c feat(update): 页面一键更新 + 守护启动脚本
系统配置页新增「版本与更新」卡片,顶栏版本号旁在有新版时亮出提示胶囊。
更新链路:下载发布包 → 比对 SHA256SUMS → -h 冒烟测试 → 暂存 artex.new
→ 以退出码 75 退出 → 守护脚本重新拉起并完成换装,页面轮询 /api/health
等版本号变化后自动刷新。

新增 start.sh / start.bat 作为正式启动入口,只按退出码决定是否重新拉起
(0 停止 / 75 应用新版 / 其余崩溃退避)。校验、冒烟、换装、回滚全部收在
selfupdate 包里而不写进脚本:这些逻辑在 sh 和 bat 上要写两套,而它们恰恰
最不能出错——换上跑不起来的二进制后守护进程会反复拉起它,只能上机器手工救。
Docker 的 ENTRYPOINT 一并改为该脚本,并由它转发 SIGTERM,否则 docker stop
只发给 PID 1,artex 做不了优雅关闭会被 SIGKILL 硬杀。

失败保护两道闸门互补:无法 exec 由换装前的冒烟挡住,能执行但初始化崩溃
由启动计数兜住(连续 3 次失败自动回滚 artex.old,坏的留作 artex.failed)。

GitHub 查询结果后端缓存 30 分钟(失败 2 分钟)。未认证 API 是每 IP 每小时
60 次,且这 60 次是服务器 IP 上所有用户共用的,顶栏每次整页加载都查一次,
不缓存会很快耗光配额导致真想更新时反而查不动。手动「检查更新」带 force=1
绕过缓存。

安全:只认 GitHub 域名且强制 HTTPS(逐跳校验重定向),发布源写死不可配置;
升级文件挂在可执行文件所在目录而非 CWD(服务化运行时 CWD 可能是 /);
开发构建版本号不可比较,禁用一键更新。

走完整 zip 而非裸二进制,因为现有 Release 的 SHA256SUMS 只覆盖 zip,
这样无需改 CI,也兼容已发布的历史版本。

已知限制:Docker 下只换程序不换镜像(工具链不同步、重建容器会退回镜像
版本);不同步发布包里的 skills/;更新即重启会中断运行中的任务。
2026-09-11 12:39:59 -04:00
Autumn-27 557317491b feat(assets): 任务测试资产支持 DSL 搜索
任务详情「测试资产」接口/服务多时不好找。复用资产管理页的 DSL
搜索(字段自动补全 + 分页),搜索始终限定在当前任务范围内。

- 抽出共享组件 asset-dsl-search.tsx,资产页与任务页复用,UI/交互一致
- QueryDSL/CountDSL 增加 taskID 参数,taskID>0 时强制 AND $N = ANY(task_ids)
  并补 task 来源信息;即便 DSL 内写 task_id 也无法越出当前任务
- 任务资产 tab 接入搜索框:有 DSL 走 searchTaskAssets,否则走 taskAssets

Closes #107
2026-09-11 11:59:46 -04:00
Autumn-27 25b82f2544 fix(mcp): http 传输支持跳过 TLS 证书校验(自签证书)
MCP server 走 HTTPS 且用自签证书时,客户端 TLS 校验失败,报
"tls: failed to verify certificate" 无法连接。

mcp_servers 增加 insecure 开关(默认 false),置 true 时远程 MCP
客户端使用 InsecureSkipVerify 的 transport。stdio 传输不受影响。

- mcphttp.New 增加 insecure 参数
- db: MCPServer.Insecure 字段 + schema 加列(补 ALTER 兼容旧库)
- create_mcp/update_mcp 工具与前端 http 配置项增加勾选框

Closes #108
2026-09-11 11:37:56 -04:00
Autumn 4d7d65a1cf Merge pull request #106 from RuoJi6/codex/btw-side-question
feat: add /btw side questions
2026-09-11 23:08:46 +08:00
Autumn-27 399f971f41 fix(llm): 测试连接补发自定义会话头,修 opencode zen 400
testLLM 单发路径既没往 context 挂 session id,也没把 profile 的
session_header_key 透传给 cfg,导致强制要求 x-opencode-session 的端点
(opencode zen)在"对话正常"时"点击测试"却 400 MissingSessionID。

- provider.go: TestConnection 挂一个一次性随机 session id 作头值
- server.go: testLLM 透传 session_header_key,并从已存 profile 兜底
- web: api.ts / llm page 把该字段传到 /llm/test
2026-09-11 10:45:27 -04:00
ji ruo 272004c2e4 Merge upstream/main into codex/btw-side-question
同步官方 main 的任务会话与 spawn_task 更新,保留 /btw 旁路上下文能力。
2026-09-11 08:47:57 +08:00
Autumn-27 6b59d4126e fix(agent): 主 Agent 每个会话均可交互,修实时徽章滞留
上一版把非当前段设为只读、且仅当前段可发消息,与"像会话页一样在任一
会话都能对话"的诉求不符;同时实时徽章改用 recentLive 后,turn 结束仍
会在 5s 窗口内继续显示"实时流式中"。

- server: chat 接口接收目标段 seg,消息写到用户正在看的会话段(缺省=最新段)
- web: 去掉只读/当前/历史区分,任一主 Agent 会话都可直接对话;send 带 seg
- web: 实时徽章改回按真实运行状态(sending/mainChatRunning)判断,且收到
  终结记录(result/报错)即刻熄灭;输入框同样在终结记录后立即解禁
2026-09-10 13:14:54 -04:00
Autumn-27 ee3eb22433 feat(agent): 任务内主 Agent 支持多会话,可切换且上下文可重置
主 Agent 会话原为一个任务恒定单例,对话历史随 transcript 只增不减、
上下文越滚越大。现引入会话分段(seq):新建会话切一个干净的 transcript
段,任务的图谱/资产/目标共享保留,旧段以只读历史随时切回查看。

- db: 新增 main_sessions 表与 activity.main_seg 列(ALTER ADD COLUMN
  IF NOT EXISTS 兼容旧库);ActivitySessionFilter 按段过滤(段 0 兼容
  旧 NULL 行);新增 CurrentMainSeg/ListMainSessions/NewMainSession;
  per-session token 统计按 main:<seg> 分段
- agent: MainAgent.Chat 增加 mainSeg,transcript SessionID 分段
  (段 0 保留旧名 exp<id>-main 兼容既有对话)
- server: parseActivitySession 支持 main:<seq>;chat handler 每轮
  stamp 当前段;新增 GET main-sessions / POST main-session/new
- web: 主 Agent 分组渲染多段会话,支持新建(轻确认)、切换、旧段只读
2026-09-10 12:56:59 -04:00
ji ruo 2930c4b915 Merge origin/main into codex/btw-side-question
合入 main 的 norma v0.3.7、会话分组与流量证据更新,保留 /btw 快照和输入布局。同步自动放行、关闭流量绑定的测试断言,并等待归档测试夹具的旁路后台退出。
2026-09-11 00:54:51 +08:00
ji ruo d893861d00 fix(btw): 修复长对话上下文预算与旁路输入布局 2026-09-11 00:41:01 +08:00
Autumn-27 a90f6e67a3 feat(web): 攻击链路图渲染压缩(digest)节点并收缩其成员
- ExploreKind/ExploreRel 增加 digest/covers 类型
- digest 节点独立样式(青色 Layers)、图例与摘要(body)
- collapseDigestGraph:active digest 覆盖的 fact/intent 成员从图中隐藏,
  触及成员的边端点改接到 digest,成员内部边丢弃并去重,covers 边不渲染
- 详情抽屉展示压缩结论与被压缩成员列表,成员可点击下钻
2026-09-10 11:02:33 -04:00
Autumn-27 e8efce605c Merge PR #102: feat: 支持漏洞关联多条流量证据
冲突解决:
- db/schema.sql: 复测表(#103)与流量证据表(#102)均为追加,两者保留
- server/server.go: 启动序列同时保留 seedFindingRetester 与 evidence GC
- web/src/lib/types.ts: InterceptAudit/InterceptDetail(#101) 与流量证据类型(#102)并存
- findings/detail/page.tsx: 去掉 #103 带入的重复 import,仅保留 FindingRetestPanel
- chat/page.tsx: 保留 #103 的 Spinner import
2026-09-10 10:04:53 -04:00
Autumn-27 071d87896d Merge PR #103: feat: 支持会话级漏洞复测与运行状态展示 2026-09-10 10:02:39 -04:00
ji ruo 555539bc8e feat(agent): 支持持久化 /btw 旁路提问 2026-09-10 21:42:25 +08:00
ji ruo 82c1ed9cbb feat: 支持会话级漏洞复测与运行状态展示 2026-09-10 16:06:08 +08:00
ji ruo 9ad323dc4c feat(intercept): 增加审批记录详情与执行审计 2026-09-10 15:10:50 +08:00
ji ruo a3bb2c7959 feat: 增加 Agent 流量绑定开关并补齐证据交接 2026-09-10 14:08:40 +08:00
ji ruo ec4ef35fff feat: 支持漏洞关联多条流量证据 2026-09-10 13:03:20 +08:00
Autumn-27 a50bf02428 feat(llm): 五层重试的次数与间隔可配
一次模型调用的失败由内到外经过五层重试:建连(SDK)、空响应(SDK)、同 provider
安全窗口、轮询熔断、意图重跑。此前五层的次数与间隔全是写死的常量,遇到脾气各异
的中转站只能改代码。现在都能在 LLM 页配置,不配就是原来的默认值。

配置语义五层统一(db.RetryRule):次数 0=内置默认 / -1=关掉这层 / >0=该值;
间隔 0=原本的指数退避 / >0=改用固定间隔。0 被"未配置"占用,故关闭用 -1。
写库前夹紧到 次数 [-1,20]、间隔 [0,1h],DB 另有 CHECK 兜底。

粒度按层的性质分:前三层跟着端点走,可在每个模型配置里逐字段覆盖全局默认(只钉
间隔的仍继承全局次数);熔断与意图重跑是进程级语义,只有全局一份。

生效路径:①②是 provider 构建参数,保存后重建缓存;③随每次 hooks.current()
解析,故障转移换配置时重试节奏跟着换;④在失败路径上每次都要读,由 applyRetryPolicy
推给 llmpool.Registry;⑤每条意图收尾读一次。全部热生效,无需重启。

连接测试刻意不带这些参数——它有 30s 硬超时,叠上用户配的重试只会把本来能用的
端点测成超时失败。

norma 升 v0.3.5(llm.Config 新增 RetryInterval / EmptyResponseRetries /
EmptyResponseInterval)。旧库升级后行为逐字节不变:新列默认 0,settings 键不
存在即全默认。设计见 docs/LLM重试设计.md。
2026-09-09 13:35:04 -04:00
Autumn-27 377ccc7e5a fix(web): 修正意图状态标签 exhausted/blocked 语义错误
- exhausted「已穷尽」→「预算耗尽」:实为达步数/时间预算被中途掐断、只写回部分结果,
  并非该方向已探尽(易被误读为无需再探)。
- blocked「被拦截」→「执行出错」:实为模型/API/网络故障重试用尽、意图基本没真正探成,
  并非目标/WAF 拦截。
- 补上缺失的 stopped「已停止」(用户手动停止的 work)。
2026-09-09 12:59:48 -04:00
Autumn-27 4319fe413f feat(llm): 每个 LLM 配置支持自定义会话头
新增 session_header_key:非空时每次 LLM 请求带上该 HTTP 头,头值为当前
运行的 session id(chat 会话=conv-<id>,worker=exp<x>-worker-i<intent>
等)。用于某些按 session-id 头做提示缓存/粘性路由的网关。

实现:在已有的 quotaAwareTransport 里从请求 context 读取 session id
(transcript.WithSessionID 挂上的)并注入,无需改 norma;同一共享 provider
也能按会话发出不同头值。DB 加 session_header_key 列(带旧库迁移),前端
LLM 配置弹窗新增输入框。
2026-09-07 11:21:50 -04:00
Autumn-27 b513b656aa feat(proxy): 新增全局出口代理配置
所有目标流量可经统一的全局代理出网(http/https/socks5,支持 user:pass):
- 开启流量捕获时,作为 MITM 记录代理的上游(流量照录再经代理出网);
  拦截与透传两条路径都走上游,不泄露源 IP。
- 关闭捕获时,直接注入 agent 的 bash 环境与 WebFetch;proxyEnv 增加
  ALL_PROXY 以支持 socks5。

配置存于 settings KV 表(无需迁移),前端系统配置页新增「全局代理」卡片。
与网络搜索代理、LLM 代理相互独立。
2026-09-07 10:43:38 -04:00
Autumn-27 7cc467c159 feat(llm): 模型配置新增输出上限,支持 max_completion_tokens 字段名
llm_profiles 加两列:max_tokens(单次回复输出上限,0=不发送该字段,由服务端
默认值决定)与 max_tokens_field(上限发哪个键)。后者仅对 format=openai 生效:
空(默认)= max_tokens;'max_completion_tokens' = 新键。OpenAI 推理模型
(o 系列/GPT-5)拒收 max_tokens、只认新键,而多数兼容网关反过来只认旧键,
故做成显式开关而非自动推断。anthropic 与 openai-responses 自带字段名,
存下来只会误导,保存时一并清空。

顺带补上一处从未接通的链路:planner/worker/chat/mainagent/goals 五个
agentcore.Options 都没设过 MaxTokens,恒为 0——openai 系因 omitempty 压根
不发上限,anthropic 走 norma 的 8192 兜底。光加配置项而不接这条线,用户在
后台填了数字也不会生效,故本次一并接通,取值与 streaming 一样按 profile
每轮解析,故障转移切换后下一轮即生效。

task_llm.go 里 nonStreaming() 的来源优先级(agent 绑定 → 任务链激活 profile
→ 全局)抽成共用的 activeCfg(),避免 maxTokens() 再抄一份同样的三级回退。

norma 升到 v0.3.3(该版本提供 Config.MaxTokensField)。go.mod 只动 norma 这
一行:仓库此前未 tidy 过,跑 go mod tidy 会顺带升 x/crypto、x/net 等一批无关
依赖,不混进本次改动。

迁移:新列走 ADD COLUMN IF NOT EXISTS + 默认 0/'',旧库升级后行为完全不变;
CHECK 约束限定取值,每次启动先删后建保持幂等。
2026-08-31 12:20:31 -04:00
Autumn-27 acd1ac29d7 feat(assets): 去掉企业资产范围 256 条规则上限
逐个 IP / 域名录范围的企业很容易撞上这个上限,撞上之后只能拆成多个企业,
而范围本身并不因为条数多就更慢。

- db:删掉 MaxCompanyScopeRules 常量、请求条数校验与
  ensureCompanyScopeCapacityTx(每企业持久化总数的事务内校验)
- 前端:去掉 MAX_COMPANY_SCOPE_RULES 与「剩余额度」计算,追加范围弹窗不再
  按剩余条数报错;demo mock 的两处上限一并移除
- 单条规则仍限 1024 字符;请求正文 2 MiB(maxCompanyMutationBodyBytes)保留
  作兜底,约合四五万条规则

测试:原先断言「超容量被拒」的两个用例翻转为「超过旧上限也能写入」——
db 侧批量写 300 条 + 追加 1 条,server 侧一次创建带 300 条范围的企业。
新用例先注册清理再断言,避免断言失败把企业留在共享开发库里。
2026-08-31 11:22:34 -04:00
Autumn-27 48e14e8cf2 fix(findings): 补齐「按资产」视图的 mock,修两处标签重复
demo 模式(NEXT_PUBLIC_MOCK=1)下资产树接口没有实现,点开是空白。

- mock findings 关联到 fixture 里已有的资产:一条挂两个资产(验证父节点不重复
  计数)、一条不挂(演示「未关联资产」桶)
- mock handler 实现 asset-tree,并在平铺/分组两个列表分支接上 asset_scope。
  父子优先级、祖先补齐、去重计数、企业层出现条件都与 db/finding_assets.go
  一致;顺带把三处重复的筛选链抽成 mockFilterFindings
- 没有 URL 的服务(SMB、非 HTTP 端口)标签回退成裸 IP,与宿主那行显示得一模
  一样 —— 后端与 mock 都改为补端口(10.10.10.20:8080)
- 接口挂在 host:port 形式的服务下时没触发简写,仍显示完整 URL。宿主判断统一
  成解析后的 host,现在显示 /script

跑 mock handler 实测:17 个节点逐个对账「树上 total == 该节点子树查出的条数」,
无不一致。
2026-08-31 11:10:47 -04:00
Autumn-27 23cfb9ed4e feat(findings): 发现页新增「按资产」视图
左侧资产树 + 右侧该子树下的发现,与另外两个视图共用同一张表和同一批筛选。

后端
- db/finding_assets.go:按当前筛选构建资产树。只收有发现的资产,祖先链逐层
  补齐(endpoint→service→subdomain/ip→root_domain),父子优先级与
  BuildCoverageGraph 同源;计数沿祖先链去重累加,一条发现挂多个资产不会让
  父节点重复计数
- FindingFilter 加 AssetScope:选中节点=选中整棵子树,解析成资产 id 集合后
  下推 SQL,列表 / 分组 / 导出三个入口共用,导出「当前筛选」自动带上
- 「未关联资产」同时收 asset_ids 为空与指向已删资产的发现,与树上桶的口径
  一致(只判空数组会让桶上的数字大于点开后的条数)
- findingFilterFromQuery 统一四处的筛选解析;新增 GIN 索引
  idx_findings_asset_ids,按资产反查发现不再全表扫

前端
- 树默认展开一层,支持过滤(匹配项自动展开)、面包屑下钻、手动刷新
- 每层只显示相对上一层的增量:子域名去根域名后缀、服务显示 `https :443`、
  接口只留路径。完整值在 title 与面包屑,搜索仍按完整值匹配
- 不轮询:进入视图 / 改筛选 / 页内改动发现 / 点刷新时才查
- 节点超上限时整层丢弃接口/服务并提示,计数已在上层不会丢
2026-08-31 10:58:32 -04:00
Autumn-27 c9bf534818 重构 worker 对话:复用 resume 机制,改专属 goroutine 运行
把「给运行中 Worker 发消息调方向」从自建的介入持久化协议,改为复用
已有的暂停/恢复 + transcript resume 能力,实现与主 Agent chat 一致。

- 拆 runWorkerStep:抽出 runIntent(执行+善后),池子与消息路径共用一份
  善后逻辑;新增 runDetachedIntent,把意图 paused→running(不经 frontier)
  并在专属 goroutine 里直接跑,用户消息不受 3 槽池限制、随发随跑。
- 精简 sendWorkerMessage handler:校验 + emit 用户活动 + 专属运行;消息经
  ExecuteWithMessage 作为下一轮输入注入,request_id 仅做 transcript 去重。
- 删除介入 DB 协议与 15 处 activity 查询过滤(回退 exploration.go)、
  directedClaims 调度屏障、RecoverWorkerMessages 恢复、workerWake/waitWorker、
  AbortWorkIntervenedByUser。无 DB schema 改动。
- 前端:保留消息框,恢复「直接继续」(resume)按钮;发送改由 SSE 承载,
  去掉乐观插入。
- 取舍(低频可接受):消息仅存内存,不做崩溃恢复;发消息时该任务可能瞬时
  超并发 1 个 worker。

净改动 9 文件 +583/-46(原 PR 15 文件 +1940/-72)。
2026-08-31 09:00:21 -04:00
pphua cb706d3c8c 新增worker直接对话 2026-08-29 21:55:27 +08:00
Autumn-27 9534e5e8a8 feat(demo): enrich planner rounds in the Vercel mock dataset
The demo's Plan session showed one line per round with no visible
reasoning, no cross-reference to worker output, and no intent-generation
tool calls, so it looked hollow and unrealistic.

Rebuild all five planner rounds as the full decision chain a real
planner emits: read the situation, pull the relevant worker facts for
detail (node_detail / list_findings), judge goals with prove_goal
(including the quantified-acceptance check that refuses to mark g2 met on
a foothold alone), and derive new directions through add_intent with
asset_ids / parent_ids / priority whose results reference the intent ids
already in the graph. Reasoning now cites the worker facts (fa1–fa10) by
id, so the plan is tied to what the workers actually found.

Also renumber the planner activity seq into a single monotonic range so
the rounds render in chronological order; previously round 4 (seq 4–5)
sorted ahead of rounds 1–3 (seq 300+).

Only the mock dataset changes; this affects the NEXT_PUBLIC_MOCK demo
build only, no backend behaviour.
2026-08-29 02:19:48 -04:00
pphua d803ae2b11 merge: sync official main into PR branch 2026-08-28 14:14:41 +08:00
pphua 22132a4d21 chore: sync upstream v0.3.6 changes 2026-08-28 14:03:07 +08:00
pphua 9da521ee4e 归档 2026-08-28 12:56:29 +08:00
pphua 594436fddd 修复BUG: 1、当存在较多任务时,系统会发生卡顿,加载对话或者加载界面时候存在明显卡顿,优化性能找出问题 2026-08-28 08:00:36 +08:00
pphua cf0989c67d 修复
1、修复流量包里的复制按钮不工作问题
2、修复新建任务关联资产不同步到任务测试范围问题
2026-08-28 07:37:24 +08:00
Autumn-27 7b1f7e141b fix(llm): 测试连接校验模型确有回复,并按配置的收发模式测
测试连接此前只判 err:请求通了但模型一个字不吐(思考烧光预算、正文被
安全策略吞掉、兼容层丢 content)照样报成功,而这种配置在会话里就是不
回话——正是「测试成功、对话不成功」的来源。

- TestConnection 返回回复文本,空回复直接判失败
- 回复回传前端,成功 toast 里展示,测试通过有据可查
- 测试连接改用该配置真实的收发模式:此前恒走流式(ConfigFrom 默认
  Stream=true),选了非流式的配置测的是另一条通道;请求省略 streaming
  时仍默认流式,老客户端不受影响

Closes #65
2026-08-27 11:14:48 -04:00