diff --git a/.task/feature-sillytavern-review.md b/.task/feature-sillytavern-review.md new file mode 100644 index 00000000..8c0fd085 --- /dev/null +++ b/.task/feature-sillytavern-review.md @@ -0,0 +1,32 @@ +# feature/sillytavern-review 任务卡 + +任务主记录:[Dev #186](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/186);状态:进行中;owner:weichen + +## 基线与授权 + +- 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= 4fd03eee6230f82464def08f2543adab27aba948 +- 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-sillytavern-review(worktree);分支:feature/sillytavern-review +- 授权与交付终点:调研记录、已核实的安全缺口,以及方案里的批次 A–D 都在本任务实现。完成后推送、建 PR、合入,并在 worktree 内 `make task-finish`。不拷 SillyTavern 代码或文案。不轮换 Tavily 密钥,只在验收说明里建议轮换。不改认证默认 `auto`,不加 CSRF token,不加 CSP 上报端点。 + +## 目标与非目标 + +- 目标:Documents 记录与提案 §2.5;HTML 清洗与安全响应头;来源校验与非回环无认证拒绝启动;密钥独立存储与设置快照;个人指令、会话要求、条件注入、上下文分段估算与消息整形;复制、成组排除、追加式候选回复;用户 `/` 命令展开成提示词且不自动触发。 +- 契约:`Message` 增加 `excluded` / `variantGroup` / `variantIndex`。`Conversation` 增加 `sessionNote`。`ContextObservation` 增加 `sections` 与 `prefixHash`。新表见 Backend 迁移 v16。设置新增 `context.userInstructions`、`context.contextWindow`、`context.messageShape`。 +- 兼容:反向代理或用主机名从局域网访问时,必须把对外域名写入 `allowedHosts`,否则未开认证时 Host 校验返回 403。旧设置里的明文密钥在启动时迁入 `secret_keys` 后从设置 JSON 清除;运行时仍接受尚未迁走的旧字段。 +- 非目标:缓存断点、编辑重发、会话分支、窗口外召回、世界书概率/递归/分组/定时、密钥静态加密、i18n、出站代理、画像导入导出、扩展系统、宏、群聊、角色卡、自定义 CSS、删除消息、自动触发的快捷回复。 + +## 同步记录 + +| 节点 | sync_base_sha | tested_head_sha | checked_at | +|---|---|---|---| +| 启动 | 4fd03eee6230f82464def08f2543adab27aba948 | 4fd03eee6230f82464def08f2543adab27aba948 | 2026-10-04T17:06:46Z | + +## 结果与验证(完成后填写) + +- 结果:安全缺口 S1–S4 与批次 A–D 已在本分支实现。子仓 PR 已合入:Documents [#37](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Documents/pulls/37)、UI [#34](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-UI/pulls/34)、Core [#21](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Core/pulls/21)、Frontend [#43](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Frontend/pulls/43)、Native [#16](https://git-home.u1680832.nyat.app:30319/weichen/Agent-Native/pulls/16)、Squad [#15](https://git-home.u1680832.nyat.app:30319/weichen/Agent-Squad/pulls/15)、Backend [#63](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Backend/pulls/63)。Dev 钉住的功能提交是这些合入提交的祖先:core `0b5c774`,native `3a110a7`,squad `5a57636`,ui `6b2589c`,frontend `eb6502f`,documents `f3f823e`,backend `c05832d`。 +- 验证:`make test` 与 `make build` 退出码 0。`config explain --addr 0.0.0.0:8788` 显示拒绝启动。`serve --addr 0.0.0.0:18799` 退出码 1 且不建库。dev 已部署 `dev@ae06838`,监听 `127.0.0.1:8788`;`/` 带 CSP、nosniff、same-origin。该实例开了认证:跨站 POST 403,无 Origin 的 POST 与 `Host: evil.example` 为 401。同一二进制的无认证实例上,无 Origin 的 POST 为 201,跨站 POST 403,`Host: evil.example` 403,`127.0.0.1` 的健康检查 200,HTML 工件带 `sandbox`。浏览器:Markdown 预览去掉 script 与 `javascript:` 链接,外链图片变成「外部图片 · 域名」;docx、xlsx、pdf 与示例插件工作区无 CSP 报错;mock 对话一轮可见复制、排除、重新生成和「约 N token」。 +- 影响与剩余项:Tavily 密钥曾暴露在无认证监听上,建议轮换,本任务不轮换。暂缓项与拒绝项仍不做。pptx 没有可用样例,未单独打开预览。 +| 同步前验收 | 4fd03eee6230f82464def08f2543adab27aba948 | cd6be001414759f3ad00cf860ae095b70593e296 | 2026-10-04T18:42:56Z | +| 同步前验收 | 4fd03eee6230f82464def08f2543adab27aba948 | ce551683256e770d96c18fdaf93df49df4e0e3b1 | 2026-10-04T18:45:12Z | +| 同步前验收 | 4fd03eee6230f82464def08f2543adab27aba948 | ae06838d66c295d674cee0334ac2a7e9acd1a92f | 2026-10-04T19:45:46Z | +| 同步前验收 | 4fd03eee6230f82464def08f2543adab27aba948 | 3678f58cd3b8b3ca48e412c650c6be3befdf04fa | 2026-10-04T19:46:37Z | diff --git a/DESIGN.md b/DESIGN.md index 480f5280..75655853 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -169,6 +169,7 @@ Agent-System-Dev 是桌面优先、Web 兼容的 AI 工作台。界面应**冷 - 展开态按 id 记忆,切回不丢; - 失败不强制展开:状态词虚线下划线,hover tooltip 给报错,支持一键复制; - 内容懒渲染,收起后延迟卸载(300ms,配合高度动画)。 +- 模型、卡片和文档里的 HTML 只经 `@ui` `safeHtml` 写入。外部图片和音视频不直接加载,改成带来源域名的链接;同源地址、`data:image` 和 `blob:` 照常显示。 ### 9.2 折叠(@ui Collapsible 原语) @@ -232,6 +233,7 @@ Primary(`--primary` 反色)、Ghost(透明,hover 出表面)、Danger 5. 弹窗套弹窗; 6. 同一对象出现第二个预览落位(预览只在预览区,全屏是它的放大); 7. `
` 折叠——用 Collapsible。 +8. 绕过 `safeHtml` 直接把 HTML 字符串写进页面(`dangerouslySetInnerHTML` 或非空的 `innerHTML` 赋值)。 ## 12. 演进规则 diff --git a/deps/agent-native b/deps/agent-native index e4020d29..3a110a72 160000 --- a/deps/agent-native +++ b/deps/agent-native @@ -1 +1 @@ -Subproject commit e4020d297c168347626f9fd75456a71374a0a6c8 +Subproject commit 3a110a728cf520cfbbbafc0c4c75f14bf78bec3f diff --git a/deps/agent-squad b/deps/agent-squad index dcd523ea..5a57636c 160000 --- a/deps/agent-squad +++ b/deps/agent-squad @@ -1 +1 @@ -Subproject commit dcd523ea05fe44901a6ab06e9cc8a2f0d074e0e6 +Subproject commit 5a57636cc0b8426a86a72bbbdd5b7f30e4fcac88 diff --git a/docs/svc.md b/docs/svc.md index aabfe710..c70fd7b8 100644 --- a/docs/svc.md +++ b/docs/svc.md @@ -164,6 +164,8 @@ scripts/svc.sh ui deploy --kind static --dir ../dist # 直接服务既有 | `--data DIR` | agent 数据目录(默认 `runtime//data`) | | `--plugins DIR` | agent 插件源(默认随 deploy 复制环境目录的 `plugins/`) | | `--dsn DSN` / `--auth on\|off\|auto` / `--mock` | agent 运行参数(非 dev 环境默认 `--auth auto`) | +| `SVC__INSECURE_LISTEN` | 设为 `1` 时允许该服务在非回环地址上不开启认证。值传给进程的 `AGENT_SYSTEM_INSECURE_LISTEN`,不写进 `exec=`。旧二进制会忽略 | +| `SVC__ALLOWED_HOSTS` | 逗号分隔的额外主机名,传给 `AGENT_SYSTEM_ALLOWED_HOSTS`,供反向代理的 Host / Origin 校验 | | `--model-base/--model-key/--model-name`、`--light-*`、`--tavily-keys` | 启动健康后播种 | | `--dry-run` | 只解析并打印部署计划(来源、物化路径、产物去向、启动参数) | | `--pick [dev\|release]` | 交互式编号选提交(需 TTY) | diff --git a/modules/backend b/modules/backend index fd170110..c05832dd 160000 --- a/modules/backend +++ b/modules/backend @@ -1 +1 @@ -Subproject commit fd17011047e5059e59df5f2f10965c7b6ef34070 +Subproject commit c05832dd6a3624cfdbd528f23288b9c20dc76f24 diff --git a/modules/core b/modules/core index 5dc190ee..0b5c7747 160000 --- a/modules/core +++ b/modules/core @@ -1 +1 @@ -Subproject commit 5dc190ee63174be71208609309f0b36a5fe070e0 +Subproject commit 0b5c7747a3165bf0d0f2219204b7b70ec3ed7645 diff --git a/modules/documents b/modules/documents index 847f6815..f3f823ef 160000 --- a/modules/documents +++ b/modules/documents @@ -1 +1 @@ -Subproject commit 847f6815f15cd1d778a312fcd2f67c0a9f6dbd54 +Subproject commit f3f823ef8d68045350039e1fbffd1bf8ed591093 diff --git a/modules/frontend b/modules/frontend index e26119db..eb6502f0 160000 --- a/modules/frontend +++ b/modules/frontend @@ -1 +1 @@ -Subproject commit e26119db89d254aee15fba834e4bf1d8309ad153 +Subproject commit eb6502f0effd0d02d8a131930fbe60e61d651657 diff --git a/modules/ui b/modules/ui index 8e66bce0..6b2589c1 160000 --- a/modules/ui +++ b/modules/ui @@ -1 +1 @@ -Subproject commit 8e66bce0f93529ae6e709cecf4b9db804da460cf +Subproject commit 6b2589c19873719c1c203ef7feb542b20a56799a diff --git a/policy/architecture-baseline.json b/policy/architecture-baseline.json index d9147566..a26faaab 100644 --- a/policy/architecture-baseline.json +++ b/policy/architecture-baseline.json @@ -2,6 +2,7 @@ "backend/app backend/bus", "backend/app backend/cardsvc", "backend/app backend/cmdbus", + "backend/app backend/config", "backend/app backend/hostapi", "backend/app backend/intentgate", "backend/app backend/pgbus", diff --git a/scripts/svc.sh b/scripts/svc.sh index 574bbf99..f46eaa43 100755 --- a/scripts/svc.sh +++ b/scripts/svc.sh @@ -55,7 +55,8 @@ # ════════════════════ 配置优先级 ════════════════════ # 命令行 > --config/--env 文件 > svc.env 持久化(exec=/addr=)> SVC__* 环境变量 # (.svc.env 自动加载,同层)> 默认值。裸 start/restart 复用上次启动配置;显式参数 -# 出现即覆盖。任意环境 X 的变量名:SVC__ADDR/DATA/DSN/AUTH/MOCK。 +# 出现即覆盖。任意环境 X 的变量名:SVC__ADDR/DATA/DSN/AUTH/MOCK, +# 以及 INSECURE_LISTEN / ALLOWED_HOSTS(传给进程的 AGENT_SYSTEM_*,旧二进制会忽略)。 # # ════════════════════ 服务模型与登记 ════════════════════ # - 服务名 ^[a-z][a-z0-9-]{0,15}$(保留字不可用);dev=8788 / prod=8787 默认端口, @@ -1206,9 +1207,22 @@ agent_do_start() { fi SVC_EXEC="$exec_args" SVC_PIDCHECK="$ENV_BIN" + local guard_env=() insecure hosts + insecure="$(env_var "$ENV_NAME" INSECURE_LISTEN)" + hosts="$(env_var "$ENV_NAME" ALLOWED_HOSTS)" + [ -n "$insecure" ] && guard_env+=("AGENT_SYSTEM_INSECURE_LISTEN=$insecure") + [ -n "$hosts" ] && guard_env+=("AGENT_SYSTEM_ALLOWED_HOSTS=$hosts") c_info "[$ENV_NAME] 启动:$ENV_BIN serve $exec_args" + if [ -n "$insecure" ] || [ -n "$hosts" ]; then + c_info "[$ENV_NAME] 监听守卫:insecureListen=${insecure:-0} allowedHosts=${hosts:-无}" + fi # 直接 nohup 简单命令:$! 即服务进程本身,pidfile 语义才成立。 - nohup "$ENV_BIN" serve $exec_args >> "$ENV_DIR/svc.log" 2>&1 & + # 守卫变量走环境,不写进 exec=;旧二进制不认识这两个变量,会忽略。 + if [ "${#guard_env[@]}" -gt 0 ]; then + nohup env "${guard_env[@]}" "$ENV_BIN" serve $exec_args >> "$ENV_DIR/svc.log" 2>&1 & + else + nohup "$ENV_BIN" serve $exec_args >> "$ENV_DIR/svc.log" 2>&1 & + fi echo $! > "$ENV_PID" record_state # 健康探测:取 exec 里的 --addr(复用持久化配置时可能与当前派生值不同)。 @@ -2402,7 +2416,11 @@ env_status_detail() { printf ' 数据库 %s\n' "${dbref:-无(内嵌 SQLite 档;绑定: db )}" cfile="$(svc_get conffile)" [ -z "$cfile" ] && cfile="$(printf '%s' "$(svc_get exec)" | sed -n 's/.*--config \([^ ]*\).*/\1/p')" - printf ' 配置文件 %s\n' "${cfile:-无(命令行参数形态; config 绑定)}" ;; + printf ' 配置文件 %s\n' "${cfile:-无(命令行参数形态; config 绑定)}" + printf ' 监听守卫 insecureListen=%s allowedHosts=%s\n' \ + "$(env_var "$ENV_NAME" INSECURE_LISTEN)" \ + "$(env_var "$ENV_NAME" ALLOWED_HOSTS)" + ;; postgres) printf ' 库 %s 用户 %s\n' "$(svc_get dbname)" "$(svc_get user)" printf ' DSN postgresql://%s:***@%s:%s/%s(db dsn %s --reveal 看密码)\n' \