luxin-cli 0.2.6 → 0.2.8
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 +36 -0
- package/README.md +58 -0
- package/bin/luxin.mjs +180 -18
- package/cli.md +64 -0
- package/commands.json +19 -2
- package/llms.txt +4 -0
- package/package.json +2 -1
- package/skill-core.md +417 -0
- package/skill.md +30 -381
- package/skills/agent-image-generation/SKILL.md +24 -0
- package/skills/ai-audio-generation/SKILL.md +24 -0
- package/skills/ai-image-generation/SKILL.md +24 -0
- package/skills/ai-video-generation/SKILL.md +24 -0
- package/skills/creative-media/SKILL.md +24 -0
- package/skills/image-edit/SKILL.md +24 -0
- package/skills/image-generation/SKILL.md +24 -0
- package/skills/image-skill/SKILL.md +24 -0
- package/skills/image-to-3d/SKILL.md +24 -0
- package/skills/luxin/SKILL.md +30 -381
- package/skills/luxin/references/cli.md +64 -0
- package/skills/luxin/references/commands.json +19 -2
- package/skills/luxin/references/llms.txt +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,42 @@ provenance; this file is the human- and agent-readable release map.
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
## 0.2.8 - 2026-08-12
|
|
10
|
+
|
|
11
|
+
- New command: `luxin skill` prints the full usage guidance from bundled
|
|
12
|
+
package bytes, so instructions always match the CLI you are running. The
|
|
13
|
+
installed SKILL.md is now a ~4KB discovery stub that points here; the full
|
|
14
|
+
body is also served at https://luxin.sh/skill-core.md.
|
|
15
|
+
- Skill freshness handshake: export `LUXIN_SKILL_REVISION=<the revision in
|
|
16
|
+
your stub's frontmatter>` and `create --guide`, `edit --guide`, and
|
|
17
|
+
`luxin skill` will return `data.skill_refresh` with the current revision and
|
|
18
|
+
the exact refresh command (`npx skills update luxin`) whenever your installed
|
|
19
|
+
copy no longer matches. The field is omitted entirely when you are current.
|
|
20
|
+
Nothing ever rewrites your files, config, or hooks — refresh is always an
|
|
21
|
+
explicit command you run.
|
|
22
|
+
- `agent_skill.read_command` now points at `luxin skill --json` instead of
|
|
23
|
+
curling the stub.
|
|
24
|
+
|
|
25
|
+
## 0.2.7 - 2026-08-12
|
|
26
|
+
|
|
27
|
+
- Release (pricing): the guide's local credit quoting for xAI models moved from
|
|
28
|
+
a `startsWith("xai.grok-imagine-image")` prefix test to an explicit model-id
|
|
29
|
+
list. The prefix test would have priced any Grok Imagine model it had never
|
|
30
|
+
heard of off the 1.x table — for the new `xai.grok-imagine-image-2.0` that
|
|
31
|
+
meant quoting 4 credits for a 10-credit create. Models outside the list now
|
|
32
|
+
defer to the hosted registry's published debit instead of guessing.
|
|
33
|
+
- Adds the `xai.grok-imagine-image-2.0` quality×resolution credit matrix to
|
|
34
|
+
local guide pricing (low/1k through medium/2k), matching the registry the
|
|
35
|
+
hosted API serves since 2026-08-12. Every tier was verified against live
|
|
36
|
+
provider billing before release ($0.04/$0.06/$0.07/$0.08 receipts).
|
|
37
|
+
- The registry behind `models show` grew from 290 to 316 models server-side
|
|
38
|
+
(grok-imagine-image-2.0 create+edit executable and listed; 24 summer-wave
|
|
39
|
+
fal models cataloged with honest tier pricing before they are wired —
|
|
40
|
+
reachable via `models show MODEL_ID`, not yet in the `models list` output,
|
|
41
|
+
which serves executable models only). No CLI change was needed for that —
|
|
42
|
+
noted here because agents read this file to decide whether to upgrade:
|
|
43
|
+
upgrade for the pricing fix, not for model availability.
|
|
44
|
+
|
|
9
45
|
## 0.2.6 - 2026-08-09
|
|
10
46
|
|
|
11
47
|
- Release (trust): `create --guide` now says when it cannot price the request it
|
package/README.md
CHANGED
|
@@ -85,9 +85,67 @@ Naming note: Luxin is a creative-media runtime for agents. It is unrelated to
|
|
|
85
85
|
`luxon`, the datetime library; the npm package here is `luxin-cli` and the
|
|
86
86
|
installed binary is `luxin`.
|
|
87
87
|
|
|
88
|
+
## Keeping The Skill Current
|
|
89
|
+
|
|
90
|
+
The installed `SKILL.md` is a ~4KB discovery stub. Everything volatile — flags,
|
|
91
|
+
workflows, recovery, funding — lives in the guidance the CLI itself carries, so
|
|
92
|
+
it always matches the code you are running:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npm_config_update_notifier=false npx -y luxin-cli@latest skill
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Refresh the installed stub with the standard verb:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npx skills update luxin
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The stub records its own identity as `metadata.skill_revision`. Export it and
|
|
105
|
+
the CLI will say when your copy no longer matches the guidance it ships,
|
|
106
|
+
returning `data.skill_refresh` plus one warning line on `luxin skill` and
|
|
107
|
+
`create --guide`:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
export LUXIN_SKILL_REVISION=<metadata.skill_revision from your installed SKILL.md>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Detection is remote; mutation stays local and explicit. Luxin prints the refresh
|
|
114
|
+
command and never rewrites your skill files, agent config, or hook files.
|
|
115
|
+
|
|
116
|
+
### Optional: refresh at session start (copy-paste, opt-in)
|
|
117
|
+
|
|
118
|
+
Some runtimes can run a command when a session starts. If you want an automatic
|
|
119
|
+
refresh, add it yourself — Luxin will not install it for you, and nothing below
|
|
120
|
+
runs unless you put it there. For Claude Code, in `.claude/settings.json`:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"hooks": {
|
|
125
|
+
"SessionStart": [
|
|
126
|
+
{
|
|
127
|
+
"hooks": [
|
|
128
|
+
{
|
|
129
|
+
"type": "command",
|
|
130
|
+
"command": "npx skills update luxin",
|
|
131
|
+
"timeout": 60
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Two things worth knowing before you adopt it: it adds a network call to every
|
|
141
|
+
session start, and it applies updates without showing you a diff first. Running
|
|
142
|
+
`npx skills update luxin` by hand when a nudge appears keeps the change
|
|
143
|
+
reviewable.
|
|
144
|
+
|
|
88
145
|
Agent-facing contracts:
|
|
89
146
|
|
|
90
147
|
- [Hosted skill contract](https://luxin.sh/skill.md)
|
|
148
|
+
- [Hosted skill guidance](https://luxin.sh/skill-core.md)
|
|
91
149
|
- [Hosted LLM contract](https://luxin.sh/llms.txt)
|
|
92
150
|
- [Hosted CLI contract](https://luxin.sh/cli.md)
|
|
93
151
|
- [Public repo skill source](https://github.com/danielgwilson/luxin/tree/main/skills/luxin)
|
package/bin/luxin.mjs
CHANGED
|
@@ -15,7 +15,20 @@ 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.
|
|
18
|
+
const VERSION = "0.2.8";
|
|
19
|
+
// Content-derived identity of the guidance this package ships (#2302). Kept in
|
|
20
|
+
// sync with docs/public-contract/skill.md by `pnpm skill-revision:write` and
|
|
21
|
+
// gated by `pnpm skill-revision:check`; the mirror cannot import from src/.
|
|
22
|
+
const SKILL_REVISION = "b1dc1284d18d";
|
|
23
|
+
// `luxin skill` prints these bundled bytes rather than fetching them, so the
|
|
24
|
+
// guidance can never describe a CLI other than the one printing it. Packed by
|
|
25
|
+
// public-cli/package.json `files`.
|
|
26
|
+
const SKILL_GUIDANCE_FILE = "skill-core.md";
|
|
27
|
+
const SKILL_GUIDANCE_SCHEMA = "image-skill.skill-guidance.v1";
|
|
28
|
+
const SKILL_CORE_URL = "https://luxin.sh/skill-core.md";
|
|
29
|
+
const SKILL_REFRESH_COMMAND = "npx skills update luxin";
|
|
30
|
+
const INSTALLED_SKILL_REVISION_ENV = "LUXIN_SKILL_REVISION";
|
|
31
|
+
const INSTALLED_SKILL_REVISION_HEADER = "x-luxin-skill-revision";
|
|
19
32
|
const PACKAGE_NAME = "luxin";
|
|
20
33
|
const DEFAULT_API_BASE_URL = "https://api.luxin.sh";
|
|
21
34
|
const DEFAULT_DOCS_BASE_URL = "https://luxin.sh";
|
|
@@ -101,12 +114,28 @@ const ACCEPTED_PUBLIC_MEDIA_HOSTS = [
|
|
|
101
114
|
// price. These are prices, not costs: the CLI never computes or publishes
|
|
102
115
|
// provider cost or margin.
|
|
103
116
|
const XAI_IMAGE_CREDIT_PRICES = {
|
|
104
|
-
source_image: { standard: 1 / 3, quality: 5 / 3 },
|
|
117
|
+
source_image: { standard: 1 / 3, quality: 5 / 3, image_2: 5 / 3 },
|
|
105
118
|
output_image: {
|
|
106
119
|
standard: 10 / 3,
|
|
107
120
|
quality: { "1k": 25 / 3, "2k": 35 / 3 },
|
|
121
|
+
image_2: {
|
|
122
|
+
low: { "1k": 20 / 3, "2k": 10 },
|
|
123
|
+
medium: { "1k": 10, "2k": 40 / 3 },
|
|
124
|
+
},
|
|
108
125
|
},
|
|
109
126
|
};
|
|
127
|
+
// Mirrors src/credit-pricing.ts XAI_IMAGE_MODEL_IDS. This is an explicit list,
|
|
128
|
+
// not a prefix test: a Grok Imagine image model this CLI has never heard of is
|
|
129
|
+
// priced by the hosted registry's published debit, not by guessing it onto the
|
|
130
|
+
// 1.x price table.
|
|
131
|
+
const XAI_LOCALLY_PRICED_IMAGE_MODEL_IDS = new Set([
|
|
132
|
+
"xai.grok-imagine-image",
|
|
133
|
+
"xai.grok-imagine-image-edit",
|
|
134
|
+
"xai.grok-imagine-image-quality",
|
|
135
|
+
"xai.grok-imagine-image-quality-edit",
|
|
136
|
+
"xai.grok-imagine-image-2.0",
|
|
137
|
+
"xai.grok-imagine-image-2.0-edit",
|
|
138
|
+
]);
|
|
110
139
|
const MODALITY_COMMAND_ALIASES = new Map([
|
|
111
140
|
["image", { command: "create", intent: null }],
|
|
112
141
|
["video", { command: "create", intent: "video" }],
|
|
@@ -318,7 +347,8 @@ function agentSkillHint(commandPrefix = "luxin") {
|
|
|
318
347
|
url: AGENT_SKILL_URL,
|
|
319
348
|
llms_url: AGENT_LLMS_URL,
|
|
320
349
|
cli_docs_url: AGENT_CLI_DOCS_URL,
|
|
321
|
-
|
|
350
|
+
// #2302: point at the CLI-carried guidance, not the discovery stub.
|
|
351
|
+
read_command: "luxin skill --json",
|
|
322
352
|
recommended_start_command: renderGuidePrefixedCommand(
|
|
323
353
|
commandPrefix,
|
|
324
354
|
"create --guide --prompt PROMPT --json",
|
|
@@ -371,6 +401,8 @@ async function main(rawArgv) {
|
|
|
371
401
|
return await doctor(rest);
|
|
372
402
|
case "trust":
|
|
373
403
|
return await trust(rest);
|
|
404
|
+
case "skill":
|
|
405
|
+
return await skill(rest);
|
|
374
406
|
case "signup":
|
|
375
407
|
return await signup(rest);
|
|
376
408
|
case "claim":
|
|
@@ -487,12 +519,13 @@ function commandHelpByKey(key) {
|
|
|
487
519
|
"": {
|
|
488
520
|
command: "help",
|
|
489
521
|
usage:
|
|
490
|
-
"luxin <doctor|trust|signup|claim|whoami|usage|quota|credits|capabilities|models|create|upload|edit|assets|jobs|activity|feedback> --json",
|
|
522
|
+
"luxin <doctor|trust|skill|signup|claim|whoami|usage|quota|credits|capabilities|models|create|upload|edit|assets|jobs|activity|feedback> --json",
|
|
491
523
|
docs_url: "https://luxin.sh/cli.md",
|
|
492
524
|
agent_skill: agentSkillHint(),
|
|
493
525
|
commands: [
|
|
494
526
|
"doctor",
|
|
495
527
|
"trust",
|
|
528
|
+
"skill",
|
|
496
529
|
"signup --agent --agent-name NAME --runtime RUNTIME",
|
|
497
530
|
"claim request --contact INBOX",
|
|
498
531
|
"claim code",
|
|
@@ -544,6 +577,13 @@ function commandHelpByKey(key) {
|
|
|
544
577
|
description:
|
|
545
578
|
"Return npm provenance, hosted contract hashes, API health, and model availability evidence.",
|
|
546
579
|
},
|
|
580
|
+
skill: {
|
|
581
|
+
command: "luxin skill help",
|
|
582
|
+
usage: "luxin skill --json",
|
|
583
|
+
docs_url: "https://luxin.sh/cli.md#luxin-skill",
|
|
584
|
+
description:
|
|
585
|
+
"Print the full agent guidance bundled with this CLI version, so instructions always match the installed code. No network call, no auth, no spend.",
|
|
586
|
+
},
|
|
547
587
|
signup: {
|
|
548
588
|
command: "luxin signup help",
|
|
549
589
|
usage: "luxin signup --agent --agent-name NAME --runtime RUNTIME --json",
|
|
@@ -864,6 +904,104 @@ function unsupportedFlagsMessage(command, flags) {
|
|
|
864
904
|
.join(", ")}`;
|
|
865
905
|
}
|
|
866
906
|
|
|
907
|
+
// #2302: the installed SKILL.md is a ~4KB discovery stub. Everything volatile
|
|
908
|
+
// -- flags, workflows, recovery, funding -- lives in the guidance body this
|
|
909
|
+
// command prints, so an agent working from a months-old install still reads
|
|
910
|
+
// instructions that match the code it is about to run.
|
|
911
|
+
//
|
|
912
|
+
// Bundled, not fetched. A network fetch could serve prose this build does not
|
|
913
|
+
// implement, which is the drift the split exists to remove.
|
|
914
|
+
async function skill(argv) {
|
|
915
|
+
const args = parseArgs(argv);
|
|
916
|
+
const unsupportedFlags = [...args.flags.keys()].filter(
|
|
917
|
+
(flag) => !["json"].includes(flag),
|
|
918
|
+
);
|
|
919
|
+
if (args.positionals.length > 0 || unsupportedFlags.length > 0) {
|
|
920
|
+
return invalid(
|
|
921
|
+
"luxin skill",
|
|
922
|
+
unsupportedFlags.length > 0
|
|
923
|
+
? unsupportedFlagsMessage("skill", unsupportedFlags)
|
|
924
|
+
: "skill does not accept positional arguments",
|
|
925
|
+
);
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
let content;
|
|
929
|
+
try {
|
|
930
|
+
content = await readFile(
|
|
931
|
+
new URL(`../${SKILL_GUIDANCE_FILE}`, import.meta.url),
|
|
932
|
+
"utf8",
|
|
933
|
+
);
|
|
934
|
+
} catch (error) {
|
|
935
|
+
return failure(
|
|
936
|
+
"luxin skill",
|
|
937
|
+
7,
|
|
938
|
+
"SKILL_GUIDANCE_UNAVAILABLE",
|
|
939
|
+
`bundled skill guidance could not be read: ${
|
|
940
|
+
error instanceof Error ? error.message : "unknown error"
|
|
941
|
+
}. Reinstall the CLI, or read ${SKILL_CORE_URL}`,
|
|
942
|
+
false,
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
const refresh = skillRefresh();
|
|
947
|
+
return success(
|
|
948
|
+
"luxin skill",
|
|
949
|
+
{
|
|
950
|
+
schema: SKILL_GUIDANCE_SCHEMA,
|
|
951
|
+
revision: SKILL_REVISION,
|
|
952
|
+
source: "bundled_cli_package",
|
|
953
|
+
format: "markdown",
|
|
954
|
+
bytes: Buffer.byteLength(content, "utf8"),
|
|
955
|
+
canonical_url: SKILL_CORE_URL,
|
|
956
|
+
refresh_command: SKILL_REFRESH_COMMAND,
|
|
957
|
+
mutation: {
|
|
958
|
+
provider_call: false,
|
|
959
|
+
credit_debit: false,
|
|
960
|
+
media_write: false,
|
|
961
|
+
local_file_write: false,
|
|
962
|
+
},
|
|
963
|
+
...(refresh === null ? {} : { skill_refresh: refresh }),
|
|
964
|
+
content,
|
|
965
|
+
},
|
|
966
|
+
refresh === null ? [] : [skillRefreshWarning(refresh)],
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/**
|
|
971
|
+
* Self-reported identity of the caller's installed skill copy. 12 lowercase hex
|
|
972
|
+
* or nothing: the value is echoed into a response field and forwarded as a
|
|
973
|
+
* header, so it must not become a channel for arbitrary text.
|
|
974
|
+
*/
|
|
975
|
+
function installedSkillRevision() {
|
|
976
|
+
const raw = process.env[INSTALLED_SKILL_REVISION_ENV];
|
|
977
|
+
if (typeof raw !== "string") {
|
|
978
|
+
return null;
|
|
979
|
+
}
|
|
980
|
+
const trimmed = raw.trim().toLowerCase();
|
|
981
|
+
return /^[0-9a-f]{12}$/.test(trimmed) ? trimmed : null;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
/**
|
|
985
|
+
* The compact nudge, or nothing at all. Omitted when the caller reports nothing
|
|
986
|
+
* or reports the revision this CLI ships. Content hashes are unordered, so this
|
|
987
|
+
* says "differs", never "older".
|
|
988
|
+
*/
|
|
989
|
+
function skillRefresh() {
|
|
990
|
+
const installed = installedSkillRevision();
|
|
991
|
+
if (installed === null || installed === SKILL_REVISION) {
|
|
992
|
+
return null;
|
|
993
|
+
}
|
|
994
|
+
return {
|
|
995
|
+
installed_revision: installed,
|
|
996
|
+
current_revision: SKILL_REVISION,
|
|
997
|
+
refresh_command: SKILL_REFRESH_COMMAND,
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
function skillRefreshWarning(refresh) {
|
|
1002
|
+
return `installed skill revision ${refresh.installed_revision} does not match the current revision ${refresh.current_revision} this CLI ships; refresh with: ${refresh.refresh_command}`;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
867
1005
|
async function trust(argv) {
|
|
868
1006
|
const args = parseArgs(argv);
|
|
869
1007
|
const unsupportedFlags = [...args.flags.keys()].filter(
|
|
@@ -2326,6 +2464,7 @@ async function createGuide(args, options = {}) {
|
|
|
2326
2464
|
},
|
|
2327
2465
|
),
|
|
2328
2466
|
};
|
|
2467
|
+
const guideSkillRefresh = skillRefresh();
|
|
2329
2468
|
const guideData = {
|
|
2330
2469
|
schema:
|
|
2331
2470
|
guideOperation === "edit"
|
|
@@ -2452,20 +2591,25 @@ async function createGuide(args, options = {}) {
|
|
|
2452
2591
|
credit_debit: false,
|
|
2453
2592
|
media_write: false,
|
|
2454
2593
|
},
|
|
2594
|
+
// #2302: present only when the caller self-reported a revision that is not
|
|
2595
|
+
// the one this CLI ships. Survives ready_compact deliberately -- a nudge
|
|
2596
|
+
// that only appears in the blocked stages would never reach the agents who
|
|
2597
|
+
// are working fine on stale instructions, which is the whole failure mode.
|
|
2598
|
+
...(guideSkillRefresh === null ? {} : { skill_refresh: guideSkillRefresh }),
|
|
2455
2599
|
};
|
|
2456
2600
|
for (const field of compactOmittedFields) {
|
|
2457
2601
|
delete guideData[field];
|
|
2458
2602
|
}
|
|
2459
|
-
return createGuideSuccess(
|
|
2460
|
-
|
|
2461
|
-
quota?.envelope.actor ?? null,
|
|
2462
|
-
guideData,
|
|
2463
|
-
plannedDebitUnavailable
|
|
2603
|
+
return createGuideSuccess(command, quota?.envelope.actor ?? null, guideData, [
|
|
2604
|
+
...(plannedDebitUnavailable
|
|
2464
2605
|
? [
|
|
2465
2606
|
"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
2607
|
]
|
|
2467
|
-
: [],
|
|
2468
|
-
|
|
2608
|
+
: []),
|
|
2609
|
+
...(guideSkillRefresh === null
|
|
2610
|
+
? []
|
|
2611
|
+
: [skillRefreshWarning(guideSkillRefresh)]),
|
|
2612
|
+
]);
|
|
2469
2613
|
}
|
|
2470
2614
|
|
|
2471
2615
|
function createGuideSuccess(command, actor, data, warnings = []) {
|
|
@@ -3039,14 +3183,16 @@ function createGuideAspectRatioCreditPricing(model, context) {
|
|
|
3039
3183
|
}
|
|
3040
3184
|
|
|
3041
3185
|
function createGuideCanPriceModelParameters(model) {
|
|
3042
|
-
return String(model?.id ?? "")
|
|
3186
|
+
return XAI_LOCALLY_PRICED_IMAGE_MODEL_IDS.has(String(model?.id ?? ""));
|
|
3043
3187
|
}
|
|
3044
3188
|
|
|
3045
3189
|
function createGuideXaiImagePricing(model, modelParameters, context) {
|
|
3046
3190
|
const modelId = String(model?.id ?? "");
|
|
3047
3191
|
const quality = modelId.includes("-quality");
|
|
3192
|
+
const image2 = modelId.startsWith("xai.grok-imagine-image-2.0");
|
|
3048
3193
|
const edit = modelId.endsWith("-edit");
|
|
3049
3194
|
const resolution = modelParameters?.resolution === "2k" ? "2k" : "1k";
|
|
3195
|
+
const image2Quality = modelParameters?.quality === "low" ? "low" : "medium";
|
|
3050
3196
|
const outputImageCount =
|
|
3051
3197
|
Number.isInteger(context?.outputCount) && context.outputCount > 0
|
|
3052
3198
|
? context.outputCount
|
|
@@ -3057,12 +3203,16 @@ function createGuideXaiImagePricing(model, modelParameters, context) {
|
|
|
3057
3203
|
? context.referenceAssetCount
|
|
3058
3204
|
: 0;
|
|
3059
3205
|
const sourceImageCount = edit ? 1 + referenceAssetCount : 0;
|
|
3060
|
-
const sourceCredits =
|
|
3061
|
-
? XAI_IMAGE_CREDIT_PRICES.source_image.
|
|
3062
|
-
:
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3206
|
+
const sourceCredits = image2
|
|
3207
|
+
? XAI_IMAGE_CREDIT_PRICES.source_image.image_2
|
|
3208
|
+
: quality
|
|
3209
|
+
? XAI_IMAGE_CREDIT_PRICES.source_image.quality
|
|
3210
|
+
: XAI_IMAGE_CREDIT_PRICES.source_image.standard;
|
|
3211
|
+
const outputCredits = image2
|
|
3212
|
+
? XAI_IMAGE_CREDIT_PRICES.output_image.image_2[image2Quality][resolution]
|
|
3213
|
+
: quality
|
|
3214
|
+
? XAI_IMAGE_CREDIT_PRICES.output_image.quality[resolution]
|
|
3215
|
+
: XAI_IMAGE_CREDIT_PRICES.output_image.standard;
|
|
3066
3216
|
const creditsRequired = Math.max(
|
|
3067
3217
|
1,
|
|
3068
3218
|
Math.ceil(
|
|
@@ -3075,8 +3225,14 @@ function createGuideXaiImagePricing(model, modelParameters, context) {
|
|
|
3075
3225
|
modelParameters?.resolution === undefined ||
|
|
3076
3226
|
modelParameters?.resolution === null ||
|
|
3077
3227
|
modelParameters?.resolution === "1k";
|
|
3228
|
+
const defaultQuality =
|
|
3229
|
+
!image2 ||
|
|
3230
|
+
modelParameters?.quality === undefined ||
|
|
3231
|
+
modelParameters?.quality === null ||
|
|
3232
|
+
modelParameters?.quality === "medium";
|
|
3078
3233
|
const defaultShape =
|
|
3079
3234
|
defaultResolution &&
|
|
3235
|
+
defaultQuality &&
|
|
3080
3236
|
outputImageCount === 1 &&
|
|
3081
3237
|
sourceImageCount === (edit ? 1 : 0);
|
|
3082
3238
|
return {
|
|
@@ -6841,6 +6997,12 @@ async function apiRequest(input) {
|
|
|
6841
6997
|
...(input.token === undefined
|
|
6842
6998
|
? {}
|
|
6843
6999
|
: { authorization: `Bearer ${input.token}` }),
|
|
7000
|
+
// #2302: self-reported identity of the installed skill copy, so the
|
|
7001
|
+
// hosted side can measure how stale the installed base is. Non-secret,
|
|
7002
|
+
// omitted entirely when unset, never guessed.
|
|
7003
|
+
...(installedSkillRevision() === null
|
|
7004
|
+
? {}
|
|
7005
|
+
: { [INSTALLED_SKILL_REVISION_HEADER]: installedSkillRevision() }),
|
|
6844
7006
|
},
|
|
6845
7007
|
body: input.body === undefined ? undefined : JSON.stringify(input.body),
|
|
6846
7008
|
});
|
package/cli.md
CHANGED
|
@@ -93,6 +93,63 @@ verified, the command still returns a packet with explicit `unreachable`,
|
|
|
93
93
|
`not_available_yet`, `inspect_only`, or `stale_or_mismatched` states rather
|
|
94
94
|
than omitting the field.
|
|
95
95
|
|
|
96
|
+
### `luxin skill`
|
|
97
|
+
|
|
98
|
+
Prints the full agent guidance that shipped with this CLI version.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
luxin skill --json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The published `SKILL.md` at `https://luxin.sh/skill.md` is a ~4KB discovery
|
|
105
|
+
stub: it carries identity, the first command, the safety invariants, and a
|
|
106
|
+
revision, and nothing else. Flags, workflows, model parameters, recovery, and
|
|
107
|
+
funding details live here, because an installed skill file is a snapshot that
|
|
108
|
+
never updates while `npx luxin-cli@latest` updates on every call.
|
|
109
|
+
|
|
110
|
+
The body is read from the package this command is running from, not fetched, so
|
|
111
|
+
the guidance always matches the installed code by construction. No network call,
|
|
112
|
+
no auth, no spend. The same bytes are served at
|
|
113
|
+
`https://luxin.sh/skill-core.md`.
|
|
114
|
+
|
|
115
|
+
`data` uses `schema: "image-skill.skill-guidance.v1"` and carries `revision`
|
|
116
|
+
(the 12-hex content-derived identity of the published skill), `source`,
|
|
117
|
+
`format`, `bytes`, `canonical_url`, `refresh_command`, `mutation`, and
|
|
118
|
+
`content`.
|
|
119
|
+
|
|
120
|
+
#### Skill revision and staleness
|
|
121
|
+
|
|
122
|
+
An installed skill file records its revision as `metadata.skill_revision` in its
|
|
123
|
+
frontmatter. Export it so the CLI can tell you when your copy has fallen behind
|
|
124
|
+
the guidance the CLI ships:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
export LUXIN_SKILL_REVISION=<metadata.skill_revision from your installed SKILL.md>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
When the value differs from what the running CLI ships, `luxin skill` and
|
|
131
|
+
`create --guide` / `edit --guide` add `data.skill_refresh`:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"skill_refresh": {
|
|
136
|
+
"installed_revision": "0123456789ab",
|
|
137
|
+
"current_revision": "b1dc1284d18d",
|
|
138
|
+
"refresh_command": "npx skills update luxin"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
They also emit one warning line naming the same command. When the revisions
|
|
144
|
+
match, or when `LUXIN_SKILL_REVISION` is unset, the field is omitted entirely.
|
|
145
|
+
|
|
146
|
+
Refreshing is always a command you choose to run. Luxin never rewrites your
|
|
147
|
+
skill files, agent config, or hooks, and never fetches instructions to follow
|
|
148
|
+
them. The revision is also forwarded to the hosted API as a non-secret
|
|
149
|
+
`x-luxin-skill-revision` header and published unauthenticated on
|
|
150
|
+
`GET /healthz` as `skill_revision`, so a client can compare without downloading
|
|
151
|
+
any contract file.
|
|
152
|
+
|
|
96
153
|
### `luxin signup --agent`
|
|
97
154
|
|
|
98
155
|
Bootstraps restricted agent access. Signup is anonymous by default: no contact
|
|
@@ -280,6 +337,13 @@ recommended (`data.self_fund_preparation.recommended` is `true`), the
|
|
|
280
337
|
`data.self_fund_*` fields stay in the compact response and are not listed in
|
|
281
338
|
`data.output_mode.omitted_fields`.
|
|
282
339
|
|
|
340
|
+
`data.skill_refresh` is the other field that survives the compact response, for
|
|
341
|
+
the same reason: an agent whose installed skill file has gone stale is usually
|
|
342
|
+
an agent whose calls are otherwise succeeding. It appears only when
|
|
343
|
+
`LUXIN_SKILL_REVISION` is exported and differs from the revision the running CLI
|
|
344
|
+
ships, and carries `installed_revision`, `current_revision`, and
|
|
345
|
+
`refresh_command`. See [`luxin skill`](#luxin-skill) for the full handshake.
|
|
346
|
+
|
|
283
347
|
```bash
|
|
284
348
|
IMAGE_SKILL_DISCOVERY_SOURCE=cli-md luxin create --guide --prompt "a compact field camera on a stainless workbench"
|
|
285
349
|
```
|
package/commands.json
CHANGED
|
@@ -20,6 +20,13 @@
|
|
|
20
20
|
"mutation": false,
|
|
21
21
|
"spend": false
|
|
22
22
|
},
|
|
23
|
+
{
|
|
24
|
+
"id": "skill",
|
|
25
|
+
"docs_anchor": "luxin-skill",
|
|
26
|
+
"surface": "client",
|
|
27
|
+
"mutation": false,
|
|
28
|
+
"spend": false
|
|
29
|
+
},
|
|
23
30
|
{
|
|
24
31
|
"id": "signup",
|
|
25
32
|
"docs_anchor": "luxin-signup-agent",
|
|
@@ -148,13 +155,13 @@
|
|
|
148
155
|
"key": "",
|
|
149
156
|
"help": {
|
|
150
157
|
"command": "help",
|
|
151
|
-
"usage": "luxin <doctor|trust|signup|claim|whoami|usage|quota|credits|capabilities|models|create|upload|edit|assets|jobs|activity|feedback> --json",
|
|
158
|
+
"usage": "luxin <doctor|trust|skill|signup|claim|whoami|usage|quota|credits|capabilities|models|create|upload|edit|assets|jobs|activity|feedback> --json",
|
|
152
159
|
"docs_url": "https://luxin.sh/cli.md",
|
|
153
160
|
"agent_skill": {
|
|
154
161
|
"url": "https://luxin.sh/skill.md",
|
|
155
162
|
"llms_url": "https://luxin.sh/llms.txt",
|
|
156
163
|
"cli_docs_url": "https://luxin.sh/cli.md",
|
|
157
|
-
"read_command": "
|
|
164
|
+
"read_command": "luxin skill --json",
|
|
158
165
|
"recommended_start_command": "luxin create --guide --prompt PROMPT --json",
|
|
159
166
|
"model_discovery_command": "luxin models list --available --operation image.generate --json",
|
|
160
167
|
"model_inspection_command": "luxin models show MODEL_ID --json",
|
|
@@ -164,6 +171,7 @@
|
|
|
164
171
|
"commands": [
|
|
165
172
|
"doctor",
|
|
166
173
|
"trust",
|
|
174
|
+
"skill",
|
|
167
175
|
"signup --agent --agent-name NAME --runtime RUNTIME",
|
|
168
176
|
"claim request --contact INBOX",
|
|
169
177
|
"claim code",
|
|
@@ -220,6 +228,15 @@
|
|
|
220
228
|
"description": "Return npm provenance, hosted contract hashes, API health, and model availability evidence."
|
|
221
229
|
}
|
|
222
230
|
},
|
|
231
|
+
{
|
|
232
|
+
"key": "skill",
|
|
233
|
+
"help": {
|
|
234
|
+
"command": "luxin skill help",
|
|
235
|
+
"usage": "luxin skill --json",
|
|
236
|
+
"docs_url": "https://luxin.sh/cli.md#luxin-skill",
|
|
237
|
+
"description": "Print the full agent guidance bundled with this CLI version, so instructions always match the installed code. No network call, no auth, no spend."
|
|
238
|
+
}
|
|
239
|
+
},
|
|
223
240
|
{
|
|
224
241
|
"key": "signup",
|
|
225
242
|
"help": {
|
package/llms.txt
CHANGED
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
Status: live preview hosted-product contract
|
|
4
4
|
Canonical homepage: https://luxin.sh
|
|
5
5
|
Canonical skill URL: https://luxin.sh/skill.md
|
|
6
|
+
Canonical skill guidance URL: https://luxin.sh/skill-core.md
|
|
6
7
|
Canonical LLM URL: https://luxin.sh/llms.txt
|
|
7
8
|
Canonical CLI URL: https://luxin.sh/cli.md
|
|
8
9
|
Canonical hosted API URL: https://api.luxin.sh
|
|
9
10
|
|
|
11
|
+
Skill freshness:
|
|
12
|
+
https://luxin.sh/skill.md is a ~4KB discovery stub carrying identity, the first command, the safety invariants, and metadata.skill_revision. The full guidance is https://luxin.sh/skill-core.md, and `luxin skill --json` prints those same bytes from the installed package, so guidance always matches the running CLI. Export LUXIN_SKILL_REVISION=<metadata.skill_revision of your installed copy>: when it differs from what the CLI ships, `luxin skill` and `create --guide` return data.skill_refresh with installed_revision, current_revision, and refresh_command `npx skills update luxin`, plus one warning line. When it matches or is unset the field is omitted. Refreshing is a command you run; Luxin never rewrites skill files, agent config, or hooks. GET https://api.luxin.sh/healthz publishes the current skill_revision unauthenticated.
|
|
13
|
+
|
|
10
14
|
Purpose:
|
|
11
15
|
Luxin is zero-setup creative media for agents: no provider API key, no OAuth, no install to manage, and no per-provider billing account. Agents start with the hosted guide, follow one next command, and use one thin CLI/client and API to generate and edit images, generate video and audio (music, sound), and create 3D assets (image-to-3D mesh, glb), get durable owned media URLs, recover jobs, inspect models, cap spend, pay through credits (browserless agent x402 when returned available; Stripe Checkout human handoff as fallback), and leave feedback. If the guide needs restricted agent signup before first media, it returns that command explicitly.
|
|
12
16
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "luxin-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
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,
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"CONTRIBUTING.md",
|
|
22
22
|
"CODE_OF_CONDUCT.md",
|
|
23
23
|
"skill.md",
|
|
24
|
+
"skill-core.md",
|
|
24
25
|
"llms.txt",
|
|
25
26
|
"cli.md",
|
|
26
27
|
"commands.json",
|