From aadc8d0115e7024976bf1e5c4ef545154d9b95a3 Mon Sep 17 00:00:00 2001 From: ThearchyHelios Date: Wed, 21 Oct 2026 08:13:58 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AD=E6=96=87=20README=20=E7=A7=BB?= =?UTF-8?q?=E5=88=B0=20README.zh-CN.md=EF=BC=88=E5=86=85=E5=AE=B9=E4=B8=8D?= =?UTF-8?q?=E6=94=B9=EF=BC=8C=E9=A1=B6=E4=B8=8A=E5=8A=A0=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=E5=88=87=E6=8D=A2=EF=BC=89=EF=BC=8C=E4=B8=AD=E6=96=87=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E9=87=8C=E6=8C=87=E5=90=91=20README=20=E7=AB=A0?= =?UTF-8?q?=E8=8A=82=E7=9A=84=E5=9C=B0=E6=96=B9=E6=94=B9=E6=8C=87=E4=B8=AD?= =?UTF-8?q?=E6=96=87=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git mv 保留历史;顶上一行「[English](README.md) | 简体中文」,英文版随后单独提交。 改指 README.zh-CN.md 的:报错文字(cluster/guard.py、cluster/version.py、db/base.py 两处)、.env.example 三处注释、 scripts/prod.sh 用法说明、scripts/test-postgres.sh 注释、「口径同 README「哪些角色看得到原值」」的四处代码注释 (terms.ts 两处、DataSourcesTab.tsx、check-manage.mjs),deploy/README.md 里三处「仓库 README」写成指向 ../README.zh-CN.md 对应章节的链接。 没改的:deploy/deploy.sh 四处「README 的常见问题」「README「用 PostgreSQL」」和 deploy/agentlab.env 117 行——离线包里和 deploy.sh 放在一起的 README.md 就是 deploy/README.md,那几句指的正是它的常见问题、用 PostgreSQL 两节; deploy/README.md 第 16 行文件清单说的是它自己;version.py、runner.py 文档串里「以前 README 写…」是旧事的叙述。 验收:相关后端测试 117 通过、7 跳过;tsc -b、check-copy 通过。 --- .env.example | 6 +++--- README.md => README.zh-CN.md | 2 ++ backend/app/cluster/guard.py | 2 +- backend/app/cluster/version.py | 2 +- backend/app/db/base.py | 4 ++-- deploy/README.md | 6 +++--- frontend/src/lib/terms.ts | 4 ++-- frontend/src/pages/DataSourcesTab.tsx | 2 +- scripts/check-manage.mjs | 2 +- scripts/prod.sh | 2 +- scripts/test-postgres.sh | 2 +- 11 files changed, 18 insertions(+), 16 deletions(-) rename README.md => README.zh-CN.md (99%) diff --git a/.env.example b/.env.example index a32e27f5..2f2fb9b9 100644 --- a/.env.example +++ b/.env.example @@ -12,7 +12,7 @@ # ---- 应用库 ---- # 不设:数据目录里的 SQLite(data/agentlab.db,断点 data/checkpoints.db),单机单进程。 # 设成 PostgreSQL 时整个应用库和断点都放进去(要 [postgres] 额外依赖,environment.yml 已带);数据目录照样要有。 -# 从现有的 SQLite 数据目录搬过去:python -m app.db copy-to-postgres data(README「用 PostgreSQL」) +# 从现有的 SQLite 数据目录搬过去:python -m app.db copy-to-postgres data(README.zh-CN.md「用 PostgreSQL」) # AGENTLAB_DATABASE_URL=postgresql+asyncpg://agentlab:密码@127.0.0.1:5432/agentlab # 要 SSL 时加 ?sslmode=require(verify-ca / verify-full 同理);证书文件用环境变量 PGSSLROOTCERT / PGSSLCERT / PGSSLKEY,不写在地址里 # AGENTLAB_DATABASE_URL=postgresql+asyncpg://agentlab:密码@db.example.com:5432/agentlab?sslmode=verify-full @@ -31,7 +31,7 @@ # 一条连接用多久换新的(秒),缺省 1800 # AGENTLAB_DB_POOL_RECYCLE=1800 -# ---- PgBouncer(README「多进程」的「直连与 PgBouncer」)---- +# ---- PgBouncer(README.zh-CN.md「多进程」的「直连与 PgBouncer」)---- # 直连地址(写法同 AGENTLAB_DATABASE_URL):进程间通知、跨进程锁、断点这几样依赖会话状态的连接走它,普通查询走上面的地址。 # 不设就全用 AGENTLAB_DATABASE_URL(直连 PostgreSQL、或 PgBouncer 的会话模式时都不用设) # AGENTLAB_DATABASE_DIRECT_URL=postgresql+asyncpg://agentlab:密码@db.example.com:5432/agentlab @@ -39,7 +39,7 @@ # 这时必须另给上面的直连地址,没给就拒绝启动 # AGENTLAB_DB_PGBOUNCER=0 -# ---- 多进程(README「多进程」;只有应用库是 PostgreSQL 时才能大于 1)---- +# ---- 多进程(README.zh-CN.md「多进程」;只有应用库是 PostgreSQL 时才能大于 1)---- # 几个工作进程,缺省 1(scripts/prod.sh、Docker 的入口按它起;dev.sh 总是一个进程、热重载) # AGENTLAB_WORKERS=1 # 每个进程在库里登记、续租约:租约多长(秒,缺省 30)、隔多久续一次(秒,缺省 5)。租约到期没续上算进程没了,别的进程接手它的活 diff --git a/README.md b/README.zh-CN.md similarity index 99% rename from README.md rename to README.zh-CN.md index 83b4ae0c..2548eab9 100644 --- a/README.md +++ b/README.zh-CN.md @@ -1,3 +1,5 @@ +[English](README.md) | 简体中文 + # AgentLab **可视化 Agent 编排实验台**——在画布上定义工作流,运行时逐节点观察执行过程, diff --git a/backend/app/cluster/guard.py b/backend/app/cluster/guard.py index 355b8a94..7873aa41 100644 --- a/backend/app/cluster/guard.py +++ b/backend/app/cluster/guard.py @@ -22,7 +22,7 @@ LOCK_FILE = ".agentlab.lock" SINGLE_PROCESS = ("应用库是 SQLite 时只支持单进程:数据目录 {dir} 已经被另一个 AgentLab 进程使用({hint})。" "SQLite 不能多进程部署——不要给 uvicorn 加 --workers、不要让两个服务指着同一个数据目录;" - "要多进程,把应用库换成 PostgreSQL(AGENTLAB_DATABASE_URL,见 README「用 PostgreSQL」「多进程」)") + "要多进程,把应用库换成 PostgreSQL(AGENTLAB_DATABASE_URL,见 README.zh-CN.md「用 PostgreSQL」「多进程」)") class SingleProcessOnly(RuntimeError): diff --git a/backend/app/cluster/version.py b/backend/app/cluster/version.py index be3df40b..8f22b952 100644 --- a/backend/app/cluster/version.py +++ b/backend/app/cluster/version.py @@ -208,7 +208,7 @@ def _naive(moment: Any) -> Any: def _message(peers: list[dict[str, Any]], *, beating: set[str] | None = None) -> str: listed = ";".join(_describe(p, beating) for p in peers) return (f"库里还有 {len(peers)} 个版本不同的 AgentLab 进程活着:{listed}。本进程是代码 {code_version()}、库结构 " - f"{schema_version()}。不支持新旧版本同时运行:先停掉这些进程再启动新版本(升级步骤见 README「多进程」的「升级」)") + f"{schema_version()}。不支持新旧版本同时运行:先停掉这些进程再启动新版本(升级步骤见 README.zh-CN.md「多进程」的「升级」)") def check_rows(rows: list[Any], now: Any) -> None: diff --git a/backend/app/db/base.py b/backend/app/db/base.py index 5369bd15..53a53a8b 100644 --- a/backend/app/db/base.py +++ b/backend/app/db/base.py @@ -308,13 +308,13 @@ def check_pgbouncer() -> None: if not settings.database_direct_url: raise RuntimeError("AGENTLAB_DB_PGBOUNCER=1(应用库地址是 PgBouncer 的事务模式)时要另给 AGENTLAB_DATABASE_DIRECT_URL:" "进程间通知(LISTEN)、跨进程的锁(会话级咨询锁)、断点库要直连 PostgreSQL(或 PgBouncer 的会话模式)。" - "见 README「多进程」里的「直连与 PgBouncer」") + "见 README.zh-CN.md「多进程」里的「直连与 PgBouncer」") if _endpoint(settings.database_direct_url) == _endpoint(settings.database_url): from app.db.urls import describe raise RuntimeError(f"AGENTLAB_DATABASE_DIRECT_URL 和 AGENTLAB_DATABASE_URL 指着同一个地址({describe(settings.database_url)}):" "AGENTLAB_DB_PGBOUNCER=1 说应用库地址是 PgBouncer 的事务模式,直连地址要绕过它、直接连 PostgreSQL" - "(或者 PgBouncer 的会话模式那个端口)。见 README「多进程」里的「直连与 PgBouncer」") + "(或者 PgBouncer 的会话模式那个端口)。见 README.zh-CN.md「多进程」里的「直连与 PgBouncer」") def _endpoint(url: str) -> tuple[str, int]: diff --git a/deploy/README.md b/deploy/README.md index a31a944c..fb08b0db 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -250,8 +250,8 @@ docker run --rm --user 10001:10001 -v "$(pwd)/data:/data" --env-file agentlab.en **多进程。** 换成 PostgreSQL 之后可以在容器里起几个工作进程:`agentlab.env` 里加 `AGENTLAB_WORKERS=4`(缺省 1)再 `./deploy.sh upgrade`。几个进程共用一个端口,各自在库里登记、续租约;一个进程没了,别的进程在租约到期后接手它留下的运行、 -问数据和后台任务(规矩见仓库 README「多进程」)。SQLite 时设大于 1 会启动失败(照实报错:SQLite 只支持单进程)。 -几台机器、几个容器指着同一个库也行,但数据目录要放在共享存储上、每台挂在同一个路径,限制见仓库 README「多进程」。 +问数据和后台任务(规矩见仓库 [README.zh-CN.md](../README.zh-CN.md#多进程)「多进程」)。SQLite 时设大于 1 会启动失败(照实报错:SQLite 只支持单进程)。 +几台机器、几个容器指着同一个库也行,但数据目录要放在共享存储上、每台挂在同一个路径,限制见仓库 [README.zh-CN.md](../README.zh-CN.md#多进程)「多进程」。 内置 PostgreSQL 是直连(中间没有 PgBouncer),多进程时什么都不用另设(不用 `AGENTLAB_DATABASE_DIRECT_URL`;设了它、或者 `AGENTLAB_DB_PGBOUNCER=1`,deploy.sh 照实拦下)。库还是 SQLite 时 `AGENTLAB_WORKERS` 大于 1,deploy.sh 在起容器之前就拦下。新旧版本的进程不能同时 @@ -317,7 +317,7 @@ cp ../agentlab-<旧版本>-linux-__AGENTLAB_ARCH__/agentlab.env . # 沿用原 - **默认不开登录。** 不开登录时,同一网络里打得开页面的人都能用它:跑工作流、花你配的模型额度、 读你接入的数据源、在沙箱里执行代码,审批记的是各自填的署名、未经核实。只在信得过的网络里这样用。 多人使用请开登录:`agentlab.env` 里设 `AGENTLAB_AUTH_MODE=local`(账号密码)或 `oidc`(单点登录), - `./deploy.sh install` 生效,第一次打开登录页时建第一个管理员。角色、权限和遮罩的边界见仓库 README 的「身份与权限」。 + `./deploy.sh install` 生效,第一次打开登录页时建第一个管理员。角色、权限和遮罩的边界见仓库 [README.zh-CN.md](../README.zh-CN.md#身份与权限) 的「身份与权限」。 - 忘了管理员密码:`docker exec -it agentlab python -m app.auth reset-admin`(不给 `--password` 时随机生成并打印一次)。 - 用防火墙限制能访问端口的来源。注意 Docker 发布的端口会绕过 ufw 的默认规则,要么把 `BIND_ADDR` 设成具体网卡的地址或 `127.0.0.1`,要么在 `DOCKER-USER` 链里加规则。 diff --git a/frontend/src/lib/terms.ts b/frontend/src/lib/terms.ts index b6149d7f..990e4d6b 100644 --- a/frontend/src/lib/terms.ts +++ b/frontend/src/lib/terms.ts @@ -398,7 +398,7 @@ export const EVIDENCE_TEXT = { /** 遮没遮核对不了、不显示的值(快照、取值链上的产出读不出来):和「已遮罩」分开,数据源可能根本没设遮罩 */ unverifiedValue: '无法核对', /** - * 面板底部:被遮罩的列 + 遮罩对谁是边界(用户拍板写明;口径同 README「哪些角色看得到原值」)。搭建者、管理员和未开启登录时 + * 面板底部:被遮罩的列 + 遮罩对谁是边界(用户拍板写明;口径同 README.zh-CN.md「哪些角色看得到原值」)。搭建者、管理员和未开启登录时 * 的所有人:只减少暴露,完整快照和原始工件中仍为原值;开了登录的使用者:是边界,原值不给 */ maskNote: (cols: string[]) => @@ -6304,7 +6304,7 @@ export const TOOL_ENDPOINT_TEXT = { } /** - * 数据源「遮罩的列」下面那句边界说明,口径同 README「哪些角色看得到原值」:对开了登录的使用者是边界(查询结果按派生遮罩 + * 数据源「遮罩的列」下面那句边界说明,口径同 README.zh-CN.md「哪些角色看得到原值」:对开了登录的使用者是边界(查询结果按派生遮罩 * 处理后才给,工具快照原文、运行事件里的结果预览不给,工件按白名单给);对搭建者、管理员,以及未开启登录时的所有人, * 只减少暴露 */ diff --git a/frontend/src/pages/DataSourcesTab.tsx b/frontend/src/pages/DataSourcesTab.tsx index fdcd0bd5..a5618571 100644 --- a/frontend/src/pages/DataSourcesTab.tsx +++ b/frontend/src/pages/DataSourcesTab.tsx @@ -1724,7 +1724,7 @@ function useSchemaColumns(sourceId: string | undefined, active: boolean) { /** * 遮罩的列:列名一个个加成标签,可以从已探查的结构里挑,也可以直接输。 - * 用户拍板写明遮罩的边界,口径同 README「哪些角色看得到原值」:对开了登录的使用者是边界;对搭建者、管理员,以及未开启 + * 用户拍板写明遮罩的边界,口径同 README.zh-CN.md「哪些角色看得到原值」:对开了登录的使用者是边界;对搭建者、管理员,以及未开启 * 登录时的所有人,只减少暴露(MASK_BOUNDARY_TEXT) */ function MaskColumnsInput({ id, sourceId, synced, value, onChange }: { diff --git a/scripts/check-manage.mjs b/scripts/check-manage.mjs index 16feed64..3749051f 100644 --- a/scripts/check-manage.mjs +++ b/scripts/check-manage.mjs @@ -1628,7 +1628,7 @@ await section('数据 · 遮罩列(证据面板的 mask_columns)', async () && await field.locator('[data-mask-chip="phone"]').count() === 1) const boundary = await field.locator('[data-mask-boundary]').innerText().catch(() => '') check('写明遮罩只减少暴露、不是安全边界', boundary.includes('遮罩只减少暴露,不是安全边界'), boundary) - // 口径同 README「哪些角色看得到原值」:未开启登录时对谁都只减少暴露,开了登录对使用者是边界——两头都说清 + // 口径同 README.zh-CN.md「哪些角色看得到原值」:未开启登录时对谁都只减少暴露,开了登录对使用者是边界——两头都说清 check('……并写明开启登录后对使用者是边界', await field.locator('[data-mask-boundary]').getAttribute('data-mask-boundary') === 'off' && boundary.includes('开启登录后,遮罩对使用者是边界'), boundary) check('高级连接参数里不再另摆一个遮罩的文本框(只有这一处)', await ed.locator('#ds-adv-mask_columns').count() === 0) diff --git a/scripts/prod.sh b/scripts/prod.sh index c3e9be81..521ccc88 100755 --- a/scripts/prod.sh +++ b/scripts/prod.sh @@ -18,7 +18,7 @@ usage() { 默认只在 frontend/dist 不存在、或者比前端源码旧的时候才构建。 数据目录照后端配置:默认是仓库下的 data/,用环境变量 AGENTLAB_DATA_DIR 改。 -应用库是 SQLite(缺省)时只能单进程;换成 PostgreSQL 之后可以多进程(README「多进程」)。 +应用库是 SQLite(缺省)时只能单进程;换成 PostgreSQL 之后可以多进程(README.zh-CN.md「多进程」)。 USAGE } diff --git a/scripts/test-postgres.sh b/scripts/test-postgres.sh index f93dbffd..cf1e47f9 100755 --- a/scripts/test-postgres.sh +++ b/scripts/test-postgres.sh @@ -48,6 +48,6 @@ echo "测试库:127.0.0.1:${PORT}/${DB}(容器 ${NAME},结束后删除)" cd "$ROOT/backend" args=("$@") [ ${#args[@]} -eq 0 ] && args=(-n auto) -# 同 README「开发与验证」:环境里的密钥不带进测试 +# 同 README.zh-CN.md「开发与验证」:环境里的密钥不带进测试 env -u ANTHROPIC_API_KEY -u ANTHROPIC_BASE_URL -u ANTHROPIC_AUTH_TOKEN -u OPENAI_API_KEY \ "$PY" -m pytest "${args[@]}"