test
This commit is contained in:
365
setup-pi.sh
Executable file
365
setup-pi.sh
Executable file
@@ -0,0 +1,365 @@
|
||||
#!/usr/bin/env bash
|
||||
# setup-pi.sh — Install pi and configure models/settings like the reference machine.
|
||||
#
|
||||
# Usage:
|
||||
# curl -fsSL <url> | bash # or
|
||||
# bash setup-pi.sh
|
||||
# bash setup-pi.sh --force # overwrite existing config files
|
||||
# PI_INSTALL_METHOD=npm bash setup-pi.sh
|
||||
#
|
||||
# After install, edit API keys in:
|
||||
# ~/.pi/agent/models.json
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PI_HOME="${PI_HOME:-$HOME/.pi}"
|
||||
AGENT_DIR="$PI_HOME/agent"
|
||||
FORCE=0
|
||||
INSTALL_METHOD="${PI_INSTALL_METHOD:-auto}" # auto | bun | npm
|
||||
PI_PACKAGE="@earendil-works/pi-coding-agent"
|
||||
|
||||
# ── args ──────────────────────────────────────────────────────────────────────
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--force|-f) FORCE=1 ;;
|
||||
--bun) INSTALL_METHOD=bun ;;
|
||||
--npm) INSTALL_METHOD=npm ;;
|
||||
--help|-h)
|
||||
sed -n '2,14p' "$0"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $arg" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ── helpers ────────────────────────────────────────────────────────────────────
|
||||
info() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
|
||||
ok() { printf '\033[1;32m✓\033[0m %s\n' "$*"; }
|
||||
warn() { printf '\033[1;33m!\033[0m %s\n' "$*"; }
|
||||
die() { printf '\033[1;31m✗\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
write_file() {
|
||||
# write_file <path> <heredoc via stdin>
|
||||
local path="$1"
|
||||
if [[ -f "$path" && $FORCE -eq 0 ]]; then
|
||||
warn "skip existing: $path (use --force to overwrite)"
|
||||
return 0
|
||||
fi
|
||||
mkdir -p "$(dirname "$path")"
|
||||
cat > "$path"
|
||||
ok "wrote $path"
|
||||
}
|
||||
|
||||
have() { command -v "$1" >/dev/null 2>&1; }
|
||||
|
||||
# ── 1. prerequisites ──────────────────────────────────────────────────────────
|
||||
info "Checking prerequisites"
|
||||
|
||||
if ! have curl && ! have wget; then
|
||||
die "Need curl or wget"
|
||||
fi
|
||||
|
||||
# Node is required for pi runtime even when installed via bun
|
||||
if ! have node; then
|
||||
die "Node.js is required. Install Node 20+ then re-run."
|
||||
fi
|
||||
|
||||
NODE_MAJOR="$(node -p 'process.versions.node.split(".")[0]')"
|
||||
if (( NODE_MAJOR < 20 )); then
|
||||
warn "Node $NODE_MAJOR detected; pi recommends Node 20+"
|
||||
fi
|
||||
ok "node $(node -v)"
|
||||
|
||||
# ── 2. install pi ─────────────────────────────────────────────────────────────
|
||||
info "Installing $PI_PACKAGE"
|
||||
|
||||
resolve_method() {
|
||||
case "$INSTALL_METHOD" in
|
||||
bun|npm) echo "$INSTALL_METHOD" ;;
|
||||
auto)
|
||||
if have bun; then echo bun
|
||||
elif have npm; then echo npm
|
||||
else die "Need bun or npm to install pi"
|
||||
fi
|
||||
;;
|
||||
*) die "Invalid PI_INSTALL_METHOD=$INSTALL_METHOD (use auto|bun|npm)" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
METHOD="$(resolve_method)"
|
||||
case "$METHOD" in
|
||||
bun)
|
||||
ok "using bun $(bun -v 2>/dev/null || true)"
|
||||
bun install -g "$PI_PACKAGE"
|
||||
# Ensure bun bin is on PATH for this session
|
||||
export BUN_INSTALL="${BUN_INSTALL:-$HOME/.bun}"
|
||||
export PATH="$BUN_INSTALL/bin:$PATH"
|
||||
;;
|
||||
npm)
|
||||
ok "using npm $(npm -v 2>/dev/null || true)"
|
||||
npm install -g --ignore-scripts "$PI_PACKAGE"
|
||||
;;
|
||||
esac
|
||||
|
||||
if ! have pi; then
|
||||
die "pi binary not found on PATH after install. Add bun/npm global bin to PATH and re-run."
|
||||
fi
|
||||
ok "pi $(pi --version 2>/dev/null || echo installed) via $METHOD"
|
||||
|
||||
# ── 3. directory layout ───────────────────────────────────────────────────────
|
||||
info "Creating $AGENT_DIR"
|
||||
mkdir -p "$AGENT_DIR"/{sessions,extensions,skills,bin,npm,ayu/checkpoints}
|
||||
ok "dirs ready"
|
||||
|
||||
# ── 4. settings.json ──────────────────────────────────────────────────────────
|
||||
info "Writing settings.json"
|
||||
write_file "$AGENT_DIR/settings.json" <<'EOF'
|
||||
{
|
||||
"defaultProvider": "llm-gw",
|
||||
"defaultModel": "code",
|
||||
"packages": [],
|
||||
"images": {
|
||||
"blockImages": true
|
||||
},
|
||||
"terminal": {
|
||||
"showTerminalProgress": true
|
||||
},
|
||||
"steeringMode": "one-at-a-time",
|
||||
"theme": "dark",
|
||||
"hideThinkingBlock": true,
|
||||
"collapseChangelog": true,
|
||||
"defaultProjectTrust": "always",
|
||||
"warnings": {
|
||||
"anthropicExtraUsage": true
|
||||
},
|
||||
"defaultThinkingLevel": "high",
|
||||
"enableInstallTelemetry": false,
|
||||
"compaction": {
|
||||
"enabled": true,
|
||||
"reserveTokens": 25600,
|
||||
"keepRecentTokens": 20000
|
||||
},
|
||||
"retry": {
|
||||
"enabled": true,
|
||||
"maxRetries": 3,
|
||||
"baseDelayMs": 2000,
|
||||
"provider": {
|
||||
"timeoutMs": 300000,
|
||||
"maxRetries": 2,
|
||||
"maxRetryDelayMs": 60000
|
||||
}
|
||||
},
|
||||
"lsp": {
|
||||
"hookMode": "disabled"
|
||||
},
|
||||
"httpIdleTimeoutMs": 120000,
|
||||
"treeFilterMode": "default"
|
||||
}
|
||||
EOF
|
||||
|
||||
# ── 5. models.json (template keys) ────────────────────────────────────────────
|
||||
info "Writing models.json (API key placeholders)"
|
||||
write_file "$AGENT_DIR/models.json" <<'EOF'
|
||||
{
|
||||
"providers": {
|
||||
"llm-gw": {
|
||||
"baseUrl": "https://llm-gw.luulam.dev/v1",
|
||||
"apiKey": "YOUR_LLM_GW_API_KEY",
|
||||
"api": "openai-completions",
|
||||
"models": [
|
||||
{
|
||||
"id": "code",
|
||||
"name": "code",
|
||||
"reasoning": false,
|
||||
"input": ["text"],
|
||||
"contextWindow": 256000,
|
||||
"maxTokens": 128000,
|
||||
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
|
||||
}
|
||||
]
|
||||
},
|
||||
"mbbank": {
|
||||
"baseUrl": "https://api-sandbox.mbbank.com.vn/llm-gateway-dev/v1",
|
||||
"apiKey": "YOUR_MBBANK_API_KEY",
|
||||
"api": "openai-completions",
|
||||
"models": [
|
||||
{
|
||||
"id": "glm-text",
|
||||
"name": "glm-text",
|
||||
"reasoning": false,
|
||||
"input": ["text"],
|
||||
"contextWindow": 256000,
|
||||
"maxTokens": 128000,
|
||||
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# ── 6. APPEND_SYSTEM.md ───────────────────────────────────────────────────────
|
||||
info "Writing APPEND_SYSTEM.md"
|
||||
write_file "$AGENT_DIR/APPEND_SYSTEM.md" <<'EOF'
|
||||
# Default Coding Guidelines
|
||||
|
||||
Apply these guidelines by default for all coding, reviewing, debugging, and refactoring tasks.
|
||||
|
||||
## Karpathy Guidelines
|
||||
|
||||
Behavioral guidelines to reduce common LLM coding mistakes. These guidelines bias toward caution over speed. For trivial tasks, use judgment.
|
||||
|
||||
### 1. Think Before Coding
|
||||
|
||||
Don't assume. Don't hide confusion. Surface tradeoffs.
|
||||
|
||||
Before implementing:
|
||||
- State your assumptions explicitly. If uncertain, ask.
|
||||
- If multiple interpretations exist, present them; don't pick silently.
|
||||
- If a simpler approach exists, say so. Push back when warranted.
|
||||
- If something is unclear, stop. Name what's confusing. Ask.
|
||||
|
||||
### 2. Simplicity First
|
||||
|
||||
Minimum code that solves the problem. Nothing speculative.
|
||||
|
||||
- No features beyond what was asked.
|
||||
- No abstractions for single-use code.
|
||||
- No "flexibility" or "configurability" that wasn't requested.
|
||||
- No error handling for impossible scenarios.
|
||||
- If you write 200 lines and it could be 50, rewrite it.
|
||||
|
||||
Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
|
||||
|
||||
### 3. Surgical Changes
|
||||
|
||||
Touch only what you must. Clean up only your own mess.
|
||||
|
||||
When editing existing code:
|
||||
- Don't "improve" adjacent code, comments, or formatting.
|
||||
- Don't refactor things that aren't broken.
|
||||
- Match existing style, even if you'd do it differently.
|
||||
- If you notice unrelated dead code, mention it; don't delete it.
|
||||
|
||||
When your changes create orphans:
|
||||
- Remove imports, variables, or functions that your changes made unused.
|
||||
- Don't remove pre-existing dead code unless asked.
|
||||
|
||||
The test: every changed line should trace directly to the user's request.
|
||||
|
||||
### 4. Goal-Driven Execution
|
||||
|
||||
Define success criteria. Loop until verified.
|
||||
|
||||
Transform tasks into verifiable goals:
|
||||
- "Add validation" → "Write tests for invalid inputs, then make them pass."
|
||||
- "Fix the bug" → "Write a test that reproduces it, then make it pass."
|
||||
- "Refactor X" → "Ensure tests pass before and after."
|
||||
|
||||
For multi-step tasks, state a brief plan:
|
||||
|
||||
```text
|
||||
1. [Step] → verify: [check]
|
||||
2. [Step] → verify: [check]
|
||||
3. [Step] → verify: [check]
|
||||
```
|
||||
|
||||
Strong success criteria let you loop independently. Weak criteria like "make it work" require clarification.
|
||||
EOF
|
||||
|
||||
# ── 7. minimal auth + trust stubs ─────────────────────────────────────────────
|
||||
# auth.json empty object is fine; keys live in models.json for custom providers
|
||||
if [[ ! -f "$AGENT_DIR/auth.json" || $FORCE -eq 1 ]]; then
|
||||
echo '{}' > "$AGENT_DIR/auth.json"
|
||||
ok "wrote $AGENT_DIR/auth.json"
|
||||
else
|
||||
warn "skip existing: $AGENT_DIR/auth.json"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$AGENT_DIR/trust.json" || $FORCE -eq 1 ]]; then
|
||||
# Trust the pi home dir by default; add project paths later via pi UI
|
||||
cat > "$AGENT_DIR/trust.json" <<EOF
|
||||
{
|
||||
"$PI_HOME": true
|
||||
}
|
||||
EOF
|
||||
ok "wrote $AGENT_DIR/trust.json"
|
||||
else
|
||||
warn "skip existing: $AGENT_DIR/trust.json"
|
||||
fi
|
||||
|
||||
# ── 8. PATH hint for bun installs ─────────────────────────────────────────────
|
||||
ensure_path_hint() {
|
||||
if [[ "$METHOD" != "bun" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local rc=""
|
||||
if [[ -n "${ZSH_VERSION:-}" ]] || [[ -f "$HOME/.zshrc" && ! -f "$HOME/.bashrc" ]]; then
|
||||
rc="$HOME/.zshrc"
|
||||
elif [[ -f "$HOME/.bashrc" ]]; then
|
||||
rc="$HOME/.bashrc"
|
||||
elif [[ -f "$HOME/.profile" ]]; then
|
||||
rc="$HOME/.profile"
|
||||
fi
|
||||
|
||||
local marker='# >>> pi / bun >>>'
|
||||
if [[ -z "$rc" ]]; then
|
||||
warn "Could not detect shell rc. Ensure \$HOME/.bun/bin is on PATH."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if grep -qF "$marker" "$rc" 2>/dev/null; then
|
||||
ok "PATH already configured in $rc"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Append without command-substitution (avoids ')' inside case breaking $())
|
||||
{
|
||||
echo ""
|
||||
echo "# >>> pi / bun >>>"
|
||||
echo 'export BUN_INSTALL="${BUN_INSTALL:-$HOME/.bun}"'
|
||||
echo 'if [[ ":$PATH:" != *":$BUN_INSTALL/bin:"* ]]; then'
|
||||
echo ' export PATH="$BUN_INSTALL/bin:$PATH"'
|
||||
echo 'fi'
|
||||
echo "# <<< pi / bun <<<"
|
||||
} >> "$rc"
|
||||
ok "appended bun PATH to $rc"
|
||||
}
|
||||
ensure_path_hint
|
||||
|
||||
# ── done ──────────────────────────────────────────────────────────────────────
|
||||
cat <<EOF
|
||||
|
||||
────────────────────────────────────────────────────────
|
||||
Pi core setup complete
|
||||
────────────────────────────────────────────────────────
|
||||
Binary : $(command -v pi)
|
||||
Version: $(pi --version 2>/dev/null || echo unknown)
|
||||
Config : $AGENT_DIR
|
||||
|
||||
Next steps:
|
||||
1. Edit API keys:
|
||||
$EDITOR "$AGENT_DIR/models.json"
|
||||
Replace:
|
||||
YOUR_LLM_GW_API_KEY
|
||||
YOUR_MBBANK_API_KEY
|
||||
|
||||
2. Verify models:
|
||||
pi --list-models
|
||||
|
||||
3. Start:
|
||||
pi
|
||||
# or pin model:
|
||||
pi --provider llm-gw --model code
|
||||
|
||||
Re-run with --force to overwrite settings/models/APPEND_SYSTEM.
|
||||
Optional later:
|
||||
pi install npm:context-mode
|
||||
pi install npm:pi-mcp-adapter
|
||||
# ...other packages from the full machine profile
|
||||
────────────────────────────────────────────────────────
|
||||
EOF
|
||||
Reference in New Issue
Block a user