@_xtribe/cli 1.0.5 → 1.0.7

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.
Files changed (2) hide show
  1. package/install-tribe.js +57 -21
  2. package/package.json +1 -1
package/install-tribe.js CHANGED
@@ -16,14 +16,12 @@ const platform = os.platform();
16
16
  const nodeArch = os.arch();
17
17
  const arch = nodeArch === 'x64' ? 'amd64' : (nodeArch === 'arm64' || nodeArch === 'aarch64' ? 'arm64' : nodeArch);
18
18
  const homeDir = os.homedir();
19
- const binDir = path.join(homeDir, 'bin');
20
19
  const tribeDir = path.join(homeDir, '.tribe');
21
20
  const tribeBinDir = path.join(tribeDir, 'bin');
21
+ // Use consistent directory for all binaries
22
+ const binDir = tribeBinDir;
22
23
 
23
- // Ensure local bin directory exists
24
- if (!fs.existsSync(binDir)) {
25
- fs.mkdirSync(binDir, { recursive: true });
26
- }
24
+ // No need to create ~/bin anymore since we're using ~/.tribe/bin
27
25
 
28
26
  // Ensure TRIBE config directory exists
29
27
  if (!fs.existsSync(tribeDir)) {
@@ -98,13 +96,26 @@ async function downloadFile(url, dest) {
98
96
 
99
97
  // Check if this might be a pointer file
100
98
  const stats = fs.statSync(dest);
101
- if (stats.size < 100) {
99
+ if (stats.size < 500) { // Increased size check - binaries are much larger
102
100
  const content = fs.readFileSync(dest, 'utf8').trim();
103
101
  // Check if content looks like a path (e.g., "main-121/tribe-linux-amd64")
104
- if (content.match(/^[\w\-\/]+$/) && content.includes('/')) {
105
- console.log(`📎 Following pointer to: ${content}`);
106
- const baseUrl = url.substring(0, url.lastIndexOf('/'));
107
- const actualBinaryUrl = `${baseUrl}/${content}`;
102
+ if (content.match(/^[\w\-\/]+$/) && !content.includes('<!DOCTYPE') && !content.includes('<html')) {
103
+ console.log(`📎 Detected pointer file, following to: ${content}`);
104
+ let actualBinaryUrl;
105
+
106
+ // Handle different pointer formats
107
+ if (content.startsWith('http')) {
108
+ // Direct URL
109
+ actualBinaryUrl = content;
110
+ } else if (content.includes('/')) {
111
+ // Relative path - construct full URL
112
+ const baseUrl = url.substring(0, url.lastIndexOf('/'));
113
+ actualBinaryUrl = `${baseUrl}/${content}`;
114
+ } else {
115
+ // Just a filename
116
+ const baseUrl = url.substring(0, url.lastIndexOf('/'));
117
+ actualBinaryUrl = `${baseUrl}/${content}`;
118
+ }
108
119
 
109
120
  // Download the actual binary
110
121
  fs.unlinkSync(dest); // Remove pointer file
@@ -564,6 +575,10 @@ async function installTribeCLI() {
564
575
  // Fallback to other methods if the API fails
565
576
  }
566
577
 
578
+ // Check if there's a local build available
579
+ const localBuildPath = path.join(__dirname, '..', '..', '..', 'sdk', 'cmd', 'cli-gui', 'tribe');
580
+ const hasLocalBuild = fs.existsSync(localBuildPath);
581
+
567
582
  const sources = isTestEnv ? [isTestEnv] : [
568
583
  downloadUrl,
569
584
  // Public releases repository (primary source)
@@ -572,6 +587,8 @@ async function installTribeCLI() {
572
587
  `https://github.com/${githubRepo}/releases/latest/download/tribe-${platform}-${arch}`,
573
588
  // Try jsDelivr CDN (for better availability)
574
589
  `https://cdn.jsdelivr.net/gh/${githubRepo}@main/cli/latest-tribe-${platform}-${arch}`,
590
+ // Local build if available
591
+ ...(hasLocalBuild ? [`file://${localBuildPath}`] : [])
575
592
  ].filter(Boolean); // Filter out empty downloadUrl if API failed
576
593
 
577
594
  let downloaded = false;
@@ -611,8 +628,15 @@ async function installTribeCLI() {
611
628
  spinner.text = `Found ${release.prerelease ? 'pre-release' : 'release'}: ${release.tag_name}`;
612
629
  }
613
630
 
614
- spinner.text = `Downloading TRIBE CLI from ${new URL(downloadUrl).hostname}...`;
615
- await downloadFile(downloadUrl, tribeDest);
631
+ if (downloadUrl.startsWith('file://')) {
632
+ // Handle local file copy
633
+ const sourcePath = downloadUrl.replace('file://', '');
634
+ spinner.text = `Copying TRIBE CLI from local build...`;
635
+ fs.copyFileSync(sourcePath, tribeDest);
636
+ } else {
637
+ spinner.text = `Downloading TRIBE CLI from ${new URL(downloadUrl).hostname}...`;
638
+ await downloadFile(downloadUrl, tribeDest);
639
+ }
616
640
 
617
641
  // Check if file is not empty
618
642
  const stats = fs.statSync(tribeDest);
@@ -624,10 +648,22 @@ async function installTribeCLI() {
624
648
 
625
649
  // Verify the binary works
626
650
  try {
651
+ // Try version command first
627
652
  execSync(`${tribeDest} version`, { stdio: 'ignore' });
628
653
  } catch (versionError) {
629
- // If version fails, still consider it downloaded if file is valid
630
- log.warning('Binary downloaded but version check failed - may need different architecture');
654
+ // If version command doesn't exist, try help to see if binary is valid
655
+ try {
656
+ const helpOutput = execSync(`${tribeDest} help`, { encoding: 'utf8' });
657
+ if (helpOutput.includes('TRIBE') || helpOutput.includes('tribe')) {
658
+ // Binary works, just doesn't have version command
659
+ log.info('Binary validated (version command not available)');
660
+ } else {
661
+ throw new Error('Binary validation failed');
662
+ }
663
+ } catch (helpError) {
664
+ // Binary might not be valid
665
+ log.warning('Binary downloaded but validation failed - may need different architecture');
666
+ }
631
667
  }
632
668
 
633
669
  spinner.succeed('TRIBE CLI installed successfully');
@@ -1210,14 +1246,15 @@ async function forceCleanInstallation() {
1210
1246
  // It might not be installed, which is fine
1211
1247
  }
1212
1248
 
1213
- // List of binaries to remove from ~/bin
1249
+ // Clean from old ~/bin location
1250
+ const oldBinDir = path.join(homeDir, 'bin');
1214
1251
  const binariesToRemove = ['tribe', 'kubectl', 'colima'];
1215
1252
 
1216
1253
  for (const binary of binariesToRemove) {
1217
- const binaryPath = path.join(binDir, binary);
1218
- if (fs.existsSync(binaryPath)) {
1254
+ const oldPath = path.join(oldBinDir, binary);
1255
+ if (fs.existsSync(oldPath)) {
1219
1256
  try {
1220
- fs.unlinkSync(binaryPath);
1257
+ fs.unlinkSync(oldPath);
1221
1258
  log.success(`Removed existing ${binary} binary from ~/bin`);
1222
1259
  } catch (error) {
1223
1260
  log.warning(`Could not remove ${binary}: ${error.message}`);
@@ -1225,9 +1262,8 @@ async function forceCleanInstallation() {
1225
1262
  }
1226
1263
  }
1227
1264
 
1228
- // Also clean from .tribe/bin
1229
- const tribeBinariesToRemove = ['tribe'];
1230
- for (const binary of tribeBinariesToRemove) {
1265
+ // Clean from ~/.tribe/bin
1266
+ for (const binary of binariesToRemove) {
1231
1267
  const binaryPath = path.join(tribeBinDir, binary);
1232
1268
  if (fs.existsSync(binaryPath)) {
1233
1269
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_xtribe/cli",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "TRIBE multi-agent development system - Zero to productive with one command",
5
5
  "main": "install-tribe.js",
6
6
  "bin": {