feat: 添加MinIO文件系统支持并优化外部连接器功能
- 添加MinIO用户文件系统配置选项(BEAVER_MINIO_ROOT_USER等) - 更新外部连接器配置结构,包括BASE_URL和认证令牌设置 - 改进connector provider支持更多类型(official, feishu_bot等) - 实现Mistral模型推理模式支持reasoning_effort参数 - 增强外部连接器策略配置和运行时配置管理 - 添加connector bridge事件验证和安全保护机制 - 优化任务路由逻辑,区分simple_chat和new_task场景 - 更新初始技能工具提示配置,分离authoring admin功能
This commit is contained in:
116
scripts/deploy-initial-skills.sh
Normal file → Executable file
116
scripts/deploy-initial-skills.sh
Normal file → Executable file
@ -1,61 +1,101 @@
|
||||
#!/bin/bash
|
||||
# Deploy initial skills to all runtime instances via docker cp
|
||||
# Usage: ./scripts/deploy-initial-skills.sh
|
||||
#!/usr/bin/env bash
|
||||
# Deploy initial skills to app-instance containers without overwriting existing skill directories.
|
||||
# Usage:
|
||||
# ./scripts/deploy-initial-skills.sh
|
||||
# ./scripts/deploy-initial-skills.sh app-instance-terminaltest
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SKILL_SOURCE="/home/ivan/xuan/beaver_project/skills"
|
||||
DOCKER_NAMES=("app-instance-steven" "app-instance-benson" "app-instance-jayc" "app-instance-officebench")
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
SKILL_SOURCE="${SKILL_SOURCE:-${REPO_ROOT}/skills}"
|
||||
SKILL_EXCLUDE="${SKILL_EXCLUDE:-officebench-mcp}"
|
||||
|
||||
SKILLS=(
|
||||
"outlook-mail"
|
||||
"filesystem-operation"
|
||||
"terminal-operation"
|
||||
"web-operation"
|
||||
"utility-tools"
|
||||
"skills-admin"
|
||||
"cron-scheduler"
|
||||
"memory-management"
|
||||
if [[ ! -f "${SKILL_SOURCE}/_index/published.json" ]]; then
|
||||
printf '[deploy-initial-skills] missing published index: %s\n' "${SKILL_SOURCE}/_index/published.json" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $# -gt 0 ]]; then
|
||||
DOCKER_NAMES=("$@")
|
||||
else
|
||||
mapfile -t DOCKER_NAMES < <(docker ps --format '{{.Names}}' | grep '^app-instance-' | sort)
|
||||
fi
|
||||
|
||||
if [[ "${#DOCKER_NAMES[@]}" -eq 0 ]]; then
|
||||
printf '[deploy-initial-skills] no app-instance containers found\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SKILLS_JSON="$(SKILL_SOURCE="$SKILL_SOURCE" SKILL_EXCLUDE="$SKILL_EXCLUDE" python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
source = Path(os.environ["SKILL_SOURCE"])
|
||||
excluded = {item.strip() for item in os.environ.get("SKILL_EXCLUDE", "").split(",") if item.strip()}
|
||||
items = json.loads((source / "_index" / "published.json").read_text(encoding="utf-8")).get("items", [])
|
||||
print(json.dumps([str(item).strip() for item in items if str(item).strip() and str(item).strip() not in excluded]))
|
||||
PY
|
||||
)"
|
||||
|
||||
mapfile -t SKILLS < <(SKILLS_JSON="$SKILLS_JSON" python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
|
||||
for item in json.loads(os.environ["SKILLS_JSON"]):
|
||||
print(item)
|
||||
PY
|
||||
)
|
||||
|
||||
for container in "${DOCKER_NAMES[@]}"; do
|
||||
echo "==> Deploying to $container..."
|
||||
printf '==> Deploying initial skills to %s...\n' "$container"
|
||||
|
||||
docker exec "$container" mkdir -p /root/.beaver/workspace/skills/_index
|
||||
|
||||
for skill in "${SKILLS[@]}"; do
|
||||
if [ -d "$SKILL_SOURCE/$skill" ]; then
|
||||
docker cp "$SKILL_SOURCE/$skill" "$container":/root/.beaver/workspace/skills/
|
||||
echo " + $skill"
|
||||
if [[ ! -d "$SKILL_SOURCE/$skill" ]]; then
|
||||
printf ' ! missing source skill: %s\n' "$skill"
|
||||
continue
|
||||
fi
|
||||
if docker exec "$container" test -e "/root/.beaver/workspace/skills/$skill"; then
|
||||
printf ' = %s\n' "$skill"
|
||||
continue
|
||||
fi
|
||||
docker cp "$SKILL_SOURCE/$skill" "$container":/root/.beaver/workspace/skills/
|
||||
printf ' + %s\n' "$skill"
|
||||
done
|
||||
|
||||
# Merge index: keep existing entries + add new skills, no duplicates
|
||||
docker exec "$container" python3 -c "
|
||||
docker exec -i -e SKILLS_JSON="$SKILLS_JSON" "$container" python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
idx = Path('/root/.beaver/workspace/skills/_index/published.json')
|
||||
existing = json.loads(idx.read_text()) if idx.exists() else {'items': []}
|
||||
idx = Path("/root/.beaver/workspace/skills/_index/published.json")
|
||||
try:
|
||||
existing = json.loads(idx.read_text(encoding="utf-8")) if idx.exists() else {"items": []}
|
||||
except json.JSONDecodeError:
|
||||
existing = {"items": []}
|
||||
items = existing.get("items")
|
||||
if not isinstance(items, list):
|
||||
items = []
|
||||
|
||||
new_skills = $(printf '["%s"]' "$(IFS=,; echo "${SKILLS[*]}")" | sed 's/,/", "/g')
|
||||
merged = []
|
||||
for item in [*items, *json.loads(os.environ["SKILLS_JSON"])]:
|
||||
text = str(item).strip()
|
||||
if text and text not in merged:
|
||||
merged.append(text)
|
||||
|
||||
seen = set(existing['items'])
|
||||
for s in new_skills:
|
||||
if s not in seen:
|
||||
existing['items'].append(s)
|
||||
seen.add(s)
|
||||
idx.parent.mkdir(parents=True, exist_ok=True)
|
||||
idx.write_text(json.dumps({"items": merged}, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||||
print(f" index updated: {len(merged)} skills")
|
||||
PY
|
||||
|
||||
idx.write_text(json.dumps(existing, ensure_ascii=False, indent=2) + '\n')
|
||||
print(f\"Index updated: {len(existing['items'])} skills\")
|
||||
"
|
||||
if [[ -f "$SKILL_SOURCE/_index/disabled.json" ]]; then
|
||||
docker cp "$SKILL_SOURCE/_index/disabled.json" "$container":/root/.beaver/workspace/skills/_index/disabled.json
|
||||
fi
|
||||
|
||||
docker cp "$SKILL_SOURCE/_index/disabled.json" "$container":/root/.beaver/workspace/skills/_index/disabled.json
|
||||
|
||||
echo " [done]"
|
||||
printf ' [done]\n'
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Done! All skills deployed to all instances."
|
||||
echo "Containers: ${DOCKER_NAMES[*]}"
|
||||
echo "Skills: ${SKILLS[*]}"
|
||||
printf '\nDone. Containers: %s\n' "${DOCKER_NAMES[*]}"
|
||||
|
||||
Reference in New Issue
Block a user