@vargai/sdk 0.1.1

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 (67) hide show
  1. package/.env.example +24 -0
  2. package/CLAUDE.md +118 -0
  3. package/HIGGSFIELD_REWRITE_SUMMARY.md +300 -0
  4. package/README.md +231 -0
  5. package/SKILLS.md +157 -0
  6. package/STRUCTURE.md +92 -0
  7. package/TEST_RESULTS.md +122 -0
  8. package/action/captions/SKILL.md +170 -0
  9. package/action/captions/index.ts +169 -0
  10. package/action/edit/SKILL.md +235 -0
  11. package/action/edit/index.ts +437 -0
  12. package/action/image/SKILL.md +140 -0
  13. package/action/image/index.ts +105 -0
  14. package/action/sync/SKILL.md +136 -0
  15. package/action/sync/index.ts +145 -0
  16. package/action/transcribe/SKILL.md +179 -0
  17. package/action/transcribe/index.ts +210 -0
  18. package/action/video/SKILL.md +116 -0
  19. package/action/video/index.ts +125 -0
  20. package/action/voice/SKILL.md +125 -0
  21. package/action/voice/index.ts +136 -0
  22. package/biome.json +33 -0
  23. package/bun.lock +842 -0
  24. package/cli/commands/find.ts +58 -0
  25. package/cli/commands/help.ts +70 -0
  26. package/cli/commands/list.ts +49 -0
  27. package/cli/commands/run.ts +237 -0
  28. package/cli/commands/which.ts +66 -0
  29. package/cli/discover.ts +66 -0
  30. package/cli/index.ts +33 -0
  31. package/cli/runner.ts +65 -0
  32. package/cli/types.ts +49 -0
  33. package/cli/ui.ts +185 -0
  34. package/index.ts +75 -0
  35. package/lib/README.md +144 -0
  36. package/lib/ai-sdk/fal.ts +106 -0
  37. package/lib/ai-sdk/replicate.ts +107 -0
  38. package/lib/elevenlabs.ts +382 -0
  39. package/lib/fal.ts +467 -0
  40. package/lib/ffmpeg.ts +467 -0
  41. package/lib/fireworks.ts +235 -0
  42. package/lib/groq.ts +246 -0
  43. package/lib/higgsfield/MIGRATION.md +308 -0
  44. package/lib/higgsfield/README.md +273 -0
  45. package/lib/higgsfield/example.ts +228 -0
  46. package/lib/higgsfield/index.ts +241 -0
  47. package/lib/higgsfield/soul.ts +262 -0
  48. package/lib/higgsfield.ts +176 -0
  49. package/lib/remotion/SKILL.md +823 -0
  50. package/lib/remotion/cli.ts +115 -0
  51. package/lib/remotion/functions.ts +283 -0
  52. package/lib/remotion/index.ts +19 -0
  53. package/lib/remotion/templates.ts +73 -0
  54. package/lib/replicate.ts +304 -0
  55. package/output.txt +1 -0
  56. package/package.json +42 -0
  57. package/pipeline/cookbooks/SKILL.md +285 -0
  58. package/pipeline/cookbooks/remotion-video.md +585 -0
  59. package/pipeline/cookbooks/round-video-character.md +337 -0
  60. package/pipeline/cookbooks/talking-character.md +59 -0
  61. package/scripts/produce-menopause-campaign.sh +202 -0
  62. package/service/music/SKILL.md +229 -0
  63. package/service/music/index.ts +296 -0
  64. package/test-import.ts +7 -0
  65. package/test-services.ts +97 -0
  66. package/tsconfig.json +29 -0
  67. package/utilities/s3.ts +147 -0
