@gptmarket/temporal-types 0.0.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.
package/client.ts ADDED
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Temporal client utilities for Next.js.
3
+ * Auto-generated - DO NOT EDIT MANUALLY
4
+ */
5
+
6
+ import { Client, Connection, WorkflowHandle } from "@temporalio/client";
7
+ import type { WorkflowProgress, StepProgress, WorkflowStatus } from "./types";
8
+
9
+ // =============================================================================
10
+ // Configuration
11
+ // =============================================================================
12
+
13
+ export interface TemporalConfig {
14
+ host: string;
15
+ namespace: string;
16
+ taskQueue: string;
17
+ }
18
+
19
+ const defaultConfig: TemporalConfig = {
20
+ host: process.env.TEMPORAL_HOST || "localhost:7233",
21
+ namespace: process.env.TEMPORAL_NAMESPACE || "default",
22
+ taskQueue: process.env.TEMPORAL_TASK_QUEUE || "generation-queue",
23
+ };
24
+
25
+ let _client: Client | null = null;
26
+ let _config: TemporalConfig = defaultConfig;
27
+
28
+ /**
29
+ * Configure the Temporal client.
30
+ * Call this once at app startup if you need custom settings.
31
+ */
32
+ export function configureTemporalClient(config: Partial<TemporalConfig>): void {
33
+ _config = { ...defaultConfig, ...config };
34
+ _client = null; // Reset client to use new config
35
+ }
36
+
37
+ /**
38
+ * Get or create the Temporal client (singleton).
39
+ */
40
+ export async function getTemporalClient(): Promise<Client> {
41
+ if (!_client) {
42
+ const connection = await Connection.connect({
43
+ address: _config.host,
44
+ });
45
+
46
+ _client = new Client({
47
+ connection,
48
+ namespace: _config.namespace,
49
+ });
50
+ }
51
+
52
+ return _client;
53
+ }
54
+
55
+ /**
56
+ * Get the current task queue.
57
+ */
58
+ export function getTaskQueue(): string {
59
+ return _config.taskQueue;
60
+ }
61
+
62
+ // =============================================================================
63
+ // Workflow Execution
64
+ // =============================================================================
65
+
66
+ export interface StartWorkflowResult {
67
+ workflowId: string;
68
+ }
69
+
70
+ /**
71
+ * Start a workflow and return its ID.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * const { workflowId } = await startWorkflow('RubyWorkflow', { topic: 'AI news' });
76
+ * ```
77
+ */
78
+ export async function startWorkflow<TInput>(
79
+ workflowName: string,
80
+ input: TInput,
81
+ options?: { id?: string; idPrefix?: string },
82
+ ): Promise<StartWorkflowResult> {
83
+ const client = await getTemporalClient();
84
+ const workflowId =
85
+ options?.id ||
86
+ `${options?.idPrefix || workflowName.toLowerCase()}-${randomId()}`;
87
+
88
+ await client.workflow.start(workflowName, {
89
+ taskQueue: _config.taskQueue,
90
+ workflowId,
91
+ args: [input],
92
+ });
93
+
94
+ return { workflowId };
95
+ }
96
+
97
+ /**
98
+ * Get the current progress of a workflow.
99
+ */
100
+ export async function getWorkflowProgress(
101
+ workflowId: string,
102
+ ): Promise<WorkflowProgress> {
103
+ const client = await getTemporalClient();
104
+ const handle = client.workflow.getHandle(workflowId);
105
+
106
+ try {
107
+ const description = await handle.describe();
108
+ const executionStatus = description.status.name;
109
+
110
+ let status: WorkflowStatus = "pending";
111
+ let currentStep: StepProgress | null = null;
112
+ let result: unknown = undefined;
113
+ let error: string | undefined = undefined;
114
+
115
+ if (isWorkflowRunning(executionStatus)) {
116
+ try {
117
+ status = await handle.query<WorkflowStatus>("get_status");
118
+ currentStep = await handle.query<StepProgress>("get_current_step");
119
+ } catch {
120
+ status = "running";
121
+ }
122
+ } else if (executionStatus === "COMPLETED") {
123
+ status = "completed";
124
+ try {
125
+ result = await handle.result();
126
+ } catch (e) {
127
+ error = String(e);
128
+ }
129
+ } else if (
130
+ executionStatus === "FAILED" ||
131
+ executionStatus === "TERMINATED" ||
132
+ executionStatus === "TIMED_OUT"
133
+ ) {
134
+ status = "failed";
135
+ error = `Workflow ${executionStatus.toLowerCase()}`;
136
+ } else if (executionStatus === "CANCELLED") {
137
+ status = "cancelled";
138
+ }
139
+
140
+ return {
141
+ workflowId,
142
+ status,
143
+ executionStatus,
144
+ currentStep,
145
+ result,
146
+ error,
147
+ };
148
+ } catch (e) {
149
+ return {
150
+ workflowId,
151
+ status: "failed",
152
+ executionStatus: "NOT_FOUND",
153
+ currentStep: null,
154
+ error: `Workflow not found: ${String(e)}`,
155
+ };
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Wait for a workflow to complete and return its result.
161
+ */
162
+ export async function waitForWorkflow<TResult>(
163
+ workflowId: string,
164
+ timeoutMs: number = 300000,
165
+ ): Promise<{ result?: TResult; error?: string; timedOut?: boolean }> {
166
+ const client = await getTemporalClient();
167
+ const handle = client.workflow.getHandle(workflowId);
168
+
169
+ try {
170
+ const result = await Promise.race([
171
+ handle.result() as Promise<TResult>,
172
+ new Promise<never>((_, reject) =>
173
+ setTimeout(() => reject(new Error("TIMEOUT")), timeoutMs),
174
+ ),
175
+ ]);
176
+ return { result };
177
+ } catch (e) {
178
+ const errorStr = String(e);
179
+ if (errorStr.includes("TIMEOUT")) {
180
+ return { timedOut: true };
181
+ }
182
+ return { error: errorStr };
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Cancel a running workflow.
188
+ */
189
+ export async function cancelWorkflow(
190
+ workflowId: string,
191
+ ): Promise<{ success: boolean; error?: string }> {
192
+ const client = await getTemporalClient();
193
+ const handle = client.workflow.getHandle(workflowId);
194
+
195
+ try {
196
+ await handle.cancel();
197
+ return { success: true };
198
+ } catch (e) {
199
+ return { success: false, error: String(e) };
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Get a handle to an existing workflow.
205
+ */
206
+ export async function getWorkflowHandle(
207
+ workflowId: string,
208
+ ): Promise<WorkflowHandle> {
209
+ const client = await getTemporalClient();
210
+ return client.workflow.getHandle(workflowId);
211
+ }
212
+
213
+ // =============================================================================
214
+ // Helpers
215
+ // =============================================================================
216
+
217
+ function randomId(): string {
218
+ return Math.random().toString(36).substring(2, 14);
219
+ }
220
+
221
+ function isWorkflowRunning(status: string): boolean {
222
+ return status === "RUNNING" || status === "CONTINUED_AS_NEW";
223
+ }
package/index.ts ADDED
@@ -0,0 +1,43 @@
1
+ /**
2
+ * GPTMarket Temporal Types
3
+ *
4
+ * Types, workflow registry, and client utilities for GPTMarket Temporal workflows.
5
+ *
6
+ * @example Start a workflow
7
+ * ```ts
8
+ * import { startWorkflow, waitForWorkflow } from '@gptmarket/temporal-types/client';
9
+ * import type { RubyInput, RubyOutput } from '@gptmarket/temporal-types';
10
+ *
11
+ * const { workflowId } = await startWorkflow('RubyWorkflow', { topic: 'AI news' });
12
+ * const { result } = await waitForWorkflow<RubyOutput>(workflowId);
13
+ * ```
14
+ *
15
+ * @example Dynamic form generation
16
+ * ```ts
17
+ * import { workflowRegistry } from '@gptmarket/temporal-types';
18
+ *
19
+ * const ruby = workflowRegistry.ruby;
20
+ * ruby.fields.forEach(field => {
21
+ * console.log(field.name, field.type, field.options);
22
+ * });
23
+ * ```
24
+ */
25
+
26
+ // Types
27
+ export * from "./types";
28
+
29
+ // Workflow registry and definitions
30
+ export * from "./registry";
31
+
32
+ // Client utilities
33
+ export {
34
+ configureTemporalClient,
35
+ getTemporalClient,
36
+ getTaskQueue,
37
+ startWorkflow,
38
+ getWorkflowProgress,
39
+ waitForWorkflow,
40
+ cancelWorkflow,
41
+ getWorkflowHandle,
42
+ } from "./client";
43
+ export type { TemporalConfig, StartWorkflowResult } from "./client";
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@gptmarket/temporal-types",
3
+ "version": "0.0.1",
4
+ "description": "TypeScript types, workflow registry, and client utilities for GPTMarket Temporal workflows",
5
+ "main": "index.ts",
6
+ "types": "index.ts",
7
+ "exports": {
8
+ ".": "./index.ts",
9
+ "./types": "./types.ts",
10
+ "./registry": "./registry.ts",
11
+ "./client": "./client.ts"
12
+ },
13
+ "files": [
14
+ "index.ts",
15
+ "types.ts",
16
+ "registry.ts",
17
+ "client.ts",
18
+ "schemas/"
19
+ ],
20
+ "peerDependencies": {
21
+ "@temporalio/client": ">=1.0.0"
22
+ },
23
+ "keywords": [
24
+ "temporal",
25
+ "gptmarket",
26
+ "types",
27
+ "typescript",
28
+ "workflows"
29
+ ],
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/gptmarket/gptmarket-generator.git"
34
+ }
35
+ }
package/registry.ts ADDED
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Auto-generated workflow registry for dynamic form generation.
3
+ * DO NOT EDIT MANUALLY - run `make types`
4
+ */
5
+
6
+ import type * as Types from "./types";
7
+
8
+ // =============================================================================
9
+ // Field Types
10
+ // =============================================================================
11
+
12
+ export type FieldType =
13
+ | "text"
14
+ | "textarea"
15
+ | "number"
16
+ | "select"
17
+ | "checkbox"
18
+ | "json";
19
+
20
+ export interface SelectOption {
21
+ value: string;
22
+ label: string;
23
+ }
24
+
25
+ export interface FieldValidation {
26
+ min?: number;
27
+ max?: number;
28
+ minLength?: number;
29
+ maxLength?: number;
30
+ pattern?: string;
31
+ }
32
+
33
+ export interface FieldDefinition {
34
+ name: string;
35
+ type: FieldType;
36
+ label: string;
37
+ description: string;
38
+ required: boolean;
39
+ default: unknown;
40
+ options?: SelectOption[];
41
+ validation?: FieldValidation;
42
+ hidden?: boolean;
43
+ }
44
+
45
+ // =============================================================================
46
+ // Workflow Definition
47
+ // =============================================================================
48
+
49
+ export interface WorkflowDefinition<TInput = unknown, TOutput = unknown> {
50
+ id: string;
51
+ name: string;
52
+ description: string;
53
+ workflowClass: string;
54
+ inputType: string;
55
+ outputType: string;
56
+ fields: FieldDefinition[];
57
+ }
58
+
59
+ // =============================================================================
60
+ // Workflow Definitions
61
+ // =============================================================================
62
+
63
+ export const ruby: WorkflowDefinition<Types.RubyInput, Types.RubyOutput> = {
64
+ id: "ruby",
65
+ name: "Ruby",
66
+ description: "Ruby - AI Influencer for Short-form Videos.",
67
+ workflowClass: "RubyWorkflow",
68
+ inputType: "RubyInput",
69
+ outputType: "RubyOutput",
70
+ fields: [
71
+ {
72
+ name: "topic",
73
+ type: "text",
74
+ label: "Topic",
75
+ description: "What the influencer is reacting to",
76
+ required: true,
77
+ default: null,
78
+ },
79
+ {
80
+ name: "emotion",
81
+ type: "select",
82
+ label: "Emotion",
83
+ description: "Emotion: shocked, scared, surprised, worried, excited",
84
+ required: false,
85
+ default: "shocked",
86
+ options: [
87
+ { value: "shocked", label: "Shocked" },
88
+ { value: "scared", label: "Scared" },
89
+ { value: "surprised", label: "Surprised" },
90
+ { value: "worried", label: "Worried" },
91
+ { value: "excited", label: "Excited" },
92
+ ],
93
+ },
94
+ {
95
+ name: "hook",
96
+ type: "text",
97
+ label: "Hook",
98
+ description: 'Text overlay (e.g., "You won\'t believe this...")',
99
+ required: false,
100
+ default: "",
101
+ },
102
+ {
103
+ name: "style",
104
+ type: "select",
105
+ label: "Style",
106
+ description: "Style: realistic or stylized",
107
+ required: false,
108
+ default: "realistic",
109
+ options: [
110
+ { value: "realistic", label: "Realistic" },
111
+ { value: "stylized", label: "Stylized" },
112
+ ],
113
+ },
114
+ {
115
+ name: "gender",
116
+ type: "select",
117
+ label: "Gender",
118
+ description: "Gender: female or male",
119
+ required: false,
120
+ default: "female",
121
+ options: [
122
+ { value: "female", label: "Female" },
123
+ { value: "male", label: "Male" },
124
+ ],
125
+ },
126
+ {
127
+ name: "aspect_ratio",
128
+ type: "select",
129
+ label: "Aspect Ratio",
130
+ description: "Aspect ratio: 9:16, 16:9, 1:1",
131
+ required: false,
132
+ default: "9:16",
133
+ options: [
134
+ { value: "9:16", label: "9:16" },
135
+ { value: "16:9", label: "16:9" },
136
+ { value: "1:1", label: "1:1" },
137
+ ],
138
+ },
139
+ {
140
+ name: "image_model",
141
+ type: "text",
142
+ label: "Image Model",
143
+ description: "Image model ID from registry",
144
+ required: false,
145
+ default: "hidream-fast",
146
+ hidden: true,
147
+ },
148
+ {
149
+ name: "video_model",
150
+ type: "text",
151
+ label: "Video Model",
152
+ description: "Video model ID from registry",
153
+ required: false,
154
+ default: "seedance-1.5-pro",
155
+ hidden: true,
156
+ },
157
+ {
158
+ name: "image_model_params",
159
+ type: "json",
160
+ label: "Image Model Params",
161
+ description:
162
+ 'Override image model params (e.g., {"speed_mode": "Extra Juiced 🚀"})',
163
+ required: false,
164
+ default: null,
165
+ hidden: true,
166
+ },
167
+ {
168
+ name: "video_model_params",
169
+ type: "json",
170
+ label: "Video Model Params",
171
+ description:
172
+ 'Override video model params (e.g., {"camera_fixed": False})',
173
+ required: false,
174
+ default: null,
175
+ hidden: true,
176
+ },
177
+ {
178
+ name: "slow_motion_factor",
179
+ type: "number",
180
+ label: "Slow Motion Factor",
181
+ description: "Speed factor (0.5 = half speed)",
182
+ required: false,
183
+ default: 0.7,
184
+ },
185
+ {
186
+ name: "video_duration",
187
+ type: "number",
188
+ label: "Video Duration",
189
+ description: "Video duration in seconds",
190
+ required: false,
191
+ default: 5,
192
+ },
193
+ ],
194
+ };
195
+
196
+ export const slideshows_pinterest: WorkflowDefinition<
197
+ Types.SlideshowsPinterestInput,
198
+ Types.SlideshowsPinterestOutput
199
+ > = {
200
+ id: "slideshows_pinterest",
201
+ name: "Slideshows Pinterest",
202
+ description: "Pinterest Slideshow Generator.",
203
+ workflowClass: "SlideshowsPinterestWorkflow",
204
+ inputType: "SlideshowsPinterestInput",
205
+ outputType: "SlideshowsPinterestOutput",
206
+ fields: [
207
+ {
208
+ name: "prompt",
209
+ type: "textarea",
210
+ label: "Prompt",
211
+ description: "User text describing what kind of images they want",
212
+ required: true,
213
+ default: null,
214
+ },
215
+ {
216
+ name: "num_images",
217
+ type: "number",
218
+ label: "Num Images",
219
+ description: "Number of images to return",
220
+ required: false,
221
+ default: 10,
222
+ validation: { min: 1, max: 50 },
223
+ },
224
+ {
225
+ name: "num_queries",
226
+ type: "number",
227
+ label: "Num Queries",
228
+ description: "Number of search queries to generate",
229
+ required: false,
230
+ default: 3,
231
+ validation: { min: 1, max: 5 },
232
+ },
233
+ {
234
+ name: "pages_per_query",
235
+ type: "number",
236
+ label: "Pages Per Query",
237
+ description: "Pages to scrape per query",
238
+ required: false,
239
+ default: 1,
240
+ validation: { min: 1, max: 3 },
241
+ },
242
+ ],
243
+ };
244
+
245
+ // =============================================================================
246
+ // Registry
247
+ // =============================================================================
248
+
249
+ export const workflowRegistry = {
250
+ ruby,
251
+ slideshows_pinterest,
252
+ } as const;
253
+
254
+ export type WorkflowId = keyof typeof workflowRegistry;
255
+
256
+ // =============================================================================
257
+ // Helpers
258
+ // =============================================================================
259
+
260
+ export function getWorkflow<T extends WorkflowId>(
261
+ id: T,
262
+ ): (typeof workflowRegistry)[T] {
263
+ return workflowRegistry[id];
264
+ }
265
+
266
+ export function getAllWorkflows(): WorkflowDefinition[] {
267
+ return Object.values(workflowRegistry);
268
+ }
269
+
270
+ export function getWorkflowIds(): WorkflowId[] {
271
+ return Object.keys(workflowRegistry) as WorkflowId[];
272
+ }
273
+
274
+ // Type mappings
275
+ export type WorkflowInputMap = {
276
+ ruby: Types.RubyInput;
277
+ slideshows_pinterest: Types.SlideshowsPinterestInput;
278
+ };
279
+
280
+ export type WorkflowOutputMap = {
281
+ ruby: Types.RubyOutput;
282
+ slideshows_pinterest: Types.SlideshowsPinterestOutput;
283
+ };
@@ -0,0 +1,81 @@
1
+ {
2
+ "description": "Input for Ruby generation.",
3
+ "properties": {
4
+ "topic": {
5
+ "description": "What the influencer is reacting to",
6
+ "title": "Topic",
7
+ "type": "string"
8
+ },
9
+ "emotion": {
10
+ "default": "shocked",
11
+ "description": "Emotion: shocked, scared, surprised, worried, excited",
12
+ "title": "Emotion",
13
+ "type": "string"
14
+ },
15
+ "hook": {
16
+ "default": "",
17
+ "description": "Text overlay (e.g., \"You won't believe this...\")",
18
+ "title": "Hook",
19
+ "type": "string"
20
+ },
21
+ "style": {
22
+ "default": "realistic",
23
+ "description": "Style: realistic or stylized",
24
+ "title": "Style",
25
+ "type": "string"
26
+ },
27
+ "gender": {
28
+ "default": "female",
29
+ "description": "Gender: female or male",
30
+ "title": "Gender",
31
+ "type": "string"
32
+ },
33
+ "aspect_ratio": {
34
+ "default": "9:16",
35
+ "description": "Aspect ratio: 9:16, 16:9, 1:1",
36
+ "title": "Aspect Ratio",
37
+ "type": "string"
38
+ },
39
+ "image_model": {
40
+ "default": "hidream-fast",
41
+ "description": "Image model ID from registry",
42
+ "title": "Image Model",
43
+ "type": "string"
44
+ },
45
+ "video_model": {
46
+ "default": "seedance-1.5-pro",
47
+ "description": "Video model ID from registry",
48
+ "title": "Video Model",
49
+ "type": "string"
50
+ },
51
+ "image_model_params": {
52
+ "additionalProperties": true,
53
+ "description": "Override image model params (e.g., {\"speed_mode\": \"Extra Juiced \ud83d\ude80\"})",
54
+ "title": "Image Model Params",
55
+ "type": "object"
56
+ },
57
+ "video_model_params": {
58
+ "additionalProperties": true,
59
+ "description": "Override video model params (e.g., {\"camera_fixed\": False})",
60
+ "title": "Video Model Params",
61
+ "type": "object"
62
+ },
63
+ "slow_motion_factor": {
64
+ "default": 0.7,
65
+ "description": "Speed factor (0.5 = half speed)",
66
+ "title": "Slow Motion Factor",
67
+ "type": "number"
68
+ },
69
+ "video_duration": {
70
+ "default": 5,
71
+ "description": "Video duration in seconds",
72
+ "title": "Video Duration",
73
+ "type": "integer"
74
+ }
75
+ },
76
+ "required": [
77
+ "topic"
78
+ ],
79
+ "title": "RubyInput",
80
+ "type": "object"
81
+ }
@@ -0,0 +1,51 @@
1
+ {
2
+ "description": "Output from Ruby generation.",
3
+ "properties": {
4
+ "face_image_url": {
5
+ "description": "URL of generated face image",
6
+ "title": "Face Image Url",
7
+ "type": "string"
8
+ },
9
+ "raw_video_url": {
10
+ "description": "URL of raw video before effects",
11
+ "title": "Raw Video Url",
12
+ "type": "string"
13
+ },
14
+ "final_video_url": {
15
+ "description": "URL of final video with all effects",
16
+ "title": "Final Video Url",
17
+ "type": "string"
18
+ },
19
+ "enhanced_image_prompt": {
20
+ "description": "The enhanced prompt used for face generation",
21
+ "title": "Enhanced Image Prompt",
22
+ "type": "string"
23
+ },
24
+ "enhanced_video_prompt": {
25
+ "description": "The enhanced prompt used for video generation",
26
+ "title": "Enhanced Video Prompt",
27
+ "type": "string"
28
+ },
29
+ "image_model": {
30
+ "description": "Image model used",
31
+ "title": "Image Model",
32
+ "type": "string"
33
+ },
34
+ "video_model": {
35
+ "description": "Video model used",
36
+ "title": "Video Model",
37
+ "type": "string"
38
+ }
39
+ },
40
+ "required": [
41
+ "face_image_url",
42
+ "raw_video_url",
43
+ "final_video_url",
44
+ "enhanced_image_prompt",
45
+ "enhanced_video_prompt",
46
+ "image_model",
47
+ "video_model"
48
+ ],
49
+ "title": "RubyOutput",
50
+ "type": "object"
51
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "description": "Input for Pinterest slideshow generation.",
3
+ "properties": {
4
+ "prompt": {
5
+ "description": "User text describing what kind of images they want",
6
+ "title": "Prompt",
7
+ "type": "string"
8
+ },
9
+ "num_images": {
10
+ "default": 10,
11
+ "description": "Number of images to return",
12
+ "maximum": 50,
13
+ "minimum": 1,
14
+ "title": "Num Images",
15
+ "type": "integer"
16
+ },
17
+ "num_queries": {
18
+ "default": 3,
19
+ "description": "Number of search queries to generate",
20
+ "maximum": 5,
21
+ "minimum": 1,
22
+ "title": "Num Queries",
23
+ "type": "integer"
24
+ },
25
+ "pages_per_query": {
26
+ "default": 1,
27
+ "description": "Pages to scrape per query",
28
+ "maximum": 3,
29
+ "minimum": 1,
30
+ "title": "Pages Per Query",
31
+ "type": "integer"
32
+ }
33
+ },
34
+ "required": [
35
+ "prompt"
36
+ ],
37
+ "title": "SlideshowsPinterestInput",
38
+ "type": "object"
39
+ }
@@ -0,0 +1,110 @@
1
+ {
2
+ "$defs": {
3
+ "PinterestImage": {
4
+ "description": "A single Pinterest image result.",
5
+ "properties": {
6
+ "id": {
7
+ "description": "Pin ID",
8
+ "title": "Id",
9
+ "type": "string"
10
+ },
11
+ "title": {
12
+ "anyOf": [
13
+ {
14
+ "type": "string"
15
+ },
16
+ {
17
+ "type": "null"
18
+ }
19
+ ],
20
+ "default": null,
21
+ "description": "Pin title",
22
+ "title": "Title"
23
+ },
24
+ "description": {
25
+ "anyOf": [
26
+ {
27
+ "type": "string"
28
+ },
29
+ {
30
+ "type": "null"
31
+ }
32
+ ],
33
+ "default": null,
34
+ "description": "Pin description",
35
+ "title": "Description"
36
+ },
37
+ "image_url": {
38
+ "description": "Image URL",
39
+ "title": "Image Url",
40
+ "type": "string"
41
+ },
42
+ "aspect_ratio": {
43
+ "description": "Aspect ratio (e.g., 9:16)",
44
+ "title": "Aspect Ratio",
45
+ "type": "string"
46
+ },
47
+ "image_width": {
48
+ "anyOf": [
49
+ {
50
+ "type": "integer"
51
+ },
52
+ {
53
+ "type": "null"
54
+ }
55
+ ],
56
+ "default": null,
57
+ "description": "Image width in pixels",
58
+ "title": "Image Width"
59
+ },
60
+ "image_height": {
61
+ "anyOf": [
62
+ {
63
+ "type": "integer"
64
+ },
65
+ {
66
+ "type": "null"
67
+ }
68
+ ],
69
+ "default": null,
70
+ "description": "Image height in pixels",
71
+ "title": "Image Height"
72
+ }
73
+ },
74
+ "required": [
75
+ "id",
76
+ "image_url",
77
+ "aspect_ratio"
78
+ ],
79
+ "title": "PinterestImage",
80
+ "type": "object"
81
+ }
82
+ },
83
+ "description": "Output from Pinterest slideshow generation.",
84
+ "properties": {
85
+ "images": {
86
+ "description": "List of Pinterest images",
87
+ "items": {
88
+ "$ref": "#/$defs/PinterestImage"
89
+ },
90
+ "title": "Images",
91
+ "type": "array"
92
+ },
93
+ "queries_used": {
94
+ "description": "Search queries that were used",
95
+ "items": {
96
+ "type": "string"
97
+ },
98
+ "title": "Queries Used",
99
+ "type": "array"
100
+ },
101
+ "total_scraped": {
102
+ "default": 0,
103
+ "description": "Total pins scraped before filtering",
104
+ "title": "Total Scraped",
105
+ "type": "integer"
106
+ }
107
+ },
108
+ "title": "SlideshowsPinterestOutput",
109
+ "type": "object"
110
+ }
package/types.ts ADDED
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Auto-generated TypeScript types from Pydantic schemas.
3
+ * DO NOT EDIT MANUALLY - run `make types`
4
+ */
5
+
6
+ // =============================================================================
7
+ // Common Types
8
+ // =============================================================================
9
+
10
+ export type WorkflowStatus =
11
+ | "pending"
12
+ | "running"
13
+ | "completed"
14
+ | "failed"
15
+ | "cancelled";
16
+
17
+ export interface StepProgress {
18
+ step_id: string;
19
+ step_name: string;
20
+ status: WorkflowStatus;
21
+ progress_pct: number;
22
+ message: string | null;
23
+ }
24
+
25
+ export interface WorkflowProgress<TResult = unknown> {
26
+ workflowId: string;
27
+ status: WorkflowStatus;
28
+ executionStatus: string;
29
+ currentStep: StepProgress | null;
30
+ result?: TResult;
31
+ error?: string;
32
+ }
33
+
34
+ // =============================================================================
35
+ // Workflow Schemas
36
+ // =============================================================================
37
+
38
+ export interface RubyInput {
39
+ /** What the influencer is reacting to */
40
+ topic: string;
41
+ /** Emotion: shocked, scared, surprised, worried, excited */
42
+ emotion?: string;
43
+ /** Text overlay (e.g., "You won't believe this...") */
44
+ hook?: string;
45
+ /** Style: realistic or stylized */
46
+ style?: string;
47
+ /** Gender: female or male */
48
+ gender?: string;
49
+ /** Aspect ratio: 9:16, 16:9, 1:1 */
50
+ aspect_ratio?: string;
51
+ /** Image model ID from registry */
52
+ image_model?: string;
53
+ /** Video model ID from registry */
54
+ video_model?: string;
55
+ /** Override image model params (e.g., {"speed_mode": "Extra Juiced 🚀"}) */
56
+ image_model_params?: Record<string, unknown>;
57
+ /** Override video model params (e.g., {"camera_fixed": False}) */
58
+ video_model_params?: Record<string, unknown>;
59
+ /** Speed factor (0.5 = half speed) */
60
+ slow_motion_factor?: number;
61
+ /** Video duration in seconds */
62
+ video_duration?: number;
63
+ }
64
+
65
+ export interface RubyOutput {
66
+ /** URL of generated face image */
67
+ face_image_url: string;
68
+ /** URL of raw video before effects */
69
+ raw_video_url: string;
70
+ /** URL of final video with all effects */
71
+ final_video_url: string;
72
+ /** The enhanced prompt used for face generation */
73
+ enhanced_image_prompt: string;
74
+ /** The enhanced prompt used for video generation */
75
+ enhanced_video_prompt: string;
76
+ /** Image model used */
77
+ image_model: string;
78
+ /** Video model used */
79
+ video_model: string;
80
+ }
81
+
82
+ export interface SlideshowsPinterestInput {
83
+ /** User text describing what kind of images they want */
84
+ prompt: string;
85
+ /** Number of images to return */
86
+ num_images?: number;
87
+ /** Number of search queries to generate */
88
+ num_queries?: number;
89
+ /** Pages to scrape per query */
90
+ pages_per_query?: number;
91
+ }
92
+
93
+ export interface SlideshowsPinterestOutput {
94
+ /** List of Pinterest images */
95
+ images?: {
96
+ id: string;
97
+ title?: string | null;
98
+ description?: string | null;
99
+ image_url: string;
100
+ aspect_ratio: string;
101
+ image_width?: number | null;
102
+ image_height?: number | null;
103
+ }[];
104
+ /** Search queries that were used */
105
+ queries_used?: string[];
106
+ /** Total pins scraped before filtering */
107
+ total_scraped?: number;
108
+ }