evals 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/cli.js +61 -1
- package/onboarding-prompt.md +164 -8
- package/package.json +6 -3
- package/start.ps1 +44 -6
- package/start.sh +56 -14
- package/vendor/LICENSE-coding-harness-tracing +202 -0
- package/vendor/MANIFEST +6 -0
- package/vendor/certifi-2026.7.22-py3-none-any.whl +0 -0
- package/vendor/coding_harness_tracing-0.1.0-py3-none-any.whl +0 -0
- package/vendor/harness-install.bat +351 -0
- package/vendor/harness-install.sh +439 -0
- package/vendor/harness-pin.lock.json +18 -0
- package/vendor/python_dotenv-1.2.1-py3-none-any.whl +0 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Arize Coding Harness Tracing — Thin shell router
|
|
3
|
+
#
|
|
4
|
+
# Handles Python discovery, repo clone/tarball, venv creation, and pip install.
|
|
5
|
+
# All harness-specific logic lives in tracing/<harness>/install.py.
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# curl -sSL .../install.sh | bash -s -- claude [--with-skills] [--branch NAME]
|
|
9
|
+
# ./install.sh uninstall [<harness>]
|
|
10
|
+
# ./install.sh update
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
REPO_URL="https://github.com/Arize-ai/coding-harness-tracing.git"
|
|
15
|
+
INSTALL_BRANCH="${ARIZE_INSTALL_BRANCH:-main}"
|
|
16
|
+
TARBALL_URL="https://github.com/Arize-ai/coding-harness-tracing/archive/refs/heads/${INSTALL_BRANCH}.tar.gz"
|
|
17
|
+
INSTALL_DIR="${HOME}/.arize/harness"
|
|
18
|
+
VENV_DIR="${INSTALL_DIR}/venv"
|
|
19
|
+
# When set, install from local wheels in this directory instead of fetching the
|
|
20
|
+
# repo. Lets a caller that already ships the wheels install with no network at
|
|
21
|
+
# all — and with no remote code execution for a permission layer to object to.
|
|
22
|
+
WHEEL_DIR="${ARIZE_WHEEL_DIR:-}"
|
|
23
|
+
|
|
24
|
+
# -- Terminal helpers --------------------------------------------------------
|
|
25
|
+
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
|
26
|
+
BLUE='\033[0;34m'; BOLD='\033[1m'; NC='\033[0m'
|
|
27
|
+
[[ -n "${NO_COLOR:-}" ]] || [[ ! -t 1 ]] && { RED=""; GREEN=""; YELLOW=""; BLUE=""; BOLD=""; NC=""; }
|
|
28
|
+
|
|
29
|
+
info() { echo -e "${GREEN}[arize]${NC} $*"; }
|
|
30
|
+
warn() { echo -e "${YELLOW}[arize]${NC} $*"; }
|
|
31
|
+
err() { echo -e "${RED}[arize]${NC} $*" >&2; }
|
|
32
|
+
header() { echo -e "\n${BOLD}${BLUE}$*${NC}\n"; }
|
|
33
|
+
command_exists() { command -v "$1" &>/dev/null; }
|
|
34
|
+
|
|
35
|
+
# TTY input for curl|bash scenarios
|
|
36
|
+
_tty_in=""
|
|
37
|
+
if [[ -t 0 ]]; then _tty_in="/dev/stdin"
|
|
38
|
+
elif (exec 3< /dev/tty) 2>/dev/null; then exec 3<&-; _tty_in="/dev/tty"; fi
|
|
39
|
+
|
|
40
|
+
# Run a command with stdin wired to the user's TTY when possible.
|
|
41
|
+
# Under `curl | bash`, our own stdin is the pipe — not a terminal — so any
|
|
42
|
+
# subprocess that calls input() (e.g. tracing/<harness>/install.py) would hit
|
|
43
|
+
# EOFError on the very first prompt. Redirecting from _tty_in lets Python read
|
|
44
|
+
# from the actual terminal. No-op in non-interactive environments without a TTY.
|
|
45
|
+
run_with_tty() {
|
|
46
|
+
if [[ -n "$_tty_in" ]]; then
|
|
47
|
+
"$@" < "$_tty_in"
|
|
48
|
+
else
|
|
49
|
+
"$@"
|
|
50
|
+
fi
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# -- Python discovery --------------------------------------------------------
|
|
54
|
+
find_python() {
|
|
55
|
+
local candidates=(python3 python /usr/bin/python3 /usr/local/bin/python3 "$HOME/.local/bin/python3")
|
|
56
|
+
[[ -d "$HOME/.pyenv/shims" ]] && candidates+=("$HOME/.pyenv/shims/python3")
|
|
57
|
+
[[ -x "/opt/homebrew/bin/python3" ]] && candidates+=("/opt/homebrew/bin/python3")
|
|
58
|
+
local conda_base
|
|
59
|
+
conda_base=$(conda info --base 2>/dev/null) && [[ -n "$conda_base" ]] && candidates+=("${conda_base}/bin/python3")
|
|
60
|
+
for p in "${candidates[@]}"; do
|
|
61
|
+
local resolved
|
|
62
|
+
if [[ "$p" == /* ]]; then resolved="$p"
|
|
63
|
+
else resolved=$(command -v "$p" 2>/dev/null || true); fi
|
|
64
|
+
[[ -z "$resolved" || ! -f "$resolved" ]] && continue
|
|
65
|
+
"$resolved" -c "import sys; assert sys.version_info >= (3, 9)" 2>/dev/null && { echo "$resolved"; return 0; }
|
|
66
|
+
done
|
|
67
|
+
return 1
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# -- Venv helpers ------------------------------------------------------------
|
|
71
|
+
venv_python() {
|
|
72
|
+
[[ -x "${VENV_DIR}/bin/python" ]] && { echo "${VENV_DIR}/bin/python"; return; }
|
|
73
|
+
[[ -x "${VENV_DIR}/Scripts/python.exe" ]] && { echo "${VENV_DIR}/Scripts/python.exe"; return; }
|
|
74
|
+
return 1
|
|
75
|
+
}
|
|
76
|
+
venv_pip() {
|
|
77
|
+
[[ -x "${VENV_DIR}/bin/pip" ]] && { echo "${VENV_DIR}/bin/pip"; return; }
|
|
78
|
+
[[ -x "${VENV_DIR}/Scripts/pip.exe" ]] && { echo "${VENV_DIR}/Scripts/pip.exe"; return; }
|
|
79
|
+
return 1
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# -- Repository download ----------------------------------------------------
|
|
83
|
+
git_sync_harness_repo() {
|
|
84
|
+
local branch="$1"
|
|
85
|
+
[[ -d "${INSTALL_DIR}/.git" ]] || return 1
|
|
86
|
+
info "Syncing with origin/${branch}..."
|
|
87
|
+
git -C "$INSTALL_DIR" fetch --depth 1 origin "$branch" 2>/dev/null \
|
|
88
|
+
&& git -C "$INSTALL_DIR" checkout -B "$branch" FETCH_HEAD 2>/dev/null && return 0
|
|
89
|
+
git -C "$INSTALL_DIR" fetch origin "$branch" 2>/dev/null \
|
|
90
|
+
&& git -C "$INSTALL_DIR" checkout -B "$branch" FETCH_HEAD 2>/dev/null && return 0
|
|
91
|
+
warn "git fetch/checkout failed — trying pull --ff-only"
|
|
92
|
+
git -C "$INSTALL_DIR" pull --ff-only origin "$branch" 2>/dev/null && return 0
|
|
93
|
+
git -C "$INSTALL_DIR" pull --ff-only 2>/dev/null && return 0
|
|
94
|
+
return 1
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
install_repo_tarball() {
|
|
98
|
+
local tarball_url="${1:-$TARBALL_URL}"
|
|
99
|
+
info "Downloading coding-harness-tracing tarball..."
|
|
100
|
+
local tmp_tar; tmp_tar="$(mktemp)"
|
|
101
|
+
if command_exists curl; then curl -sSfL "$tarball_url" -o "$tmp_tar"
|
|
102
|
+
elif command_exists wget; then wget -qO "$tmp_tar" "$tarball_url"
|
|
103
|
+
else rm -f "$tmp_tar"; err "Neither curl nor wget found — cannot download"; exit 1; fi
|
|
104
|
+
mkdir -p "$INSTALL_DIR"
|
|
105
|
+
tar xzf "$tmp_tar" --strip-components=1 -C "$INSTALL_DIR"
|
|
106
|
+
rm -f "$tmp_tar"
|
|
107
|
+
info "Extracted to ${INSTALL_DIR}"
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
install_repo() {
|
|
111
|
+
# Wheel mode fetches nothing. The wheel carries every module the harness
|
|
112
|
+
# needs, so there is no source tree to place — but install.sh itself has to
|
|
113
|
+
# land in INSTALL_DIR, because `status`, `update` and `uninstall` are all
|
|
114
|
+
# documented as running from there and repo mode gets it via the extract.
|
|
115
|
+
if [[ -n "$WHEEL_DIR" ]]; then
|
|
116
|
+
mkdir -p "$INSTALL_DIR"
|
|
117
|
+
if [[ -f "${BASH_SOURCE[0]}" ]] && ! cmp -s "${BASH_SOURCE[0]}" "${INSTALL_DIR}/install.sh"; then
|
|
118
|
+
cp "${BASH_SOURCE[0]}" "${INSTALL_DIR}/install.sh" && chmod +x "${INSTALL_DIR}/install.sh"
|
|
119
|
+
fi
|
|
120
|
+
return 0
|
|
121
|
+
fi
|
|
122
|
+
git_sync_harness_repo "$INSTALL_BRANCH" && return 0
|
|
123
|
+
install_repo_tarball
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# Invoke a harness's install.py. Repo mode runs the file from the source tree;
|
|
127
|
+
# wheel mode has no source tree, so it runs the same code as a module. Both
|
|
128
|
+
# resolve `core.*` from site-packages either way — the package is pip-installed,
|
|
129
|
+
# never on sys.path by accident — so these are equivalent, not a fallback.
|
|
130
|
+
run_harness_py() {
|
|
131
|
+
local key="$1" vp="$2"; shift 2
|
|
132
|
+
local dir; dir=$(harness_dir "$key") || return 1
|
|
133
|
+
if [[ -f "${INSTALL_DIR}/${dir}/install.py" ]]; then
|
|
134
|
+
run_with_tty "$vp" "${INSTALL_DIR}/${dir}/install.py" "$@"
|
|
135
|
+
else
|
|
136
|
+
run_with_tty "$vp" -m "${dir//\//.}.install" "$@"
|
|
137
|
+
fi
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
# -- Venv setup --------------------------------------------------------------
|
|
141
|
+
|
|
142
|
+
# Fix SSL certificate verification on macOS.
|
|
143
|
+
#
|
|
144
|
+
# Python.org installers ship their own OpenSSL that doesn't trust the macOS
|
|
145
|
+
# system keychain, so urllib (used by every arize-hook-*) fails with
|
|
146
|
+
# "CERTIFICATE_VERIFY_FAILED" against https://otlp.arize.com.
|
|
147
|
+
#
|
|
148
|
+
# Fix: install certifi into the venv and write a sitecustomize.py that sets
|
|
149
|
+
# SSL_CERT_FILE before any hook code runs. Idempotent — safe to call repeatedly.
|
|
150
|
+
_fix_macos_ssl_certs() {
|
|
151
|
+
local pip="$1"
|
|
152
|
+
local vp
|
|
153
|
+
vp=$(venv_python 2>/dev/null) || return 0
|
|
154
|
+
|
|
155
|
+
local offline=()
|
|
156
|
+
[[ -n "$WHEEL_DIR" ]] && offline=(--no-index --find-links "$WHEEL_DIR")
|
|
157
|
+
if ! "$pip" install --quiet "${offline[@]+"${offline[@]}"}" certifi 2>/dev/null; then
|
|
158
|
+
warn "Could not install certifi — SSL verification may fail on macOS"
|
|
159
|
+
[[ -n "$WHEEL_DIR" ]] && warn "Bundle a certifi wheel in ${WHEEL_DIR} to fix this offline."
|
|
160
|
+
return 0
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
local certifi_where site_dir sc
|
|
164
|
+
certifi_where=$("$vp" -c "import certifi; print(certifi.where())" 2>/dev/null) || return 0
|
|
165
|
+
[[ -z "$certifi_where" ]] && return 0
|
|
166
|
+
|
|
167
|
+
site_dir=$("$vp" -c "import site; print(site.getsitepackages()[0])" 2>/dev/null) || return 0
|
|
168
|
+
sc="${site_dir}/sitecustomize.py"
|
|
169
|
+
|
|
170
|
+
cat > "$sc" <<'PYEOF'
|
|
171
|
+
# Arize Coding Harness Tracing: point Python's SSL stack at certifi's CA bundle on macOS.
|
|
172
|
+
# This runs automatically at interpreter startup, before any hook code.
|
|
173
|
+
import os as _os
|
|
174
|
+
try:
|
|
175
|
+
import certifi as _certifi
|
|
176
|
+
_bundle = _certifi.where()
|
|
177
|
+
_os.environ.setdefault("SSL_CERT_FILE", _bundle)
|
|
178
|
+
_os.environ.setdefault("REQUESTS_CA_BUNDLE", _bundle)
|
|
179
|
+
except ImportError:
|
|
180
|
+
pass
|
|
181
|
+
PYEOF
|
|
182
|
+
info "SSL certificates configured via certifi"
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
# Install the package into the venv. Extra args go to pip (`-U` for update).
|
|
186
|
+
# Shared so install and update cannot drift: they were the same wheel/repo branch
|
|
187
|
+
# twice, differing only by -U, and a flag added to one would have missed the other.
|
|
188
|
+
pip_install_harness() {
|
|
189
|
+
local pip="$1"; shift
|
|
190
|
+
if [[ -n "$WHEEL_DIR" ]]; then
|
|
191
|
+
# --no-index so a missing wheel fails loudly instead of quietly reaching
|
|
192
|
+
# PyPI, which would defeat the point of installing offline.
|
|
193
|
+
"$pip" install --quiet "$@" --no-index --find-links "$WHEEL_DIR" coding-harness-tracing \
|
|
194
|
+
|| { err "Failed to install coding-harness-tracing from ${WHEEL_DIR}"; return 1; }
|
|
195
|
+
else
|
|
196
|
+
"$pip" install --quiet "$@" "$INSTALL_DIR" 2>/dev/null \
|
|
197
|
+
|| { err "Failed to install coding-harness-tracing package"; return 1; }
|
|
198
|
+
fi
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
setup_venv() {
|
|
202
|
+
local python_cmd="$1"
|
|
203
|
+
if ! venv_python &>/dev/null; then
|
|
204
|
+
info "Creating venv..."
|
|
205
|
+
"$python_cmd" -m venv "$VENV_DIR" 2>/dev/null || {
|
|
206
|
+
err "Failed to create venv with $python_cmd"
|
|
207
|
+
err "You may need to install the venv module: apt install python3-venv (Debian/Ubuntu)"
|
|
208
|
+
return 1
|
|
209
|
+
}
|
|
210
|
+
fi
|
|
211
|
+
local pip; pip=$(venv_pip) || { err "pip not found in venv"; return 1; }
|
|
212
|
+
info "Installing coding-harness-tracing into venv..."
|
|
213
|
+
pip_install_harness "$pip" || return 1
|
|
214
|
+
|
|
215
|
+
[[ "$(uname)" == "Darwin" ]] && _fix_macos_ssl_certs "$pip"
|
|
216
|
+
|
|
217
|
+
info "Venv ready at ${VENV_DIR}"
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
# -- Harness name mapping ----------------------------------------------------
|
|
221
|
+
#
|
|
222
|
+
# Accepts both the CLI name and the config key. They are the same for every
|
|
223
|
+
# harness except Claude Code, which writes HARNESS_NAME "claude-code" while its
|
|
224
|
+
# CLI name is "claude". `update` and full `uninstall` discover harnesses via
|
|
225
|
+
# list_installed_harnesses(), which yields *config keys*, so without the alias
|
|
226
|
+
# both skipped Claude Code entirely — a full uninstall wiped the venv and left
|
|
227
|
+
# its hooks in ~/.claude/settings.json pointing at the deleted path.
|
|
228
|
+
# install.bat has accepted both spellings all along.
|
|
229
|
+
harness_dir() {
|
|
230
|
+
case "$1" in
|
|
231
|
+
claude|claude-code) echo "tracing/claude_code" ;;
|
|
232
|
+
codex) echo "tracing/codex" ;;
|
|
233
|
+
copilot) echo "tracing/copilot" ;;
|
|
234
|
+
cursor) echo "tracing/cursor" ;;
|
|
235
|
+
gemini) echo "tracing/gemini" ;;
|
|
236
|
+
kiro) echo "tracing/kiro" ;;
|
|
237
|
+
antigravity) echo "tracing/antigravity" ;;
|
|
238
|
+
opencode) echo "tracing/opencode" ;;
|
|
239
|
+
omp) echo "tracing/omp" ;;
|
|
240
|
+
devin) echo "tracing/devin" ;;
|
|
241
|
+
*) return 1 ;;
|
|
242
|
+
esac
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
install_harness() {
|
|
246
|
+
local cmd="$1" skills="$2"
|
|
247
|
+
harness_dir "$cmd" >/dev/null || { err "Unknown harness: ${cmd}"; usage; exit 1; }
|
|
248
|
+
header "Installing ${cmd} tracing"
|
|
249
|
+
local python_cmd; python_cmd=$(find_python) || { err "No Python 3.9+ found"; exit 1; }
|
|
250
|
+
info "Found Python: ${python_cmd} ($("$python_cmd" --version 2>&1))"
|
|
251
|
+
install_repo
|
|
252
|
+
setup_venv "$python_cmd"
|
|
253
|
+
local vp; vp=$(venv_python) || { err "Venv python not found after setup"; exit 1; }
|
|
254
|
+
info "Migrating legacy config.yaml to config.json (if present)..."
|
|
255
|
+
"$vp" -m core.config migrate || true
|
|
256
|
+
if [[ "$skills" == true ]]; then
|
|
257
|
+
run_harness_py "$cmd" "$vp" install --with-skills
|
|
258
|
+
else
|
|
259
|
+
run_harness_py "$cmd" "$vp" install
|
|
260
|
+
fi
|
|
261
|
+
info "Setup complete!"
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
usage() {
|
|
265
|
+
cat <<'EOF'
|
|
266
|
+
|
|
267
|
+
Arize Coding Harness Tracing Installer
|
|
268
|
+
|
|
269
|
+
Usage: install.sh <command> [flags]
|
|
270
|
+
|
|
271
|
+
Commands:
|
|
272
|
+
claude Install and configure tracing for Claude Code / Agent SDK
|
|
273
|
+
codex Install and configure tracing for OpenAI Codex CLI
|
|
274
|
+
copilot Install and configure tracing for GitHub Copilot (VS Code + CLI)
|
|
275
|
+
cursor Install and configure tracing for Cursor IDE
|
|
276
|
+
gemini Install and configure tracing for Gemini CLI
|
|
277
|
+
kiro Install and configure tracing for Kiro CLI
|
|
278
|
+
antigravity Install and configure tracing for Google Antigravity CLI/IDE
|
|
279
|
+
opencode Install and configure tracing for opencode
|
|
280
|
+
omp Install and configure tracing for Oh My Pi (omp)
|
|
281
|
+
devin Install and configure tracing for Devin CLI
|
|
282
|
+
status Report configured harnesses and whether their hooks are wired up
|
|
283
|
+
update Update the installed coding-harness-tracing and re-register all harnesses
|
|
284
|
+
uninstall <harness> Tear down one harness
|
|
285
|
+
uninstall Full wipe: venv + repo + shared config
|
|
286
|
+
|
|
287
|
+
Flags:
|
|
288
|
+
--with-skills Symlink harness skills into .agents/skills/
|
|
289
|
+
--branch NAME Install from a specific git branch (default: main)
|
|
290
|
+
--wheel-dir DIR Install from local wheels in DIR instead of downloading
|
|
291
|
+
the repo. No network and no remote code execution; also
|
|
292
|
+
settable as ARIZE_WHEEL_DIR. Bundle a certifi wheel
|
|
293
|
+
alongside it to keep macOS SSL working offline.
|
|
294
|
+
--json With `status`: emit machine-readable JSON. Exit code is
|
|
295
|
+
0 all wired up, 1 nothing configured, 2 hooks missing.
|
|
296
|
+
--non-interactive, -y Ask nothing; read every value from the environment or a
|
|
297
|
+
file named by ARIZE_ENV_FILE. Missing required
|
|
298
|
+
values are an error.
|
|
299
|
+
|
|
300
|
+
Non-interactive install:
|
|
301
|
+
Values come from the environment, or from a dotenv file named with
|
|
302
|
+
ARIZE_ENV_FILE — which keeps the API key out of the command line and shell
|
|
303
|
+
history. A named file outranks the environment, so there is no automatic
|
|
304
|
+
./.env search: a cloned repo's dotenv must not get to choose the endpoint
|
|
305
|
+
your credentials are sent to.
|
|
306
|
+
|
|
307
|
+
ARIZE_API_KEY, ARIZE_SPACE_ID Arize AX credentials (both required)
|
|
308
|
+
PHOENIX_ENDPOINT, PHOENIX_API_KEY Phoenix credentials
|
|
309
|
+
ARIZE_BACKEND arize|phoenix (default: inferred — a space
|
|
310
|
+
ID means Arize AX, a Phoenix endpoint
|
|
311
|
+
means Phoenix)
|
|
312
|
+
ARIZE_PROJECT_NAME Project name (default: the harness name)
|
|
313
|
+
ARIZE_USER_ID Optional user ID stamped on spans
|
|
314
|
+
ARIZE_OTLP_ENDPOINT Override otlp.arize.com:443
|
|
315
|
+
ARIZE_LOG_PROMPTS Set true to capture prompt text (off here)
|
|
316
|
+
ARIZE_LOG_TOOL_DETAILS Set true to capture tool commands and paths
|
|
317
|
+
ARIZE_LOG_TOOL_CONTENT Set true to capture tool output
|
|
318
|
+
|
|
319
|
+
Example — credentials straight from a dotenv file, nothing exported:
|
|
320
|
+
ax api-keys create --env-file ~/.arize/onboarding.env
|
|
321
|
+
echo 'ARIZE_SPACE_ID=<space-id>' >> ~/.arize/onboarding.env
|
|
322
|
+
ARIZE_ENV_FILE=~/.arize/onboarding.env ./install.sh claude --non-interactive
|
|
323
|
+
|
|
324
|
+
EOF
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
# -- Main dispatch -----------------------------------------------------------
|
|
328
|
+
main() {
|
|
329
|
+
local cmd="${1:-}"; shift || true
|
|
330
|
+
local subcmd="" with_skills=false status_args=""
|
|
331
|
+
local args=("$@") i=0
|
|
332
|
+
while [[ $i -lt ${#args[@]} ]]; do
|
|
333
|
+
case "${args[$i]}" in
|
|
334
|
+
--with-skills) with_skills=true ;;
|
|
335
|
+
--non-interactive|-y) export ARIZE_NONINTERACTIVE=1 ;;
|
|
336
|
+
--json) status_args="--json" ;;
|
|
337
|
+
--branch)
|
|
338
|
+
i=$((i + 1))
|
|
339
|
+
INSTALL_BRANCH="${args[$i]:-main}"
|
|
340
|
+
TARBALL_URL="https://github.com/Arize-ai/coding-harness-tracing/archive/refs/heads/${INSTALL_BRANCH}.tar.gz"
|
|
341
|
+
;;
|
|
342
|
+
--wheel-dir)
|
|
343
|
+
i=$((i + 1))
|
|
344
|
+
WHEEL_DIR="${args[$i]:-}"
|
|
345
|
+
[[ -d "$WHEEL_DIR" ]] || { err "--wheel-dir needs a directory; got '${WHEEL_DIR}'"; exit 1; }
|
|
346
|
+
WHEEL_DIR="$(cd "$WHEEL_DIR" && pwd)"
|
|
347
|
+
compgen -G "${WHEEL_DIR}/coding_harness_tracing-*.whl" >/dev/null \
|
|
348
|
+
|| { err "No coding_harness_tracing-*.whl in ${WHEEL_DIR}"; exit 1; }
|
|
349
|
+
;;
|
|
350
|
+
*) [[ -z "$subcmd" ]] && subcmd="${args[$i]}" ;;
|
|
351
|
+
esac
|
|
352
|
+
i=$((i + 1))
|
|
353
|
+
done
|
|
354
|
+
|
|
355
|
+
case "$cmd" in
|
|
356
|
+
claude|codex|copilot|cursor|gemini|kiro|antigravity|opencode|omp|devin)
|
|
357
|
+
install_harness "$cmd" "$with_skills"
|
|
358
|
+
;;
|
|
359
|
+
uninstall)
|
|
360
|
+
if [[ -n "$subcmd" ]]; then
|
|
361
|
+
harness_dir "$subcmd" >/dev/null || { err "Unknown harness: ${subcmd}"; usage; exit 1; }
|
|
362
|
+
local vp; vp=$(venv_python) || { err "Venv not found — nothing to uninstall"; exit 1; }
|
|
363
|
+
header "Uninstalling ${subcmd} tracing"
|
|
364
|
+
run_harness_py "$subcmd" "$vp" uninstall
|
|
365
|
+
else
|
|
366
|
+
local vp; vp=$(venv_python) || {
|
|
367
|
+
warn "Venv not found — removing install directory"; rm -rf "$INSTALL_DIR"
|
|
368
|
+
info "Uninstall complete."; return 0; }
|
|
369
|
+
header "Full uninstall"
|
|
370
|
+
# Run each installed harness's uninstall first so external
|
|
371
|
+
# registrations (settings.json hooks, config.toml notify,
|
|
372
|
+
# cursor hooks.json, .github/hooks/*) are cleaned before the
|
|
373
|
+
# shared runtime is wiped. wipe.py deliberately does not
|
|
374
|
+
# touch those files.
|
|
375
|
+
local harnesses
|
|
376
|
+
harnesses=$("$vp" -c 'from core.setup import list_installed_harnesses as L; print("\n".join(L()))' 2>/dev/null) || true
|
|
377
|
+
if [[ -n "$harnesses" ]]; then
|
|
378
|
+
while IFS= read -r key; do
|
|
379
|
+
harness_dir "$key" >/dev/null || { warn "Unknown harness: ${key} (skipping)"; continue; }
|
|
380
|
+
info "Uninstalling ${key} tracing..."
|
|
381
|
+
run_harness_py "$key" "$vp" uninstall || warn "${key} uninstall failed (continuing)"
|
|
382
|
+
done <<< "$harnesses"
|
|
383
|
+
fi
|
|
384
|
+
"$vp" -m core.setup.wipe
|
|
385
|
+
fi
|
|
386
|
+
;;
|
|
387
|
+
status)
|
|
388
|
+
local vp; vp=$(venv_python) || { err "Venv not found — nothing installed"; exit 1; }
|
|
389
|
+
"$vp" -m core.setup.status $status_args
|
|
390
|
+
;;
|
|
391
|
+
update)
|
|
392
|
+
header "Updating coding-harness-tracing"
|
|
393
|
+
# Re-registering runs each harness's installer, which prompts for the
|
|
394
|
+
# project name. With no terminal to answer on that used to die with an
|
|
395
|
+
# EOFError, so fall back to stored values there — and only there, so an
|
|
396
|
+
# interactive update keeps every prompt it has today.
|
|
397
|
+
[[ -n "$_tty_in" ]] || export ARIZE_NONINTERACTIVE=1
|
|
398
|
+
# A wheel install has no repo to pull and no newer wheel to hand us.
|
|
399
|
+
# Silently converting it to a network install would change how it was
|
|
400
|
+
# installed behind the user's back, so refuse and say who can update.
|
|
401
|
+
if [[ -z "$WHEEL_DIR" && ! -d "${INSTALL_DIR}/.git" && ! -f "${INSTALL_DIR}/pyproject.toml" ]]; then
|
|
402
|
+
err "This looks like an offline install with no source tree to update."
|
|
403
|
+
err "Re-run the installer that created it (for npx evals, update that), or"
|
|
404
|
+
err "pass --wheel-dir <dir> with a newer wheel."
|
|
405
|
+
exit 1
|
|
406
|
+
fi
|
|
407
|
+
if [[ -n "$WHEEL_DIR" ]]; then
|
|
408
|
+
info "Updating from local wheels in ${WHEEL_DIR}..."
|
|
409
|
+
elif [[ -d "${INSTALL_DIR}/.git" ]]; then
|
|
410
|
+
info "Pulling latest changes..."
|
|
411
|
+
git -C "$INSTALL_DIR" pull --ff-only 2>/dev/null || {
|
|
412
|
+
warn "git pull failed — falling back to tarball re-extract"; install_repo_tarball; }
|
|
413
|
+
else install_repo_tarball; fi
|
|
414
|
+
local pip; pip=$(venv_pip) || { err "Venv not found — run install first"; exit 1; }
|
|
415
|
+
info "Reinstalling coding-harness-tracing..."
|
|
416
|
+
pip_install_harness "$pip" -U || exit 1
|
|
417
|
+
local vp; vp=$(venv_python) || { err "venv python not found"; exit 1; }
|
|
418
|
+
info "Migrating legacy config.yaml to config.json (if present)..."
|
|
419
|
+
"$vp" -m core.config migrate || true
|
|
420
|
+
local harnesses
|
|
421
|
+
harnesses=$("$vp" -c 'from core.setup import list_installed_harnesses as L; print("\n".join(L()))' 2>/dev/null) || true
|
|
422
|
+
if [[ -n "$harnesses" ]]; then
|
|
423
|
+
while IFS= read -r key; do
|
|
424
|
+
harness_dir "$key" >/dev/null || { warn "Unknown harness: ${key} (skipping)"; continue; }
|
|
425
|
+
# Keep going, as the uninstall loop does: one harness whose
|
|
426
|
+
# registration fails should not abandon the rest half-updated.
|
|
427
|
+
info "Re-registering ${key}..."
|
|
428
|
+
run_harness_py "$key" "$vp" install || warn "${key} re-registration failed (continuing)"
|
|
429
|
+
done <<< "$harnesses"
|
|
430
|
+
else info "No installed harnesses found to re-register"; fi
|
|
431
|
+
info "Update complete."
|
|
432
|
+
;;
|
|
433
|
+
-h|--help|help) usage ;;
|
|
434
|
+
"") usage; exit 1 ;;
|
|
435
|
+
*) err "Unknown command: ${cmd}"; usage; exit 1 ;;
|
|
436
|
+
esac
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
main "$@"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"repo": "https://github.com/Arize-ai/coding-harness-tracing",
|
|
3
|
+
"ref": "main",
|
|
4
|
+
"resolvedSha": "dd3ed1c455daab380e915fc5404a167811c460f0",
|
|
5
|
+
"source": "git",
|
|
6
|
+
"wheel": "coding_harness_tracing-0.1.0-py3-none-any.whl",
|
|
7
|
+
"wheelVersion": "0.1.0",
|
|
8
|
+
"wheelSha256": "e17d86afa36365ddd451325b7b2ed3e35ba85801fb10e35401fded609095f550",
|
|
9
|
+
"files": [
|
|
10
|
+
"LICENSE-coding-harness-tracing",
|
|
11
|
+
"MANIFEST",
|
|
12
|
+
"certifi-2026.7.22-py3-none-any.whl",
|
|
13
|
+
"coding_harness_tracing-0.1.0-py3-none-any.whl",
|
|
14
|
+
"harness-install.bat",
|
|
15
|
+
"harness-install.sh",
|
|
16
|
+
"python_dotenv-1.2.1-py3-none-any.whl"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
Binary file
|