feat: merge cli and shell config toml

This commit is contained in:
alan.cl
2026-03-25 17:10:05 +08:00
parent 8fef80a427
commit 2911a9d613
29 changed files with 351 additions and 328 deletions

View File

@@ -177,7 +177,7 @@ MINIMAX_API_KEY=sk-xxx \
After installation, start the server with the generated profile config:
```bash
cd ~/.dbgpt/DB-GPT && uv run dbgpt start webserver --config ~/.dbgpt/configs/<profile>.toml
cd ~/.dbgpt/DB-GPT && uv run dbgpt start webserver --profile <profile>
```
Then open [http://localhost:5670](http://localhost:5670).

View File

@@ -168,7 +168,7 @@ MINIMAX_API_KEY=sk-xxx \
安装完成后,使用生成的 profile 配置启动服务:
```bash
cd ~/.dbgpt/DB-GPT && uv run dbgpt start webserver --config ~/.dbgpt/configs/<profile>.toml
cd ~/.dbgpt/DB-GPT && uv run dbgpt start webserver --profile <profile>
```
然后打开 [http://localhost:5670](http://localhost:5670)。

View File

@@ -1,6 +1,6 @@
[project]
name = "dbgpt-acc-auto"
version = "0.8.0rc6"
version = "0.8.0rc7"
description = "Add your description here"
authors = [
{ name = "csunny", email = "cfqcsunny@gmail.com" }

View File

@@ -1 +1 @@
version = "0.8.0rc6"
version = "0.8.0rc7"

View File

@@ -2,7 +2,7 @@
# https://github.com/astral-sh/uv/issues/2252#issuecomment-2624150395
[project]
name = "dbgpt-acc-flash-attn"
version = "0.8.0rc6"
version = "0.8.0rc7"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.10"

View File

@@ -1 +1 @@
version = "0.8.0rc6"
version = "0.8.0rc7"

View File

@@ -0,0 +1,94 @@
"""Hatch build hook for dbgpt-app.
Dynamically resolves force-include paths for wheel builds based on the build
mode. This is necessary because source paths differ between editable installs
(where files live at the repository root) and standard builds from sdist
(where files have been copied into the sdist archive).
Problem solved:
- editable (uv sync): root = packages/dbgpt-app/, files at ../../skills/
- standard (from sdist): root = /tmp/extracted-sdist/, files at skills/
Static pyproject.toml force-include cannot handle both cases.
"""
from __future__ import annotations
import os
from pathlib import Path
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
# Source paths relative to REPO ROOT -> wheel target paths
# Used in editable mode where we can reach repo root via ../../
_SKILLS_MAP = {
"skills/csv-data-analysis": "dbgpt_app/_builtin_skills/csv-data-analysis",
"skills/skill-creator": "dbgpt_app/_builtin_skills/skill-creator",
"skills/financial-report-analyzer": "dbgpt_app/_builtin_skills/financial-report-analyzer",
"skills/walmart-sales-analyzer": "dbgpt_app/_builtin_skills/walmart-sales-analyzer",
"skills/agent-browser": "dbgpt_app/_builtin_skills/agent-browser",
}
_EXAMPLES_MAP = {
# repo_root_relative_path -> wheel_target
"docker/examples/excel/Walmart_Sales.csv": "dbgpt_app/_builtin_examples/excel/Walmart_Sales.csv",
"docker/examples/fin_report/pdf/2020-01-23__浙江海翔药业股份有限公司__002099__海翔药业__2019年__年度报告.pdf": "dbgpt_app/_builtin_examples/fin_report/pdf/2020-01-23__浙江海翔药业股份有限公司__002099__海翔药业__2019年__年度报告.pdf",
}
_PILOT_TPL_MAP = {
# repo_root_relative_path -> wheel_target
"pilot/meta_data/alembic.ini": "dbgpt_app/pilot_template/meta_data/alembic.ini",
"pilot/meta_data/alembic/README": "dbgpt_app/pilot_template/meta_data/alembic/README",
"pilot/meta_data/alembic/env.py": "dbgpt_app/pilot_template/meta_data/alembic/env.py",
"pilot/meta_data/alembic/script.py.mako": "dbgpt_app/pilot_template/meta_data/alembic/script.py.mako",
"pilot/benchmark_meta_data/2025_07_27_public_500_standard_benchmark_question_list.xlsx": "dbgpt_app/pilot_template/benchmark_meta_data/2025_07_27_public_500_standard_benchmark_question_list.xlsx",
"pilot/examples/Walmart_Sales.db": "dbgpt_app/pilot_template/examples/Walmart_Sales.db",
}
# sdist force-include remaps these paths:
# ../../skills/X -> skills/X
# ../../docker/examples/X -> examples/X
# ../../pilot/X -> pilot_tpl/X
_SDIST_REMAP = {
"skills/": "skills/", # no change
"docker/examples/": "examples/", # strip "docker/"
"pilot/": "pilot_tpl/", # pilot -> pilot_tpl
}
class CustomBuildHook(BuildHookInterface):
"""Dynamically set wheel force-include paths for editable and standard builds."""
def initialize(self, version, build_data):
"""Called by hatchling before building.
Args:
version: "editable" for uv sync / pip install -e .
"standard" for uv build / pip wheel
build_data: mutable dict; set "force_include" key to inject mappings
"""
pkg_root = Path(self.root) # packages/dbgpt-app/
all_mappings = {**_SKILLS_MAP, **_EXAMPLES_MAP, **_PILOT_TPL_MAP}
force_include = {}
if version == "editable":
# Editable: resolve from repo root (two levels up from packages/dbgpt-app/)
repo_root = pkg_root.parent.parent
for repo_rel_path, wheel_target in all_mappings.items():
source = str(repo_root / repo_rel_path)
if os.path.exists(source):
force_include[source] = wheel_target
else:
# Standard build from sdist: files were placed at sdist-relative paths
# by the sdist force-include config in pyproject.toml
for repo_rel_path, wheel_target in all_mappings.items():
sdist_path = repo_rel_path
for prefix, replacement in _SDIST_REMAP.items():
if repo_rel_path.startswith(prefix):
sdist_path = replacement + repo_rel_path[len(prefix) :]
break
source = str(pkg_root / sdist_path)
if os.path.exists(source):
force_include[source] = wheel_target
build_data["force_include"] = force_include

View File

@@ -1,6 +1,6 @@
[project]
name = "dbgpt-app"
version = "0.8.0rc6"
version = "0.8.0rc7"
description = "Add your description here"
authors = [
{ name = "csunny", email = "cfqcsunny@gmail.com" }
@@ -82,21 +82,5 @@ exclude = [
"../../pilot/benchmark_meta_data/2025_07_27_public_500_standard_benchmark_question_list.xlsx" = "pilot_tpl/benchmark_meta_data/2025_07_27_public_500_standard_benchmark_question_list.xlsx"
"../../pilot/examples/Walmart_Sales.db" = "pilot_tpl/examples/Walmart_Sales.db"
[tool.hatch.build.targets.wheel.force-include]
# Builtin skills
"skills/csv-data-analysis" = "dbgpt_app/_builtin_skills/csv-data-analysis"
"skills/skill-creator" = "dbgpt_app/_builtin_skills/skill-creator"
"skills/financial-report-analyzer" = "dbgpt_app/_builtin_skills/financial-report-analyzer"
"skills/walmart-sales-analyzer" = "dbgpt_app/_builtin_skills/walmart-sales-analyzer"
"skills/agent-browser" = "dbgpt_app/_builtin_skills/agent-browser"
# Builtin example files
"examples/excel/Walmart_Sales.csv" = "dbgpt_app/_builtin_examples/excel/Walmart_Sales.csv"
"examples/fin_report/pdf/2020-01-23__浙江海翔药业股份有限公司__002099__海翔药业__2019年__年度报告.pdf" = "dbgpt_app/_builtin_examples/fin_report/pdf/2020-01-23__浙江海翔药业股份有限公司__002099__海翔药业__2019年__年度报告.pdf"
# Pilot workspace template files (provisioned to ~/.dbgpt/workspace/pilot/ on first startup)
"pilot_tpl/meta_data/alembic.ini" = "dbgpt_app/pilot_template/meta_data/alembic.ini"
"pilot_tpl/meta_data/alembic/README" = "dbgpt_app/pilot_template/meta_data/alembic/README"
"pilot_tpl/meta_data/alembic/env.py" = "dbgpt_app/pilot_template/meta_data/alembic/env.py"
"pilot_tpl/meta_data/alembic/script.py.mako" = "dbgpt_app/pilot_template/meta_data/alembic/script.py.mako"
"pilot_tpl/benchmark_meta_data/2025_07_27_public_500_standard_benchmark_question_list.xlsx" = "dbgpt_app/pilot_template/benchmark_meta_data/2025_07_27_public_500_standard_benchmark_question_list.xlsx"
"pilot_tpl/examples/Walmart_Sales.db" = "dbgpt_app/pilot_template/examples/Walmart_Sales.db"
[tool.hatch.build.hooks.custom]

View File

@@ -1 +1 @@
version = "0.8.0rc6"
version = "0.8.0rc7"

View File

@@ -1,6 +1,6 @@
[project]
name = "dbgpt-client"
version = "0.8.0rc6"
version = "0.8.0rc7"
description = "Add your description here"
authors = [
{ name = "csunny", email = "cfqcsunny@gmail.com" }

View File

@@ -1 +1 @@
version = "0.8.0rc6"
version = "0.8.0rc7"

View File

@@ -1,6 +1,6 @@
[project]
name = "dbgpt"
version = "0.8.0rc6"
version = "0.8.0rc7"
description = """DB-GPT is an experimental open-source project that uses localized GPT \
large models to interact with your data and environment. With this solution, you can be\
assured that there is no risk of data leakage, and your data is 100% private and secure.\

View File

@@ -1 +1 @@
version = "0.8.0rc6"
version = "0.8.0rc7"

View File

@@ -155,8 +155,8 @@ def _render_profile_toml(
else:
embedding_api_url = spec.embedding_api_url
data_dir = str(dbgpt_home() / "workspace" / "pilot" / "meta_data" / "dbgpt.db")
vector_dir = str(dbgpt_home() / "workspace" / "pilot" / "data")
data_dir = "pilot/meta_data/dbgpt.db"
vector_dir = "pilot/data"
lines = [
f"# DB-GPT configuration — profile: {spec.name}",

View File

@@ -103,10 +103,10 @@ PROFILES: Dict[str, ProfileSpec] = {
llm_model="kimi-k2",
llm_provider="proxy/moonshot",
llm_api_base="https://api.moonshot.cn/v1",
embedding_model="text-embedding-v3",
embedding_provider="proxy/tongyi",
embedding_api_url="https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings",
embedding_env_var="DASHSCOPE_API_KEY",
embedding_model="text-embedding-3-small",
embedding_provider="proxy/openai",
embedding_api_url="https://api.openai.com/v1/embeddings",
embedding_env_var="OPENAI_API_KEY",
),
"qwen": ProfileSpec(
name="qwen",

View File

@@ -86,29 +86,25 @@ class TestDbgptHomeEnvVar:
class TestWorkspacePaths:
def test_render_toml_data_path_contains_workspace(self, isolated_dbgpt_home):
def test_render_toml_data_path_is_relative(self, isolated_dbgpt_home):
from dbgpt.cli._config import _render_profile_toml
from dbgpt.cli._profiles import get_profile
spec = get_profile("openai")
content = _render_profile_toml(spec, api_key="test-key")
assert "workspace/pilot/meta_data/dbgpt.db" in content
# Database and vector paths should be relative
assert 'path = "pilot/meta_data/dbgpt.db"' in content
assert 'persist_path = "pilot/data"' in content
def test_render_toml_data_path_not_absolute(self, isolated_dbgpt_home):
from dbgpt.cli._config import _render_profile_toml
from dbgpt.cli._profiles import get_profile
spec = get_profile("openai")
content = _render_profile_toml(spec, api_key="test-key")
assert "workspace/pilot/data" in content
def test_render_toml_uses_custom_home_in_data_path(self, isolated_dbgpt_home):
from dbgpt.cli._config import _render_profile_toml
from dbgpt.cli._profiles import get_profile
spec = get_profile("openai")
content = _render_profile_toml(spec, api_key="test-key")
# 路径中包含 isolated_dbgpt_home 的字符串
assert str(isolated_dbgpt_home) in content
assert "workspace/pilot/meta_data/dbgpt.db" in content
# Paths should NOT contain workspace prefix (old absolute pattern)
assert "workspace/pilot/meta_data" not in content
assert "workspace/pilot/data" not in content
class TestExtendedSignature:
@@ -218,14 +214,14 @@ class TestExtendedSignature:
class TestKimiEmbeddingEnvVar:
def test_kimi_embedding_uses_dashscope_env_var(self, isolated_dbgpt_home):
"""Kimi profile should reference DASHSCOPE_API_KEY for embeddings."""
def test_kimi_embedding_uses_openai_env_var(self, isolated_dbgpt_home):
"""Kimi profile should reference OPENAI_API_KEY for embeddings."""
from dbgpt.cli._config import _render_profile_toml
from dbgpt.cli._profiles import get_profile
spec = get_profile("kimi")
content = _render_profile_toml(spec, api_key=None)
assert "${env:DASHSCOPE_API_KEY:-sk-xxx}" in content
assert "${env:OPENAI_API_KEY:-sk-xxx}" in content
def test_kimi_llm_uses_moonshot_env_var(self, isolated_dbgpt_home):
"""Kimi profile LLM section should still reference MOONSHOT_API_KEY."""
@@ -248,8 +244,8 @@ class TestKimiEmbeddingEnvVar:
data = tomlkit.loads(content)
assert data["models"]["embeddings"][0]["api_key"] == "ds-key"
def test_kimi_embedding_api_url_is_dashscope(self, isolated_dbgpt_home):
"""Kimi embedding api_url should point to DashScope."""
def test_kimi_embedding_api_url_is_openai(self, isolated_dbgpt_home):
"""Kimi embedding api_url should point to OpenAI."""
import tomlkit
from dbgpt.cli._config import _render_profile_toml
@@ -259,7 +255,7 @@ class TestKimiEmbeddingEnvVar:
content = _render_profile_toml(spec, api_key=None)
data = tomlkit.loads(content)
assert data["models"]["embeddings"][0]["api_url"] == (
"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings"
"https://api.openai.com/v1/embeddings"
)
def test_openai_same_key_used_for_embeddings(self, isolated_dbgpt_home):

View File

@@ -112,26 +112,23 @@ class TestErrorHandling:
class TestKimiEmbedding:
"""Tests for Kimi embedding configuration using DashScope."""
"""Tests for Kimi embedding configuration using OpenAI."""
def test_kimi_embedding_uses_tongyi_provider(self):
def test_kimi_embedding_uses_openai_provider(self):
p = get_profile("kimi")
assert p.embedding_provider == "proxy/tongyi"
assert p.embedding_provider == "proxy/openai"
def test_kimi_embedding_model_is_text_embedding_v3(self):
def test_kimi_embedding_model_is_text_embedding_3_small(self):
p = get_profile("kimi")
assert p.embedding_model == "text-embedding-v3"
assert p.embedding_model == "text-embedding-3-small"
def test_kimi_embedding_api_url_is_dashscope(self):
def test_kimi_embedding_api_url_is_openai(self):
p = get_profile("kimi")
assert (
p.embedding_api_url
== "https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings"
)
assert p.embedding_api_url == "https://api.openai.com/v1/embeddings"
def test_kimi_has_separate_embedding_env_var(self):
p = get_profile("kimi")
assert p.embedding_env_var == "DASHSCOPE_API_KEY"
assert p.embedding_env_var == "OPENAI_API_KEY"
assert p.embedding_env_var != p.env_var
def test_kimi_llm_still_uses_moonshot_env_var(self):

View File

@@ -1,6 +1,6 @@
[project]
name = "dbgpt-ext"
version = "0.8.0rc6"
version = "0.8.0rc7"
description = "Add your description here"
authors = [
{ name = "csunny", email = "cfqcsunny@gmail.com" }

View File

@@ -1 +1 @@
version = "0.8.0rc6"
version = "0.8.0rc7"

View File

@@ -1,6 +1,6 @@
[project]
name = "dbgpt-sandbox"
version = "0.8.0rc6"
version = "0.8.0rc7"
description = "A secure sandbox execution environment for DB-GPT Agent"
authors = [
{ name = "csunny", email = "cfqcsunny@gmail.com" }

View File

@@ -1,6 +1,6 @@
[project]
name = "dbgpt-serve"
version = "0.8.0rc6"
version = "0.8.0rc7"
description = "Add your description here"
authors = [
{ name = "csunny", email = "cfqcsunny@gmail.com" }

View File

@@ -1 +1 @@
version = "0.8.0rc6"
version = "0.8.0rc7"

View File

@@ -1,6 +1,6 @@
[project]
name = "dbgpt-mono"
version = "0.8.0rc6"
version = "0.8.0rc7"
description = """DB-GPT is an experimental open-source project that uses localized GPT \
large models to interact with your data and environment. With this solution, you can be\
assured that there is no risk of data leakage, and your data is 100% private and secure.\

View File

@@ -12,7 +12,7 @@
# ║ 3. Install uv (if not already present) ║
# ║ 4. Clone (or update) the DB-GPT repository ║
# ║ 5. Run `uv sync` with the extras for the chosen profile ║
# ║ 6. Generate a user config from template
# ║ 6. Generate config via dbgpt setup wizard
# ║ 7. Print next-steps (start command, URL) ║
# ║ ║
# ║ What this script does NOT do: ║
@@ -56,20 +56,6 @@ _source_lib() {
_source_lib "common.sh"
_source_lib "profiles.sh"
# ── Fetch template file ──────────────────────────────────────────────────────
# Returns the local path to the template. Downloads from GitHub when needed.
_resolve_template() {
local name="$1"
if [[ -n "${SCRIPT_DIR}" && -f "${SCRIPT_DIR}/templates/${name}" ]]; then
echo "${SCRIPT_DIR}/templates/${name}"
else
local tmp
tmp="$(mktemp)"
curl -fsSL "${REMOTE_BASE}/templates/${name}" -o "${tmp}"
echo "${tmp}"
fi
}
# ── Default values ────────────────────────────────────────────────────────────
PROFILE=""
INSTALL_DIR="${DBGPT_INSTALL_DIR:-${HOME}/.dbgpt}"
@@ -79,6 +65,7 @@ USE_EXISTING_REPO="false"
MIRROR=""
YES="false"
START_AFTER_INSTALL="false"
USER_CONFIG=""
# ── Usage ─────────────────────────────────────────────────────────────────────
usage() {
@@ -89,7 +76,8 @@ Usage:
install.sh [options]
Options:
--profile <name> Deployment profile (currently: openai, kimi, minimax)
--profile <name> Deployment profile (openai, kimi, qwen, minimax, glm, custom, default)
--config <path> Use existing TOML config (skip config generation)
--install-dir <path> Where to install (default: ~/.dbgpt)
--version <git-ref> Git tag or branch to check out (default: main)
--repo-dir <path> Use an existing local DB-GPT checkout
@@ -99,7 +87,11 @@ Options:
-h, --help Show this help
Environment variables:
OPENAI_API_KEY Automatically injected into OpenAI config
OPENAI_API_KEY Automatically injected into OpenAI / custom / default / kimi(embedding) config
MOONSHOT_API_KEY Automatically injected into Kimi config
DASHSCOPE_API_KEY Automatically injected into Qwen config
MINIMAX_API_KEY Automatically injected into MiniMax config
ZHIPUAI_API_KEY Automatically injected into GLM config
DBGPT_INSTALL_DIR Override default install directory
DBGPT_REPO_DIR Reuse an existing local DB-GPT repo
DBGPT_VERSION Override default git ref
@@ -117,12 +109,21 @@ Examples:
# With Kimi / Moonshot API key
MOONSHOT_API_KEY=sk-xxx bash install.sh --profile kimi --yes
# With Minimax API key
# With Qwen / DashScope API key
DASHSCOPE_API_KEY=sk-xxx bash install.sh --profile qwen --yes
# With MiniMax API key
MINIMAX_API_KEY=sk-xxx bash install.sh --profile minimax --yes
# With GLM / ZhipuAI API key
ZHIPUAI_API_KEY=sk-xxx bash install.sh --profile glm --yes
# Reuse your current local repo (skip clone/update)
OPENAI_API_KEY=sk-xxx bash install.sh --profile openai --repo-dir . --yes
# Power-user: provide your own config file (skip config generation)
bash install.sh --config /path/to/my.toml --profile openai --yes
# China mirror
bash install.sh --profile openai --mirror china
EOF
@@ -165,6 +166,11 @@ parse_args() {
START_AFTER_INSTALL="true"
shift
;;
--config)
USER_CONFIG="${2:-}"
[[ -z "${USER_CONFIG}" ]] && die "--config requires a value"
shift 2
;;
-h|--help)
usage
exit 0
@@ -213,20 +219,30 @@ step_choose_profile() {
printf '%b' "${COLOR_CYAN}Select a deployment profile:${COLOR_RESET}\n"
printf ' 1) openai — OpenAI API proxy (recommended)\n'
printf ' 2) kimi — Kimi 2.5 via Moonshot API\n'
printf ' 3) minimax — MiniMax OpenAI-compatible API\n'
printf ' 3) qwen — Qwen via DashScope API\n'
printf ' 4) minimax — MiniMax OpenAI-compatible API\n'
printf ' 5) glm — GLM-5 via ZhipuAI API\n'
printf ' 6) custom — Custom OpenAI-compatible provider\n'
printf ' 7) default — Default (OpenAI-compatible)\n'
printf ' q) quit\n'
printf '\n'
printf '%b' "${COLOR_CYAN}Please select a profile by entering the corresponding number:${COLOR_RESET}\n"
printf '\n'
local choice
prompt_input "Enter choice [1]: " choice
choice="${choice:-1}"
case "${choice}" in
1|openai) PROFILE="openai" ;;
2|kimi) PROFILE="kimi" ;;
3|minimax) PROFILE="minimax" ;;
q|Q) info "Installation cancelled."; exit 0 ;;
*) die "Invalid choice: ${choice}" ;;
1|openai) PROFILE="openai" ;;
2|kimi) PROFILE="kimi" ;;
3|qwen) PROFILE="qwen" ;;
4|minimax) PROFILE="minimax" ;;
5|glm) PROFILE="glm" ;;
6|custom) PROFILE="custom" ;;
7|default) PROFILE="default" ;;
q|Q) info "Installation cancelled."; exit 0 ;;
*) die "Invalid choice: ${choice}" ;;
esac
}
@@ -266,7 +282,7 @@ step_apply_mirror() {
}
step_prepare_dirs() {
mkdir -p "${INSTALL_DIR}/configs"
mkdir -p "${INSTALL_DIR}"
}
resolve_repo_dir() {
@@ -340,37 +356,46 @@ step_install_deps() {
success "Dependencies installed."
}
step_generate_config() {
local template_name
template_name="$(profile_template "${PROFILE}")"
step_check_api_key() {
local env_name
env_name="$(profile_api_key_env "${PROFILE}")"
local template_path
template_path="$(_resolve_template "${template_name}")"
local target_path="${INSTALL_DIR}/configs/${template_name}"
if [[ -f "${target_path}" ]]; then
if ! confirm "Config already exists: ${target_path}. Overwrite?"; then
info "Keeping existing config."
return
fi
# Primary API key check
if [[ -n "${env_name}" ]] && [[ -z "${!env_name:-}" ]]; then
warn "Environment variable ${env_name} is not set."
warn "The wizard will generate config with a placeholder."
warn "Set it before starting: export ${env_name}=sk-xxx"
fi
cp "${template_path}" "${target_path}"
# Kimi special handling: also needs OPENAI_API_KEY for embeddings
if [[ "${PROFILE}" == "kimi" ]] && [[ -z "${OPENAI_API_KEY:-}" ]]; then
warn "Kimi profile also needs OPENAI_API_KEY for embeddings."
warn "Set it before starting: export OPENAI_API_KEY=sk-xxx"
fi
}
# Inject API key from environment if available
local api_key_env api_key_token
step_generate_config() {
info "Generating configuration via dbgpt setup..."
local setup_args=(dbgpt setup --profile "${PROFILE}" --yes)
# If user explicitly provided an API key via environment, pass it through
local api_key_env
api_key_env="$(profile_api_key_env "${PROFILE}")"
api_key_token="$(profile_api_key_token "${PROFILE}")"
if [[ -n "${api_key_env}" && -n "${!api_key_env:-}" ]]; then
setup_args+=(--api-key "${!api_key_env}")
fi
if [[ -n "${api_key_env}" && -n "${api_key_token}" ]]; then
local api_key_value="${!api_key_env:-}"
if [[ -n "${api_key_value}" ]]; then
replace_token "${target_path}" "${api_key_token}" "${api_key_value}"
success "API key injected from \$${api_key_env}."
else
warn "\$${api_key_env} is not set. Please edit ${target_path} and fill in your API key before starting."
fi
(
cd "${REPO_DIR}"
run "Running dbgpt setup..." uv run "${setup_args[@]}"
)
local config_path="${HOME}/.dbgpt/configs/${PROFILE}.toml"
if [[ -f "${config_path}" ]]; then
success "Config written to ${config_path}"
else
die "Config generation failed — ${config_path} not found"
fi
}
@@ -389,9 +414,7 @@ step_validate() {
step_print_summary() {
local repo_dir="${REPO_DIR}"
local template_name
template_name="$(profile_template "${PROFILE}")"
local config_path="${INSTALL_DIR}/configs/${template_name}"
local config_path="${HOME}/.dbgpt/configs/${PROFILE}.toml"
printf '%b' "
${COLOR_GREEN}════════════════════════════════════════════════════════════${COLOR_RESET}
@@ -404,11 +427,11 @@ ${COLOR_GREEN}══════════════════════
${COLOR_CYAN}Next steps:${COLOR_RESET}
1. Review / edit your config (set API key if not done):
1. Review / Edit your config (set Custom API key Or BaseURL if not done):
${COLOR_YELLOW}${config_path}${COLOR_RESET}
2. Start DB-GPT:
${COLOR_YELLOW}cd \"${repo_dir}\" && uv run dbgpt start webserver --config \"${config_path}\"${COLOR_RESET}
${COLOR_YELLOW}cd \"${repo_dir}\" && uv run dbgpt start webserver --profile ${PROFILE}${COLOR_RESET}
3. Open your browser:
${COLOR_YELLOW}http://localhost:5670${COLOR_RESET}
@@ -422,14 +445,14 @@ step_start_if_requested() {
fi
local repo_dir="${REPO_DIR}"
local template_name
template_name="$(profile_template "${PROFILE}")"
local config_path="${INSTALL_DIR}/configs/${template_name}"
info "Starting DB-GPT server..."
(
cd "${repo_dir}"
exec uv run dbgpt start webserver --config "${config_path}"
if [[ -n "${USER_CONFIG:-}" ]]; then
exec uv run dbgpt start webserver --config "${USER_CONFIG}"
else
exec uv run dbgpt start webserver --profile "${PROFILE}"
fi
)
}
@@ -452,18 +475,39 @@ BANNER
parse_args "$@"
step_check_platform
step_ensure_base_commands
step_choose_profile
validate_profile "${PROFILE}"
step_apply_mirror
step_prepare_dirs
resolve_repo_dir
step_ensure_uv
step_clone_or_update_repo
step_install_deps
step_generate_config
step_validate
step_print_summary
step_start_if_requested
if [[ -n "${USER_CONFIG:-}" ]]; then
[[ -f "${USER_CONFIG}" ]] || die "Config file not found: ${USER_CONFIG}"
info "Using user-provided config: ${USER_CONFIG}"
if [[ -z "${PROFILE}" ]]; then
PROFILE="openai"
info "No --profile specified with --config; defaulting to 'openai' for dependency extras."
fi
validate_profile "${PROFILE}"
step_apply_mirror
step_prepare_dirs
resolve_repo_dir
step_ensure_uv
step_clone_or_update_repo
step_install_deps
step_validate
step_print_summary
step_start_if_requested
else
step_choose_profile
validate_profile "${PROFILE}"
step_apply_mirror
step_prepare_dirs
resolve_repo_dir
step_ensure_uv
step_clone_or_update_repo
step_install_deps
step_check_api_key
step_generate_config
step_validate
step_print_summary
step_start_if_requested
fi
}
main "$@"

View File

@@ -88,29 +88,3 @@ confirm() {
[[ "${answer}" =~ ^[Yy]$ ]]
}
# ── String helpers ────────────────────────────────────────────────────────────
# Replace a placeholder token inside a file with a real value.
# Usage: replace_token <file> <token> <value>
# Example: replace_token config.toml "__OPENAI_API_KEY__" "sk-xxx"
replace_token() {
local file="$1"
local token="$2"
local value="$3"
if [[ ! -f "${file}" ]]; then
die "replace_token: file not found: ${file}"
fi
# Use python3 for safe in-place replacement (avoids sed portability issues
# between macOS and Linux). We pass values through environment variables to
# avoid shell-injection via triple-quote escapes.
_RT_FILE="${file}" _RT_TOKEN="${token}" _RT_VALUE="${value}" python3 -c "
import os
from pathlib import Path
p = Path(os.environ['_RT_FILE'])
text = p.read_text()
text = text.replace(os.environ['_RT_TOKEN'], os.environ['_RT_VALUE'])
p.write_text(text)
"
}

View File

@@ -3,18 +3,17 @@
#
# Each profile maps to:
# 1. A set of uv extras (fed to `uv sync --extra ...`)
# 2. A config template under templates/
# 3. The official config file path in the repo (for reference)
# 2. The API key environment variable name
# ── Validation ────────────────────────────────────────────────────────────────
# Currently supported profiles. Extend this list when adding new profiles.
readonly SUPPORTED_PROFILES="openai kimi minimax"
readonly SUPPORTED_PROFILES="openai kimi qwen minimax glm custom default"
validate_profile() {
local profile="$1"
case "${profile}" in
openai|kimi|minimax) ;;
openai|kimi|qwen|minimax|glm|custom|default) ;;
*)
die "Unsupported profile: ${profile}. Supported profiles: ${SUPPORTED_PROFILES}"
;;
@@ -44,6 +43,15 @@ proxy_openai
rag
storage_chromadb
dbgpts
EOF
;;
qwen)
cat <<'EOF'
base
proxy_openai
rag
storage_chromadb
dbgpts
EOF
;;
minimax)
@@ -53,6 +61,33 @@ proxy_openai
rag
storage_chromadb
dbgpts
EOF
;;
glm)
cat <<'EOF'
base
proxy_openai
rag
storage_chromadb
dbgpts
EOF
;;
custom)
cat <<'EOF'
base
proxy_openai
rag
storage_chromadb
dbgpts
EOF
;;
default)
cat <<'EOF'
base
proxy_openai
rag
storage_chromadb
dbgpts
EOF
;;
*)
@@ -61,31 +96,6 @@ EOF
esac
}
# ── Config template name ──────────────────────────────────────────────────────
# Returns the template filename (relative to templates/ dir).
profile_template() {
local profile="$1"
case "${profile}" in
openai) echo "openai.toml" ;;
kimi) echo "kimi.toml" ;;
minimax) echo "minimax.toml" ;;
*) die "No template defined for profile: ${profile}" ;;
esac
}
# ── Repo config path (for display / fallback) ────────────────────────────────
profile_repo_config() {
local profile="$1"
case "${profile}" in
openai) echo "configs/dbgpt-proxy-openai.toml" ;;
kimi) echo "configs/dbgpt-proxy-moonshot.toml" ;;
minimax) echo "configs/dbgpt-proxy-openai.toml" ;;
*) die "No repo config path defined for profile: ${profile}" ;;
esac
}
# ── Environment variable name for API key ─────────────────────────────────────
profile_api_key_env() {
@@ -93,19 +103,11 @@ profile_api_key_env() {
case "${profile}" in
openai) echo "OPENAI_API_KEY" ;;
kimi) echo "MOONSHOT_API_KEY" ;;
qwen) echo "DASHSCOPE_API_KEY" ;;
minimax) echo "MINIMAX_API_KEY" ;;
*) echo "" ;;
esac
}
# ── Placeholder token in config template ──────────────────────────────────────
profile_api_key_token() {
local profile="$1"
case "${profile}" in
openai) echo "__OPENAI_API_KEY__" ;;
kimi) echo "__MOONSHOT_API_KEY__" ;;
minimax) echo "__MINIMAX_API_KEY__" ;;
glm) echo "ZHIPUAI_API_KEY" ;;
custom) echo "OPENAI_API_KEY" ;;
default) echo "OPENAI_API_KEY" ;;
*) echo "" ;;
esac
}

