@humanu/orchestra 0.5.22 → 0.5.25

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/install.js CHANGED
@@ -111,7 +111,23 @@ function linkCompatibilityBinary(binaryPath) {
111
111
  function installPrebuiltBinary() {
112
112
  const platform = getPlatformKey();
113
113
  const source = path.join(prebuiltDir, platform, BINARY_NAME);
114
+
114
115
  if (!fs.existsSync(source)) {
116
+ console.log(`⚠️ No prebuilt binary found for ${platform}`);
117
+
118
+ // Check if we have binaries for other platforms (for debugging)
119
+ if (fs.existsSync(prebuiltDir)) {
120
+ const availablePlatforms = fs.readdirSync(prebuiltDir).filter(item => {
121
+ const platformPath = path.join(prebuiltDir, item);
122
+ return fs.statSync(platformPath).isDirectory() &&
123
+ fs.existsSync(path.join(platformPath, BINARY_NAME));
124
+ });
125
+
126
+ if (availablePlatforms.length > 0) {
127
+ console.log(` Available platforms: ${availablePlatforms.join(', ')}`);
128
+ }
129
+ }
130
+
115
131
  return false;
116
132
  }
117
133
 
@@ -124,24 +140,61 @@ function installPrebuiltBinary() {
124
140
 
125
141
  function buildFromSource() {
126
142
  if (!hasLocalSource) {
127
- console.error('No prebuilt binary available and source tree not found.');
128
- console.error('Clone the repository and run `cargo build --release` to build locally.');
143
+ console.error('No prebuilt binary available and source tree not found.');
144
+ console.error('');
145
+ console.error('This usually happens when:');
146
+ console.error('1. The npm package was built on a different platform (e.g., macOS vs Linux)');
147
+ console.error('2. The binary for your platform is missing from the package');
148
+ console.error('');
149
+ console.error('Solutions:');
150
+ console.error('1. Install from source (requires Rust toolchain):');
151
+ console.error(' git clone https://github.com/humanunsupervised/orchestra.git');
152
+ console.error(' cd orchestra');
153
+ console.error(' cargo build --release');
154
+ console.error('');
155
+ console.error('2. Use a pre-built release:');
156
+ console.error(' Download from: https://github.com/humanunsupervised/orchestra/releases');
157
+ console.error('');
158
+ console.error('3. Install Rust and build locally:');
159
+ console.error(' curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh');
160
+ console.error(' source ~/.cargo/env');
161
+ console.error(' cargo build --release');
129
162
  process.exit(1);
130
163
  }
131
164
 
132
165
  try {
133
166
  execSync('cargo --version', { stdio: 'ignore' });
134
167
  } catch (error) {
135
- console.error('Rust toolchain not found. Install Rust from https://rustup.rs/.');
168
+ console.error('Rust toolchain not found.');
169
+ console.error('');
170
+ console.error('Install Rust from https://rustup.rs/');
171
+ console.error('Then run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh');
136
172
  process.exit(1);
137
173
  }
138
174
 
139
- console.log('Building from source...');
140
- execSync('cargo build --release', { stdio: 'inherit', cwd: path.join(projectRoot, 'gw-tui') });
175
+ console.log('🔨 Building from source... (this may take a few minutes)');
176
+ console.log(' Working directory:', path.join(projectRoot, 'gw-tui'));
177
+
178
+ try {
179
+ execSync('cargo build --release', { stdio: 'inherit', cwd: path.join(projectRoot, 'gw-tui') });
180
+ } catch (error) {
181
+ console.error('❌ Build failed.');
182
+ console.error('');
183
+ console.error('Common issues:');
184
+ console.error('- Missing system dependencies (openssl, pkg-config, etc.)');
185
+ console.error('- Network issues during dependency download');
186
+ console.error('');
187
+ console.error('Try installing dependencies:');
188
+ console.error('- Ubuntu/Debian: sudo apt-get install libssl-dev pkg-config');
189
+ console.error('- macOS: brew install openssl pkg-config');
190
+ console.error('- Fedora: sudo dnf install openssl-devel pkgconfig');
191
+ process.exit(1);
192
+ }
141
193
 
142
194
  const builtBinary = path.join(projectRoot, 'gw-tui', 'target', 'release', 'gw-tui');
143
195
  if (!fs.existsSync(builtBinary)) {
144
- console.error('Build finished but gw-tui binary was not produced.');
196
+ console.error('Build finished but gw-tui binary was not produced.');
197
+ console.error(' Expected location:', builtBinary);
145
198
  process.exit(1);
146
199
  }
147
200
 
@@ -149,6 +202,8 @@ function buildFromSource() {
149
202
  fs.copyFileSync(builtBinary, destination);
150
203
  fs.chmodSync(destination, 0o755);
151
204
  linkCompatibilityBinary(destination);
205
+
206
+ console.log('✅ Successfully built from source!');
152
207
  }
153
208
 
154
209
  function assetsReady() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@humanu/orchestra",
3
- "version": "0.5.22",
3
+ "version": "0.5.25",
4
4
  "description": "AI-powered Git worktree and tmux session manager with modern TUI",
5
5
  "keywords": [
6
6
  "git",
@@ -0,0 +1,244 @@
1
+ #!/bin/bash
2
+
3
+ ###############################################################################
4
+ # copy_env.sh – Shared helpers for copying .env/config files into worktrees
5
+ # ---------------------------------------------------------------------------
6
+ # Provides reusable functions consumed by commands.sh, gw-bridge.sh, and any
7
+ # other shell entry point. Adds structured logging so we can troubleshoot which
8
+ # files were selected and whether individual copy operations succeeded.
9
+ ###############################################################################
10
+
11
+ # Global variables populated by copy_env_files
12
+ COPY_ENV_LAST_COPIED=0
13
+ COPY_ENV_LAST_TARGET=""
14
+ COPY_ENV_LOG_FILE=""
15
+
16
+ # Internal: write a log line (timestamped). Respects COPY_ENV_VERBOSE: if set to
17
+ # 1, the message is also echoed to stderr for real-time debugging.
18
+ copy_env_log() {
19
+ local level="$1"
20
+ shift
21
+ local message="$*"
22
+ local timestamp
23
+ timestamp="$(date '+%Y-%m-%d %H:%M:%S')"
24
+ if [[ -n "$COPY_ENV_LOG_FILE" ]]; then
25
+ if ! printf '%s [%s] %s\n' "$timestamp" "$level" "$message" >>"$COPY_ENV_LOG_FILE" 2>/dev/null; then
26
+ # If we cannot write to the configured log file, drop logging to disk
27
+ COPY_ENV_LOG_FILE=""
28
+ fi
29
+ fi
30
+ if [[ ${COPY_ENV_VERBOSE:-0} -eq 1 ]]; then
31
+ printf '[copy-env][%s] %s\n' "$level" "$message" >&2
32
+ fi
33
+ }
34
+
35
+ # Determine which locations to copy by reading <repo>/.orchestra/options.json.
36
+ copy_env_load_locations() {
37
+ local repo_root="$1"
38
+ local config_file="$repo_root/.orchestra/options.json"
39
+
40
+ if [[ -f "$config_file" ]]; then
41
+ if command -v jq >/dev/null 2>&1; then
42
+ jq -r '(.copy_locations // ["/"])[]' "$config_file" 2>/dev/null || printf '/\n'
43
+ return
44
+ elif command -v python3 >/dev/null 2>&1; then
45
+ python3 - "$config_file" <<'PY'
46
+ import json
47
+ import sys
48
+ from pathlib import Path
49
+
50
+ config_path = Path(sys.argv[1])
51
+ try:
52
+ data = json.loads(config_path.read_text())
53
+ except Exception:
54
+ data = {}
55
+ locations = data.get("copy_locations")
56
+ if isinstance(locations, list) and locations:
57
+ for entry in locations:
58
+ if isinstance(entry, str):
59
+ print(entry)
60
+ else:
61
+ print("/")
62
+ PY
63
+ return
64
+ fi
65
+ fi
66
+ # Fallback: default to repo root
67
+ printf '/\n'
68
+ }
69
+
70
+ # Copy .env files from the source worktree into the target worktree.
71
+ # Arguments:
72
+ # $1 - source root (worktree we are copying from)
73
+ # $2 - target root (new or existing worktree)
74
+ # $3 - repository shared root (defaults to source root)
75
+ # $4 - quiet flag (1 suppresses user-facing echo output)
76
+ copy_env_files() {
77
+ local source_root="$1"
78
+ local target_root="$2"
79
+ local repo_root="${3:-$source_root}"
80
+ local quiet="${4:-0}"
81
+
82
+ COPY_ENV_LAST_COPIED=0
83
+ COPY_ENV_LAST_TARGET="$target_root"
84
+
85
+ local enable_logs=${COPY_ENV_ENABLE_LOG:-0}
86
+ local log_file="${COPY_ENV_LOG_FILE:-}"
87
+ local log_dir="${COPY_ENV_LOG_DIR:-}"
88
+
89
+ if [[ -n "$log_file" ]]; then
90
+ mkdir -p "$(dirname "$log_file")" 2>/dev/null || true
91
+ COPY_ENV_LOG_FILE="$log_file"
92
+ elif [[ $enable_logs -eq 1 || -n "$log_dir" ]]; then
93
+ log_dir="${log_dir:-$repo_root/.orchestra/logs}"
94
+ mkdir -p "$log_dir" 2>/dev/null || true
95
+ COPY_ENV_LOG_FILE="$log_dir/copy-env.log"
96
+ else
97
+ COPY_ENV_LOG_FILE=""
98
+ fi
99
+
100
+ copy_env_log "INFO" "Starting copy (source=$source_root, target=$target_root, repo=$repo_root)"
101
+
102
+ local override_locations="${COPY_ENV_OVERRIDE_LOCATIONS:-}"
103
+ unset COPY_ENV_OVERRIDE_LOCATIONS
104
+ local locations=()
105
+ if [[ -n "$override_locations" ]]; then
106
+ while IFS= read -r line; do
107
+ [[ -z "$line" ]] && continue
108
+ locations+=("$line")
109
+ done <<<"$override_locations"
110
+ else
111
+ while IFS= read -r line; do
112
+ [[ -z "$line" ]] && continue
113
+ locations+=("$line")
114
+ done < <(copy_env_load_locations "$repo_root")
115
+ fi
116
+
117
+ if [[ ${#locations[@]} -eq 0 ]]; then
118
+ locations=("/")
119
+ fi
120
+
121
+ local bases=("$source_root")
122
+ if [[ -n "$repo_root" && "$repo_root" != "$source_root" ]]; then
123
+ bases+=("$repo_root")
124
+ fi
125
+
126
+ local overall_copied=0
127
+ local overall_failed=0
128
+
129
+ (( quiet != 1 )) && echo "🔧 Copying .env files to worktree..."
130
+
131
+ for raw_location in "${locations[@]}"; do
132
+ local trimmed
133
+ trimmed="$(printf '%s' "$raw_location" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
134
+ [[ -z "$trimmed" ]] && continue
135
+
136
+ local rel="${trimmed#/}"
137
+ rel="${rel#./}"
138
+
139
+ local location_copied=0
140
+ local location_failed=0
141
+
142
+ for base in "${bases[@]}"; do
143
+ [[ -z "$base" ]] && continue
144
+
145
+ copy_env_log "DEBUG" "Checking location '$trimmed' in base '$base'"
146
+
147
+ if [[ "$trimmed" == "/" ]]; then
148
+ local found_root=0
149
+ for env_file in "$base"/.env*; do
150
+ [[ -f "$env_file" ]] || continue
151
+ mkdir -p "$target_root"
152
+ local err_msg
153
+ err_msg="$(cp "$env_file" "$target_root/$(basename "$env_file")" 2>&1)"
154
+ if [[ $? -eq 0 ]]; then
155
+ (( overall_copied++ ))
156
+ location_copied=1
157
+ found_root=1
158
+ (( quiet != 1 )) && echo " ✅ Copied $(basename "$env_file") from $base/"
159
+ copy_env_log "INFO" "Copied $(basename "$env_file") from $base/"
160
+ else
161
+ (( overall_failed++ ))
162
+ (( location_failed++ ))
163
+ (( quiet != 1 )) && echo " ❌ Failed to copy $(basename "$env_file") from $base/"
164
+ copy_env_log "ERROR" "Failed to copy $(basename "$env_file") from $base/: ${err_msg:-unknown error}"
165
+ fi
166
+ done
167
+ if [[ $found_root -eq 1 ]]; then
168
+ break
169
+ fi
170
+ else
171
+ local source_path="$base/$rel"
172
+ if [[ -d "$source_path" ]]; then
173
+ local dest_dir="$target_root/$rel"
174
+ mkdir -p "$dest_dir"
175
+ local found_any=0
176
+ for env_file in "$source_path"/.env*; do
177
+ [[ -f "$env_file" ]] || continue
178
+ local err_msg
179
+ err_msg="$(cp "$env_file" "$dest_dir/$(basename "$env_file")" 2>&1)"
180
+ if [[ $? -eq 0 ]]; then
181
+ (( overall_copied++ ))
182
+ location_copied=1
183
+ found_any=1
184
+ (( quiet != 1 )) && echo " ✅ Copied $(basename "$env_file") from $rel/"
185
+ copy_env_log "INFO" "Copied $(basename "$env_file") from $rel/"
186
+ else
187
+ (( overall_failed++ ))
188
+ (( location_failed++ ))
189
+ (( quiet != 1 )) && echo " ❌ Failed to copy $(basename "$env_file") from $rel/"
190
+ copy_env_log "ERROR" "Failed to copy $(basename "$env_file") from $rel/: ${err_msg:-unknown error}"
191
+ fi
192
+ done
193
+ if [[ $found_any -eq 1 ]]; then
194
+ break
195
+ fi
196
+ elif [[ -f "$source_path" ]]; then
197
+ local dest_dir
198
+ dest_dir="$(dirname "$rel")"
199
+ if [[ "$dest_dir" != "." ]]; then
200
+ mkdir -p "$target_root/$dest_dir"
201
+ else
202
+ mkdir -p "$target_root"
203
+ fi
204
+ local err_msg
205
+ err_msg="$(cp "$source_path" "$target_root/$rel" 2>&1)"
206
+ if [[ $? -eq 0 ]]; then
207
+ (( overall_copied++ ))
208
+ location_copied=1
209
+ (( quiet != 1 )) && echo " ✅ Copied $rel"
210
+ copy_env_log "INFO" "Copied file $rel"
211
+ else
212
+ (( overall_failed++ ))
213
+ (( location_failed++ ))
214
+ (( quiet != 1 )) && echo " ❌ Failed to copy $rel"
215
+ copy_env_log "ERROR" "Failed to copy file $rel: ${err_msg:-unknown error}"
216
+ fi
217
+ break
218
+ fi
219
+ fi
220
+ done
221
+
222
+ if [[ $location_copied -eq 0 ]]; then
223
+ if [[ "$trimmed" == "/" ]]; then
224
+ (( quiet != 1 )) && echo " ⚠️ No .env files found in any root"
225
+ copy_env_log "WARN" "No .env files discovered for '/'"
226
+ else
227
+ (( quiet != 1 )) && echo " ⚠️ No .env files found for $trimmed"
228
+ copy_env_log "WARN" "No .env files found for '$trimmed'"
229
+ fi
230
+ fi
231
+ done
232
+
233
+ COPY_ENV_LAST_COPIED=$overall_copied
234
+
235
+ if [[ $overall_copied -eq 0 ]]; then
236
+ copy_env_log "WARN" "Completed with no files copied"
237
+ (( quiet != 1 )) && echo " ⚠️ No environment files copied."
238
+ else
239
+ copy_env_log "INFO" "Completed: $overall_copied file(s) copied, failures=$overall_failed"
240
+ (( quiet != 1 )) && echo " ✅ Environment files copied ($overall_copied)."
241
+ fi
242
+
243
+ return 0
244
+ }