clixad 0.0.1-beta.27 → 0.0.1-beta.28

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/clixad.mjs +63 -11
  2. package/package.json +1 -1
package/dist/clixad.mjs CHANGED
@@ -310,8 +310,10 @@ function accessColumn(m, premium) {
310
310
  function premiumLocked(premium) {
311
311
  return premium !== void 0 && !premium.unlocked && premium.credits <= 0;
312
312
  }
313
- function premiumUnlockHint(unlockUsd) {
314
- return typeof unlockUsd === "number" && unlockUsd > 0 ? `premium: a survey or ${usd(unlockUsd)} unlocks it` : "premium: a survey unlocks it";
313
+ function premiumUnlockHint(unlockUsd, streak) {
314
+ const base = typeof unlockUsd === "number" && unlockUsd > 0 ? `premium: a survey or ${usd(unlockUsd)} unlocks it` : "premium: a survey unlocks it";
315
+ const s = usableStreak(streak);
316
+ return s && s.day < s.min_day ? `${base}, or a ${s.min_day}-day streak` : base;
315
317
  }
316
318
  function premiumHeadline(unlockUsd) {
317
319
  return typeof unlockUsd === "number" && unlockUsd > 0 ? `Premium: complete a survey or unlock from ${usd(unlockUsd)}.` : "Premium: complete a survey to unlock it.";
@@ -319,6 +321,33 @@ function premiumHeadline(unlockUsd) {
319
321
  function usd(v) {
320
322
  return Number.isInteger(v) ? `$${v}` : `$${v.toFixed(2)}`;
321
323
  }
324
+ function usableStreak(streak) {
325
+ if (typeof streak !== "object" || streak === null) return void 0;
326
+ const s = streak;
327
+ const num = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
328
+ const day = num(s.day);
329
+ const minDay = num(s.min_day);
330
+ const daily = num(s.daily_credits);
331
+ const left = num(s.credits_left);
332
+ if (day === void 0 || minDay === void 0 || daily === void 0 || left === void 0 || daily <= 0) {
333
+ return void 0;
334
+ }
335
+ return { day, min_day: minDay, daily_credits: daily, credits_left: left };
336
+ }
337
+ function premiumStreakLine(streak) {
338
+ const s = usableStreak(streak);
339
+ if (!s) return null;
340
+ const n = (x) => x.toLocaleString("en-US");
341
+ if (s.day < s.min_day) {
342
+ const wait = s.min_day - s.day;
343
+ const when = wait === 1 ? "tomorrow" : wait === 2 ? "the day after tomorrow" : `in ${wait} days`;
344
+ return `From day ${s.min_day} of your login streak, ${n(s.daily_credits)} bonus credits a day work on premium models too. You are on day ${s.day}, so that starts ${when} if you open Clixad every day.`;
345
+ }
346
+ if (s.credits_left <= 0) {
347
+ return `Today's ${n(s.daily_credits)} bonus credits for premium models are used up. They come back at 00:00 UTC while your login streak holds.`;
348
+ }
349
+ return `Your login streak lets ${n(s.credits_left)} more bonus credits go to premium models today.`;
350
+ }
322
351
  function adsPerTaskLabel(estAdsPerTask) {
323
352
  const effort = estAdsPerTask >= 1 ? `~${estAdsPerTask} ads/task` : "<1 ad/task";
324
353
  return `${effort} on completion (median)`;
@@ -336,7 +365,18 @@ function streakLabel(streak) {
336
365
  if (!streak.claimed) return `daily streak: ${where} \xB7 today's already counted`;
337
366
  const tomorrow = streak.schedule[Math.min(streak.day, streak.length - 1)];
338
367
  const next = tomorrow === void 0 ? "" : ` \xB7 tomorrow ${n(tomorrow)}`;
339
- return `daily streak: ${where} \xB7 +${n(streak.credits)} credits${next}`;
368
+ return `daily streak: ${where} \xB7 +${n(streak.credits)} credits${next}${streakPremiumClause(streak)}`;
369
+ }
370
+ function streakPremiumClause(streak) {
371
+ const p = streak.premium;
372
+ if (!p) return "";
373
+ return streak.day < p.minDay ? ` \xB7 bonus credits on premium from day ${p.minDay}` : ` \xB7 ${p.dailyCredits.toLocaleString("en-US")} bonus credits a day on premium`;
374
+ }
375
+ function streakPremium(raw) {
376
+ if (typeof raw !== "object" || raw === null) return {};
377
+ const p = raw;
378
+ if (typeof p.min_day !== "number" || typeof p.daily_credits !== "number" || p.daily_credits <= 0) return {};
379
+ return { premium: { minDay: p.min_day, dailyCredits: p.daily_credits } };
340
380
  }
341
381
  function referLines(info) {
342
382
  const n = (x) => x.toLocaleString("en-US");
@@ -431,7 +471,8 @@ function premiumLockedError(message, model, body) {
431
471
  num(body?.premium_credits),
432
472
  typeof body?.unlock_usd === "number" && body.unlock_usd > 0 ? body.unlock_usd : null,
433
473
  num(body?.grant_per_ad),
434
- freeAlternatives(body?.free_models)
474
+ freeAlternatives(body?.free_models),
475
+ usableStreak(body?.streak)
435
476
  );
436
477
  }
437
478
  function shortfallHeadline(err, model) {
@@ -627,7 +668,7 @@ var init_client = __esm({
627
668
  freeModels;
628
669
  };
629
670
  PremiumLockedError = class extends Error {
630
- constructor(message, model, neededCredits, premiumCredits, unlockUsd, grantPerAd, freeModels) {
671
+ constructor(message, model, neededCredits, premiumCredits, unlockUsd, grantPerAd, freeModels, streak) {
631
672
  super(message);
632
673
  this.model = model;
633
674
  this.neededCredits = neededCredits;
@@ -635,6 +676,7 @@ var init_client = __esm({
635
676
  this.unlockUsd = unlockUsd;
636
677
  this.grantPerAd = grantPerAd;
637
678
  this.freeModels = freeModels;
679
+ this.streak = streak;
638
680
  this.name = "PremiumLockedError";
639
681
  }
640
682
  model;
@@ -643,6 +685,7 @@ var init_client = __esm({
643
685
  unlockUsd;
644
686
  grantPerAd;
645
687
  freeModels;
688
+ streak;
646
689
  };
647
690
  GatewayUnreachableError = class extends Error {
648
691
  constructor(host, code) {
@@ -801,7 +844,8 @@ var init_client = __esm({
801
844
  claimed: body.claimed === true,
802
845
  balance: typeof body.balance === "number" ? body.balance : 0,
803
846
  schedule: Array.isArray(body.schedule) ? body.schedule : [],
804
- length: typeof body.length === "number" ? body.length : 0
847
+ length: typeof body.length === "number" ? body.length : 0,
848
+ ...streakPremium(body.premium)
805
849
  };
806
850
  } catch {
807
851
  return null;
@@ -6641,7 +6685,7 @@ function App({
6641
6685
  if (event.creditsCharged > 0 && premiumRef.current) {
6642
6686
  const p = premiumRef.current;
6643
6687
  setPremium({
6644
- unlocked: p.unlocked,
6688
+ ...p,
6645
6689
  credits: Math.max(0, p.unlocked ? event.balance : Math.min(event.balance, p.credits - event.creditsCharged))
6646
6690
  });
6647
6691
  }
@@ -6796,15 +6840,17 @@ ${NO_SEARCH_INSTRUCTION}`),
6796
6840
  if (err instanceof PremiumLockedError) {
6797
6841
  pendingTaskRef.current = { task, images };
6798
6842
  pendingPremiumRef.current = err;
6799
- setPremium({ unlocked: false, credits: err.premiumCredits });
6843
+ setPremium({ unlocked: false, credits: err.premiumCredits, ...err.streak ? { streak: err.streak } : {} });
6800
6844
  const short2 = err.premiumCredits > 0 ? ` This turn needs about ${err.neededCredits.toLocaleString("en-US")} of those credits, and you have ${err.premiumCredits.toLocaleString("en-US")}.
6801
6845
  ` : "";
6846
+ const streakLine = premiumStreakLine(err.streak);
6802
6847
  push({
6803
6848
  kind: "notice",
6804
6849
  tone: "warn",
6805
6850
  text: ` ${premiumHeadline(err.unlockUsd)}
6806
6851
  ${err.model} is a premium model. It runs on credits you earned on the offer walls or bought.
6807
- ` + short2 + " Your bonus credits (the signup bonus, our own surveys) still work on budget models.\n Press enter to unlock it or to switch to a budget model. Your request is kept."
6852
+ ` + short2 + (streakLine ? ` ${streakLine}
6853
+ ` : "") + " Your bonus credits (the signup bonus, our own surveys) still work on budget models.\n Press enter to unlock it or to switch to a budget model. Your request is kept."
6808
6854
  });
6809
6855
  } else if (err instanceof PaywallError) {
6810
6856
  pendingTaskRef.current = { task, images };
@@ -7267,7 +7313,7 @@ ${NO_SEARCH_INSTRUCTION}`),
7267
7313
  const items = models.map((m) => ({
7268
7314
  value: m.id,
7269
7315
  label: m.id,
7270
- hint: accessColumn(m, premium2) + (m.access === "premium" && premiumLocked(premium2) ? premiumUnlockHint(unlockUsd) : modelHint(m, free)),
7316
+ hint: accessColumn(m, premium2) + (m.access === "premium" && premiumLocked(premium2) ? premiumUnlockHint(unlockUsd, premium2?.streak) : modelHint(m, free)),
7271
7317
  current: m.id === model
7272
7318
  }));
7273
7319
  const preselect = items.findIndex((i) => i.value === arg);
@@ -7283,12 +7329,14 @@ ${NO_SEARCH_INSTRUCTION}`),
7283
7329
  push({ kind: "notice", text: ` model \u2192 ${choice.value}` });
7284
7330
  const picked = models.find((m) => m.id === choice.value);
7285
7331
  if (picked?.access === "premium" && premiumLocked(premium2)) {
7332
+ const streakLine = premiumStreakLine(premium2?.streak);
7286
7333
  push({
7287
7334
  kind: "notice",
7288
7335
  tone: "warn",
7289
7336
  text: ` ${premiumHeadline(unlockUsd)}
7290
7337
  ${choice.value} runs on credits you earned on the offer walls or bought.
7291
- /earn opens the offer walls` + (unlockUsd ? `, /buy unlocks premium from ${usd(unlockUsd)}.` : ".") + " Your bonus credits work on budget models."
7338
+ ` + (streakLine ? ` ${streakLine}
7339
+ ` : "") + " /earn opens the offer walls" + (unlockUsd ? `, /buy unlocks premium from ${usd(unlockUsd)}.` : ".") + " Your bonus credits work on budget models."
7292
7340
  });
7293
7341
  }
7294
7342
  }
@@ -8672,6 +8720,8 @@ function printPremiumRefusal(err) {
8672
8720
  )
8673
8721
  );
8674
8722
  }
8723
+ const streakLine = premiumStreakLine(err.streak);
8724
+ if (streakLine) console.log(c.yellow(streakLine));
8675
8725
  console.log(c.yellow(`Run \`clixad earn\` for a survey on the offer walls. Offers pay ${grantLabel(err.grantPerAd)}.`));
8676
8726
  if (err.unlockUsd) {
8677
8727
  console.log(c.yellow(`Or unlock premium from ${usd(err.unlockUsd)}: start \`clixad\` and type /buy.`));
@@ -8703,6 +8753,8 @@ async function setModel(client, config, model) {
8703
8753
  `${model} runs on credits you earned on the offer walls or bought. Run \`clixad earn\` for a survey` + (client.premiumUnlockUsd ? `, or start \`clixad\` and type /buy.` : ".")
8704
8754
  )
8705
8755
  );
8756
+ const streakLine = premiumStreakLine(w?.premium?.streak);
8757
+ if (streakLine) console.log(c.yellow(streakLine));
8706
8758
  }
8707
8759
  }
8708
8760
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clixad",
3
- "version": "0.0.1-beta.27",
3
+ "version": "0.0.1-beta.28",
4
4
  "description": "Free AI coding agent in your terminal, funded by rewarded ads.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",