@nolimitcli/cli 2.0.0 → 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 (3) hide show
  1. package/README.md +51 -9
  2. package/dist/index.js +52 -58
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,25 +1,67 @@
1
- # @nolimit/cli
1
+ # @nolimitcli/cli
2
2
 
3
3
  No subscription. Just code.
4
4
 
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- npx @nolimit/cli
8
+ npx @nolimitcli/cli
9
9
  ```
10
10
 
11
- ## Commands
11
+ Or install globally:
12
12
 
13
13
  ```bash
14
- nolimit auth # Authenticate (get 2K welcome tokens)
15
- nolimit earn # Watch ad to earn 8K tokens
16
- nolimit balance # Check token balance
14
+ npm install -g @nolimitcli/cli
15
+ nolimit
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ Just run the command and start chatting:
21
+
17
22
  ```
23
+ ┌─────────────────────────────┐
24
+ │ NoLimit v2.0.0 │
25
+ │ No subscription. Just code. │
26
+ └─────────────────────────────┘
27
+
28
+ Balance: 2K tokens
29
+
30
+ Commands: /earn · /balance · /help · /quit
31
+ ─────────────────────────────────
32
+
33
+ › Write a function to reverse a string
34
+
35
+ function reverse(str) {
36
+ return str.split('').reverse().join('');
37
+ }
38
+
39
+ ─ 89 tokens used
40
+
41
+
42
+ ```
43
+
44
+ ## Commands
45
+
46
+ | Command | Description |
47
+ |---------|-------------|
48
+ | `/earn` | Watch an ad to earn 8K tokens |
49
+ | `/balance` | Check your token balance |
50
+ | `/clear` | Clear the screen |
51
+ | `/help` | Show all commands |
52
+ | `/quit` | Exit |
18
53
 
19
54
  ## How it works
20
55
 
21
- 1. Watch a 30-second ad
22
- 2. Earn 8,000 tokens
23
- 3. Use tokens for AI prompts
56
+ 1. First run auto-authenticates (2K welcome tokens)
57
+ 2. Type anything to chat with AI
58
+ 3. When tokens run low, type `/earn`
59
+ 4. Watch a 30-second ad in your browser
60
+ 5. Continue chatting
24
61
 
25
62
  No subscription. No credit card. Just code.
