@sogni-ai/sogni-creative-agent-skill 3.3.4 → 3.4.0

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/README.md CHANGED
@@ -70,14 +70,23 @@ With this skill, an agent can:
70
70
  ## Quick Start
71
71
 
72
72
  1. Get a Sogni API key from [dashboard.sogni.ai](https://dashboard.sogni.ai) (open the account menu) and save it — see [Setup](#setup-sogni-api-key).
73
- 2. Install the CLI:
73
+ 2. Install (one command):
74
+
75
+ ```bash
76
+ npx setup-sogni-agent-skill
77
+ ```
78
+
79
+ This auto-detects Claude Code, Codex CLI, and Hermes; installs the CLI globally;
80
+ registers the skill into each detected runtime; and prompts for your API key.
81
+
82
+ Prefer to do it manually? Install the CLI directly:
74
83
 
75
84
  ```bash
76
85
  npm install -g @sogni-ai/sogni-creative-agent-skill@latest
77
86
  sogni-agent --version
78
87
  ```
79
88
 
80
- 3. Point your agent runtime at this repository's [`SKILL.md`](./SKILL.md).
89
+ Then point your agent runtime at this repository's [`SKILL.md`](./SKILL.md).
81
90
 
82
91
  Then ask your agent to do something:
83
92
 
@@ -133,6 +142,8 @@ openclaw plugins install sogni-creative-agent-skill
133
142
 
134
143
  The installed plugin loads its behavior from [`SKILL.md`](./SKILL.md) via [`openclaw.plugin.json`](./openclaw.plugin.json).
135
144
 
145
+ > **API key under OpenClaw:** the plugin config holds non-secret defaults only (models, timeouts, paths) — it does **not** carry your API key. Provide `SOGNI_API_KEY` via the environment the OpenClaw gateway passes to the CLI, or save it to `~/.config/sogni/credentials` (`SOGNI_API_KEY=<your-key>`). This keeps your key out of plugin config files.
146
+
136
147
  For a local checkout that you want to update continuously, link the minimal OpenClaw surface (`.openclaw-link/`) — not the repository root, which contains development tests that OpenClaw correctly blocks during plugin safety scanning:
137
148
 
138
149
  ```bash
@@ -322,9 +333,9 @@ sogni-agent --api-workflow storyboard-video "10s neon city flyover"
322
333
 
323
334
  # Local segment + concat with external soundtrack
324
335
  sogni-agent --video --workflow v2v --ref-video dance.mp4 \
325
- --video-start 10 --duration 8 --controlnet-name pose -o /tmp/clip-2.mp4 \
336
+ --video-start 10 --duration 8 --controlnet-name pose -o ./clip-2.mp4 \
326
337
  "robot dancing"
327
- sogni-agent --concat-videos /tmp/final.mp4 /tmp/clip-1.mp4 /tmp/clip-2.mp4 \
338
+ sogni-agent --concat-videos ./final.mp4 ./clip-1.mp4 ./clip-2.mp4 \
328
339
  --concat-audio song.mp3 --concat-audio-start 0
329
340
 
330
341
  # Balances and help
@@ -451,7 +462,7 @@ LTX-2.3 prompt: "A medium cinematic shot frames a woman in her 30s standing in a
451
462
 
452
463
  ## Photobooth (Face Transfer)
453
464
 
454
- Generate stylized portraits from a face photo using InstantID ControlNet:
465
+ Generate new stylized portraits from a face photo using InstantID ControlNet:
455
466
 
456
467
  ```bash
457
468
  sogni-agent --photobooth --ref face.jpg "80s fashion portrait"
@@ -460,6 +471,8 @@ sogni-agent --photobooth --ref face.jpg -n 4 "LinkedIn professional headshot"
460
471
 
461
472
  Uses SDXL Turbo (`coreml-sogniXLturbo_alpha1_ad`) at 1024×1024 by default. The face image is passed via `--ref` and styled by the prompt. Cannot be combined with `--video` or `-c` / `--context`.
462
473
 
474
+ `--photobooth` is face-reference generation, not full-image editing. If the request is "same image, different style" — for example an anime version that must keep the same face, pose, clothing, background, framing, and composition — use Qwen image editing with `-c/--context` instead.
475
+
463
476
  Multi-angle mode (`--multi-angle` / `--angles-360`) auto-builds the `<sks>` prompt and applies the `multiple_angles` LoRA. `--angles-360-video` generates i2v clips between consecutive angles (including last → first) and concatenates them with `ffmpeg` into a seamless loop.
464
477
 
465
478
  `--balance` / `--balances` does not require a prompt and prints current `SPARK` and `SOGNI` balances before exiting.
@@ -577,7 +590,7 @@ Use `--token-type auto` to retry native Sogni models with SOGNI tokens when SPAR
577
590
  sogni-agent --token-type auto "a dragon eating tacos"
578
591
  ```
579
592
 
580
- Tries SPARK first (free daily tokens), then falls back to SOGNI if the balance is too low. Vendor models such as Seedance and GPT Image 2 require Premium Spark eligibility and never use SOGNI fallback.
593
+ Tries SPARK first, then falls back to SOGNI if the balance is too low. Vendor models such as Seedance and GPT Image 2 require Premium Spark eligibility and never use SOGNI fallback. If usable balance is still insufficient, buy Spark Packs at https://docs.sogni.ai/pricing/#spark-packs.
581
594
 
582
595
  ---
583
596
 
@@ -632,6 +645,15 @@ Reusable workflow rules should come from the shared Sogni runtime before they ar
632
645
 
633
646
  Public-skill regex should stay limited to CLI argument/fact extraction such as file paths, URLs, extensions, dimensions, durations, and explicit positions. Hosted-style decisions such as latest-video continuation, uploaded-video modification, image-selection waits, stitch-after-batch state, and repair/control routing belong upstream in typed planner/runtime fields before they are synced here.
634
647
 
648
+ ### Execution boundaries: local CLI vs. hosted surfaces
649
+
650
+ `sogni-agent.mjs` is a **local command-line tool** (`#!/usr/bin/env node`, the package `bin`). It is the only place that may assume a local filesystem and a local `ffmpeg`/`ffprobe` binary. Flags like `--concat-videos`, `--remix-audio`, `--extract-first-frame`, `--extract-last-frame`, and `--angles-360-video` shell out to ffmpeg behind `ensureFfmpegAvailable()` and run only when those flags are passed.
651
+
652
+ Hosted surfaces — including the chat.sogni.ai web app — do **not** run `sogni-agent.mjs`. They consume `@sogni-ai/sogni-intelligence-client` and the hosted `/v1/chat/completions` and `/v1/creative-agent/workflows` APIs, where there is no local ffmpeg and no local filesystem. Therefore:
653
+
654
+ - Keep ffmpeg- and filesystem-dependent helpers (frame extraction, concat, audio remux, media listing) **local to `sogni-agent.mjs`**. Do not move them into the shared runtime or `@sogni-ai/sogni-intelligence-client`, and never make hosted code paths depend on a local binary.
655
+ - Server-side equivalents of these capabilities (e.g. `stitch_video`, `overlay_video`, `extend_video`) live in the hosted creative-agent tool surface and belong upstream, not in the CLI.
656
+
635
657
  Issues and feature requests: [github.com/Sogni-AI/sogni-creative-agent-skill/issues](https://github.com/Sogni-AI/sogni-creative-agent-skill/issues).
636
658
 
637
659
  ---
package/SKILL.md CHANGED
@@ -2,7 +2,7 @@
2
2
  name: sogni-creative-agent-skill
3
3
  description: "Sogni Creative Agent Skill: agent skill and CLI for image, video, and music generation using Sogni AI's decentralized GPU network. Supports personas (named people with saved reference photos and voice clips), persistent memories, custom personality, style transfer, angle synthesis, Seedance/LTX/WAN video, music/lyrics, hosted chat, durable workflows, replay records, and multi-step creative workflows. Ask the agent to \"draw\", \"generate\", \"create an image\", \"make a video/animate\", \"make music\", \"apply a style\", or \"generate me as a superhero\"."
4
4
  metadata:
5
- version: "3.3.4"
5
+ version: "3.4.0"
6
6
  homepage: https://sogni.ai
7
7
  clawdbot:
8
8
  emoji: "🎨"
@@ -72,6 +72,10 @@ npm --prefix "$DEST" install
72
72
 
73
73
  If that checkout does not exist, prefer the npm-based local skill install below, or ask before cloning.
74
74
 
75
+ ## Uninstall Request Policy
76
+
77
+ When a user asks to uninstall, run `npx setup-sogni-agent-skill --uninstall --remove-cli --purge`. This removes the skill files, the global CLI, and the user's data in `~/.config/sogni/` after backing it up to `~/.config/sogni.backup-<timestamp>.tar.gz`. Always tell the user the backup path and that it contains their API key. To keep their data, omit `--purge`.
78
+
75
79
  ## Setup
76
80
 
77
81
  1. **Get your Sogni API key** by logging into https://dashboard.sogni.ai and opening the account menu.
@@ -110,6 +114,18 @@ ln -sfn node_modules/@sogni-ai/sogni-creative-agent-skill sogni-creative-agent-s
110
114
 
111
115
  When this skill is distributed via ClawHub, it bootstraps its local runtime dependencies from `skill-package.json` during install. That avoids relying on a root `package.json` being present in the published skill artifact.
112
116
 
117
+ ## Output Path Convention
118
+
119
+ **Always save generated images, videos, and music to the user's current working directory (PWD), not `/tmp`.** Pass a relative path or bare filename to `-o`/`--output`:
120
+
121
+ ```bash
122
+ sogni-agent -o ./cat.png "a cat wearing a hat" # ✓ lands in PWD
123
+ sogni-agent -o cat.png "a cat wearing a hat" # ✓ lands in PWD
124
+ sogni-agent -o /tmp/cat.png "a cat wearing a hat" # ✗ avoid — user can't easily find it
125
+ ```
126
+
127
+ `/tmp` (and `mkdtempSync(...)`) is reserved internally for transient intermediate files the CLI cleans up itself (audio re-encodes, intermediate clips during stitching). Final renders the user is asking for must remain inside their working directory unless they explicitly request a different location.
128
+
113
129
  ## Filesystem Paths and Overrides
114
130
 
115
131
  Default file paths used by this skill:
@@ -172,8 +188,8 @@ sogni-agent --video --ref hero.png -n 3 --duration 5 \
172
188
  # Token auto-fallback for native Sogni models (tries SPARK, falls back to SOGNI)
173
189
  sogni-agent --token-type auto "a cat wearing a hat"
174
190
 
175
- # Save to file
176
- sogni-agent -o /tmp/cat.png "a cat wearing a hat"
191
+ # Save to file (relative paths land in the current working directory)
192
+ sogni-agent -o ./cat.png "a cat wearing a hat"
177
193
 
178
194
  # JSON output (for scripting)
179
195
  sogni-agent --json "a cat wearing a hat"
@@ -185,7 +201,7 @@ sogni-agent --balance
185
201
  sogni-agent --json --balance
186
202
 
187
203
  # Quiet mode (suppress progress)
188
- sogni-agent -q -o /tmp/cat.png "a cat wearing a hat"
204
+ sogni-agent -q -o ./cat.png "a cat wearing a hat"
189
205
 
190
206
  # Direct music/audio generation
191
207
  sogni-agent --music --duration 30 \
@@ -451,9 +467,19 @@ positions.
451
467
  | `--strict-size` | Do not auto-adjust i2v video size for reference resizing constraints | false |
452
468
  | `-q, --quiet` | No progress output | false |
453
469
  | `--extract-last-frame <video> <image>` | Extract last frame from video (safe ffmpeg wrapper) | - |
454
- | `--concat-videos <out> <clips...>` | Concatenate video clips (safe ffmpeg wrapper) | - |
470
+ | `--extract-first-frame <video> <image>` | Extract first frame from video (safe ffmpeg wrapper) | - |
471
+ | `--concat-videos <out> <clips...>` | Concatenate video clips; normalizes fps/size and fills silent audio so mismatched clips stitch cleanly (safe ffmpeg wrapper) | - |
472
+ | `--concat-fps <n>` | Override target fps for `--concat-videos` | highest clip fps |
455
473
  | `--concat-audio <path>` | Optional audio track to mux over `--concat-videos` output | - |
456
474
  | `--concat-audio-start <sec>` | Start offset into `--concat-audio` | - |
475
+ | `--remix-audio <in> <out>` | Rebuild a video's audio (loop/fade/mix) without re-encoding video (safe ffmpeg wrapper) | - |
476
+ | `--bed-audio <path>` | Audio bed for `--remix-audio` (path or video; defaults to input's own audio) | - |
477
+ | `--audio-loop` | Loop the bed to cover the full video duration (`--remix-audio`) | false |
478
+ | `--audio-fade-in <sec>` | Fade the bed in over `<sec>` (`--remix-audio`) | - |
479
+ | `--audio-fade-out <sec>` | Fade the bed out over `<sec>` at the tail (`--remix-audio`) | - |
480
+ | `--mix-audio <path>` | Overlay one extra audio track, mixed with the bed (`--remix-audio`) | - |
481
+ | `--mix-at <sec>` | Start offset for `--mix-audio` | 0 |
482
+ | `--mix-gain <db>` | Gain in dB applied to `--mix-audio` | 0 |
457
483
  | `--list-media [type]` | List recent inbound media (images\|audio\|all) | images |
458
484
  | `--api-chat` | Call OpenAI-compatible `/v1/chat/completions`; CLI default sends the hosted `creative-agent` tool surface | - |
459
485
  | `--durable-chat` | Start and stream a durable `/v1/chat/runs` record through SDK transport; requires `SOGNI_SKILL_USE_SDK_TRANSPORT=1` | - |
@@ -653,9 +679,17 @@ sogni-agent --last-image "make it more vibrant"
653
679
 
654
680
  When context images are provided without `-m`, defaults to `qwen_image_edit_2511_fp8_lightning`. Select `-m gpt-image-2` for GPT Image 2's higher reference-image limit and OpenAI-backed image editing.
655
681
 
682
+ Use context-image editing for source-preserving edits. If the user says "use this image as the base", "keep everything the same", "only change the style", "anime version of this image", or asks to preserve pose, clothing, background, framing, or composition, use `-c/--context` with a Qwen image edit model instead of `--photobooth`. For stronger preservation than the lightning default, prefer:
683
+
684
+ ```bash
685
+ sogni-agent -c photo.jpg -m qwen_image_edit_2511_fp8 "turn this into anime style; keep the same face, pose, clothing, background, framing, and composition"
686
+ ```
687
+
656
688
  ## Photobooth (Face Transfer)
657
689
 
658
- Generate stylized portraits from a face photo using InstantID ControlNet. When a user mentions "photobooth", wants a stylized portrait of themselves, or asks to transfer their face into a style, use `--photobooth` with `--ref` pointing to their face image.
690
+ Generate new stylized portraits from a face photo using InstantID ControlNet. Use `--photobooth` with `--ref` when the user explicitly asks for photobooth/face-transfer mode, wants a new portrait or headshot based on their face, or asks to place their face identity into a different portrait concept.
691
+
692
+ Do not use `--photobooth` for full-image style edits where the original photo must stay intact. `--photobooth` treats the input as a face reference, not as a base image, so it can change pose, clothing, background, framing, and composition. For "same image, different style" requests, route to Qwen context editing with `-c/--context`.
659
693
 
660
694
  ```bash
661
695
  # Basic photobooth
@@ -673,10 +707,10 @@ Uses SDXL Turbo (`coreml-sogniXLturbo_alpha1_ad`) at 1024x1024 by default. The f
673
707
  **Agent usage:**
674
708
  ```bash
675
709
  # Photobooth: stylize a face photo
676
- sogni-agent -q --photobooth --ref /path/to/face.jpg -o /tmp/stylized.png "80s fashion portrait"
710
+ sogni-agent -q --photobooth --ref /path/to/face.jpg -o ./stylized.png "80s fashion portrait"
677
711
 
678
712
  # Multiple photobooth outputs
679
- sogni-agent -q --photobooth --ref /path/to/face.jpg -n 4 -o /tmp/stylized.png "LinkedIn professional headshot"
713
+ sogni-agent -q --photobooth --ref /path/to/face.jpg -n 4 -o ./stylized.png "LinkedIn professional headshot"
680
714
  ```
681
715
 
682
716
  ## Multiple Angles (Turnaround)
@@ -695,7 +729,7 @@ sogni-agent --angles-360 -c subject.jpg --distance medium --elevation eye-level
695
729
  "studio portrait, same person"
696
730
 
697
731
  # 360 sweep video (looping mp4, uses i2v between angles; requires ffmpeg)
698
- sogni-agent --angles-360 --angles-360-video /tmp/turntable.mp4 \
732
+ sogni-agent --angles-360 --angles-360-video ./turntable.mp4 \
699
733
  -c subject.jpg --distance medium --elevation eye-level \
700
734
  "studio portrait, same person"
701
735
  ```
@@ -725,14 +759,14 @@ When a user requests a "360 video", follow this workflow:
725
759
 
726
760
  4. **Example command**:
727
761
  ```bash
728
- sogni-agent --angles-360 --angles-360-video /tmp/output.mp4 \
762
+ sogni-agent --angles-360 --angles-360-video ./output.mp4 \
729
763
  -c /path/to/image.png --elevation eye-level --distance medium \
730
764
  "description of subject"
731
765
  ```
732
766
 
733
767
  ### Transition Video Rule
734
768
 
735
- For **any transition video work**, always use the **Sogni skill/plugin** (not raw ffmpeg or other shell commands). Use the built-in `--extract-last-frame`, `--concat-videos`, and `--looping` flags for video manipulation.
769
+ For **any transition video work**, always use the **Sogni skill/plugin** (not raw ffmpeg or other shell commands). Use the built-in `--extract-last-frame`, `--extract-first-frame`, `--concat-videos`, `--remix-audio`, and `--looping` flags for video and audio manipulation.
736
770
 
737
771
  ### Insufficient Funds Handling
738
772
 
@@ -740,7 +774,9 @@ Use `--token-type auto` to automatically retry native Sogni models with SOGNI to
740
774
 
741
775
  When you see **"Debit Error: Insufficient funds"** even with auto-fallback, reply:
742
776
 
743
- "Insufficient funds. Claim 50 free daily Spark points at https://app.sogni.ai/"
777
+ "Insufficient funds. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
778
+
779
+ Do not collect payment details, quote a custom price, or simulate a purchase in the terminal.
744
780
 
745
781
  ## Video Generation
746
782
 
@@ -865,10 +901,11 @@ sogni-agent --json --list-media images
865
901
 
866
902
  **Do NOT use `ls`, `cp`, or other shell commands to browse user files.** Always use `--list-media` to find inbound media.
867
903
 
868
- ## IMPORTANT KEYWORD RULE
904
+ ## Photobooth Routing Rule
869
905
 
870
- - If the user message includes the word "photobooth" (case-insensitive), always use `--photobooth` mode with `--ref` set to the user-provided face image.
871
- - Prioritize this rule over generic image-edit flows (`-c`) for that request.
906
+ - If the user explicitly asks to use "photobooth", "photobooth path", or "face transfer", use `--photobooth` with `--ref` set to the user-provided face image.
907
+ - If the same request also requires preserving the whole source image (same pose, clothes, background, framing, composition, or "keep everything the same"), explain that photobooth is face-reference generation and prefer Qwen context editing unless the user insists on photobooth.
908
+ - Do not route to `--photobooth` merely because the user asks to preserve a face in a style edit. Face-preserving full-image edits should use `-c/--context` with Qwen image edit.
872
909
 
873
910
  ## LTX-2.3 Prompt Rule
874
911
 
@@ -929,35 +966,35 @@ When user asks to generate/draw/create an image:
929
966
 
930
967
  ```bash
931
968
  # Generate and save locally (use -Q for quality presets instead of memorizing model IDs)
932
- sogni-agent -q -Q fast -o /tmp/generated.png "user's prompt"
933
- sogni-agent -q -Q pro -o /tmp/generated.png "user's prompt"
969
+ sogni-agent -q -Q fast -o ./generated.png "user's prompt"
970
+ sogni-agent -q -Q pro -o ./generated.png "user's prompt"
934
971
 
935
972
  # Generate with prompt variations (diverse images in one call)
936
- sogni-agent -q -n 3 -o /tmp/cars.png "a {red|blue|green} sports car"
973
+ sogni-agent -q -n 3 -o ./cars.png "a {red|blue|green} sports car"
937
974
 
938
975
  # Edit an existing image
939
- sogni-agent -q -c /path/to/input.jpg -o /tmp/edited.png "make it pop art style"
976
+ sogni-agent -q -c /path/to/input.jpg -o ./edited.png "make it pop art style"
940
977
 
941
978
  # Generate video from image
942
- sogni-agent -q --video --ref /path/to/image.png -o /tmp/video.mp4 "A medium shot holds on the subject in soft late-afternoon light as fabric edges and background details remain clear and stable. The camera performs a slow push-in while the subject shifts weight subtly and turns slightly toward the lens, keeping the motion gentle and continuous. Leaves rustle softly in the background and the scene maintains smooth cinematic movement with no abrupt action changes."
979
+ sogni-agent -q --video --ref /path/to/image.png -o ./video.mp4 "A medium shot holds on the subject in soft late-afternoon light as fabric edges and background details remain clear and stable. The camera performs a slow push-in while the subject shifts weight subtly and turns slightly toward the lens, keeping the motion gentle and continuous. Leaves rustle softly in the background and the scene maintains smooth cinematic movement with no abrupt action changes."
943
980
 
944
981
  # Generate text-to-video
945
- sogni-agent -q --video -o /tmp/video.mp4 "A wide cinematic shot opens on ocean waves rolling toward a rocky shoreline at sunset, golden light spreading across the water while sea mist drifts through the air. Foam patterns form and recede over the dark sand as the horizon glows orange and pink in the distance. The camera glides forward in one continuous movement, holding smooth stabilized motion and calm environmental detail throughout the scene."
982
+ sogni-agent -q --video -o ./video.mp4 "A wide cinematic shot opens on ocean waves rolling toward a rocky shoreline at sunset, golden light spreading across the water while sea mist drifts through the air. Foam patterns form and recede over the dark sand as the horizon glows orange and pink in the distance. The camera glides forward in one continuous movement, holding smooth stabilized motion and calm environmental detail throughout the scene."
946
983
 
947
984
  # Generate direct music/audio
948
- sogni-agent -q --music --duration 30 -o /tmp/music.mp3 "uplifting cinematic synthwave theme for a product launch"
985
+ sogni-agent -q --music --duration 30 -o ./music.mp3 "uplifting cinematic synthwave theme for a product launch"
949
986
 
950
987
  # HD / "4K" text-to-video: prefer LTX-2.3
951
- sogni-agent -q --video -m ltx23-22b-fp8_t2v_distilled -w 1920 -h 1088 -o /tmp/video.mp4 "A wide cinematic aerial shot opens over a rugged ocean coastline at golden hour, warm sunlight catching the cliff faces while white surf breaks against dark rock below. Low sea mist hangs over the water and bands of foam trace the shoreline as gulls wheel through the distance. The camera glides forward in one continuous pass, revealing the curve of the coast while wet stone flashes with reflected light and the scene keeps smooth stabilized motion from start to finish. The overall mood feels expansive and polished, with crisp environmental detail and steady travel-film energy."
988
+ sogni-agent -q --video -m ltx23-22b-fp8_t2v_distilled -w 1920 -h 1088 -o ./video.mp4 "A wide cinematic aerial shot opens over a rugged ocean coastline at golden hour, warm sunlight catching the cliff faces while white surf breaks against dark rock below. Low sea mist hangs over the water and bands of foam trace the shoreline as gulls wheel through the distance. The camera glides forward in one continuous pass, revealing the curve of the coast while wet stone flashes with reflected light and the scene keeps smooth stabilized motion from start to finish. The overall mood feels expansive and polished, with crisp environmental detail and steady travel-film energy."
952
989
 
953
990
  # HD / "4K" image-to-video: prefer LTX i2v
954
- sogni-agent -q --video --ref /path/to/image.png -m ltx23-22b-fp8_i2v_distilled -w 1920 -h 1088 -o /tmp/video.mp4 "A medium cinematic shot holds on the scene with clean subject separation and stable environmental detail as directional light shapes the surfaces and background depth. The camera performs a slow push-in while the main subject makes one subtle continuous movement, keeping posture and identity consistent from start to finish. Ambient motion in the background stays gentle and the overall clip remains smooth, stabilized, and visually coherent."
991
+ sogni-agent -q --video --ref /path/to/image.png -m ltx23-22b-fp8_i2v_distilled -w 1920 -h 1088 -o ./video.mp4 "A medium cinematic shot holds on the scene with clean subject separation and stable environmental detail as directional light shapes the surfaces and background depth. The camera performs a slow push-in while the main subject makes one subtle continuous movement, keeping posture and identity consistent from start to finish. Ambient motion in the background stays gentle and the overall clip remains smooth, stabilized, and visually coherent."
955
992
 
956
993
  # Photobooth: stylize a face photo
957
- sogni-agent -q --photobooth --ref /path/to/face.jpg -o /tmp/stylized.png "80s fashion portrait"
994
+ sogni-agent -q --photobooth --ref /path/to/face.jpg -o ./stylized.png "80s fashion portrait"
958
995
 
959
996
  # Token auto-fallback for native Sogni models (tries SPARK first, retries with SOGNI on insufficient balance)
960
- sogni-agent -q --token-type auto -o /tmp/generated.png "user's prompt"
997
+ sogni-agent -q --token-type auto -o ./generated.png "user's prompt"
961
998
 
962
999
  # Check current SPARK/SOGNI balances (no prompt required)
963
1000
  sogni-agent --json --balance
@@ -1005,7 +1042,7 @@ If clips need different source images, end frames, durations, audio windows, or
1005
1042
 
1006
1043
  ### Token Auto-Fallback
1007
1044
 
1008
- Use `--token-type auto` when the user's SPARK balance might be low. It tries SPARK first (free daily tokens) and automatically retries with SOGNI if insufficient.
1045
+ Use `--token-type auto` when the user's SPARK balance might be low. It tries SPARK first and automatically retries with SOGNI if insufficient.
1009
1046
 
1010
1047
  ## High-Res Video Routing
1011
1048
 
@@ -1020,7 +1057,7 @@ When the user asks for video in **"hd"**, **"1080p"**, **"4k"**, **"uhd"**, or *
1020
1057
  - Rewrite the user's request using the **LTX-2.3 Prompt Rule** before invoking the command. Do not send short slogan-style prompts to LTX.
1021
1058
  - Treat "4k" as a signal to use the highest practical LTX path exposed by this skill, even though the current wrapper caps non-WAN video dimensions at 2048px on the long side.
1022
1059
 
1023
- **Security:** Agents must use the CLI's built-in flags (`--extract-last-frame`, `--concat-videos`, `--list-media`) for all file operations and video manipulation. Never run raw shell commands (`ffmpeg`, `ls`, `cp`, etc.) directly.
1060
+ **Security:** Agents must use the CLI's built-in flags (`--extract-last-frame`, `--extract-first-frame`, `--concat-videos`, `--remix-audio`, `--list-media`) for all file operations and video/audio manipulation. Never run raw shell commands (`ffmpeg`, `ls`, `cp`, etc.) directly.
1024
1061
 
1025
1062
  ## Animate Between Two Images (First-Frame / Last-Frame)
1026
1063
 
@@ -1028,7 +1065,7 @@ When a user asks to **animate between two images**, use `--ref` (first frame) an
1028
1065
 
1029
1066
  ```bash
1030
1067
  # Animate from image A to image B
1031
- sogni-agent -q --video --ref /tmp/imageA.png --ref-end /tmp/imageB.png -o /tmp/transition.mp4 "descriptive prompt of the transition"
1068
+ sogni-agent -q --video --ref ./imageA.png --ref-end ./imageB.png -o ./transition.mp4 "descriptive prompt of the transition"
1032
1069
  ```
1033
1070
 
1034
1071
  ### Animate a Video to an Image (Scene Continuation)
@@ -1037,15 +1074,15 @@ When a user asks to **animate from a video to an image** (or "continue" a video
1037
1074
 
1038
1075
  1. **Extract the last frame** of the existing video using the built-in safe wrapper:
1039
1076
  ```bash
1040
- sogni-agent --extract-last-frame /tmp/existing.mp4 /tmp/lastframe.png
1077
+ sogni-agent --extract-last-frame ./existing.mp4 ./lastframe.png
1041
1078
  ```
1042
1079
  2. **Generate a new video** using the last frame as `--ref` and the target image as `--ref-end`:
1043
1080
  ```bash
1044
- sogni-agent -q --video --ref /tmp/lastframe.png --ref-end /tmp/target.png -o /tmp/continuation.mp4 "scene transition prompt"
1081
+ sogni-agent -q --video --ref ./lastframe.png --ref-end ./target.png -o ./continuation.mp4 "scene transition prompt"
1045
1082
  ```
1046
1083
  3. **Concatenate the videos** using the built-in safe wrapper:
1047
1084
  ```bash
1048
- sogni-agent --concat-videos /tmp/full_sequence.mp4 /tmp/existing.mp4 /tmp/continuation.mp4
1085
+ sogni-agent --concat-videos ./full_sequence.mp4 ./existing.mp4 ./continuation.mp4
1049
1086
  ```
1050
1087
 
1051
1088
  This ensures visual continuity — the new clip picks up exactly where the previous one ended.
@@ -1059,6 +1096,50 @@ When the final stitched output needs a single external soundtrack, add `--concat
1059
1096
  - User says "animate this video to this image" → extract last frame, use as `--ref`, target image as `--ref-end`, then stitch
1060
1097
  - User says "continue this video" with a target image → same as above
1061
1098
 
1099
+ ### Transition Between Two Videos (Bridge Clip)
1100
+
1101
+ When a user asks to **create a transition between two existing videos** (A → B), bridge them with a generated clip anchored on both boundary frames:
1102
+
1103
+ 1. **Extract the last frame of video A** and the **first frame of video B**:
1104
+ ```bash
1105
+ sogni-agent --extract-last-frame ./videoA.mp4 ./A_last.png
1106
+ sogni-agent --extract-first-frame ./videoB.mp4 ./B_first.png
1107
+ ```
1108
+ 2. **Generate the transition** with i2v, anchoring start→end so both seams are clean. Match `--fps` to the surrounding clips:
1109
+ ```bash
1110
+ sogni-agent -q --video -m wan_v2.2-14b-fp8_i2v_lightx2v \
1111
+ --ref ./A_last.png --ref-end ./B_first.png --fps 24 \
1112
+ -o ./transition.mp4 "descriptive morph between the two scenes"
1113
+ ```
1114
+ 3. **Concatenate A → transition → B**:
1115
+ ```bash
1116
+ sogni-agent --concat-videos ./merged.mp4 ./videoA.mp4 ./transition.mp4 ./videoB.mp4
1117
+ ```
1118
+
1119
+ > **i2v clips are silent and use the model's own frame rate** (often not 24). `--concat-videos` now normalizes fps/size and fills silent audio automatically, so mismatched clips stitch correctly — but passing `--fps` to the transition generation keeps things clean from the start. Use `--concat-fps <n>` to force a specific output frame rate.
1120
+
1121
+ ### Remix / Layer Audio After Stitching
1122
+
1123
+ After concatenating, use `--remix-audio` to rebuild the audio track **without re-encoding the video** (it is stream-copied, so it is fast and lossless on the picture). Combine the audio flags:
1124
+
1125
+ ```bash
1126
+ # Loop one clip's audio across the whole merged video and fade it out at the end
1127
+ sogni-agent --remix-audio ./merged.mp4 ./final.mp4 \
1128
+ --bed-audio ./clip1.mp4 --audio-loop --audio-fade-out 2
1129
+
1130
+ # Same, but also layer a second clip's original audio back in starting at 18s
1131
+ sogni-agent --remix-audio ./merged.mp4 ./final.mp4 \
1132
+ --bed-audio ./clip1.mp4 --audio-loop --audio-fade-out 2 \
1133
+ --mix-audio ./clip3.mp4 --mix-at 18.01 --mix-gain -3
1134
+ ```
1135
+
1136
+ - `--bed-audio` accepts a video or audio file; if omitted, the input video's own audio is the bed.
1137
+ - `--audio-loop` loops the bed to cover the full video; `--audio-fade-in` / `--audio-fade-out` fade it.
1138
+ - `--mix-audio` overlays one extra track (mixed at full level with a peak limiter so it never clips); position it with `--mix-at` and adjust level with `--mix-gain` (dB).
1139
+ - To mix more than two layers, chain `--remix-audio` passes (each only re-encodes audio).
1140
+
1141
+ **Do NOT run raw `ffmpeg` commands** for any of this. Use `--extract-first-frame`, `--extract-last-frame`, `--concat-videos`, and `--remix-audio`.
1142
+
1062
1143
  ## JSON Output
1063
1144
 
1064
1145
  ```json
@@ -1069,7 +1150,7 @@ When the final stitched output needs a single external soundtrack, add `--concat
1069
1150
  "width": 512,
1070
1151
  "height": 512,
1071
1152
  "urls": ["https://..."],
1072
- "localPath": "/tmp/cat.png"
1153
+ "localPath": "./cat.png"
1073
1154
  }
1074
1155
  ```
1075
1156
 
@@ -1122,7 +1203,7 @@ sogni-agent --persona-list --json
1122
1203
  sogni-agent --persona-resolve "me" --json
1123
1204
 
1124
1205
  # Generate using a persona (auto-injects photo as context)
1125
- sogni-agent --persona "Mark" -o /tmp/hero.png "superhero in dramatic lighting"
1206
+ sogni-agent --persona "Mark" -o ./hero.png "superhero in dramatic lighting"
1126
1207
 
1127
1208
  # Remove a persona
1128
1209
  sogni-agent --persona-remove "Mark"
@@ -1183,13 +1264,13 @@ Apply artistic styles to existing images:
1183
1264
 
1184
1265
  ```bash
1185
1266
  # Apply a named artist style
1186
- sogni-agent -c photo.jpg -o /tmp/styled.png "Apply style: Andy Warhol pop art with bold primary colors"
1267
+ sogni-agent -c photo.jpg -o ./styled.png "Apply style: Andy Warhol pop art with bold primary colors"
1187
1268
 
1188
1269
  # Studio Ghibli transformation
1189
- sogni-agent -c photo.jpg -o /tmp/ghibli.png "Apply style: Studio Ghibli watercolor with soft pastel sky and lush greenery"
1270
+ sogni-agent -c photo.jpg -o ./ghibli.png "Apply style: Studio Ghibli watercolor with soft pastel sky and lush greenery"
1190
1271
 
1191
1272
  # For photos with people, always preserve identity
1192
- sogni-agent -c portrait.jpg -o /tmp/styled.png "Apply style: oil painting in the style of Vermeer. Preserve all facial features, expressions, and identity."
1273
+ sogni-agent -c portrait.jpg -o ./styled.png "Apply style: oil painting in the style of Vermeer. Preserve all facial features, expressions, and identity."
1193
1274
  ```
1194
1275
 
1195
1276
  **Tips:** Reference artists and styles BY NAME for best results. Use positive phrasing. For photos with people, always append identity preservation instructions.
@@ -556,7 +556,7 @@ const REPAIR_RECIPES = [
556
556
  "errorCode": "COST_LIMIT_EXCEEDED",
557
557
  "mode": "stopAndAsk",
558
558
  "maxRetries": 0,
559
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
559
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
560
560
  },
561
561
  {
562
562
  "recipeId": "edit_image.cost_limit_exceeded",
@@ -565,7 +565,7 @@ const REPAIR_RECIPES = [
565
565
  "errorCode": "COST_LIMIT_EXCEEDED",
566
566
  "mode": "stopAndAsk",
567
567
  "maxRetries": 0,
568
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
568
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
569
569
  },
570
570
  {
571
571
  "recipeId": "restore_photo.cost_limit_exceeded",
@@ -574,7 +574,7 @@ const REPAIR_RECIPES = [
574
574
  "errorCode": "COST_LIMIT_EXCEEDED",
575
575
  "mode": "stopAndAsk",
576
576
  "maxRetries": 0,
577
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
577
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
578
578
  },
579
579
  {
580
580
  "recipeId": "apply_style.cost_limit_exceeded",
@@ -583,7 +583,7 @@ const REPAIR_RECIPES = [
583
583
  "errorCode": "COST_LIMIT_EXCEEDED",
584
584
  "mode": "stopAndAsk",
585
585
  "maxRetries": 0,
586
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
586
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
587
587
  },
588
588
  {
589
589
  "recipeId": "refine_result.cost_limit_exceeded",
@@ -592,7 +592,7 @@ const REPAIR_RECIPES = [
592
592
  "errorCode": "COST_LIMIT_EXCEEDED",
593
593
  "mode": "stopAndAsk",
594
594
  "maxRetries": 0,
595
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
595
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
596
596
  },
597
597
  {
598
598
  "recipeId": "animate_photo.cost_limit_exceeded",
@@ -601,7 +601,7 @@ const REPAIR_RECIPES = [
601
601
  "errorCode": "COST_LIMIT_EXCEEDED",
602
602
  "mode": "stopAndAsk",
603
603
  "maxRetries": 0,
604
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
604
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
605
605
  },
606
606
  {
607
607
  "recipeId": "change_angle.cost_limit_exceeded",
@@ -610,7 +610,7 @@ const REPAIR_RECIPES = [
610
610
  "errorCode": "COST_LIMIT_EXCEEDED",
611
611
  "mode": "stopAndAsk",
612
612
  "maxRetries": 0,
613
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
613
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
614
614
  },
615
615
  {
616
616
  "recipeId": "generate_video.cost_limit_exceeded",
@@ -619,7 +619,7 @@ const REPAIR_RECIPES = [
619
619
  "errorCode": "COST_LIMIT_EXCEEDED",
620
620
  "mode": "stopAndAsk",
621
621
  "maxRetries": 0,
622
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
622
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
623
623
  },
624
624
  {
625
625
  "recipeId": "sound_to_video.cost_limit_exceeded",
@@ -628,7 +628,7 @@ const REPAIR_RECIPES = [
628
628
  "errorCode": "COST_LIMIT_EXCEEDED",
629
629
  "mode": "stopAndAsk",
630
630
  "maxRetries": 0,
631
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
631
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
632
632
  },
633
633
  {
634
634
  "recipeId": "video_to_video.cost_limit_exceeded",
@@ -637,7 +637,7 @@ const REPAIR_RECIPES = [
637
637
  "errorCode": "COST_LIMIT_EXCEEDED",
638
638
  "mode": "stopAndAsk",
639
639
  "maxRetries": 0,
640
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
640
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
641
641
  },
642
642
  {
643
643
  "recipeId": "generate_music.cost_limit_exceeded",
@@ -646,7 +646,7 @@ const REPAIR_RECIPES = [
646
646
  "errorCode": "COST_LIMIT_EXCEEDED",
647
647
  "mode": "stopAndAsk",
648
648
  "maxRetries": 0,
649
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
649
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
650
650
  },
651
651
  {
652
652
  "recipeId": "extend_video.cost_limit_exceeded",
@@ -655,7 +655,7 @@ const REPAIR_RECIPES = [
655
655
  "errorCode": "COST_LIMIT_EXCEEDED",
656
656
  "mode": "stopAndAsk",
657
657
  "maxRetries": 0,
658
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
658
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
659
659
  },
660
660
  {
661
661
  "recipeId": "replace_video_segment.cost_limit_exceeded",
@@ -664,7 +664,7 @@ const REPAIR_RECIPES = [
664
664
  "errorCode": "COST_LIMIT_EXCEEDED",
665
665
  "mode": "stopAndAsk",
666
666
  "maxRetries": 0,
667
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
667
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
668
668
  },
669
669
  {
670
670
  "recipeId": "overlay_video.cost_limit_exceeded",
@@ -673,7 +673,7 @@ const REPAIR_RECIPES = [
673
673
  "errorCode": "COST_LIMIT_EXCEEDED",
674
674
  "mode": "stopAndAsk",
675
675
  "maxRetries": 0,
676
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
676
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
677
677
  },
678
678
  {
679
679
  "recipeId": "add_subtitles.cost_limit_exceeded",
@@ -682,7 +682,7 @@ const REPAIR_RECIPES = [
682
682
  "errorCode": "COST_LIMIT_EXCEEDED",
683
683
  "mode": "stopAndAsk",
684
684
  "maxRetries": 0,
685
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
685
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
686
686
  },
687
687
  {
688
688
  "recipeId": "stitch_video.cost_limit_exceeded",
@@ -691,7 +691,7 @@ const REPAIR_RECIPES = [
691
691
  "errorCode": "COST_LIMIT_EXCEEDED",
692
692
  "mode": "stopAndAsk",
693
693
  "maxRetries": 0,
694
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
694
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
695
695
  },
696
696
  {
697
697
  "recipeId": "orbit_video.cost_limit_exceeded",
@@ -700,7 +700,7 @@ const REPAIR_RECIPES = [
700
700
  "errorCode": "COST_LIMIT_EXCEEDED",
701
701
  "mode": "stopAndAsk",
702
702
  "maxRetries": 0,
703
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
703
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
704
704
  },
705
705
  {
706
706
  "recipeId": "dance_montage.cost_limit_exceeded",
@@ -709,7 +709,7 @@ const REPAIR_RECIPES = [
709
709
  "errorCode": "COST_LIMIT_EXCEEDED",
710
710
  "mode": "stopAndAsk",
711
711
  "maxRetries": 0,
712
- "repairNoteTemplate": "You have hit the credit limit for this turn. Top up credits or wait for the daily refill."
712
+ "repairNoteTemplate": "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs"
713
713
  },
714
714
  {
715
715
  "recipeId": "generate_image.asset_not_found",
@@ -2550,6 +2550,38 @@ const PROMPT_CONTRACTS = [
2550
2550
  // '../public-skill-runtime/index.js' (and downstream consumers that still
2551
2551
  // reference the creative-agent subpath) keep working unchanged.
2552
2552
  export * from '@sogni-ai/sogni-intelligence-client/public-skill-runtime';
2553
+
2554
+ // PUBLIC_SKILL_SPARK_PACKS_COST_LIMIT_OVERRIDE
2555
+ import {
2556
+ PUBLIC_SKILL_DEFAULT_POLICIES as SOGNI_PUBLIC_SKILL_DEFAULT_POLICIES,
2557
+ PUBLIC_SKILL_DEFAULT_PROMPT_CONTRACTS as SOGNI_PUBLIC_SKILL_DEFAULT_PROMPT_CONTRACTS,
2558
+ PUBLIC_SKILL_DEFAULT_REPAIR_RECIPES as SOGNI_PUBLIC_SKILL_DEFAULT_REPAIR_RECIPES,
2559
+ createPublicSkillContractRuntime as createSogniPublicSkillContractRuntime,
2560
+ } from '@sogni-ai/sogni-intelligence-client/public-skill-runtime';
2561
+
2562
+ export const PUBLIC_SKILL_DEFAULT_REPAIR_RECIPES = SOGNI_PUBLIC_SKILL_DEFAULT_REPAIR_RECIPES.map((recipe) =>
2563
+ recipe.errorCode === 'COST_LIMIT_EXCEEDED'
2564
+ ? { ...recipe, message: "You have hit the credit limit for this turn. Buy Spark Packs to continue: https://docs.sogni.ai/pricing/#spark-packs" }
2565
+ : recipe
2566
+ );
2567
+
2568
+ export function createPublicSkillDefaultContractRuntime(input = {}) {
2569
+ return createSogniPublicSkillContractRuntime({
2570
+ policies: [
2571
+ ...SOGNI_PUBLIC_SKILL_DEFAULT_POLICIES,
2572
+ ...(input.policies ?? []),
2573
+ ],
2574
+ promptContracts: [
2575
+ ...SOGNI_PUBLIC_SKILL_DEFAULT_PROMPT_CONTRACTS,
2576
+ ...(input.promptContracts ?? []),
2577
+ ],
2578
+ repairRecipes: [
2579
+ ...PUBLIC_SKILL_DEFAULT_REPAIR_RECIPES,
2580
+ ...(input.repairRecipes ?? []),
2581
+ ],
2582
+ });
2583
+ }
2584
+
2553
2585
  // Moved to @sogni-ai/sogni-intelligence-client/skill-runtime-source in Phase 8.4 follow-up.
2554
2586
  // This file is kept as a thin re-export so existing internal `testing/`
2555
2587
  // callers keep working. New code should import from the public mid-tier: