refactor: setup-plugins writes config via openclaw config set

Instead of just exporting env vars (which are ephemeral), the script
now calls 'openclaw config set' to persist each plugin's sensitive
fields (apiKey, tokens, ports, etc.) under plugins.entries.<id>.config.

Config key mapping per plugin is derived from each plugin's
openclaw.plugin.json configSchema. .env.example updated with all
available variables and their corresponding plugin IDs.
This commit is contained in:
2026-04-16 08:02:54 +00:00
parent 7eb3d177e0
commit 601262abec
2 changed files with 152 additions and 77 deletions

View File

@@ -1,18 +1,35 @@
# HangmanLab.Server.T2 — Plugin Configuration
# Copy to .env and fill in values. This file is gitignored.
# Values are written to openclaw config via 'openclaw config set'.
# ── OpenClaw ─────────────────────────────────────────────────────────────────
OPENCLAW_PATH=~/.openclaw
# ── HarborForge Plugin ───────────────────────────────────────────────────────
# ── HarborForge Plugin (harbor-forge) ────────────────────────────────────────
HF_BACKEND_URL=https://hf-api.hangman-lab.top
HF_API_KEY=
HF_MONITOR_IDENTIFIER=
HF_MONITOR_PORT=
HF_REPORT_INTERVAL=30
HF_CALENDAR_API_KEY=
# ── Yonexus.Server ───────────────────────────────────────────────────────────
YONEXUS_PORT=18900
YONEXUS_SECRET=
# ── ContractorAgent ──────────────────────────────────────────────────────────
# ── ContractorAgent (contractor-agent) ───────────────────────────────────────
CONTRACTOR_BRIDGE_PORT=18800
CONTRACTOR_BRIDGE_API_KEY=
# ── Dirigent (dirigent) ──────────────────────────────────────────────────────
DIRIGENT_MODERATOR_BOT_TOKEN=
DIRIGENT_SIDECAR_PORT=
DIRIGENT_NO_REPLY_PROVIDER=
DIRIGENT_NO_REPLY_MODEL=
DIRIGENT_SCHEDULE_IDENTIFIER=
# ── PaddedCell (padded-cell) ─────────────────────────────────────────────────
PADDEDCELL_SECRET_MGR_PATH=
PADDEDCELL_OPENCLAW_PATH=
# ── Yonexus.Server (yonexus-server) ──────────────────────────────────────────
YONEXUS_PORT=18900
YONEXUS_NOTIFY_BOT_TOKEN=
YONEXUS_ADMIN_USER_ID=
YONEXUS_PUBLIC_WS_URL=

View File

