luxin-cli 0.2.5 → 0.2.6

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/CHANGELOG.md CHANGED
@@ -6,6 +6,23 @@ provenance; this file is the human- and agent-readable release map.
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 0.2.6 - 2026-08-09
10
+
11
+ - Release (trust): `create --guide` now says when it cannot price the request it
12
+ is planning, instead of presenting the model's default-shape quote as the
13
+ planned debit. `selection.planned_debit_source` reports which of the two you
14
+ got, and the unpriceable case carries a warning pointing at the dry-run.
15
+ - This closes a gap that was invisible rather than wrong: the hosted API
16
+ published per-aspect-ratio create debits only when they differed from the
17
+ quote, so an absent field could mean either "the quote already is the debit"
18
+ or "this server is older than your CLI". The npm package and the hosted API
19
+ deploy independently, so that second case is permanent, not a one-off, and it
20
+ under-quoted silently during any deploy gap or rollback. The API now publishes
21
+ the debit for every create-capable model (107 of 107 live rows), so absence
22
+ means exactly one thing, and the CLI now treats it that way.
23
+ - Carries the correction to the 0.2.5 note below: the "known issue" that shipped
24
+ in the 0.2.5 tarball describes behaviour that does not exist.
25
+
9
26
  ## 0.2.5 - 2026-08-09
10
27
 
11
28
  - Release (correctness): `edit --guide` selects a model again. It gated on
@@ -19,12 +36,15 @@ provenance; this file is the human- and agent-readable release map.
19
36
  `selection.suggested_aspect_ratio` read the same unpublished block and
20
37
  returned null on every real video call unless the brief happened to name a
21
38
  ratio.
