# seshat **Repository Path**: agent_26/seshat ## Basic Information - **Project Name**: seshat - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: fix/ranking_list_2026_10_29 - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-11-02 - **Last Updated**: 2026-11-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # content-seshat 面向企业上线的小说本地化改编与改编质检平台。 架构基线:[`docs/content-seshat-architecture.md`](docs/content-seshat-architecture.md)(v0.7)。 偏离基线的决定记录在 [`docs/adr/`](docs/adr/)。 ## 当前进度 **阶段 0 · 第一个可运行增量**。已交付的是"底座",不含业务功能: - Monorepo 与 `web` / `business-api` / `agent-api` 三个服务骨架 - 分层目录 + 依赖边界检查(Python `import-linter` ×2、前端 `eslint-plugin-boundaries`) - 配置加载(`APP_ENV` 分环境、prod 必填校验、密钥 `SecretStr`) - 健康检查 `/healthz`(liveness,不查依赖)、`/readyz`(真查 PostgreSQL + Redis)、`/version` - 结构化日志与密钥脱敏 - 飞书登录、角色权限、用户组与飞书部门快照的数据库表结构(12 张,`business` schema) - 权限键授权模型(ADR 0013):闸门判 `cs.admin` / `cs.manager` 两个权限键而不是判角色 - 路由权限后台可配(ADR 0017):`permission_key.route_pattern` 决定哪个路径要哪个键,不用发版 - 业务管理后台 `/manager`:成员、用户组、角色与权限三个页面 + `/api/manager/*` 全套接口 - 三个多阶段 Dockerfile、开发环境 compose、Helm 基础模板(4 套 values) - GitLab CI 与单元 / 集成测试 **尚未实现**(后续增量):飞书 OAuth 登录流程、RBAC 判定、项目与文档、 Run/Job/持久化 Runner、SSE/AG-UI、LangGraph、Skill、质检与本地化。 `agent-api` 的 `RUNNER_ENABLED` 目前只是配置回显,Runner 本身还没写; 启动日志里会带 `runner_implemented=false`,不要误读为"已在领任务"。 ## 三个服务 | 服务 | 目录 | 容器内端口 | 本地宿主端口 | 职责 | |---|---|---|---|---| | web | `apps/web` | 3000 | 3000 | Next.js 页面 | | business-api | `services/business-api` | 8080 | **18080** | 业务服务 + BFF:飞书登录、RBAC(权限键)、用户组、项目、文档元数据、业务审计 | | agent-api | `services/agent-api` | 8000 | 18000 | Agent 模块化单体:Run / SSE / LangGraph / Runner / 旁路 Job | 宿主端口 18080 而不是 8080,是因为本机 8080 被容器 `tei-bge-m3` 占用(ADR 0003 第 4 条)。 容器内端口与 Helm 里的 `containerPort` 严格按基线,没有改。 架构硬约束(基线 15.2 节): - 只有这三个应用服务,首版不拆独立 Worker / Skill 服务 / 回译服务。 - Web 的业务请求走 `business-api`;拿到短期 Agent Token 后 Run/SSE 才直连 `agent-api`。 - 飞书 OAuth / token / 文档客户端**只允许**存在于 `business-api`。 ## 环境要求 | 工具 | 版本 | 说明 | |---|---|---| | Python | 3.13 | `requires-python = ">=3.13,<3.14"` | | uv | 0.11.2 | Python 包管理与 workspace | | Node | 22 | | | pnpm | 11.7.0 | | | Docker | 29+ | 含 compose v2 | | helm | 4.x | 仅部署与 `make helm-lint` 需要 | 中间件复用本机已在运行的容器(ADR 0003 第 5 条): | 中间件 | 地址 | 说明 | |---|---|---| | PostgreSQL | `127.0.0.1:5432`(容器 `pg17`,账号 postgres/postgres) | 独立库 `content-seshat`,内含 `business` / `agent` / `agent_checkpoint` 三个 schema | | Redis | `127.0.0.1:6379`(容器 `redis8`,无密码) | `db=1` 归 business-api,`db=2` 归 agent-api | 本机没有这两个容器时:`make compose-up-middleware` 会起一套(端口错开到 15432 / 16379), 然后把 `.env.dev` 里的连接串改过去。 ## 本地启动 ### 1. 安装依赖 ```bash make setup # uv sync --all-packages + pnpm install + make hooks ``` `make hooks` 会把本机的 `core.hooksPath` 指到仓库里的 `.githooks/`, 提交前多一道 `.env.example` / `.env.dev` 的 key 一致性检查(见 CONTRIBUTING.md)。 不想启用就单独跑 `uv sync --all-packages` 与 `pnpm install`。 ### 2. 准备环境变量 ```bash cp services/business-api/.env.example services/business-api/.env.dev cp services/agent-api/.env.example services/agent-api/.env.dev cp apps/web/.env.example apps/web/.env.dev ``` 按注释填值。真实 `.env.*` 已被 `.gitignore` 覆盖,**不要提交**。 密钥生成:`openssl rand -base64 32`。 配置加载优先级(基线第 5 节):系统环境变量 / Secret > `.env.{APP_ENV}` > 代码默认值。 三个环境都读 `.env.{APP_ENV}`;`APP_ENV=prod` 时缺少必填项直接启动失败。 两个 Python 服务的 `.env.test` / `.env.prod` 随镜像发布(2026-09 决策):它们入 Git, Dockerfile 用 `COPY services//.env.* ./` 拷到 WORKDIR,部署时只需给容器设 `APP_ENV`。 已知代价:能 pull 镜像或读仓库的人即可拿到其中凭证,轮换凭证需重新构建发布。 `apps/web` 不走这条路 —— `NEXT_PUBLIC_*` 是 `next build` **构建期**内联的, 且 `output: "standalone"` 运行时不会重新执行 `next.config.ts`,只能用 `--build-arg` 传。 ### 3. 建库建表 ```bash make db-create # 在 pg17 里创建 content-seshat 空库(只建库,不建表) ``` 表结构和内置 Skill 数据**由研发手工执行**:把 `database/schema/business/*.sql`(13 个) 与 `database/schema/agent/*.sql`(16 个)按序号贴进 DMS 点执行,再贴一次 `database/seed/*.sql`。详见 [`database/README.md`](database/README.md)。 `schema/{business,agent}` 是**完整建表快照**(一表一文件,只有 `create`,可重复执行), 新库贴它。给已有库升级的 `alter` / 数据回填在 `database/schema/change/` 下, 按日期命名,**新库不要执行**。 **所有 SQL 都是研发在 DMS 手工执行,没有任何自动化入口**(ADR 0011):没有 alembic、 没有 `make db-upgrade`、没有启动时迁移或播种、没有 entrypoint / Helm hook / CI 会跑 `database/**/*.sql`。改了这些文件,库里不会自己变。 唯一例外是 `make test-integration`:它建一个随机命名的临时库、灌 schema SQL、 测完 `drop database`,碰不到任何人在用的库。 ### 4. 启动服务 三个终端分别跑(改代码即时生效): ```bash make dev-business-api # http://127.0.0.1:18080 make dev-agent-api # http://127.0.0.1:18000 make dev-web # http://127.0.0.1:3000 ``` 或者用容器(更接近生产,但改代码要重新 build): ```bash make compose-up make compose-logs make compose-down ``` ### 5. 验证 ```bash make smoke # 三个服务的健康检查 + X-Request-ID 透传 ``` 期望输出里 `business-api /readyz` 与 `agent-api /readyz` 都是 `http=200` 且 `ready: true`。 如果 `ready: false`,看 `checks` 数组里哪个依赖挂了——错误摘要会写明原因, 且不会泄漏连接串密码。 手工看几个端点: ```bash curl -s http://127.0.0.1:18080/healthz # liveness,永远 200 curl -s http://127.0.0.1:18080/readyz | jq # readiness,依赖挂了返回 503 curl -s http://127.0.0.1:18080/version | jq # 版本与 git sha open http://127.0.0.1:18080/docs # OpenAPI 文档 ``` ## 常用命令 ```bash make help # 全部可用 target make lint # ruff + eslint + tsc make format # ruff 自动修复 make boundaries # 依赖边界检查(含"规则是否静默失效"的自检) make test # 全部单元测试(4 组) make test-integration # 需要真实 PostgreSQL make ci # CI 门禁的完整集合 make verify # ci + 集成测试 make docker-build # 构建三个镜像 make helm-lint # 四套 values 的 helm lint make helm-template # 渲染 prod 模板 make observability-up # 本地 Prometheus(:19090)+ Grafana(:13000) make observability-down ``` `/metrics` 由 `business-api` 与 `agent-api` 各自暴露(ADR 0015),挂在根路径 —— 不在 Ingress 转发的 `/api`、`/agent` 两个前缀下,公网打不到,但**集群内无鉴权**。 本地要让容器抓到宿主进程,两个服务必须绑 0.0.0.0: ```bash make dev-business-api DEV_HOST=0.0.0.0 make dev-agent-api DEV_HOST=0.0.0.0 ``` ## 目录结构 ``` apps/web/ Next.js。src/{app,features,components,lib} services/business-api/ app/{api,application,domain,infrastructure,middleware,config} services/agent-api/ 同上,另加 {runtime,jobs,skills,tools,events} packages/contracts/ 跨服务 DTO / 事件 / JSON Schema,零服务依赖 packages/infrastructure-kit/ DB / Redis / 日志 / ASGI 低层封装,无业务逻辑 database/ schema SQL(唯一事实源,研发在 DMS 手工执行) database/schema/{business,agent}/ 完整建表快照,一表一文件,新库贴它 database/schema/change/ 发版变更语句(给已有库升级),日期前缀命名 database/seed/ 系统角色与内置 Skill 的播种 SQL deploy/docker/ 三个多阶段 Dockerfile deploy/compose/ 开发环境 compose deploy/helm/ Chart + dev/test/prod values tests/ 跨切面测试,见 tests/README.md scripts/ 冒烟与边界自检脚本 docs/adr/ 架构决策记录 ``` 依赖方向(基线 3.1 节,CI 强制): ``` api → application → domain ← infrastructure graphs → subgraphs → nodes → states web: app → features/*(公开入口) → lib ``` `app/main.py` 是唯一的 composition root —— 只有它能同时看到 config、infrastructure、 application 和 api。其他任何层 import `infrastructure` 都会被 CI 拦下。 ## 提交规范 见 [`CONTRIBUTING.md`](CONTRIBUTING.md)。分支从 `main` 拉出,走 Merge Request, 不直接推 `main`。 ## 排查提示 **`/readyz` 返回 503。** 看响应体的 `checks`:`postgres` 报 `InvalidCatalogNameError` 说明库没建(`make db-create`);`redis` 报 `ConnectionError` 说明 `redis8` 容器没起。 **时间差了 8 小时。** 所有时间列是 UTC。`psql` 显示受会话 `TimeZone` 影响, 而本机 `pg17` 容器带的是 `PGTZ=Asia/Shanghai`。比对前先 `set timezone='UTC'`。 **改了 `.env.dev` 但没生效。** `APP_ENV` 决定读哪个文件;进程环境变量优先级更高, 检查有没有在 shell 里 export 过同名变量。前端还要注意 `NEXT_PUBLIC_*` 是 **构建期**内联的,容器镜像里的值改运行时环境变量无效。 **前端边界规则好像不生效。** 跑 `./scripts/verify-frontend-boundaries.sh`。 `eslint-plugin-boundaries` 有多种"配了但静默失效"的方式,只跑 `eslint` 看不出来。