free-pi-cli 0.4.0 → 0.4.1
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.
package/dist/index.js
CHANGED
|
@@ -44,7 +44,7 @@ function openBrowser(url, platform = process.platform, spawnImpl = spawn) {
|
|
|
44
44
|
// package.json
|
|
45
45
|
var package_default = {
|
|
46
46
|
name: "free-pi-cli",
|
|
47
|
-
version: "0.4.
|
|
47
|
+
version: "0.4.1",
|
|
48
48
|
description: "Free, ad-supported distribution of the pi coding agent. Inference paid for by ads.",
|
|
49
49
|
license: "MIT",
|
|
50
50
|
type: "module",
|
|
@@ -4820,6 +4820,7 @@ var AuthConsentRequestSchema = object({
|
|
|
4820
4820
|
consent_version: string2()
|
|
4821
4821
|
});
|
|
4822
4822
|
var AccountTierSchema = _enum(["new", "young", "established"]);
|
|
4823
|
+
var UsageLaneSchema = _enum(["standard", "fallback", "wait"]);
|
|
4823
4824
|
var MeResponseSchema = object({
|
|
4824
4825
|
user_id: string2(),
|
|
4825
4826
|
handle: string2(),
|
|
@@ -4828,7 +4829,12 @@ var MeResponseSchema = object({
|
|
|
4828
4829
|
tier: AccountTierSchema,
|
|
4829
4830
|
credit_usd: number2(),
|
|
4830
4831
|
notice: string2().optional(),
|
|
4831
|
-
buy_url: string2().optional()
|
|
4832
|
+
buy_url: string2().optional(),
|
|
4833
|
+
allowance_credits: number2().optional(),
|
|
4834
|
+
remaining_credits_today: number2().optional(),
|
|
4835
|
+
refill_at: string2().optional(),
|
|
4836
|
+
lane: UsageLaneSchema.optional(),
|
|
4837
|
+
bonus_credits: number2().optional()
|
|
4832
4838
|
});
|
|
4833
4839
|
var MeStatsResponseSchema = object({
|
|
4834
4840
|
user_id: string2(),
|
|
@@ -4839,6 +4845,11 @@ var MeStatsResponseSchema = object({
|
|
|
4839
4845
|
remaining_usd_today: number2(),
|
|
4840
4846
|
credit_usd: number2(),
|
|
4841
4847
|
credit_credits: number2(),
|
|
4848
|
+
allowance_credits: number2(),
|
|
4849
|
+
remaining_credits_today: number2(),
|
|
4850
|
+
refill_at: string2(),
|
|
4851
|
+
lane: UsageLaneSchema,
|
|
4852
|
+
bonus_credits: number2(),
|
|
4842
4853
|
request_count_today: number2(),
|
|
4843
4854
|
prompt_tokens_today: number2(),
|
|
4844
4855
|
completion_tokens_today: number2(),
|
|
@@ -4912,7 +4923,7 @@ function assertExhaustiveErrorCode(code) {
|
|
|
4912
4923
|
}
|
|
4913
4924
|
// ../shared/src/config.ts
|
|
4914
4925
|
var ConfigSchema = object({
|
|
4915
|
-
perUserDailyCapUsd: number2().default(
|
|
4926
|
+
perUserDailyCapUsd: number2().default(1.125),
|
|
4916
4927
|
perUserRollingCapUsd: number2().default(0),
|
|
4917
4928
|
rollingCapWindowHours: number2().int().default(5),
|
|
4918
4929
|
globalDailyCapUsd: number2().default(50),
|
|
@@ -4936,8 +4947,12 @@ var ConfigSchema = object({
|
|
|
4936
4947
|
providerOrder: array(string2()).optional(),
|
|
4937
4948
|
tierNewMaxDays: number2().int().default(30),
|
|
4938
4949
|
tierYoungMaxDays: number2().int().default(365),
|
|
4939
|
-
tierCapNewUsd: number2().default(0.
|
|
4940
|
-
tierCapYoungUsd: number2().default(
|
|
4950
|
+
tierCapNewUsd: number2().default(0.45),
|
|
4951
|
+
tierCapYoungUsd: number2().default(1.125),
|
|
4952
|
+
fallbackLaneUsd: number2().default(0.225),
|
|
4953
|
+
fallbackHourlyCap: number2().int().default(10),
|
|
4954
|
+
fallbackLaneMinHeadroomBps: number2().int().default(1000),
|
|
4955
|
+
queueWaitRetryAfterSeconds: number2().int().default(0),
|
|
4941
4956
|
sessionLeaseTtlMinutes: number2().int().default(30),
|
|
4942
4957
|
minCliVersion: string2().default("0.0.0"),
|
|
4943
4958
|
latestCliVersion: string2().default("0.2.0"),
|
|
@@ -5006,6 +5021,10 @@ function loadConfig(env = process.env) {
|
|
|
5006
5021
|
tierYoungMaxDays: envNumber(env.TIER_YOUNG_MAX_DAYS),
|
|
5007
5022
|
tierCapNewUsd: envNumber(env.TIER_CAP_NEW_USD),
|
|
5008
5023
|
tierCapYoungUsd: envNumber(env.TIER_CAP_YOUNG_USD),
|
|
5024
|
+
fallbackLaneUsd: envNumber(env.FALLBACK_LANE_USD),
|
|
5025
|
+
fallbackHourlyCap: envNumber(env.FALLBACK_HOURLY_CAP),
|
|
5026
|
+
fallbackLaneMinHeadroomBps: envNumber(env.FALLBACK_LANE_MIN_HEADROOM_BPS),
|
|
5027
|
+
queueWaitRetryAfterSeconds: envNumber(env.QUEUE_WAIT_RETRY_AFTER_SECONDS),
|
|
5009
5028
|
sessionLeaseTtlMinutes: envNumber(env.SESSION_LEASE_TTL_MINUTES),
|
|
5010
5029
|
minCliVersion: env.MIN_CLI_VERSION || undefined,
|
|
5011
5030
|
latestCliVersion: env.LATEST_CLI_VERSION || undefined,
|
|
@@ -5051,6 +5070,21 @@ var CREDITS_PER_USD = 40000 / 3;
|
|
|
5051
5070
|
function usdToCredits(usd) {
|
|
5052
5071
|
return Math.round(Number(usd) * CREDITS_PER_USD);
|
|
5053
5072
|
}
|
|
5073
|
+
function formatRefillEt(date, timeZone = "America/New_York") {
|
|
5074
|
+
const formatted = new Intl.DateTimeFormat("en-US", {
|
|
5075
|
+
timeZone,
|
|
5076
|
+
hour: "numeric",
|
|
5077
|
+
minute: "2-digit",
|
|
5078
|
+
hour12: true
|
|
5079
|
+
}).format(date);
|
|
5080
|
+
return `${formatted} ET`;
|
|
5081
|
+
}
|
|
5082
|
+
function formatCreditsLeftLine(remaining, allowance, refillAt) {
|
|
5083
|
+
const left = remaining.toLocaleString("en-US");
|
|
5084
|
+
const total = allowance.toLocaleString("en-US");
|
|
5085
|
+
return `${left} / ${total} credits left today · refills ${formatRefillEt(refillAt)}`;
|
|
5086
|
+
}
|
|
5087
|
+
var SLOW_LANE_METER_LINE = "Slow lane: cheapest model until refill";
|
|
5054
5088
|
// ../pi-ads/src/api.ts
|
|
5055
5089
|
var REQUEST_TIMEOUT_MS = 3000;
|
|
5056
5090
|
async function authedFetch(deps, path, init) {
|
|
@@ -5157,6 +5191,9 @@ function renderPlainAdLine(creative, clickUrl, theme, columns) {
|
|
|
5157
5191
|
function renderErrorLine(message, theme) {
|
|
5158
5192
|
return theme.fg("error", message);
|
|
5159
5193
|
}
|
|
5194
|
+
function renderWarningLine(message, theme) {
|
|
5195
|
+
return theme.fg("warning", message);
|
|
5196
|
+
}
|
|
5160
5197
|
|
|
5161
5198
|
// ../pi-ads/src/banner.ts
|
|
5162
5199
|
var BANNER_WIDGET_ID = "freepi-ad";
|
|
@@ -5224,7 +5261,9 @@ function createInlineRenderer() {
|
|
|
5224
5261
|
function mapErrorCode(code) {
|
|
5225
5262
|
switch (code) {
|
|
5226
5263
|
case "daily_cap":
|
|
5227
|
-
return "out of free
|
|
5264
|
+
return "out of free credits today — refills at UTC midnight";
|
|
5265
|
+
case "queue_wait":
|
|
5266
|
+
return "free-pi is near its daily budget — wait and retry";
|
|
5228
5267
|
case "rolling_cap":
|
|
5229
5268
|
return "over the rolling spend cap on the free tier — wait for the Retry-After window";
|
|
5230
5269
|
case "concurrent":
|
|
@@ -5257,6 +5296,13 @@ function inferErrorFromRemainingBudget(remainingUsdToday) {
|
|
|
5257
5296
|
|
|
5258
5297
|
// ../pi-ads/src/meter.ts
|
|
5259
5298
|
var METER_WIDGET_ID = "freepi-meter";
|
|
5299
|
+
var METER_STATUS_KEY = "freepi-credits";
|
|
5300
|
+
var LOW_CREDIT_FRACTION = 0.1;
|
|
5301
|
+
var BUY_LINK_TEXT = "freepi.ai/buy";
|
|
5302
|
+
function buyMore(buyUrl) {
|
|
5303
|
+
const url = typeof buyUrl === "string" ? sanitizeText(buyUrl) : "";
|
|
5304
|
+
return url !== "" ? ` · Buy more: ${osc8(BUY_LINK_TEXT, url)}` : "";
|
|
5305
|
+
}
|
|
5260
5306
|
var CONFIRM_TURNS = 3;
|
|
5261
5307
|
var lastCreditUsd;
|
|
5262
5308
|
var confirm;
|
|
@@ -5265,6 +5311,7 @@ function creditAddedMessage(addedUsd) {
|
|
|
5265
5311
|
}
|
|
5266
5312
|
async function renderMeter(deps, ctx) {
|
|
5267
5313
|
const me = await fetchMe(deps);
|
|
5314
|
+
ctx.ui.setStatus(METER_STATUS_KEY, undefined);
|
|
5268
5315
|
if (!me) {
|
|
5269
5316
|
ctx.ui.setWidget(METER_WIDGET_ID, undefined);
|
|
5270
5317
|
return;
|
|
@@ -5286,6 +5333,24 @@ async function renderMeter(deps, ctx) {
|
|
|
5286
5333
|
ctx.ui.setWidget(METER_WIDGET_ID, [renderErrorLine(notice, theme)]);
|
|
5287
5334
|
return;
|
|
5288
5335
|
}
|
|
5336
|
+
if (me.lane === "fallback") {
|
|
5337
|
+
ctx.ui.setStatus(METER_STATUS_KEY, theme.fg("muted", "0 credits · slow lane"));
|
|
5338
|
+
ctx.ui.setWidget(METER_WIDGET_ID, [
|
|
5339
|
+
renderWarningLine(`Out of free credits — slow lane until refill${buyMore(me.buy_url)}`, theme)
|
|
5340
|
+
]);
|
|
5341
|
+
return;
|
|
5342
|
+
}
|
|
5343
|
+
if (typeof me.remaining_credits_today === "number" && typeof me.allowance_credits === "number" && typeof me.refill_at === "string") {
|
|
5344
|
+
const refill = new Date(me.refill_at);
|
|
5345
|
+
if (!Number.isNaN(refill.getTime()) && me.lane !== "wait") {
|
|
5346
|
+
const left = me.remaining_credits_today;
|
|
5347
|
+
const bought = typeof me.bonus_credits === "number" && me.bonus_credits > 0 ? ` + ${me.bonus_credits.toLocaleString("en-US")}` : "";
|
|
5348
|
+
ctx.ui.setStatus(METER_STATUS_KEY, theme.fg("muted", `${left.toLocaleString("en-US")}${bought} credits`));
|
|
5349
|
+
const low = left > 0 && left <= me.allowance_credits * LOW_CREDIT_FRACTION;
|
|
5350
|
+
ctx.ui.setWidget(METER_WIDGET_ID, low ? [renderWarningLine(`Low on credits: ${left.toLocaleString("en-US")} left today${buyMore(me.buy_url)}`, theme)] : undefined);
|
|
5351
|
+
return;
|
|
5352
|
+
}
|
|
5353
|
+
}
|
|
5289
5354
|
const errorCode = inferErrorFromRemainingBudget(me.remaining_usd_today);
|
|
5290
5355
|
if (errorCode === undefined) {
|
|
5291
5356
|
ctx.ui.setWidget(METER_WIDGET_ID, undefined);
|
|
@@ -5688,12 +5753,19 @@ function percentUsed(spentUsd, capUsd) {
|
|
|
5688
5753
|
}
|
|
5689
5754
|
function formatStats(stats) {
|
|
5690
5755
|
const credits = stats.credit_credits;
|
|
5756
|
+
const remaining = stats.remaining_credits_today;
|
|
5757
|
+
const allowance = stats.allowance_credits;
|
|
5758
|
+
const refillAt = stats.refill_at;
|
|
5759
|
+
const lane = stats.lane;
|
|
5760
|
+
const todayLine = typeof remaining === "number" && typeof allowance === "number" && typeof refillAt === "string" ? formatCreditsLeftLine(remaining, allowance, new Date(refillAt)) : `today: ${percentUsed(stats.spent_usd_today, stats.cap_usd_today)}% of your free daily allowance used`;
|
|
5691
5761
|
return [
|
|
5692
5762
|
`tier: ${stats.tier}`,
|
|
5693
|
-
|
|
5763
|
+
todayLine,
|
|
5764
|
+
...lane === "fallback" ? [SLOW_LANE_METER_LINE] : [],
|
|
5694
5765
|
...typeof credits === "number" ? [`credit: ${credits.toLocaleString("en-US")} credits remaining`] : [],
|
|
5695
5766
|
`today tokens: ${stats.prompt_tokens_today} prompt / ${stats.completion_tokens_today} completion`,
|
|
5696
|
-
`lifetime: ${stats.lifetime.prompt_tokens} prompt / ${stats.lifetime.completion_tokens} completion tokens
|
|
5767
|
+
`lifetime: ${stats.lifetime.prompt_tokens} prompt / ${stats.lifetime.completion_tokens} completion tokens`,
|
|
5768
|
+
"buy more credits: /buy-credits"
|
|
5697
5769
|
].join(`
|
|
5698
5770
|
`);
|
|
5699
5771
|
}
|
|
@@ -6281,6 +6353,13 @@ function registerBugAutocomplete(pi) {
|
|
|
6281
6353
|
|
|
6282
6354
|
// src/changelog.ts
|
|
6283
6355
|
var CHANGELOG_HIGHLIGHTS = [
|
|
6356
|
+
{
|
|
6357
|
+
version: "0.4.1",
|
|
6358
|
+
highlights: [
|
|
6359
|
+
"The footer now shows your credits left, including any you bought. A warning appears when you are low or in the slow lane.",
|
|
6360
|
+
"/usage shows credits left today and when they refill, with /buy-credits to get more."
|
|
6361
|
+
]
|
|
6362
|
+
},
|
|
6284
6363
|
{
|
|
6285
6364
|
version: "0.4.0",
|
|
6286
6365
|
highlights: [
|
|
@@ -6520,7 +6599,7 @@ function createFreePiCommandsExtension(opts) {
|
|
|
6520
6599
|
handler: (_args, ctx) => runUpdate(ctx)
|
|
6521
6600
|
});
|
|
6522
6601
|
pi.registerCommand("usage", {
|
|
6523
|
-
description: "Show
|
|
6602
|
+
description: "Show credits left today, refill time, and purchased credit.",
|
|
6524
6603
|
handler: (_args, ctx) => showUsage(opts, ctx)
|
|
6525
6604
|
});
|
|
6526
6605
|
pi.registerCommand("buy-credits", {
|
|
@@ -6545,7 +6624,7 @@ function createFreePiCommandsExtension(opts) {
|
|
|
6545
6624
|
|
|
6546
6625
|
// src/header.ts
|
|
6547
6626
|
var COMMANDS = [
|
|
6548
|
-
{ name: "/usage", description: "
|
|
6627
|
+
{ name: "/usage", description: "credits left today and refill time" },
|
|
6549
6628
|
{ name: "/support", description: "visit today's advertiser" },
|
|
6550
6629
|
{ name: "/tos", description: "terms of service" },
|
|
6551
6630
|
{ name: "/privacy-policy", description: "privacy policy" },
|