Files
my-pi/configure.sh
T
云服务部-叶林立andDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> f9a7f743dd feat: 接入 Pi 内置 codemode,并修复全面审查发现的问题
- codemode:Tool Search 常驻(alwaysEnabled)、权限 allow(嵌套调用仍逐个过权限门)、
  tools.jsonc 登记使用规则;RTK 跳过 parentToolCallId 嵌套调用,避免丢失 bash
  structuredContent;Tool Search 目录过滤 hidden / codemode(script-only)exposure;
  扩展加载测试加载 builtin:codemode 并断言其常驻激活
- 搜索 key 不再经命令行参数传递:search-auth.mjs 改为 --set-stdin(先读校验再加锁),
  configure.sh 交互输入经管道、非交互用 --<provider> -
- CodeGraph 客户端监听子进程 stdin error,避免 EPIPE 未处理导致崩溃
- 移除 PI_TOOL_SEARCH/HERMES_MEMORY/RTK_CONFIG_PATH 环境变量入口,测试改用工厂 configPath 注入
- pi-subagents 固定 vitest / coverage-istanbul 4.1.10,修复 npm ls 版本冲突
- 补 pi-web-search / pi-worktree UPSTREAM.md 与 pi-minimal-footer AGENTS.md,
  files 白名单补齐并加测试;.codegraph/.gitignore 移出跟踪
- detect_kitty 优先识别官方安装目录

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-21 23:18:34 -07:00

154 lines
4.4 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
./configure.sh search --migrate [search.env 路径]
./configure.sh search --list
选项:
--tavily - 从标准输入读取 tavily api_key 凭据
--exa - 从标准输入读取 exa api_key 凭据
--keenable - 从标准输入读取 keenable api_key 凭据
--migrate 从旧 search.env 导入缺失的 key
--list 显示各 provider 配置状态(不输出 key)
--auth FILE 覆盖 auth.json 路径
-h, --help 显示帮助
key 不得出现在命令行参数中:非交互方式用 `--<provider> -` 从标准输入
读取,每次调用最多一个 provider 可经标准输入配置;不传参数时进入
隐藏输入的交互模式,未指定的 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
search_stdin_provider=
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 "交互模式需要终端;请改用 '--<provider> -' 从标准输入提供 key。"
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; }
if [ "$2" != "-" ]; then
warn "$1 不接受明文 key:key 不得出现在命令行参数中;请用交互模式或 '$1 -' 从标准输入提供。"
exit 2
fi
[ -z "$search_stdin_provider" ] || { warn "每次调用最多一个 provider 可经标准输入读取 key。"; exit 2; }
search_stdin_provider=${1#--}
search_mode=noninteractive; search_did_work=1
run_search_auth --set-stdin "$search_stdin_provider" || 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
printf '%s' "$value" | run_search_auth --set-stdin "$provider" || 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