@@ -0,0 +1,241 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Higgsfield API client using HTTP requests
4
+ * Base client for all Higgsfield models
5
+ */
6
+
7
+ const BASE_URL = "https://platform.higgsfield.ai";
8
+
9
+ export interface HiggsfieldConfig {
10
+ apiKey?: string;
11
+ apiSecret?: string;
12
+ }
13
+
14
+ export type RequestStatus =
15
+ | "queued"
16
+ | "in_progress"
17
+ | "nsfw"
18
+ | "failed"
19
+ | "completed"
20
+ | "canceled";
21
+
22
+ export interface GenerationRequest {
23
+ status: RequestStatus;
24
+ request_id: string;
25
+ status_url: string;
26
+ cancel_url: string;
27
+ }
28
+
29
+ export interface CompletedRequest extends GenerationRequest {
30
+ status: "completed";
31
+ images?: Array<{ url: string }>;
32
+ video?: { url: string };
33
+ }
34
+
35
+ export interface FailedRequest extends GenerationRequest {
36
+ status: "failed";
37
+ error: string;
38
+ }
39
+
40
+ export interface GenerationResponse {
41
+ status: RequestStatus;
42
+ request_id: string;
43
+ status_url: string;
44
+ cancel_url: string;
45
+ images?: Array<{ url: string }>;
46
+ video?: { url: string };
47
+ error?: string;
48
+ }
49
+
50
+ export class HiggsfieldClient {
51
+ private apiKey: string;
52
+ private apiSecret: string;
53
+
54
+ constructor(config?: HiggsfieldConfig) {
55
+ this.apiKey =
56
+ config?.apiKey ||
57
+ process.env.HIGGSFIELD_API_KEY ||
58
+ process.env.HF_API_KEY ||
59
+ "";
60
+ this.apiSecret =
61
+ config?.apiSecret ||
62
+ process.env.HIGGSFIELD_SECRET ||
63
+ process.env.HF_API_SECRET ||
64
+ "";
65
+
66
+ if (!this.apiKey || !this.apiSecret) {
67
+ throw new Error(
68
+ "Higgsfield API credentials not found. Set HIGGSFIELD_API_KEY and HIGGSFIELD_SECRET environment variables.",
69
+ );
70
+ }
71
+ }
72
+
73
+ private getAuthHeader(): string {
74
+ return `Key ${this.apiKey}:${this.apiSecret}`;
75
+ }
76
+
77
+ /**
78
+ * Submit a generation request to the queue
79
+ */
80
+ async submitRequest<T>(
81
+ modelId: string,
82
+ params: T,
83
+ webhook?: string,
84
+ ): Promise<GenerationResponse> {
85
+ const url = webhook
86
+ ? `${BASE_URL}/${modelId}?hf_webhook=${encodeURIComponent(webhook)}`
87
+ : `${BASE_URL}/${modelId}`;
88
+
89
+ console.log(`[higgsfield] submitting request to ${modelId}`);
90
+
91
+ const response = await fetch(url, {
92
+ method: "POST",
93
+ headers: {
94
+ Authorization: this.getAuthHeader(),
95
+ "Content-Type": "application/json",
96
+ Accept: "application/json",
97
+ },
98
+ body: JSON.stringify(params),
99
+ });
100
+
101
+ if (!response.ok) {
102
+ const errorText = await response.text();
103
+ throw new Error(
104
+ `Higgsfield API error (${response.status}): ${errorText}`,
105
+ );
106
+ }
107
+
108
+ const data = (await response.json()) as GenerationResponse;
109
+ console.log(`[higgsfield] request queued: ${data.request_id}`);
110
+ return data;
111
+ }
112
+
113
+ /**
114
+ * Get the status of a generation request
115
+ */
116
+ async getStatus(requestId: string): Promise<GenerationResponse> {
117
+ const url = `${BASE_URL}/requests/${requestId}/status`;
118
+
119
+ const response = await fetch(url, {
120
+ method: "GET",
121
+ headers: {
122
+ Authorization: this.getAuthHeader(),
123
+ Accept: "application/json",
124
+ },
125
+ });
126
+
127
+ if (!response.ok) {
128
+ const errorText = await response.text();
129
+ throw new Error(
130
+ `Higgsfield API error (${response.status}): ${errorText}`,
131
+ );
132
+ }
133
+
134
+ return (await response.json()) as GenerationResponse;
135
+ }
136
+
137
+ /**
138
+ * Cancel a pending request (only works in "queued" status)
139
+ */
140
+ async cancelRequest(requestId: string): Promise<boolean> {
141
+ const url = `${BASE_URL}/requests/${requestId}/cancel`;
142
+
143
+ console.log(`[higgsfield] canceling request: ${requestId}`);
144
+
145
+ const response = await fetch(url, {
146
+ method: "POST",
147
+ headers: {
148
+ Authorization: this.getAuthHeader(),
149
+ },
150
+ });
151
+
152
+ if (response.status === 202) {
153
+ console.log(`[higgsfield] request canceled successfully`);
154
+ return true;
155
+ }
156
+
157
+ if (response.status === 400) {
158
+ console.log(`[higgsfield] request cannot be canceled (already processing)`);
159
+ return false;
160
+ }
161
+
162
+ const errorText = await response.text();
163
+ throw new Error(`Higgsfield API error (${response.status}): ${errorText}`);
164
+ }
165
+
166
+ /**
167
+ * Wait for a request to complete with polling
168
+ */
169
+ async waitForCompletion(
170
+ requestId: string,
171
+ options: {
172
+ pollingInterval?: number;
173
+ maxWaitTime?: number;
174
+ onUpdate?: (status: GenerationResponse) => void;
175
+ } = {},
176
+ ): Promise<GenerationResponse> {
177
+ const pollingInterval = options.pollingInterval || 2000; // 2 seconds
178
+ const maxWaitTime = options.maxWaitTime || 300000; // 5 minutes
179
+ const startTime = Date.now();
180
+
181
+ while (true) {
182
+ const status = await this.getStatus(requestId);
183
+
184
+ if (options.onUpdate) {
185
+ options.onUpdate(status);
186
+ }
187
+
188
+ // Check if completed, failed, or nsfw
189
+ if (
190
+ status.status === "completed" ||
191
+ status.status === "failed" ||
192
+ status.status === "nsfw" ||
193
+ status.status === "canceled"
194
+ ) {
195
+ return status;
196
+ }
197
+
198
+ // Check timeout
199
+ if (Date.now() - startTime > maxWaitTime) {
200
+ throw new Error(
201
+ `Request timeout after ${maxWaitTime}ms. Request ID: ${requestId}`,
202
+ );
203
+ }
204
+
205
+ // Wait before next poll
206
+ await new Promise((resolve) => setTimeout(resolve, pollingInterval));
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Submit and wait for completion in one call
212
+ */
213
+ async generate<T>(
214
+ modelId: string,
215
+ params: T,
216
+ options: {
217
+ webhook?: string;
218
+ pollingInterval?: number;
219
+ maxWaitTime?: number;
220
+ onUpdate?: (status: GenerationResponse) => void;
221
+ } = {},
222
+ ): Promise<GenerationResponse> {
223
+ const request = await this.submitRequest(modelId, params, options.webhook);
224
+
225
+ // If webhook is provided, return immediately
226
+ if (options.webhook) {
227
+ console.log(`[higgsfield] webhook configured, returning request info`);
228
+ return request;
229
+ }
230
+
231
+ // Otherwise, wait for completion
232
+ return await this.waitForCompletion(request.request_id, {
233
+ pollingInterval: options.pollingInterval,
234
+ maxWaitTime: options.maxWaitTime,
235
+ onUpdate: options.onUpdate,
236
+ });
237
+ }
238
+ }
239
+
240
+ export default HiggsfieldClient;
241
+
@@ -0,0 +1,262 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Higgsfield Soul API - Image generation with Soul styles
4
+ */
5
+
6
+ import HiggsfieldClient, {
7
+ type GenerationResponse,
8
+ type HiggsfieldConfig,
9
+ } from "./index";
10
+
11
+ const BASE_URL = "https://platform.higgsfield.ai";
12
+
13
+ // Soul size options
14
+ export const SoulSize = {
15
+ PORTRAIT_1152x2048: "1152x2048",
16
+ PORTRAIT_2048x1152: "2048x1152",
17
+ SQUARE_2048x2048: "2048x2048",
18
+ LANDSCAPE_1536x2048: "1536x2048",
19
+ LANDSCAPE_2016x1344: "2016x1344",
20
+ } as const;
21
+
22
+ // Quality options
23
+ export const SoulQuality = {
24
+ SD: "720p",
25
+ HD: "1080p",
26
+ } as const;
27
+
28
+ // Batch size options
29
+ export const BatchSize = {
30
+ SINGLE: 1,
31
+ FOUR: 4,
32
+ } as const;
33
+
34
+ export interface SoulGenerationParams {
35
+ prompt: string;
36
+ width_and_height?: (typeof SoulSize)[keyof typeof SoulSize];
37
+ quality?: (typeof SoulQuality)[keyof typeof SoulQuality];
38
+ style_id?: string;
39
+ batch_size?: (typeof BatchSize)[keyof typeof BatchSize];
40
+ enhance_prompt?: boolean;
41
+ seed?: number;
42
+ style_strength?: number;
43
+ image_reference?: string;
44
+ custom_reference_id?: string;
45
+ custom_reference_strength?: number;
46
+ }
47
+
48
+ export interface SoulStyle {
49
+ id: string;
50
+ name: string;
51
+ preview_url: string;
52
+ description?: string;
53
+ }
54
+
55
+ export class SoulClient extends HiggsfieldClient {
56
+ private static readonly MODEL_ID = "soul";
57
+
58
+ constructor(config?: HiggsfieldConfig) {
59
+ super(config);
60
+ }
61
+
62
+ /**
63
+ * Generate Soul images
64
+ */
65
+ async generateSoul(
66
+ params: SoulGenerationParams,
67
+ options: {
68
+ webhook?: string;
69
+ pollingInterval?: number;
70
+ maxWaitTime?: number;
71
+ onUpdate?: (status: GenerationResponse) => void;
72
+ } = {},
73
+ ): Promise<GenerationResponse> {
74
+ console.log(`[higgsfield:soul] generating image`);
75
+ console.log(`[higgsfield:soul] prompt: ${params.prompt}`);
76
+
77
+ return await this.generate(SoulClient.MODEL_ID, params, {
78
+ ...options,
79
+ onUpdate: (status) => {
80
+ console.log(`[higgsfield:soul] status: ${status.status}`);
81
+ if (options.onUpdate) {
82
+ options.onUpdate(status);
83
+ }
84
+ },
85
+ });
86
+ }
87
+
88
+ /**
89
+ * Get available Soul styles
90
+ */
91
+ async getSoulStyles(): Promise<SoulStyle[]> {
92
+ console.log("[higgsfield:soul] fetching soul styles");
93
+
94
+ const url = `${BASE_URL}/v1/text2image/soul-styles`;
95
+
96
+ const response = await fetch(url, {
97
+ method: "GET",
98
+ headers: {
99
+ Authorization: `Key ${process.env.HIGGSFIELD_API_KEY || process.env.HF_API_KEY}:${process.env.HIGGSFIELD_SECRET || process.env.HF_API_SECRET}`,
100
+ Accept: "application/json",
101
+ },
102
+ });
103
+
104
+ if (!response.ok) {
105
+ const errorText = await response.text();
106
+ throw new Error(
107
+ `Higgsfield API error (${response.status}): ${errorText}`,
108
+ );
109
+ }
110
+
111
+ const styles = (await response.json()) as SoulStyle[];
112
+ console.log(`[higgsfield:soul] found ${styles.length} styles`);
113
+ return styles;
114
+ }
115
+ }
116
+
117
+ // Convenience function for generating Soul images
118
+ export async function generateSoul(
119
+ params: SoulGenerationParams,
120
+ config?: HiggsfieldConfig,
121
+ ): Promise<GenerationResponse> {
122
+ const client = new SoulClient(config);
123
+ return await client.generateSoul(params);
124
+ }
125
+
126
+ // Convenience function for listing styles
127
+ export async function listSoulStyles(
128
+ config?: HiggsfieldConfig,
129
+ ): Promise<SoulStyle[]> {
130
+ const client = new SoulClient(config);
131
+ return await client.getSoulStyles();
132
+ }
133
+
134
+ // CLI runner
135
+ if (import.meta.main) {
136
+ const [command, ...args] = process.argv.slice(2);
137
+
138
+ switch (command) {
139
+ case "generate": {
140
+ if (!args[0]) {
141
+ console.log(`
142
+ usage:
143
+ bun run lib/higgsfield/soul.ts generate <prompt> [styleId] [webhook]
144
+
145
+ examples:
146
+ bun run lib/higgsfield/soul.ts generate "beautiful sunset"
147
+ bun run lib/higgsfield/soul.ts generate "portrait of a woman" "style-id-123"
148
+ bun run lib/higgsfield/soul.ts generate "landscape" "" "https://webhook.url"
149
+ `);
150
+ process.exit(1);
151
+ }
152
+
153
+ const result = await generateSoul({
154
+ prompt: args[0],
155
+ style_id: args[1] || undefined,
156
+ width_and_height: SoulSize.PORTRAIT_1152x2048,
157
+ quality: SoulQuality.HD,
158
+ batch_size: BatchSize.SINGLE,
159
+ enhance_prompt: false,
160
+ });
161
+
162
+ console.log("\n=== Generation Result ===");
163
+ console.log(`Request ID: ${result.request_id}`);
164
+ console.log(`Status: ${result.status}`);
165
+
166
+ if (result.status === "completed" && result.images) {
167
+ console.log("\nGenerated Images:");
168
+ for (const image of result.images) {
169
+ console.log(` - ${image.url}`);
170
+ }
171
+ } else if (result.status === "failed") {
172
+ console.log(`\nError: ${result.error}`);
173
+ } else if (result.status === "nsfw") {
174
+ console.log("\nContent failed moderation (NSFW)");
175
+ }
176
+
177
+ break;
178
+ }
179
+
180
+ case "list_styles": {
181
+ const styles = await listSoulStyles();
182
+
183
+ console.log("\n=== Soul Styles ===");
184
+ for (const style of styles) {
185
+ console.log(`\nID: ${style.id}`);
186
+ console.log(`Name: ${style.name}`);
187
+ console.log(`Preview: ${style.preview_url}`);
188
+ if (style.description) {
189
+ console.log(`Description: ${style.description}`);
190
+ }
191
+ }
192
+
193
+ break;
194
+ }
195
+
196
+ case "status": {
197
+ if (!args[0]) {
198
+ console.log(`
199
+ usage:
200
+ bun run lib/higgsfield/soul.ts status <request_id>
201
+ `);
202
+ process.exit(1);
203
+ }
204
+
205
+ const client = new SoulClient();
206
+ const status = await client.getStatus(args[0]);
207
+
208
+ console.log("\n=== Request Status ===");
209
+ console.log(JSON.stringify(status, null, 2));
210
+
211
+ break;
212
+ }
213
+
214
+ case "cancel": {
215
+ if (!args[0]) {
216
+ console.log(`
217
+ usage:
218
+ bun run lib/higgsfield/soul.ts cancel <request_id>
219
+ `);
220
+ process.exit(1);
221
+ }
222
+
223
+ const client = new SoulClient();
224
+ const canceled = await client.cancelRequest(args[0]);
225
+
226
+ if (canceled) {
227
+ console.log("\n✓ Request canceled successfully");
228
+ } else {
229
+ console.log("\n✗ Request could not be canceled (already processing)");
230
+ }
231
+
232
+ break;
233
+ }
234
+
235
+ default:
236
+ console.log(`
237
+ usage:
238
+ bun run lib/higgsfield/soul.ts generate <prompt> [styleId] [webhook]
239
+ bun run lib/higgsfield/soul.ts list_styles
240
+ bun run lib/higgsfield/soul.ts status <request_id>
241
+ bun run lib/higgsfield/soul.ts cancel <request_id>
242
+
243
+ examples:
244
+ # Generate image
245
+ bun run lib/higgsfield/soul.ts generate "beautiful landscape"
246
+
247
+ # Generate with style
248
+ bun run lib/higgsfield/soul.ts generate "portrait" "style-id-123"
249
+
250
+ # List available styles
251
+ bun run lib/higgsfield/soul.ts list_styles
252
+
253
+ # Check request status
254
+ bun run lib/higgsfield/soul.ts status "request-id-here"
255
+
256
+ # Cancel pending request
257
+ bun run lib/higgsfield/soul.ts cancel "request-id-here"
258
+ `);
259
+ process.exit(1);
260
+ }
261
+ }
262
+
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * higgsfield client wrapper for soul image generation and character creation
4
+ * usage: bun run lib/higgsfield.ts <command> <args>
5
+ */
6
+
7
+ import {
8
+ BatchSize,
9
+ HiggsfieldClient,
10
+ InputImageType,
11
+ SoulQuality,
12
+ SoulSize,
13
+ } from "@higgsfield/client";
14
+
15
+ const client = new HiggsfieldClient({
16
+ apiKey: process.env.HIGGSFIELD_API_KEY || process.env.HF_API_KEY,
17
+ apiSecret: process.env.HIGGSFIELD_SECRET || process.env.HF_API_SECRET,
18
+ });
19
+
20
+ export interface GenerateSoulArgs {
21
+ prompt: string;
22
+ widthAndHeight?: (typeof SoulSize)[keyof typeof SoulSize];
23
+ quality?: (typeof SoulQuality)[keyof typeof SoulQuality];
24
+ styleId?: string;
25
+ batchSize?: (typeof BatchSize)[keyof typeof BatchSize];
26
+ enhancePrompt?: boolean;
27
+ }
28
+
29
+ export interface CreateSoulIdArgs {
30
+ name: string;
31
+ imageUrls: string[];
32
+ }
33
+
34
+ export async function generateSoul(args: GenerateSoulArgs) {
35
+ console.log("[higgsfield] generating soul image");
36
+ console.log(`[higgsfield] prompt: ${args.prompt}`);
37
+
38
+ try {
39
+ const jobSet = await client.generate("/v1/text2image/soul", {
40
+ prompt: args.prompt,
41
+ width_and_height: args.widthAndHeight || SoulSize.PORTRAIT_1152x2048,
42
+ quality: args.quality || SoulQuality.HD,
43
+ style_id: args.styleId,
44
+ batch_size: args.batchSize || BatchSize.SINGLE,
45
+ enhance_prompt: args.enhancePrompt ?? false,
46
+ });
47
+
48
+ console.log(`[higgsfield] job created: ${jobSet.id}`);
49
+ console.log(`[higgsfield] completed: ${jobSet.isCompleted}`);
50
+
51
+ return jobSet;
52
+ } catch (error) {
53
+ console.error("[higgsfield] error:", error);
54
+ throw error;
55
+ }
56
+ }
57
+
58
+ export async function listSoulStyles() {
59
+ console.log("[higgsfield] fetching soul styles");
60
+
61
+ try {
62
+ const styles = await client.getSoulStyles();
63
+ return styles;
64
+ } catch (error) {
65
+ console.error("[higgsfield] error:", error);
66
+ throw error;
67
+ }
68
+ }
69
+
70
+ export async function createSoulId(args: CreateSoulIdArgs) {
71
+ console.log(`[higgsfield] creating soul id: ${args.name}`);
72
+ console.log(`[higgsfield] images: ${args.imageUrls.length}`);
73
+
74
+ try {
75
+ const soulId = await client.createSoulId({
76
+ name: args.name,
77
+ input_images: args.imageUrls.map((url) => ({
78
+ type: InputImageType.IMAGE_URL,
79
+ image_url: url,
80
+ })),
81
+ });
82
+
83
+ console.log(`[higgsfield] soul id created: ${soulId.id}`);
84
+ return soulId;
85
+ } catch (error) {
86
+ console.error("[higgsfield] error:", error);
87
+ throw error;
88
+ }
89
+ }
90
+
91
+ export async function listSoulIds(page = 1, pageSize = 20) {
92
+ console.log("[higgsfield] listing soul ids");
93
+
94
+ try {
95
+ const soulIds = await client.listSoulIds(page, pageSize);
96
+ return soulIds;
97
+ } catch (error) {
98
+ console.error("[higgsfield] error:", error);
99
+ throw error;
100
+ }
101
+ }
102
+
103
+ // cli runner
104
+ if (import.meta.main) {
105
+ const [command, ...args] = process.argv.slice(2);
106
+
107
+ switch (command) {
108
+ case "generate_soul": {
109
+ if (!args[0]) {
110
+ console.log(`
111
+ usage:
112
+ bun run lib/higgsfield.ts generate_soul <prompt> [styleId]
113
+ `);
114
+ process.exit(1);
115
+ }
116
+ const soulResult = await generateSoul({
117
+ prompt: args[0],
118
+ styleId: args[1],
119
+ });
120
+
121
+ // print job status and results
122
+ console.log(`\njob id: ${soulResult.id}`);
123
+ console.log(
124
+ `status: completed=${soulResult.isCompleted}, failed=${soulResult.isFailed}`,
125
+ );
126
+
127
+ if (soulResult.isCompleted && soulResult.jobs.length > 0) {
128
+ for (const job of soulResult.jobs) {
129
+ if (job.results) {
130
+ console.log(`\nimage url: ${job.results.raw.url}`);
131
+ }
132
+ }
133
+ }
134
+ break;
135
+ }
136
+
137
+ case "list_styles": {
138
+ const styles = await listSoulStyles();
139
+ console.log(JSON.stringify(styles, null, 2));
140
+ break;
141
+ }
142
+
143
+ case "create_soul_id": {
144
+ if (!args[0] || !args[1]) {
145
+ console.log(`
146
+ usage:
147
+ bun run lib/higgsfield.ts create_soul_id <name> <imageUrl1> [imageUrl2...]
148
+ `);
149
+ process.exit(1);
150
+ }
151
+ const imageUrls = args.slice(1);
152
+ const soulIdResult = await createSoulId({
153
+ name: args[0],
154
+ imageUrls,
155
+ });
156
+ console.log(JSON.stringify(soulIdResult, null, 2));
157
+ break;
158
+ }
159
+
160
+ case "list_soul_ids": {
161
+ const soulIds = await listSoulIds();
162
+ console.log(JSON.stringify(soulIds, null, 2));
163
+ break;
164
+ }
165
+
166
+ default:
167
+ console.log(`
168
+ usage:
169
+ bun run lib/higgsfield.ts generate_soul <prompt> [styleId]
170
+ bun run lib/higgsfield.ts list_styles
171
+ bun run lib/higgsfield.ts create_soul_id <name> <imageUrl1> [imageUrl2...]
172
+ bun run lib/higgsfield.ts list_soul_ids
173
+ `);
174
+ process.exit(1);
175
+ }
176
+ }