vibehacker 4.2.0 → 4.2.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/package.json +1 -1
- package/src/src/app.js +50 -5
- package/src/src/config.js +1 -1
- package/src/src/setup.js +41 -28
package/package.json
CHANGED
package/src/src/app.js
CHANGED
|
@@ -1711,24 +1711,69 @@ class HackerCLIApp {
|
|
|
1711
1711
|
this._menuOpen = true;
|
|
1712
1712
|
const sc = this.screen;
|
|
1713
1713
|
|
|
1714
|
-
const
|
|
1714
|
+
const W = Math.min(64, sc.width - 4);
|
|
1715
|
+
|
|
1716
|
+
const box = blessed.box({
|
|
1715
1717
|
parent: sc,
|
|
1716
1718
|
top: 'center', left: 'center',
|
|
1717
|
-
width:
|
|
1719
|
+
width: W, height: 7,
|
|
1718
1720
|
tags: true,
|
|
1719
1721
|
border: { type: 'line' },
|
|
1720
1722
|
label: ` {#00ff88-fg}{bold}Input{/bold}{/#00ff88-fg} `,
|
|
1721
1723
|
style: { fg: '#00ff88', bg: '#000a00', border: { fg: '#00aa44' } },
|
|
1724
|
+
padding: { left: 1, right: 1 },
|
|
1725
|
+
});
|
|
1726
|
+
|
|
1727
|
+
// Label text
|
|
1728
|
+
blessed.text({
|
|
1729
|
+
parent: box,
|
|
1730
|
+
top: 0, left: 0, right: 0, height: 1,
|
|
1731
|
+
tags: true,
|
|
1732
|
+
content: ` {#888888-fg}${label}{/#888888-fg}`,
|
|
1733
|
+
style: { bg: '#000a00' },
|
|
1722
1734
|
});
|
|
1723
1735
|
|
|
1724
|
-
|
|
1736
|
+
// Textarea input — immune to right-click cancel bug
|
|
1737
|
+
const input = blessed.textarea({
|
|
1738
|
+
parent: box,
|
|
1739
|
+
top: 2, left: 0, right: 0, height: 3,
|
|
1740
|
+
border: { type: 'line' },
|
|
1741
|
+
style: {
|
|
1742
|
+
fg: '#00ff88', bg: '#001100',
|
|
1743
|
+
border: { fg: '#003300' },
|
|
1744
|
+
focus: { border: { fg: '#00aa44' } },
|
|
1745
|
+
},
|
|
1746
|
+
inputOnFocus: true,
|
|
1747
|
+
mouse: true,
|
|
1748
|
+
keys: true,
|
|
1749
|
+
});
|
|
1750
|
+
|
|
1751
|
+
let done = false;
|
|
1752
|
+
const finish = (value) => {
|
|
1753
|
+
if (done) return;
|
|
1754
|
+
done = true;
|
|
1725
1755
|
this._menuOpen = false;
|
|
1726
|
-
|
|
1756
|
+
try { box.destroy(); } catch (_) {}
|
|
1727
1757
|
this.inputBox.focus();
|
|
1728
1758
|
sc.render();
|
|
1729
|
-
if (
|
|
1759
|
+
if (value && value.trim()) callback(value.trim());
|
|
1760
|
+
};
|
|
1761
|
+
|
|
1762
|
+
// Enter submits, Escape cancels
|
|
1763
|
+
input.key(['enter', 'return'], () => {
|
|
1764
|
+
finish(input.getValue().replace(/\n/g, '').trim());
|
|
1765
|
+
});
|
|
1766
|
+
|
|
1767
|
+
input.key(['escape'], () => {
|
|
1768
|
+
finish(null);
|
|
1769
|
+
});
|
|
1770
|
+
|
|
1771
|
+
// Block newlines
|
|
1772
|
+
input.on('keypress', (ch, key) => {
|
|
1773
|
+
if (key && (key.name === 'enter' || key.name === 'return')) return false;
|
|
1730
1774
|
});
|
|
1731
1775
|
|
|
1776
|
+
input.focus();
|
|
1732
1777
|
sc.render();
|
|
1733
1778
|
}
|
|
1734
1779
|
|
package/src/src/config.js
CHANGED
|
@@ -36,7 +36,7 @@ const config = {
|
|
|
36
36
|
apiKey: _saved.apiKey || '',
|
|
37
37
|
baseURL: _saved.baseURL || 'https://openrouter.ai/api/v1',
|
|
38
38
|
appName: 'Vibe Hacker',
|
|
39
|
-
version: '4.2.
|
|
39
|
+
version: '4.2.1',
|
|
40
40
|
noLogging: true,
|
|
41
41
|
maxTokens: 8192,
|
|
42
42
|
temperature: 0.6, // slightly lower for more reliable tool use
|
package/src/src/setup.js
CHANGED
|
@@ -7,11 +7,14 @@ function ew(s) {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
// ── First-run setup — simple API key paste ─────────────────────────────────
|
|
10
|
+
// Uses a raw textarea instead of textbox/prompt to avoid blessed's
|
|
11
|
+
// right-click-fires-cancel bug. Paste works with Ctrl+V, Shift+Insert,
|
|
12
|
+
// and terminal right-click paste on all platforms.
|
|
10
13
|
|
|
11
14
|
function showSetup(screen) {
|
|
12
15
|
return new Promise((resolve) => {
|
|
13
16
|
const W = Math.min(screen.width - 4, 60);
|
|
14
|
-
const H = Math.min(screen.height - 2,
|
|
17
|
+
const H = Math.min(screen.height - 2, 20);
|
|
15
18
|
|
|
16
19
|
const overlay = blessed.box({
|
|
17
20
|
parent: screen,
|
|
@@ -27,68 +30,78 @@ function showSetup(screen) {
|
|
|
27
30
|
'',
|
|
28
31
|
'{center}{green-fg}{bold}◈ Vibe Hacker — Get Started{/bold}{/green-fg}{/center}',
|
|
29
32
|
'',
|
|
30
|
-
'{center}{#888888-fg}
|
|
33
|
+
'{center}{#888888-fg}Paste your API key below.{/#888888-fg}{/center}',
|
|
31
34
|
'{center}{#888888-fg}Get a free key at vibsecurity.com{/#888888-fg}{/center}',
|
|
32
35
|
'',
|
|
33
|
-
'{#003300-fg} ════════════════════════════════════════════{/#003300-fg}',
|
|
34
|
-
'',
|
|
35
36
|
' {#555555-fg}Supported keys:{/#555555-fg}',
|
|
36
|
-
' {#44ff88-fg}Vibe Hacker{/#44ff88-fg} {#666666-fg}vh_… / sk-or-v1-…{/#666666-fg}',
|
|
37
37
|
' {#44ff88-fg}Groq{/#44ff88-fg} {#666666-fg}gsk_…{/#666666-fg}',
|
|
38
38
|
' {#44ff88-fg}Gemini{/#44ff88-fg} {#666666-fg}AIza…{/#666666-fg}',
|
|
39
39
|
' {#44ff88-fg}Cerebras{/#44ff88-fg} {#666666-fg}csk-…{/#666666-fg}',
|
|
40
|
+
' {#44ff88-fg}OpenRouter{/#44ff88-fg} {#666666-fg}sk-or-v1-…{/#666666-fg}',
|
|
40
41
|
' {#44ff88-fg}OpenAI{/#44ff88-fg} {#666666-fg}sk-…{/#666666-fg}',
|
|
41
42
|
' {#44ff88-fg}Anthropic{/#44ff88-fg} {#666666-fg}sk-ant-…{/#666666-fg}',
|
|
42
43
|
'',
|
|
43
44
|
].join('\n'));
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
// Use textarea instead of textbox — it doesn't fire cancel on right-click
|
|
47
|
+
const input = blessed.textarea({
|
|
46
48
|
parent: overlay,
|
|
47
49
|
bottom: 1, left: 2, right: 2, height: 3,
|
|
48
50
|
border: { type: 'line' },
|
|
49
|
-
label: ' {#00ff88-fg}Paste API Key{/#00ff88-fg} ',
|
|
50
|
-
style: {
|
|
51
|
-
|
|
51
|
+
label: ' {#00ff88-fg}Paste API Key (Enter to submit){/#00ff88-fg} ',
|
|
52
|
+
style: {
|
|
53
|
+
fg: '#00ff88', bg: '#001100',
|
|
54
|
+
border: { fg: '#00aa44' },
|
|
55
|
+
focus: { border: { fg: '#00ff88' } },
|
|
56
|
+
},
|
|
57
|
+
inputOnFocus: true,
|
|
52
58
|
mouse: true,
|
|
59
|
+
keys: true,
|
|
53
60
|
});
|
|
54
61
|
|
|
55
62
|
const statusLine = blessed.text({
|
|
56
63
|
parent: overlay,
|
|
57
64
|
bottom: 0, left: 2, right: 2, height: 1,
|
|
58
65
|
tags: true,
|
|
59
|
-
content: '',
|
|
66
|
+
content: ' {#444444-fg}Paste key then press Enter{/#444444-fg}',
|
|
60
67
|
style: { fg: '#00aa44', bg: 'black' },
|
|
61
68
|
});
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
input.
|
|
68
|
-
input.readInput();
|
|
70
|
+
let resolved = false;
|
|
71
|
+
function finish(val) {
|
|
72
|
+
if (resolved) return;
|
|
73
|
+
resolved = true;
|
|
74
|
+
try { input.destroy(); overlay.destroy(); } catch (_) {}
|
|
69
75
|
screen.render();
|
|
70
|
-
|
|
76
|
+
resolve(val);
|
|
77
|
+
}
|
|
71
78
|
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
// Handle key events manually — Enter submits, Escape cancels
|
|
80
|
+
input.key(['enter', 'return'], () => {
|
|
81
|
+
const key = (input.getValue() || '').replace(/\n/g, '').trim();
|
|
74
82
|
if (!key || key.length < 10) {
|
|
75
83
|
statusLine.setContent(' {red-fg}Key too short — paste a valid API key{/red-fg}');
|
|
76
84
|
input.clearValue();
|
|
77
|
-
input.focus();
|
|
78
|
-
input.readInput();
|
|
79
85
|
screen.render();
|
|
80
86
|
return;
|
|
81
87
|
}
|
|
82
|
-
|
|
83
|
-
screen.render();
|
|
84
|
-
resolve(key);
|
|
88
|
+
finish(key);
|
|
85
89
|
});
|
|
86
90
|
|
|
87
|
-
input.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
input.key(['escape'], () => {
|
|
92
|
+
finish(null);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Prevent newlines in the input (textarea allows them by default)
|
|
96
|
+
input.on('keypress', (ch, key) => {
|
|
97
|
+
if (key && (key.name === 'enter' || key.name === 'return')) {
|
|
98
|
+
// Already handled above — prevent default newline insertion
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
91
101
|
});
|
|
102
|
+
|
|
103
|
+
input.focus();
|
|
104
|
+
screen.render();
|
|
92
105
|
});
|
|
93
106
|
}
|
|
94
107
|
|