free-pi-cli 0.6.12 → 0.6.14

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
@@ -27,4 +27,4 @@ if (err) {
27
27
  console.error(err);
28
28
  process.exit(1);
29
29
  }
30
- await import("./main-1yrj772b.js");
30
+ await import("./main-j1ey9ghj.js");
@@ -515,7 +515,7 @@ function folderMatches(cwd, sessionCwd) {
515
515
  // package.json
516
516
  var package_default = {
517
517
  name: "free-pi-cli",
518
- version: "0.6.12",
518
+ version: "0.6.14",
519
519
  description: "Free AI coding agent for your terminal. Ads and a daily free allowance pay for the models; sign in with GitHub and run npx free-pi-cli.",
520
520
  keywords: [
521
521
  "coding agent",
@@ -6267,6 +6267,14 @@ var ConfigSchema = object({
6267
6267
  experientialTtftMs: number2().int().min(1).default(1e4),
6268
6268
  experientialMaxCostUsdPerRequest: string2().default("0.0005"),
6269
6269
  experientialPriceCooldownMs: number2().int().min(1).default(3600000),
6270
+ particleEnabled: boolean2().default(false),
6271
+ particleBaseUrl: string2().default("https://api.particle.ai/v1"),
6272
+ particleModelMap: record(string2(), string2()).default({
6273
+ particle: "particle-1",
6274
+ "deepseek-v4.1-flash": "deepseek-ai/deepseek-v41-flash-1017",
6275
+ "glm-5.3-flash": "z-ai/glm-5.3-flash"
6276
+ }),
6277
+ particleTtftMs: number2().int().min(1).default(1e4),
6270
6278
  minCliVersion: string2().default("0.0.0"),
6271
6279
  latestCliVersion: string2().default("0.2.0"),
6272
6280
  minDesktopVersion: string2().default("0.0.0"),
@@ -6571,6 +6579,10 @@ function loadConfig(env = process.env) {
6571
6579
  experientialTtftMs: envNumber(env.EXPERIENTIAL_TTFT_MS),
6572
6580
  experientialMaxCostUsdPerRequest: /^\d{1,6}(\.\d{1,6})?$/.test(env.EXPERIENTIAL_MAX_COST_USD_PER_REQUEST?.trim() ?? "") ? env.EXPERIENTIAL_MAX_COST_USD_PER_REQUEST.trim() : undefined,
6573
6581
  experientialPriceCooldownMs: envNumber(env.EXPERIENTIAL_PRICE_COOLDOWN_MS),
6582
+ particleEnabled: envBoolean(env.PARTICLE_ENABLED),
6583
+ particleBaseUrl: env.PARTICLE_BASE_URL?.trim().replace(/\/$/, "") || undefined,
6584
+ particleModelMap: envPairs(env.PARTICLE_MODEL_MAP),
6585
+ particleTtftMs: envNumber(env.PARTICLE_TTFT_MS),
6574
6586
  minCliVersion: env.MIN_CLI_VERSION || undefined,
6575
6587
  latestCliVersion: env.LATEST_CLI_VERSION || undefined,
6576
6588
  minDesktopVersion: env.MIN_DESKTOP_VERSION || undefined,
@@ -9636,6 +9648,18 @@ function mergeAttribution(a, b) {
9636
9648
 
9637
9649
  // src/changelog.ts
9638
9650
  var CHANGELOG_HIGHLIGHTS = [
9651
+ {
9652
+ version: "0.6.14",
9653
+ highlights: [
9654
+ "Free Unlimited for a limited time: Particle, DeepSeek V4.1 Flash and GLM 5.3 Flash use no credits. They are at the top of the model list."
9655
+ ]
9656
+ },
9657
+ {
9658
+ version: "0.6.13",
9659
+ highlights: [
9660
+ "New: Particle, a free model that uses no credits, when it is available."
9661
+ ]
9662
+ },
9639
9663
  {
9640
9664
  version: "0.6.12",
9641
9665
  highlights: [
@@ -11425,6 +11449,8 @@ var ALL_COMMANDS = [
11425
11449
  var commands = () => ALL_COMMANDS.filter((c) => c.name !== "/hive" || process.env.FREEPI_HIVE === "1");
11426
11450
  var NAME_COLUMN = 24;
11427
11451
  var WELCOME_LINE = "Welcome to Free Pi, ad-supported inference. Please visit our advertisers to support us.";
11452
+ var FREE_LABEL = "Free Unlimited: limited time";
11453
+ var PARTICLE_LINE = `${FREE_LABEL} — doesn't use any credits.`;
11428
11454
  var GUEST_LINE = "Guest trial — sign in with GitHub (/login) to unlock daily credits and a comeback bonus.";
11429
11455
  var CONSENT_LINE_1 = "Usage is funded by ads and training. By using free-pi you consent.";
11430
11456
  var CONSENT_LINE_2 = "See /tos and /privacy-policy.";
@@ -11455,7 +11481,7 @@ function truncate2(text, maxWidth) {
11455
11481
  return text.slice(0, maxWidth);
11456
11482
  return `${text.slice(0, maxWidth - 1)}…`;
11457
11483
  }
11458
- function headerLines(theme, modelName, expanded, width = Number.POSITIVE_INFINITY, updateLatest, guest, allowanceLine) {
11484
+ function headerLines(theme, modelName, expanded, width = Number.POSITIVE_INFINITY, updateLatest, guest, allowanceLine, particleFree) {
11459
11485
  const inner = width - 1;
11460
11486
  const fit = (plain, styled) => plain.length <= inner ? styled() : theme.fg("dim", truncate2(plain, inner));
11461
11487
  const titleRest = ` · ${modelName} · ctrl+o for help`;
@@ -11470,6 +11496,7 @@ function headerLines(theme, modelName, expanded, width = Number.POSITIVE_INFINIT
11470
11496
  title,
11471
11497
  "",
11472
11498
  dim(WELCOME_LINE),
11499
+ ...particleFree ? [dim(PARTICLE_LINE)] : [],
11473
11500
  ...guest ? [dim(GUEST_LINE)] : [],
11474
11501
  ...allowanceLine ? [dim(allowanceLine)] : [],
11475
11502
  "",
@@ -11495,7 +11522,9 @@ function createHeaderExtension(opts) {
11495
11522
  let expanded = false;
11496
11523
  return {
11497
11524
  render(width) {
11498
- return headerLines(theme, opts.modelName, expanded, width, opts.updateLatest, opts.guest, opts.allowanceLine);
11525
+ const active = ctx.model?.id;
11526
+ const name = active && opts.modelNameFor?.(active) || opts.modelName;
11527
+ return headerLines(theme, name, expanded, width, opts.updateLatest, opts.guest, opts.allowanceLine, name.includes(FREE_LABEL));
11499
11528
  },
11500
11529
  invalidate() {},
11501
11530
  setExpanded(next) {
@@ -13409,7 +13438,8 @@ function buildRuntimeOptions(opts, sessionId) {
13409
13438
  modelName: resolveModelName(opts),
13410
13439
  updateLatest: opts.updateLatest,
13411
13440
  guest: opts.guest,
13412
- allowanceLine: opts.allowanceLine
13441
+ allowanceLine: opts.allowanceLine,
13442
+ modelNameFor: (id) => catalogModelsFor(opts).find((m) => m.id === id)?.name
13413
13443
  });
13414
13444
  const todoToolExtension = createTodoToolExtension();
13415
13445
  const shellSandbox = opts.shellSandbox ?? createShellSandbox();
@@ -13498,14 +13528,13 @@ patchResumeLine(process.stdout);
13498
13528
  function pickerScopeFor(modelRuntime, opts) {
13499
13529
  const main = resolveFreePiScope(modelRuntime, PROVIDER_NAME, catalogModelsFor(opts).map((m) => m.id));
13500
13530
  const defense = resolveFreePiScope(modelRuntime, DEFENSE_PROVIDER_NAME, defenseModelsFor(opts).map((m) => m.id));
13501
- const fusion = main.filter((s) => s.model.id === FUSION_PICKER_ID);
13502
- const rest = main.filter((s) => !fusion.includes(s));
13503
- const tierOf = new Map((opts.models ?? []).map((m) => [m.id, m.tier]));
13504
- if ((opts.models ?? []).some((m) => m.tier !== undefined)) {
13505
- const rank = (s) => tierOf.get(s.model.id) === "premium" ? 1 : 0;
13506
- return [...fusion, ...rest.filter((s) => rank(s) === 0), ...rest.filter((s) => rank(s) === 1), ...defense];
13507
- }
13508
- return [...fusion, ...defense, ...rest];
13531
+ const all = [...main, ...defense];
13532
+ const nameOf = (s) => s.model.name ?? "";
13533
+ const idOf = (s) => s.model.id;
13534
+ const serverOrder = new Map((opts.models ?? []).map((m, i) => [m.id, i]));
13535
+ const free = all.filter((s) => nameOf(s).includes(FREE_LABEL)).sort((a, b) => (serverOrder.get(idOf(a)) ?? 0) - (serverOrder.get(idOf(b)) ?? 0));
13536
+ const others = all.filter((s) => !free.includes(s)).sort((a, b) => idOf(a).localeCompare(idOf(b)));
13537
+ return [...free, ...others];
13509
13538
  }
13510
13539
  function interactiveModeOptions(opts) {
13511
13540
  return { initialImages: [], initialMessages: [], ...opts.initialMessage ? { initialMessage: opts.initialMessage } : {} };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-pi-cli",
3
- "version": "0.6.12",
3
+ "version": "0.6.14",
4
4
  "description": "Free AI coding agent for your terminal. Ads and a daily free allowance pay for the models; sign in with GitHub and run npx free-pi-cli.",
5
5
  "keywords": [
6
6
  "coding agent",