@osfactory/har 0.49.2 → 0.50.1

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.
@@ -27,6 +27,119 @@ pt_log() {
27
27
  fi
28
28
  }
29
29
 
30
+ # ── Node package manager helpers ──────────────────────────────────────────────
31
+ # Mirrored verbatim in harness.env and provision-toolchain.sh so a sourcing
32
+ # script and the provisioning subprocess resolve the same tool.
33
+
34
+ # Package managers HAR can drive, in fallback preference order.
35
+ HAR_NODE_PACKAGE_MANAGERS="npm bun pnpm yarn"
36
+
37
+ # Package manager the repo declares: an explicit HARNESS_NODE_PACKAGE_MANAGER
38
+ # wins, then package.json "packageManager", then the lockfile. Empty when the
39
+ # repo says nothing.
40
+ har_node_declared_package_manager() {
41
+ local dir="${1:-.}"
42
+
43
+ if [ -n "${HARNESS_NODE_PACKAGE_MANAGER:-}" ]; then
44
+ echo "$HARNESS_NODE_PACKAGE_MANAGER"
45
+ return
46
+ fi
47
+ if [ -f "$dir/package.json" ]; then
48
+ local field
49
+ field="$(sed -n 's/.*"packageManager"[[:space:]]*:[[:space:]]*"\([a-z]*\)@.*/\1/p' "$dir/package.json" | head -1)"
50
+ if [ -n "$field" ]; then
51
+ echo "$field"
52
+ return
53
+ fi
54
+ fi
55
+ if [ -f "$dir/bun.lock" ] || [ -f "$dir/bun.lockb" ]; then echo bun; return; fi
56
+ if [ -f "$dir/pnpm-lock.yaml" ]; then echo pnpm; return; fi
57
+ if [ -f "$dir/yarn.lock" ]; then echo yarn; return; fi
58
+ if [ -f "$dir/package-lock.json" ]; then echo npm; return; fi
59
+ echo ""
60
+ }
61
+
62
+ # Package manager to actually run. A manager the repo declares but this machine
63
+ # lacks falls back to one that is installed, so a repo pinned to npm still
64
+ # provisions on a bun-only machine (and the reverse).
65
+ har_node_package_manager() {
66
+ local dir="${1:-.}"
67
+ local declared
68
+ declared="$(har_node_declared_package_manager "$dir")"
69
+
70
+ if [ -n "$declared" ] && command -v "$declared" >/dev/null 2>&1; then
71
+ echo "$declared"
72
+ return
73
+ fi
74
+
75
+ local candidate
76
+ for candidate in $HAR_NODE_PACKAGE_MANAGERS; do
77
+ if command -v "$candidate" >/dev/null 2>&1; then
78
+ echo "$candidate"
79
+ return
80
+ fi
81
+ done
82
+
83
+ echo "${declared:-npm}"
84
+ }
85
+
86
+ # Lockfile a manager writes, so a substitute install can clean up after itself.
87
+ har_node_lockfile() {
88
+ case "$1" in
89
+ bun) echo "bun.lock" ;;
90
+ npm) echo "package-lock.json" ;;
91
+ pnpm) echo "pnpm-lock.yaml" ;;
92
+ yarn) echo "yarn.lock" ;;
93
+ *) echo "" ;;
94
+ esac
95
+ }
96
+
97
+ # Install dependencies in a directory. When a substitute manager stands in for
98
+ # the one the repo declares, any lockfile it creates is removed afterwards:
99
+ # provisioning must not migrate the repo to a different package manager.
100
+ # (bun writes bun.lock even under --no-save, so the flags alone are not enough.)
101
+ har_node_install() {
102
+ local dir="$1"
103
+ local manager="$2"
104
+ local declared="${3:-}"
105
+ local substituting=false
106
+ local lockfile=""
107
+ local had_lockfile=false
108
+
109
+ if [ -n "$declared" ] && [ "$declared" != "$manager" ]; then
110
+ substituting=true
111
+ lockfile="$(har_node_lockfile "$manager")"
112
+ if [ -n "$lockfile" ] && [ -e "$dir/$lockfile" ]; then
113
+ had_lockfile=true
114
+ fi
115
+ fi
116
+
117
+ local code=0
118
+ (cd "$dir" && "$manager" install --silent) || code=$?
119
+
120
+ if [ "$substituting" = true ] && [ "$had_lockfile" = false ] && [ -n "$lockfile" ]; then
121
+ rm -f "$dir/$lockfile"
122
+ [ "$manager" = "bun" ] && rm -f "$dir/bun.lockb"
123
+ fi
124
+ return $code
125
+ }
126
+
127
+ # Package runner (npx equivalent) for one-off CLIs such as pm2, including the
128
+ # flag that keeps it non-interactive. Takes a manager name, or none to resolve
129
+ # from the environment and PATH.
130
+ har_pkg_exec() {
131
+ case "${1:-${HARNESS_NODE_PACKAGE_MANAGER:-}}" in
132
+ bun) echo "bunx"; return ;;
133
+ pnpm) echo "pnpm dlx"; return ;;
134
+ yarn) echo "yarn dlx"; return ;;
135
+ npm) echo "npx --yes"; return ;;
136
+ esac
137
+ if command -v npx >/dev/null 2>&1; then echo "npx --yes"; return; fi
138
+ if command -v bunx >/dev/null 2>&1; then echo "bunx"; return; fi
139
+ if command -v pnpm >/dev/null 2>&1; then echo "pnpm dlx"; return; fi
140
+ echo "npx --yes"
141
+ }
142
+
30
143
  append_env() {
31
144
  local key="$1"
32
145
  local value="$2"
@@ -81,32 +194,37 @@ run_install_cmd() {
81
194
 
82
195
  provision_node() {
83
196
  local dir="$1"
84
- local npm_bin="npm"
85
197
  local node_bin="node"
198
+ local pkg_manager declared_manager
199
+ declared_manager="$(har_node_declared_package_manager "$dir")"
200
+ pkg_manager="$(har_node_package_manager "$dir")"
201
+
202
+ if [ -n "$declared_manager" ] && [ "$declared_manager" != "$pkg_manager" ]; then
203
+ pt_log "Repo declares ${declared_manager}, which is not on PATH — installing with ${pkg_manager} and leaving the lockfile untouched."
204
+ fi
86
205
 
87
206
  if ! run_install_cmd "$dir"; then
88
- pt_log "Installing Node dependencies..."
89
- if [ -f "$dir/pnpm-lock.yaml" ] && command -v pnpm >/dev/null 2>&1; then
90
- (cd "$dir" && pnpm install --silent)
91
- npm_bin="pnpm"
92
- elif [ -f "$dir/yarn.lock" ] && command -v yarn >/dev/null 2>&1; then
93
- (cd "$dir" && yarn install --silent)
94
- npm_bin="yarn"
95
- else
96
- (cd "$dir" && npm install --silent)
97
- fi
207
+ pt_log "Installing Node dependencies with ${pkg_manager}..."
208
+ har_node_install "$dir" "$pkg_manager" "$declared_manager"
98
209
  fi
99
210
 
100
211
  if command -v node >/dev/null 2>&1; then
101
212
  node_bin="$(command -v node)"
213
+ elif [ "$pkg_manager" = "bun" ]; then
214
+ # bun-only machine: bun runs the `node -e` snippets verify.sh relies on.
215
+ node_bin="$(command -v bun)"
102
216
  fi
103
- if [ "$npm_bin" = "npm" ] && command -v npm >/dev/null 2>&1; then
104
- npm_bin="$(command -v npm)"
217
+
218
+ local npm_bin="$pkg_manager"
219
+ if command -v "$pkg_manager" >/dev/null 2>&1; then
220
+ npm_bin="$(command -v "$pkg_manager")"
105
221
  fi
106
222
 
107
223
  append_env "HARNESS_ECOSYSTEM" "node"
108
224
  append_env "NODE_BIN" "$node_bin"
109
225
  append_env "NPM_BIN" "$npm_bin"
226
+ append_env "HARNESS_NODE_PACKAGE_MANAGER" "$pkg_manager"
227
+ append_env "HARNESS_PKG_EXEC" "$(har_pkg_exec "$pkg_manager")"
110
228
  append_path_prefix "$dir/node_modules/.bin"
111
229
  }
112
230
 
@@ -252,8 +370,11 @@ provision_monorepo_root() {
252
370
  [ -n "$HAR_WORKTREE_DIR" ] || return 0
253
371
  [ -f "$HAR_WORKTREE_DIR/package.json" ] || return 0
254
372
  [ -d "$HAR_WORKTREE_DIR/node_modules" ] && return 0
255
- pt_log "Installing monorepo root dependencies in $HAR_WORKTREE_DIR..."
256
- (cd "$HAR_WORKTREE_DIR" && npm install --silent)
373
+ local pkg_manager
374
+ pkg_manager="$(har_node_package_manager "$HAR_WORKTREE_DIR")"
375
+ pt_log "Installing monorepo root dependencies in $HAR_WORKTREE_DIR with ${pkg_manager}..."
376
+ har_node_install "$HAR_WORKTREE_DIR" "$pkg_manager" \
377
+ "$(har_node_declared_package_manager "$HAR_WORKTREE_DIR")"
257
378
  }
258
379
 
259
380
  provision_ecosystem() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osfactory/har",
3
- "version": "0.49.2",
3
+ "version": "0.50.1",
4
4
  "description": "Open harness for reproducible multi-agent coding workflows",
5
5
  "keywords": [
6
6
  "har",