layer 1.0.4__tar.gz → 1.0.6__tar.gz

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.
Files changed (28) hide show
  1. {layer-1.0.4 → layer-1.0.6}/PKG-INFO +44 -5
  2. layer-1.0.6/README.md +108 -0
  3. {layer-1.0.4 → layer-1.0.6}/pyproject.toml +1 -1
  4. {layer-1.0.4 → layer-1.0.6}/pyproject.toml.orig +1 -1
  5. {layer-1.0.4 → layer-1.0.6}/src/layer/_api/models.py +134 -0
  6. layer-1.0.4/README.md +0 -69
  7. {layer-1.0.4 → layer-1.0.6}/src/layer/__init__.py +0 -0
  8. {layer-1.0.4 → layer-1.0.6}/src/layer/__main__.py +0 -0
  9. {layer-1.0.4 → layer-1.0.6}/src/layer/_api/__init__.py +0 -0
  10. {layer-1.0.4 → layer-1.0.6}/src/layer/_api/client.py +0 -0
  11. {layer-1.0.4 → layer-1.0.6}/src/layer/_cli/__init__.py +0 -0
  12. {layer-1.0.4 → layer-1.0.6}/src/layer/_cli/auth_commands.py +0 -0
  13. {layer-1.0.4 → layer-1.0.6}/src/layer/_cli/base_model_commands.py +0 -0
  14. {layer-1.0.4 → layer-1.0.6}/src/layer/_cli/context.py +0 -0
  15. {layer-1.0.4 → layer-1.0.6}/src/layer/_cli/context_commands.py +0 -0
  16. {layer-1.0.4 → layer-1.0.6}/src/layer/_cli/generate_commands.py +0 -0
  17. {layer-1.0.4 → layer-1.0.6}/src/layer/_cli/main.py +0 -0
  18. {layer-1.0.4 → layer-1.0.6}/src/layer/_cli/output.py +0 -0
  19. {layer-1.0.4 → layer-1.0.6}/src/layer/_cli/workspaces.py +0 -0
  20. {layer-1.0.4 → layer-1.0.6}/src/layer/auth.py +0 -0
  21. {layer-1.0.4 → layer-1.0.6}/src/layer/catalog.py +0 -0
  22. {layer-1.0.4 → layer-1.0.6}/src/layer/config.py +0 -0
  23. {layer-1.0.4 → layer-1.0.6}/src/layer/credentials.py +0 -0
  24. {layer-1.0.4 → layer-1.0.6}/src/layer/download.py +0 -0
  25. {layer-1.0.4 → layer-1.0.6}/src/layer/exit_codes.py +0 -0
  26. {layer-1.0.4 → layer-1.0.6}/src/layer/generate.py +0 -0
  27. {layer-1.0.4 → layer-1.0.6}/src/layer/oauth.py +0 -0
  28. {layer-1.0.4 → layer-1.0.6}/src/layer/params.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: layer
3
- Version: 1.0.4
3
+ Version: 1.0.6
4
4
  Summary: Command-line interface for Layer — AI asset generation for game studios.
5
5
  Keywords: layer,ai,generative,game-development,cli
6
6
  Author: Layer
@@ -28,15 +28,18 @@ Description-Content-Type: text/markdown
28
28
 
