Autumn-27
159c587c2e
fix(script): start.bat 改用 CRLF 并切 UTF-8 代码页
...
start.bat 之前是 LF 换行。cmd.exe 解析批处理按字节偏移边读边执行,
只认 \r\n,全 LF 时会读串行,表现为 goto loop 被截断成 'oop'、
"75"( 不是内部或外部命令、: 运算符不存在等一连串报错,脚本根本跑不起来。
同时文件是 UTF-8 无 BOM,中文控制台默认 GBK(936),注释和 echo 全是乱码。
- 顶部加 chcp 65001,中文提示正常显示(artex 本身输出也是 UTF-8)
- 新增 .gitattributes:*.bat 钉 eol=crlf、*.sh 钉 eol=lf,
避免在 Linux 上编辑或重新 checkout 后又被打回 LF
2026-09-12 05:32:09 -04:00
Autumn-27
4ccb8f4ff2
fix(agent): list_assets 按任务范围过滤,修复任务间资产互串 ( #59 )
...
list_assets 此前把任务 id 写死为 0、裸查整个共享资产库,模型又无从写出
范围过滤条件,于是把别的任务的资产(尤其 IP)当成本任务目标,测试方向
被带偏。
- 新增 QueryDSLInScope / GetByIDsInScope:只返回落在【本任务及直接关联
任务】task_scope 内的资产,按归属匹配而非字面值(根域范围含其全部子域/
服务/接口,网段范围含段内主机及服务);越权 id 静默丢弃
- 新增 scopeTargetCTE(纯 scope 归属判定,不含 anchor/tested);whereBuilder
加占位符偏移,$1 留给 taskID
- 修复 IP 直连主机(http://1.2.3.4/api )无法被网段范围命中的盲区:谓词加
OR ts.net >>= try_inet(a.domain)
- 非任务上下文(Auto/pentest, taskID<=0)无范围可依,回退全库
- QueryDSL/CountDSL 原样未动,UI 的「测试资产」视图(按生产者过滤)不受影响
2026-09-12 03:25:47 -04:00
Autumn-27
16e87b48c2
fix(db): side_question checkpoint 入库前剥除 jsonb 不支持的 NUL 转义
...
HTTP/工具响应含裸 NUL 字节时,json.Marshal 将其编码为 \u0000 转义,
PostgreSQL jsonb 列拒绝并抛 SQLSTATE 22P05,导致 SaveSideSnapshot 的
INSERT 每秒失败数十次刷屏。新增 jsonbClean 在 marshal 后剥除真正的
\u0000 转义(按前置反斜杠奇偶判断,避免误伤字面 \\u0000),并订正
exploration.go 中 "json.Marshal already sanitizes" 的错误注释。
Closes #111 , Closes #112
2026-09-12 03:00:28 -04:00
Autumn-27
42f0ff97d3
refactor(agent): 测试范围与资产覆盖度开关解耦,移除 insert_assets 的 related 入参
...
task_scope 是任务的授权边界、资产查询的过滤基准,覆盖度开关只该决定要不要
拿它当分母算指标,不该决定要不要累积范围本身。此前关闭覆盖度会让 auto 与
agent 两条写入路径同时失效,task_scope 只剩界面手工添加的行。
- insert_assets 的自动入范围(source='auto')无条件执行,不再判 coverageDisabled
- add_task_scope 移出 coverageOnlyTools,planner / 任务内主 Agent / 目标拆解
Agent 在覆盖度关闭时照样持有;list_untested_assets 仍随开关隐藏(纯覆盖度视角)
- 移除 insert_assets 每条资产的 related 入参:唯一作用是决定要不要入范围,值又
不落库(同一资产再次登记即作废、界面上也看不出谁被判为无关),连带删除
StripCoverageParams 及其专用的 deepCopyJSONMap / nestedMap
- add_task_scope 与 goalsScopeTail 的描述改为「授权边界」优先、「覆盖度分母」其次
2026-09-11 13:33:44 -04:00
Autumn-27
33d3d00c4b
docs(changelog): 定版 0.3.9
2026-09-11 12:59:32 -04:00
Autumn-27
aa3ef63121
docs(changelog): 补齐 0.3.8 以来的变更条目
2026-09-11 12:45:23 -04:00
Autumn-27
f5c38da8dc
Merge feat/one-click-update: 页面一键更新 + 守护启动脚本
2026-09-11 12:41:31 -04:00
Autumn-27
d69ab3b0f8
Merge remote-tracking branch 'origin/main' into feat/one-click-update
2026-09-11 12:41:02 -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
3f8f072202
Merge pull request #110 from Autumn-27/feat/task-assets-dsl-search
...
feat(assets): 任务测试资产支持 DSL 搜索
2026-09-12 00:04:19 +08: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
1f258837f5
Merge pull request #109 from Autumn-27/fix/mcp-insecure-tls
...
fix(mcp): http 传输支持跳过 TLS 证书校验(自签证书)
2026-09-11 23:38:36 +08: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-27
cde3ce9b25
fix(btw): 非安全上下文降级生成旁路请求 ID
...
crypto.randomUUID 仅在 https/localhost 可用,经 IP+http 访问 Web UI 时
为 undefined,导致 /btw 提问抛 "crypto.randomUUID is not a function"。
改用与 sessions-tab / tasks 页面一致的降级写法。
2026-09-11 11:13:21 -04:00
Autumn-27
151bedcdf5
fix(btw): 无 Postgres 时跳过旁路测试,go.mod 补 uuid 直接依赖
...
server/side_questions_test.go 的 fixture 在拿不到数据库配置时走 t.Fatal,
导致未设置 ARTEX_PG_DSN 的环境跑 go test ./server 直接失败,掩盖真实回归。
改为 t.Skipf,与 server 包其余测试一致。
db/side_questions.go 直接引用 github.com/google/uuid,go mod tidy 将其
从 indirect 移到 direct。
2026-09-11 11:10:32 -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
5a92e0089e
Merge fix/llm-test-session-header: 测试连接补发自定义会话头,修 opencode zen 400
2026-09-11 10:47:25 -04: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
Autumn
d86dd152c3
Merge pull request #105 from Autumn-27/feat/spawn-task-source-ids
...
feat(orchestration): spawn_task 支持 source_task_ids 只读继承来源任务
2026-09-11 01:43:53 +08:00
Autumn-27
f34cc82873
feat(orchestration): spawn_task 支持 source_task_ids 只读继承来源任务
...
- spawn_task 新增 source_task_ids 参数(字符串数组,上限 MaxTaskSourceCount),
子任务可只读继承来源任务已探明的资产/结论;校验规则(数量/有效/去重/存在)
与 HTTP 建任务一致,底层由 CreateTask 改走 CreateTaskWithOptions。
- 修复既有 bug:参数 struct 字段缺 json tag,导致带下划线的键无法匹配,
parent_ref 实际从未生效。为全部字段补齐显式 json tag。
2026-09-10 13:34:34 -04:00
Autumn-27
98f2a28f25
Merge fix/main-session-interactive-live: 主 Agent 任一会话可交互 + 实时徽章修复
2026-09-10 13:16:26 -04: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
b4bbe612df
Merge feat/main-agent-multi-session: 任务内主 Agent 支持多会话可切换
2026-09-10 12:57:59 -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
Autumn-27
9ad88d5ce8
fix(guard): 拦截文案标明为平台管控而非目标防御
...
拦截 deny/ask 回给 agent 的 tool_result 原文案(禁止执行/用户拒绝)
读起来与目标侧 WAF/403 无异,渗透 agent 会当成目标防御去改写命令、
换 payload 尝试绕过。统一经 systemBlockMessage 加平台权威框架,说明
此为平台管控、操作被禁止,引导换方向而非规避。
2026-09-10 11:30:28 -04:00
Autumn-27
01760aa345
refactor(agent): 精简 worker 默认提示词
...
- 边界①收敛为「只做领到的这一条意图」,去掉指纹意图的冗长举例
- report_finding 去掉流量绑定的细节段落(traffic_refs 用法另在 [B] 段)
- 删除可选流量绑定说明与结尾的措辞冗余,收尾一句话总结保留
2026-09-10 11:08:06 -04:00
Autumn-27
066681a71d
Merge feat/chat-session-grouping: 会话列表按 Agent 分组
2026-09-10 11:04:58 -04:00
Autumn-27
97e67df158
feat(chat): 会话列表按 Agent 分组,支持展开收起与置顶独立
...
左侧会话列表原先所有 Agent 的会话混在一起平铺,现按 Agent 分组:
- 分组头可点击展开/收起,收起状态存 localStorage 刷新后保持
- 分组顺序按会话活跃度排(后端已 updated_at DESC,首次出现即最近活跃)
- 置顶会话仍独立平铺在所有分组之上
- 分组头吸顶,带运行中标记与会话数;收起时若当前会话在组内提示圆点
- 分组内行不再重复显示 Agent 名
2026-09-10 11:02:36 -04: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
3c2a60fba7
fix(agent): 空转回合注入续跑指令,复用空响应重试次数
...
模型有时一整轮只输出思考、既不给正文也不调工具,harness 视为自然结束
(end_turn 且无 tool_use),直接以 completed + 空总结收场,一条未完成的意图
断在半路,表现为「任务正常结束但没有文字总结」。五层 LLM 重试均够不着它
(非错误路径),SDK 空响应重试也够不着(以是否 yield 过事件判空,而思考增量
本身就是事件)。
work 的 Stop 钩子现识别这种回合并注入一条续跑指令,让模型带着已有思考继续
执行下一步——不选原样重发,因这类空转由提示词与上下文形状决定,是稳定行为
而非随机抽风。次数复用 LLM 页「空响应重试次数」(默认 2、-1 关闭),是一条
意图的总量闸而非连续次数(harness 已限死连续空转只推一次)。
2026-09-10 10:49:11 -04:00
Autumn-27
eb5290039a
refactor: 升级 norma v0.3.7 并精简 insert_assets/list_assets 描述
...
- go.mod/go.sum: norma v0.3.6 -> v0.3.7(含 shell_* 工具描述精简)。
- insert_assets: 顶层描述去掉与字段 schema 重复的逐类型字段罗列,
仅保留各类型条件必填字段、非 HTTP service 的 ip/domain 约束、
append 合并语义与返回结构。
- list_assets: 字段清单合并、示例保留 2 条覆盖全部语法,去掉多处
重复的 dsl 必填约束与示例。语义不变。
2026-09-10 10:46:47 -04:00
Autumn-27
97ce284c98
refactor(worker): 关闭跨 engagement 记忆,收敛默认工具面
...
- 移除 worker 的 memory 挂载:删掉两处 SetMemory 调用及 worker.go
里的 mem 字段/SetMemory 方法/opts.Memory 装配,RecallMemory、
RecordMemory 两个工具及每轮记忆自动注入不再启用。
- worker 默认工具集剔除 MultiEdit/Glob/Grep:新增 defaultToolsExcept
按名过滤 SDK 默认工具;文件精改用 Edit、检索走 Bash(grep/find)。
planner/mainagent 不受影响。
2026-09-10 10:29:35 -04:00
Autumn-27
ae22e456ce
refactor(tools): get_worker_output 移除 terminated 与 worker_name 字段
...
terminated 仅凭有无 result 记录推断,会把运行中(尚无最终结论)的 work
误报为 terminated=true,语义不可靠;worker_name 对调用方也无实际用途。
两字段一并从返回中删除,并同步更新工具描述。
2026-09-10 10:19:19 -04:00
Autumn-27
72a52e9202
fix: 修复合并后审查发现的 6 个中/高问题
...
#102 高:证据正文下载在全局 advisory lock 事务内 io.Copy 给 HTTP 客户端,
verifyFile 又要整读一遍算 SHA-256 —— 一次大文件下载或慢客户端就会挂住
全进程的证据写入。改为事务内只解析绑定元数据(Store.Binding),出锁后再校验
与串流;blob 内容寻址且 GC 有 24h 宽限,已打开的 fd 也不受 unlink 影响。
#102 高:traffic_evidence_snapshots 的 url/req_head/resp_head 直接来自目标
原始报文,未清洗就写 PG TEXT。目标返回非 UTF-8 头(GBK filename)或 NUL 会让
RecordFindingTx 整个事务回滚,已确认的漏洞完全不落库。新增
TrafficEvidenceSnapshot.Normalize(),在算 ID 之前套用仓库既有的 utf8Clean,
保证哈希与入库字节一致。
#102 中:自动绑定默认关闭,reporter 便不会传 evidence_version,
SetFindingReportVersionByNodeID 按 legacy 语义写 -1,报告永久显示「待更新」
且 UI 无处清除;老库还因 reporter_agent_seed_v1 守卫拿不到新触发文案。
触发消息改为无条件先读 get_finding_traffic(只读工具,不依赖捕获开关)并回传
版本,并加一次性迁移刷新老库中未被用户改动的默认文案。
#102 中:开关关闭时 report_finding 只要收到 traffic_refs/evidence_hint_id
就在写入前报错,模型幻觉出多余字段即丢掉一个真实漏洞。改为忽略这两个参数
照常登记,由既有的 evidence_status=not_bound 说明未绑定。
#101 中:删掉 RuleID!=0 判断后,每次模型放行都写一行带完整审计快照的
intercept_pending(单行最坏 24×8KiB 上下文 + 32KiB 输入)。开启兜底裁判的
渗透任务会灌入数百 MB,并经 task_archives 的 SELECT * 进入归档。放行行改为
只留决策元数据与执行结果,丢掉重放快照;ask/deny 路径不变。
#103 中:FindingRetestForConversation 出错时在收尾 defer 注册前就 return,
复测行永远停在 pending —— 漏洞列表常驻「复测中」,后续发起复测被去重拦下,
只有重启才能清。新增 FailPendingRetestForConversation 按会话 ID 收尾。
2026-09-10 10:15:24 -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
Autumn-27
29fa64cdbe
Merge PR #101 : feat(intercept): 增加审批记录详情与执行审计
2026-09-10 10:02:29 -04:00
Autumn-27
8dae851b9b
docs(changelog): 发布 0.3.8
2026-09-09 14:10:07 -04:00
Autumn-27
c585b196b5
docs(changelog): 补全 v0.3.7 以来的未记录变更到 [Unreleased]
...
把 v0.3.7 之后除五层重试外的 25 个 commit 归类补入 [Unreleased]:
cold-digest 冷节点压缩、全局出口代理、自定义会话头、墙钟就地收尾、
worker/planner 提示词与工具集调整、graph_overview 改动、意图状态标签
语义修正等。新增「探索图」「网络」两个章节。
2026-09-09 14:08:48 -04:00
Autumn-27
5327f88ebc
refactor(worker): 收敛 work agent 默认工具集与资产写回提示
...
work agent 只负责单条意图的执行与写回,读上下文/跨 work 复盘属规划职责:
- 从 WorkerTools() 移除 list_facts / node_detail / list_companies 及跨 work 检索
(search_all_worker_traces / list_worker_traces / get_worker_trace),只留
list_findings(报漏洞前查重) + add_finding/record_fact + insert_assets/list_assets。
- 旧库迁移 seedWorkerReadToolsUnbind(flag worker_readtools_unbind_v1):逐个
RemoveAgentFromTool 把上述工具从 worker 默认绑定剥离,planner/main 同名绑定不动。
- worker 提示词「查上下文」段收敛为 list_assets/list_findings;insert_assets 段删掉
与工具 schema 冲突的陈旧字段(type=tech/on_url/props/props.http),字段填法交回工具
自身说明,只留路由与边界。reseedWorkerPrompt 版本 bump v3→v4 下发旧库。
2026-09-09 13:59:47 -04:00
Autumn-27
64b08f518f
feat(agent): 墙钟超时改为就地收尾,移除外部硬 ctx 兜底
...
依赖 norma v0.3.6:MaxDuration 到点会打断在跑工具并就地进收尾(在活 ctx
上按收尾轮数续跑落库+总结,终态 timeout),不再依赖 worker/planner 各自
的 maxDur+90s 外部硬 ctx 把卡住的 run 直接杀成 aborted_tools。
- worker/planner: 删除 WithTimeoutCause 硬 ctx 与 settleHardGrace 常量,
run 直接用 ctx(仅承载 pause/kill/shutdown)。
- chat 走同一 harness 自动获得同样行为;mainagent 无 MaxDuration 不受影响。
- terminalreason: 更新 ReasonTimeout 文案。
2026-09-09 13:49:59 -04:00
Autumn-27
aa12706ed1
docs(llm): 重试配置每层写清「什么错误会走到这层」
...
原来每层只有一句泛泛的说明,用户填了旋钮看不到效果时无从判断是配错了还是
这类错误压根不落在这层。现在每层固定给两句:
触发 具体到状态码——建连是 408/429/5xx 与网络层错误,空响应是 200+
正常 stop 却无内容块,安全窗口是拿到 200 之后的断流/overloaded/
流内 429,熔断区分瞬时(429/5xx)与确定性(401/402/403/404),
意图重跑是前面几层都没兜住的 model_error
不走这层 长得像但走别处的:max_tokens 截断、额度耗尽(402)、上下文过长
(413)、4xx 确定性拒绝
模型配置抽屉里的紧凑版只显示「触发」这一句,全局页两句都给。纯文案,无逻辑改动。
2026-09-09 13:39:44 -04: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
ae29b6714e
Merge feat/cold-digest: 探索图冷节点压缩(cold-digest)
...
冷节点折叠成 digest 进 graph_overview,原节点保留、按 id 可还原(无损、可逆)。
含 §3.1 同父归组、后台 minor/major 压缩、按资产索引、related_tasks 只读折叠、
expand_digest/expand_index 工具(仅 planner/main agent)。经 20 项对抗式评审修正。
2026-09-09 12:54:27 -04:00
Autumn-27
67787b5be8
chore(digest): expand_digest/expand_index 只给 planner 与 main agent,不给 worker
...
worker 不读 graph_overview、不需要按 digest 列成员;命中折叠成员 id 时用 node_detail
(直接取原节点、非折叠感知)即可还原。故从 WorkerTools 移除这两个工具,只保留在
PlannerTools 与 MainAgentTools。
2026-09-09 12:28:39 -04:00
Autumn-27
775189d916
feat(digest): related_tasks 只读折叠(§2 跨任务)
...
关联/继承任务的概览现在复用其【自身的折叠视图】,与当前任务同逻辑:
- relatedTaskOverviews 按 source 任务自己的 covered/hot 折出已折成员(recent_facts /
recent_intent_results 跳过已折且仍冷的成员),并把该任务的 cold_digests(body)只读带出,
统一 inherited=true / source_task_id 标记。
- expand_digest 支持跨任务:先查本任务,再查直接关联任务(read-only),返回成员紧凑列表并
标继承;node_detail 已有的 GetNodeWithSources 负责成员完整还原。
- 复活检查同样生效:source 任务里已复活(转热)的被覆盖成员照常显示,不被折出。
至此设计文档 §2 跨任务折叠全部落地;仅 §2.3 墙钟兜底(任务停摆判稳)按既定作为后续。
2026-09-09 12:09:01 -04:00
Autumn-27
eefd5ee2f2
fix(digest): 多智能体评审修正 — 资产索引收敛 + 60cap 保 hot + 文档同步
...
对照 cold-digest-spec 的对抗式评审(20 项发现)逐条核对实现,两处真实代码问题已修:
- 资产索引膨胀(评审 §6.2 高危):早前把一个 digest 落进它成员命中的【每个】asset 桶,
跨资产 digest 会复制进几十个桶、顶层条目不降反升(真实图 asset_ids 约 144 个)。改为
每个 digest 只归一个【代表资产】桶(成员锚定众数、并列取最小 id;无锚定 → 0 号兜底桶),
条目数 ≤ digest 数。
- 60 兜底截断误砍活跃上下文(评审 §6.3 高危):hot(live 前沿祖先链 / live 意图下新事实)
是活跃推理上下文,绝不能截。改为 hot 全保、60-cap 只约束【冷但未折】残余;冷区两侧
均衡保留。graph_overview 每轮计算 render 期 hot 集(兼用于复活检查)。
其余 16 项评审发现经核对,本实现已由设计选择规避/处理:全量扫描维护(静默变冷/传递翻转
盖章)、签名含锚节点、minor+major 统一走同一 group()(§3.1 在两处都生效、major 不会拆散
同父组)、提交时活跃度复核(不折入复活成员)、content_version 列+状态变更 bump、渲染期索引
(无 KindIndex 陈旧)、cold_digests 与索引并列(body 仍在顶层)、singleton 只进 recent。
文档 §6.2 同步上述解决口径(body 归属、一 digest 一桶、singleton 归 recent)。
2026-09-09 12:04:17 -04:00
Autumn-27
4f088e519b
feat(digest): 探索图冷节点压缩(cold-digest)
...
把老且长期不活跃的意图/事实折叠成 digest 节点进 graph_overview 展示,
原始节点永久保留、按 id 可完整还原(存储无损、只压呈现、折叠可逆)。
- 数据模型:KindDigest 节点 + RelCovers 边(真相源);新列 content_version、
cold_since_round(节点级)、round_no(任务级 planner 轮次);均带旧库迁移。
- 纯算法(coldgraph.go):冷热判定(逆向可达 + 任一活分支即热) + R=6 轮防抖 +
连通分量分组(§3) + §3.1 同父兄弟归组(救"热 hub+扁平死叶") + §5.3 签名。
- 后台压缩(compaction.go):minor 折未覆盖冷块(tiered)、major 回源重压合并碎片;
签名幂等复用 body;提交时活跃度复核(绝不覆盖已复活节点);60s 冷却 + 互斥。
- 概览折叠(§6):recent_* 剔除已折成员 + 渲染时复活检查;cold_digests + 按资产
索引 cold_index(§6.2);expand_digest/expand_index 还原;covered_members 反查
悬空血缘 id;60 兜底截断均衡保 live。
- planner 每轮 OnPlannerRound 维护戳记并触发后台压缩,绝不上热路径。
纯算法单测覆盖 §附/§3.1/§2.3/§5.3;已对 437 节点真实图验证:热 86、冷候选 324、
§3.1 分组 47 块 + 14 孤立冷点(对齐设计文档实测校验)。
2026-09-09 11:52:15 -04:00
Autumn-27
801160930b
feat(planner): 心跳唤醒时若无 open/running 意图则强制补出新意图
...
停摆兜底:心跳/无变动唤醒且全图已无任何 open 或 running 意图时,
开场白改为停摆告警,明确告知 planner 无 worker 在跑、无排队方向,
本轮必须产出一个或多个与既有意图互不重复的新意图(不得产出 0 意图)。
2026-09-09 10:45:20 -04:00
Autumn-27
d728e509dc
feat(overview): graph_overview 全量输出 finding_list
...
findings 是任务最高价值产物且单任务通常不多,改为在 graph_overview
里全量带出 finding_list(不像 facts 只给最近窗口),planner/worker 每轮
即可一眼看全所有确认漏洞,无需再调 list_findings。
每条精简为 {id, summary, evidence?, from_intent?, assets?}:
- evidence 取 finding payload 的 evidence.poc
- from_intent 为产生该漏洞的意图(yields 边)
- assets 直接给受影响资产的可读内容(url/域名/ip:port 等,不再是裸 id),
经 FindingMetaByNodeID 反查锚定资产、批量 GetByIDs 解析
- vulnclass/severity/state 等仍走 list_findings / node_detail
新增 AssetStore.FindingMetaByNodeID 薄封装,让只持有 AssetStore 的
ToolSet 能拿到 node_id→资产映射(读 anchors 表,覆盖新旧漏洞)。
2026-09-09 09:24:13 -04:00
Autumn-27
f270ca66bc
feat(tasks): 任务列表新增「运行中 Worker」列
...
TaskListMetricsAll 增加一个 LATERAL 子查询统计 kind='intent' 且
state='running' 的节点数,随 TaskDTO.in_flight 一并返回,口径与任务
详情页概览的「运行中 Worker」完全一致。列表页在「目标进度」后新增该
列,无运行中 Worker 时显示 0。
2026-09-08 14:25:49 -04:00
Autumn-27
4fba36b73d
refactor(worker): 意图/启动指令/锚定资产移入 system prompt,user 只留全局态势
...
意图是 worker 贯穿整个 run 的唯一职责,放 system 每 run 重拼、绝不被
compaction 压掉,续跑也不依赖 transcript 首消息留存;意图锚定资产原始
JSON 与启动指令一并随意图进 system。启动 user 消息瘦身为仅全局态势
overview(可降级、容忍 stale),空时回退一句启动词避免空首轮。
代价:system 混入 per-intent 数据、失去跨意图缓存复用,为不丢意图的
刻意取舍;与 planner 态势块放 user turn 有意分叉(planner 无单一 mandate)。
2026-09-08 13:51:24 -04:00
Autumn-27
7d4223c535
refactor(worker): record_fact 删否定结论段、confidence 与穷尽解耦、facts 分条收紧
...
worker 默认提示词的 record_fact 段易误导规划者:
- 删掉「否定类结论只写观察+试探性读法」整句,worker 不再被引导写“看不出/放弃”式判断
- confidence(observed/inferred) 与「是否穷尽本意图手段」解耦,回归“直接看到 vs 据现象推断”
- facts 数组分条收紧为「彼此完全独立、无法归并」的极少数例外,默认写一条并进 detail
reseedWorkerPrompt flag bump v2→v3,存量库再刷一次新默认。
2026-09-08 12:39:40 -04:00
Autumn-27
01f223aaa1
feat(planner): done 触发块列出本意图新产生的 fact id
...
worker 结束触发规划时,除输出结论外,追加该意图经 yields 边产生的
fact id 列表,让规划者聚焦本轮增量、可直接 node_detail 查详情。
新增 ExplorationStore.FactsYielded 查询。
2026-09-08 12:15:48 -04:00
Autumn-27
dc4645753c
Merge branch 'graph-overview/trim-hosts-add-done-total'
2026-09-08 11:19:23 -04:00
Autumn-27
b39284f1c6
refactor(overview): graph_overview 不再平铺 hosts,新增 done_intents_total
...
- coverage 块移除 hosts 列表(大范围任务里每轮携带最多 500 个 host 字符串,
对规划决策价值有限),只保留 host_count;具体主机按需 list_assets 查
- 新增顶层 done_intents_total:已结束意图(done/blocked/exhausted)总数,与
recent_done_intents(≤15 截断视图)平行命名,让 planner 去重时知道有无被截,
key 即自描述、无需写进提示词
- db: 新增 ExplorationStore.CountFinishedIntents
- 测试:blackboard 继承用例改用 host_count 断言,移除随之无用的 containsString
2026-09-08 11:19:18 -04:00
Autumn-27
6b18845939
Merge branch 'prompt/planner-worker-refactor'
2026-09-08 10:42:06 -04:00
Autumn-27
1dffe05728
refactor(prompts): 精简 planner/worker 正文并修正实战问题,reseed 推送存量库
...
- planner/worker 默认正文精简(合并重复复述,逻辑无损)
- planner: recent_done 按 state 区分处理(blocked/exhausted 先查 trace 再决定,
不当死路也不无脑重跑);否定结论改为“观察/存疑、非定论”、采信前看 evidence、
inferred 默认派复核意图且至多一次;目标未达成且无 open/running 意图必须产出(硬底线);
“克制”降级为仅去重;深度优先于覆盖度
- worker: 否定类结论只写“观察+试探性读法”、判决权归 planner;
跨意图线索写进 fact 的 summary 交规划者、不自己追
- terminalreason: 修正 blocked 描述(传输层故障、需查执行过程,非“此路不通”)
- reseed flag 均 bump 至 v2:存量旧库启动时把新默认追加为新版本并切过去,
旧版本/用户自定义保留在历史可回滚
2026-09-08 10:32:43 -04:00
Autumn-27
3d71196774
feat(tools): planner 默认绑定 list_assets
...
新库经 PlannerTools() 并入 list_assets 绑定;老库由
seedPlannerListAssetsBinding() 一次性回填(flag 幂等,不覆盖用户解绑)。
planner 现同时具备 list_assets(DSL 全库检索)与 list_untested_assets(范围内未测)。
2026-09-08 08:53:50 -04:00
Autumn-27
f29b37c5b1
fix(db): session_header_key 空值不再写入 NULL
...
SaveProfile 对 session_header_key 套了 NULLIF($n,''),未填写会话头时会写
NULL,而该列是 NOT NULL DEFAULT '',保存 LLM 配置直接报 23502。NULLIF 是
从可空的 base_url/proxy/api_key 抄来的,这列跟 max_tokens_field 一样是空
串语义,去掉 NULLIF 直接传参。
2026-09-08 07:33:30 -04:00
Autumn-27
1e7fe8550e
feat(tools): add_company_scope 默认绑定由 worker 改为 planner
...
- WorkerTools 移除 add_company_scope,PlannerTools 新增
- 新库 seed 默认绑定变为 mainagent/planner/auto
- 老库加一次性迁移 seedCompanyScopeRebind:加 planner、去 worker
2026-09-07 11:35:07 -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
651b961ffc
fix(mcp): 升级 norma v0.3.4,MCP 工具输出增加截断与落盘
...
MCP 工具之前无输出大小限制,现在统一走 tool.Capture:
超过 30000 字符时落盘到 cmd-output/ 并返回 head + 文件指针。
2026-09-07 10:18:41 -04:00
Autumn-27
f66ac54fd6
docs(changelog): 发布 0.3.7
2026-08-31 12:24: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
338e77c064
fix(skills): 修复技能压缩包上传失败与中文命名被判非法
...
- 补上 bzip2 / Zstandard 解压器(标准库 + 已有的 klauspost/compress,不引新依赖),
不再对压缩软件非默认档位打出的包抛 "zip: unsupported compression";
Deflate64/LZMA/XZ/PPMd 等真解不了的方式与加密包改为解压前给出中文提示,
点名文件、压缩方式与重新打包的办法
- 技能内文件路径校验从 [A-Za-z0-9-_./] 的 ASCII 白名单改为 Unicode 黑名单:
放行各语言文件名与空格,仍拒绝控制字符、非法 UTF-8、零宽与双向控制字符、
\ % # ? * : " < > | 及 .. / 绝对路径 / 空路径段,防目录穿越行为不变
- 技能名放开非 ASCII 字母数字(中文可直接作技能名),ASCII 仍守 agentskills.io
规范,空格、点与路径分隔符照旧拒绝
- Windows 压缩软件按 GBK 写的文件名兜底解码后再校验;frontmatter 的
name: "中文技能" 去引号
- 新增 8 个测试:zstd 包、GBK 包、不支持的压缩方式、加密包、目录穿越、名称与
路径校验
2026-08-31 11:37:44 -04:00
Autumn
99fb78df1c
Merge pull request #78 from begininvoke/redgem/security-fix-a64cefdb
...
Fix possible fix(deps): 2 vulnerable dependencies in go.mod
2026-08-31 23:23:49 +08: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
796dbf5600
docs(readme): 增加微信公众号交流群二维码
2026-08-31 09:59:23 -04:00
Autumn-27
5fa2ff0b46
feat(findings): 发现页新增平铺大表视图并设为默认
...
分组视图要逐个任务展开才看得到漏洞,跨任务扫列表时反而绕路。新增
「全部发现」平铺视图作为默认视图,与「按任务分组」通过页头 Tab 切换。
- 表格主体抽成 FindingsTable,两个视图共用同一份行渲染,勾选/行内展开/
行内改名与改状态/深入/删除的行为完全一致
- 平铺视图走 findingsPage(后端本就支持不带 task_id 的跨任务分页),
页码与每页条数独立 state,筛选变更即重置回第一页
- 两视图共用统计卡片与筛选条,当前视图随筛选项一起持久化到 localStorage
- 轮询只打当前视图;行内改动同步写两边缓存,切换视图不会看到过期数据
- 首个请求推迟到偏好水合之后,避免按默认视图白拉一次
2026-08-31 09:59:15 -04:00
Autumn-27
3ddb0cb808
feat(llm): 连接测试打印网关原始响应(状态码+响应体)
...
点击后台「测试」时,把每次 HTTP 尝试的状态码与原始 wire body 打进
服务端日志,便于诊断 401/额度文案/空帧/返回 HTML 页面等情况——不再
只看到 UI 折叠后的 ok/err。
- llmrec.Capture 新增 Attempts(),按次返回 {状态码, 响应体}
- TestConnection 自建 Capture 挂到 ctx(不依赖 LLM 记录开关),
经 quotaAwareTransport 填充后由 logTestConnection 输出,body 裁到 4K
2026-08-31 09:45:01 -04:00
Autumn-27
a2f7ac9747
feat(llm): 任务 LLM 配置链改为任何状态都可修改
...
任务结束(done/failed/timeout)后主 Agent 对话仍走任务配置链,链上模型出问题时
既不能改配置链、也就没法继续交互。去掉 HTTP 与 DB 事务两处终态拦截,前端弹窗
对终态任务同样开放编辑与保存(顺带修掉 queued 状态也不能编辑的口子)。
终态任务保存时不再重开额度阻塞意图:那些意图会从 blocked 挪到 open,既没有
worker 执行、也不再满足「重跑意图」的可重跑条件,反而变成死状态。终态任务想
继续跑仍走重跑意图/新增目标,由它们把任务重新 admit 回运行态。
2026-08-31 09:26:33 -04:00
Autumn
db4f97ee95
Merge pull request #85 from neouks/main
...
支持 Worker 对话实时调整执行方向
2026-08-31 21:08:28 +08: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
Autumn
98d30b28de
Merge pull request #83 from Autumn-27/fix/mobile-session-transcript-height
...
fix(web): 手机端会话详情折叠会话列表,避免会话记录被挤压看不全
2026-08-29 21:30:55 +08:00
Autumn-27
5f0d91bbb3
fix(web): 手机端会话详情折叠会话列表,避免会话记录被挤压看不全
...
小屏下会话列表固定占 10~15rem,会话记录只剩标题和输入框。改为 <lg
默认折叠列表(标题栏显示当前会话名+其它会话未读合计,点开选完自动
收起),并把高度预留从 13rem 收到 10rem。桌面端两栏布局不受影响。
2026-08-29 09:08:10 -04:00
Autumn
7ab0c214c9
Merge pull request #82 from Autumn-27/demo/enrich-planner-mock
...
feat(demo): 丰富 Vercel mock 里的 planner 规划过程
2026-08-29 15:06:25 +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
Autumn
6d4408276c
Merge pull request #79 from neouks/codex/sync-v0.3.6
...
feat: 增加任务冷归档与大任务性能优化
2026-08-29 13:52:05 +08:00
Autumn-27
21656cc2e3
fix: restore changes dropped by the upstream sync merge
...
The manual v0.3.6 sync (22132a4 ) was incomplete, and the follow-up merge
(d803ae2 ) resolved conflicts in favour of that copy, silently reverting three
shipped changes. main is already an ancestor of this branch, so re-merging
cannot bring them back; restore them explicitly.
- schema.sql: re-add the idempotent llm_profiles_format_check migration.
CREATE TABLE IF NOT EXISTS leaves an existing table alone, so databases
created before openai-responses kept the old two-value CHECK and rejected
every openai-responses profile.
- orchestration.go: re-add the reseedPlannerPrompt/reseedWorkerPrompt calls,
dropped by a comment-alignment hunk while the functions stayed behind as
dead code. Without them existing installs never receive the quantified
acceptance check or the negative-conclusion evidence threshold.
- CHANGELOG.md: restore the 0.3.6 entries, the @neouks credit and the correct
norma version range.
Also close three recovery gaps in the new cold-archive path:
- traffic: write the staging journal even when no legacy host directory
exists. Modern installs keep traffic in SQLite only, so a crash between the
PostgreSQL commit and the SQLite commit left the archived task's exclusive
traffic in the hot store with nothing for recovery to act on.
- recoverTaskArchiveStages: treat a missing journal.json as a discardable
directory instead of an error, which used to set recoveryFailed and stop the
archive worker from starting for the rest of the process lifetime.
- stageTaskArchiveFiles: replay the journal's renames when resuming an
existing staging root. The journal is written before the first rename, so
its presence did not guarantee a complete payload, and a resumed round could
package an archive missing transcripts or workspace files.
2026-08-29 01:37:46 -04:00
Autumn
f3cfbafa8f
Merge pull request #75 from Autumn-27/docs/release-0.3.6
...
docs(changelog): 发布 0.3.6
2026-08-28 00:36:46 +08:00
Autumn-27
051ca84a20
docs(changelog): 发布 0.3.6
2026-08-27 12:34:51 -04:00
Autumn
88bca9783f
Merge pull request #74 from Autumn-27/feat/list-facts-paging
...
feat(agent): list_facts 改为分页+关键词过滤,避免上下文膨胀
2026-08-28 00:17:06 +08:00
Autumn-27
10f6a4fbc7
feat(agent): list_facts 改为分页+关键词过滤,避免上下文膨胀
...
fact 多时旧的 list_facts 一次返回每任务至多 500 条且 summary 不截断,
一次调用就可能撑爆上下文。改为分页(默认 20,最新在前)+ q 关键词过滤,
返回 {facts, total, has_more, next_before},summary 超长按 rune 截断。
- db: listByKindPageFiltered/countByKindFiltered(payload->>'summary' ILIKE)
+ ListByKindPageWithSources 跨本任务/继承任务合并分页
- agent: list_facts 加 limit/before/q 参数,compactFact 截断 summary;
worker/planner 提示词同步说明分页语义
- server: 旧库一次性迁移把 list_facts 新 schema 刷进 tools 目录表
(SeedTool 首插入only,否则工具管理页显示「无参数」);flag bump 到 v7
2026-08-27 12:15:02 -04:00
Autumn
6b6b56e0a7
Merge pull request #73 from Autumn-27/fix/llm-test-verify-reply
...
fix(llm): 测试连接校验模型确有回复,并按配置的收发模式测
2026-08-27 23:16:52 +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
Autumn
68a221eda1
Merge pull request #72 from Autumn-27/feat/tool-call-stats
...
feat(commands): 工具执行页新增调用次数统计
2026-08-27 22:58:02 +08:00
Autumn-27
e10f8413dc
feat(commands): 工具执行页新增调用次数统计
...
「工具执行」页工具栏加「统计」按钮,弹窗按工具展示调用次数、占比与
失败次数,按次数降序。统计沿用列表的 task/q 筛选,算的是整个结果集
而非当前页;弹窗打开时才请求,翻页不会多付一次聚合查询。
- db: 抽出 commandFilter,列表与统计共用同一份 WHERE;新增 ToolStats
- server: GET /api/commands/stats
- web: 统计弹窗 + demo 模式 mock
2026-08-27 10:56:11 -04:00
Autumn
a380eb4195
Merge pull request #71 from Autumn-27/fix/llm-profile-streaming-dto
...
fix(llm): 配置列表返回 streaming 字段
2026-08-27 22:39:55 +08:00
Autumn-27
8be7631eb3
fix(llm): 配置列表返回 streaming 字段
...
LLMProfileDTO 漏了 streaming,接口从不返回该字段,前端读到 undefined
后一律回落成默认的流式,导致「非流式」保存成功但重新打开开关仍是开的。
字段不加 omitempty:false 必须出现在响应里。
Closes #69
2026-08-27 10:37:53 -04:00
Autumn
529f34007c
Merge pull request #70 from Autumn-27/chore/bump-norma-v0.3.2
...
chore(deps): 升级 norma v0.3.1 → v0.3.2
2026-08-27 22:10:26 +08:00
Autumn-27
f891f4ffb8
chore(deps): 升级 norma v0.3.1 → v0.3.2
...
带入本轮 norma 修复:
- OpenAI 系响应里被静默丢弃的 reasoning/refusal,Responses 补 reasoning_text
- reasoning 字段三名去重
- 空响应(零内容块)有界重试
- 压缩边界切断工具配对导致的网关 400(同时修复已烤进 transcript 的存量孤儿)
2026-08-27 10:00:04 -04:00
Autumn-27
f6c4cbb013
docs(changelog): 补全 0.3.5 遗漏条目
...
补上 v0.3.4 以来已合入但未记录的变更:LLM 流式/非流式切换、
OpenAI Responses API 格式、LLM 请求/响应原文录制、会话列表多选模式、
以及 #57 的任务/会话/流量体验增强;0.3.5 贡献者补记 @neouks。
2026-08-25 12:27:38 -04:00
Autumn-27
48f260fdde
docs(changelog): 发布 0.3.5
2026-08-25 12:22:06 -04:00
Autumn-27
99ac96da2f
feat(agent): 优化 planner/worker 提示词并加量化验收核对
...
- planner 判目标新增「量化验收核对」:覆盖度/flag 数/权限等可量化目标
未达标时禁止 prove_goal,修复覆盖度要求 100%、实测 40% 却被判完成
- 重写 planner「0 意图」判定:仅在「方向已被现有意图覆盖」或「下一步
依赖在跑 work 的产出」两种情况才 0 意图,避免目标未达成时过早收手
- 强化 worker 否定结论证据门槛:未穷尽手段/证据弱一律标 inferred,
避免轻率的 observed 否定把整条路线焊死
- 加 reseedPlannerPrompt / reseedWorkerPrompt 一次性迁移,旧库追加新
默认版本并切换,旧版保留在历史可恢复
2026-08-25 12:19:04 -04:00
Autumn-27
a9304d5a4f
feat(chat): 会话列表多选改为「多选」模式开关
...
默认列表不再常驻每行勾选框(观感更干净),表头改为「共 N 个 + 多选」按钮。
点「多选」进入选择模式:显示每行勾选框、全选、批量删除,「完成」退出并清空
选择;批量删除全部成功后自动退出(有失败则留在选择模式便于重试)。单条的
重命名/置顶/删除仍走每行的 ⋯ 菜单。
2026-08-25 12:08:18 -04:00