free-pi-cli 0.2.10 → 0.2.11

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
@@ -30,4 +30,4 @@ if (err) {
30
30
  console.error(err);
31
31
  process.exit(1);
32
32
  }
33
- await import("./main-b5491jxx.js");
33
+ await import("./main-q2v4gzhd.js");
@@ -48,7 +48,7 @@ function openBrowser(url, platform = process.platform, spawnImpl = spawn) {
48
48
  // package.json
49
49
  var package_default = {
50
50
  name: "free-pi-cli",
51
- version: "0.2.10",
51
+ version: "0.2.11",
52
52
  description: "Free, ad-supported distribution of the pi coding agent. Inference paid for by ads.",
53
53
  license: "MIT",
54
54
  type: "module",
@@ -14512,7 +14512,10 @@ var MeResponseSchema = exports_external.object({
14512
14512
  handle: exports_external.string(),
14513
14513
  remaining_usd_today: exports_external.number(),
14514
14514
  cap_usd_today: exports_external.number(),
14515
- tier: AccountTierSchema
14515
+ tier: AccountTierSchema,
14516
+ credit_usd: exports_external.number(),
14517
+ notice: exports_external.string().optional(),
14518
+ buy_url: exports_external.string().optional()
14516
14519
  });
14517
14520
  var MeStatsResponseSchema = exports_external.object({
14518
14521
  user_id: exports_external.string(),
@@ -14521,6 +14524,7 @@ var MeStatsResponseSchema = exports_external.object({
14521
14524
  cap_usd_today: exports_external.number(),
14522
14525
  spent_usd_today: exports_external.number(),
14523
14526
  remaining_usd_today: exports_external.number(),
14527
+ credit_usd: exports_external.number(),
14524
14528
  request_count_today: exports_external.number(),
14525
14529
  prompt_tokens_today: exports_external.number(),
14526
14530
  completion_tokens_today: exports_external.number(),
@@ -14922,6 +14926,11 @@ async function renderMeter(deps, ctx) {
14922
14926
  return;
14923
14927
  }
14924
14928
  const theme = ctx.ui.theme;
14929
+ const notice = typeof me.notice === "string" ? sanitizeText(me.notice).trim() : "";
14930
+ if (notice !== "") {
14931
+ ctx.ui.setWidget(METER_WIDGET_ID, [renderErrorLine(notice, theme)]);
14932
+ return;
14933
+ }
14925
14934
  const errorCode = inferErrorFromRemainingBudget(me.remaining_usd_today);
14926
14935
  if (errorCode === undefined) {
14927
14936
  ctx.ui.setWidget(METER_WIDGET_ID, undefined);
@@ -19262,9 +19271,11 @@ __export(exports_typebox, {
19262
19271
  var USAGE_TOOL_NAME = "free_pi_usage";
19263
19272
  var PARAMS = exports_typebox.Object({});
19264
19273
  function formatStats(stats) {
19274
+ const credit = stats.credit_usd;
19265
19275
  return [
19266
19276
  `tier: ${stats.tier} (cap $${stats.cap_usd_today.toFixed(2)}/day)`,
19267
19277
  `today: spent $${stats.spent_usd_today.toFixed(4)}, remaining $${stats.remaining_usd_today.toFixed(4)}, ${stats.request_count_today} request(s)`,
19278
+ ...typeof credit === "number" ? [`credit: $${credit.toFixed(2)} purchased usage remaining`] : [],
19268
19279
  `today tokens: ${stats.prompt_tokens_today} prompt / ${stats.completion_tokens_today} completion`,
19269
19280
  `lifetime: spent $${stats.lifetime.spent_usd.toFixed(4)}, ${stats.lifetime.request_count} request(s), ${stats.lifetime.prompt_tokens} prompt / ${stats.lifetime.completion_tokens} completion tokens`
19270
19281
  ].join(`
@@ -19311,6 +19322,65 @@ function createUsageToolExtension(opts) {
19311
19322
  };
19312
19323
  }
19313
19324
 
19325
+ // src/buy-tool.ts
19326
+ var BUY_TOOL_NAME = "free_pi_buy_credits";
19327
+ var PARAMS2 = exports_typebox.Object({});
19328
+ var NOT_AVAILABLE_TEXT = "Buying credits is not available on this server yet.";
19329
+ function buyText(url2) {
19330
+ return `Opening the buy page in your browser. If it did not open (for example over SSH), visit:
19331
+ ${url2}
19332
+
19333
+ Packs: $5 → $4.00 of usage, $10 → $8.00. Card or USDC.`;
19334
+ }
19335
+ function createBuyToolExtension(opts) {
19336
+ return {
19337
+ name: "free-pi-buy-tool",
19338
+ factory(pi) {
19339
+ pi.registerTool({
19340
+ name: BUY_TOOL_NAME,
19341
+ label: "Buy Credits",
19342
+ description: "Opens the free-pi buy-credits page in your browser (and prints the URL, for SSH sessions with no browser). Read-only against the server, takes no arguments.",
19343
+ promptSnippet: "Buy more free-pi credits",
19344
+ parameters: PARAMS2,
19345
+ async execute() {
19346
+ try {
19347
+ const token = await opts.getToken();
19348
+ const doFetch = opts.fetchImpl ?? fetch;
19349
+ const openBrowserFn = opts.openBrowserImpl ?? openBrowser;
19350
+ const res = await doFetch(`${opts.baseUrl}/me`, {
19351
+ headers: { Authorization: `Bearer ${token}` },
19352
+ signal: AbortSignal.timeout(5000)
19353
+ });
19354
+ if (!res.ok) {
19355
+ return {
19356
+ content: [{ type: "text", text: `Could not fetch the buy page (HTTP ${res.status}).` }],
19357
+ details: { ok: false }
19358
+ };
19359
+ }
19360
+ const me = await res.json();
19361
+ if (!me.buy_url) {
19362
+ return {
19363
+ content: [{ type: "text", text: NOT_AVAILABLE_TEXT }],
19364
+ details: { available: false }
19365
+ };
19366
+ }
19367
+ openBrowserFn(me.buy_url);
19368
+ return {
19369
+ content: [{ type: "text", text: buyText(me.buy_url) }],
19370
+ details: { buy_url: me.buy_url }
19371
+ };
19372
+ } catch (err) {
19373
+ return {
19374
+ content: [{ type: "text", text: `Could not fetch the buy page: ${String(err)}` }],
19375
+ details: { ok: false }
19376
+ };
19377
+ }
19378
+ }
19379
+ });
19380
+ }
19381
+ };
19382
+ }
19383
+
19314
19384
  // src/tool-guard.ts
19315
19385
  async function reportToolGuardTrigger(opts, toolName) {
19316
19386
  try {
@@ -19340,6 +19410,13 @@ function createToolGuardExtension(opts) {
19340
19410
 
19341
19411
  // src/changelog.ts
19342
19412
  var CHANGELOG_HIGHLIGHTS = [
19413
+ {
19414
+ version: "0.2.11",
19415
+ highlights: [
19416
+ 'Out of free usage? You can now buy more — $5 or $10 packs, card or USDC. Ask pi to "buy credits" or follow the link in the out-of-usage notice.',
19417
+ "The out-of-usage notice now comes from the server, and `free_pi_usage` shows your purchased balance."
19418
+ ]
19419
+ },
19343
19420
  {
19344
19421
  version: "0.2.10",
19345
19422
  highlights: [
@@ -19491,7 +19568,7 @@ function catalogModelsFor(opts) {
19491
19568
  const id = opts.model || MODEL_ID;
19492
19569
  return [{ id, name: id }];
19493
19570
  }
19494
- var ALLOWED_TOOL_NAMES = [...SAFE_TOOLS, USAGE_TOOL_NAME];
19571
+ var ALLOWED_TOOL_NAMES = [...SAFE_TOOLS, USAGE_TOOL_NAME, BUY_TOOL_NAME];
19495
19572
  function buildRuntimeOptions(opts, sessionId) {
19496
19573
  const models = catalogModelsFor(opts);
19497
19574
  const providerExtension = {
@@ -19509,6 +19586,10 @@ function buildRuntimeOptions(opts, sessionId) {
19509
19586
  baseUrl: opts.baseUrl,
19510
19587
  getToken: () => opts.jwt
19511
19588
  });
19589
+ const buyToolExtension = createBuyToolExtension({
19590
+ baseUrl: opts.baseUrl,
19591
+ getToken: () => opts.jwt
19592
+ });
19512
19593
  const toolGuardExtension = createToolGuardExtension({
19513
19594
  baseUrl: opts.baseUrl,
19514
19595
  getToken: () => opts.jwt,
@@ -19522,6 +19603,7 @@ function buildRuntimeOptions(opts, sessionId) {
19522
19603
  providerExtension,
19523
19604
  adsExtension,
19524
19605
  usageToolExtension,
19606
+ buyToolExtension,
19525
19607
  toolGuardExtension,
19526
19608
  commandsExtension
19527
19609
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-pi-cli",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "Free, ad-supported distribution of the pi coding agent. Inference paid for by ads.",
5
5
  "license": "MIT",
6
6
  "type": "module",