View File

@@ -1,34 +0,0 @@
# DB-GPT Quick Install - Kimi 2.5 Profile
# Generated by install.sh. Edit the __PLACEHOLDERS__ below before starting.
[system]
language = "${env:DBGPT_LANG:-en}"
api_keys = []
# Server Configurations
[service.web]
host = "0.0.0.0"
port = 5670
[service.web.database]
type = "sqlite"
path = "pilot/meta_data/dbgpt.db"
[rag.storage]
[rag.storage.vector]
type = "chroma"
persist_path = "pilot/data"
# Model Configurations
[models]
[[models.llms]]
name = "kimi-k2-turbo-preview"
provider = "proxy/moonshot"
api_base = "https://api.moonshot.ai/v1"
api_key = "__MOONSHOT_API_KEY__"
[[models.embeddings]]
name = "text-embedding-3-small"
provider = "proxy/openai"
api_url = "https://api.openai.com/v1/embeddings"
api_key = "__MOONSHOT_API_KEY__"

View File

@@ -1,34 +0,0 @@
# DB-GPT Quick Install - OpenAI Profile
# Generated by install.sh. Edit the __PLACEHOLDERS__ below before starting.
[system]
language = "${env:DBGPT_LANG:-en}"
api_keys = []
# Server Configurations
[service.web]
host = "0.0.0.0"
port = 5670
[service.web.database]
type = "sqlite"
path = "pilot/meta_data/dbgpt.db"
[rag.storage]
[rag.storage.vector]
type = "chroma"
persist_path = "pilot/data"
# Model Configurations
[models]
[[models.llms]]
name = "gpt-4o"
provider = "proxy/openai"
api_base = "https://api.openai.com/v1"
api_key = "__OPENAI_API_KEY__"
[[models.embeddings]]
name = "text-embedding-3-small"
provider = "proxy/openai"
api_url = "https://api.openai.com/v1/embeddings"
api_key = "__OPENAI_API_KEY__"

100
uv.lock generated

File diff suppressed because one or more lines are too long