63
+
64
+ ## Links
65
+
66
+ - [nolimit.dev](https://nolimit.dev)
67
+ - [GitHub](https://github.com/buzzernetwork/nolimit)
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.0';
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,24 +170,22 @@ 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) => {
173
+ const rl = createReadline();
174
+ // Main loop
175
+ let running = true;
176
+ while (running) {
177
+ try {
178
+ const input = await question(rl, chalk.green('› '));
167
179
  const trimmed = input.trim();
168
- if (!trimmed) {
169
- prompt();
170
- return;
171
- }
180
+ if (!trimmed)
181
+ continue;
172
182
  // Handle commands
173
183
  if (trimmed.startsWith('/')) {
174
184
  const cmd = trimmed.toLowerCase();
175
185
  if (cmd === '/quit' || cmd === '/exit' || cmd === '/q') {
176
186
  console.log(chalk.dim('\n Goodbye.\n'));
177
- rl.close();
178
- process.exit(0);
187
+ running = false;
188
+ break;
179
189
  }
180
190
  if (cmd === '/help' || cmd === '/h') {
181
191
  console.log();
@@ -185,8 +195,7 @@ async function main() {
185
195
  console.log(chalk.cyan(' /clear') + chalk.dim(' Clear the screen'));
186
196
  console.log(chalk.cyan(' /quit') + chalk.dim(' Exit NoLimit'));
187
197
  console.log();
188
- prompt();
189
- return;
198
+ continue;
190
199
  }
191
200
  if (cmd === '/earn' || cmd === '/e') {
192
201
  console.log();
@@ -196,8 +205,7 @@ async function main() {
196
205
  balance = newData?.balance || balance;
197
206
  }
198
207
  console.log();
199
- prompt();
200
- return;
208
+ continue;
201
209
  }
202
210
  if (cmd === '/balance' || cmd === '/b') {
203
211
  const data = await getBalance(apiKey);
@@ -209,29 +217,22 @@ async function main() {
209
217
  console.log(chalk.dim(' Spent: ') + formatTokens(data.totalSpent));
210
218
  console.log();
211
219
  }
212
- prompt();
213
- return;
220
+ continue;
214
221
  }
215
222
  if (cmd === '/clear' || cmd === '/c') {
216
223
  showWelcome(balance);
217
- prompt();
218
- return;
224
+ continue;
219
225
  }
220
226
  console.log(chalk.dim(`\n Unknown command: ${trimmed}\n`));
221
- prompt();
222
- return;
227
+ continue;
223
228
  }
224
229
  // Check if we have enough tokens
225
230
  if (balance < 100) {
226
231
  console.log();
227
232
  console.log(chalk.yellow(' Low tokens.') + chalk.dim(' Watch an ad to continue.'));
228
233
  console.log();
229
- const watch = await new Promise((resolve) => {
230
- rl.question(chalk.dim(' Watch now? ') + chalk.cyan('[Y/n] '), (answer) => {
231
- resolve(answer.toLowerCase() !== 'n');
232
- });
233
- });
234
- if (watch) {
234
+ const answer = await question(rl, chalk.dim(' Watch now? ') + chalk.cyan('[Y/n] '));
235
+ if (answer.toLowerCase() !== 'n') {
235
236
  const success = await watchAd(apiKey);
236
237
  if (success) {
237
238
  const newData = await getBalance(apiKey);
@@ -239,8 +240,7 @@ async function main() {
239
240
  }
240
241
  }
241
242
  console.log();
242
- prompt();
243
- return;
243
+ continue;
244
244
  }
245
245
  // Generate response
246
246
  console.log();
@@ -249,19 +249,14 @@ async function main() {
249
249
  if (!result) {
250
250
  spinner.fail(chalk.red('Failed to generate response'));
251
251
  console.log();
252
- prompt();
253
- return;
252
+ continue;
254
253
  }
255
254
  if (result.text === '__INSUFFICIENT_TOKENS__') {
256
255
  spinner.stop();
257
256
  console.log(chalk.yellow(' Insufficient tokens.') + chalk.dim(' Watch an ad to continue.'));
258
257
  console.log();
259
- const watch = await new Promise((resolve) => {
260
- rl.question(chalk.dim(' Watch now? ') + chalk.cyan('[Y/n] '), (answer) => {
261
- resolve(answer.toLowerCase() !== 'n');
262
- });
263
- });
264
- if (watch) {
258
+ const answer = await question(rl, chalk.dim(' Watch now? ') + chalk.cyan('[Y/n] '));
259
+ if (answer.toLowerCase() !== 'n') {
265
260
  const success = await watchAd(apiKey);
266
261
  if (success) {
267
262
  const newData = await getBalance(apiKey);
@@ -269,8 +264,7 @@ async function main() {
269
264
  }
270
265
  }
271
266
  console.log();
272
- prompt();
273
- return;
267
+ continue;
274
268
  }
275
269
  spinner.stop();
276
270
  // Show response
@@ -280,16 +274,16 @@ async function main() {
280
274
  console.log();
281
275
  // Update balance
282
276
  balance = Math.max(0, balance - result.tokensUsed);
283
- prompt();
284
- });
285
- };
286
- // Handle Ctrl+C gracefully
287
- rl.on('close', () => {
288
- console.log(chalk.dim('\n Goodbye.\n'));
289
- process.exit(0);
290
- });
291
- // Start prompt loop
292
- prompt();
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);
293
287
  }
294
288
  // Run
295
289
  main().catch((error) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nolimitcli/cli",
3
- "version": "2.0.0",
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",