已合并
fix: missing studio module #219
fix: missing studio module #219
已合并
陈卉创建于 5月7日
19 个文件变更+119-96
@@ -69,10 +69,10 @@ agent-runtime/
69 69 
70## 环境要求70## 环境要求
71 71 
72-* python>=3.11.472+- python>=3.11.4
73-* uv>=0.25.x73+- uv>=0.25.x
74-* git(用于拉取代码)74+- git(用于拉取代码)
75-* bash(Linux/macOS 系统)或 PowerShell(Windows 系统)75+- bash(Linux/macOS 系统)或 PowerShell(Windows 系统)
76 76 
77## 快速开始77## 快速开始
78 78 
@@ -92,15 +92,15 @@ cp .env.example .env
92 92 
93然后按需修改 `server/.env`,重点包括:93然后按需修改 `server/.env`,重点包括:
94 94 
95-- `DB_TYPE`:支持 `sqlite` / `mysql` / `gaussdb` / `opengauss`95+- `RUNTIME_DB_TYPE`:支持 `sqlite` / `mysql` / `gaussdb` / `opengauss`
96- `IP`:Runtime 服务地址96- `IP`:Runtime 服务地址
97- `LOWCODE_IMAGE`:低码 Agent 相关镜像配置97- `LOWCODE_IMAGE`:低码 Agent 相关镜像配置
98 98 
99说明:99说明:
100 100 
101- 默认安装仅包含 `sqlite` / `mysql` 所需依赖。101- 默认安装仅包含 `sqlite` / `mysql` 所需依赖。
102-- 当 `DB_TYPE=gaussdb` 或 `DB_TYPE=opengauss` 时,需要额外安装 `async-gaussdb`。102+- 当 `RUNTIME_DB_TYPE=gaussdb` 或 `RUNTIME_DB_TYPE=opengauss` 时,需要额外安装 `async-gaussdb`。
103-- 使用仓库自带启动脚本时,脚本会根据 `server/.env` 中的 `DB_TYPE` 自动安装 `foundation[gaussdb]` 可选依赖;手工安装时可执行 `uv pip install -e "./foundation[gaussdb]"`。103+- 使用仓库自带启动脚本时,脚本会根据 `server/.env` 中的 `RUNTIME_DB_TYPE` 自动安装 `foundation[gaussdb]` 可选依赖;手工安装时可执行 `uv pip install -e "./foundation[gaussdb]"`。
104 104 
105完整配置项说明请参考 `docs/zh/2. 配置说明.md`105完整配置项说明请参考 `docs/zh/2. 配置说明.md`
106 106 
@@ -169,4 +169,3 @@ Windows(PowerShell):
169- 完善 Docker / Kubernetes 部署能力169- 完善 Docker / Kubernetes 部署能力
170- 补齐 CLI 接入能力170- 补齐 CLI 接入能力
171- 补齐 WebUI 接入能力171- 补齐 WebUI 接入能力
172- 
@@ -92,15 +92,15 @@ cp .env.example .env
92 92 
93Edit `server/.env` as needed. Important fields include:93Edit `server/.env` as needed. Important fields include:
94 94 
95-- **`DB_TYPE`**: `sqlite`, `mysql`, `gaussdb`, or `opengauss`95+- **`RUNTIME_DB_TYPE`**: `sqlite`, `mysql`, `gaussdb`, or `opengauss`
96- **`IP`**: reachable address for Runtime / agents96- **`IP`**: reachable address for Runtime / agents
97- **`LOWCODE_IMAGE`**: low-code agent container image (required when using Docker/K8s-style flows)97- **`LOWCODE_IMAGE`**: low-code agent container image (required when using Docker/K8s-style flows)
98 98 
99Notes:99Notes:
100 100 
101- The default install only includes dependencies for `sqlite` and `mysql`.101- The default install only includes dependencies for `sqlite` and `mysql`.
102-- When `DB_TYPE=gaussdb` or `DB_TYPE=opengauss`, Runtime additionally needs `async-gaussdb`.102+- When `RUNTIME_DB_TYPE=gaussdb` or `RUNTIME_DB_TYPE=opengauss`, Runtime additionally needs `async-gaussdb`.
103-- If you use the repository startup scripts, they detect `DB_TYPE` from `server/.env` and install `foundation[gaussdb]` automatically. For a manual setup, run `uv pip install -e "./foundation[gaussdb]"`.103+- If you use the repository startup scripts, they detect `RUNTIME_DB_TYPE` from `server/.env` and install `foundation[gaussdb]` automatically. For a manual setup, run `uv pip install -e "./foundation[gaussdb]"`.
104 104 
105For a full reference, see **`docs/en/2. Configuration.md`** (Chinese: `docs/zh/2. 配置说明.md`).105For a full reference, see **`docs/en/2. Configuration.md`** (Chinese: `docs/zh/2. 配置说明.md`).
106 106 
@@ -1 +1 @@
1-Subproject commit 95637327f3bfcc3e9aca5b46a72192a1ee363d9c1+Subproject commit 6c31c54681e17df6c15e03aca2e8e756b3d29e4b
@@ -42,10 +42,10 @@ from typing import AsyncIterator, Tuple
42 42 
43# 运行时数据库类型:优先保留外部注入(例如 gaussdb),缺失/非法值回退 sqlite。43# 运行时数据库类型:优先保留外部注入(例如 gaussdb),缺失/非法值回退 sqlite。
44_VALID_DB_TYPES = {"mysql", "sqlite", "gaussdb", "opengauss"}44_VALID_DB_TYPES = {"mysql", "sqlite", "gaussdb", "opengauss"}
45-_runtime_db_type = (os.getenv("DB_TYPE") or "").strip().lower()45+_runtime_db_type = (os.getenv("RUNTIME_DB_TYPE") or "").strip().lower()
46if _runtime_db_type not in _VALID_DB_TYPES:46if _runtime_db_type not in _VALID_DB_TYPES:
47 _runtime_db_type = "sqlite"47 _runtime_db_type = "sqlite"
48-os.environ["DB_TYPE"] = _runtime_db_type48+os.environ["RUNTIME_DB_TYPE"] = _runtime_db_type
49 49 
50# lowcode 运行链路会间接导入 openjiuwen_studio,当前其数据库层仅支持 mysql/sqlite/none。50# lowcode 运行链路会间接导入 openjiuwen_studio,当前其数据库层仅支持 mysql/sqlite/none。
51# 当 runtime 以 gaussdb/opengauss 启动时,这里切换 studio 侧 DB_TYPE,避免因不支持而阻塞低码启动。51# 当 runtime 以 gaussdb/opengauss 启动时,这里切换 studio 侧 DB_TYPE,避免因不支持而阻塞低码启动。
@@ -77,7 +77,7 @@ def _parse_userdata_env_vars():
77 pass77 pass
78 78 
79 for key, value in env_vars.items():79 for key, value in env_vars.items():
80- if key not in os.environ and key != "DB_TYPE":80+ if key not in os.environ and key != "RUNTIME_DB_TYPE":
81 os.environ[key] = str(value)81 os.environ[key] = str(value)
82 82 
83 return env_vars83 return env_vars
@@ -116,7 +116,7 @@ from openjiuwen_runtime.examples.lowcode_agent.workflow_registration import (
116from openjiuwen_runtime.service.app.agent_app import AgentApp116from openjiuwen_runtime.service.app.agent_app import AgentApp
117 117 
118if _runtime_db_type in {"gaussdb", "opengauss"}:118if _runtime_db_type in {"gaussdb", "opengauss"}:
119- os.environ["DB_TYPE"] = _studio_db_type119+ os.environ["RUNTIME_DB_TYPE"] = _studio_db_type
120 120 
121from openjiuwen_studio.core.executor.component.code_runner.remote import remote_code_runner121from openjiuwen_studio.core.executor.component.code_runner.remote import remote_code_runner
122 122 
@@ -5,6 +5,7 @@ FROM ${BASE_IMAGE} AS builder
5ARG INDEX_URL5ARG INDEX_URL
6 6 
7WORKDIR /app7WORKDIR /app
8+COPY agent-studio ./agent-studio
8COPY applications ./applications9COPY applications ./applications
9COPY service ./service10COPY service ./service
10COPY foundation ./foundation11COPY foundation ./foundation
@@ -14,10 +15,15 @@ RUN sed -i '/"openjiuwen-runtime-service==/d' /app/applications/lowcode_agent/py
14RUN sed -i '/"openjiuwen-runtime-foundation==/d' /app/service/pyproject.toml15RUN sed -i '/"openjiuwen-runtime-foundation==/d' /app/service/pyproject.toml
15 16 
16RUN pip install uv -i ${INDEX_URL}17RUN pip install uv -i ${INDEX_URL}
18+RUN sed -i "s#url = \"[^\"]*\"#url = \"${INDEX_URL}\"#g" /app/agent-studio/backend/pyproject.toml
17RUN sed -i "s#url = \"[^\"]*\"#url = \"${INDEX_URL}\"#g" /app/applications/lowcode_agent/pyproject.toml19RUN sed -i "s#url = \"[^\"]*\"#url = \"${INDEX_URL}\"#g" /app/applications/lowcode_agent/pyproject.toml
18RUN sed -i "s#url = \"[^\"]*\"#url = \"${INDEX_URL}\"#g" /app/service/pyproject.toml20RUN sed -i "s#url = \"[^\"]*\"#url = \"${INDEX_URL}\"#g" /app/service/pyproject.toml
19RUN sed -i "s#url = \"[^\"]*\"#url = \"${INDEX_URL}\"#g" /app/foundation/pyproject.toml21RUN sed -i "s#url = \"[^\"]*\"#url = \"${INDEX_URL}\"#g" /app/foundation/pyproject.toml
20 22 
23+WORKDIR /app/agent-studio/backend
24+RUN uv sync --group dev
25+RUN uv build --out-dir /app/dist
26+ 
21WORKDIR /app/applications/lowcode_agent27WORKDIR /app/applications/lowcode_agent
22RUN uv sync --group dev28RUN uv sync --group dev
23RUN uv build --out-dir /app/dist29RUN uv build --out-dir /app/dist
@@ -34,6 +40,7 @@ RUN uv build --out-dir /app/dist
34ARG BASE_IMAGE40ARG BASE_IMAGE
35FROM ${BASE_IMAGE} AS runtime41FROM ${BASE_IMAGE} AS runtime
36 42 
43+ARG STUDIO_VERSION
37ARG LOWCODE_AGENT_VERSION44ARG LOWCODE_AGENT_VERSION
38ARG RUNTIME_SERVICE_VERSION45ARG RUNTIME_SERVICE_VERSION
39ARG RUNTIME_FOUNDATION_VERSION46ARG RUNTIME_FOUNDATION_VERSION
@@ -41,6 +48,7 @@ ARG INDEX_URL
41 48 
42RUN mkdir -p /app/dist49RUN mkdir -p /app/dist
43 50 
51+COPY --from=builder /app/dist/openjiuwen_studio-${STUDIO_VERSION}-py3-none-any.whl /app/dist
44COPY --from=builder /app/dist/lowcode_agent_runner-${LOWCODE_AGENT_VERSION}-py3-none-any.whl /app/dist52COPY --from=builder /app/dist/lowcode_agent_runner-${LOWCODE_AGENT_VERSION}-py3-none-any.whl /app/dist
45COPY --from=builder /app/dist/openjiuwen_runtime_service-${RUNTIME_SERVICE_VERSION}-py3-none-any.whl /app/dist53COPY --from=builder /app/dist/openjiuwen_runtime_service-${RUNTIME_SERVICE_VERSION}-py3-none-any.whl /app/dist
46COPY --from=builder /app/dist/openjiuwen_runtime_foundation-${RUNTIME_FOUNDATION_VERSION}-py3-none-any.whl /app/dist54COPY --from=builder /app/dist/openjiuwen_runtime_foundation-${RUNTIME_FOUNDATION_VERSION}-py3-none-any.whl /app/dist
@@ -50,6 +58,7 @@ COPY --from=builder /app/dist/openjiuwen_runtime_foundation-${RUNTIME_FOUNDATION
50# 必须要用uv(新一代 Python 包管理器),专门修复了这个 bug,安装共享目录包时,只新增 / 覆盖文件,绝不删除整个目录58# 必须要用uv(新一代 Python 包管理器),专门修复了这个 bug,安装共享目录包时,只新增 / 覆盖文件,绝不删除整个目录
51 59 
52RUN pip install uv -i ${INDEX_URL}60RUN pip install uv -i ${INDEX_URL}
61+RUN uv pip install /app/dist/openjiuwen_studio-${STUDIO_VERSION}-py3-none-any.whl --index-url ${INDEX_URL} --target=/app/site-packages
53RUN uv pip install /app/dist/lowcode_agent_runner-${LOWCODE_AGENT_VERSION}-py3-none-any.whl --index-url ${INDEX_URL} --target=/app/site-packages62RUN uv pip install /app/dist/lowcode_agent_runner-${LOWCODE_AGENT_VERSION}-py3-none-any.whl --index-url ${INDEX_URL} --target=/app/site-packages
54RUN uv pip install /app/dist/openjiuwen_runtime_service-${RUNTIME_SERVICE_VERSION}-py3-none-any.whl --index-url ${INDEX_URL} --target=/app/site-packages63RUN uv pip install /app/dist/openjiuwen_runtime_service-${RUNTIME_SERVICE_VERSION}-py3-none-any.whl --index-url ${INDEX_URL} --target=/app/site-packages
55RUN uv pip install /app/dist/openjiuwen_runtime_foundation-${RUNTIME_FOUNDATION_VERSION}-py3-none-any.whl --index-url ${INDEX_URL} --target=/app/site-packages64RUN uv pip install /app/dist/openjiuwen_runtime_foundation-${RUNTIME_FOUNDATION_VERSION}-py3-none-any.whl --index-url ${INDEX_URL} --target=/app/site-packages
@@ -15,13 +15,13 @@ We recommend using Runtime from **source**: clone the repository and use the sta
15 15 
16Refer to [Configuration](<2. Configuration.md>) to create and edit the `.env` file, and adjust runtime parameters as needed. Key configuration items are as follows:16Refer to [Configuration](<2. Configuration.md>) to create and edit the `.env` file, and adjust runtime parameters as needed. Key configuration items are as follows:
17 17 
18-- `DB_TYPE`: `mysql`, `sqlite`, `gaussdb`, or `opengauss`18+- `RUNTIME_DB_TYPE`: `mysql`, `sqlite`, `gaussdb`, or `opengauss`
19- Other runtime settings (e.g. IP address, port)19- Other runtime settings (e.g. IP address, port)
20 20 
21Additional notes:21Additional notes:
22 22 
23- The default install only includes dependencies for `sqlite` and `mysql`.23- The default install only includes dependencies for `sqlite` and `mysql`.
24-- When `DB_TYPE=gaussdb` or `DB_TYPE=opengauss`, Runtime also needs `async-gaussdb`.24+- When `RUNTIME_DB_TYPE=gaussdb` or `RUNTIME_DB_TYPE=opengauss`, Runtime also needs `async-gaussdb`.
25- For a manual setup, run `uv pip install -e "./foundation[gaussdb]"`.25- For a manual setup, run `uv pip install -e "./foundation[gaussdb]"`.
26 26 
27### 3) Run the startup script27### 3) Run the startup script
@@ -6,7 +6,7 @@ All variables in this file are part of how Runtime starts and runs. Follow confi
6 6 
7## Common database settings7## Common database settings
8 8 
9-### DB_TYPE (database engine)9+### RUNTIME_DB_TYPE (database engine)
10 10 
11**Purpose:** Selects the database backend for Runtime. Supported values are **`mysql`**, **`sqlite`**, **`gaussdb`**, and **`opengauss`**. Default is **`sqlite`**.11**Purpose:** Selects the database backend for Runtime. Supported values are **`mysql`**, **`sqlite`**, **`gaussdb`**, and **`opengauss`**. Default is **`sqlite`**.
12 12 
@@ -15,41 +15,41 @@ All variables in this file are part of how Runtime starts and runs. Follow confi
15**Optional dependency note:**15**Optional dependency note:**
16 16 
17- The default install only includes dependencies for `sqlite` and `mysql`.17- The default install only includes dependencies for `sqlite` and `mysql`.
18-- When `DB_TYPE=gaussdb` or `DB_TYPE=opengauss`, Runtime additionally needs `async-gaussdb`.18+- When `RUNTIME_DB_TYPE=gaussdb` or `RUNTIME_DB_TYPE=opengauss`, Runtime additionally needs `async-gaussdb`.
19-- If you use the repository startup scripts, they detect `DB_TYPE` from `server/.env` and install `foundation[gaussdb]` automatically.19+- If you use the repository startup scripts, they detect `RUNTIME_DB_TYPE` from `server/.env` and install `foundation[gaussdb]` automatically.
20- For a manual setup, run `uv pip install -e "./foundation[gaussdb]"`.20- For a manual setup, run `uv pip install -e "./foundation[gaussdb]"`.
21 21 
22## MySQL / GaussDB / openGauss settings22## MySQL / GaussDB / openGauss settings
23 23 
24-### DB_HOST (database host)24+### RUNTIME_DB_HOST (database host)
25 25 
26**Purpose:** Hostname or IP of the database server Runtime connects to.26**Purpose:** Hostname or IP of the database server Runtime connects to.
27 27 
28**Guidance:** Use the remote host’s public IP if MySQL is remote; use `127.0.0.1` or `localhost` if MySQL is on the same machine as Runtime. Ensure the host is reachable from the Runtime host (firewall / security groups / ports).28**Guidance:** Use the remote host’s public IP if MySQL is remote; use `127.0.0.1` or `localhost` if MySQL is on the same machine as Runtime. Ensure the host is reachable from the Runtime host (firewall / security groups / ports).
29 29 
30-### DB_PORT (database port)30+### RUNTIME_DB_PORT (database port)
31 31 
32**Purpose:** Database listen port.32**Purpose:** Database listen port.
33 33 
34**Guidance:** Set this to the actual database port. Typical defaults are **3306** for MySQL and **5432** for GaussDB / openGauss. If you use **SQLite**, this value is ignored.34**Guidance:** Set this to the actual database port. Typical defaults are **3306** for MySQL and **5432** for GaussDB / openGauss. If you use **SQLite**, this value is ignored.
35 35 
36-### DB_USER (database username)36+### RUNTIME_DB_USER (database username)
37 37 
38**Purpose:** Database user Runtime uses. The account needs sufficient privileges (read/write, DDL such as table creation) for Runtime to operate the schema.38**Purpose:** Database user Runtime uses. The account needs sufficient privileges (read/write, DDL such as table creation) for Runtime to operate the schema.
39 39 
40-**Guidance:** Avoid `root` in production. Prefer a dedicated account (e.g. `jiuwen_runtime_user`) with least privilege on the database named in `DB_NAME` only.40+**Guidance:** Avoid `root` in production. Prefer a dedicated account (e.g. `jiuwen_runtime_user`) with least privilege on the database named in `RUNTIME_DB_NAME` only.
41 41 
42-### DB_PASSWORD (database password)42+### RUNTIME_DB_PASSWORD (database password)
43 43 
44-**Purpose:** Password for `DB_USER`.44+**Purpose:** Password for `RUNTIME_DB_USER`.
45 45 
46**Guidance:** Always use a strong password in production (mixed case, digits, symbols, length ≥ 8). Avoid trivial passwords. Store and rotate secrets securely.46**Guidance:** Always use a strong password in production (mixed case, digits, symbols, length ≥ 8). Avoid trivial passwords. Store and rotate secrets securely.
47 47 
48-### DB_NAME (database name)48+### RUNTIME_DB_NAME (database name)
49 49 
50**Purpose:** Database name Runtime uses. On startup, Runtime validates that the database exists; it **does not** auto-create the database — create it yourself in advance.50**Purpose:** Database name Runtime uses. On startup, Runtime validates that the database exists; it **does not** auto-create the database — create it yourself in advance.
51 51 
52-**Guidance:** You may use different names per environment (e.g. `prod_jiuwen_runtime`, `test_jiuwen_runtime`). Ensure the database exists and that `DB_USER` has the required privileges.52+**Guidance:** You may use different names per environment (e.g. `prod_jiuwen_runtime`, `test_jiuwen_runtime`). Ensure the database exists and that `RUNTIME_DB_USER` has the required privileges.
53 53 
54# Deployment-related settings54# Deployment-related settings
55 55 
@@ -15,7 +15,7 @@ Agent Runtime 首版本主要支持低码方式的 Agent 发布:与 openJiuwen
15 15 
16请参考 [配置说明](<2. 配置说明.md>) 创建并编辑 `.env` 配置文件,按需调整运行参数,核心配置项如下,重点包括:16请参考 [配置说明](<2. 配置说明.md>) 创建并编辑 `.env` 配置文件,按需调整运行参数,核心配置项如下,重点包括:
17 17 
18-- `DB_TYPE`:支持 `mysql` 和 `sqlite`18+- `RUNTIME_DB_TYPE`:支持 `mysql` 和 `sqlite`
19-`MODE`的值改成`product`19-`MODE`的值改成`product`
20- 其他运行时相关参数(如ip地址、端口号等)20- 其他运行时相关参数(如ip地址、端口号等)
21 21 
@@ -40,13 +40,13 @@ uv pip install agent-runtime-server
40 40 
41按需修改 `.env` 中的配置项,重点包括:41按需修改 `.env` 中的配置项,重点包括:
42 42 
43-- `DB_TYPE`:支持 `mysql`、`sqlite`、`gaussdb` 和 `opengauss`43+- `RUNTIME_DB_TYPE`:支持 `mysql`、`sqlite`、`gaussdb` 和 `opengauss`
44- 其他运行时相关参数(如ip地址、端口号等)44- 其他运行时相关参数(如ip地址、端口号等)
45 45 
46补充说明:46补充说明:
47 47 
48- 默认安装仅包含 `sqlite` / `mysql` 所需依赖;48- 默认安装仅包含 `sqlite` / `mysql` 所需依赖;
49-- 当 `DB_TYPE=gaussdb` 或 `DB_TYPE=opengauss` 时,还需要 `async-gaussdb`;49+- 当 `RUNTIME_DB_TYPE=gaussdb` 或 `RUNTIME_DB_TYPE=opengauss` 时,还需要 `async-gaussdb`;
50- 若手工安装,请执行 `uv pip install -e "./foundation[gaussdb]"`50- 若手工安装,请执行 `uv pip install -e "./foundation[gaussdb]"`
51 51 
52### 3) 执行启动脚本:52### 3) 执行启动脚本:
@@ -6,7 +6,7 @@
6 6 
7## 数据库通用配置7## 数据库通用配置
8 8 
9-## DB_TYPE(数据库类型)9+## RUNTIME_DB_TYPE(数据库类型)
10 10 
11**作用**:定义 Runtime 服务所使用的数据库类型,支持 mysql、sqlite、gaussdb、opengauss 四个可选值,默认配置为 sqlite。11**作用**:定义 Runtime 服务所使用的数据库类型,支持 mysql、sqlite、gaussdb、opengauss 四个可选值,默认配置为 sqlite。
12 12 
@@ -15,33 +15,33 @@
15**可选依赖说明**15**可选依赖说明**
16 16 
17- 默认安装仅包含 `sqlite` / `mysql` 所需依赖;17- 默认安装仅包含 `sqlite` / `mysql` 所需依赖;
18-- 当 `DB_TYPE=gaussdb` 或 `DB_TYPE=opengauss` 时,需要额外安装 `async-gaussdb`;18+- 当 `RUNTIME_DB_TYPE=gaussdb` 或 `RUNTIME_DB_TYPE=opengauss` 时,需要额外安装 `async-gaussdb`;
19-- 使用仓库自带启动脚本时,脚本会根据 `server/.env` 中的 `DB_TYPE` 自动安装 `foundation[gaussdb]`;19+- 使用仓库自带启动脚本时,脚本会根据 `server/.env` 中的 `RUNTIME_DB_TYPE` 自动安装 `foundation[gaussdb]`;
20- 若手工安装,请执行 `uv pip install -e "./foundation[gaussdb]"`20- 若手工安装,请执行 `uv pip install -e "./foundation[gaussdb]"`
21 21 
22## MySQL / GaussDB / openGauss 数据库专用配置22## MySQL / GaussDB / openGauss 数据库专用配置
23 23 
24-### DB_HOST(数据库主机地址)24+### RUNTIME_DB_HOST(数据库主机地址)
25 25 
26**作用**:指定数据库服务所在的主机IP地址或域名,Runtime 服务通过该地址连接数据库。26**作用**:指定数据库服务所在的主机IP地址或域名,Runtime 服务通过该地址连接数据库。
27 27 
28**修改建议**:若MySQL数据库部署在远程服务器,需将值改为远程数据库的公网IP地址;若数据库与 Runtime 服务部署在同一服务器,可改为 127.0.0.1或localhost。修改后需确保该地址可被 Runtime 服务所在服务器访问,无防火墙、端口限制。28**修改建议**:若MySQL数据库部署在远程服务器,需将值改为远程数据库的公网IP地址;若数据库与 Runtime 服务部署在同一服务器,可改为 127.0.0.1或localhost。修改后需确保该地址可被 Runtime 服务所在服务器访问,无防火墙、端口限制。
29 29 
30-### DB_PORT(数据库端口)30+### RUNTIME_DB_PORT(数据库端口)
31 31 
32**作用**:指定数据库服务的监听端口。32**作用**:指定数据库服务的监听端口。
33 33 
34**修改建议**:MySQL 默认端口通常为 3306,GaussDB / openGauss 默认端口通常为 5432。若使用 SQLite 数据库,该配置项不生效,但也不影响服务运行,建议保留注释说明以避免混淆。34**修改建议**:MySQL 默认端口通常为 3306,GaussDB / openGauss 默认端口通常为 5432。若使用 SQLite 数据库,该配置项不生效,但也不影响服务运行,建议保留注释说明以避免混淆。
35 35 
36-### DB_USER(数据库登录用户名)36+### RUNTIME_DB_USER(数据库登录用户名)
37 37 
38**作用**:指定连接MySQL数据库的用户名,需具备该数据库的读写、创建表等权限,确保 Runtime 服务能正常操作数据库。38**作用**:指定连接MySQL数据库的用户名,需具备该数据库的读写、创建表等权限,确保 Runtime 服务能正常操作数据库。
39 39 
40-**修改建议**:生产环境中不建议使用 root 账号,建议创建专用数据库账号(如 jiuwen_runtime_user),并分配最小必要权限(仅对 DB_NAME 指定的数据库有操作权限),修改该值为创建的专用账号,提升安全性。40+**修改建议**:生产环境中不建议使用 root 账号,建议创建专用数据库账号(如 jiuwen_runtime_user),并分配最小必要权限(仅对 RUNTIME_DB_NAME 指定的数据库有操作权限),修改该值为创建的专用账号,提升安全性。
41 41 
42-### DB_PASSWORD(数据库登录密码)42+### RUNTIME_DB_PASSWORD(数据库登录密码)
43 43 
44-**作用**:对应 DB_USER 的登录密码,用于验证数据库连接权限,是数据库安全的核心参数。44+**作用**:对应 RUNTIME_DB_USER 的登录密码,用于验证数据库连接权限,是数据库安全的核心参数。
45 45 
46**修改建议**:生产环境必须修改,建议设置复杂密码(包含大小写字母、数字、特殊符号,长度不小于8位),避免使用简单密码(如 123456、admin);密码修改后需同步告知相关运维人员,妥善保管,避免泄露。46**修改建议**:生产环境必须修改,建议设置复杂密码(包含大小写字母、数字、特殊符号,长度不小于8位),避免使用简单密码(如 123456、admin);密码修改后需同步告知相关运维人员,妥善保管,避免泄露。
47 47 
@@ -49,7 +49,7 @@
49 49 
50**作用**:指定 Runtime 服务需要连接、操作的数据库名称,服务启动时会自动校验该数据库是否存在(不会自动创建, 请自行提前创建)。50**作用**:指定 Runtime 服务需要连接、操作的数据库名称,服务启动时会自动校验该数据库是否存在(不会自动创建, 请自行提前创建)。
51 51 
52-**修改建议**:可根据实际业务需求修改(如 prod_jiuwen_runtime 用于生产环境,test_jiuwen_runtime 用于测试环境)。修改后需确保该数据库已提前创建(服务不支持自动创建),且 DB_USER 账号对该数据库有对应操作权限。52+**修改建议**:可根据实际业务需求修改(如 prod_jiuwen_runtime 用于生产环境,test_jiuwen_runtime 用于测试环境)。修改后需确保该数据库已提前创建(服务不支持自动创建),且 RUNTIME_DB_USER 账号对该数据库有对应操作权限。
53 53 
54# 服务部署相关配置54# 服务部署相关配置
55 55 
@@ -16,16 +16,16 @@ class Settings(BaseSettings):
16 # --------------------------16 # --------------------------
17 # 【基础配置】17 # 【基础配置】
18 # --------------------------18 # --------------------------
19- DB_TYPE: Literal["mysql", "sqlite", "gaussdb", "opengauss"] = Field(default="sqlite", env="DB_TYPE")19+ RUNTIME_DB_TYPE: Literal["mysql", "sqlite", "gaussdb", "opengauss"] = Field(default="sqlite", env="RUNTIME_DB_TYPE")
20 20 
21 # --------------------------21 # --------------------------
22- # 【MySQL 配置】(静态可选,DB_TYPE=mysql 时必选)22+ # 【MySQL RUNTIME_DB_TYPE=mysql 时必选)
23 # --------------------------23 # --------------------------
24- DB_HOST: Optional[str] = Field(default=None, env="DB_HOST")24+ RUNTIME_DB_HOST: Optional[str] = Field(default=None, env="RUNTIME_DB_HOST")
25- DB_PORT: Optional[int] = Field(default=None, env="DB_PORT")25+ RUNTIME_DB_PORT: Optional[int] = Field(default=None, env="RUNTIME_DB_PORT")
26- DB_USER: Optional[str] = Field(default=None, env="DB_USER")26+ RUNTIME_DB_USER: Optional[str] = Field(default=None, env="RUNTIME_DB_USER")
27- DB_PASSWORD: Optional[str] = Field(default=None, env="DB_PASSWORD")27+ RUNTIME_DB_PASSWORD: Optional[str] = Field(default=None, env="RUNTIME_DB_PASSWORD")
28- DB_NAME: Optional[str] = Field(default=None, env="DB_NAME")28+ RUNTIME_DB_NAME: Optional[str] = Field(default=None, env="RUNTIME_DB_NAME")
29 29 
30 # --------------------------30 # --------------------------
31 # 【服务配置】31 # 【服务配置】
@@ -53,23 +53,26 @@ class Settings(BaseSettings):
53 # ========================53 # ========================
54 @model_validator(mode="after")54 @model_validator(mode="after")
55 def check_mysql_required(self) -> "Settings":55 def check_mysql_required(self) -> "Settings":
56- if self.DB_TYPE in {"mysql", "gaussdb", "opengauss"}:56+ if self.RUNTIME_DB_TYPE in {"mysql", "gaussdb", "opengauss"}:
57 missing = []57 missing = []
58- if not self.DB_HOST:58+ if not self.RUNTIME_DB_HOST:
59- missing.append("DB_HOST")59+ missing.append("RUNTIME_DB_HOST")
60- if not self.DB_PORT:60+ if not self.RUNTIME_DB_PORT:
61- missing.append("DB_PORT")61+ missing.append("RUNTIME_DB_PORT")
62- if not self.DB_USER:62+ if not self.RUNTIME_DB_USER:
63- missing.append("DB_USER")63+ missing.append("RUNTIME_DB_USER")
64- if not self.DB_PASSWORD:64+ if not self.RUNTIME_DB_PASSWORD:
65- missing.append("DB_PASSWORD")65+ missing.append("RUNTIME_DB_PASSWORD")
66- if not self.DB_NAME:66+ if not self.RUNTIME_DB_NAME:
67- missing.append("DB_NAME")67+ missing.append("RUNTIME_DB_NAME")
68 68 
69 if missing:69 if missing:
70- raise ValueError(70+ msg = (
71- f"When DB_TYPE is mysql/gaussdb/opengauss, the following fields are required: {', '.join(missing)}"71+ "When RUNTIME_DB_TYPE is mysql/gaussdb/opengauss, "
72+ "the following fields are required: "
73+ f"{', '.join(missing)}"
72 )74 )
75+ raise ValueError(msg)
73 return self76 return self
74 77 
75 @model_validator(mode="after")78 @model_validator(mode="after")
@@ -130,7 +133,8 @@ class Settings(BaseSettings):
130 model_config = SettingsConfigDict(133 model_config = SettingsConfigDict(
131 env_file=os.path.join(PROJECT_ROOT, "server/.env"),134 env_file=os.path.join(PROJECT_ROOT, "server/.env"),
132 env_file_encoding="utf-8",135 env_file_encoding="utf-8",
133- case_sensitive=True136+ case_sensitive=True,
137+ extra="ignore"
134 )138 )
135 139 
136# 初始化配置140# 初始化配置
@@ -9,7 +9,7 @@ from sqlalchemy.util import memoized_property
9 9 
10_MODULE_PATH = "openjiuwen_runtime.foundation.db.dialects.gaussdb_asyncgaussdb"10_MODULE_PATH = "openjiuwen_runtime.foundation.db.dialects.gaussdb_asyncgaussdb"
11_DRIVER_INSTALL_HINT = (11_DRIVER_INSTALL_HINT = (
12- "DB_TYPE is set to gaussdb/opengauss, but optional dependency async-gaussdb is not installed. "12+ "RUNTIME_DB_TYPE is set to gaussdb/opengauss, but optional dependency async-gaussdb is not installed. "
13 "Install openjiuwen-runtime-foundation[gaussdb] or async-gaussdb>=0.30.4."13 "Install openjiuwen-runtime-foundation[gaussdb] or async-gaussdb>=0.30.4."
14)14)
15 15 
@@ -15,10 +15,10 @@ class GaussDBHandler(SQLAlchemyHandler):
15 def __init__(self):15 def __init__(self):
16 ensure_async_gaussdb_installed()16 ensure_async_gaussdb_installed()
17 ensure_gaussdb_dialect_registered()17 ensure_gaussdb_dialect_registered()
18- user = quote(settings.DB_USER or "", safe="")18+ user = quote(settings.RUNTIME_DB_USER or "", safe="")
19- password = quote(settings.DB_PASSWORD or "", safe="")19+ password = quote(settings.RUNTIME_DB_PASSWORD or "", safe="")
20 database_url = (20 database_url = (
21 f"gaussdb+async_gaussdb://{user}:{password}@"21 f"gaussdb+async_gaussdb://{user}:{password}@"
22- f"{settings.DB_HOST}:{settings.DB_PORT}/{settings.DB_NAME}"22+ f"{settings.RUNTIME_DB_HOST}:{settings.RUNTIME_DB_PORT}/{settings.RUNTIME_DB_NAME}"
23 )23 )
24 super().__init__(database_url)24 super().__init__(database_url)
@@ -12,11 +12,11 @@ class MySQLHandler(SQLAlchemyHandler):
12 def __init__(12 def __init__(
13 self13 self
14 ):14 ):
15- self.host = settings.DB_HOST15+ self.host = settings.RUNTIME_DB_HOST
16- self.port = settings.DB_PORT16+ self.port = settings.RUNTIME_DB_PORT
17- self.database = settings.DB_NAME17+ self.database = settings.RUNTIME_DB_NAME
18- self.user = settings.DB_USER18+ self.user = settings.RUNTIME_DB_USER
19- self.password = settings.DB_PASSWORD19+ self.password = settings.RUNTIME_DB_PASSWORD
20 20 
21 database_url = f"mysql+aiomysql://{self.user}:{self.password}@{self.host}:{self.port}/{self.database}"21 database_url = f"mysql+aiomysql://{self.user}:{self.password}@{self.host}:{self.port}/{self.database}"
22 super().__init__(database_url)22 super().__init__(database_url)
@@ -52,7 +52,7 @@ class TestGaussDBRealDatabaseSystem(unittest.IsolatedAsyncioTestCase):
52 if not _is_enabled(enabled):52 if not _is_enabled(enabled):
53 raise unittest.SkipTest("real-db ST is disabled; set GAUSSDB_REAL_ST_ENABLED=1 to enable")53 raise unittest.SkipTest("real-db ST is disabled; set GAUSSDB_REAL_ST_ENABLED=1 to enable")
54 54 
55- db_type = _pick_env("GAUSSDB_REAL_DB_TYPE", "DB_TYPE", default="gaussdb").lower()55+ db_type = _pick_env("GAUSSDB_REAL_DB_TYPE", "RUNTIME_DB_TYPE", default="gaussdb").lower()
56 if db_type not in {"gaussdb", "opengauss"}:56 if db_type not in {"gaussdb", "opengauss"}:
57 raise unittest.SkipTest(f"unsupported db type for this ST: {db_type!r}")57 raise unittest.SkipTest(f"unsupported db type for this ST: {db_type!r}")
58 58 
@@ -187,7 +187,18 @@ class DockerDeployer(Deployer[DockerParams]):
187 self._containers[deployment_id] = container_id187 self._containers[deployment_id] = container_id
188 188 
189 # 获取该容器在宿主机上的port189 # 获取该容器在宿主机上的port
190- success, port_output = await self._run_docker_command("port", container_id, iport)190+ port_output = None
191+ max_retry = 6 # 最多重试6次
192+ retry_interval = 1 # 每次间隔1秒
193+ 
194+ for i in range(max_retry):
195+ success, port_output = await self._run_docker_command("port", container_id, iport)
196+ if success and port_output:
197+ break
198+ logger.warning(f"第{i+1}次获取端口失败,等待{retry_interval}秒后重试... container_id={container_id}")
199+ await asyncio.sleep(retry_interval)
200+ 
201+ # 最终判断
191 if not success or not port_output:202 if not success or not port_output:
192 raise RuntimeError(f"无法获取容器映射的端口: {container_id}")203 raise RuntimeError(f"无法获取容器映射的端口: {container_id}")
193 204 
@@ -142,8 +142,8 @@ class LocalSubprocessDeployer(Deployer[SubprocessParams]):
142 logger.info("Virtual environment created: %s", venv_path)142 logger.info("Virtual environment created: %s", venv_path)
143 143 
144 if settings.MODE == "dev":144 if settings.MODE == "dev":
145- # 安装基础运行时 WHL(foundation/management/service)145+ # 安装基础运行时 WHL(studio/foundation/management/service)
146- base_whl_files = sorted(settings.dist_path.glob("openjiuwen_runtime_*.whl"))146+ base_whl_files = sorted(settings.dist_path.glob("openjiuwen_*.whl"))
147 for whl_file in base_whl_files:147 for whl_file in base_whl_files:
148 self.venv_manager.pip_install(deployment_id, str(whl_file))148 self.venv_manager.pip_install(deployment_id, str(whl_file))
149 logger.info("Installed base WHL: %s", whl_file.name)149 logger.info("Installed base WHL: %s", whl_file.name)
@@ -38,10 +38,10 @@ source ${ENV_FILE} # Load environment variables from file
38set +a # Disable automatic export38set +a # Disable automatic export
39 39 
40FOUNDATION_INSTALL_TARGET="../foundation"40FOUNDATION_INSTALL_TARGET="../foundation"
41-DB_TYPE_NORMALIZED="$(echo "${DB_TYPE:-}" | tr '[:upper:]' '[:lower:]')"41+DB_TYPE_NORMALIZED="$(echo "${RUNTIME_DB_TYPE:-}" | tr '[:upper:]' '[:lower:]')"
42if [[ "${DB_TYPE_NORMALIZED}" == "gaussdb" || "${DB_TYPE_NORMALIZED}" == "opengauss" ]]; then42if [[ "${DB_TYPE_NORMALIZED}" == "gaussdb" || "${DB_TYPE_NORMALIZED}" == "opengauss" ]]; then
43 FOUNDATION_INSTALL_TARGET="../foundation[gaussdb]"43 FOUNDATION_INSTALL_TARGET="../foundation[gaussdb]"
44- echo "Detected DB_TYPE=${DB_TYPE}; install foundation with [gaussdb] optional dependency."44+ echo "Detected RUNTIME_DB_TYPE=${RUNTIME_DB_TYPE}; install foundation with [gaussdb] optional dependency."
45fi45fi
46 46 
47if [[ "$OSTYPE" == "darwin"* ]]; then47if [[ "$OSTYPE" == "darwin"* ]]; then
@@ -1,33 +1,33 @@
1# 数据库类型:支持 mysql、sqlite、gaussdb、opengauss1# 数据库类型:支持 mysql、sqlite、gaussdb、opengauss
2-DB_TYPE=mysql2+RUNTIME_DB_TYPE=mysql
3 3 
4# 数据库主机地址4# 数据库主机地址
5-DB_HOST=localhost5+RUNTIME_DB_HOST=localhost
6 6 
7# 数据库端口:MySQL 默认 3306,GaussDB/openGauss 默认 54327# 数据库端口:MySQL 默认 3306,GaussDB/openGauss 默认 5432
8-DB_PORT=33068+RUNTIME_DB_PORT=3306
9 9 
10# 数据库登录用户名10# 数据库登录用户名
11-DB_USER=root11+RUNTIME_DB_USER=root
12 12 
13# 数据库登录密码13# 数据库登录密码
14-DB_PASSWORD=root14+RUNTIME_DB_PASSWORD=root
15 15 
16# 要连接的数据库名称16# 要连接的数据库名称
17-DB_NAME=jiuwen_runtime17+RUNTIME_DB_NAME=jiuwen_runtime
18 18 
19# -----------------------------------------------------------------------------19# -----------------------------------------------------------------------------
20# GaussDB/openGauss POC 验证建议值20# GaussDB/openGauss POC 验证建议值
21# -----------------------------------------------------------------------------21# -----------------------------------------------------------------------------
22-# 使用仓库自带 scripts/run-server.sh / run-server.ps1 启动时,脚本会在 DB_TYPE=gaussdb/opengauss22+# 使用仓库自带 scripts/run-server.sh / run-server.ps1 启动时,脚本会在 RUNTIME_DB_TYPE=gaussdb/opengauss
23# 场景下自动安装 foundation[gaussdb];若手工安装,请额外安装 async-gaussdb>=0.30.4。23# 场景下自动安装 foundation[gaussdb];若手工安装,请额外安装 async-gaussdb>=0.30.4。
24# 验证 GaussDB/openGauss POC 时,建议至少替换为以下值:24# 验证 GaussDB/openGauss POC 时,建议至少替换为以下值:
25-# DB_TYPE=gaussdb # 或 opengauss25+# RUNTIME_DB_TYPE=gaussdb # 或 opengauss
26-# DB_HOST=127.0.0.126+# RUNTIME_DB_HOST=127.0.0.1
27-# DB_PORT=543227+# RUNTIME_DB_PORT=5432
28-# DB_USER=gaussdb_user28+# RUNTIME_DB_USER=gaussdb_user
29-# DB_PASSWORD=gaussdb_password29+# RUNTIME_DB_PASSWORD=gaussdb_password
30-# DB_NAME=gaussdb_runtime30+# RUNTIME_DB_NAME=gaussdb_runtime
31 31 
32# 低码agent 和 agent-runtime-server 运行所在的主机IP地址32# 低码agent 和 agent-runtime-server 运行所在的主机IP地址
33IP=127.0.0.133IP=127.0.0.1
@@ -40,18 +40,18 @@ logger = get_logger(__name__)
40_allocated_ports: set[int] = set()40_allocated_ports: set[int] = set()
41 41 
42# 初始化数据库组件42# 初始化数据库组件
43-logger.info(f"Using database: {settings.DB_TYPE}")43+logger.info(f"Using database: {settings.RUNTIME_DB_TYPE}")
44-if settings.DB_TYPE == "sqlite":44+if settings.RUNTIME_DB_TYPE == "sqlite":
45 db_handler = SQLiteHandler("deployments.db")45 db_handler = SQLiteHandler("deployments.db")
46-elif settings.DB_TYPE == "mysql":46+elif settings.RUNTIME_DB_TYPE == "mysql":
47 db_handler = MySQLHandler()47 db_handler = MySQLHandler()
48-elif settings.DB_TYPE in {"gaussdb", "opengauss"}:48+elif settings.RUNTIME_DB_TYPE in {"gaussdb", "opengauss"}:
49 from openjiuwen_runtime.foundation.db.gaussdb_handler import GaussDBHandler49 from openjiuwen_runtime.foundation.db.gaussdb_handler import GaussDBHandler
50 50 
51 db_handler = GaussDBHandler()51 db_handler = GaussDBHandler()
52else:52else:
53 raise ValueError(53 raise ValueError(
54- f"Unsupported DB_TYPE: {settings.DB_TYPE}. Use 'sqlite', 'mysql', 'gaussdb', or 'opengauss'."54+ f"Unsupported RUNTIME_DB_TYPE: {settings.RUNTIME_DB_TYPE}. Use 'sqlite', 'mysql', 'gaussdb', or 'opengauss'."
55 )55 )
56 56 
57manager = DeploymentManager(db_handler)57manager = DeploymentManager(db_handler)