@nolimitcli/cli 2.0.1 → 2.0.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.
Files changed (2) hide show
  1. package/dist/index.js +120 -132
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import ora from 'ora';
5
5
  import open from 'open';
6
6
  import * as readline from 'readline';
7
7
  const API_BASE = 'https://nolimit-production-2589.up.railway.app';
8
- const VERSION = '2.0.1';
8
+ const VERSION = '2.0.2';
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,11 +111,27 @@ 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
  }
122
118
  // ============================================================================
119
+ // READLINE HELPERS
120
+ // ============================================================================
121
+ function createReadline() {
122
+ return readline.createInterface({
123
+ input: process.stdin,
124
+ output: process.stdout,
125
+ });
126
+ }
127
+ function question(rl, query) {
128
+ return new Promise((resolve) => {
129
+ rl.question(query, (answer) => {
130
+ resolve(answer);
131
+ });
132
+ });
133
+ }
134
+ // ============================================================================
123
135
  // WELCOME SCREEN
124
136
  // ============================================================================
125
137
  function showWelcome(balance) {
@@ -158,144 +170,120 @@ async function main() {
158
170
  // Show welcome
159
171
  showWelcome(balance);
160
172
  // Create readline interface
161
- const rl = readline.createInterface({
162
- input: process.stdin,
163
- output: process.stdout,
164
- });
165
- const prompt = () => {
166
- rl.question(chalk.green('› '), async (input) => {
167
- try {
168
- const trimmed = input.trim();
169
- if (!trimmed) {
170
- prompt();
171
- return;
173
+ const rl = createReadline();
174
+ // Main loop
175
+ let running = true;
176
+ while (running) {
177
+ try {
178
+ const input = await question(rl, chalk.green('› '));
179
+ const trimmed = input.trim();
180
+ if (!trimmed)
181
+ continue;
182
+ // Handle commands
183
+ if (trimmed.startsWith('/')) {
184
+ const cmd = trimmed.toLowerCase();
185
+ if (cmd === '/quit' || cmd === '/exit' || cmd === '/q') {
186
+ console.log(chalk.dim('\n Goodbye.\n'));
187
+ running = false;
188
+ break;
172
189
  }
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;
190
+ if (cmd === '/help' || cmd === '/h') {
191
+ console.log();
192
+ console.log(chalk.dim(' Commands:'));
193
+ console.log(chalk.cyan(' /earn') + chalk.dim(' Watch an ad to earn tokens'));
194
+ console.log(chalk.cyan(' /balance') + chalk.dim(' Check your token balance'));
195
+ console.log(chalk.cyan(' /clear') + chalk.dim(' Clear the screen'));
196
+ console.log(chalk.cyan(' /quit') + chalk.dim(' Exit NoLimit'));
197
+ console.log();
198
+ continue;
199
+ }
200
+ if (cmd === '/earn' || cmd === '/e') {
201
+ console.log();
202
+ const success = await watchAd(apiKey);
203
+ if (success) {
204
+ const newData = await getBalance(apiKey);
205
+ balance = newData?.balance || balance;
191
206
  }
192
- if (cmd === '/earn' || cmd === '/e') {
207
+ console.log();
208
+ continue;
209
+ }
210
+ if (cmd === '/balance' || cmd === '/b') {
211
+ const data = await getBalance(apiKey);
212
+ if (data) {
213
+ balance = data.balance;
193
214
  console.log();
194
- const success = await watchAd(apiKey);
195
- if (success) {
196
- const newData = await getBalance(apiKey);
197
- balance = newData?.balance || balance;
198
- }
215
+ console.log(chalk.dim(' Balance: ') + chalk.bold.white(formatTokens(data.balance)) + chalk.dim(' tokens'));
216
+ console.log(chalk.dim(' Earned: ') + formatTokens(data.totalEarned));
217
+ console.log(chalk.dim(' Spent: ') + formatTokens(data.totalSpent));
199
218
  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
219
  }
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;
220
+ continue;
224
221
  }
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;
222
+ if (cmd === '/clear' || cmd === '/c') {
223
+ showWelcome(balance);
224
+ continue;
245
225
  }
246
- // Generate response
226
+ console.log(chalk.dim(`\n Unknown command: ${trimmed}\n`));
227
+ continue;
228
+ }
229
+ // Check if we have enough tokens
230
+ if (balance < 100) {
247
231
  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;
255
- }
256
- if (result.text === '__INSUFFICIENT_TOKENS__') {
257
- spinner.stop();
258
- console.log(chalk.yellow(' Insufficient tokens.') + chalk.dim(' Watch an ad to continue.'));
259
- 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
- }
232
+ console.log(chalk.yellow(' Low tokens.') + chalk.dim(' Watch an ad to continue.'));
233
+ console.log();
234
+ const answer = await question(rl, chalk.dim(' Watch now? ') + chalk.cyan('[Y/n] '));
235
+ if (answer.toLowerCase() !== 'n') {
236
+ const success = await watchAd(apiKey);
237
+ if (success) {
238
+ const newData = await getBalance(apiKey);
239
+ balance = newData?.balance || balance;
271
240
  }
272
- console.log();
273
- prompt();
274
- return;
275
241
  }
276
- spinner.stop();
277
- // Show response
278
- console.log(chalk.white(result.text));
279
242
  console.log();
280
- console.log(chalk.dim(` ─ ${formatTokens(result.tokensUsed)} tokens used`));
243
+ continue;
244
+ }
245
+ // Generate response
246
+ console.log();
247
+ const spinner = ora({ text: chalk.dim('Thinking...'), spinner: 'dots' }).start();
248
+ const result = await generate(apiKey, trimmed);
249
+ if (!result) {
250
+ spinner.fail(chalk.red('Failed to generate response'));
281
251
  console.log();
282
- // Update balance
283
- balance = Math.max(0, balance - result.tokensUsed);
284
- prompt();
252
+ continue;
285
253
  }
286
- catch (error) {
287
- console.log(chalk.red('\n Error occurred. Please try again.\n'));
288
- prompt();
254
+ if (result.text === '__INSUFFICIENT_TOKENS__') {
255
+ spinner.stop();
256
+ console.log(chalk.yellow(' Insufficient tokens.') + chalk.dim(' Watch an ad to continue.'));
257
+ console.log();
258
+ const answer = await question(rl, chalk.dim(' Watch now? ') + chalk.cyan('[Y/n] '));
259
+ if (answer.toLowerCase() !== 'n') {
260
+ const success = await watchAd(apiKey);
261
+ if (success) {
262
+ const newData = await getBalance(apiKey);
263
+ balance = newData?.balance || balance;
264
+ }
265
+ }
266
+ console.log();
267
+ continue;
289
268
  }
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();
269
+ spinner.stop();
270
+ // Show response
271
+ console.log(chalk.white(result.text));
272
+ console.log();
273
+ console.log(chalk.dim(` ─ ${formatTokens(result.tokensUsed)} tokens used`));
274
+ console.log();
275
+ // Update balance
276
+ balance = Math.max(0, balance - result.tokensUsed);
277
+ }
278
+ catch (error) {
279
+ // Handle Ctrl+C or EOF
280
+ console.log(chalk.dim('\n Goodbye.\n'));
281
+ running = false;
282
+ break;
283
+ }
284
+ }
285
+ rl.close();
286
+ process.exit(0);
299
287
  }
300
288
  // Run
301
289
  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.0.2",
4
4
  "type": "module",
5
5
  "description": "No subscription. Just code. AI chat powered by watching ads.",
6
6
  "main": "dist/index.js",