合入:README 默认改成英文版(README.md,中文版的完整翻译),中文版独立成 README.zh-CN.md(内容不变),两边顶上互相链接;中文提示里指向 README 章节的地方改指中文版

This commit is contained in:
ThearchyHelios
2026-10-21 08:55:03 +08:00
12 changed files with 2934 additions and 1014 deletions
+3 -3
View File
@@ -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)。租约到期没续上算进程没了,别的进程接手它的活
+1527 -998
View File
File diff suppressed because it is too large Load Diff
+1391
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -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):
+1 -1
View File
@@ -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:
+2 -2
View File
@@ -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]:
+3 -3
View File
@@ -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` 链里加规则。
+2 -2
View File
@@ -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「哪些角色看得到原值」:对开了登录的使用者是边界(查询结果按派生遮罩
* 处理后才给,工具快照原文、运行事件里的结果预览不给,工件按白名单给);对搭建者、管理员,以及未开启登录时的所有人,
* 只减少暴露
*/
+1 -1
View File
@@ -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 }: {
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -18,7 +18,7 @@ usage() {
默认只在 frontend/dist 不存在、或者比前端源码旧的时候才构建。
数据目录照后端配置:默认是仓库下的 data/,用环境变量 AGENTLAB_DATA_DIR 改。
应用库是 SQLite(缺省)时只能单进程;换成 PostgreSQL 之后可以多进程(README「多进程」)。
应用库是 SQLite(缺省)时只能单进程;换成 PostgreSQL 之后可以多进程(README.zh-CN.md「多进程」)。
USAGE
}
+1 -1
View File
@@ -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[@]}"