jbai-cli 2.1.0 → 2.1.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.
- package/README.md +34 -38
- package/bin/jbai-claude.js +3 -17
- package/bin/jbai-codex-5.4.js +6 -0
- package/bin/jbai-codex.js +13 -17
- package/bin/jbai-continue.js +3 -17
- package/bin/jbai-council.js +1 -1
- package/bin/jbai-gemini.js +3 -17
- package/bin/jbai-goose.js +3 -18
- package/bin/jbai-opencode.js +6 -51
- package/bin/jbai-proxy.js +27 -5
- package/bin/jbai.js +315 -121
- package/lib/completions.js +5 -8
- package/lib/config.js +15 -92
- package/lib/model-list.js +2 -2
- package/lib/postinstall.js +0 -23
- package/package.json +3 -4
- package/lib/handoff.js +0 -152
- package/lib/interactive-handoff.js +0 -220
package/bin/jbai.js
CHANGED
|
@@ -7,7 +7,6 @@ const fs = require('fs');
|
|
|
7
7
|
const path = require('path');
|
|
8
8
|
const os = require('os');
|
|
9
9
|
const config = require('../lib/config');
|
|
10
|
-
const { createHandoff } = require('../lib/handoff');
|
|
11
10
|
const { getGroupsForTool, showModelsForTool } = require('../lib/model-list');
|
|
12
11
|
const completions = require('../lib/completions');
|
|
13
12
|
|
|
@@ -50,18 +49,31 @@ const TOOLS = {
|
|
|
50
49
|
}
|
|
51
50
|
};
|
|
52
51
|
|
|
52
|
+
const MENU_WRAPPERS = {
|
|
53
|
+
claude: 'jbai-claude.js',
|
|
54
|
+
codex: 'jbai-codex.js',
|
|
55
|
+
opencode: 'jbai-opencode.js',
|
|
56
|
+
gemini: 'jbai-gemini.js',
|
|
57
|
+
goose: 'jbai-goose.js',
|
|
58
|
+
continue: 'jbai-continue.js',
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const CLI_PACKAGE = 'jbai-cli';
|
|
62
|
+
const NPM_BIN = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
63
|
+
|
|
53
64
|
const VERSION = require('../package.json').version;
|
|
54
65
|
|
|
55
66
|
const HELP = `
|
|
56
67
|
jbai-cli v${VERSION} - JetBrains AI Platform CLI Tools
|
|
57
68
|
|
|
69
|
+
Launch 'jbai' with no arguments to open the interactive terminal control panel.
|
|
70
|
+
|
|
58
71
|
COMMANDS:
|
|
59
72
|
jbai token Show token status
|
|
60
73
|
jbai token set Set token interactively
|
|
61
74
|
jbai token refresh Auto-refresh token via API
|
|
62
75
|
jbai token refresh <token> Set new token (saves to ~/.jbai/token + ~/.zshrc)
|
|
63
76
|
jbai test Test API endpoints (incl. Codex /responses)
|
|
64
|
-
jbai handoff Continue task in Orca Lab
|
|
65
77
|
jbai env [staging|production] Switch environment
|
|
66
78
|
jbai models [tool] List Grazie models (all|claude|codex|gemini|opencode|goose|continue)
|
|
67
79
|
jbai install Install all AI tools (claude, codex, gemini, opencode, goose, continue)
|
|
@@ -70,6 +82,7 @@ COMMANDS:
|
|
|
70
82
|
jbai completions Print zsh completions to stdout
|
|
71
83
|
jbai completions --install Add completions to ~/.zshrc
|
|
72
84
|
jbai completions --bash Print bash completions
|
|
85
|
+
jbai menu Open interactive control panel
|
|
73
86
|
jbai help Show this help
|
|
74
87
|
|
|
75
88
|
PROXY (for Codex Desktop, Cursor, etc.):
|
|
@@ -88,6 +101,7 @@ TOOL WRAPPERS:
|
|
|
88
101
|
MODEL SHORTCUTS (super mode by default):
|
|
89
102
|
jbai-claude-opus Claude Code + Opus 4.6
|
|
90
103
|
jbai-claude-sonnet Claude Code + Sonnet 4.6
|
|
104
|
+
jbai-codex-5.4 Codex + GPT-5.4
|
|
91
105
|
jbai-codex-5.3 Codex + GPT-5.3
|
|
92
106
|
jbai-codex-5.2 Codex + GPT-5.2
|
|
93
107
|
jbai-codex-rockhopper Codex + Rockhopper Alpha (OpenAI EAP)
|
|
@@ -112,7 +126,6 @@ EXAMPLES:
|
|
|
112
126
|
jbai-gemini-supernova # Gemini with Supernova (super mode)
|
|
113
127
|
jbai-council # Launch all 3 agents in tmux
|
|
114
128
|
jbai-council --super # All agents in super mode
|
|
115
|
-
jbai handoff --task "fix lint" # Handoff task to Orca Lab
|
|
116
129
|
|
|
117
130
|
TOKEN:
|
|
118
131
|
Get token: ${config.getEndpoints().tokenUrl}
|
|
@@ -524,139 +537,318 @@ async function installTools(toolKey) {
|
|
|
524
537
|
console.log('Run: jbai doctor to verify');
|
|
525
538
|
}
|
|
526
539
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
Options:
|
|
535
|
-
--task, -t Task description (or pass as positional)
|
|
536
|
-
--repo, -r Git repo URL (defaults to origin remote)
|
|
537
|
-
--ref Git ref (defaults to current branch)
|
|
538
|
-
--branch, -b Working branch name for the agent
|
|
539
|
-
--model, -m Claude model (default: ${config.MODELS.claude.default})
|
|
540
|
-
--grazie-env, -e STAGING | PREPROD | PRODUCTION
|
|
541
|
-
--grazie-token Override Grazie token (default: ~/.jbai/token)
|
|
542
|
-
--git-token, -g GitHub token (default: GITHUB_TOKEN/GH_TOKEN)
|
|
543
|
-
--facade-token, -f Facade JWT token (default: FACADE_JWT_TOKEN)
|
|
544
|
-
--orca-url, -o Orca Lab URL (default: http://localhost:3000)
|
|
545
|
-
--no-open Do not open the Orca Lab URL
|
|
546
|
-
--no-auto-start Do not auto-start the agent task
|
|
547
|
-
--help Show this help
|
|
548
|
-
`;
|
|
540
|
+
function ask(question) {
|
|
541
|
+
return new Promise((resolve) => {
|
|
542
|
+
const rl = readline.createInterface({
|
|
543
|
+
input: process.stdin,
|
|
544
|
+
output: process.stdout
|
|
545
|
+
});
|
|
549
546
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
547
|
+
rl.question(question, (answer) => {
|
|
548
|
+
rl.close();
|
|
549
|
+
resolve((answer || '').trim());
|
|
550
|
+
});
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
function waitForEnter() {
|
|
555
|
+
return ask('\nPress Enter to continue...');
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
function runNodeScript(scriptName, args = []) {
|
|
559
|
+
return new Promise((resolve) => {
|
|
560
|
+
const scriptPath = path.join(__dirname, scriptName);
|
|
561
|
+
const child = spawn(process.execPath, [scriptPath, ...args], {
|
|
562
|
+
stdio: 'inherit'
|
|
563
|
+
});
|
|
564
564
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
565
|
+
child.on('close', (code) => resolve(code || 0));
|
|
566
|
+
child.on('error', (error) => {
|
|
567
|
+
console.error(`Unable to run ${scriptName}: ${error.message}`);
|
|
568
|
+
resolve(1);
|
|
569
|
+
});
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
function runCommand(command, args = []) {
|
|
574
|
+
return new Promise((resolve) => {
|
|
575
|
+
const child = spawn(command, args, {
|
|
576
|
+
stdio: 'inherit',
|
|
577
|
+
shell: false
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
child.on('close', (code) => resolve(code || 0));
|
|
581
|
+
child.on('error', (error) => {
|
|
582
|
+
console.error(`Command failed: ${command} ${args.join(' ')}`);
|
|
583
|
+
console.error(error.message);
|
|
584
|
+
resolve(1);
|
|
585
|
+
});
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
async function launchAgent(tool) {
|
|
590
|
+
const script = MENU_WRAPPERS[tool];
|
|
591
|
+
if (!script) {
|
|
592
|
+
console.log(`Unsupported agent: ${tool}`);
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (!isToolInstalled(tool)) {
|
|
597
|
+
console.log(`❌ ${TOOLS[tool].name} is not installed.`);
|
|
598
|
+
const installNow = (await ask(`Install ${TOOLS[tool].name} now? [y/N]: `)).toLowerCase() === 'y';
|
|
599
|
+
if (!installNow) {
|
|
600
|
+
return;
|
|
570
601
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
602
|
+
|
|
603
|
+
await installTools(tool);
|
|
604
|
+
if (!isToolInstalled(tool)) {
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
await runNodeScript(script);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
async function setupClients() {
|
|
613
|
+
const installed = Object.keys(TOOLS).filter(isToolInstalled);
|
|
614
|
+
if (installed.length === 0) {
|
|
615
|
+
console.log('No tools installed yet. Install a tool first, then wire it up.');
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
const code = await runNodeScript('jbai-proxy.js', ['setup']);
|
|
620
|
+
if (code !== 0) {
|
|
621
|
+
console.log('Client setup reported issues. Fix the errors above and try again.');
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
console.log('\nClient wiring complete.');
|
|
626
|
+
console.log('- Codex Desktop: config.toml updated');
|
|
627
|
+
console.log('- Shell env: JBAI_PROXY_KEY added');
|
|
628
|
+
console.log('- Proxy: started + launch settings configured');
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
async function updateCli() {
|
|
632
|
+
const confirm = (await ask('Update jbai-cli to latest from npm? [Y/n]: ')).toLowerCase();
|
|
633
|
+
if (confirm && confirm !== 'y' && confirm !== '') {
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
const code = await runCommand(NPM_BIN, ['install', '-g', `${CLI_PACKAGE}@latest`]);
|
|
638
|
+
if (code === 0) {
|
|
639
|
+
console.log('✅ Update completed. Restart terminal to load updated binary.');
|
|
640
|
+
} else {
|
|
641
|
+
console.log('❌ Update failed. Check npm output and try again.');
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
async function uninstallCli() {
|
|
646
|
+
const confirm = (await ask(`This will uninstall ${CLI_PACKAGE} and close this app. Continue? [y/N]: `)).toLowerCase();
|
|
647
|
+
if (confirm !== 'y') {
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
const code = await runCommand(NPM_BIN, ['uninstall', '-g', CLI_PACKAGE]);
|
|
652
|
+
if (code === 0) {
|
|
653
|
+
console.log('✅ jbai-cli removed.');
|
|
654
|
+
process.exit(0);
|
|
655
|
+
}
|
|
656
|
+
console.log('❌ Uninstall failed. Check npm output and try again.');
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
function environmentLabel() {
|
|
660
|
+
return config.getEnvironment() === 'production' ? 'PRODUCTION' : 'STAGING';
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
async function runTokenMenu() {
|
|
664
|
+
while (true) {
|
|
665
|
+
const action = (await ask(`\nToken Management\n1) Show status\n2) Set token\n3) Refresh token\n0) Back\n\nSelect: `)).toLowerCase();
|
|
666
|
+
|
|
667
|
+
if (action === '0' || action === 'b' || action === 'back') {
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
if (action === '1') {
|
|
672
|
+
showTokenStatus();
|
|
673
|
+
await waitForEnter();
|
|
588
674
|
continue;
|
|
589
675
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
676
|
+
|
|
677
|
+
if (action === '2') {
|
|
678
|
+
await setToken();
|
|
679
|
+
await waitForEnter();
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
if (action === '3') {
|
|
684
|
+
await refreshTokenCommand();
|
|
685
|
+
await waitForEnter();
|
|
686
|
+
continue;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
console.log('Invalid selection.');
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
async function runSettingsMenu() {
|
|
694
|
+
while (true) {
|
|
695
|
+
const action = (await ask(`\nSettings\n1) Show environment (${environmentLabel()})\n2) Switch to staging\n3) Switch to production\n0) Back\n\nSelect: `)).toLowerCase();
|
|
696
|
+
|
|
697
|
+
if (action === '0' || action === 'b' || action === 'back') {
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
if (action === '1') {
|
|
702
|
+
console.log(`Current environment: ${environmentLabel()}`);
|
|
703
|
+
console.log(`Token URL: ${config.getEndpoints().tokenUrl}`);
|
|
704
|
+
await waitForEnter();
|
|
705
|
+
continue;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
if (action === '2') {
|
|
709
|
+
setEnvironment('staging');
|
|
710
|
+
await waitForEnter();
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
if (action === '3') {
|
|
715
|
+
setEnvironment('production');
|
|
716
|
+
await waitForEnter();
|
|
604
717
|
continue;
|
|
605
718
|
}
|
|
606
|
-
|
|
719
|
+
|
|
720
|
+
console.log('Invalid selection.');
|
|
607
721
|
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
async function runAgentMenu() {
|
|
725
|
+
const action = (await ask(`\nStart Agent\n1) Claude\n2) Codex\n3) OpenCode\n4) Gemini\n5) Goose\n6) Continue\n0) Back\n\nSelect: `)).toLowerCase();
|
|
726
|
+
|
|
727
|
+
const map = {
|
|
728
|
+
'1': 'claude',
|
|
729
|
+
'2': 'codex',
|
|
730
|
+
'3': 'opencode',
|
|
731
|
+
'4': 'gemini',
|
|
732
|
+
'5': 'goose',
|
|
733
|
+
'6': 'continue'
|
|
734
|
+
};
|
|
608
735
|
|
|
609
|
-
|
|
736
|
+
if (action === '0' || action === 'b' || action === 'back') {
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
const tool = map[action];
|
|
741
|
+
if (!tool) {
|
|
742
|
+
console.log('Invalid selection.');
|
|
743
|
+
await waitForEnter();
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
console.log(`\nStarting ${TOOLS[tool].name}...\n`);
|
|
748
|
+
await launchAgent(tool);
|
|
610
749
|
}
|
|
611
750
|
|
|
612
|
-
function
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
751
|
+
async function runInstallMenu() {
|
|
752
|
+
const missing = Object.entries(TOOLS).filter(([key]) => !isToolInstalled(key));
|
|
753
|
+
if (missing.length === 0) {
|
|
754
|
+
console.log('✅ All agents are already installed.');
|
|
755
|
+
await waitForEnter();
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
const choices = [];
|
|
760
|
+
missing.forEach(([key], index) => {
|
|
761
|
+
choices.push(`${index + 1}) ${TOOLS[key].name}`);
|
|
619
762
|
});
|
|
620
|
-
}
|
|
621
763
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
if (
|
|
625
|
-
console.log(HANDOFF_HELP);
|
|
764
|
+
const action = (await ask(`\nInstall Agents\n${choices.join('\n')}\nA) Install all missing\n0) Back\n\nSelect: `)).toLowerCase();
|
|
765
|
+
|
|
766
|
+
if (action === '0' || action === 'b' || action === 'back') {
|
|
626
767
|
return;
|
|
627
768
|
}
|
|
628
769
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
770
|
+
if (action === 'a') {
|
|
771
|
+
await installTools();
|
|
772
|
+
await waitForEnter();
|
|
773
|
+
return;
|
|
632
774
|
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
775
|
+
|
|
776
|
+
const index = parseInt(action, 10);
|
|
777
|
+
if (!Number.isInteger(index) || index < 1 || index > missing.length) {
|
|
778
|
+
console.log('Invalid selection.');
|
|
779
|
+
return;
|
|
636
780
|
}
|
|
637
781
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
782
|
+
const tool = missing[index - 1][0];
|
|
783
|
+
await installTools(tool);
|
|
784
|
+
await waitForEnter();
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
async function runStandaloneMenu() {
|
|
788
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
789
|
+
console.log('Interactive mode requires a TTY terminal. Run: jbai help');
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
while (true) {
|
|
794
|
+
const action = (await ask(`\n┌─ jbai control panel\n│1) Token management\n│2) Settings (environment)\n│3) Install agents\n│4) Wire configured clients\n│5) Doctor (health + install status)\n│6) Start agent chat\n│7) Update jbai-cli\n│8) Uninstall jbai-cli\n│9) Version\n│0) Exit\n└─ Select: `)).toLowerCase();
|
|
795
|
+
|
|
796
|
+
if (action === '0' || action === 'q' || action === 'exit') {
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
if (action === '1') {
|
|
801
|
+
await runTokenMenu();
|
|
802
|
+
continue;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
if (action === '2') {
|
|
806
|
+
await runSettingsMenu();
|
|
807
|
+
continue;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
if (action === '3') {
|
|
811
|
+
await runInstallMenu();
|
|
812
|
+
continue;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
if (action === '4') {
|
|
816
|
+
await setupClients();
|
|
817
|
+
await waitForEnter();
|
|
818
|
+
continue;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
if (action === '5') {
|
|
822
|
+
doctor();
|
|
823
|
+
await waitForEnter();
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
if (action === '6') {
|
|
828
|
+
await runAgentMenu();
|
|
829
|
+
continue;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
if (action === '7') {
|
|
833
|
+
await updateCli();
|
|
834
|
+
await waitForEnter();
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
if (action === '8') {
|
|
839
|
+
await uninstallCli();
|
|
840
|
+
continue;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
if (action === '9') {
|
|
844
|
+
console.log(`jbai-cli v${VERSION}`);
|
|
845
|
+
console.log(`Node: ${process.version}`);
|
|
846
|
+
console.log(`Environment: ${environmentLabel()}`);
|
|
847
|
+
await waitForEnter();
|
|
848
|
+
continue;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
console.log('Invalid selection.');
|
|
660
852
|
}
|
|
661
853
|
}
|
|
662
854
|
|
|
@@ -676,9 +868,6 @@ switch (command) {
|
|
|
676
868
|
case 'test':
|
|
677
869
|
testEndpoints();
|
|
678
870
|
break;
|
|
679
|
-
case 'handoff':
|
|
680
|
-
handoffToOrca(args);
|
|
681
|
-
break;
|
|
682
871
|
case 'models':
|
|
683
872
|
if (args[0]) {
|
|
684
873
|
const allowed = new Set(['all', 'claude', 'codex', 'gemini', 'opencode', 'goose', 'continue']);
|
|
@@ -712,9 +901,14 @@ switch (command) {
|
|
|
712
901
|
case 'help':
|
|
713
902
|
case '--help':
|
|
714
903
|
case '-h':
|
|
715
|
-
case undefined:
|
|
716
904
|
console.log(HELP);
|
|
717
905
|
break;
|
|
906
|
+
case 'menu':
|
|
907
|
+
runStandaloneMenu();
|
|
908
|
+
break;
|
|
909
|
+
case undefined:
|
|
910
|
+
runStandaloneMenu();
|
|
911
|
+
break;
|
|
718
912
|
case 'version':
|
|
719
913
|
case '--version':
|
|
720
914
|
case '-v':
|
package/lib/completions.js
CHANGED
|
@@ -15,12 +15,9 @@ const config = require('./config');
|
|
|
15
15
|
const pkg = require('../package.json');
|
|
16
16
|
const ALL_BINS = Object.keys(pkg.bin).sort();
|
|
17
17
|
|
|
18
|
-
// Shortcuts = bins that have a dash after the tool name (jbai-codex-5.3, etc.)
|
|
19
|
-
const TOOLS = ['claude', 'codex', 'gemini', 'opencode', 'goose', 'continue', 'council', 'proxy'];
|
|
20
|
-
|
|
21
18
|
// jbai subcommands
|
|
22
19
|
const JBAI_SUBCOMMANDS = [
|
|
23
|
-
'
|
|
20
|
+
'menu', 'token', 'test', 'env', 'models', 'install', 'doctor',
|
|
24
21
|
'status', 'proxy', 'help', 'version', 'completions',
|
|
25
22
|
];
|
|
26
23
|
|
|
@@ -51,7 +48,7 @@ function generateZsh() {
|
|
|
51
48
|
shortcutDescriptions[bin] = bin;
|
|
52
49
|
}
|
|
53
50
|
|
|
54
|
-
return `#compdef jbai jbai-claude jbai-codex jbai-gemini jbai-opencode jbai-goose jbai-continue jbai-council jbai-proxy jbai-claude-opus jbai-claude-sonnet jbai-codex-5.2 jbai-codex-5.3 jbai-codex-rockhopper jbai-gemini-3.1 jbai-gemini-supernova jbai-opencode-rockhopper jbai-opencode-grok jbai-opencode-deepseek
|
|
51
|
+
return `#compdef jbai jbai-claude jbai-codex jbai-gemini jbai-opencode jbai-goose jbai-continue jbai-council jbai-proxy jbai-claude-opus jbai-claude-sonnet jbai-codex-5.2 jbai-codex-5.3 jbai-codex-5.4 jbai-codex-rockhopper jbai-gemini-3.1 jbai-gemini-supernova jbai-opencode-rockhopper jbai-opencode-grok jbai-opencode-deepseek
|
|
55
52
|
# ─── jbai-cli zsh completions (auto-generated) ───
|
|
56
53
|
|
|
57
54
|
# Complete model names after --model flag
|
|
@@ -65,9 +62,9 @@ ${UNIQUE_MODELS.map(m => ` '${m}'`).join('\n')}
|
|
|
65
62
|
# Main jbai command completions
|
|
66
63
|
_jbai() {
|
|
67
64
|
local -a subcommands=(
|
|
65
|
+
'menu:Open interactive control panel'
|
|
68
66
|
'token:Show or manage authentication token'
|
|
69
67
|
'test:Test API endpoints'
|
|
70
|
-
'handoff:Continue task in Orca Lab'
|
|
71
68
|
'env:Switch environment (staging/production)'
|
|
72
69
|
'models:List available models'
|
|
73
70
|
'install:Install AI tools'
|
|
@@ -137,7 +134,7 @@ _jbai_tool_wrapper() {
|
|
|
137
134
|
compdef _jbai jbai
|
|
138
135
|
compdef _jbai_tool_wrapper jbai-claude jbai-codex jbai-gemini jbai-opencode jbai-goose jbai-continue
|
|
139
136
|
compdef _jbai_tool_wrapper jbai-claude-opus jbai-claude-sonnet
|
|
140
|
-
compdef _jbai_tool_wrapper jbai-codex-5.2 jbai-codex-5.3 jbai-codex-rockhopper
|
|
137
|
+
compdef _jbai_tool_wrapper jbai-codex-5.2 jbai-codex-5.3 jbai-codex-5.4 jbai-codex-rockhopper
|
|
141
138
|
compdef _jbai_tool_wrapper jbai-gemini-3.1 jbai-gemini-supernova
|
|
142
139
|
compdef _jbai_tool_wrapper jbai-opencode-rockhopper jbai-opencode-grok jbai-opencode-deepseek
|
|
143
140
|
`;
|
|
@@ -205,7 +202,7 @@ _jbai_tool_completions() {
|
|
|
205
202
|
complete -F _jbai_completions jbai
|
|
206
203
|
complete -F _jbai_tool_completions jbai-claude jbai-codex jbai-gemini jbai-opencode jbai-goose jbai-continue
|
|
207
204
|
complete -F _jbai_tool_completions jbai-claude-opus jbai-claude-sonnet
|
|
208
|
-
complete -F _jbai_tool_completions jbai-codex-5.2 jbai-codex-5.3 jbai-codex-rockhopper
|
|
205
|
+
complete -F _jbai_tool_completions jbai-codex-5.2 jbai-codex-5.3 jbai-codex-5.4 jbai-codex-rockhopper
|
|
209
206
|
complete -F _jbai_tool_completions jbai-gemini-3.1 jbai-gemini-supernova
|
|
210
207
|
complete -F _jbai_tool_completions jbai-opencode-rockhopper jbai-opencode-grok jbai-opencode-deepseek
|
|
211
208
|
`;
|