@@ -16,6 +16,30 @@ ok() { printf "${GREEN} ✓${NC} %s\n" "$*"; }
warn() { printf "${YELLOW}${NC} %s\n" "$*"; }
err() { printf "${RED}${NC} %s\n" "$*"; }
oc_set_str() {
local key="$1" val="$2"
if [[ -n "$val" ]]; then
openclaw config set "$key" "\"$val\"" --json
ok "config: $key"
fi
}
oc_set_num() {
local key="$1" val="$2"
if [[ -n "$val" ]]; then
openclaw config set "$key" "$val" --json
ok "config: $key = $val"
fi
}
oc_set_bool() {
local key="$1" val="$2"
if [[ -n "$val" ]]; then
openclaw config set "$key" "$val" --json
ok "config: $key = $val"
fi
}
usage() {
cat <<EOF
Usage: $(basename "$0") [options] [plugin ...]
@@ -28,11 +52,13 @@ Options:
--list List available plugins and exit
--uninstall Uninstall plugins instead of installing
--skip-deps Skip npm install step
--skip-config Skip openclaw config set step
-h, --help Show this help
Plugins: PaddedCell, ContractorAgent, Dirigent, HarborForge.OpenclawPlugin, Yonexus.Server
Sensitive configuration is read from .env (see .env.example for reference).
Sensitive configuration is read from .env (see .env.example for reference)
and written to openclaw config via 'openclaw config set'.
EOF
exit 0
}
@@ -41,6 +67,7 @@ EOF
UNINSTALL=false
SKIP_DEPS=false
SKIP_CONFIG=false
SELECTED_PLUGINS=()
while [[ $# -gt 0 ]]; do
@@ -49,6 +76,7 @@ while [[ $# -gt 0 ]]; do
--list) ls "$PLUGINS_DIR"; exit 0 ;;
--uninstall) UNINSTALL=true; shift ;;
--skip-deps) SKIP_DEPS=true; shift ;;
--skip-config) SKIP_CONFIG=true; shift ;;
-h|--help) usage ;;
-*) err "Unknown option: $1"; usage ;;
*) SELECTED_PLUGINS+=("$1"); shift ;;
@@ -93,7 +121,7 @@ for p in "${SELECTED_PLUGINS[@]}"; do
fi
done
# ── Per-plugin install/uninstall ─────────────────────────────────────────────
# ── Per-plugin helpers ───────────────────────────────────────────────────────
install_deps() {
local dir="$1"
@@ -122,79 +150,109 @@ find_install_script() {
done
}
run_install_script() {
local name="$1" dir="$2" action="$3"
local script
script=$(find_install_script "$dir")
if [[ -n "$script" ]]; then
log " Running $(basename "$script") --$action"
node "$script" "--$action" || {
err "$name script failed"
return 1
}
return 0
fi
if [[ "$action" == "install" ]] && [[ -f "$dir/package.json" ]]; then
if grep -q "\"install-plugin\"" "$dir/package.json" 2>/dev/null; then
log " Running npm run install-plugin"
(cd "$dir" && npm run install-plugin)
return $?
elif grep -q "\"postinstall\"" "$dir/package.json" 2>/dev/null; then
log " Running npm run postinstall"
(cd "$dir" && npm run postinstall)
return $?
fi
fi
warn "No install script found for $name"
return 0
}
# ── Plugin config mapping ────────────────────────────────────────────────────
# Maps .env variables → openclaw config keys via 'openclaw config set'.
# Each plugin's config lives under plugins.entries.<id>.config.*
configure_plugin() {
local name="$1"
if [[ "$SKIP_CONFIG" == true ]]; then return; fi
log " Writing openclaw config"
case "$name" in
HarborForge.OpenclawPlugin)
local P="plugins.entries.harbor-forge.config"
oc_set_str "$P.backendUrl" "${HF_BACKEND_URL:-}"
oc_set_str "$P.apiKey" "${HF_API_KEY:-}"
oc_set_str "$P.identifier" "${HF_MONITOR_IDENTIFIER:-}"
oc_set_num "$P.monitor_port" "${HF_MONITOR_PORT:-}"
oc_set_num "$P.reportIntervalSec" "${HF_REPORT_INTERVAL:-}"
oc_set_str "$P.calendarApiKey" "${HF_CALENDAR_API_KEY:-}"
oc_set_bool "$P.enabled" "true"
;;
ContractorAgent)
local P="plugins.entries.contractor-agent.config"
oc_set_num "$P.bridgePort" "${CONTRACTOR_BRIDGE_PORT:-}"
oc_set_str "$P.bridgeApiKey" "${CONTRACTOR_BRIDGE_API_KEY:-}"
;;
Dirigent)
local P="plugins.entries.dirigent.config"
oc_set_str "$P.moderatorBotToken" "${DIRIGENT_MODERATOR_BOT_TOKEN:-}"
oc_set_num "$P.sideCarPort" "${DIRIGENT_SIDECAR_PORT:-}"
oc_set_str "$P.noReplyProvider" "${DIRIGENT_NO_REPLY_PROVIDER:-}"
oc_set_str "$P.noReplyModel" "${DIRIGENT_NO_REPLY_MODEL:-}"
oc_set_str "$P.scheduleIdentifier" "${DIRIGENT_SCHEDULE_IDENTIFIER:-}"
;;
PaddedCell)
local P="plugins.entries.padded-cell.config"
oc_set_str "$P.secretMgrPath" "${PADDEDCELL_SECRET_MGR_PATH:-}"
oc_set_str "$P.openclawProfilePath" "${PADDEDCELL_OPENCLAW_PATH:-}"
oc_set_bool "$P.enabled" "true"
;;
Yonexus.Server)
local P="plugins.entries.yonexus-server.config"
oc_set_str "$P.notifyBotToken" "${YONEXUS_NOTIFY_BOT_TOKEN:-}"
oc_set_str "$P.adminUserId" "${YONEXUS_ADMIN_USER_ID:-}"
oc_set_num "$P.listenPort" "${YONEXUS_PORT:-}"
oc_set_str "$P.publicWsUrl" "${YONEXUS_PUBLIC_WS_URL:-}"
;;
*)
warn "No config mapping for $name"
;;
esac
}
# ── Main loop ────────────────────────────────────────────────────────────────
run_plugin() {
local name="$1"
local dir="$PLUGINS_DIR/$name"
local action="install"
[[ "$UNINSTALL" == true ]] && action="uninstall"
echo
log "[$action] $name"
if [[ "$UNINSTALL" == true ]]; then
local script
script=$(find_install_script "$dir")
if [[ -n "$script" ]]; then
node "$script" --uninstall || warn "$name uninstall script returned non-zero"
else
warn "No install script found for $name — skipping"
fi
return
log "[uninstall] $name"
run_install_script "$name" "$dir" "uninstall"
return $?
fi
# Install dependencies
log "[install] $name"
install_deps "$dir"
# Plugin-specific env setup (pass through to install scripts via env)
case "$name" in
HarborForge.OpenclawPlugin)
export HF_BACKEND_URL="${HF_BACKEND_URL:-}"
export HF_API_KEY="${HF_API_KEY:-}"
export HF_MONITOR_IDENTIFIER="${HF_MONITOR_IDENTIFIER:-}"
;;
Yonexus.Server)
export YONEXUS_PORT="${YONEXUS_PORT:-}"
export YONEXUS_SECRET="${YONEXUS_SECRET:-}"
;;
ContractorAgent)
export CONTRACTOR_BRIDGE_PORT="${CONTRACTOR_BRIDGE_PORT:-18800}"
export CONTRACTOR_BRIDGE_API_KEY="${CONTRACTOR_BRIDGE_API_KEY:-}"
;;
esac
# Run install script
local script
script=$(find_install_script "$dir")
if [[ -n "$script" ]]; then
log " Running $(basename "$script")"
node "$script" --install || {
err "$name install script failed"
return 1
run_install_script "$name" "$dir" "install" || return $?
configure_plugin "$name"
ok "$name done"
}
ok "$name installed"
else
# Some plugins (like PaddedCell) may have a different layout
if [[ -f "$dir/package.json" ]] && grep -q '"install-plugin"' "$dir/package.json" 2>/dev/null; then
log " Running npm run install-plugin"
(cd "$dir" && npm run install-plugin) || {
err "$name install failed"
return 1
}
ok "$name installed"
elif [[ -f "$dir/package.json" ]] && grep -q '"postinstall"' "$dir/package.json" 2>/dev/null; then
log " Running npm run postinstall"
(cd "$dir" && npm run postinstall) || {
err "$name install failed"
return 1
}
ok "$name installed"
else
warn "No install script found for $name — submodule present but not auto-installable"
fi
fi
}
# ── Main ─────────────────────────────────────────────────────────────────────
FAILURES=0