@_xtribe/cli 2.2.51 → 2.2.55
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-tribe.js +119 -9
- package/package.json +1 -1
- package/tribe-deployment.yaml +143 -0
package/install-tribe.js
CHANGED
|
@@ -219,6 +219,98 @@ async function setupPathQuiet() {
|
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
+
async function autoEnableTelemetry() {
|
|
223
|
+
const homeDir = os.homedir();
|
|
224
|
+
const tribeBin = path.join(homeDir, '.tribe', 'bin', 'tribe');
|
|
225
|
+
const tutorCollector = path.join(homeDir, '.tribe', 'bin', 'tutor-collector');
|
|
226
|
+
|
|
227
|
+
// Check if binaries exist
|
|
228
|
+
if (!fs.existsSync(tribeBin) || !fs.existsSync(tutorCollector)) {
|
|
229
|
+
return; // Binaries not installed yet
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// On macOS, create launchd agent for auto-start on boot
|
|
233
|
+
if (process.platform === 'darwin') {
|
|
234
|
+
const launchAgentsDir = path.join(homeDir, 'Library', 'LaunchAgents');
|
|
235
|
+
const logsDir = path.join(homeDir, '.tribe', 'logs');
|
|
236
|
+
const plistPath = path.join(launchAgentsDir, 'ai.tribe.tutor-collector.plist');
|
|
237
|
+
|
|
238
|
+
// Ensure directories exist
|
|
239
|
+
fs.mkdirSync(launchAgentsDir, { recursive: true });
|
|
240
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
241
|
+
|
|
242
|
+
const serverURL = process.env.TRIBE_TUTOR_SERVER_URL || 'https://tutor.tribecode.ai';
|
|
243
|
+
|
|
244
|
+
const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
245
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
246
|
+
<plist version="1.0">
|
|
247
|
+
<dict>
|
|
248
|
+
<key>Label</key>
|
|
249
|
+
<string>ai.tribe.tutor-collector</string>
|
|
250
|
+
<key>ProgramArguments</key>
|
|
251
|
+
<array>
|
|
252
|
+
<string>${tutorCollector}</string>
|
|
253
|
+
<string>-server</string>
|
|
254
|
+
<string>${serverURL}</string>
|
|
255
|
+
<string>-interval</string>
|
|
256
|
+
<string>10s</string>
|
|
257
|
+
<string>-buffer</string>
|
|
258
|
+
<string>50</string>
|
|
259
|
+
</array>
|
|
260
|
+
<key>RunAtLoad</key>
|
|
261
|
+
<true/>
|
|
262
|
+
<key>KeepAlive</key>
|
|
263
|
+
<dict>
|
|
264
|
+
<key>SuccessfulExit</key>
|
|
265
|
+
<false/>
|
|
266
|
+
</dict>
|
|
267
|
+
<key>StandardOutPath</key>
|
|
268
|
+
<string>${logsDir}/tutor-collector.log</string>
|
|
269
|
+
<key>StandardErrorPath</key>
|
|
270
|
+
<string>${logsDir}/tutor-collector.error.log</string>
|
|
271
|
+
<key>WorkingDirectory</key>
|
|
272
|
+
<string>${homeDir}</string>
|
|
273
|
+
<key>EnvironmentVariables</key>
|
|
274
|
+
<dict>
|
|
275
|
+
<key>HOME</key>
|
|
276
|
+
<string>${homeDir}</string>
|
|
277
|
+
<key>PATH</key>
|
|
278
|
+
<string>/usr/local/bin:/usr/bin:/bin:${homeDir}/.tribe/bin</string>
|
|
279
|
+
</dict>
|
|
280
|
+
</dict>
|
|
281
|
+
</plist>
|
|
282
|
+
`;
|
|
283
|
+
|
|
284
|
+
// Unload old agents first
|
|
285
|
+
for (const oldLabel of ['ai.tribe.tutor', 'ai.tribecode.tutor', 'ai.tribe.tutor-collector']) {
|
|
286
|
+
try {
|
|
287
|
+
execSync(`launchctl unload "${path.join(launchAgentsDir, oldLabel + '.plist')}"`, { stdio: 'ignore' });
|
|
288
|
+
} catch {
|
|
289
|
+
// Ignore errors
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Write and load new plist
|
|
294
|
+
fs.writeFileSync(plistPath, plistContent);
|
|
295
|
+
try {
|
|
296
|
+
execSync(`launchctl load "${plistPath}"`, { stdio: 'ignore' });
|
|
297
|
+
} catch {
|
|
298
|
+
// If launchctl fails, try starting directly
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Also try to start via tribe enable for immediate startup
|
|
303
|
+
try {
|
|
304
|
+
execSync(`"${tribeBin}" enable`, {
|
|
305
|
+
stdio: 'ignore',
|
|
306
|
+
timeout: 10000,
|
|
307
|
+
env: { ...process.env, HOME: homeDir }
|
|
308
|
+
});
|
|
309
|
+
} catch {
|
|
310
|
+
// Ignore - launchd will handle it on next boot
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
222
314
|
async function main() {
|
|
223
315
|
const args = process.argv.slice(2);
|
|
224
316
|
|
|
@@ -256,22 +348,40 @@ async function main() {
|
|
|
256
348
|
// Silently ignore update failures
|
|
257
349
|
});
|
|
258
350
|
|
|
351
|
+
// Auto-enable telemetry collection (critical for data gathering)
|
|
352
|
+
try {
|
|
353
|
+
await autoEnableTelemetry();
|
|
354
|
+
} catch (error) {
|
|
355
|
+
// Log but don't fail installation
|
|
356
|
+
console.warn(chalk.dim('Note: Run "tribe enable" to start telemetry'));
|
|
357
|
+
}
|
|
358
|
+
|
|
259
359
|
spinner.succeed('Ready!');
|
|
260
360
|
|
|
261
|
-
//
|
|
361
|
+
// Check if ~/.tribe/bin is already in the user's actual PATH
|
|
362
|
+
// Note: 'which tribe' may work in subprocess even when parent shell doesn't have it
|
|
363
|
+
const userPath = process.env.PATH || '';
|
|
364
|
+
const tribeBinInPath = userPath.includes('.tribe/bin');
|
|
365
|
+
|
|
366
|
+
// Also verify the binary actually exists and is executable
|
|
262
367
|
let commandWorks = false;
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
368
|
+
if (tribeBinInPath) {
|
|
369
|
+
try {
|
|
370
|
+
execSync('which tribe', { stdio: 'ignore', timeout: 2000 });
|
|
371
|
+
commandWorks = true;
|
|
372
|
+
} catch (error) {
|
|
373
|
+
commandWorks = false;
|
|
374
|
+
}
|
|
268
375
|
}
|
|
269
376
|
|
|
270
|
-
// Show
|
|
271
|
-
if (commandWorks) {
|
|
377
|
+
// Show completion message - always provide activation command for fresh installs
|
|
378
|
+
if (commandWorks && tribeBinInPath) {
|
|
272
379
|
console.log(chalk.green('\n✅ Ready! Type ' + chalk.cyan.bold('tribe') + ' to get started'));
|
|
273
380
|
} else {
|
|
274
|
-
|
|
381
|
+
// Provide explicit activation command since PATH isn't set up yet
|
|
382
|
+
console.log(chalk.yellow('\n📍 To activate TRIBE in this terminal:'));
|
|
383
|
+
console.log(chalk.cyan(' source ~/.tribe/tribe-env.sh'));
|
|
384
|
+
console.log(chalk.dim('\n Or restart your terminal, then type ') + chalk.cyan.bold('tribe'));
|
|
275
385
|
}
|
|
276
386
|
|
|
277
387
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@_xtribe/cli",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.55",
|
|
4
4
|
"description": "TRIBE - Privacy-first AI development analytics. Self-host your telemetry, skip authentication, or run completely offline. Your data stays on your machine.",
|
|
5
5
|
"main": "install-tribe.js",
|
|
6
6
|
"bin": {
|
package/tribe-deployment.yaml
CHANGED
|
@@ -457,6 +457,149 @@ spec:
|
|
|
457
457
|
name: claude-config
|
|
458
458
|
optional: true
|
|
459
459
|
---
|
|
460
|
+
# Gemini Worker Deployment
|
|
461
|
+
apiVersion: apps/v1
|
|
462
|
+
kind: Deployment
|
|
463
|
+
metadata:
|
|
464
|
+
name: gemini-worker-deployment
|
|
465
|
+
namespace: tribe-system
|
|
466
|
+
spec:
|
|
467
|
+
replicas: 1
|
|
468
|
+
selector:
|
|
469
|
+
matchLabels:
|
|
470
|
+
app: gemini-worker
|
|
471
|
+
template:
|
|
472
|
+
metadata:
|
|
473
|
+
labels:
|
|
474
|
+
app: gemini-worker
|
|
475
|
+
app.kubernetes.io/name: gemini-agent
|
|
476
|
+
spec:
|
|
477
|
+
containers:
|
|
478
|
+
- name: gemini-agent
|
|
479
|
+
image: tribexal/tribe:latest-gemini-agent
|
|
480
|
+
imagePullPolicy: IfNotPresent
|
|
481
|
+
ports:
|
|
482
|
+
- containerPort: 7781
|
|
483
|
+
name: ttyd
|
|
484
|
+
resources:
|
|
485
|
+
requests:
|
|
486
|
+
memory: "512Mi"
|
|
487
|
+
cpu: "500m"
|
|
488
|
+
limits:
|
|
489
|
+
memory: "2Gi"
|
|
490
|
+
cpu: "2"
|
|
491
|
+
env:
|
|
492
|
+
- name: AGENT_TYPE
|
|
493
|
+
value: "gemini"
|
|
494
|
+
- name: AGENT_CAPABILITIES
|
|
495
|
+
value: "gemini,api,code-review"
|
|
496
|
+
- name: ROLE
|
|
497
|
+
value: worker
|
|
498
|
+
- name: TASKMASTER_URL
|
|
499
|
+
value: http://taskmaster:8080
|
|
500
|
+
- name: GITEA_URL
|
|
501
|
+
value: http://gitea:3000
|
|
502
|
+
- name: GITEA_USER
|
|
503
|
+
value: gitea_admin
|
|
504
|
+
- name: GITEA_PASS
|
|
505
|
+
value: admin123
|
|
506
|
+
- name: GITEA_TOKEN
|
|
507
|
+
valueFrom:
|
|
508
|
+
secretKeyRef:
|
|
509
|
+
name: gitea-token
|
|
510
|
+
key: token
|
|
511
|
+
optional: true
|
|
512
|
+
- name: NAMESPACE
|
|
513
|
+
value: tribe-system
|
|
514
|
+
- name: GOOGLE_API_KEY
|
|
515
|
+
valueFrom:
|
|
516
|
+
secretKeyRef:
|
|
517
|
+
name: gemini-api-key
|
|
518
|
+
key: GOOGLE_API_KEY
|
|
519
|
+
optional: true
|
|
520
|
+
- name: GEMINI_MODEL
|
|
521
|
+
value: "gemini-2.0-flash-exp"
|
|
522
|
+
- name: GH_HOST
|
|
523
|
+
value: gitea:3000
|
|
524
|
+
- name: GH_ENTERPRISE_TOKEN
|
|
525
|
+
valueFrom:
|
|
526
|
+
secretKeyRef:
|
|
527
|
+
name: gitea-token
|
|
528
|
+
key: token
|
|
529
|
+
optional: true
|
|
530
|
+
volumeMounts:
|
|
531
|
+
- name: workspace
|
|
532
|
+
mountPath: /workspace
|
|
533
|
+
volumes:
|
|
534
|
+
- name: workspace
|
|
535
|
+
emptyDir: {}
|
|
536
|
+
---
|
|
537
|
+
# Gemini Review Agents
|
|
538
|
+
apiVersion: apps/v1
|
|
539
|
+
kind: Deployment
|
|
540
|
+
metadata:
|
|
541
|
+
name: gemini-review-agents
|
|
542
|
+
namespace: tribe-system
|
|
543
|
+
spec:
|
|
544
|
+
replicas: 0
|
|
545
|
+
selector:
|
|
546
|
+
matchLabels:
|
|
547
|
+
app: gemini-review-agent
|
|
548
|
+
worker-type: review
|
|
549
|
+
template:
|
|
550
|
+
metadata:
|
|
551
|
+
labels:
|
|
552
|
+
app: gemini-review-agent
|
|
553
|
+
worker-type: review
|
|
554
|
+
spec:
|
|
555
|
+
containers:
|
|
556
|
+
- name: gemini-agent
|
|
557
|
+
image: tribexal/tribe:latest-gemini-agent
|
|
558
|
+
imagePullPolicy: IfNotPresent
|
|
559
|
+
ports:
|
|
560
|
+
- containerPort: 7781
|
|
561
|
+
name: ttyd
|
|
562
|
+
resources:
|
|
563
|
+
requests:
|
|
564
|
+
memory: "512Mi"
|
|
565
|
+
cpu: "500m"
|
|
566
|
+
limits:
|
|
567
|
+
memory: "2Gi"
|
|
568
|
+
cpu: "2"
|
|
569
|
+
env:
|
|
570
|
+
- name: AGENT_TYPE
|
|
571
|
+
value: "gemini-reviewer"
|
|
572
|
+
- name: AGENT_CAPABILITIES
|
|
573
|
+
value: "gemini,code-review"
|
|
574
|
+
- name: ROLE
|
|
575
|
+
value: reviewer
|
|
576
|
+
- name: TASKMASTER_URL
|
|
577
|
+
value: http://taskmaster:8080
|
|
578
|
+
- name: GITEA_URL
|
|
579
|
+
value: http://gitea:3000
|
|
580
|
+
- name: GITEA_USER
|
|
581
|
+
value: gitea_admin
|
|
582
|
+
- name: GITEA_TOKEN
|
|
583
|
+
valueFrom:
|
|
584
|
+
secretKeyRef:
|
|
585
|
+
name: gitea-token
|
|
586
|
+
key: token
|
|
587
|
+
optional: true
|
|
588
|
+
- name: GOOGLE_API_KEY
|
|
589
|
+
valueFrom:
|
|
590
|
+
secretKeyRef:
|
|
591
|
+
name: gemini-api-key
|
|
592
|
+
key: GOOGLE_API_KEY
|
|
593
|
+
optional: true
|
|
594
|
+
- name: GEMINI_MODEL
|
|
595
|
+
value: "gemini-2.0-flash-exp"
|
|
596
|
+
volumeMounts:
|
|
597
|
+
- name: workspace
|
|
598
|
+
mountPath: /workspace
|
|
599
|
+
volumes:
|
|
600
|
+
- name: workspace
|
|
601
|
+
emptyDir: {}
|
|
602
|
+
---
|
|
460
603
|
# NodePort service for easy access
|
|
461
604
|
apiVersion: v1
|
|
462
605
|
kind: Service
|