mirror of
https://github.com/wanikua/danghuangshang.git
synced 2026-09-02 22:44:36 +08:00
fix: 全面审查修复 — 安装脚本/JSON配置/Docker/CI
P0 修复: - install-mac.sh: 修复 create_agent_workspaces() 函数被错误粘贴的注入人设代码块破坏, 提取为独立步骤;删除重复的 skill 安装块;移除 set -e 下的 $? 死代码 - gui/keepalive.sh: SERVER_DIR 路径从 gui/server 改为 server - gui/server/keepalive.sh: SERVER_DIR 路径从 gui/server 改为当前目录 - package.json: 合并两个重复的 scripts 块,恢复 jest 为主 test 命令 - .dockerignore: 添加 !**/package-lock.json 例外,修复 npm ci 构建失败 - 删除 docker.yml(与 docker-build.yml 重复,tag push 会触发两次构建) P1 修复: - docker-build.yml: 升级 build-push-action v5->v6,启用 provenance/sbom, Trivy 锁定到 0.28.0(不用 @master),添加 build step id,workflow 级 permissions - install.ps1: 配置路径从 ~/clawd/ 改为 ~/.openclaw/(与 Bash 脚本一致), MSI 路径引号防空格,添加 ErrorActionPreference,下载失败生成最小配置兜底 - configs/modern-ceo/openclaw.json: CMO agent id 从 cmk 改为 cmo(4处 typo) - docker/entrypoint.sh: Python 代码改用环境变量传递路径,消除注入风险 - install-lite.sh: 移除 set -e 下的 $? 死代码 - ci.yml + duchayuan-review.yml: 添加 permissions: contents: read Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -55,6 +55,7 @@ memory/
|
||||
logs/
|
||||
*.pid
|
||||
*.lock
|
||||
!**/package-lock.json
|
||||
|
||||
# 嵌套仓库(可选,减小镜像体积)
|
||||
meow/
|
||||
|
||||
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
@@ -7,6 +7,9 @@ on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint-and-validate:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
25
.github/workflows/docker-build.yml
vendored
25
.github/workflows/docker-build.yml
vendored
@@ -6,6 +6,11 @@ on:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
security-events: write
|
||||
|
||||
env:
|
||||
REGISTRY: docker.io
|
||||
IMAGE_NAME: boluobobo/ai-court
|
||||
@@ -13,9 +18,6 @@ env:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -47,7 +49,8 @@ jobs:
|
||||
type=ref,event=tag
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
@@ -57,20 +60,12 @@ jobs:
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
BUILDKIT_INLINE_CACHE=1
|
||||
provenance: false
|
||||
sbom: false
|
||||
provenance: true
|
||||
sbom: true
|
||||
|
||||
- name: Image digest
|
||||
run: echo ${{ steps.build.outputs.digest }}
|
||||
|
||||
- name: Check image size
|
||||
if: always()
|
||||
run: |
|
||||
echo "Image size:"
|
||||
docker images ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} --format "{{.Size}}"
|
||||
|
||||
security-scan:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
@@ -79,7 +74,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
uses: aquasecurity/trivy-action@0.28.0
|
||||
with:
|
||||
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
format: 'sarif'
|
||||
|
||||
37
.github/workflows/docker.yml
vendored
37
.github/workflows/docker.yml
vendored
@@ -1,37 +0,0 @@
|
||||
name: Build & Push Docker (multi-arch)
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ['v*']
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
DOCKERHUB_IMAGE: boluobobo/ai-court
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
- uses: docker/login-action@v3
|
||||
with:
|
||||
username: boluobobo
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.DOCKERHUB_IMAGE }}:latest
|
||||
${{ env.DOCKERHUB_IMAGE }}:${{ github.ref_name }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
# [L-11] 供应链安全:添加 provenance 和 SBOM
|
||||
provenance: true
|
||||
sbom: true
|
||||
3
.github/workflows/duchayuan-review.yml
vendored
3
.github/workflows/duchayuan-review.yml
vendored
@@ -11,6 +11,9 @@ on:
|
||||
- 'images/**'
|
||||
- 'LICENSE'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
duchayuan-review:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cmk",
|
||||
"id": "cmo",
|
||||
"name": "CMO",
|
||||
"model": {
|
||||
"primary": "your-provider/fast-model"
|
||||
@@ -268,7 +268,7 @@
|
||||
"applicationId": "YOUR_CFO_APPLICATION_ID",
|
||||
"groupPolicy": "open"
|
||||
},
|
||||
"cmk": {
|
||||
"cmo": {
|
||||
"name": "CMO",
|
||||
"token": "YOUR_CMO_BOT_TOKEN",
|
||||
"applicationId": "YOUR_CMO_APPLICATION_ID",
|
||||
@@ -359,7 +359,7 @@
|
||||
"name": "COO",
|
||||
"groupPolicy": "open"
|
||||
},
|
||||
"cmk": {
|
||||
"cmo": {
|
||||
"appId": "YOUR_CMO_APP_ID",
|
||||
"appSecret": "YOUR_CMO_APP_SECRET",
|
||||
"name": "CMO",
|
||||
@@ -393,7 +393,7 @@
|
||||
{ "agentId": "cto", "match": { "channel": "discord", "accountId": "cto" } },
|
||||
{ "agentId": "coo", "match": { "channel": "discord", "accountId": "coo" } },
|
||||
{ "agentId": "cfo", "match": { "channel": "discord", "accountId": "cfo" } },
|
||||
{ "agentId": "cmk", "match": { "channel": "discord", "accountId": "cmk" } },
|
||||
{ "agentId": "cmo", "match": { "channel": "discord", "accountId": "cmo" } },
|
||||
{ "agentId": "eng", "match": { "channel": "discord", "accountId": "eng" } },
|
||||
{ "agentId": "prod", "match": { "channel": "discord", "accountId": "prod" } },
|
||||
{ "agentId": "qa", "match": { "channel": "discord", "accountId": "qa" } },
|
||||
|
||||
@@ -182,7 +182,8 @@ echo ""
|
||||
|
||||
# 自动补全 gateway.mode(缺少会导致启动失败)
|
||||
if command -v openclaw &>/dev/null && [ -f "$CONFIG_DIR/openclaw.json" ]; then
|
||||
if ! grep -q '"gateway"' "$CONFIG_DIR/openclaw.json" 2>/dev/null || ! python3 -c "import json; d=json.load(open('$CONFIG_DIR/openclaw.json')); assert d.get('gateway',{}).get('mode')" 2>/dev/null; then
|
||||
if ! grep -q '"gateway"' "$CONFIG_DIR/openclaw.json" 2>/dev/null || \
|
||||
! CONFIG_PATH="$CONFIG_DIR/openclaw.json" python3 -c "import json,os; d=json.load(open(os.environ['CONFIG_PATH'])); assert d.get('gateway',{}).get('mode')" 2>/dev/null; then
|
||||
echo "⚠ gateway.mode 未设置,自动设为 local..."
|
||||
openclaw config set gateway.mode local 2>/dev/null || true
|
||||
fi
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Boluo GUI Server Keepalive
|
||||
# Ensures node server/index.js stays running on port 18795
|
||||
|
||||
SERVER_DIR="$(cd "$(dirname "$0")/gui/server" && pwd)"
|
||||
SERVER_DIR="$(cd "$(dirname "$0")/server" && pwd)"
|
||||
LOG_FILE="/tmp/boluo-gui.log"
|
||||
PID_FILE="/tmp/boluo-gui.pid"
|
||||
CHECK_INTERVAL=15
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Boluo GUI Server Keepalive
|
||||
# Ensures node server/index.js stays running on port 18795
|
||||
|
||||
SERVER_DIR="$(cd "$(dirname "$0")/gui/server" && pwd)"
|
||||
SERVER_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
LOG_FILE="/tmp/boluo-gui.log"
|
||||
PID_FILE="/tmp/boluo-gui.pid"
|
||||
CHECK_INTERVAL=15
|
||||
|
||||
@@ -298,13 +298,8 @@ generate_config_from_template() {
|
||||
process.stdout.write(out + '\n');
|
||||
" "$mode" > "$output"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
chmod 600 "$output"
|
||||
echo -e " ${GREEN}✓ ${mode} 模式配置已生成${NC}"
|
||||
else
|
||||
echo -e " ${RED}✗ 配置生成失败${NC}"
|
||||
return 1
|
||||
fi
|
||||
chmod 600 "$output"
|
||||
echo -e " ${GREEN}✓ ${mode} 模式配置已生成${NC}"
|
||||
}
|
||||
|
||||
if [ -f "$CONFIG_DIR/$CONFIG_FILE" ]; then
|
||||
|
||||
@@ -166,38 +166,6 @@ create_agent_workspaces() {
|
||||
local workspaces
|
||||
workspaces=$(jq -r '.agents.list[]? | "\(.id):\(.workspace // empty)"' "$config_file" 2>/dev/null)
|
||||
for entry in $workspaces; do
|
||||
# ---- 注入人设(从 agents/*.md 文件)----
|
||||
echo ""
|
||||
echo -e "${YELLOW}[2.5/5] 注入人设...${NC}"
|
||||
TEMPLATE_AGENTS_DIR="$WORKSPACE/configs/ming-neige/agents"
|
||||
if [ -d "$TEMPLATE_AGENTS_DIR" ] && [ -f "$CONFIG_DIR/$CONFIG_FILE" ]; then
|
||||
echo -e " ${CYAN}正在从独立文件注入人设...${NC}"
|
||||
|
||||
agent_count=$(jq '.agents.list | length' "$CONFIG_DIR/$CONFIG_FILE" 2>/dev/null || echo "0")
|
||||
injected=0
|
||||
|
||||
for ((i=0; i<agent_count; i++)); do
|
||||
agent_id=$(jq -r ".agents.list[$i].id" "$CONFIG_DIR/$CONFIG_FILE" 2>/dev/null)
|
||||
persona_file="$TEMPLATE_AGENTS_DIR/${agent_id}.md"
|
||||
|
||||
if [ -f "$persona_file" ]; then
|
||||
persona=$(tail -n +3 "$persona_file")
|
||||
persona_escaped=$(echo "$persona" | jq -Rs '.')
|
||||
|
||||
jq --argjson idx "$i" --argjson persona "$persona_escaped" \
|
||||
".agents.list[$idx].identity.theme = \$persona" \
|
||||
"$CONFIG_DIR/$CONFIG_FILE" > "${CONFIG_DIR}/${CONFIG_FILE}.tmp" && mv "${CONFIG_DIR}/${CONFIG_FILE}.tmp" "$CONFIG_DIR/$CONFIG_FILE"
|
||||
|
||||
echo -e " ${GREEN}✓${NC} $agent_id"
|
||||
injected=$((injected + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e " ${GREEN}✓${NC} 已注入 $injected 个人设"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} 人设目录不存在,使用模板中的内置人设"
|
||||
fi
|
||||
|
||||
local aws="${entry##*:}"
|
||||
aws="${aws/\$HOME/$HOME}"
|
||||
if [ -n "$aws" ] && [ "$aws" != "$WORKSPACE" ]; then
|
||||
@@ -252,34 +220,6 @@ SOUL_EOF
|
||||
echo -e " ${GREEN}✓ SOUL.md 已创建${NC}"
|
||||
fi
|
||||
|
||||
# ---- 安装默认 Skill: self-improving ----
|
||||
echo ""
|
||||
echo -e "${YELLOW}安装默认 Skill...${NC}"
|
||||
if ! command -v clawdhub &>/dev/null; then
|
||||
npm install -g clawdhub 2>/dev/null || true
|
||||
fi
|
||||
if command -v clawdhub &>/dev/null; then
|
||||
# 主工作区
|
||||
clawdhub install self-improving --workdir "$WORKSPACE" --force 2>/dev/null && \
|
||||
echo -e " ${GREEN}✓ self-improving 已安装到主工作区${NC}" || \
|
||||
echo -e " ${YELLOW}⚠ 主工作区 skill 安装失败,可稍后手动安装: clawdhub install self-improving${NC}"
|
||||
mkdir -p "$WORKSPACE/.learnings"
|
||||
# 各部门工作区
|
||||
if [ -f "$CONFIG_DIR/$CONFIG_FILE" ] && command -v jq &>/dev/null; then
|
||||
SKILL_AGENT_WORKSPACES=$(jq -r '.agents.list[]? | .workspace // empty' "$CONFIG_DIR/$CONFIG_FILE" 2>/dev/null)
|
||||
echo "$SKILL_AGENT_WORKSPACES" | while IFS= read -r SKILL_WS; do
|
||||
[ -z "$SKILL_WS" ] && continue
|
||||
SKILL_WS="${SKILL_WS/\$HOME/$HOME}"
|
||||
[ "$SKILL_WS" = "$WORKSPACE" ] && continue
|
||||
clawdhub install self-improving --workdir "$SKILL_WS" --force 2>/dev/null
|
||||
mkdir -p "$SKILL_WS/.learnings"
|
||||
done
|
||||
echo -e " ${GREEN}✓ self-improving 已安装到所有工作区${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e " ${YELLOW}⚠ clawdhub 未安装,跳过 skill 安装。安装后运行: clawdhub install self-improving${NC}"
|
||||
fi
|
||||
|
||||
# IDENTITY.md
|
||||
if [ ! -f "$WORKSPACE/IDENTITY.md" ]; then
|
||||
cat > "$WORKSPACE/IDENTITY.md" << 'ID_EOF'
|
||||
@@ -416,13 +356,8 @@ generate_config_from_template() {
|
||||
process.stdout.write(out + '\n');
|
||||
" "$mode" > "$output"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
chmod 600 "$output"
|
||||
echo -e " ${GREEN}✓ ${mode} 模式配置已生成${NC}"
|
||||
else
|
||||
echo -e " ${RED}✗ 配置生成失败${NC}"
|
||||
return 1
|
||||
fi
|
||||
chmod 600 "$output"
|
||||
echo -e " ${GREEN}✓ ${mode} 模式配置已生成${NC}"
|
||||
}
|
||||
|
||||
if [ -f "$CONFIG_DIR/$CONFIG_FILE" ]; then
|
||||
@@ -436,7 +371,37 @@ else
|
||||
generate_config_from_template "$CONFIG_MODE" "$CONFIG_DIR/$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# ---- 注入人设(从 agents/*.md 文件)----
|
||||
echo ""
|
||||
echo -e "${YELLOW}注入人设...${NC}"
|
||||
TEMPLATE_AGENTS_DIR="$WORKSPACE/configs/ming-neige/agents"
|
||||
if [ -d "$TEMPLATE_AGENTS_DIR" ] && [ -f "$CONFIG_DIR/$CONFIG_FILE" ] && command -v jq &>/dev/null; then
|
||||
echo -e " ${CYAN}正在从独立文件注入人设...${NC}"
|
||||
|
||||
agent_count=$(jq '.agents.list | length' "$CONFIG_DIR/$CONFIG_FILE" 2>/dev/null || echo "0")
|
||||
injected=0
|
||||
|
||||
for ((i=0; i<agent_count; i++)); do
|
||||
agent_id=$(jq -r ".agents.list[$i].id" "$CONFIG_DIR/$CONFIG_FILE" 2>/dev/null)
|
||||
persona_file="$TEMPLATE_AGENTS_DIR/${agent_id}.md"
|
||||
|
||||
if [ -f "$persona_file" ]; then
|
||||
persona=$(tail -n +3 "$persona_file")
|
||||
persona_escaped=$(echo "$persona" | jq -Rs '.')
|
||||
|
||||
jq --argjson idx "$i" --argjson persona "$persona_escaped" \
|
||||
".agents.list[\$idx].identity.theme = \$persona" \
|
||||
"$CONFIG_DIR/$CONFIG_FILE" > "${CONFIG_DIR}/${CONFIG_FILE}.tmp" && mv "${CONFIG_DIR}/${CONFIG_FILE}.tmp" "$CONFIG_DIR/$CONFIG_FILE"
|
||||
|
||||
echo -e " ${GREEN}✓${NC} $agent_id"
|
||||
injected=$((injected + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e " ${GREEN}✓${NC} 已注入 $injected 个人设"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} 人设目录不存在或缺少 jq,使用模板中的内置人设"
|
||||
fi
|
||||
|
||||
# ---- 可选:安装 Dashboard Web UI ----
|
||||
echo ""
|
||||
|
||||
34
install.ps1
34
install.ps1
@@ -7,6 +7,8 @@ param(
|
||||
[switch]$Help
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
if ($Help) {
|
||||
Write-Host @"
|
||||
AI 朝廷 Windows 安装脚本
|
||||
@@ -90,7 +92,7 @@ if (Test-NodeJs) {
|
||||
try {
|
||||
Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath -UseBasicParsing
|
||||
Write-Info "正在运行安装器..."
|
||||
Start-Process msiexec.exe -Wait -ArgumentList "/i $installerPath /quiet /norestart"
|
||||
Start-Process msiexec.exe -Wait -ArgumentList "/i `"$installerPath`" /quiet /norestart"
|
||||
Remove-Item $installerPath -Force
|
||||
|
||||
# 刷新环境变量
|
||||
@@ -132,14 +134,40 @@ if (-not (Test-Path $workspacePath)) {
|
||||
# ============================================
|
||||
Write-Info "正在下载 AI 朝廷配置..."
|
||||
|
||||
$configDir = Join-Path $env:USERPROFILE ".openclaw"
|
||||
if (-not (Test-Path $configDir)) {
|
||||
New-Item -ItemType Directory -Path $configDir | Out-Null
|
||||
}
|
||||
|
||||
$configUrl = "https://raw.githubusercontent.com/wanikua/danghuangshang/main/openclaw.example.json"
|
||||
$configPath = Join-Path $workspacePath "openclaw.json"
|
||||
$configPath = Join-Path $configDir "openclaw.json"
|
||||
|
||||
try {
|
||||
Invoke-WebRequest -Uri $configUrl -OutFile $configPath -UseBasicParsing
|
||||
Write-Success "配置文件已下载:$configPath"
|
||||
} catch {
|
||||
Write-Warn "配置文件下载失败,将手动创建模板"
|
||||
Write-Warn "配置文件下载失败,生成最小配置模板"
|
||||
$minimalConfig = @'
|
||||
{
|
||||
"models": {
|
||||
"providers": {
|
||||
"your-provider": {
|
||||
"baseUrl": "https://your-llm-provider-api-url",
|
||||
"apiKey": "YOUR_LLM_API_KEY",
|
||||
"api": "openai",
|
||||
"models": [{ "id": "fast-model", "name": "快速模型", "contextWindow": 200000, "maxTokens": 8192 }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"gateway": { "mode": "local", "port": 18789 },
|
||||
"agents": {
|
||||
"defaults": { "workspace": "$workspacePath", "skipBootstrap": true, "model": { "primary": "your-provider/fast-model" } },
|
||||
"list": [{ "id": "silijian", "name": "司礼监", "identity": { "theme": "你是AI朝廷的总管,负责日常对话和任务调度。回答用中文,简洁高效。" } }]
|
||||
}
|
||||
}
|
||||
'@
|
||||
$minimalConfig | Out-File -FilePath $configPath -Encoding UTF8
|
||||
Write-Success "最小配置模板已生成:$configPath"
|
||||
}
|
||||
|
||||
# ============================================
|
||||
|
||||
12
package.json
12
package.json
@@ -6,18 +6,16 @@
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"test:coverage": "jest --coverage",
|
||||
"test:watch": "jest --watch"
|
||||
"test:watch": "jest --watch",
|
||||
"test:manual": "node tests/test-task-store.js && node tests/test-context-compressor.js",
|
||||
"lint": "bash -n scripts/*.sh && node -c scripts/*.js 2>/dev/null || true",
|
||||
"health": "bash scripts/health-check.sh",
|
||||
"cleanup": "bash scripts/cleanup-repo.sh"
|
||||
},
|
||||
"bin": {
|
||||
"task-store": "./scripts/task-store.js",
|
||||
"context-compressor": "./scripts/context-compressor.js"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node tests/test-task-store.js && node tests/test-context-compressor.js",
|
||||
"lint": "bash -n scripts/*.sh && node -c scripts/*.js 2>/dev/null || true",
|
||||
"health": "bash scripts/health-check.sh",
|
||||
"cleanup": "bash scripts/cleanup-repo.sh"
|
||||
},
|
||||
"keywords": [
|
||||
"ai",
|
||||
"multi-agent",
|
||||
|
||||
Reference in New Issue
Block a user