29
29
  Command-line interface for [Layer](https://layer.ai) — AI asset generation for game studios.
30
30
 
31
- > **Pre-release.** This is an early build of the rewritten CLI. Asset generation is
32
- > landing next; today it covers signing in and choosing a workspace.
31
+ Reaches the same models, workspaces, and Creative Unit balance as the app, from a
32
+ terminal, a Makefile, or a CI job.
33
33
 
34
34
  ## Install
35
35
 
36
36
  ```sh
37
- uv tool install --prerelease=allow layer # or: pipx install --pip-args=--pre layer
37
+ uv tool install layer # or: pipx install layer
38
38
  ```
39
39
 
40
+ Python 3.10 and up — deliberately older than the services that build it, so the same
41
+ package imports inside Blender, Maya, and Houdini.
42
+
40
43
  Working on the CLI itself? Install it from your checkout instead, so the `layer`
41
44
  command follows the branch you have out:
42
45
 
@@ -56,6 +59,36 @@ layer use my-studio
56
59
  For CI and other unattended runs, set `LAYER_API_KEY` to a personal access token instead
57
60
  of signing in.
58
61
 
62
+ ## Generate
63
+
64
+ ```sh
65
+ layer generate image -p "a crystal sword icon, transparent background"
66
+ layer generate video -d 5 --aspect-ratio 16:9 -p "camera pushes through the gate"
67
+ layer generate mesh -p "weathered treasure chest, game-ready"
68
+ layer generate audio -p "arcade coin pickup"
69
+ ```
70
+
71
+ Each waits for the run, prints what it cost, and writes the result into the working
72
+ directory under a name derived from the prompt — never overwriting a file already there.
73
+ `-o` takes a directory, or the exact filename when there is a single output;
74
+ `--no-download` prints URLs instead.
75
+
76
+ Leave `--base-model` off and the recommended model for that modality is chosen and
77
+ named. The catalogue is read from your workspace, not shipped with the package:
78
+
79
+ ```sh
80
+ layer base-models list --modality video
81
+ layer base-models show bfl-flux-2-pro # the keys --param accepts
82
+ ```
83
+
84
+ Every run is priced before it executes. `--confirm` asks first; `--max-cost 8` refuses
85
+ anything more expensive. For a long render, submit and collect later:
86
+
87
+ ```sh
88
+ id=$(layer --json generate video --no-wait -p "..." | jq -r .inference_id)
89
+ layer generate status "$id" --wait
90
+ ```
91
+
59
92
  ## Where settings come from
60
93
 
61
94
  Highest wins:
@@ -81,15 +114,21 @@ go to stderr, so a pipeline never has to filter them out.
81
114
 
82
115
  ```sh
83
116
  layer --json whoami | jq -r .workspace
117
+ layer --json generate image -p "..." | jq -r '.files[].path'
84
118
  ```
85
119
 
86
120
  Exit codes: `0` ok, `1` error, `2` usage, `3` auth, `4` insufficient balance,
87
- `5` invalid input, `6` content policy, `7` timeout.
121
+ `5` invalid input, `6` content policy, `7` timeout. They may gain members, never change
122
+ meaning, so a caller can branch on them without parsing prose.
88
123
 
89
124
  ## Documentation
90
125
 
91
126
  <https://www.layer.ai/docs/cli>
92
127
 
128
+ Driving Layer from an agent rather than a shell? There is an
129
+ [MCP server](https://www.layer.ai/mcp) and an
130
+ [Agent Skills pack](https://www.layer.ai/skills).
131
+
93
132
  ## Licence
94
133
 
95
134
  Apache-2.0
layer-1.0.6/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # layer
2
+
3
+ Command-line interface for [Layer](https://layer.ai) — AI asset generation for game studios.
4
+
5
+ Reaches the same models, workspaces, and Creative Unit balance as the app, from a
6
+ terminal, a Makefile, or a CI job.
7
+
8
+ ## Install
9
+
10
+ ```sh
11
+ uv tool install layer # or: pipx install layer
12
+ ```
13
+
14
+ Python 3.10 and up — deliberately older than the services that build it, so the same
15
+ package imports inside Blender, Maya, and Houdini.
16
+
17
+ Working on the CLI itself? Install it from your checkout instead, so the `layer`
18
+ command follows the branch you have out:
19
+
20
+ ```sh
21
+ task -d apps/cli-py install-cli
22
+ ```
23
+
24
+ ## Sign in
25
+
26
+ ```sh
27
+ layer login # opens a browser
28
+ layer login --device # for SSH sessions and containers
29
+ layer whoami
30
+ layer use my-studio
31
+ ```
32
+
33
+ For CI and other unattended runs, set `LAYER_API_KEY` to a personal access token instead
34
+ of signing in.
35
+
36
+ ## Generate
37
+
38
+ ```sh
39
+ layer generate image -p "a crystal sword icon, transparent background"
40
+ layer generate video -d 5 --aspect-ratio 16:9 -p "camera pushes through the gate"
41
+ layer generate mesh -p "weathered treasure chest, game-ready"
42
+ layer generate audio -p "arcade coin pickup"
43
+ ```
44
+
45
+ Each waits for the run, prints what it cost, and writes the result into the working
46
+ directory under a name derived from the prompt — never overwriting a file already there.
47
+ `-o` takes a directory, or the exact filename when there is a single output;
48
+ `--no-download` prints URLs instead.
49
+
50
+ Leave `--base-model` off and the recommended model for that modality is chosen and
51
+ named. The catalogue is read from your workspace, not shipped with the package:
52
+
53
+ ```sh
54
+ layer base-models list --modality video
55
+ layer base-models show bfl-flux-2-pro # the keys --param accepts
56
+ ```
57
+
58
+ Every run is priced before it executes. `--confirm` asks first; `--max-cost 8` refuses
59
+ anything more expensive. For a long render, submit and collect later:
60
+
61
+ ```sh
62
+ id=$(layer --json generate video --no-wait -p "..." | jq -r .inference_id)
63
+ layer generate status "$id" --wait
64
+ ```
65
+
66
+ ## Where settings come from
67
+
68
+ Highest wins:
69
+
70
+ 1. a command-line flag
71
+ 2. an environment variable — `LAYER_PROFILE`, `LAYER_WORKSPACE`, `LAYER_PROJECT`,
72
+ `LAYER_API_URL`, `LAYER_API_KEY`
73
+ 3. `layer.toml`, found by walking up from the working directory
74
+ 4. the active profile in `~/.layer/config.toml`
75
+
76
+ Committing a `layer.toml` pins a checkout to its workspace, so two repos open in two
77
+ terminals cannot generate into each other's:
78
+
79
+ ```toml
80
+ workspace = "my-studio"
81
+ project = "season-12-art"
82
+ ```
83
+
84
+ ## Scripting
85
+
86
+ `--json` puts the result on stdout and nothing else — progress, warnings, and errors all
87
+ go to stderr, so a pipeline never has to filter them out.
88
+
89
+ ```sh
90
+ layer --json whoami | jq -r .workspace
91
+ layer --json generate image -p "..." | jq -r '.files[].path'
92
+ ```
93
+
94
+ Exit codes: `0` ok, `1` error, `2` usage, `3` auth, `4` insufficient balance,
95
+ `5` invalid input, `6` content policy, `7` timeout. They may gain members, never change
96
+ meaning, so a caller can branch on them without parsing prose.
97
+
98
+ ## Documentation
99
+
100
+ <https://www.layer.ai/docs/cli>
101
+
102
+ Driving Layer from an agent rather than a shell? There is an
103
+ [MCP server](https://www.layer.ai/mcp) and an
104
+ [Agent Skills pack](https://www.layer.ai/skills).
105
+
106
+ ## Licence
107
+
108
+ Apache-2.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "layer"
3
- version = "1.0.4"
3
+ version = "1.0.6"
4
4
  description = "Command-line interface for Layer — AI asset generation for game studios."
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "layer"
3
- version = "1.0.4"
3
+ version = "1.0.6"
4
4
  description = "Command-line interface for Layer — AI asset generation for game studios."
5
5
  readme = "README.md"
6
6
  authors = [{ name = "Layer", email = "info@layer.ai" }]
@@ -29,6 +29,22 @@ class AddProjectMembersBody(BaseModel):
29
29
  )
30
30
 
31
31
 
32
+ class AudioOutputFormat(Enum):
33
+ """
34
+ Container for a delivered audio file.
35
+
36
+ Providers name these their own way and Layer never re-encodes what one returns, so the
37
+ format a caller asks for is only keepable on models whose capabilities list it. Members are
38
+ named for their wire value: the frontend artifacts preserve enum *names*, and a name that
39
+ differed from the value would hand clients a format string the request API rejects.
40
+ """
41
+
42
+ mp3 = "mp3"
43
+ wav = "wav"
44
+ aac = "aac"
45
+ flac = "flac"
46
+
47
+
32
48
  class BlueprintRunStatus(Enum):
33
49
  """
34
50
  Enum representing the status of a blueprint run.
@@ -1495,6 +1511,48 @@ class BaseModelCapabilitiesREST(BaseModel):
1495
1511
  generate_parts: bool | None = Field(False, title="Generate Parts")
1496
1512
  text_to_speech: bool | None = Field(False, title="Text To Speech")
1497
1513
  sound_effect: bool | None = Field(False, title="Sound Effect")
1514
+ music: bool | None = Field(
1515
+ False,
1516
+ description="Composes music. Distinguishes a music model from a sound-effect model, which the modality and the duration range alone do not.",
1517
+ title="Music",
1518
+ )
1519
+ lyrics: bool | None = Field(
1520
+ False,
1521
+ description="Takes sung words in a dedicated lyrics input, separate from the text prompt. This describes the input shape, not whether the model can sing: some families read lyrics written into the prompt instead, so a false value is not a reason to rule a model out for a song.",
1522
+ title="Lyrics",
1523
+ )
1524
+ auto_duration: bool | None = Field(
1525
+ False,
1526
+ description="The model sets the output length itself, from the text or the input file. It has no duration control, so duration_seconds is ignored: do not promise a requested length.",
1527
+ title="Auto Duration",
1528
+ )
1529
+ instrumental: bool | None = Field(
1530
+ False,
1531
+ description="Takes a flag that guarantees no vocals. On other music models, asking for an instrumental in the prompt is only a suggestion.",
1532
+ title="Instrumental",
1533
+ )
1534
+ loop: bool | None = Field(
1535
+ False,
1536
+ description="Composes the clip to repeat with no audible seam when the `loop` parameter is set.",
1537
+ title="Loop",
1538
+ )
1539
+ audio_inpaint: bool | None = Field(False, title="Audio Inpaint")
1540
+ audio_outpaint: bool | None = Field(False, title="Audio Outpaint")
1541
+ audio_segments: bool | None = Field(
1542
+ False,
1543
+ description="Scores a video stretch by stretch from a contiguous list of per-stretch briefs.",
1544
+ title="Audio Segments",
1545
+ )
1546
+ output_formats: list[str] | None = Field(
1547
+ None,
1548
+ description="Containers this model can be asked to deliver. Layer never re-encodes a clip, so an empty list means the model returns what it returns and the format cannot be promised.",
1549
+ title="Output Formats",
1550
+ )
1551
+ voice_reference_set_required: bool | None = Field(
1552
+ False,
1553
+ description="Speaks only in a trained voice, so a generation needs a reference set holding one. Without it the provider falls back to its own default voice.",
1554
+ title="Voice Reference Set Required",
1555
+ )
1498
1556
  camera_transform: bool | None = Field(False, title="Camera Transform")
1499
1557
  voice_changer: bool | None = Field(False, title="Voice Changer")
1500
1558
  audio_isolation: bool | None = Field(False, title="Audio Isolation")
@@ -2179,6 +2237,25 @@ class EstimateInferencePriceRequest(BaseModel):
2179
2237
  )
2180
2238
  generate_audio: bool | None = Field(None, description="Generate audio with video.", title="Generate Audio")
2181
2239
  keep_audio: bool | None = Field(None, description="Keep audio from input video.", title="Keep Audio")
2240
+ instrumental: bool | None = Field(
2241
+ None,
2242
+ description="Guarantee a track with no vocals, on models whose capabilities report instrumental. Asking for one in the prompt is only a suggestion.",
2243
+ title="Instrumental",
2244
+ )
2245
+ loop: bool | None = Field(
2246
+ None,
2247
+ description="Compose the clip to repeat with no audible seam, on models whose capabilities report loop.",
2248
+ title="Loop",
2249
+ )
2250
+ output_format: AudioOutputFormat | None = Field(
2251
+ None,
2252
+ description="Container for the delivered file, one of the values the model's capabilities list under output_formats. Layer never re-encodes a clip, so a model that lists none delivers what it delivers.",
2253
+ )
2254
+ lyrics: str | None = Field(
2255
+ None,
2256
+ description="Words to be sung, for models whose capabilities report lyrics. A separate input from the prompt, which describes the music itself.",
2257
+ title="Lyrics",
2258
+ )
2182
2259
  fps: Fps | None = Field(None, description="FPS for LTX video generation (e.g. 25 or 50).", title="Fps")
2183
2260
  video_effects: list[ForgeVideoEffectInput] | None = Field(
2184
2261
  [], description="Video effects to apply.", title="Video Effects"
@@ -2287,6 +2364,25 @@ class EstimateInferencePriceV2Request(BaseModel):
2287
2364
  )
2288
2365
  generate_audio: bool | None = Field(None, description="Generate audio with video.", title="Generate Audio")
2289
2366
  keep_audio: bool | None = Field(None, description="Keep audio from input video.", title="Keep Audio")
2367
+ instrumental: bool | None = Field(
2368
+ None,
2369
+ description="Guarantee a track with no vocals, on models whose capabilities report instrumental. Asking for one in the prompt is only a suggestion.",
2370
+ title="Instrumental",
2371
+ )
2372
+ loop: bool | None = Field(
2373
+ None,
2374
+ description="Compose the clip to repeat with no audible seam, on models whose capabilities report loop.",
2375
+ title="Loop",
2376
+ )
2377
+ output_format: AudioOutputFormat | None = Field(
2378
+ None,
2379
+ description="Container for the delivered file, one of the values the model's capabilities list under output_formats. Layer never re-encodes a clip, so a model that lists none delivers what it delivers.",
2380
+ )
2381
+ lyrics: str | None = Field(
2382
+ None,
2383
+ description="Words to be sung, for models whose capabilities report lyrics. A separate input from the prompt, which describes the music itself.",
2384
+ title="Lyrics",
2385
+ )
2290
2386
  fps: Fps | None = Field(None, description="FPS for LTX video generation (e.g. 25 or 50).", title="Fps")
2291
2387
  video_effects: list[ForgeVideoEffectInput] | None = Field(
2292
2388
  [], description="Video effects to apply.", title="Video Effects"
@@ -2389,6 +2485,25 @@ class ExecuteInferenceRequest(BaseModel):
2389
2485
  )
2390
2486
  generate_audio: bool | None = Field(None, description="Generate audio with video.", title="Generate Audio")
2391
2487
  keep_audio: bool | None = Field(None, description="Keep audio from input video.", title="Keep Audio")
2488
+ instrumental: bool | None = Field(
2489
+ None,
2490
+ description="Guarantee a track with no vocals, on models whose capabilities report instrumental. Asking for one in the prompt is only a suggestion.",
2491
+ title="Instrumental",
2492
+ )
2493
+ loop: bool | None = Field(
2494
+ None,
2495
+ description="Compose the clip to repeat with no audible seam, on models whose capabilities report loop.",
2496
+ title="Loop",
2497
+ )
2498
+ output_format: AudioOutputFormat | None = Field(
2499
+ None,
2500
+ description="Container for the delivered file, one of the values the model's capabilities list under output_formats. Layer never re-encodes a clip, so a model that lists none delivers what it delivers.",
2501
+ )
2502
+ lyrics: str | None = Field(
2503
+ None,
2504
+ description="Words to be sung, for models whose capabilities report lyrics. A separate input from the prompt, which describes the music itself.",
2505
+ title="Lyrics",
2506
+ )
2392
2507
  fps: Fps | None = Field(None, description="FPS for LTX video generation (e.g. 25 or 50).", title="Fps")
2393
2508
  video_effects: list[ForgeVideoEffectInput] | None = Field(
2394
2509
  [], description="Video effects to apply.", title="Video Effects"
@@ -2506,6 +2621,25 @@ class ExecuteInferenceV2Request(BaseModel):
2506
2621
  )
2507
2622
  generate_audio: bool | None = Field(None, description="Generate audio with video.", title="Generate Audio")
2508
2623
  keep_audio: bool | None = Field(None, description="Keep audio from input video.", title="Keep Audio")
2624
+ instrumental: bool | None = Field(
2625
+ None,
2626
+ description="Guarantee a track with no vocals, on models whose capabilities report instrumental. Asking for one in the prompt is only a suggestion.",
2627
+ title="Instrumental",
2628
+ )
2629
+ loop: bool | None = Field(
2630
+ None,
2631
+ description="Compose the clip to repeat with no audible seam, on models whose capabilities report loop.",
2632
+ title="Loop",
2633
+ )
2634
+ output_format: AudioOutputFormat | None = Field(
2635
+ None,
2636
+ description="Container for the delivered file, one of the values the model's capabilities list under output_formats. Layer never re-encodes a clip, so a model that lists none delivers what it delivers.",
2637
+ )
2638
+ lyrics: str | None = Field(
2639
+ None,
2640
+ description="Words to be sung, for models whose capabilities report lyrics. A separate input from the prompt, which describes the music itself.",
2641
+ title="Lyrics",
2642
+ )
2509
2643
  fps: Fps | None = Field(None, description="FPS for LTX video generation (e.g. 25 or 50).", title="Fps")
2510
2644
  video_effects: list[ForgeVideoEffectInput] | None = Field(
2511
2645
  [], description="Video effects to apply.", title="Video Effects"
layer-1.0.4/README.md DELETED
@@ -1,69 +0,0 @@
1
- # layer
2
-
3
- Command-line interface for [Layer](https://layer.ai) — AI asset generation for game studios.
4
-
5
- > **Pre-release.** This is an early build of the rewritten CLI. Asset generation is
6
- > landing next; today it covers signing in and choosing a workspace.
7
-
8
- ## Install
9
-
10
- ```sh
11
- uv tool install --prerelease=allow layer # or: pipx install --pip-args=--pre layer
12
- ```
13
-
14
- Working on the CLI itself? Install it from your checkout instead, so the `layer`
15
- command follows the branch you have out:
16
-
17
- ```sh
18
- task -d apps/cli-py install-cli
19
- ```
20
-
21
- ## Sign in
22
-
23
- ```sh
24
- layer login # opens a browser
25
- layer login --device # for SSH sessions and containers
26
- layer whoami
27
- layer use my-studio
28
- ```
29
-
30
- For CI and other unattended runs, set `LAYER_API_KEY` to a personal access token instead
31
- of signing in.
32
-
33
- ## Where settings come from
34
-
35
- Highest wins:
36
-
37
- 1. a command-line flag
38
- 2. an environment variable — `LAYER_PROFILE`, `LAYER_WORKSPACE`, `LAYER_PROJECT`,
39
- `LAYER_API_URL`, `LAYER_API_KEY`
40
- 3. `layer.toml`, found by walking up from the working directory
41
- 4. the active profile in `~/.layer/config.toml`
42
-
43
- Committing a `layer.toml` pins a checkout to its workspace, so two repos open in two
44
- terminals cannot generate into each other's:
45
-
46
- ```toml
47
- workspace = "my-studio"
48
- project = "season-12-art"
49
- ```
50
-
51
- ## Scripting
52
-
53
- `--json` puts the result on stdout and nothing else — progress, warnings, and errors all
54
- go to stderr, so a pipeline never has to filter them out.
55
-
56
- ```sh
57
- layer --json whoami | jq -r .workspace
58
- ```
59
-
60
- Exit codes: `0` ok, `1` error, `2` usage, `3` auth, `4` insufficient balance,
61
- `5` invalid input, `6` content policy, `7` timeout.
62
-
63
- ## Documentation
64
-
65
- <https://www.layer.ai/docs/cli>
66
-
67
- ## Licence
68
-
69
- Apache-2.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes