mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 02:35:24 +00:00
- 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>
154 lines
4.4 KiB
Bash
Executable File
154 lines
4.4 KiB
Bash
Executable File
#!/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
|