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
Autumn-27
12541a6dec
feat(llm): 支持 OpenAI Responses API 格式的 LLM 配置
...
依赖升级到 norma v0.3.1(新增 FormatOpenAIResponses + reasoning_content 回传
修复)。每个 LLM profile 现在可选第三种格式 openai-responses,打
POST /v1/responses,与 Chat Completions / Anthropic 并列。
- agent.Config:ConfigFrom / FromEnv / Provider() 支持 openai-responses
(BaseURL 归一化去 /responses 尾巴,默认 model gpt-5)
- server:saveLLMConfig 放开二元 format 归一;模型列表端点复用 OpenAI
/models(Responses 模型列表仍在 /v1/models)
- db: llm_profiles 的 format CHECK 约束加入 openai-responses,并幂等迁移
(DROP + ADD CONSTRAINT)补旧库
- web: 格式下拉新增「OpenAI (Responses API)」,类型与回显同步
流式/非流式两条路都走新 adapter;输出、token 统计、操作统计、LLM 录制
四条链路复用中性层,无需改动。
2026-08-25 11:39:24 -04:00
Autumn-27
587ba422b4
feat(llm): 每个 LLM 配置支持流式/非流式切换(默认流式)
...
依赖 norma v0.3.0 的 Provider.Complete。为每个 llm_profile 增加 streaming
开关:开(默认)走流式 SSE;关走真·非流式(stream:false、一次性返回完整
JSON),可绕开部分网关糟糕的 SSE 实现(空帧、思考字段丢帧),代价是失去
运行中的实时进度与实时 token 计数。
- agent.Config.Stream → agentcore.Options.NonStreaming = !Stream;worker /
planner / mainagent / chat / goals 经 SetNonStreaming resolver 注入,任务
路由按当前激活 profile 动态取值
- llmpool.Pool / llmrec.Recorder / taskLLMRuntime 三个 Provider 包装均实现
Complete(分别带故障转移 / 录制 / 同 provider 重试与额度 failover),使
输出、token 统计、操作统计、LLM 录制四条链路在非流式下保持兼容
- db: llm_profiles 新增 streaming 列 + ALTER 补旧库(默认 true,旧配置无感)
- 系统 → LLM 配置表单增加「流式输出」开关
2026-08-25 10:49:47 -04:00
Autumn-27
19a7206d12
feat(llmrec): 录制 LLM 请求/响应 HTTP 原文
...
归一化视图(request_body/response_body)会丢弃工具 schema、tool_use 块,
且看不到原始 SSE 帧,排查 provider 侧问题时信息不足。新增在 HTTP transport
层捕获真实 wire body 的能力:
- llmrec: 新增 Capture,Recorder 挂到 ctx,quotaAwareTransport 填充。
请求取 GetBody 副本(不消费原 body),响应用 tee 保持流式;norma 内部重试
的多次尝试逐次保留(旧代码会读掉丢弃),单次时为字节级原文。
- db: llm_records 增加 raw_request/raw_response 两列,含旧库 ALTER 迁移。
- web: 录制页详情面板增加「原文」视图切换,及请求/响应内容复制按钮
(兼容非安全上下文的 execCommand 回退)。
- 测试: 单元(capture)、端到端(逐字节比对捕获=服务器实际收到)、
迁移(真实 PG 事务回滚)、全链路(Recorder→provider→PG 落库)。
2026-08-25 09:40:05 -04:00
Autumn-27
4d9580ebfa
feat(ops): 新增管理员密码重置脚本 reset-password.sh
...
登录用户名固定 ARTEX,密码以 bcrypt 存于 settings 表 auth.password_hash。
脚本连库后用 pgcrypto 在库内生成 bcrypt(gen_salt('bf',10)),与后端
golang.org/x/crypto/bcrypt 校验兼容,写回该键,重置后无需重启。
- 两种部署:local(宿主机 psql)与 docker(compose/exec 在 postgres 容器内跑,
因 compose 默认不暴露 5432)。
- 连接信息优先级:命令行 > --dsn/$ARTEX_PG_DSN > config.json 的 database.*
(python3 解析,缺则 grep 后备)。
- 安全:新密码经环境变量 + psql \getenv 传入,不进 argv;SQL 用 :'newpw'
自动转义防注入;DB 密码走 PGPASSWORD;docker 用 -e 名字继承、不带值。
验证: 临时库实测三条路径(显式 dsn / config.json / 含 ';DROP TABLE' 特殊
字符密码),写回的 hash 均能被 Go bcrypt 接受、错误密码被拒、注入未生效;
bash -n 通过。全程未触碰真实 artex 库。
2026-08-25 08:47:34 -04:00
Autumn
49f6c23b21
Merge pull request #57 from neouks/main
...
feat: 增强任务管理、会话操作与流量查看体验
2026-08-25 20:45:50 +08:00
Autumn-27
6e40f41051
docs(changelog): 发布 0.3.4
2026-08-24 12:41:47 -04:00
Autumn
54af3a54b9
Merge pull request #54 from Autumn-27/feat/goalless-intent-execution
...
feat(tasks): 目标完成后支持主 agent 直投意图执行(goalless)
2026-08-25 00:22:28 +08:00
Autumn-27
01018a2161
feat(tasks): 目标完成后支持主 agent 直投意图执行(goalless)
...
所有目标达成后,主 agent 经 add_intent 下发的意图可被 worker 直接执行、跑完
即止;planner 在任务无 open 目标时不再运行,避免其重判目标达成而 cancelExec
杀掉直投意图;frontier 抽干后任务回到 done。
- db: 新增 HasOpenGoal 谓词(零迁移,读现有 goal 状态)
- engine: plannerLoop 加 goalless 门(无 open 目标则不进 planner,抽干则收尾)
- tools: add_intent 成功后调 resumeTask 复活任务(仅主 agent 生效,planner 为 nil)
- mainagent: 提示加入「目标达成后反问是否登记为正式目标」引导
- orchestration: reseedMainAgentPrompt 让旧库收到新提示(一次性,同构 reseedGoalsPrompt)
已知边角问题(paused/exhausted 意图的收官判据、零 goal 窗口、TOCTOU 等)
待后续讨论后再修。
2026-08-24 11:58:02 -04:00
Autumn-27
43edb86720
revert(tasks): 从 main 移除误并入 4cf36c7 的 goalless 直投意图改动
...
这几处 goalless(目标完成后主 agent 直投意图执行)改动被打包进了「任务列表
按 id 降序」提交(4cf36c7 ),与该提交主题无关,且尚在评审阶段不应留在 main。
此处仅做正向移除,不改写历史;功能改由独立分支 feat/goalless-intent-execution
承载,评审通过后再合入。
2026-08-24 11:57:28 -04:00
Autumn-27
7299150cfa
fix(chat): 会话已选 LLM 时不再被「全局未激活」误拦,提示按状态细分
...
发送消息的前置检查只看全局激活配置(chatAgentRef),而真正执行的
runConversationSync 会优先用会话所选/Agent 绑定的配置——两处解析分叉,导致
「会话已选一个有效配置、但全局没有激活配置」时,消息在预检查阶段就被 503
「LLM 未配置」拦下,根本走不到能用所选配置的执行阶段。
- 抽出 resolveChatAgent(conversation) 作为唯一解析入口(会话/Agent 绑定优先、
全局兜底),send 预检查与后台执行都用它,消除分叉。
- 提示按实际状态细分(chatUnavailableReason):无任何配置→提示添加;有配置但
未激活→提示激活或为本会话指定一个;而非一律「未配置」。
相邻的 StartTriggeredRun 仍用全局 gate(触发器场景,本次不动)。
验证: 新增两个测试——三态提示区分、会话所选配置在全局无激活时仍能解析出
ChatAgent(回归防护);连本地 PG 实跑通过,server 全量无回归。
2026-08-24 11:55:50 -04:00
Autumn-27
412a993c25
feat(agent): get_worker_trace 的 step_ids 超限改为降级返回而非报错
...
原先 step_ids 超过 5 个直接报错,逼 Agent 重新组织调用、白跑一轮。改为优雅
降级:先去重、剔除非法 id,超出 5 个则返回前 5 步的完整内容,并在结果里用
returned_step_ids / omitted_step_ids / notice 告知本次取了哪些、还有哪些没取,
并提示「若已足够则无需再取剩余」。Agent 立刻拿到数据,是否再取由它自行判断。
保留数量上限的原因不变:detail 是完整原文、不截断,上限用于兜住单个 tool
result 的大小。get_task_worker_trace 经 delegateToTask 复用同一实现,一并生效;
两处工具描述同步更新。
验证: 新增 TestGetWorkerTraceStepIDsDegradeGracefully(含去重/非法 id/前5/
omitted/notice/在限内不加提示),连本地 PG 实跑通过;agent 全量无回归。
2026-08-24 11:35:49 -04:00
Autumn-27
6a8e13fcbd
feat(tasks): 新建任务的分类选择器改为可搜索、可即时新建
...
原先是普通下拉,只能从已有分类里选。改成可搜索的输入框(复用 base-ui
Combobox):输入即过滤已有分类,库里没有的名称回车(或点下拉里的「创建」)会
即时调 createTaskCategory 新建并选中,选中项以可移除的 tag 展示。仍限单个
分类——multiple 仅用于 chip 视觉,onValueChange 只保留最新选中的一个。
- 新建的分类要等父层重新拉取才回流到 categories,组件内先本地留一份
(localExtra),避免选中 chip 和下拉在这段窗口显示成「未知分类」。
- 回车创建仅在完全无匹配时触发,有匹配项时保留 base-ui 的「回车选中高亮项」;
精确同名已存在则直接选中不重复创建。
- 新建成功通过 onCategoriesChanged 通知父层刷新,分类在筛选器等处随即可见。
- 任务列表筛选和批量改分类仍用下拉(选已有分类,无需创建),保持不变。
验证: tsc / biome / next build 均通过。
2026-08-24 11:24:17 -04:00
Autumn-27
4cf36c7896
fix(tasks): 任务列表改按 id 降序,消除同刻创建任务的抖动
...
原先按 created_at 降序排,但没有二级排序键。同一时刻创建的多个任务时间戳
相同,排序不稳定;叠加前端每 10 秒轮询、以及 Manager 用内存 map 存任务
(遍历顺序随机、每次 List 都要重排),这些任务就会在列表里频繁互换位置。
改用 id 降序:id 由 BIGSERIAL 单调递增分配,即插入顺序,唯一且稳定,最新
创建的在最前。db.ListTasks 的 ORDER BY 与 Manager.List 的内存排序同步改。
验证: 新增 TestListTasksOrderByIDDesc 连本地 PG 实跑通过;db/server 全量
无新增失败(仅剩既有的 TestCompanyScopeInvalid)。
2026-08-24 11:08:10 -04:00
Autumn-27
dfbbb33069
fix(assets): ip 字段拒收主机名,并告诉调用方该怎么改
...
上一次修复让非法 ip 不再打挂企业归属重算,但脏数据仍在持续产生。这次从源头
拦住:assets.ip 会被转成 inet 参与网段归属,存主机名的资产对所有 IP/CIDR
范围规则都是隐形的。
- db 层新增 ValidateAssetIP + ErrAssetIPInvalid,在 UpsertIP /
UpsertHTTPService / UpsertOtherService / UpsertEndpoint 四个入口校验。
放在 db 层是因为 Agent 工具和资产 API 都经由它们,不必写两遍;内部调用方
(enrich 的解析结果、task_assets 的 ParseCIDR 输出、RecordValue 已 ParseIP
过滤的分支)传的本就是合法地址,不受影响。
- 错误信息给的是改法而不只是「非法」:带上收到的原值,并指出主机名应改用
type=subdomain 填 domain,或先解析 A/AAAA 记录再填 ip。insert_assets 的
错误是逐条返回的({index, error}),同批其余资产照常入库,Agent 拿到后能
定位到具体那条并在下一轮自行修正。
- 同步收紧 insert_assets 的工具描述与 ip 字段说明,在提示层先挡一道。
- 空 ip 仍然合法:service / endpoint 的 ip 是可选字段。
验证: 新增 db 层四类型拒收测试与 agent 层「一批混入一条非法、其余照常入库」
测试,均连 PG 实跑通过;干净库 go test -p 1 ./... 无新增失败(仅剩既有的
TestCompanyScopeInvalid)。
2026-08-24 10:32:10 -04:00
Autumn-27
9e98407528
fix(assets): 企业归属重算不再被单行非法 ip 打挂,并明确告知是哪些资产
...
assets.ip 是自由文本(Agent 的 insert_assets 和资产 API 都可能写进主机名),
而 db/companies.go 的 IP/CIDR 归属匹配裸转 a.ip::inet。只要表里有一行不是
合法 IP,PostgreSQL 就抛 22P02 中断整条语句,连带同事务的新增/修改企业资产
范围、删除企业全部失败回滚。这个裸转从项目初始化提交就存在。
- schema.sql 新增 try_inet(text):非法值返回 NULL 而不是抛错。没用
pg_input_is_valid 是因为那要 PG16+,这里要兼容更老的存量库。
- 四处 IP/CIDR 匹配统一改用 try_inet。原先 task_scope.go 和
task_assets_context.go 用的正则 a.ip !~ '[^0-9a-fA-F:.]' 只检查字符集,
abc.def 这类全 hex 字母的主机名照样漏过去后炸,一并换掉。
- 跳过不能是静默的:重算会统计并抽样列出这些资产(id + 取值),说明它们不会
被网段规则归属。信息通过企业范围接口新增的 warnings 字段返回并在前端以
长停留 toast 展示,同时无条件写入服务端日志,覆盖没有前端响应的路径
(删除企业、scopesentry 同步、Agent 写入)。
- warnings 与 errors 分开:errors 仍只表示本次提交里不合法的行,既有数据
问题不该被记到用户这次输入头上。
验证: 干净库上 go test -p 1 ./... 仅剩 1 个既有失败(TestCompanyScopeInvalid,
与本改动无关,stash 后同样失败);改动前在含真实数据的库上有 14 个失败,现已
全部通过。go build / vet / gofmt / tsc / biome 均通过。
2026-08-24 10:16:17 -04:00
Autumn-27
fea78b2d6f
feat(tasks): 任务列表支持批量修改分类
...
勾选多个任务后可一次性移动到目标分类,或选「未分类」把它们移出当前分类。
- db: 新增 SetTasksCategory,在单个事务里校验分类存在性并 UPDATE ... WHERE
id=ANY(...),返回真正被更新的 id 和刷新后的分类(含 task_count)。分类检查
放在事务内,避免并发删除把 UPDATE 变成外键冲突。单批上限 100。
- server: 新增 POST /api/tasks/category/batch。写入原子,响应里的逐任务失败
只可能是勾选后又被删掉的任务;顺带把 category_id 的解析(必填但可为 null)
抽成 parseCategoryIDField 与单任务接口共用。
- server: 把批量 id 的 trim/归一/去重逻辑从 controlTasksBatch 抽成
normalizeBatchTaskIDs,两个批量端点共用同一套重复判定。
- manager: SetTasksCategory 在 taskStateMu 内完成 DB 写入与运行中任务 DTO
刷新,防止与单任务更新交错后留下过期的 category_name。
- web: 选中工具栏新增「修改分类」对话框(需确认目标,避免误点批量改动);
「未分类」哨兵值统一提取为 UNCATEGORIZED_VALUE。
验证: go build / vet / gofmt、db 与 server 新增测试连本地 PG 实跑通过、
tsc --noEmit、biome check、next build 均通过。
2026-08-24 09:16:44 -04:00
Autumn-27
3eca390089
style(db): 对齐 ICP 范围匹配 SQL 缩进,并注明手工挂载资产的语句顺序依赖
...
#53 引入 icp 范围匹配时,三处覆盖度 CTE 里新增的 OR 分支混进了 tab 缩进,
与同一 JOIN 条件内其它分支(纯空格)不一致。统一改回空格,SQL 语义未变
(git diff -w 无差异)。
AttachAssetsToTask 里 UPDATE assets 会先触发 trg_assets_task_links 写入
source='system',随后的显式 INSERT 才把来源改成 'manual'。加注释说明这层
顺序依赖,避免后续调换两条语句导致人工挂载的来源静默退化成 system。
2026-08-24 08:55:55 -04:00
Autumn-27
6b44a94ec7
Merge pull request #53 from neouks/main
...
feat: 同步 0.3.3 并增强任务、资产与 LLM 运行时
冲突解决说明:
main 此前已合入同源分支(#42/#31)的大部分内容,与本 PR 形成大量重复历史,
git 报出 18 个文件 104 处冲突。逐块核对后确认 PR 树已完整包含 main 的全部
内容(net diff 无任何纯删除,adc8e35/476a445/9fad543/9d8e0ba 等 main 侧修复
均已在内),故统一取 PR 侧。
另修正 db/assets.go 的静默错误自动合并: git 未报冲突但把 CountByTask /
CountsByTypeForTask / DeleteByTaskID 等 166 行重复插入两遍,会导致方法重复
定义编译失败。
相对 main 的净新增功能:
- 任务分类: task_categories 表 + tasks.category_id,分类增删改查与筛选,
改名时同步刷新运行中任务的 DTO
- 任务测试资产: task_asset_links 表记录关联来源(agent/manual/api/task/
anchor/system/legacy),支持实时挂载与移出;移出仅解绑,保留全局资产
- 测试范围新增 icp / keyword 两种 kind,ICP 按去空格小写匹配 icp/app_icp
- Worker 会话标题旁展示当前测试资产及来源摘要,继承任务仅暴露终态意图
- 前端抽出公共 ScopeTextEditor,补齐上述接口的 mock 契约
验证: go build / go vet / go test / tsc --noEmit 均通过。
2026-08-24 08:36:34 -04:00
Autumn-27
9ab9fe2327
docs(changelog): 定版 0.3.3(补齐 v0.3.2 之后的新增/修改/修复)
2026-08-23 13:32:44 -04:00
Autumn
734c7b21cf
Merge pull request #49 from Autumn-27/fix/prompt-var-duplicate-now
...
fix(prompt-vars): 消除变量目录与全局变量撞名导致的前端 key 重复
2026-08-24 01:16:29 +08:00
Autumn-27
9fad543168
fix(prompt-vars): 消除变量目录里与全局变量撞名导致的前端 key 重复
...
goals 内置 agent 的变量目录里定义了 Now,seed 进 agent_prompt_vars 后,
withGlobalVars 又追加了同名的全局 runtime 变量,getAgent 返回两条 Now →
前端 variables.map 的 key={v.name} 重复,React 报错并可能丢/重渲子节点。
- withGlobalVars: 追加全局变量前剔除同名的库内条目,全局(权威 runtime 定义)
胜出,保证返回列表名字唯一。对所有现存库立即生效,无需迁移。
- db.go: 从 goals 内置目录删掉冗余的 Now(已是全局变量);扩展既有清理 DELETE
一并清掉旧库残留的 'Now' 行(已发版→DB 改动带迁移)。
- 新增 withGlobalVars 去重回归测试。
go build / go vet / go test ./server 全绿。
2026-08-23 13:14:28 -04:00
Autumn
1de7a383cc
Merge pull request #48 from Autumn-27/fix/llm-precommit-safe-retry
...
fix(llm): 提交前安全窗口内对同一 provider 重试,减少 model_error
2026-08-24 01:06:00 +08:00
Autumn-27
9d8e0ba988
fix(llm): 提交前安全窗口内对同一 provider 重试,减少 model_error
...
SDK 的 doStream 只重试建连阶段(拿到 200 之前);流一旦开始,中途断流 /
overloaded / 流内 429 等瞬时故障会直接冒泡成 model_error,零重试。表现为
worker 常出现「无总结,终态 model_error」,甚至只跑了一两个工具就中断。
在 streamTaskLLM(所有任务 agent 的统一出口)里补一层同 provider 退避重试:
- 仅在 committed 之前(还没向调用方交付任何输出)触发,重放相同请求不会
重复模型输出或工具副作用,绝对安全
- 最多 2 次,退避 0.5s→1s(封顶 4s),ctx 取消立即让位
- 只重试瞬时故障(传输 reset/EOF/timeout、408/429/5xx、流内 overloaded);
额度耗尽交给 profile 故障转移、上下文过长交给 harness reactive 压缩、
4xx 确定性拒绝一律不重试
- 给不上时原样落到既有透传/故障转移逻辑,行为不变
新增 3 个回归测试(重试到成功 / 重试耗尽如实上报 / 4xx 不重试),退避以
变量暴露便于测试置零。go test -race 全绿。
2026-08-23 13:02:54 -04:00
Autumn
5574624984
Merge pull request #47 from Autumn-27/fix/capture-usage-yield
...
fix(test): capture_usage 遵守迭代器协议,消除 yield 告警
2026-08-24 00:53:38 +08:00
Autumn-27
5f39391594
fix(test): capture_usage 遵守迭代器协议,yield 返回 false 即停止
...
消除 vet 的 "yield may be called again after returning false" 告警:
每次 yield 后判断返回值,false 则 return,不再继续调用 yield。
2026-08-23 12:52:32 -04:00
Autumn
2a07893f64
Merge pull request #46 from Autumn-27/feat/operation-constraints
...
feat(constraints): 操作约束(抽取→注入 planner/worker 提示→总览管理)
2026-08-24 00:49:09 +08:00
Autumn-27
27c3248844
feat(constraints): 操作约束抽取→注入 planner/worker 提示→总览管理
...
- 新表 task_constraints(allow/deny),CREATE TABLE IF NOT EXISTS 无需迁移
- 新工具 set_constraints:目标拆解器 round-0 先抽约束再拆目标、主 agent 运行时可补;
拆解器提示词要求约束自包含(把「当前目标」等指代替换成具体域名/端口)
- constraintBlock 按最高优先级注入 planner+worker 系统提示;去偏:多样性/拓面显式服从约束
- 注入范围可配置(constraints_inject_planner/worker,默认都开,每轮读、即时生效)
- 总览「约束管理」卡片 + CRUD 接口(增删改不通知 planner,下轮规划自然读到)
- goals 提示词把抽约束步并入可编辑正文;旧库经 flag 守卫的一次性 reseed 追加新默认版本
2026-08-23 12:48:01 -04:00
Autumn
d8f34cc79d
Merge pull request #45 from Autumn-27/feat/goal-management
...
feat(goals): 总览目标管理(增/删/改) + 通知 planner 并复活任务
2026-08-23 23:42:43 +08:00
Autumn-27
d28ecd67fe
feat(goals): 总览新增目标管理(增/删/改),同步通知 planner 并复活任务
...
- 总览页新增「目标管理」卡片,支持人工查看/新增/修改/删除目标
- 新增/修改:通知 planner(新增了目标/由 old 变为 new)并复活任务
- 删除:硬删除 goal 节点(级联删边/锚点),通知 planner,不复活任务
- 无 schema 变更:目标仍存 exploration_nodes(kind='goal'),仅加查询方法
2026-08-23 11:41:53 -04:00
Autumn-27
025e1ce445
feat(intents): 删除 work 改为「停止+记录原因」,不再销毁数据
...
删除不再删意图与其产出,而是:停到 stopped、要求填写删除原因、把原因作为
事实挂到该意图上、并写进意图 payload,规划者收到 cancelled 触发(意图内容+原因)。
- db: StopIntentWithReason —— 标 stopped + 建原因事实 + 连边 + 合并 payload
(cancelled_by_user/cancel_reason),单事务;旧 CancelIntent 保留不再被调用
- agent/server: renderTriggers 加 cancelled 分支;Task.NotifyCancelled;
controlIntent/applyIntentControl 接收并要求 reason
- web: 删除弹窗改为必填原因的 Textarea;列表用红色垃圾桶+删除线+「已删除」徽标
区分;选中会话顶部横幅展示删除原因;controlIntent 传 reason
Claude-Session: https://claude.ai/code/session_019QXSCDmzimwnjntBNCgUD7
2026-08-23 11:14:04 -04:00
Autumn-27
3297ca1821
change(llm): 出站代理留空=直连,不再回退 HTTP_PROXY 环境变量
...
- quotaAwareHTTPClient: proxy 为空时 transport.Proxy=nil(直连),
不再用 http.ProxyFromEnvironment 吃 HTTP_PROXY/HTTPS_PROXY
- 前端代理输入:提示可带账号密码(socks5://user:pass@host:port),
文案改为「留空表示不使用代理(直连)」
显式的 ARTEX_LLM_PROXY 环境变量不受影响(仍写入 Config.Proxy)。
Claude-Session: https://claude.ai/code/session_019QXSCDmzimwnjntBNCgUD7
2026-08-23 10:41:16 -04:00
Autumn-27
52aba07846
feat(mainagent): 默认给主 agent 加上 steer_work 工具
...
主 agent 之前只能 add_hint/add_intent,无法对已在运行的 work 实时纠偏。
现将 planner 的 steer_work(不打断、不丢进展地注入纠偏指令)默认下放给主 agent。
- MainAgentTools 加入 steerWorkTool
- MainAgent 加 steerWork 字段与 SetSteerWork,Chat 里接进 ToolSet
- 全局与 per-task router 两处主 agent 构建均 SetSteerWork(engine.SteerWork)
- 主 agent 提示词「操舵」段补充 steer_work 用法引导(仅影响新 seed)
作用域安全:steer_work 仍校验 intent_id 属于本任务(关联任务只读)。
Claude-Session: https://claude.ai/code/session_019QXSCDmzimwnjntBNCgUD7
2026-08-23 10:37:24 -04:00
Autumn-27
052cf63338
fix(intercept): 加固裁判输出解析,避免正确 DENY 被当成放行
...
模型若照抄提示词里的中文标签(如「拦截:DENY:...」),旧解析要求关键词在行首,
会判为无法解析 → 按 fail_action(默认 allow)兜底,导致真实拦截被放行。
- ParseVerdict 改为扫描行内最早出现的 ALLOW/ASK/DENY 关键词,容忍前缀标签
- 提示词输出段改用箭头并明确禁止输出中文标签,附合法输出示例
- 新增 prompt_test.go 覆盖标签回显、全角冒号、大小写、超长理由截断等场景
Claude-Session: https://claude.ai/code/session_019QXSCDmzimwnjntBNCgUD7
2026-08-23 10:05:10 -04:00
Autumn-27
95d2309935
feat(intercept): 未命中规则的命令接入 LLM 兜底审批
...
在正则/字符串规则之外新增一套独立的模型兜底层:规则命中直接按规则走;
一条规则都没命中时,才由模型做语义判定(ALLOW/ASK/DENY),人工审批兜底。
- intercept: DefaultJudgePrompt(三态判定提示词)+ ParseVerdict;Reviewer 回调注入;
Judge() 读全局 llm_judge_* 配置、超时/失败回退、ask 填审批超时、模型判定加 [模型] 前缀
- guard: applyIntercept 未命中分支调 Judge;模型 allow 不落库,deny/ask 带 reason 入库
- db: intercept_pending 加 reason 列(带 ALTER IF NOT EXISTS 补旧库);
create 函数支持 reason 与 ruleID 0→NULL;历史查询带出 reason
- server: 用 providerForProfile + 单次 Stream 收集注入裁判;GET/PUT /api/intercept/judge
- web: 拦截页拆「拦截规则 / 模型配置」两 tab;拦截范围提为共用信息条;
模型配置双栏布局(提示词直接展开编辑);审批/任务拦截页标注「模型判定」+ 理由
配置默认值:失败回退 allow、审批超时动作 deny、模型 allow 不落库、
提示词默认即内置模板(清空回退模板)。无需 DB 结构性迁移(judge 走 settings KV)。
Claude-Session: https://claude.ai/code/session_019QXSCDmzimwnjntBNCgUD7
2026-08-23 10:02:43 -04:00
Autumn-27
f63a451b87
feat(tasks): 任务增加可选名称字段
...
tasks 表新增 name 列(空=未命名,前端回退到描述),端到端打通:
- DB: schema.sql 加列并补旧库 ALTER;tasks.go 的 Task/CreateOptions/CRUD;
findings.go 分组与任务下拉带出 t.name
- 后端: TaskDTO、内存 Task、createTaskReq 透传 name
- 前端: 类型/API/mock 加 name;任务列表新增名称列与搜索、创建表单加名称输入;
详情页与漏洞页标题回退 name || description
Claude-Session: https://claude.ai/code/session_019QXSCDmzimwnjntBNCgUD7
2026-08-23 09:08:05 -04:00
Autumn-27
070784d43c
revert: 恢复版本号动态注入,本地构建回退为 dev
...
本地运行不再硬编码 0.3.3,改回 dev;build.sh 通过 git describe
注入真实 tag 并经 ldflags 覆盖 main.version。
Claude-Session: https://claude.ai/code/session_01HMRoSjvobCcuH5gbKkStFF
2026-08-23 03:55:10 -04:00
Autumn-27
ca1d22b227
docs(insert_assets): 明确 related 判定,CDN/静态资源类应设 false
...
补充工具描述:与任务无关的资产(如仅存静态资源的 CDN)必须设
related=false 或不插入,避免污染资产覆盖度分母。
Claude-Session: https://claude.ai/code/session_01RtPQYJ8W1mcaace3sHWGDm
2026-08-22 12:33:26 -04:00
Autumn-27
a3fe9b767b
feat(ui): 系统设置接入会话发送键位与 Web 搜索代理
...
- 会话发送键位改用 chat-send-mode 统一配置(CHAT_SEND_MODE_OPTIONS/
useChatSendMode),替换页面内自维护的模式常量。
- Web 搜索区新增代理输入框(http/socks5,留空为直连)。
Claude-Session: https://claude.ai/code/session_01RtPQYJ8W1mcaace3sHWGDm
2026-08-22 11:46:12 -04:00
Autumn
be90d520a3
Merge pull request #43 from Autumn-27/feat/traffic-sqlite-store
...
feat(traffic): 正文入库 + 全文搜索,删除改为 SQL 事务
2026-08-22 23:43:55 +08:00
Autumn-27
fb666c03cc
feat(traffic): 正文入库 + 全文搜索,删除改为 SQL 事务
...
流量录制不再镜像 URL 路径写文件树,改为整条 exchange 落 SQLite:
- record: 元数据/头/正文写库;>256KB 的 body 才溢出到 _blobs(单层
桶、按 hash 去重),库里留 8KB 预览 + 指针。文本正文全量喂 trigram
FTS 索引(二进制按 content-type 跳过),支持任意子串与中文全文搜索。
- 删除退化为一个 SQL 事务级联删四张表,host 树后台异步回收,不再在
写锁内 RemoveAll + 全树扫描——删除从数小时降到毫秒级,期间不再停摆录制。
- gcBlobs 改走 blob_refs 反查,顺带清理空桶目录;保留对旧文件树的
引用扫描与 Get 回落,历史数据免迁移仍可读、可搜(元数据)、可删。
- 新增 traffic_blob 工具与 GET /api/traffic/blob 流式下载大 body;
traffic_search 增加 body_contains 全文参数。
新表均为 CREATE TABLE IF NOT EXISTS,旧库自动补建,无需 ALTER 迁移。
Claude-Session: https://claude.ai/code/session_01RtPQYJ8W1mcaace3sHWGDm
2026-08-22 11:36:58 -04:00
Autumn-27
22ae280584
feat(insert_assets): 资产可标记是否与当前任务相关(related)
...
insert_assets 每条资产新增 related 入参(默认 true):仅在任务开启资产
覆盖度功能时生效——true 才自动纳入覆盖度(测试范围分母),false 则只入
共享资产库、不计入本任务覆盖度(如顺带发现的旁站/无关资产)。
- Call 内部按 related + coverageDisabled 双重 gate 决定是否 AddAutoScope
- 覆盖度关闭时 related 无意义,经 StripCoverageParams 从最终工具 schema
剔除(必须在 ToolResolve 的 DB schema 覆盖之后做,故在装配链末端处理)
- 旧库经 refreshBuiltinToolSchemas(flag v6) 刷新 insert_assets schema,
否则首插入only 的 seed 收不到新参数
- 补 StripCoverageParams 回归测试(开启保留/关闭隐藏/不改原始 schema)
Claude-Session: https://claude.ai/code/session_01Jm87Gr5fq5aso6SfLyguhx
2026-08-22 10:26:11 -04:00
Autumn-27
eb3f278711
feat(task): 资产覆盖度功能可按任务开关
...
创建任务时新增「资产覆盖度功能」开关(默认开)。关闭后:
- 不计算/展示测试覆盖度,总览卡片隐藏、覆盖度 API 返回 enabled:false
- 态势图仅展示资产不显示测试进度(B1:抹平 tested、去已测统计与图例)
- 不再自动累积 task_scope(source=auto)
- planner/mainagent 的 add_task_scope、list_untested_assets 从工具列表剔除
- graph_overview 丢弃 coverage 度量块、保留 scope 字段(防上下文污染)
company 关联(task_scope kind=company)与此开关无关,永不受影响:
insertTaskCompanies 不 gate,TaskCompanyIDs 照常读回,scope 字段照常喂给 agent。
DB:tasks 加 coverage_enabled 列(schema.sql + ALTER ADD COLUMN IF NOT EXISTS
补旧库,默认 true 保持存量任务原行为)。
Claude-Session: https://claude.ai/code/session_01Jm87Gr5fq5aso6SfLyguhx
2026-08-22 10:03:18 -04:00
Autumn-27
5126ac4592
feat(ui): 会话输入框发送键位可配置
...
0.3.2 把 Ctrl+Enter 发送改成了 Enter 发送,习惯旧键位的用户没有退路。
系统设置新增「会话输入框发送键位」,两种模式二选一:
- Enter 发送,Shift+Enter 换行(默认,即 0.3.2 现行为)
- Ctrl+Enter 发送,Enter 换行(0.3.2 之前的键位)
实现:
- 新增 lib/chat-send-mode.ts,复用已有的 local-storage.client 读写封装;
纯前端偏好,不入库、不随账号同步
- 对话页与任务详情主 Agent 会话原本各自内联了一份相同判断,统一收敛到
shouldSubmitOnKey(),加模式时不必两处各改一遍
- enter 模式保留原判断(只排除 Shift),没顺手把 Ctrl+Enter 也变成换行——
原本它是会发送的,改掉会让没动设置的用户感到意外
- 中文输入法保护照旧:isComposing / keyCode 229 时放行,回车选词不误发送
- useSyncExternalStore + 自维护订阅集合:storage 事件只在其他标签页触发,
本页改完需手动 emit 才能立即生效;getServerSnapshot 给默认值避免 SSR 不一致
- ctrl-enter 模式同时接受 Ctrl 与 Cmd(macOS)
按需求放在系统设置页,未采用 issue 中建议的输入框内控件。
Closes #39
Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 07:18:21 -04:00
Autumn-27
ca7300ad52
feat(ui): 任务列表操作列增加详情与暂停/继续按钮
...
操作列此前只有删除,暂停/继续必须先勾选再点批量控制,进详情页只能点标题。
- 详情按钮用 Button asChild 包 Link,渲染为真正的 <a>,中键新开标签、
右键复制链接都可用
- 暂停/继续按钮按状态自动切换形态,调已有的 controlTask 接口,无需改后端;
终态任务渲染为 disabled 而非隐藏,各行操作列宽度才不会随状态跳动
- 状态门控与后端 applyTaskControlWithCause 对齐:非终态且未暂停可暂停
(即 created/queued/running),paused 可继续,不会给出后端会拒绝的动作
- 控制后清空 lastRef 再 load:列表轮询按负载去重,不清会把状态回写挡掉,
看起来像点了没反应;放在 finally 里是因为失败多为状态已变化,更需要重拉
- 批量控制原本自己写了一遍状态列表,改为与行内按钮共用 taskControlAction(),
避免将来新增状态时两边判断分歧
Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 06:51:39 -04:00
Autumn-27
76c648d36d
fix(ui): 任务总览的测试范围显示企业名称而非 ID
...
/api/tasks/{id}/scope 只返回 company_id,前端无从解析名称,测试范围里的
企业行只能渲染成 "company #4 "。
- TaskScope 增加 company_name,ListTaskScope 与 ListTaskScopeWithSources
都 LEFT JOIN companies 带出名称(LEFT 而非 INNER:域名/IP/网段行的
company_id 为 NULL,内连接会把它们全过滤掉)
- 两个查询函数都改,避免结构体字段"一个填一个不填"的不一致
- 前端优先显示名称,公司被删后的残留行仍以「企业 #N」兜底
覆盖图谱的企业节点本就查名显示(task_scope.go 的 BuildCoverageGraph),
不受影响。
Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 06:43:08 -04:00
Autumn-27
f0c2b43802
Merge PR #42 : 0.3.3 Worker/LLM/Agent/UI 增强
...
来自 @neouks 的 PR #42,外加本地的三个后续修改:
- fix(llm): Agent 绑定优先于任务 LLM 配置链
- feat(ui): 会话徽标改显示 LLM 配置名
- fix(scope): 含点号的文本不再被误判为 ICP 备案号
已知遗留(code review 确认,评估影响可控,后续单独处理):
- db/exploration.go CancelIntent 先数后删的并发竞态,会回滚并向用户报
"intent cleanup changed concurrently",不损坏数据
- db/assets.go company_source 优先级 CASE 在 8 处手写重复,改动易漏
- server/goals.go reconcileConcurrency 第二个 if 是死代码
Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 06:26:43 -04:00
Autumn-27
fbddf1cfb5
fix(scope): 含点号的文本不再被误判为 ICP 备案号
...
单文本框自动分类只要文本里出现 "icp" 或 "备案" 子串就判定为 ICP 规则。
备案号本身不含点号(京ICP备12345678号-1),而 ICP 归属走的是精确相等比较
(companies.go 的 kind='icp' 归属查询),所以掺了域名或版本号的描述性文字
一旦被判成 ICP,就会存成一条永远匹配不上任何资产的死规则,且无任何提示。
分类条件增加"不含点号",半角 . 之外一并覆盖全角 .和中文句号 。——粘贴
中文内容时容易出现这两个,真实备案号里同样不会有。
已有的 "京 ICP备 123号"、"沪网备案 9988" 仍判定为 ICP,不受影响。
Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 06:26:07 -04:00
Autumn-27
9b75afe9f1
feat(ui): 会话徽标改显示 LLM 配置名
...
会话标题右侧的徽标原本显示模型 ID,改为显示配置名称;模型 ID 移到 hover
的 tooltip 里,并去掉其中的协议名(openai/anthropic 等)。
- 抽出 resolutionLabel(),徽标、aria-label、tooltip 共用一处取名逻辑;
environment 来源的配置可能没有 name,按 name → model → 未命名配置 降级,
避免渲染出空徽标
- 去掉 font-mono:等宽字体是为模型 ID 准备的,配置名多为中文
- tooltip 用 filter(Boolean).join(" / ") 拼接,模型名缺失时不留孤立斜杠
Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 06:18:07 -04:00
Autumn-27
adc8e3521d
fix(llm): Agent 绑定优先于任务 LLM 配置链
...
任务内各角色解析 LLM 的顺序由「任务链 → Agent 绑定 → 全局」改为
「Agent 绑定 → 任务链 → 全局」:显式绑定了模型的角色始终跑在该模型上,
未绑定的角色才落到任务链,任务链为空时再落到全局配置。
- 拆分 fallbackProviderForAgent 为 agentBindingProvider / globalProvider,
让三个层级可按新顺序自由组合
- current()、CompactionWindow()、taskRuntimeAvailable() 统一按新顺序解析;
taskRuntimeAvailable 改为逐角色判断,有可用绑定的角色在任务链耗尽时仍可运行
- resolveTaskRoleLLM(UI 展示)与前端 mock 同步对调,避免显示与实际调用不一致
保留两处既有语义:绑定/全局路径仍返回 profileID=0,不推进任务链故障转移
(绑定自身的转移仍由 poolForBinding + llm_pool_bind_fallback 负责);未绑定
角色遇到任务链耗尽仍是硬停止,不静默降级到全局。
Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 06:14:18 -04:00
Autumn-27
63859faf3d
docs(changelog): 修正 0.3.2 贡献者为 @neouks
...
上一条把贡献者误写成 git 本地作者名 pphua;该提交经 PR 合入,
GitHub 作者实为 @neouks,更正之。
Claude-Session: https://claude.ai/code/session_01RVrPtpngE9T9DRJHosf6MB
2026-08-20 13:22:42 -04:00
Autumn-27
12de72354e
docs(changelog): 定版 0.3.2 + 贡献者
...
Claude-Session: https://claude.ai/code/session_01RVrPtpngE9T9DRJHosf6MB
2026-08-20 13:21:15 -04:00
Autumn-27
0a55c144ea
fix(skills): 补提交漏 add 的 server/skill_usage.go
...
834e945 在 assembly.go 引入了 meterSkillTool 调用,却漏 add 定义它的新文件,
导致此后 origin/main 从干净 checkout 编译失败(undefined: meterSkillTool)。
补上该文件修复构建。
Claude-Session: https://claude.ai/code/session_01RVrPtpngE9T9DRJHosf6MB
2026-08-20 13:17:38 -04:00
Autumn-27
39c540edfc
fix(chat): 打开主 Agent 会话默认贴底并完整显示最后一条
...
最后一条 final answer 的完整内容是懒加载(AnswerBlock useInView+fetchDetail),
在 activity 数组稳定后才撑开高度,而滚动 layout effect 只依赖 activity 引用、
不会因高度变化重触发,导致打开后最后一条被顶到屏幕外。新增 ResizeObserver 观测
transcript 容器:用户仍贴底时,任何高度变化(transcript 挂载/详情展开/markdown 撑高)
都重新贴底;手动上滚则不再拽回。planner/worker 会话同样受益。
Claude-Session: https://claude.ai/code/session_01RVrPtpngE9T9DRJHosf6MB
2026-08-20 13:17:38 -04:00
Autumn-27
a98081eea9
feat(agent): worker 单次 run 墙钟默认 600→1200
...
改默认不动存量行:CREATE 列默认 + 幂等 ALTER COLUMN SET DEFAULT
补旧库列默认(仅影响将来新插入)、seedBuiltins 种子默认、运行时兜底同步 1200。
旧库存量 agent 行保持原值不变。
Claude-Session: https://claude.ai/code/session_01Qx86izpr6f5R53DW864bPB
2026-08-20 13:17:24 -04:00
Autumn-27
0fc63ad94e
fix(chat): 任务暂停不再拦截主 Agent 对话 + 移除乐观回显消除消息错乱
...
- 后端 chat 处理器去掉 IsPaused 的 409 拒绝(保留 IsDeleting):主 Agent
编排会话独立于任务暂停,暂停中仍可继续对话;暂停只终止当前进行的那一轮。
- 前端 sessions-tab 删除 chatExtra 乐观回显:主 Agent 控制台改为纯服务端
数据渲染。根治伪造 seq 撞全局 DB id 导致的 React key 冲突/跨会话内容渗漏,
以及发送失败不回滚的幽灵气泡。发送失败改为回滚输入框内容 + toast 报错。
Claude-Session: https://claude.ai/code/session_01RVrPtpngE9T9DRJHosf6MB
2026-08-20 13:09:29 -04:00
Autumn-27
28c1be735b
fix(chat): 会话输入框改为 Enter 发送、Shift+Enter 换行
...
原先 Enter 换行、Ctrl+Enter 发送,不符合直觉。改为单独 Enter 发送、Shift+Enter
换行,并加 isComposing 保护避免中文输入法选字时误发(与 sessions-tab 一致)。
Claude-Session: https://claude.ai/code/session_01Bs2rrsVHUBTxRusm9espwB
2026-08-20 12:40:01 -04:00
Autumn-27
9103ff838a
feat(llmrec): 录制请求体补记实际发出的思考参数
...
Recorder 携带配置级 thinking_type/reasoning_effort(这些在 norma buildBody 里从
provider 配置注入 HTTP body,不在 CompletionRequest 上,故录制原先完全看不到)。
序列化时写入 thinking:{type,effort},type 取有效值——每请求 req.Thinking 覆盖优先
于配置级(如 compaction 摘要强制 disabled),与 buildBody 判定一致。前端录制查看页
原样美化 JSON,自动展示该字段。
Claude-Session: https://claude.ai/code/session_01Bs2rrsVHUBTxRusm9espwB
2026-08-20 12:35:12 -04:00
Autumn-27
863e44ec24
feat(llm): 思考开关与思考强度拆成两个独立可配置参数
...
- thinking_type(''/disabled/enabled) 与 reasoning_effort(''/low/medium/high/xhigh/max)
彻底解耦,可任意组合:支持「不发 thinking 字段、只靠强度激活思考」的接口
- agent.Config 拆为 ThinkingType + ReasoningEffort 两字段,NewProvider 直接透传
- db/schema.sql 加 thinking_type 列 + 一次性 DO 块迁移(仅列不存在时回填旧语义)
- 前端 LLM 配置页改为两个独立下拉,强度新增 xhigh 档
Claude-Session: https://claude.ai/code/session_01Bs2rrsVHUBTxRusm9espwB
2026-08-20 12:31:20 -04:00
Autumn-27
834e94535a
feat(skills): 新增 Skill 调用统计(账本 + 页面总览/详情)
...
后端:
- 新表 skill_usage(无外键,任务/会话删除后统计保留),一次 Skill()
调用记一行,只记维度不记 args 正文;含 found 标记未命中调用
- 用 RunInfo 经 ctx 把 task/exploration/intent/session 传到工具装配层,
在 Skill meta-tool 外包一层做埋点(可记 args 长度与不存在的 skill)
- fsListSkills 返回附带调用次数/覆盖任务/最近调用;新增
GET /api/skills/missing 与 GET /api/skills/{name}/usage
前端(/system/skills):
- 树节点显示调用次数 badge;目录优先排序 + 子项缩进错开一级
- 空态改为技能库总览(指标卡 + 调用排行 + 最近/未使用)
- 选中 skill 的详情面板改为响应式左右分栏(配置在左、统计在右,
窄屏回落上下),含最近调用明细与未命中缺口清单
Claude-Session: https://claude.ai/code/session_01BNN7npEJs4X6LfTtgniMd8
2026-08-20 12:30:01 -04:00
Autumn-27
43f40dd74f
feat(findings): 发现页支持导出(Markdown 单文件/分文件zip、CSV、JSON,按筛选/全部/勾选)
...
- 后端新增 GET /exploration/findings/export:按 scope(filtered|all|selected) ×
format(md-single|md-zip|csv|json) 导出,md-zip 用 archive/zip 后端打包
- db.ListFindingsForExport:带完整 report、不分页,按严重等级+时间排序
- report/findings.go:汇总/单条 Markdown、安全文件名、带 BOM 的 CSV 渲染
- 前端发现页加行勾选 + 导出弹窗(范围×格式);复用 lib/utils.copyText
- 顺带修复报告复制在 HTTP 非安全上下文失效(execCommand 降级)+ 复用 CopyButton
Claude-Session: https://claude.ai/code/session_01Bs2rrsVHUBTxRusm9espwB
2026-08-20 12:06:46 -04:00
Autumn-27
ed96f256a4
fix(ui): 报告复制在 HTTP 非安全上下文下失效,增加 execCommand 降级
...
Claude-Session: https://claude.ai/code/session_01Bs2rrsVHUBTxRusm9espwB
2026-08-20 11:21:07 -04:00
Autumn-27
d14ce4d9f4
feat(ui): skill 树修复长文件名与删除确认,任务列表支持多选删除
...
Skill 管理:
- 长文件名把行撑出侧栏导致操作按钮不可见,约束 ScrollArea viewport
内层并把按钮组改为绝对定位固定在右侧
- Skill / 文件夹 / 文件三处删除补上二次确认对话框
任务列表:
- 表格新增多选列(本页全选 + 跨页保留选择)
- 批量删除复用单任务的关联数据清理选项,串行执行并显示进度,
结果按成功/失败聚合提示
Claude-Session: https://claude.ai/code/session_01BNN7npEJs4X6LfTtgniMd8
2026-08-20 11:18:24 -04:00
Autumn-27
def7649baa
feat(tokens): 新增 llm_usage 计量账本,按模型统计 token + 仪表盘新旧版切换
...
- llmrec: 拆分轻量计量与重量 body 录制——token+model+task+worker 永远写入
新表 llm_usage(不含 body,不受 llm_record 开关控制),body 仍受开关控制
- 修复 token 累加 bug:usage 从覆盖改为 Add(Anthropic 把 input/output 拆到
message_start/message_delta 两个事件,覆盖会把 input 冲成 0;OpenAI 不受影响)
- 任务总览新增「LLM Token 用量」卡片:按模型统计 + 缓存命中率(缓存读/输入)
- 仪表盘 Token 卡片加「新版/旧版」开关:新版走 llm_usage(逐次精确、含中断消耗、
真实每日消耗),旧版沿用 activity 统计
- llm_usage 随任务删除保留(历史计量账本)
Claude-Session: https://claude.ai/code/session_014TfZWeVGhjXqZD3vcj44mz
2026-08-20 11:16:48 -04:00