@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.
Files changed (2) hide show
  1. package/dist/index.js +135 -144
  2. 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.1';
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, prompt) {
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 (error) {
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(' NoLimit ') + chalk.dim(`v${VERSION}`) + chalk.bold.white(' │'));
130
- console.log(chalk.bold.white(' │') + chalk.gray(' No subscription. Just code.') + chalk.bold.white(' │'));
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(' Balance: ') + chalk.bold.white(formatTokens(balance)) + chalk.dim(' tokens'));
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(' Commands: ') + chalk.cyan('/earn') + chalk.dim(' · ') + chalk.cyan('/balance') + chalk.dim(' · ') + chalk.cyan('/help') + chalk.dim(' · ') + chalk.cyan('/quit'));
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
- const prompt = () => {
166
- rl.question(chalk.green(''), async (input) => {
167
- try {
168
- const trimmed = input.trim();
169
- if (!trimmed) {
170
- prompt();
171
- return;
172
- }
173
- // Handle commands
174
- if (trimmed.startsWith('/')) {
175
- const cmd = trimmed.toLowerCase();
176
- if (cmd === '/quit' || cmd === '/exit' || cmd === '/q') {
177
- console.log(chalk.dim('\n Goodbye.\n'));
178
- rl.close();
179
- process.exit(0);
180
- }
181
- if (cmd === '/help' || cmd === '/h') {
182
- console.log();
183
- console.log(chalk.dim(' Commands:'));
184
- console.log(chalk.cyan(' /earn') + chalk.dim(' Watch an ad to earn tokens'));
185
- console.log(chalk.cyan(' /balance') + chalk.dim(' Check your token balance'));
186
- console.log(chalk.cyan(' /clear') + chalk.dim(' Clear the screen'));
187
- console.log(chalk.cyan(' /quit') + chalk.dim(' Exit NoLimit'));
188
- console.log();
189
- prompt();
190
- return;
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
- const spinner = ora({ text: chalk.dim('Thinking...'), spinner: 'dots' }).start();
249
- const result = await generate(apiKey, trimmed);
250
- if (!result) {
251
- spinner.fail(chalk.red('Failed to generate response'));
252
- console.log();
253
- prompt();
254
- return;
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
- if (result.text === '__INSUFFICIENT_TOKENS__') {
257
- spinner.stop();
258
- console.log(chalk.yellow(' Insufficient tokens.') + chalk.dim(' Watch an ad to continue.'));
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
- const watch = await new Promise((resolve) => {
261
- rl.question(chalk.dim(' Watch now? ') + chalk.cyan('[Y/n] '), (answer) => {
262
- resolve(answer.toLowerCase() !== 'n');
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
- spinner.stop();
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
- catch (error) {
287
- console.log(chalk.red('\n Error occurred. Please try again.\n'));
288
- prompt();
219
+ if (cmd === '/clear' || cmd === '/c') {
220
+ showWelcome(balance);
221
+ continue;
289
222
  }
290
- });
291
- };
292
- // Handle Ctrl+C gracefully
293
- rl.on('close', () => {
294
- console.log(chalk.dim('\n Goodbye.\n'));
295
- process.exit(0);
296
- });
297
- // Start prompt loop
298
- prompt();
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) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nolimitcli/cli",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "type": "module",
5
5
  "description": "No subscription. Just code. AI chat powered by watching ads.",
6
6
  "main": "dist/index.js",