22
- - Known issue (#2259): `create --guide` can quote a different credit figure than
23
- the `--dry-run` it hands you, because it prices the model's catalog default
24
- shape rather than the ratio the command actually sends. Measured against the
25
- live API: 4 vs 5 with no ratio stated, 4 vs 3 at 16:9. The dry-run figure is
26
- the authoritative one; budget from it, not from the guide. Unchanged from
27
- 0.2.4; the fix landed server-side but not in this package.
39
+ - Correction (added after 0.2.5 shipped): the 0.2.5 tarball carries a "known
40
+ issue" note claiming `create --guide` can quote a different credit figure than
41
+ the `--dry-run` it hands you. **That note is wrong and the behaviour it
42
+ describes does not exist.** It was written from a measurement taken during a
43
+ deploy-skew window, minutes after the fix merged and before the hosted API had
44
+ deployed its half. Measured after both halves landed, the guide and the dry-run
45
+ agree: 5 and 5 with no ratio stated, 3 and 3 at 16:9. #2259 is fixed and
46
+ closed. Budgeting from the dry-run figure remains sound advice, but it is not a
47
+ workaround for anything.
28
48
 
29
49
  ## 0.2.4 - 2026-08-09
30
50
 
package/bin/luxin.mjs CHANGED
@@ -15,7 +15,7 @@ import { Readable } from "node:stream";
15
15
  import { pipeline } from "node:stream/promises";
16
16
  import os from "node:os";
17
17
 
18
- const VERSION = "0.2.5";
18
+ const VERSION = "0.2.6";
19
19
  const PACKAGE_NAME = "luxin";
20
20
  const DEFAULT_API_BASE_URL = "https://api.luxin.sh";
21
21
  const DEFAULT_DOCS_BASE_URL = "https://luxin.sh";
@@ -2007,6 +2007,16 @@ async function createGuide(args, options = {}) {
2007
2007
  defaultedModelParameters.modelParameters,
2008
2008
  pricingContext,
2009
2009
  );
2010
+ // The quote is not the debit, and against a server that does not publish
2011
+ // debits this CLI cannot compute one -- it has no pricing engine, by design.
2012
+ // Say that plainly instead of letting the caller budget against a number the
2013
+ // product does not charge (#2259, #2272).
2014
+ const plannedDebitUnavailable =
2015
+ selected !== null &&
2016
+ createGuideModelSupportsCreate(selected) &&
2017
+ !createGuideSelectedModelRequiresInputImage(selected) &&
2018
+ !createGuideCanPriceModelParameters(selected) &&
2019
+ !createGuideRegistryPublishesCreditDebit(selected);
2010
2020
  const estimatedCredits = pricing?.credits_required ?? null;
2011
2021
  // The guide publishes what the caller will be charged, never our provider
2012
2022
  // cost. `economics.estimated_usd_per_image` is the hosted charge per image.
@@ -2406,6 +2416,9 @@ async function createGuide(args, options = {}) {
2406
2416
  pricing_source: pricing?.pricing_source ?? null,
2407
2417
  model_parameter_defaults_applied:
2408
2418
  defaultedModelParameters.defaultsApplied,
2419
+ planned_debit_source: plannedDebitUnavailable
2420
+ ? "create_credit_debit_unavailable"
2421
+ : "registry_create_credit_debit",
2409
2422
  },
2410
2423
  blocker,
2411
2424
  guide_warning: guideWarning,
@@ -2443,11 +2456,20 @@ async function createGuide(args, options = {}) {
2443
2456
  for (const field of compactOmittedFields) {
2444
2457
  delete guideData[field];
2445
2458
  }
2446
- return createGuideSuccess(command, quota?.envelope.actor ?? null, guideData);
2459
+ return createGuideSuccess(
2460
+ command,
2461
+ quota?.envelope.actor ?? null,
2462
+ guideData,
2463
+ plannedDebitUnavailable
2464
+ ? [
2465
+ "create_credit_debit_unavailable: this hosted API does not publish per-aspect-ratio create debits, so the credits above are the model's default-shape quote and may not be what create debits. Run the dry_run command in escape_hatches for the exact figure before budgeting.",
2466
+ ]
2467
+ : [],
2468
+ );
2447
2469
  }
2448
2470
 
2449
- function createGuideSuccess(command, actor, data) {
2450
- const result = success(command, data);
2471
+ function createGuideSuccess(command, actor, data, warnings = []) {
2472
+ const result = success(command, data, warnings);
2451
2473
  result.envelope.actor = actor;
2452
2474
  return result;
2453
2475
  }
@@ -2968,6 +2990,26 @@ function createGuidePricingForModel(model, modelParameters, context = {}) {
2968
2990
  // this CLI has no pricing engine to recompute it -- so the registry publishes
2969
2991
  // the answer and this reads it. Absent field means the quote already is the
2970
2992
  // debit.
2993
+ // Does this registry response publish create debits at all?
2994
+ //
2995
+ // The hosted API and this CLI ship independently, so a client can always be
2996
+ // talking to a server older than itself. `create_credit_debit_by_aspect_ratio`
2997
+ // is published for EVERY create-capable model precisely so that absence has one
2998
+ // meaning -- "this server cannot tell me the debit" -- rather than being
2999
+ // confusable with "the debit happens to equal the quote". When it is absent the
3000
+ // honest answer is to say so and point at the dry-run, not to present the
3001
+ // model's default-shape quote as the planned debit (#2259, #2272).
3002
+ function createGuideRegistryPublishesCreditDebit(model) {
3003
+ return (
3004
+ isRecord(model?.economics?.create_credit_debit_by_aspect_ratio) ||
3005
+ isRecord(model?.create_credit_debit_by_aspect_ratio)
3006
+ );
3007
+ }
3008
+
3009
+ function createGuideModelSupportsCreate(model) {
3010
+ return Array.isArray(model?.supports) && model.supports.includes("create");
3011
+ }
3012
+
2971
3013
  function createGuideAspectRatioCreditPricing(model, context) {
2972
3014
  // Both shapes: `GET /v1/models` serves the COMPACT summary, which flattens
2973
3015
  // economics onto the row, and only `?details=true` (or a fixture built from
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "luxin-cli",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "Image generation, image editing, video, audio, and image-to-3D for agents, with no API key to obtain first. The agent signs itself up, starts on free preview credits, and gets hosted media URLs, recoverable jobs, and cost receipts.",
5
5
  "type": "module",
6
6
  "private": false,