Files
my-pi/configure.sh
T
云服务部-叶林立andDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> 2aa1be0b54 feat: 组合包配置以包内 config/ 为唯一来源,并新增受保护写入人工审批
配置统一:权限策略、硬防御、Tool Search、提示词封面以及新迁入的
RTK、pi-compaction、pi-worktree、pi-hermes-memory 配置全部由扩展
直接读取已安装组合包内的 config/,pi install / pi update 即完成部署;
删除 rebuild-bundle-config.mjs 与 bundle-manifest.json,my-pi/ 只保留
日志与缓存。update.sh 成功升级后将默认 git 来源的已安装副本
reset 回发布版本。AGENTS.md 新增「组合包配置原则」。

脚本整合:search_config.sh / ssh_config.sh 合并为 configure.sh
search|ssh;install.sh / update.sh 共享函数抽到 scripts/lib.sh,远程
安装器改为先下载到临时文件再执行,下载失败可被检测。

权限:hard-guards 新增 protectedWrites,写入 Pi 凭据/设置、已安装
组合包与扩展目录、pi-ssh 凭据库时一律人工确认(跳过 AutoReview、
yolo 与 Session grant,无 UI 时拒绝);放行 ls、LSP 查询、ctx 只读、
web_search、Chrome 只读与 git 只读命令,skill_manage 改为 ask。

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-20 01:05:31 -07:00

146 lines
3.9 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/sh
set -u
SCRIPT_DIR=$(CDPATH=; cd "$(dirname "$0")" && pwd) || exit 1
say() {
printf '%s\n' "$*"
}
warn() {
printf '错误: %s\n' "$*" >&2
}
usage() {
cat >&2 <<'EOF'
用法:
./configure.sh search [选项] 配置搜索 API key(tavily / exa / keenable)
./configure.sh ssh [选项] 配置 SSH 主机凭据
EOF
}
search_usage() {
cat <<'EOF'
用法:
./configure.sh search
./configure.sh search --tavily KEY --exa KEY --keenable KEY
./configure.sh search --migrate [search.env 路径]
./configure.sh search --list
选项:
--tavily KEY 配置 tavily api_key 凭据
--exa KEY 配置 exa api_key 凭据
--keenable KEY 配置 keenable api_key 凭据
--migrate 从旧 search.env 导入缺失的 key
--list 显示各 provider 配置状态(不输出 key)
--auth FILE 覆盖 auth.json 路径
-h, --help 显示帮助
不传 key 参数时进入隐藏输入的交互模式;传入任意 key 参数时不交互,
未指定的 provider 保留已有值。凭据写入 Pi 的 auth.json
($PI_CODING_AGENT_DIR/auth.json 或 ~/.pi/agent/auth.json,权限 600)。
key 支持 auth.json 原生语义:字面量、$ENV_VAR / ${ENV_VAR} 插值、
以及 !command(执行命令取 stdout,如 "!op read op://Vault/Tavily/key")。
EOF
}
configure_search() {
SEARCH_AUTH_MJS="$SCRIPT_DIR/scripts/search-auth.mjs"
[ -f "$SEARCH_AUTH_MJS" ] || { warn "找不到 ${SEARCH_AUTH_MJS}"; exit 1; }
SEARCH_AUTH_FILE=
search_mode=interactive
search_did_work=0
run_search_auth() {
if [ -n "$SEARCH_AUTH_FILE" ]; then
node "$SEARCH_AUTH_MJS" --auth "$SEARCH_AUTH_FILE" "$@"
else
node "$SEARCH_AUTH_MJS" "$@"
fi
}
search_has_key() {
run_search_auth --has "$1" >/dev/null 2>&1
}
search_prompt_key() {
prompt_label=$1
prompt_configured=$2
if [ ! -t 0 ]; then
warn "交互模式需要终端;请改用 --tavily/--exa/--keenable 参数。"
return 2
fi
if [ "$prompt_configured" -eq 1 ]; then
printf '%s API key(回车保留现有值): ' "$prompt_label" >&2
else
printf '%s API key(回车跳过): ' "$prompt_label" >&2
fi
stty -echo
IFS= read -r prompt_value || prompt_status=$?
stty echo
printf '\n' >&2
[ "${prompt_status:-0}" -eq 0 ] || return "$prompt_status"
printf '%s\n' "$prompt_value"
}
while [ "$#" -gt 0 ]; do
case $1 in
--tavily|--exa|--keenable)
[ "$#" -ge 2 ] || { warn "$1 缺少 KEY"; exit 2; }
search_mode=noninteractive; search_did_work=1
run_search_auth --set "${1#--}=$2" || exit $?
shift 2 ;;
--migrate)
search_mode=noninteractive; search_did_work=1
if [ "$#" -ge 2 ] && [ "${2#--}" = "$2" ]; then
run_search_auth --migrate "$2" || exit $?
shift 2
else
run_search_auth --migrate || exit $?
shift
fi
say "如确认 auth.json 可用,可手动删除旧 search.env 文件。" ;;
--list) search_mode=noninteractive; search_did_work=1; run_search_auth --list || exit $?; shift ;;
--auth)
[ "$#" -ge 2 ] || { warn "--auth 缺少 FILE"; exit 2; }
SEARCH_AUTH_FILE=$2; shift 2 ;;
-h|--help) search_usage; exit 0 ;;
*) warn "未知参数:$1"; search_usage >&2; exit 2 ;;
esac
done
if [ "$search_mode" = interactive ]; then
for provider in tavily exa keenable; do
case $provider in
tavily) label=Tavily ;;
exa) label=Exa ;;
keenable) label=Keenable ;;
esac
if search_has_key "$provider"; then configured=1; else configured=0; fi
value=$(search_prompt_key "$label" "$configured") || exit $?
if [ -n "$value" ]; then
run_search_auth --set "$provider=$value" || exit $?
search_did_work=1
fi
done
[ "$search_did_work" -eq 1 ] || say "未提供任何 key,auth.json 保持不变。"
fi
}
case ${1:-} in
search)
shift
configure_search "$@"
;;
ssh)
shift
exec node "$SCRIPT_DIR/pi-ssh/scripts/ssh-config-launcher.mjs" "$@"
;;
*)
usage
exit 2
;;
esac