Seed model and search settings on service start
Why: a freshly deployed environment boots with an empty settings store, so the first run dies with "main model unconfigured" and the user has to open the settings UI before anything works - the opposite of one-command bring-up. Evidence: live matrix - full seed (chat+lightweight+tavily) lands in the settings store (API view shows baseUrl/model with the key masked), restart without flags does not re-seed and the settings persist, .svc.env sourcing seeds a fresh environment from the one-time config file, and a no-flag start stays silent. Also wrapped a /proc read race in pid_alive that printed tr noise during stop. Impact: --model-base/--model-key/--model-name, --light-base/-key/ -name, --tavily-keys on start/deploy (idempotent, only provided fields); SVC_MODEL_*/SVC_LIGHT_*/SVC_TAVILY_KEYS env vars; <repo>/ .svc.env one-time config file (gitignored) makes every future deploy self-configuring; auth-protected instances fall back to a clear hint. Refs: feature/svc-auto-seed task card.
This commit is contained in:
+66
-2
@@ -17,16 +17,24 @@
|
||||
# --auth on|off|auto API key 认证(默认 auto:PG 档开、嵌入式关)
|
||||
# --mock 演示模式(dev 常用)
|
||||
# --plugins dir 插件目录(默认 <repo>/plugins)
|
||||
# --model-base URL 启动后自动播种主模型配置(settings.models.chat.baseUrl)
|
||||
# --model-key KEY 主模型 API Key(播种用;勿写入脚本/仓库)
|
||||
# --model-name NAME 主模型名称
|
||||
# --light-base/--light-key/--light-name 轻量模型(标题生成等;可选)
|
||||
# --tavily-keys K1,K2 网络搜索密钥池(播种 tools.tavily.apiKeys)
|
||||
# -- <剩余参数> 原样透传给 agent-system serve(escape hatch)
|
||||
#
|
||||
# 环境变量默认值:
|
||||
# dev: 127.0.0.1:8788 数据 runtime/dev/data;SVC_DEV_ADDR/DATA/MOCK=1 可覆盖
|
||||
# prod: 127.0.0.1:8787 数据 runtime/prod/data;SVC_PROD_ADDR/DATA/DSN/AUTH 可覆盖
|
||||
#
|
||||
# 一次性配置:把 SVC_MODEL_BASE/SVC_MODEL_KEY/SVC_MODEL_NAME 等写入 <repo>/.svc.env
|
||||
#(已 gitignore),此后每次 start/deploy 自动播种,服务起来即可用。
|
||||
#
|
||||
# 示例:
|
||||
# scripts/svc.sh dev --port 9000 --mock
|
||||
# scripts/svc.sh prod --host 0.0.0.0 --dsn postgres://u:p@127.0.0.1:5432/as
|
||||
# scripts/svc.sh dev deploy --addr 0.0.0.0:8788
|
||||
# scripts/svc.sh dev --model-base https://api.xxx.com/v1 --model-key sk-xx --model-name glm-4.7
|
||||
# make svc ENV=dev ARGS="--port 9000"
|
||||
#
|
||||
# 安全约束:
|
||||
@@ -38,6 +46,10 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
RUNTIME="$ROOT/runtime"
|
||||
BIN="$ROOT/bin/agent-system"
|
||||
|
||||
# 一次性配置文件(含密钥,已 gitignore):SVC_MODEL_* 等在此设好后每次启动自动生效。
|
||||
# shellcheck disable=SC1090
|
||||
[ -f "$ROOT/.svc.env" ] && . "$ROOT/.svc.env"
|
||||
|
||||
c_info() { printf '\033[1;34m[svc]\033[0m %s\n' "$*"; }
|
||||
c_ok() { printf '\033[1;32m[svc]\033[0m %s\n' "$*"; }
|
||||
c_warn() { printf '\033[1;33m[svc]\033[0m %s\n' "$*"; }
|
||||
@@ -50,6 +62,8 @@ usage() {
|
||||
# ---- 命令行参数(覆盖层)----
|
||||
CLI_ADDR=""; CLI_HOST=""; CLI_PORT=""; CLI_DATA=""; CLI_DSN=""
|
||||
CLI_AUTH=""; CLI_MOCK=0; CLI_PLUGINS=""; CLI_EXTRA=""; CLI_LOGS_N=""
|
||||
CLI_MBASE=""; CLI_MKEY=""; CLI_MNAME=""
|
||||
CLI_LBASE=""; CLI_LKEY=""; CLI_LNAME=""; CLI_TAVILY=""
|
||||
|
||||
need_value() { [ $# -ge 2 ] || { c_err "参数 $1 需要值"; exit 2; }; }
|
||||
|
||||
@@ -64,6 +78,13 @@ parse_args() {
|
||||
--auth) need_value "$@"; CLI_AUTH="$2"; shift 2 ;;
|
||||
--plugins) need_value "$@"; CLI_PLUGINS="$2"; shift 2 ;;
|
||||
--mock) CLI_MOCK=1; shift ;;
|
||||
--model-base) need_value "$@"; CLI_MBASE="$2"; shift 2 ;;
|
||||
--model-key) need_value "$@"; CLI_MKEY="$2"; shift 2 ;;
|
||||
--model-name) need_value "$@"; CLI_MNAME="$2"; shift 2 ;;
|
||||
--light-base) need_value "$@"; CLI_LBASE="$2"; shift 2 ;;
|
||||
--light-key) need_value "$@"; CLI_LKEY="$2"; shift 2 ;;
|
||||
--light-name) need_value "$@"; CLI_LNAME="$2"; shift 2 ;;
|
||||
--tavily-keys) need_value "$@"; CLI_TAVILY="$2"; shift 2 ;;
|
||||
--) shift; CLI_EXTRA="$*"; break ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) c_err "未知参数:$1"; usage; exit 2 ;;
|
||||
@@ -117,7 +138,7 @@ pid_alive() {
|
||||
local pid="$1"
|
||||
[ -n "$pid" ] && [ -r "/proc/$pid/cmdline" ] || return 1
|
||||
local cmd
|
||||
cmd="$(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null)" || return 1
|
||||
cmd="$( { tr '\0' ' ' < "/proc/$pid/cmdline"; } 2>/dev/null )" || return 1
|
||||
case "$cmd" in
|
||||
*agent-system*serve*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
@@ -164,6 +185,48 @@ do_build() {
|
||||
fi
|
||||
}
|
||||
|
||||
# seed_settings:把 CLI/环境变量给出的模型与搜索配置写入 settings(幂等;
|
||||
# 只写明确给出的字段;设置持久化在环境数据目录——播种一次后续启动无需再传)。
|
||||
seed_settings() {
|
||||
local host="$1" port="$2"
|
||||
local cb="${CLI_MBASE:-${SVC_MODEL_BASE:-}}" ck="${CLI_MKEY:-${SVC_MODEL_KEY:-}}" cn="${CLI_MNAME:-${SVC_MODEL_NAME:-}}"
|
||||
local lb="${CLI_LBASE:-${SVC_LIGHT_BASE:-}}" lk="${CLI_LKEY:-${SVC_LIGHT_KEY:-}}" ln="${CLI_LNAME:-${SVC_LIGHT_NAME:-}}"
|
||||
local tk="${CLI_TAVILY:-${SVC_TAVILY_KEYS:-}}"
|
||||
[ -z "$cb$ck$cn$lb$lk$ln$tk" ] && return 0
|
||||
command -v python3 >/dev/null 2>&1 || { c_warn "[$ENV_NAME] 跳过配置播种:需要 python3 构造请求"; return 0; }
|
||||
local payload
|
||||
payload="$(python3 - "$cb" "$ck" "$cn" "$lb" "$lk" "$ln" "$tk" <<'PY'
|
||||
import json, sys
|
||||
cb, ck, cn, lb, lk, ln, tk = sys.argv[1:8]
|
||||
out = {}
|
||||
def sub(base, key, name):
|
||||
d = {}
|
||||
if base: d["baseUrl"] = base
|
||||
if key: d["apiKey"] = key
|
||||
if name: d["model"] = name
|
||||
return d
|
||||
chat, light = sub(cb, ck, cn), sub(lb, lk, ln)
|
||||
models = {}
|
||||
if chat: models["chat"] = chat
|
||||
if light: models["lightweight"] = light
|
||||
if models: out["models"] = models
|
||||
if tk: out["tools"] = {"tavily": {"apiKeys": tk}}
|
||||
print(json.dumps(out))
|
||||
PY
|
||||
)"
|
||||
local resp
|
||||
resp="$(curl -s -m 5 -X PUT "http://$host:$port/api/settings/user" -H 'Content-Type: application/json' -d "$payload")"
|
||||
if echo "$resp" | grep -q '"ok": *true'; then
|
||||
local did=""
|
||||
[ -n "$cb$ck$cn" ] && did="主模型"
|
||||
[ -n "$lb$lk$ln" ] && did="${did:+$did、}轻量模型"
|
||||
[ -n "$tk" ] && did="${did:+$did、}Tavily"
|
||||
c_ok "[$ENV_NAME] 已播种设置:$did(持久化于 $ENV_DATA,后续启动无需再传)"
|
||||
else
|
||||
c_warn "[$ENV_NAME] 设置播种未成功:${resp:-<无响应>}(若开启了 API key 认证,需在设置页手动配置)"
|
||||
fi
|
||||
}
|
||||
|
||||
do_start() {
|
||||
if pid_alive "$(read_pid)"; then
|
||||
c_warn "[$ENV_NAME] 已在运行 pid=$(read_pid)(如需换参数/新版本请用 deploy/restart)"
|
||||
@@ -190,6 +253,7 @@ do_start() {
|
||||
for _ in $(seq 1 100); do
|
||||
if curl -s -o /dev/null -m 2 "http://$host:$port/" 2>/dev/null; then
|
||||
c_ok "[$ENV_NAME] 已启动 pid=$(cat "$ENV_PID") → http://$host:$port(日志:$ENV_LOG)"
|
||||
seed_settings "$host" "$port"
|
||||
return 0
|
||||
fi
|
||||
pid_alive "$(read_pid)" || { c_err "[$ENV_NAME] 进程启动后即退出,查看日志:tail -40 $ENV_LOG"; exit 1; }
|
||||
|
||||
Reference in New Issue
Block a user