@nolimitcli/cli 2.1.0 → 2.1.2
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/dist/index.js +111 -136
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,9 +3,9 @@ import Conf from 'conf';
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import ora from 'ora';
|
|
5
5
|
import open from 'open';
|
|
6
|
-
import
|
|
6
|
+
import repl from 'repl';
|
|
7
7
|
const API_BASE = 'https://nolimit-production-2589.up.railway.app';
|
|
8
|
-
const VERSION = '2.1.
|
|
8
|
+
const VERSION = '2.1.2';
|
|
9
9
|
// Persistent config storage
|
|
10
10
|
const config = new Conf({
|
|
11
11
|
projectName: 'nolimit',
|
|
@@ -14,6 +14,9 @@ const config = new Conf({
|
|
|
14
14
|
apiKey: { type: 'string' },
|
|
15
15
|
},
|
|
16
16
|
});
|
|
17
|
+
// State
|
|
18
|
+
let apiKey;
|
|
19
|
+
let balance = 0;
|
|
17
20
|
// ============================================================================
|
|
18
21
|
// HELPERS
|
|
19
22
|
// ============================================================================
|
|
@@ -22,7 +25,9 @@ function formatTokens(tokens) {
|
|
|
22
25
|
return (tokens / 1000).toFixed(1).replace(/\.0$/, '') + 'K';
|
|
23
26
|
return tokens.toString();
|
|
24
27
|
}
|
|
25
|
-
async function getBalance(
|
|
28
|
+
async function getBalance() {
|
|
29
|
+
if (!apiKey)
|
|
30
|
+
return null;
|
|
26
31
|
try {
|
|
27
32
|
const response = await fetch(`${API_BASE}/api/credits/balance`, {
|
|
28
33
|
headers: { 'Authorization': `Bearer ${apiKey}` },
|
|
@@ -56,9 +61,11 @@ async function authenticate() {
|
|
|
56
61
|
return null;
|
|
57
62
|
}
|
|
58
63
|
}
|
|
59
|
-
async function watchAd(
|
|
64
|
+
async function watchAd() {
|
|
65
|
+
if (!apiKey)
|
|
66
|
+
return false;
|
|
60
67
|
try {
|
|
61
|
-
const startData = await getBalance(
|
|
68
|
+
const startData = await getBalance();
|
|
62
69
|
const startBalance = startData?.balance || 0;
|
|
63
70
|
const adResponse = await fetch(`${API_BASE}/api/ads/request`, {
|
|
64
71
|
headers: { 'Authorization': `Bearer ${apiKey}` },
|
|
@@ -76,9 +83,10 @@ async function watchAd(apiKey) {
|
|
|
76
83
|
attempts++;
|
|
77
84
|
const remaining = adData.duration - Math.min(attempts, adData.duration);
|
|
78
85
|
spinner.text = remaining > 0 ? `${remaining}s` : 'Verifying...';
|
|
79
|
-
const newData = await getBalance(
|
|
86
|
+
const newData = await getBalance();
|
|
80
87
|
if (newData && newData.balance > startBalance) {
|
|
81
88
|
spinner.succeed(chalk.green(`+${formatTokens(newData.balance - startBalance)} tokens`));
|
|
89
|
+
balance = newData.balance;
|
|
82
90
|
return true;
|
|
83
91
|
}
|
|
84
92
|
}
|
|
@@ -89,7 +97,9 @@ async function watchAd(apiKey) {
|
|
|
89
97
|
return false;
|
|
90
98
|
}
|
|
91
99
|
}
|
|
92
|
-
async function generate(
|
|
100
|
+
async function generate(userPrompt) {
|
|
101
|
+
if (!apiKey)
|
|
102
|
+
return null;
|
|
93
103
|
try {
|
|
94
104
|
const response = await fetch(`${API_BASE}/api/ai/generate`, {
|
|
95
105
|
method: 'POST',
|
|
@@ -116,9 +126,9 @@ async function generate(apiKey, userPrompt) {
|
|
|
116
126
|
}
|
|
117
127
|
}
|
|
118
128
|
// ============================================================================
|
|
119
|
-
// WELCOME
|
|
129
|
+
// WELCOME
|
|
120
130
|
// ============================================================================
|
|
121
|
-
function showWelcome(
|
|
131
|
+
function showWelcome() {
|
|
122
132
|
console.clear();
|
|
123
133
|
console.log();
|
|
124
134
|
console.log(chalk.bold.white(' ┌───────────────────────────────┐'));
|
|
@@ -133,11 +143,11 @@ function showWelcome(balance) {
|
|
|
133
143
|
console.log();
|
|
134
144
|
}
|
|
135
145
|
// ============================================================================
|
|
136
|
-
// MAIN
|
|
146
|
+
// MAIN
|
|
137
147
|
// ============================================================================
|
|
138
148
|
async function main() {
|
|
139
149
|
// Get or create API key
|
|
140
|
-
|
|
150
|
+
apiKey = config.get('apiKey');
|
|
141
151
|
if (!apiKey) {
|
|
142
152
|
const spinner = ora('Initializing...').start();
|
|
143
153
|
const newKey = await authenticate();
|
|
@@ -149,146 +159,111 @@ async function main() {
|
|
|
149
159
|
spinner.succeed('Ready');
|
|
150
160
|
}
|
|
151
161
|
// Get balance
|
|
152
|
-
const balanceData = await getBalance(
|
|
153
|
-
|
|
162
|
+
const balanceData = await getBalance();
|
|
163
|
+
balance = balanceData?.balance || 0;
|
|
154
164
|
// Show welcome
|
|
155
|
-
showWelcome(
|
|
156
|
-
//
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
rl.close();
|
|
165
|
-
process.exit(0);
|
|
166
|
-
});
|
|
167
|
-
// Main loop
|
|
168
|
-
while (true) {
|
|
169
|
-
let input;
|
|
170
|
-
try {
|
|
171
|
-
input = await rl.question(chalk.green('› '));
|
|
172
|
-
}
|
|
173
|
-
catch {
|
|
174
|
-
// EOF or stream closed
|
|
175
|
-
break;
|
|
176
|
-
}
|
|
177
|
-
const trimmed = input.trim();
|
|
178
|
-
if (!trimmed)
|
|
179
|
-
continue;
|
|
180
|
-
// Handle commands
|
|
181
|
-
if (trimmed.startsWith('/')) {
|
|
182
|
-
const cmd = trimmed.toLowerCase();
|
|
183
|
-
if (cmd === '/quit' || cmd === '/exit' || cmd === '/q') {
|
|
184
|
-
console.log(chalk.dim('\n Goodbye.\n'));
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
if (cmd === '/help' || cmd === '/h') {
|
|
188
|
-
console.log();
|
|
189
|
-
console.log(chalk.dim(' Commands:'));
|
|
190
|
-
console.log(chalk.cyan(' /earn') + chalk.dim(' Watch ad for 8K tokens'));
|
|
191
|
-
console.log(chalk.cyan(' /balance') + chalk.dim(' Check token balance'));
|
|
192
|
-
console.log(chalk.cyan(' /clear') + chalk.dim(' Clear screen'));
|
|
193
|
-
console.log(chalk.cyan(' /quit') + chalk.dim(' Exit'));
|
|
194
|
-
console.log();
|
|
195
|
-
continue;
|
|
165
|
+
showWelcome();
|
|
166
|
+
// Start REPL
|
|
167
|
+
const r = repl.start({
|
|
168
|
+
prompt: chalk.green('› '),
|
|
169
|
+
eval: async (input, _context, _filename, callback) => {
|
|
170
|
+
const trimmed = input.trim();
|
|
171
|
+
if (!trimmed) {
|
|
172
|
+
callback(null, undefined);
|
|
173
|
+
return;
|
|
196
174
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
if (
|
|
201
|
-
|
|
202
|
-
|
|
175
|
+
// Handle commands
|
|
176
|
+
if (trimmed.startsWith('/')) {
|
|
177
|
+
const cmd = trimmed.toLowerCase();
|
|
178
|
+
if (cmd === '/quit' || cmd === '/exit' || cmd === '/q') {
|
|
179
|
+
console.log(chalk.dim('\n Goodbye.\n'));
|
|
180
|
+
process.exit(0);
|
|
203
181
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
182
|
+
if (cmd === '/help' || cmd === '/h') {
|
|
183
|
+
console.log();
|
|
184
|
+
console.log(chalk.dim(' Commands:'));
|
|
185
|
+
console.log(chalk.cyan(' /earn') + chalk.dim(' Watch ad for 8K tokens'));
|
|
186
|
+
console.log(chalk.cyan(' /balance') + chalk.dim(' Check token balance'));
|
|
187
|
+
console.log(chalk.cyan(' /clear') + chalk.dim(' Clear screen'));
|
|
188
|
+
console.log(chalk.cyan(' /quit') + chalk.dim(' Exit'));
|
|
211
189
|
console.log();
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
190
|
+
callback(null, undefined);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (cmd === '/earn' || cmd === '/e') {
|
|
194
|
+
console.log();
|
|
195
|
+
await watchAd();
|
|
215
196
|
console.log();
|
|
197
|
+
callback(null, undefined);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (cmd === '/balance' || cmd === '/b') {
|
|
201
|
+
const data = await getBalance();
|
|
202
|
+
if (data) {
|
|
203
|
+
balance = data.balance;
|
|
204
|
+
console.log();
|
|
205
|
+
console.log(chalk.dim(' Balance: ') + chalk.bold.white(formatTokens(data.balance)));
|
|
206
|
+
console.log(chalk.dim(' Earned: ') + formatTokens(data.totalEarned));
|
|
207
|
+
console.log(chalk.dim(' Spent: ') + formatTokens(data.totalSpent));
|
|
208
|
+
console.log();
|
|
209
|
+
}
|
|
210
|
+
callback(null, undefined);
|
|
211
|
+
return;
|
|
216
212
|
}
|
|
217
|
-
|
|
213
|
+
if (cmd === '/clear' || cmd === '/c') {
|
|
214
|
+
showWelcome();
|
|
215
|
+
callback(null, undefined);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
console.log(chalk.dim(`\n Unknown: ${trimmed}\n`));
|
|
219
|
+
callback(null, undefined);
|
|
220
|
+
return;
|
|
218
221
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
+
// Check tokens
|
|
223
|
+
if (balance < 100) {
|
|
224
|
+
console.log();
|
|
225
|
+
console.log(chalk.yellow(' Low tokens. Run /earn'));
|
|
226
|
+
console.log();
|
|
227
|
+
callback(null, undefined);
|
|
228
|
+
return;
|
|
222
229
|
}
|
|
223
|
-
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
// Check if we have enough tokens
|
|
227
|
-
if (balance < 100) {
|
|
230
|
+
// Generate
|
|
228
231
|
console.log();
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
232
|
+
const spinner = ora({ text: chalk.dim('Thinking...'), spinner: 'dots' }).start();
|
|
233
|
+
const result = await generate(trimmed);
|
|
234
|
+
if (!result) {
|
|
235
|
+
spinner.fail(chalk.red('Failed'));
|
|
236
|
+
console.log();
|
|
237
|
+
callback(null, undefined);
|
|
238
|
+
return;
|
|
236
239
|
}
|
|
237
|
-
if (
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
240
|
+
if (result.text === '__INSUFFICIENT_TOKENS__') {
|
|
241
|
+
spinner.stop();
|
|
242
|
+
console.log(chalk.yellow(' Insufficient tokens. Run /earn'));
|
|
243
|
+
console.log();
|
|
244
|
+
callback(null, undefined);
|
|
245
|
+
return;
|
|
243
246
|
}
|
|
244
|
-
console.log();
|
|
245
|
-
continue;
|
|
246
|
-
}
|
|
247
|
-
// Generate response
|
|
248
|
-
console.log();
|
|
249
|
-
const spinner = ora({ text: chalk.dim('Thinking...'), spinner: 'dots' }).start();
|
|
250
|
-
const result = await generate(apiKey, trimmed);
|
|
251
|
-
if (!result) {
|
|
252
|
-
spinner.fail(chalk.red('Failed'));
|
|
253
|
-
console.log();
|
|
254
|
-
continue;
|
|
255
|
-
}
|
|
256
|
-
if (result.text === '__INSUFFICIENT_TOKENS__') {
|
|
257
247
|
spinner.stop();
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
catch {
|
|
264
|
-
break;
|
|
265
|
-
}
|
|
266
|
-
if (answer.toLowerCase() !== 'n') {
|
|
267
|
-
const success = await watchAd(apiKey);
|
|
268
|
-
if (success) {
|
|
269
|
-
const newData = await getBalance(apiKey);
|
|
270
|
-
balance = newData?.balance || balance;
|
|
271
|
-
}
|
|
248
|
+
// Show response
|
|
249
|
+
const lines = result.text.split('\n');
|
|
250
|
+
for (const line of lines) {
|
|
251
|
+
console.log(chalk.white(' ' + line));
|
|
272
252
|
}
|
|
273
253
|
console.log();
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
console.log();
|
|
287
|
-
}
|
|
288
|
-
rl.close();
|
|
289
|
-
process.exit(0);
|
|
254
|
+
balance = Math.max(0, balance - result.tokensUsed);
|
|
255
|
+
console.log(chalk.dim(` ─ ${formatTokens(result.tokensUsed)} tokens · ${formatTokens(balance)} remaining`));
|
|
256
|
+
console.log();
|
|
257
|
+
callback(null, undefined);
|
|
258
|
+
},
|
|
259
|
+
writer: () => '', // Suppress default output
|
|
260
|
+
ignoreUndefined: true,
|
|
261
|
+
});
|
|
262
|
+
r.on('exit', () => {
|
|
263
|
+
console.log(chalk.dim('\n Goodbye.\n'));
|
|
264
|
+
process.exit(0);
|
|
265
|
+
});
|
|
290
266
|
}
|
|
291
|
-
// Run
|
|
292
267
|
main().catch((error) => {
|
|
293
268
|
console.error(chalk.red('Error:'), error.message);
|
|
294
269
|
process.exit(1);
|