Files
云服务部-叶林立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

204 lines
5.4 KiB
Bash

#!/bin/sh
# Variables assigned here are consumed by the sourcing install.sh/update.sh.
# shellcheck disable=SC2034
# Shared helpers for the bundle's POSIX sh scripts.
# Source this file; it defines say(), warn(), the Kitty/Zsh resolution
# helpers, and the my-pi managed-block machinery used by install.sh and
# update.sh.
say() {
printf '%s\n' "$*"
}
warn() {
printf '警告: %s\n' "$*" >&2
}
detect_kitty() {
kitty_bin=
for candidate in /Applications/kitty.app/Contents/MacOS/kitty "$HOME/.local/kitty.app/bin/kitty"; do
if [ -x "$candidate" ]; then
kitty_bin=$candidate
return 0
fi
done
if command -v kitty >/dev/null 2>&1; then
kitty_bin=$(command -v kitty)
return 0
fi
return 1
}
resolve_kitty_config_dir() {
kitty_config_dir=${KITTY_CONFIG_DIRECTORY:-${XDG_CONFIG_HOME:-$HOME/.config}/kitty}
}
resolve_zsh_paths() {
oh_my_zsh_dir=${ZSH:-$HOME/.oh-my-zsh}
zsh_custom_dir=${ZSH_CUSTOM:-$oh_my_zsh_dir/custom}
zshrc_file=${ZDOTDIR:-$HOME}/.zshrc
my_pi_config_dir=${XDG_CONFIG_HOME:-$HOME/.config}/my-pi
p10k_managed_config_file=$my_pi_config_dir/p10k.zsh
}
# Anchor regex shared by every "before the Oh My Zsh loader" managed block.
MY_PI_ZSH_LOADER_ANCHOR='^(# >>> my-pi:oh-my-zsh-loader >>>|[[:space:]]*(source|\.)[[:space:]].*oh-my-zsh\.sh)'
replace_zsh_managed_block() {
managed_id=$1
managed_placement=$2
managed_anchor=$3
shift 3
managed_content=$(mktemp "${TMPDIR:-/tmp}/my-pi-zsh-block.XXXXXX") || return 1
printf '%s\n' "$@" > "$managed_content"
my_pi_replace_managed_block "$zshrc_file" "$managed_id" "$managed_content" \
"$managed_placement" "$managed_anchor"
managed_status=$?
rm -f "$managed_content"
return "$managed_status"
}
MY_PI_MANAGED_BACKUPS=${MY_PI_MANAGED_BACKUPS:-}
my_pi_backup_once() {
managed_file=$1
case "|$MY_PI_MANAGED_BACKUPS|" in
*"|$managed_file|"*) return 0 ;;
esac
if [ -f "$managed_file" ]; then
managed_backup=$(mktemp "$managed_file.my-pi-backup-$(date +%Y%m%d%H%M%S).XXXXXX") || return 1
cp "$managed_file" "$managed_backup" || {
rm -f "$managed_backup"
return 1
}
say "已备份配置到 $managed_backup"
fi
MY_PI_MANAGED_BACKUPS=${MY_PI_MANAGED_BACKUPS:+$MY_PI_MANAGED_BACKUPS|}$managed_file
}
my_pi_managed_block_exists() {
managed_file=$1
managed_id=$2
managed_begin="# >>> my-pi:$managed_id >>>"
managed_end="# <<< my-pi:$managed_id <<<"
[ -f "$managed_file" ] || return 1
grep -F -x "$managed_begin" "$managed_file" >/dev/null 2>&1 &&
grep -F -x "$managed_end" "$managed_file" >/dev/null 2>&1
}
my_pi_replace_managed_block() {
managed_file=$1
managed_id=$2
managed_content_file=$3
managed_placement=${4:-append}
managed_anchor=${5:-}
managed_begin="# >>> my-pi:$managed_id >>>"
managed_end="# <<< my-pi:$managed_id <<<"
managed_dir=${managed_file%/*}
[ "$managed_dir" = "$managed_file" ] && managed_dir=.
mkdir -p "$managed_dir" || return 1
[ -f "$managed_file" ] || : > "$managed_file" || return 1
managed_counts=$(awk -v begin="$managed_begin" -v end="$managed_end" '
$0 == begin {
begins++
if (active) invalid = 1
active = 1
}
$0 == end {
ends++
if (!active) invalid = 1
active = 0
}
END {
if (active) invalid = 1
printf "%d %d %d\n", begins, ends, invalid
}
' "$managed_file") || return 1
managed_begin_count=${managed_counts%% *}
managed_remainder=${managed_counts#* }
managed_end_count=${managed_remainder%% *}
managed_invalid=${managed_remainder#* }
if [ "$managed_begin_count" -ne "$managed_end_count" ] || \
[ "$managed_begin_count" -gt 1 ] || [ "$managed_invalid" -ne 0 ]; then
warn "$managed_file 中的 my-pi:$managed_id 受管标记不完整或重复,已拒绝修改。"
return 1
fi
managed_tmp=$(mktemp "$managed_dir/.my-pi-managed.XXXXXX") || return 1
if ! awk \
-v begin="$managed_begin" \
-v end="$managed_end" \
-v content="$managed_content_file" \
-v placement="$managed_placement" \
-v anchor="$managed_anchor" '
function emit_block( line) {
print begin
while ((getline line < content) > 0) print line
close(content)
print end
}
BEGIN { replacing = 0; emitted = 0 }
$0 == begin {
emit_block()
replacing = 1
emitted = 1
next
}
replacing && $0 == end { replacing = 0; next }
replacing { next }
!emitted && placement == "before" && anchor != "" && $0 ~ anchor {
emit_block()
emitted = 1
}
{ print }
END {
if (!emitted) {
if (NR > 0) print ""
emit_block()
}
}
' "$managed_file" > "$managed_tmp"; then
rm -f "$managed_tmp"
return 1
fi
if cmp -s "$managed_tmp" "$managed_file"; then
rm -f "$managed_tmp"
return 0
fi
my_pi_backup_once "$managed_file" || {
rm -f "$managed_tmp"
return 1
}
if ! mv "$managed_tmp" "$managed_file"; then
rm -f "$managed_tmp"
return 1
fi
}
my_pi_sync_managed_file() {
managed_source=$1
managed_target=$2
[ -f "$managed_source" ] || {
warn "找不到仓库配置:$managed_source"
return 1
}
if [ -f "$managed_target" ] && cmp -s "$managed_source" "$managed_target"; then
return 0
fi
managed_target_dir=${managed_target%/*}
[ "$managed_target_dir" = "$managed_target" ] && managed_target_dir=.
mkdir -p "$managed_target_dir" || return 1
my_pi_backup_once "$managed_target" || return 1
managed_tmp=$(mktemp "$managed_target_dir/.my-pi-sync.XXXXXX") || return 1
if ! cp "$managed_source" "$managed_tmp" || ! mv "$managed_tmp" "$managed_target"; then
rm -f "$managed_tmp"
return 1
fi
say "已同步受管配置:$managed_target"
}