@nolimitcli/cli 2.0.1 → 2.1.0
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 +135 -144
- 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 * as readline from 'readline';
|
|
6
|
+
import * as readline from 'readline/promises';
|
|
7
7
|
const API_BASE = 'https://nolimit-production-2589.up.railway.app';
|
|
8
|
-
const VERSION = '2.0
|
|
8
|
+
const VERSION = '2.1.0';
|
|
9
9
|
// Persistent config storage
|
|
10
10
|
const config = new Conf({
|
|
11
11
|
projectName: 'nolimit',
|
|
@@ -58,20 +58,16 @@ async function authenticate() {
|
|
|
58
58
|
}
|
|
59
59
|
async function watchAd(apiKey) {
|
|
60
60
|
try {
|
|
61
|
-
// Get starting balance
|
|
62
61
|
const startData = await getBalance(apiKey);
|
|
63
62
|
const startBalance = startData?.balance || 0;
|
|
64
|
-
// Request ad
|
|
65
63
|
const adResponse = await fetch(`${API_BASE}/api/ads/request`, {
|
|
66
64
|
headers: { 'Authorization': `Bearer ${apiKey}` },
|
|
67
65
|
});
|
|
68
66
|
if (!adResponse.ok)
|
|
69
67
|
return false;
|
|
70
68
|
const adData = await adResponse.json();
|
|
71
|
-
// Open ad viewer
|
|
72
69
|
const adUrl = `${API_BASE}/ad-viewer.html?adId=${adData.adId}&apiKey=${apiKey}`;
|
|
73
70
|
await open(adUrl);
|
|
74
|
-
// Poll for completion
|
|
75
71
|
const spinner = ora('Watching...').start();
|
|
76
72
|
let attempts = 0;
|
|
77
73
|
const maxAttempts = 60;
|
|
@@ -93,7 +89,7 @@ async function watchAd(apiKey) {
|
|
|
93
89
|
return false;
|
|
94
90
|
}
|
|
95
91
|
}
|
|
96
|
-
async function generate(apiKey,
|
|
92
|
+
async function generate(apiKey, userPrompt) {
|
|
97
93
|
try {
|
|
98
94
|
const response = await fetch(`${API_BASE}/api/ai/generate`, {
|
|
99
95
|
method: 'POST',
|
|
@@ -101,7 +97,7 @@ async function generate(apiKey, prompt) {
|
|
|
101
97
|
'Authorization': `Bearer ${apiKey}`,
|
|
102
98
|
'Content-Type': 'application/json',
|
|
103
99
|
},
|
|
104
|
-
body: JSON.stringify({ prompt }),
|
|
100
|
+
body: JSON.stringify({ prompt: userPrompt }),
|
|
105
101
|
});
|
|
106
102
|
const data = await response.json();
|
|
107
103
|
if (!response.ok) {
|
|
@@ -115,7 +111,7 @@ async function generate(apiKey, prompt) {
|
|
|
115
111
|
tokensUsed: data.usage?.totalTokens || 0,
|
|
116
112
|
};
|
|
117
113
|
}
|
|
118
|
-
catch
|
|
114
|
+
catch {
|
|
119
115
|
return null;
|
|
120
116
|
}
|
|
121
117
|
}
|
|
@@ -125,15 +121,15 @@ async function generate(apiKey, prompt) {
|
|
|
125
121
|
function showWelcome(balance) {
|
|
126
122
|
console.clear();
|
|
127
123
|
console.log();
|
|
128
|
-
console.log(chalk.bold.white('
|
|
129
|
-
console.log(chalk.bold.white(' │') + chalk.bold('
|
|
130
|
-
console.log(chalk.bold.white(' │') + chalk.
|
|
131
|
-
console.log(chalk.bold.white('
|
|
124
|
+
console.log(chalk.bold.white(' ┌───────────────────────────────┐'));
|
|
125
|
+
console.log(chalk.bold.white(' │') + chalk.bold(' NoLimit ') + chalk.dim(`v${VERSION}`) + chalk.bold.white(' │'));
|
|
126
|
+
console.log(chalk.bold.white(' │') + chalk.dim(' No subscription. Just code.') + chalk.bold.white(' │'));
|
|
127
|
+
console.log(chalk.bold.white(' └───────────────────────────────┘'));
|
|
132
128
|
console.log();
|
|
133
|
-
console.log(chalk.dim('
|
|
129
|
+
console.log(chalk.dim(' Gemini 2.0 Flash') + chalk.dim(' · ') + chalk.bold.white(formatTokens(balance)) + chalk.dim(' tokens'));
|
|
134
130
|
console.log();
|
|
135
|
-
console.log(chalk.dim('
|
|
136
|
-
console.log(chalk.dim('
|
|
131
|
+
console.log(chalk.dim(' /earn · /balance · /help · /quit'));
|
|
132
|
+
console.log(chalk.dim(' ───────────────────────────────────'));
|
|
137
133
|
console.log();
|
|
138
134
|
}
|
|
139
135
|
// ============================================================================
|
|
@@ -157,145 +153,140 @@ async function main() {
|
|
|
157
153
|
let balance = balanceData?.balance || 0;
|
|
158
154
|
// Show welcome
|
|
159
155
|
showWelcome(balance);
|
|
160
|
-
// Create readline interface
|
|
156
|
+
// Create readline interface using promises API
|
|
161
157
|
const rl = readline.createInterface({
|
|
162
158
|
input: process.stdin,
|
|
163
159
|
output: process.stdout,
|
|
164
160
|
});
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if (cmd === '/earn' || cmd === '/e') {
|
|
193
|
-
console.log();
|
|
194
|
-
const success = await watchAd(apiKey);
|
|
195
|
-
if (success) {
|
|
196
|
-
const newData = await getBalance(apiKey);
|
|
197
|
-
balance = newData?.balance || balance;
|
|
198
|
-
}
|
|
199
|
-
console.log();
|
|
200
|
-
prompt();
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
if (cmd === '/balance' || cmd === '/b') {
|
|
204
|
-
const data = await getBalance(apiKey);
|
|
205
|
-
if (data) {
|
|
206
|
-
balance = data.balance;
|
|
207
|
-
console.log();
|
|
208
|
-
console.log(chalk.dim(' Balance: ') + chalk.bold.white(formatTokens(data.balance)) + chalk.dim(' tokens'));
|
|
209
|
-
console.log(chalk.dim(' Earned: ') + formatTokens(data.totalEarned));
|
|
210
|
-
console.log(chalk.dim(' Spent: ') + formatTokens(data.totalSpent));
|
|
211
|
-
console.log();
|
|
212
|
-
}
|
|
213
|
-
prompt();
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
if (cmd === '/clear' || cmd === '/c') {
|
|
217
|
-
showWelcome(balance);
|
|
218
|
-
prompt();
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
console.log(chalk.dim(`\n Unknown command: ${trimmed}\n`));
|
|
222
|
-
prompt();
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
// Check if we have enough tokens
|
|
226
|
-
if (balance < 100) {
|
|
227
|
-
console.log();
|
|
228
|
-
console.log(chalk.yellow(' Low tokens.') + chalk.dim(' Watch an ad to continue.'));
|
|
229
|
-
console.log();
|
|
230
|
-
const watch = await new Promise((resolve) => {
|
|
231
|
-
rl.question(chalk.dim(' Watch now? ') + chalk.cyan('[Y/n] '), (answer) => {
|
|
232
|
-
resolve(answer.toLowerCase() !== 'n');
|
|
233
|
-
});
|
|
234
|
-
});
|
|
235
|
-
if (watch) {
|
|
236
|
-
const success = await watchAd(apiKey);
|
|
237
|
-
if (success) {
|
|
238
|
-
const newData = await getBalance(apiKey);
|
|
239
|
-
balance = newData?.balance || balance;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
console.log();
|
|
243
|
-
prompt();
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
// Generate response
|
|
161
|
+
// Handle Ctrl+C
|
|
162
|
+
process.on('SIGINT', () => {
|
|
163
|
+
console.log(chalk.dim('\n\n Goodbye.\n'));
|
|
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') {
|
|
247
188
|
console.log();
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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;
|
|
196
|
+
}
|
|
197
|
+
if (cmd === '/earn' || cmd === '/e') {
|
|
198
|
+
console.log();
|
|
199
|
+
const success = await watchAd(apiKey);
|
|
200
|
+
if (success) {
|
|
201
|
+
const newData = await getBalance(apiKey);
|
|
202
|
+
balance = newData?.balance || balance;
|
|
255
203
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
204
|
+
console.log();
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (cmd === '/balance' || cmd === '/b') {
|
|
208
|
+
const data = await getBalance(apiKey);
|
|
209
|
+
if (data) {
|
|
210
|
+
balance = data.balance;
|
|
259
211
|
console.log();
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
if (watch) {
|
|
266
|
-
const success = await watchAd(apiKey);
|
|
267
|
-
if (success) {
|
|
268
|
-
const newData = await getBalance(apiKey);
|
|
269
|
-
balance = newData?.balance || balance;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
212
|
+
console.log(chalk.dim(' Balance: ') + chalk.bold.white(formatTokens(data.balance)));
|
|
213
|
+
console.log(chalk.dim(' Earned: ') + formatTokens(data.totalEarned));
|
|
214
|
+
console.log(chalk.dim(' Spent: ') + formatTokens(data.totalSpent));
|
|
272
215
|
console.log();
|
|
273
|
-
prompt();
|
|
274
|
-
return;
|
|
275
216
|
}
|
|
276
|
-
|
|
277
|
-
// Show response
|
|
278
|
-
console.log(chalk.white(result.text));
|
|
279
|
-
console.log();
|
|
280
|
-
console.log(chalk.dim(` ─ ${formatTokens(result.tokensUsed)} tokens used`));
|
|
281
|
-
console.log();
|
|
282
|
-
// Update balance
|
|
283
|
-
balance = Math.max(0, balance - result.tokensUsed);
|
|
284
|
-
prompt();
|
|
217
|
+
continue;
|
|
285
218
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
219
|
+
if (cmd === '/clear' || cmd === '/c') {
|
|
220
|
+
showWelcome(balance);
|
|
221
|
+
continue;
|
|
289
222
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
223
|
+
console.log(chalk.dim(`\n Unknown: ${trimmed}\n`));
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
// Check if we have enough tokens
|
|
227
|
+
if (balance < 100) {
|
|
228
|
+
console.log();
|
|
229
|
+
console.log(chalk.yellow(' Low tokens.'));
|
|
230
|
+
let answer;
|
|
231
|
+
try {
|
|
232
|
+
answer = await rl.question(chalk.dim(' Watch ad? ') + chalk.cyan('[Y/n] '));
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
if (answer.toLowerCase() !== 'n') {
|
|
238
|
+
const success = await watchAd(apiKey);
|
|
239
|
+
if (success) {
|
|
240
|
+
const newData = await getBalance(apiKey);
|
|
241
|
+
balance = newData?.balance || balance;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
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
|
+
spinner.stop();
|
|
258
|
+
console.log(chalk.yellow(' Insufficient tokens.'));
|
|
259
|
+
let answer;
|
|
260
|
+
try {
|
|
261
|
+
answer = await rl.question(chalk.dim(' Watch ad? ') + chalk.cyan('[Y/n] '));
|
|
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
|
+
}
|
|
272
|
+
}
|
|
273
|
+
console.log();
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
spinner.stop();
|
|
277
|
+
// Show response (indented for visual hierarchy)
|
|
278
|
+
const lines = result.text.split('\n');
|
|
279
|
+
for (const line of lines) {
|
|
280
|
+
console.log(chalk.white(' ' + line));
|
|
281
|
+
}
|
|
282
|
+
console.log();
|
|
283
|
+
// Update and show balance
|
|
284
|
+
balance = Math.max(0, balance - result.tokensUsed);
|
|
285
|
+
console.log(chalk.dim(` ─ ${formatTokens(result.tokensUsed)} tokens · ${formatTokens(balance)} remaining`));
|
|
286
|
+
console.log();
|
|
287
|
+
}
|
|
288
|
+
rl.close();
|
|
289
|
+
process.exit(0);
|
|
299
290
|
}
|
|
300
291
|
// Run
|
|
301
292
|
main().catch((error) => {
|