chore: 建立本地稳定开发基线
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.next
|
||||||
|
node_modules
|
||||||
|
backend/venv
|
||||||
|
backend/__pycache__
|
||||||
|
backend/**/__pycache__
|
||||||
|
backend/.env
|
||||||
|
**/.env
|
||||||
|
**/.env.*
|
||||||
|
!**/.env.example
|
||||||
|
backend/xingbang_data
|
||||||
|
backend/logs
|
||||||
|
*.log
|
||||||
|
*.pid
|
||||||
|
docker-compose.override.yml
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# AGENTS.md — mini-OpenClaw 兴邦金租 AI 评审平台
|
||||||
|
|
||||||
|
> 本文件是仓库唯一事实来源,供 Codex / Claude / 其他 AI 编码代理读取。
|
||||||
|
> **先读本文件,再动手;开发全程遵守「改动纪律」,尤其是有序验证命令。**
|
||||||
|
|
||||||
|
## ▶️ 接手当前进度(每次新对话/会话开始时先做,别当新项目从零写)
|
||||||
|
|
||||||
|
> 本文件写的是**规则,不是进度**。你的进度在**代码 + git 工作区 + 会话历史**里,不在本文件里。
|
||||||
|
> 每次会话开始,按顺序对齐"我现在改到哪",再决定动什么 —— **不要**凭 AGENTS.md 脑补项目全貌。
|
||||||
|
|
||||||
|
1. `git status --short` → 看 **未提交的改动 / 已删除的文件**。本项目常有页面级重构(删一批 `src/app/*`、合并进 `*-workbench`),删除了就是用户正在做的整合,别当成"误删"去恢复。
|
||||||
|
2. `git log --oneline -6` → 接到最近提交那条线上(当前主线:兴邦四 Agent v2 / xingbang 工作台整合)。
|
||||||
|
3. 当前处于**_重构进行中**:`src/app/` 下多个独立页正在向 **xingbang-workbench / review-workbench / report-workbench / collateral-workbench / data-access / trajectory** 等合并。**改代码前先确认该页还在不在、已合并到哪里,别对旧页做无效修改。**
|
||||||
|
|
||||||
|
⚠️ 关键惯例:本项目也是「多轮迭代、每步有 `_backup_pre_*` 备份目录」。**改哪里先确认现状,不破坏已跑通逻辑;大改动前默认应该先在你的分支/工作区留能回滚的点。**
|
||||||
|
|
||||||
|
## 项目是什么
|
||||||
|
|
||||||
|
兴邦金租 AI Native 智能评审决策系统(四 Agent:审查 / 风控 risk / 协调 coordination / 报告 report)。前后端分离:
|
||||||
|
|
||||||
|
- `src/` — **Next.js 前端**(默认端口 **3000**),页面/组件在 `src/app/`、`src/components/`
|
||||||
|
- `backend/` — **FastAPI 后端**(默认端口 **8002**),Python + LangChain,工具在 `backend/tools/`、Agent 调度在 `backend/graph/`、API 路由在 `backend/api/`
|
||||||
|
- 关键业务模块:`review_assist.py`(评审提效)、`risk_*`(风控)、`coordination_agent.py`(协调)、`report_agent.py`(报告)、`graph/risk_task.py`,数据在 `backend/backend/xingbang_data/`
|
||||||
|
|
||||||
|
## 启动与验证命令(改动后必跑)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 后端(必须用项目虚拟环境,下同)
|
||||||
|
cd /f/mini-OpenClaw/backend
|
||||||
|
source venv/Scripts/activate # git-bash; Windows CMD 用 venv\Scripts\activate.bat
|
||||||
|
./start_backend.sh # 或 start_backend.bat ; 后端 http://localhost:8002 (docs 在 /docs)
|
||||||
|
# 或直接: uvicorn backend.backend.main:app --port 8002
|
||||||
|
|
||||||
|
# 前端(另开终端)
|
||||||
|
cd /f/mini-OpenClaw
|
||||||
|
npm run dev # 前端 http://localhost:3000
|
||||||
|
|
||||||
|
# 自测(改动相关模块后至少跑相关测试)
|
||||||
|
cd /f/mini-OpenClaw/backend && source venv/Scripts/activate
|
||||||
|
python test_risk_agent_completion.py
|
||||||
|
python test_review_assist.py 2>/dev/null || echo "无该测试,视改动定"
|
||||||
|
# API 自检: curl http://localhost:8002/docs / 或 /api/… 看路由响应
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛑 变更纪律(核心。防止把已跑通的逻辑改坏)
|
||||||
|
|
||||||
|
1. **最小改动**:只改本次任务直接相关的范围。禁止顺手重构、重排、重命名、改格式;看到能优化的代码**先不动**,除非它挡事。
|
||||||
|
2. **改动前先读调用方**:改任何函数/API/工具前,先搜它的全部调用方(`backend/`、`src/` 内 grep),确认改动不影响别的调用方。认不准就退回先问。
|
||||||
|
3. **前后端联动意识**:改后端 API 或字段时,同时确认前端 `src/app/` 对应页(可能已迁移到 workbench 页)是否受影响。**牵一发动全身,先查再改。**
|
||||||
|
4. **改后必跑验证**:见「启动与开发」的命令,跑通再继续;拿不准就还原、只保留最小可验证改动。
|
||||||
|
5. **改完自查 diff**: `git status` + `git diff --stat`,确认没多动无关文件。有"顺手动到/删到"的,**改回或向我确认**,尤其不要误删要保留的页面。
|
||||||
|
|
||||||
|
## 已知坑(务必遵守)
|
||||||
|
|
||||||
|
- **系统代理 127.0.0.1:7890**:后端 `llm`/网络调用会被全局代理干扰,`Connection error / 代理错误` 时用项目自带启动脚本(已自动禁用代理)或 `no_proxy`。别手动留代理变量。
|
||||||
|
- **端口占用**:8002 被占 → `netstat -ano | findstr :8002` + `taskkill /F /PID <PID>`;前端 3000 冲突同理。
|
||||||
|
- **必须用 `backend/venv` 虚拟环境**,别用系统 Python。LlamaIndex/依赖都在这个 venv 里。
|
||||||
|
- **节点 3000 前端是 Next.js**:改页面后不如鉴是 Node build;SSR/客户端组件区别,别引入后端跑不动的代码。
|
||||||
|
|
||||||
|
## 代码风格与目录约定
|
||||||
|
|
||||||
|
- `backend/` 用 Python,`src/` 用 TypeScript/React(Next.js App Router)。
|
||||||
|
- 业务 Agent 各在独立文件(review/risk/coordination/report),新逻辑就近放对应模块,**不要**堆进某个巨大文件。
|
||||||
|
- 重构建议:先把目标拆清(前端页面的整合去向、后端 API 是否仍有调用),再动手删/并,别让旧页"幽灵残留"引用报错。
|
||||||
|
- 提交用中文、一句话说清「改了做什么→结果」;大变化先看 `git status` 确认删的都是该删的。
|
||||||
|
|
||||||
|
## 说明
|
||||||
|
|
||||||
|
- 项目有完整 `ARCHITECTURE.md` / `DEV_*` 文档,遇到"这是什么/怎么拼"先去读,别臆造。
|
||||||
+31
-28
@@ -1,63 +1,66 @@
|
|||||||
# 兴邦金租 AI Native 智能决策系统 - Docker 镜像
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
# ============ Stage 1: Frontend Build ============
|
# ============ Stage 1: Frontend build ============
|
||||||
FROM node:18-alpine AS frontend-builder
|
FROM node:18-bookworm-slim AS frontend-builder
|
||||||
|
|
||||||
WORKDIR /app/frontend
|
WORKDIR /app/frontend
|
||||||
|
|
||||||
# 复制前端依赖文件
|
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
RUN npm install
|
RUN npm ci
|
||||||
|
|
||||||
# 复制前端代码并构建
|
|
||||||
COPY src ./src
|
COPY src ./src
|
||||||
COPY public ./public
|
COPY next-env.d.ts ./
|
||||||
COPY next.config.js ./
|
COPY next.config.mjs ./
|
||||||
COPY tsconfig.json ./
|
COPY postcss.config.mjs ./
|
||||||
COPY tailwind.config.ts ./
|
COPY tailwind.config.ts ./
|
||||||
COPY postcss.config.js ./
|
COPY tsconfig.json ./
|
||||||
|
|
||||||
|
# The stable baseline has no public directory. Keep one in the image so the
|
||||||
|
# runtime copy is deterministic and future static assets have a fixed home.
|
||||||
|
RUN mkdir -p public
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
RUN npm prune --omit=dev
|
||||||
|
|
||||||
# ============ Stage 2: Backend + Runtime ============
|
# ============ Stage 2: Backend + runtime ============
|
||||||
FROM python:3.11-slim
|
FROM python:3.11-slim AS runtime
|
||||||
|
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||||
|
PYTHONUNBUFFERED=1 \
|
||||||
|
PYTHONPATH=/app/backend \
|
||||||
|
NODE_ENV=production
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# 安装系统依赖
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
gcc \
|
gcc \
|
||||||
g++ \
|
g++ \
|
||||||
libpq-dev \
|
libpq-dev \
|
||||||
|
nodejs \
|
||||||
|
npm \
|
||||||
|
postgresql-client \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 复制后端依赖文件
|
|
||||||
COPY backend/requirements.txt ./backend/
|
COPY backend/requirements.txt ./backend/
|
||||||
RUN pip install --no-cache-dir -r backend/requirements.txt
|
RUN pip install --no-cache-dir -r backend/requirements.txt
|
||||||
|
|
||||||
# 复制后端代码
|
|
||||||
COPY backend ./backend
|
COPY backend ./backend
|
||||||
|
|
||||||
# 复制前端构建产物
|
|
||||||
COPY --from=frontend-builder /app/frontend/.next ./frontend/.next
|
COPY --from=frontend-builder /app/frontend/.next ./frontend/.next
|
||||||
COPY --from=frontend-builder /app/frontend/public ./frontend/public
|
COPY --from=frontend-builder /app/frontend/public ./frontend/public
|
||||||
COPY --from=frontend-builder /app/frontend/package.json ./frontend/
|
COPY --from=frontend-builder /app/frontend/package.json ./frontend/package.json
|
||||||
|
COPY --from=frontend-builder /app/frontend/node_modules ./frontend/node_modules
|
||||||
|
|
||||||
# 创建数据目录
|
|
||||||
RUN mkdir -p /app/backend/xingbang_data/reviewers \
|
RUN mkdir -p /app/backend/xingbang_data/reviewers \
|
||||||
/app/backend/xingbang_data/history \
|
/app/backend/xingbang_data/history \
|
||||||
/app/backend/xingbang_data/team_experience \
|
/app/backend/xingbang_data/team_experience \
|
||||||
/app/backend/logs
|
/app/backend/logs
|
||||||
|
|
||||||
# 设置环境变量
|
COPY docker-entrypoint.sh /app/docker-entrypoint.sh
|
||||||
ENV PYTHONPATH=/app/backend
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
|
|
||||||
# 暴露端口
|
|
||||||
EXPOSE 8002 3000
|
|
||||||
|
|
||||||
# 启动脚本
|
|
||||||
COPY docker-entrypoint.sh /app/
|
|
||||||
RUN chmod +x /app/docker-entrypoint.sh
|
RUN chmod +x /app/docker-entrypoint.sh
|
||||||
|
|
||||||
|
EXPOSE 8002 3000
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=120s --retries=3 \
|
||||||
|
CMD node -e "Promise.all([fetch('http://127.0.0.1:3000/'), fetch('http://127.0.0.1:8002/')]).then(rs => process.exit(rs.every(r => r.ok) ? 0 : 1)).catch(() => process.exit(1))"
|
||||||
|
|
||||||
ENTRYPOINT ["/app/docker-entrypoint.sh"]
|
ENTRYPOINT ["/app/docker-entrypoint.sh"]
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
<available_skills>
|
<available_skills>
|
||||||
|
<skill>
|
||||||
|
<name>collateral_verification</name>
|
||||||
|
<description>Explain asset, insurance and credit enhancement evidence and deterministic recovery checks.</description>
|
||||||
|
<location>./backend/skills/collateral_verification/SKILL.md</location>
|
||||||
|
</skill>
|
||||||
<skill>
|
<skill>
|
||||||
<name>get_weather</name>
|
<name>get_weather</name>
|
||||||
<description>获取指定城市的实时天气信息</description>
|
<description>获取指定城市的实时天气信息</description>
|
||||||
@@ -9,4 +14,19 @@
|
|||||||
<description>使用 OpenWeather API 获取指定城市的实时天气信息</description>
|
<description>使用 OpenWeather API 获取指定城市的实时天气信息</description>
|
||||||
<location>./backend/skills/get_weather_open/SKILL.md</location>
|
<location>./backend/skills/get_weather_open/SKILL.md</location>
|
||||||
</skill>
|
</skill>
|
||||||
|
<skill>
|
||||||
|
<name>report-evidence-drafting</name>
|
||||||
|
<description>Draft review-report sections from confirmed project snapshots, deterministic checks and evidence, with explicit missing information.</description>
|
||||||
|
<location>./backend/skills/report_evidence/SKILL.md</location>
|
||||||
|
</skill>
|
||||||
|
<skill>
|
||||||
|
<name>review_coordination</name>
|
||||||
|
<description>Prepare an evidence-based review coordination briefing from an authorized project snapshot.</description>
|
||||||
|
<location>./backend/skills/review_coordination/SKILL.md</location>
|
||||||
|
</skill>
|
||||||
|
<skill>
|
||||||
|
<name>risk-evidence-review</name>
|
||||||
|
<description>Review authorized peer data cards and human rules, then produce evidence-linked pre-submission suggestions for a customer manager.</description>
|
||||||
|
<location>./backend/skills/risk_evidence/SKILL.md</location>
|
||||||
|
</skill>
|
||||||
</available_skills>
|
</available_skills>
|
||||||
+23
-43
@@ -1,58 +1,38 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
xingbang-app:
|
xingbang-app:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
container_name: xingbang-ai-native
|
container_name: mini-openclaw-stable
|
||||||
ports:
|
ports:
|
||||||
- "8002:8002" # 后端 API
|
- "3200:3000" # frontend
|
||||||
- "3000:3000" # 前端 UI
|
- "8002:8002" # backend API used by the browser client
|
||||||
environment:
|
environment:
|
||||||
- DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}
|
DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-}
|
||||||
- DEEPSEEK_MODEL=${DEEPSEEK_MODEL:-deepseek-chat}
|
DEEPSEEK_MODEL: ${DEEPSEEK_MODEL:-deepseek-chat}
|
||||||
- DEEPSEEK_BASE_URL=${DEEPSEEK_BASE_URL:-https://api.deepseek.com}
|
DEEPSEEK_BASE_URL: ${DEEPSEEK_BASE_URL:-https://api.deepseek.com}
|
||||||
- ERP_DB_HOST=${ERP_DB_HOST}
|
ERP_DB_HOST: ${ERP_DB_HOST:-}
|
||||||
- ERP_DB_PORT=${ERP_DB_PORT:-5432}
|
ERP_DB_PORT: ${ERP_DB_PORT:-5432}
|
||||||
- ERP_DB_NAME=${ERP_DB_NAME}
|
ERP_DB_NAME: ${ERP_DB_NAME:-}
|
||||||
- ERP_DB_USER=${ERP_DB_USER}
|
ERP_DB_USER: ${ERP_DB_USER:-}
|
||||||
- ERP_DB_PASSWORD=${ERP_DB_PASSWORD}
|
ERP_DB_PASSWORD: ${ERP_DB_PASSWORD:-}
|
||||||
- ERP_DB_SSL_MODE=${ERP_DB_SSL_MODE:-require}
|
ERP_DB_SSL_MODE: ${ERP_DB_SSL_MODE:-require}
|
||||||
|
RISK_AGENT_BACKEND_URL: ${RISK_AGENT_BACKEND_URL:-http://127.0.0.1:8002}
|
||||||
volumes:
|
volumes:
|
||||||
- xingbang-data:/app/backend/xingbang_data
|
- xingbang-data:/app/backend/xingbang_data
|
||||||
- xingbang-logs:/app/backend/logs
|
- xingbang-logs:/app/backend/logs
|
||||||
secrets:
|
|
||||||
- erp_db_password
|
|
||||||
- deepseek_api_key
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
healthcheck:
|
||||||
- xingbang-network
|
test:
|
||||||
|
- CMD
|
||||||
# (可选)如果需要本地测试数据库
|
- node
|
||||||
# postgres:
|
- -e
|
||||||
# image: postgres:15-alpine
|
- "Promise.all([fetch('http://127.0.0.1:3000/'), fetch('http://127.0.0.1:8002/')]).then(rs => process.exit(rs.every(r => r.ok) ? 0 : 1)).catch(() => process.exit(1))"
|
||||||
# container_name: xingbang-erp-mock
|
interval: 30s
|
||||||
# environment:
|
timeout: 5s
|
||||||
# - POSTGRES_DB=xingbang_erp
|
start_period: 120s
|
||||||
# - POSTGRES_USER=readonly_user
|
retries: 3
|
||||||
# - POSTGRES_PASSWORD_FILE=/run/secrets/erp_db_password
|
|
||||||
# volumes:
|
|
||||||
# - postgres-data:/var/lib/postgresql/data
|
|
||||||
# networks:
|
|
||||||
# - xingbang-network
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
xingbang-data:
|
xingbang-data:
|
||||||
xingbang-logs:
|
xingbang-logs:
|
||||||
# postgres-data:
|
|
||||||
|
|
||||||
networks:
|
|
||||||
xingbang-network:
|
|
||||||
driver: bridge
|
|
||||||
|
|
||||||
secrets:
|
|
||||||
erp_db_password:
|
|
||||||
file: ./secrets/erp_db_password.txt
|
|
||||||
deepseek_api_key:
|
|
||||||
file: ./secrets/deepseek_api_key.txt
|
|
||||||
|
|||||||
+29
-18
@@ -1,24 +1,35 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
set -e
|
set -Eeuo pipefail
|
||||||
|
|
||||||
echo "🚀 启动兴邦金租 AI Native 智能决策系统"
|
echo "Starting mini OpenClaw"
|
||||||
|
|
||||||
# 等待 ERP 数据库就绪(如果配置了)
|
# An ERP connection is optional for the stable demo. If it is configured,
|
||||||
if [ ! -z "$ERP_DB_HOST" ]; then
|
# wait for it before starting the application; otherwise start immediately.
|
||||||
echo "⏳ 等待 ERP 数据库连接..."
|
if [[ -n "${ERP_DB_HOST:-}" ]]; then
|
||||||
until pg_isready -h $ERP_DB_HOST -p $ERP_DB_PORT -U $ERP_DB_USER; do
|
if command -v pg_isready >/dev/null 2>&1; then
|
||||||
echo "数据库未就绪,2秒后重试..."
|
echo "Waiting for ERP database at ${ERP_DB_HOST}:${ERP_DB_PORT:-5432}..."
|
||||||
sleep 2
|
until pg_isready -h "${ERP_DB_HOST}" -p "${ERP_DB_PORT:-5432}" -U "${ERP_DB_USER:-}" >/dev/null 2>&1; do
|
||||||
done
|
sleep 2
|
||||||
echo "✅ ERP 数据库已连接"
|
done
|
||||||
|
echo "ERP database is ready"
|
||||||
|
else
|
||||||
|
echo "pg_isready is unavailable; skipping ERP readiness check"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 启动后端(后台)
|
echo "Starting backend on port 8002"
|
||||||
echo "🔧 启动后端服务 (端口 8002)..."
|
python /app/backend/app.py &
|
||||||
cd /app/backend
|
backend_pid=$!
|
||||||
python app.py &
|
|
||||||
|
|
||||||
# 启动前端(前台)
|
echo "Starting frontend on port 3000"
|
||||||
echo "🌐 启动前端服务 (端口 3000)..."
|
|
||||||
cd /app/frontend
|
cd /app/frontend
|
||||||
npm start
|
npm start -- -H 0.0.0.0 -p 3000 &
|
||||||
|
frontend_pid=$!
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
kill "${frontend_pid}" "${backend_pid}" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
trap cleanup TERM INT EXIT
|
||||||
|
|
||||||
|
# Stop the container if either service exits; Docker can then restart it.
|
||||||
|
wait -n "${backend_pid}" "${frontend_pid}"
|
||||||
|
|||||||
Reference in New Issue
Block a user