@nolimitcli/cli 2.1.1 → 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.
Files changed (2) hide show
  1. package/dist/index.js +106 -115
  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 { createInterface } from 'readline';
6
+ import repl from 'repl';
7
7
  const API_BASE = 'https://nolimit-production-2589.up.railway.app';
8
- const VERSION = '2.1.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(apiKey) {
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(apiKey) {
64
+ async function watchAd() {
65
+ if (!apiKey)
66
+ return false;
60
67
  try {
61
- const startData = await getBalance(apiKey);
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(apiKey);
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(apiKey, userPrompt) {
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 SCREEN
129
+ // WELCOME
120
130
  // ============================================================================
121
- function showWelcome(balance) {
131
+ function showWelcome() {
122
132
  console.clear();
123
133
  console.log();
124
134
  console.log(chalk.bold.white(' ┌───────────────────────────────┐'));
@@ -137,7 +147,7 @@ function showWelcome(balance) {
137
147
  // ============================================================================
138
148
  async function main() {
139
149
  // Get or create API key
140
- let apiKey = config.get('apiKey');
150
+ apiKey = config.get('apiKey');
141
151
  if (!apiKey) {
142
152
  const spinner = ora('Initializing...').start();
143
153
  const newKey = await authenticate();
@@ -149,130 +159,111 @@ async function main() {
149
159
  spinner.succeed('Ready');
150
160
  }
151
161
  // Get balance
152
- const balanceData = await getBalance(apiKey);
153
- let balance = balanceData?.balance || 0;
162
+ const balanceData = await getBalance();
163
+ balance = balanceData?.balance || 0;
154
164
  // Show welcome
155
- showWelcome(balance);
156
- // Create readline interface
157
- const rl = createInterface({
158
- input: process.stdin,
159
- output: process.stdout,
160
- });
161
- // Show prompt
162
- const showPrompt = () => {
163
- process.stdout.write(chalk.green('› '));
164
- };
165
- // Handle each line
166
- rl.on('line', async (input) => {
167
- const trimmed = input.trim();
168
- if (!trimmed) {
169
- showPrompt();
170
- return;
171
- }
172
- // Handle commands
173
- if (trimmed.startsWith('/')) {
174
- const cmd = trimmed.toLowerCase();
175
- if (cmd === '/quit' || cmd === '/exit' || cmd === '/q') {
176
- console.log(chalk.dim('\n Goodbye.\n'));
177
- rl.close();
178
- process.exit(0);
179
- }
180
- if (cmd === '/help' || cmd === '/h') {
181
- console.log();
182
- console.log(chalk.dim(' Commands:'));
183
- console.log(chalk.cyan(' /earn') + chalk.dim(' Watch ad for 8K tokens'));
184
- console.log(chalk.cyan(' /balance') + chalk.dim(' Check token balance'));
185
- console.log(chalk.cyan(' /clear') + chalk.dim(' Clear screen'));
186
- console.log(chalk.cyan(' /quit') + chalk.dim(' Exit'));
187
- console.log();
188
- showPrompt();
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);
189
173
  return;
190
174
  }
191
- if (cmd === '/earn' || cmd === '/e') {
192
- console.log();
193
- const success = await watchAd(apiKey);
194
- if (success) {
195
- const newData = await getBalance(apiKey);
196
- balance = newData?.balance || balance;
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);
197
181
  }
198
- console.log();
199
- showPrompt();
200
- return;
201
- }
202
- if (cmd === '/balance' || cmd === '/b') {
203
- const data = await getBalance(apiKey);
204
- if (data) {
205
- balance = data.balance;
182
+ if (cmd === '/help' || cmd === '/h') {
206
183
  console.log();
207
- console.log(chalk.dim(' Balance: ') + chalk.bold.white(formatTokens(data.balance)));
208
- console.log(chalk.dim(' Earned: ') + formatTokens(data.totalEarned));
209
- console.log(chalk.dim(' Spent: ') + formatTokens(data.totalSpent));
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'));
210
189
  console.log();
190
+ callback(null, undefined);
191
+ return;
211
192
  }
212
- showPrompt();
193
+ if (cmd === '/earn' || cmd === '/e') {
194
+ console.log();
195
+ await watchAd();
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;
212
+ }
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);
213
220
  return;
214
221
  }
215
- if (cmd === '/clear' || cmd === '/c') {
216
- showWelcome(balance);
217
- showPrompt();
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);
218
228
  return;
219
229
  }
220
- console.log(chalk.dim(`\n Unknown: ${trimmed}\n`));
221
- showPrompt();
222
- return;
223
- }
224
- // Check if we have enough tokens
225
- if (balance < 100) {
226
- console.log();
227
- console.log(chalk.yellow(' Low tokens. Run /earn to get more.'));
228
- console.log();
229
- showPrompt();
230
- return;
231
- }
232
- // Generate response
233
- console.log();
234
- const spinner = ora({ text: chalk.dim('Thinking...'), spinner: 'dots' }).start();
235
- const result = await generate(apiKey, trimmed);
236
- if (!result) {
237
- spinner.fail(chalk.red('Failed'));
230
+ // Generate
238
231
  console.log();
239
- showPrompt();
240
- return;
241
- }
242
- if (result.text === '__INSUFFICIENT_TOKENS__') {
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;
239
+ }
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;
246
+ }
243
247
  spinner.stop();
244
- console.log(chalk.yellow(' Insufficient tokens. Run /earn to get more.'));
248
+ // Show response
249
+ const lines = result.text.split('\n');
250
+ for (const line of lines) {
251
+ console.log(chalk.white(' ' + line));
252
+ }
245
253
  console.log();
246
- showPrompt();
247
- return;
248
- }
249
- spinner.stop();
250
- // Show response (indented for visual hierarchy)
251
- const lines = result.text.split('\n');
252
- for (const line of lines) {
253
- console.log(chalk.white(' ' + line));
254
- }
255
- console.log();
256
- // Update and show balance
257
- balance = Math.max(0, balance - result.tokensUsed);
258
- console.log(chalk.dim(` ─ ${formatTokens(result.tokensUsed)} tokens · ${formatTokens(balance)} remaining`));
259
- console.log();
260
- showPrompt();
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
261
  });
262
- // Handle close
263
- rl.on('close', () => {
262
+ r.on('exit', () => {
264
263
  console.log(chalk.dim('\n Goodbye.\n'));
265
264
  process.exit(0);
266
265
  });
267
- // Handle Ctrl+C
268
- rl.on('SIGINT', () => {
269
- console.log(chalk.dim('\n\n Goodbye.\n'));
270
- process.exit(0);
271
- });
272
- // Start
273
- showPrompt();
274
266
  }
275
- // Run
276
267
  main().catch((error) => {
277
268
  console.error(chalk.red('Error:'), error.message);
278
269
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nolimitcli/cli",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "type": "module",
5
5
  "description": "No subscription. Just code. AI chat powered by watching ads.",
6
6
  "main": "dist/index.js",