ugcinc 4.5.77 → 4.5.78
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/dist/automations/index.d.ts +1 -1
- package/dist/automations/nodes/api-request.d.ts +29 -0
- package/dist/automations/nodes/api-request.js +103 -0
- package/dist/automations/nodes/index.d.ts +12 -0
- package/dist/automations/nodes/index.js +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -2
- package/dist/skills.js +118 -50
- package/dist/tools/automations.js +195 -15
- package/package.json +1 -1
|
@@ -26,7 +26,7 @@ export declare class AutomationsClient extends BaseClient {
|
|
|
26
26
|
* @param skipValidation - If true, skips workflow validation (for saving drafts)
|
|
27
27
|
*/
|
|
28
28
|
createTemplate(params: {
|
|
29
|
-
orgId
|
|
29
|
+
orgId?: string;
|
|
30
30
|
name: string;
|
|
31
31
|
description?: string;
|
|
32
32
|
workflowDefinition: WorkflowDefinition;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { PortValue } from '../types';
|
|
2
|
+
import { type ObjectSchemaField, type OutputMode, type SelectionMode } from './types';
|
|
3
|
+
/** API Request inputs are dynamic (template variables in URL, headers, body). */
|
|
4
|
+
export type ApiRequestNodeInputs = Record<string, PortValue | PortValue[]>;
|
|
5
|
+
/** API Request outputs are dynamic based on outputFields config. */
|
|
6
|
+
export type ApiRequestNodeOutputs = Record<string, PortValue | PortValue[]>;
|
|
7
|
+
declare const HttpMethods: readonly ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
8
|
+
type HttpMethod = typeof HttpMethods[number];
|
|
9
|
+
export interface HeaderEntry {
|
|
10
|
+
key: string;
|
|
11
|
+
value: string;
|
|
12
|
+
}
|
|
13
|
+
declare const definition: import("./types").NodeDefinition<"api-request", "generator", {
|
|
14
|
+
url: string;
|
|
15
|
+
method: HttpMethod;
|
|
16
|
+
headers: HeaderEntry[];
|
|
17
|
+
body: string;
|
|
18
|
+
outputFields: ObjectSchemaField[];
|
|
19
|
+
outputMode: OutputMode;
|
|
20
|
+
selectionMode: SelectionMode | null;
|
|
21
|
+
}, ApiRequestNodeInputs, ApiRequestNodeOutputs, false>;
|
|
22
|
+
declare const _default: typeof definition & {
|
|
23
|
+
__TInputs: ApiRequestNodeInputs;
|
|
24
|
+
__TOutputs: ApiRequestNodeOutputs;
|
|
25
|
+
};
|
|
26
|
+
export default _default;
|
|
27
|
+
export { HttpMethods };
|
|
28
|
+
export type { HttpMethod };
|
|
29
|
+
export type ApiRequestNodeConfig = typeof definition.defaults;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpMethods = void 0;
|
|
4
|
+
const utils_1 = require("../utils");
|
|
5
|
+
const types_1 = require("./types");
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// Config Types
|
|
8
|
+
// =============================================================================
|
|
9
|
+
const HttpMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
|
|
10
|
+
exports.HttpMethods = HttpMethods;
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Node Definition
|
|
13
|
+
// =============================================================================
|
|
14
|
+
const definition = (0, types_1.defineNode)({
|
|
15
|
+
nodeId: 'api-request',
|
|
16
|
+
label: 'API Request',
|
|
17
|
+
description: 'Make HTTP requests to external APIs',
|
|
18
|
+
guide: 'Makes HTTP requests to external APIs and returns parsed response data. Use when you need to fetch data from or send data to external services. Configure URL, method (GET/POST/PUT/PATCH/DELETE), headers, and body. Supports template variables ({{var}}) in URL, header values, and body for dynamic values from upstream nodes. Define output fields to extract specific data from JSON responses. Use cases: fetching external data, triggering webhooks, integrating third-party APIs, sending data to external services.',
|
|
19
|
+
type: 'generator',
|
|
20
|
+
category: 'Generation',
|
|
21
|
+
outputModes: ['per-input', 'single'],
|
|
22
|
+
selectionModes: null,
|
|
23
|
+
defaults: {
|
|
24
|
+
url: '',
|
|
25
|
+
method: 'GET',
|
|
26
|
+
headers: [],
|
|
27
|
+
body: '',
|
|
28
|
+
outputFields: [{ name: 'response', type: 'string' }],
|
|
29
|
+
outputMode: 'per-input',
|
|
30
|
+
selectionMode: null,
|
|
31
|
+
},
|
|
32
|
+
computePorts: ({ config }) => {
|
|
33
|
+
const url = config?.url ?? '';
|
|
34
|
+
const headers = (config?.headers ?? []);
|
|
35
|
+
const body = config?.body ?? '';
|
|
36
|
+
// Extract template variables from URL, header values, and body
|
|
37
|
+
const textsToScan = [
|
|
38
|
+
url,
|
|
39
|
+
body,
|
|
40
|
+
...headers.map(h => h.value),
|
|
41
|
+
];
|
|
42
|
+
const variables = (0, utils_1.extractTemplateVariables)(textsToScan);
|
|
43
|
+
const inputs = variables.map(v => ({
|
|
44
|
+
id: v,
|
|
45
|
+
type: ['text', 'object', 'boolean'],
|
|
46
|
+
isArray: false,
|
|
47
|
+
required: true,
|
|
48
|
+
}));
|
|
49
|
+
// Output ports from outputFields
|
|
50
|
+
const outputFields = (config?.outputFields ?? [{ name: 'response', type: 'string' }]);
|
|
51
|
+
const outputs = outputFields.map(f => {
|
|
52
|
+
let pType;
|
|
53
|
+
let pIsArray;
|
|
54
|
+
if (f.type === 'array') {
|
|
55
|
+
pType = f.items === 'object' ? 'object' : 'text';
|
|
56
|
+
pIsArray = true;
|
|
57
|
+
}
|
|
58
|
+
else if (f.type === 'object') {
|
|
59
|
+
pType = 'object';
|
|
60
|
+
pIsArray = false;
|
|
61
|
+
}
|
|
62
|
+
else if (f.type === 'number') {
|
|
63
|
+
pType = 'number';
|
|
64
|
+
pIsArray = false;
|
|
65
|
+
}
|
|
66
|
+
else if (f.type === 'boolean') {
|
|
67
|
+
pType = 'boolean';
|
|
68
|
+
pIsArray = false;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
pType = 'text';
|
|
72
|
+
pIsArray = false;
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
id: f.name,
|
|
76
|
+
type: pType,
|
|
77
|
+
isArray: pIsArray,
|
|
78
|
+
required: f.required ?? true,
|
|
79
|
+
...(f.objectSchema && { objectSchema: f.objectSchema }),
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
return { inputs, outputs };
|
|
83
|
+
},
|
|
84
|
+
generatePreview: (config, _ctx, cachedOutputs) => {
|
|
85
|
+
const result = {};
|
|
86
|
+
const outputFields = config.outputFields ?? [{ name: 'response', type: 'string' }];
|
|
87
|
+
for (const field of outputFields) {
|
|
88
|
+
result[field.name] = cachedOutputs?.[field.name] ?? null;
|
|
89
|
+
}
|
|
90
|
+
return (0, types_1.preview)(result);
|
|
91
|
+
},
|
|
92
|
+
validate: (config) => {
|
|
93
|
+
const errors = [];
|
|
94
|
+
if (!config.url || config.url.trim().length === 0) {
|
|
95
|
+
errors.push('URL is required');
|
|
96
|
+
}
|
|
97
|
+
if (config.method && !HttpMethods.includes(config.method)) {
|
|
98
|
+
errors.push(`Invalid HTTP method: ${config.method}`);
|
|
99
|
+
}
|
|
100
|
+
return errors;
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
exports.default = definition;
|
|
@@ -13,6 +13,18 @@ export declare const nodeDefinitions: {
|
|
|
13
13
|
__TInputs: import("./account").AccountNodeInputs;
|
|
14
14
|
__TOutputs: import("./account").AccountNodeOutputs;
|
|
15
15
|
};
|
|
16
|
+
readonly 'api-request': NodeDefinition<"api-request", "generator", {
|
|
17
|
+
url: string;
|
|
18
|
+
method: import("./api-request").HttpMethod;
|
|
19
|
+
headers: import("./api-request").HeaderEntry[];
|
|
20
|
+
body: string;
|
|
21
|
+
outputFields: import("./types").ObjectSchemaField[];
|
|
22
|
+
outputMode: import("./types").OutputMode;
|
|
23
|
+
selectionMode: import("./types").SelectionMode | null;
|
|
24
|
+
}, import("./api-request").ApiRequestNodeInputs, import("./api-request").ApiRequestNodeOutputs, false> & {
|
|
25
|
+
__TInputs: import("./api-request").ApiRequestNodeInputs;
|
|
26
|
+
__TOutputs: import("./api-request").ApiRequestNodeOutputs;
|
|
27
|
+
};
|
|
16
28
|
readonly 'auto-caption': NodeDefinition<"auto-caption", "generator", {
|
|
17
29
|
preset: import("./auto-caption").AutoCaptionPreset;
|
|
18
30
|
fontName: string | undefined;
|
|
@@ -12,6 +12,7 @@ const internal_1 = require("./internal");
|
|
|
12
12
|
Object.defineProperty(exports, "internalNodeTypes", { enumerable: true, get: function () { return internal_1.internalNodeTypes; } });
|
|
13
13
|
// Import all node definitions
|
|
14
14
|
const account_1 = __importDefault(require("./account"));
|
|
15
|
+
const api_request_1 = __importDefault(require("./api-request"));
|
|
15
16
|
const auto_caption_1 = __importDefault(require("./auto-caption"));
|
|
16
17
|
const auto_post_1 = __importDefault(require("./auto-post"));
|
|
17
18
|
const branch_1 = __importDefault(require("./branch"));
|
|
@@ -50,6 +51,7 @@ const video_import_1 = __importDefault(require("./video-import"));
|
|
|
50
51
|
*/
|
|
51
52
|
exports.nodeDefinitions = {
|
|
52
53
|
'account': account_1.default,
|
|
54
|
+
'api-request': api_request_1.default,
|
|
53
55
|
'auto-caption': auto_caption_1.default,
|
|
54
56
|
'auto-post': auto_post_1.default,
|
|
55
57
|
'branch': branch_1.default,
|
package/dist/index.d.ts
CHANGED
|
@@ -38,6 +38,8 @@ export type { VideoEditorNodeConfig, VideoEditorChannel, VideoEditorSegment, Vid
|
|
|
38
38
|
export type { ImageEditorNodeConfig, ImageComposerNodeConfig, ImageComposerRenderInput } from './automations/nodes/image-composer';
|
|
39
39
|
export { prepareImageComposerInput } from './automations/nodes/image-composer';
|
|
40
40
|
export type { AccountNodeConfig } from './automations/nodes/account';
|
|
41
|
+
export type { ApiRequestNodeConfig, HeaderEntry, HttpMethod } from './automations/nodes/api-request';
|
|
42
|
+
export { HttpMethods } from './automations/nodes/api-request';
|
|
41
43
|
export type { AutoCaptionNodeConfig, AutoCaptionPreset, AutoCaptionFontWeight, AutoCaptionPosition, } from './automations/nodes/auto-caption';
|
|
42
44
|
export { nodeConfigToCaptionStyle } from './automations/nodes/auto-caption';
|
|
43
45
|
export type { AutoPostNodeConfig, AutoPostMode, PostSchedulingMode, } from './automations/nodes/auto-post';
|
package/dist/index.js
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.removePreviewForConnection = exports.updatePreviewMapForConnection = exports.computePreviewMap = exports.computeAllNodePreviews = exports.resolveNodePreview = exports.getWorkflowOutputSchema = exports.hasMissingTerminalError = exports.hasMissingTriggerError = exports.getPortErrorsForNode = exports.getErrorNodeIds = exports.validateWorkflow = exports.getCapturedNodes = exports.getNodesDownstreamOfSet = exports.getDownstreamNodes = exports.checkCrossContextViolation = exports.getForEachContext = exports.getConnectedSource = exports.cleanupStaleConnections = exports.removeNodeConnections = exports.removeConnection = exports.addConnection = exports.deriveConnections = exports.createNode = exports.getOutputSchema = exports.getNodeByType = exports.getAllNodes = exports.getInputPreviewValue = exports.computeAllNodePortsWithPreviews = exports.computeAllNodePorts = exports.computePortsWithPreviews = exports.computePortsForNode = exports.areTypesCompatible = exports.submitIMessageDmRenderJob = exports.submitInstagramDmRenderJob = exports.submitAutoCaptionRenderJob = exports.submitScreenshotAnimationRenderJob = exports.submitDeduplicationJob = exports.getRenderJobStatus = exports.submitVideoRenderJob = exports.submitImageRenderJob = exports.BillingClient = exports.CommentsClient = exports.MediaClient = exports.AutomationsClient = exports.OrganizationClient = exports.StatsClient = exports.PostsClient = exports.TasksClient = exports.AccountsClient = exports.UGCClient = void 0;
|
|
9
|
-
exports.
|
|
10
|
-
exports.prepareVideoComposerInput = exports.formatDateTag = exports.outputFieldsToZod = exports.outputFieldToZod = void 0;
|
|
9
|
+
exports.applyLogicOperator = exports.IfLogicOperators = exports.resolvePath = exports.indexExpressionToString = exports.indexExpressionToIndexes = exports.resolveUnknownPath = exports.getOutputTypeFromCategory = exports.parseOpenAPIOutputPath = exports.parseOpenAPIInputs = exports.mapOpenAPIType = exports.nodeConfigToCaptionStyle = exports.HttpMethods = exports.prepareImageComposerInput = exports.substituteVariables = exports.processTemplate = exports.extractTemplateVariables = exports.PortIdSchema = exports.normalizeToPortId = exports.portIdToTitle = exports.isValidPortId = exports.portId = exports.selectFromPool = exports.getModelDurations = exports.getModelAspectRatios = exports.ALL_VIDEO_MODELS = exports.getAvailableInputModes = exports.hasReferenceVariant = exports.getReferenceModelId = exports.hasFirstLastFrameVariant = exports.getFirstLastFrameModelId = exports.hasImageToVideoVariant = exports.getImageToVideoModelId = exports.isImageToVideoModel = exports.IMAGE_ASPECT_RATIOS = exports.ALL_IMAGE_MODELS = exports.getEditModelId = exports.isEditModel = exports.getCapturedSourceNodeTypes = exports.getFlowControlNodeTypes = exports.getAllNodeDefinitions = exports.getNodeDefinition = exports.isPortType = exports.formatPortType = exports.isAsyncExecutor = exports.internalNodeTypes = exports.nodeDefinitions = exports.extractWorkflowConfig = exports.generateNodeName = exports.shuffleNodePreview = exports.getPreviewValue = void 0;
|
|
10
|
+
exports.prepareVideoComposerInput = exports.formatDateTag = exports.outputFieldsToZod = exports.outputFieldToZod = exports.LLMProviders = void 0;
|
|
11
11
|
// =============================================================================
|
|
12
12
|
// Client Exports
|
|
13
13
|
// =============================================================================
|
|
@@ -141,6 +141,8 @@ Object.defineProperty(exports, "processTemplate", { enumerable: true, get: funct
|
|
|
141
141
|
Object.defineProperty(exports, "substituteVariables", { enumerable: true, get: function () { return utils_1.substituteVariables; } });
|
|
142
142
|
var image_composer_1 = require("./automations/nodes/image-composer");
|
|
143
143
|
Object.defineProperty(exports, "prepareImageComposerInput", { enumerable: true, get: function () { return image_composer_1.prepareImageComposerInput; } });
|
|
144
|
+
var api_request_1 = require("./automations/nodes/api-request");
|
|
145
|
+
Object.defineProperty(exports, "HttpMethods", { enumerable: true, get: function () { return api_request_1.HttpMethods; } });
|
|
144
146
|
var auto_caption_1 = require("./automations/nodes/auto-caption");
|
|
145
147
|
Object.defineProperty(exports, "nodeConfigToCaptionStyle", { enumerable: true, get: function () { return auto_caption_1.nodeConfigToCaptionStyle; } });
|
|
146
148
|
var custom_model_1 = require("./automations/nodes/custom-model");
|
package/dist/skills.js
CHANGED
|
@@ -216,92 +216,160 @@ ${run} delete_media '{"ids":["id1","id2"]}'
|
|
|
216
216
|
`,
|
|
217
217
|
'automations/SKILL.md': `---
|
|
218
218
|
name: automations
|
|
219
|
-
description:
|
|
219
|
+
description: Build, run, and manage UGC Inc automation workflows - create templates, list nodes, trigger runs, check status, manage scheduling. Use when the user wants to build, run, check, or manage their automations.
|
|
220
220
|
allowed-tools: Bash, Read
|
|
221
221
|
---
|
|
222
222
|
|
|
223
|
-
You manage UGC Inc automations through the CLI. Run tools with:
|
|
223
|
+
You build and manage UGC Inc automations through the CLI. Run tools with:
|
|
224
224
|
\`\`\`bash
|
|
225
225
|
${run} <tool_name> '<json_params>'
|
|
226
226
|
\`\`\`
|
|
227
227
|
|
|
228
228
|
Auth: \`npx ugcinc auth <api_key> [--admin]\`. Only needed once. Use \`--admin\` for admin keys.
|
|
229
229
|
|
|
230
|
+
## Building Workflows
|
|
231
|
+
|
|
232
|
+
### Workflow Structure
|
|
233
|
+
A workflow is a directed graph of nodes. Each node has a type, config, inputs (connections from other nodes), and outputs (ports other nodes can connect to).
|
|
234
|
+
|
|
235
|
+
\`\`\`json
|
|
236
|
+
{
|
|
237
|
+
"nodes": [
|
|
238
|
+
{
|
|
239
|
+
"id": "unique-node-id",
|
|
240
|
+
"type": "node-type",
|
|
241
|
+
"name": "Display Name",
|
|
242
|
+
"config": { ... },
|
|
243
|
+
"inputs": {
|
|
244
|
+
"input-port-id": {
|
|
245
|
+
"sourceNodeId": "other-node-id",
|
|
246
|
+
"sourceOutputId": "output-port-id"
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
]
|
|
251
|
+
}
|
|
252
|
+
\`\`\`
|
|
253
|
+
|
|
254
|
+
### How to Build a Workflow
|
|
255
|
+
1. Run \`list_node_types\` to see all available nodes with descriptions, guides, ports, and defaults
|
|
256
|
+
2. Run \`get_node_type\` for detailed info on specific nodes you plan to use
|
|
257
|
+
3. Build the workflow definition by:
|
|
258
|
+
- Creating nodes with unique IDs (e.g. "llm-1", "media-1", "auto-post-1")
|
|
259
|
+
- Setting each node's config (use defaults from get_node_type as a starting point)
|
|
260
|
+
- Wiring inputs: connect each node's input ports to other nodes' output ports
|
|
261
|
+
4. Run \`validate_workflow\` to check for errors before creating
|
|
262
|
+
5. Run \`create_automation\` to save the template
|
|
263
|
+
|
|
264
|
+
### Port Types
|
|
265
|
+
Data flows between nodes through typed ports: \`image\`, \`video\`, \`audio\`, \`text\`, \`number\`, \`boolean\`, \`object\`, \`account\`, \`date\`, \`social_audio\`, \`enum\`. Ports can be arrays (e.g. image[]).
|
|
266
|
+
|
|
267
|
+
### Common Workflow Patterns
|
|
268
|
+
- **Simple post**: Media → Auto Post (with Account)
|
|
269
|
+
- **AI-generated content**: LLM → Auto Post (with Account + Media for video)
|
|
270
|
+
- **Templated content**: Media + LLM → Image/Video Composer → Auto Post
|
|
271
|
+
- **Fan-out**: Account (per-input mode) → ... → Auto Post (one post per account)
|
|
272
|
+
- **Captioned video**: Media → Auto Caption → Auto Post
|
|
273
|
+
- **AI video pipeline**: LLM (caption) + Generate Video → Auto Post
|
|
274
|
+
|
|
275
|
+
## Node Reference
|
|
276
|
+
|
|
277
|
+
Nodes are organized into 4 categories:
|
|
278
|
+
|
|
279
|
+
### Source Nodes (provide data)
|
|
280
|
+
- **account** — Select accounts to post from. Outputs: account. Modes: per-input (fan-out, one run per account) or single.
|
|
281
|
+
- **media** — Pull saved media (videos, images, audio) from library. Outputs: configurable per port. Selection: random or sequential.
|
|
282
|
+
- **text** — Text pool with {{variable}} template support. Outputs: text. Selection: random or sequential.
|
|
283
|
+
- **input** — Define runtime variables supplied when triggering the workflow. Outputs: user-defined ports.
|
|
284
|
+
- **social-audio** — Trending TikTok/Instagram audio tracks. Outputs: social_audio. Linked natively when posting.
|
|
285
|
+
- **video-import** — Import video from YouTube, TikTok, Instagram URL. Inputs: url (text). Outputs: video.
|
|
286
|
+
|
|
287
|
+
### Generator Nodes (transform/create)
|
|
288
|
+
- **llm** — Generate text/structured data with AI (Claude, GPT, Gemini, Groq, Kimi, Grok). Uses {{variable}} placeholders in system prompt for inputs. Can accept image/video inputs for multimodal. Outputs: structured fields defined in config.
|
|
289
|
+
- **generate-image** — AI image generation via fal.ai (Gemini, Nano Banana, GPT Image). Inputs: prompt (text), optional images. Outputs: image.
|
|
290
|
+
- **generate-video** — AI video generation (Veo, Kling, Sora, MiniMax, Wan). Modes: text-to-video, image-to-video, first-last-frame. Outputs: video.
|
|
291
|
+
- **image-composer** — Templated image composition with variable slots for images and text overlays. Outputs: image.
|
|
292
|
+
- **video-composer** — Templated video with timeline channels, variable media segments, and text overlays. Outputs: video.
|
|
293
|
+
- **auto-caption** — Burn TikTok-style captions into video. Presets: hormozi, minimal, bold-pop, clean, neon. Inputs: video. Outputs: video.
|
|
294
|
+
- **custom-model** — Run any fal.ai model by ID. Configure input params and output type/path. Outputs: image, video, or audio.
|
|
295
|
+
- **transcript** — Speech-to-text with timestamps. Inputs: video or audio. Outputs: text + segments (object[]).
|
|
296
|
+
- **create-dm** — Render fake DM screenshots (iMessage/Instagram). Outputs: image.
|
|
297
|
+
- **screenshot-animation** — iPhone reveal animation from image. Inputs: image. Outputs: video.
|
|
298
|
+
- **deduplicate** — Modify video to evade content-ID detection (levels 1-5). Inputs: video. Outputs: video.
|
|
299
|
+
- **regex** — Match/replace text with regex. Outputs: result (text), match (boolean), groups (text[]).
|
|
300
|
+
- **random** — Pick one value randomly from array or weighted inputs. Outputs: selected value.
|
|
301
|
+
- **not** — Invert boolean. Inputs: boolean. Outputs: boolean.
|
|
302
|
+
|
|
303
|
+
### Flow Control Nodes (routing/iteration)
|
|
304
|
+
- **if** — Conditional branching. Inputs: boolean(s) + passthroughs. Outputs: true-{port} and false-{port}. Logic: and/or/xor/nor.
|
|
305
|
+
- **branch** — Route by key match (e.g. from LLM output). Only matching branch executes. Inputs: key (text) + passthroughs.
|
|
306
|
+
- **random-route** — Route to random branch with probabilities. Only one branch executes per run.
|
|
307
|
+
- **for-each** — Iterate over array, running downstream nodes per item. Exposes item and index. Pair with Collect.
|
|
308
|
+
- **collect** — Aggregate For Each outputs back into array. Must be inside For Each context.
|
|
309
|
+
- **destructure** — Extract elements from array by index/range/list. Outputs: per-selection ports.
|
|
310
|
+
- **compose-workflow** — Embed a sub-workflow. Inputs/outputs resolved from sub-workflow's Input and Pass-Through nodes.
|
|
311
|
+
|
|
312
|
+
### Terminal Nodes (outputs)
|
|
313
|
+
- **auto-post** — Publish video or slideshow to TikTok/Instagram. Modes: video or slideshow. Scheduling: random window, min distance, max posts/day. Can require approval. Inputs: video/images + account + optional caption + optional social-audio.
|
|
314
|
+
- **save-to-media** — Save outputs to media library with optional tags. Inputs: configurable (image, video, audio, text).
|
|
315
|
+
- **passthrough** — Pass data to parent workflow (for compose-workflow sub-workflows only).
|
|
316
|
+
|
|
317
|
+
For detailed port schemas, config options, and guides, use \`list_node_types\` and \`get_node_type\`.
|
|
318
|
+
|
|
230
319
|
## Tools
|
|
231
320
|
|
|
232
|
-
###
|
|
233
|
-
List all automation templates.
|
|
321
|
+
### Node Discovery
|
|
234
322
|
\`\`\`bash
|
|
235
|
-
${run}
|
|
323
|
+
${run} list_node_types # All nodes with ports, guides, defaults
|
|
324
|
+
${run} get_node_type '{"nodeType":"llm"}' # Detailed info for one node
|
|
236
325
|
\`\`\`
|
|
237
326
|
|
|
238
|
-
###
|
|
239
|
-
Get a specific template with full workflow definition.
|
|
327
|
+
### Template Management
|
|
240
328
|
\`\`\`bash
|
|
241
|
-
${run}
|
|
329
|
+
${run} list_automations # List all templates
|
|
330
|
+
${run} get_automation '{"templateId":"id"}' # Get template with full workflow
|
|
331
|
+
${run} create_automation '{"name":"My Automation","workflowDefinition":{...}}'
|
|
332
|
+
${run} update_automation '{"templateId":"id","name":"Updated","workflowDefinition":{...}}'
|
|
333
|
+
${run} validate_workflow '{"workflowDefinition":{...}}'
|
|
334
|
+
${run} delete_automation '{"templateId":"id"}'
|
|
242
335
|
\`\`\`
|
|
243
336
|
|
|
244
|
-
###
|
|
245
|
-
Run an automation. Optionally provide variable inputs.
|
|
337
|
+
### Execution
|
|
246
338
|
\`\`\`bash
|
|
247
339
|
${run} run_automation '{"templateId":"id"}'
|
|
248
340
|
${run} run_automation '{"templateId":"id","variableInputs":{"node-id":"value"}}'
|
|
249
|
-
\`\`\`
|
|
250
|
-
|
|
251
|
-
### get_automation_status
|
|
252
|
-
Get run status with executor nodes and data flow edges.
|
|
253
|
-
\`\`\`bash
|
|
254
341
|
${run} get_automation_status '{"runId":"id"}'
|
|
342
|
+
${run} get_automation_logs '{"runId":"id"}'
|
|
343
|
+
${run} stop_automation '{"runId":"id"}'
|
|
344
|
+
${run} export_automation '{"templateId":"id"}' # Debug: full template export
|
|
345
|
+
${run} export_automation_run '{"runId":"id"}' # Debug: full run export with executor outputs
|
|
255
346
|
\`\`\`
|
|
256
347
|
|
|
257
|
-
###
|
|
258
|
-
List runs for a specific template.
|
|
348
|
+
### Run History & Review
|
|
259
349
|
\`\`\`bash
|
|
260
350
|
${run} list_automation_runs '{"templateId":"id","limit":10}'
|
|
261
|
-
\`\`\`
|
|
262
|
-
|
|
263
|
-
### list_all_automation_runs
|
|
264
|
-
List all runs across all templates.
|
|
265
|
-
\`\`\`bash
|
|
266
351
|
${run} list_all_automation_runs '{"limit":10}'
|
|
267
352
|
${run} list_all_automation_runs '{"reviewStatus":"pending_review"}'
|
|
353
|
+
${run} update_automation_review '{"runId":"id","reviewStatus":"approved"}'
|
|
354
|
+
${run} delete_automation_run '{"runId":"id"}'
|
|
268
355
|
\`\`\`
|
|
269
356
|
|
|
270
|
-
###
|
|
271
|
-
Stop a running automation.
|
|
272
|
-
\`\`\`bash
|
|
273
|
-
${run} stop_automation '{"runId":"id"}'
|
|
274
|
-
\`\`\`
|
|
275
|
-
|
|
276
|
-
### publish_automation
|
|
277
|
-
Enable recurrence scheduling.
|
|
278
|
-
\`\`\`bash
|
|
279
|
-
${run} publish_automation '{"templateId":"id"}'
|
|
280
|
-
\`\`\`
|
|
281
|
-
|
|
282
|
-
### unpublish_automation
|
|
283
|
-
Disable recurrence scheduling.
|
|
357
|
+
### Scheduling
|
|
284
358
|
\`\`\`bash
|
|
359
|
+
${run} get_recurrence_status '{"templateId":"id"}'
|
|
360
|
+
${run} publish_automation '{"templateId":"id","scheduleConfig":{"frequencyType":"per-day","runsPerDay":3,"timingType":"random-window","randomWindowStart":"09:00","randomWindowEnd":"21:00","timezone":"America/New_York"},"accountIterationConfig":null}'
|
|
285
361
|
${run} unpublish_automation '{"templateId":"id"}'
|
|
286
|
-
\`\`\`
|
|
287
|
-
|
|
288
|
-
### run_automation_once
|
|
289
|
-
Run once immediately (also updates recurrence schedule if published).
|
|
290
|
-
\`\`\`bash
|
|
291
362
|
${run} run_automation_once '{"templateId":"id"}'
|
|
292
363
|
\`\`\`
|
|
293
364
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
\`\`\`
|
|
299
|
-
|
|
300
|
-
## Workflow tips
|
|
301
|
-
- Always list automations first to get template IDs and names
|
|
365
|
+
## Workflow Tips
|
|
366
|
+
- **Always start with \`list_node_types\`** to understand available nodes before building
|
|
367
|
+
- Use \`get_node_type\` to see a node's default config, then customize from there
|
|
368
|
+
- Use \`validate_workflow\` before \`create_automation\` to catch errors early
|
|
302
369
|
- After running, use \`get_automation_status\` to monitor progress
|
|
303
|
-
- For recurring automations, check \`publish_automation\` / \`unpublish_automation\`
|
|
304
370
|
- Summarize run status: show completed/total nodes, any failures
|
|
371
|
+
- For recurring automations, use \`publish_automation\` / \`unpublish_automation\`
|
|
372
|
+
- When building from a user description, map their intent to node types, then wire the data flow
|
|
305
373
|
- If $ARGUMENTS is provided, interpret it as a natural language request
|
|
306
374
|
`,
|
|
307
375
|
'billing/SKILL.md': `---
|
|
@@ -2,7 +2,125 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.automationTools = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const graph_controller_1 = require("../automations/graph-controller");
|
|
6
|
+
const workflowNodeSchema = zod_1.z.object({
|
|
7
|
+
id: zod_1.z.string().describe('Unique node ID (e.g. "llm-1", "media-2")'),
|
|
8
|
+
type: zod_1.z.string().describe('Node type (e.g. "llm", "media", "auto-post"). Use list_node_types to see all types.'),
|
|
9
|
+
name: zod_1.z.string().optional().describe('Display name for the node'),
|
|
10
|
+
x: zod_1.z.number().optional().describe('Canvas X position'),
|
|
11
|
+
y: zod_1.z.number().optional().describe('Canvas Y position'),
|
|
12
|
+
config: zod_1.z.record(zod_1.z.unknown()).describe('Node-specific config. Use get_node_type to see defaults and available options.'),
|
|
13
|
+
inputs: zod_1.z.record(zod_1.z.object({
|
|
14
|
+
sourceNodeId: zod_1.z.string().describe('ID of the source node'),
|
|
15
|
+
sourceOutputId: zod_1.z.string().describe('Output port ID on the source node'),
|
|
16
|
+
})).describe('Map of input port ID → source connection'),
|
|
17
|
+
});
|
|
18
|
+
const workflowDefinitionSchema = zod_1.z.object({
|
|
19
|
+
nodes: zod_1.z.array(workflowNodeSchema).describe('Array of workflow nodes'),
|
|
20
|
+
canvasState: zod_1.z.object({
|
|
21
|
+
zoom: zod_1.z.number(),
|
|
22
|
+
panX: zod_1.z.number(),
|
|
23
|
+
panY: zod_1.z.number(),
|
|
24
|
+
}).optional().describe('Canvas UI state'),
|
|
25
|
+
});
|
|
26
|
+
const scheduleConfigSchema = zod_1.z.object({
|
|
27
|
+
frequencyType: zod_1.z.enum(['per-day', 'periodic']).describe("'per-day' = N runs per day, 'periodic' = every M days"),
|
|
28
|
+
runsPerDay: zod_1.z.number().optional().describe('Number of runs per day (for per-day frequency)'),
|
|
29
|
+
periodDays: zod_1.z.number().optional().describe('Run every N days (for periodic frequency)'),
|
|
30
|
+
daysOfWeek: zod_1.z.array(zod_1.z.enum(['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'])).optional().describe('Which days of the week to run'),
|
|
31
|
+
timingType: zod_1.z.enum(['specific', 'random-window']).describe("'specific' = run at exact times, 'random-window' = run randomly within a window"),
|
|
32
|
+
specificTimes: zod_1.z.array(zod_1.z.string()).optional().describe('Exact times to run (HH:MM format, for specific timing)'),
|
|
33
|
+
randomWindowStart: zod_1.z.string().optional().describe('Window start time (HH:MM format, for random-window timing)'),
|
|
34
|
+
randomWindowEnd: zod_1.z.string().optional().describe('Window end time (HH:MM format, for random-window timing)'),
|
|
35
|
+
timezone: zod_1.z.string().describe('IANA timezone (e.g. "America/New_York")'),
|
|
36
|
+
});
|
|
37
|
+
const accountIterationConfigSchema = zod_1.z.object({
|
|
38
|
+
enabled: zod_1.z.boolean().describe('Whether account iteration is enabled'),
|
|
39
|
+
selectionMode: zod_1.z.enum(['specific', 'by-tag']).describe("'specific' = use accountIds, 'by-tag' = use accountTag"),
|
|
40
|
+
accountIds: zod_1.z.array(zod_1.z.string()).optional().describe('Specific account IDs to iterate over'),
|
|
41
|
+
accountTag: zod_1.z.string().optional().describe('Tag to select accounts by'),
|
|
42
|
+
iterationMode: zod_1.z.enum(['sequential', 'random']).describe('How to iterate through accounts'),
|
|
43
|
+
});
|
|
44
|
+
function getNodeTypeInfo(params) {
|
|
45
|
+
const node = (0, graph_controller_1.getNodeByType)(params.nodeType);
|
|
46
|
+
if (!node) {
|
|
47
|
+
return { ok: false, error: `Unknown node type: ${params.nodeType}` };
|
|
48
|
+
}
|
|
49
|
+
return { ok: true, data: node };
|
|
50
|
+
}
|
|
5
51
|
exports.automationTools = [
|
|
52
|
+
// =========================================================================
|
|
53
|
+
// Node Discovery (local, no API call)
|
|
54
|
+
// =========================================================================
|
|
55
|
+
{
|
|
56
|
+
name: 'list_node_types',
|
|
57
|
+
description: 'List all available automation node types with descriptions, guides, input/output ports, and default configs. Use this to understand what nodes exist before building a workflow.',
|
|
58
|
+
schema: zod_1.z.object({}),
|
|
59
|
+
execute: async () => {
|
|
60
|
+
const nodes = (0, graph_controller_1.getAllNodes)().filter(n => !n.hidden);
|
|
61
|
+
return { ok: true, data: nodes };
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'get_node_type',
|
|
66
|
+
description: 'Get detailed info for a specific node type including ports, defaults, and guide. Use this to understand a node before adding it to a workflow.',
|
|
67
|
+
schema: zod_1.z.object({
|
|
68
|
+
nodeType: zod_1.z.string().describe('Node type ID (e.g. "llm", "auto-post", "media")'),
|
|
69
|
+
}),
|
|
70
|
+
execute: async (_client, params) => {
|
|
71
|
+
return getNodeTypeInfo(params);
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
// =========================================================================
|
|
75
|
+
// Template Management
|
|
76
|
+
// =========================================================================
|
|
77
|
+
{
|
|
78
|
+
name: 'create_automation',
|
|
79
|
+
description: 'Create a new automation template with a workflow definition. Use list_node_types and get_node_type to understand available nodes, then build the workflow.',
|
|
80
|
+
schema: zod_1.z.object({
|
|
81
|
+
name: zod_1.z.string().describe('Name for the automation'),
|
|
82
|
+
description: zod_1.z.string().optional().describe('Description of what this automation does'),
|
|
83
|
+
workflowDefinition: workflowDefinitionSchema,
|
|
84
|
+
skipValidation: zod_1.z.boolean().optional().describe('Skip validation (for saving drafts)'),
|
|
85
|
+
}),
|
|
86
|
+
execute: async (client, params) => {
|
|
87
|
+
return client.automations.createTemplate(params);
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'update_automation',
|
|
92
|
+
description: 'Update an existing automation template. Replaces the full workflow definition.',
|
|
93
|
+
schema: zod_1.z.object({
|
|
94
|
+
templateId: zod_1.z.string().describe('ID of the template to update'),
|
|
95
|
+
name: zod_1.z.string().describe('Updated name'),
|
|
96
|
+
description: zod_1.z.string().optional().describe('Updated description'),
|
|
97
|
+
workflowDefinition: workflowDefinitionSchema,
|
|
98
|
+
skipValidation: zod_1.z.boolean().optional().describe('Skip validation (for saving drafts)'),
|
|
99
|
+
}),
|
|
100
|
+
execute: async (client, params) => {
|
|
101
|
+
return client.automations.createTemplate(params);
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: 'validate_workflow',
|
|
106
|
+
description: 'Validate a workflow definition without creating it. Returns validation errors if any.',
|
|
107
|
+
schema: zod_1.z.object({
|
|
108
|
+
workflowDefinition: workflowDefinitionSchema,
|
|
109
|
+
}),
|
|
110
|
+
execute: async (client, params) => {
|
|
111
|
+
return client.automations.validateWorkflow(params);
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: 'delete_automation',
|
|
116
|
+
description: 'Delete an automation template permanently.',
|
|
117
|
+
schema: zod_1.z.object({
|
|
118
|
+
templateId: zod_1.z.string().describe('ID of the template to delete'),
|
|
119
|
+
}),
|
|
120
|
+
execute: async (client, params) => {
|
|
121
|
+
return client.automations.deleteTemplate(params);
|
|
122
|
+
},
|
|
123
|
+
},
|
|
6
124
|
{
|
|
7
125
|
name: 'list_automations',
|
|
8
126
|
description: 'List all automation templates for the organization.',
|
|
@@ -21,6 +139,19 @@ exports.automationTools = [
|
|
|
21
139
|
return client.automations.getTemplate(params);
|
|
22
140
|
},
|
|
23
141
|
},
|
|
142
|
+
{
|
|
143
|
+
name: 'export_automation',
|
|
144
|
+
description: 'Export an automation template for debugging. Returns the complete template definition with nodes and connections in a readable format.',
|
|
145
|
+
schema: zod_1.z.object({
|
|
146
|
+
templateId: zod_1.z.string().describe('Automation template ID'),
|
|
147
|
+
}),
|
|
148
|
+
execute: async (client, params) => {
|
|
149
|
+
return client.automations.exportTemplate(params);
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
// =========================================================================
|
|
153
|
+
// Execution
|
|
154
|
+
// =========================================================================
|
|
24
155
|
{
|
|
25
156
|
name: 'run_automation',
|
|
26
157
|
description: 'Run an automation template. Optionally provide variable inputs and a tag.',
|
|
@@ -44,6 +175,39 @@ exports.automationTools = [
|
|
|
44
175
|
return client.automations.getStatus(params);
|
|
45
176
|
},
|
|
46
177
|
},
|
|
178
|
+
{
|
|
179
|
+
name: 'get_automation_logs',
|
|
180
|
+
description: 'Get execution logs for an automation run. Returns log entries in chronological order.',
|
|
181
|
+
schema: zod_1.z.object({
|
|
182
|
+
runId: zod_1.z.string().describe('Run ID to get logs for'),
|
|
183
|
+
}),
|
|
184
|
+
execute: async (client, params) => {
|
|
185
|
+
return client.automations.getLogs(params);
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
name: 'stop_automation',
|
|
190
|
+
description: 'Stop a running automation. Marks the run and all pending executors as failed.',
|
|
191
|
+
schema: zod_1.z.object({
|
|
192
|
+
runId: zod_1.z.string().describe('Run ID to stop'),
|
|
193
|
+
}),
|
|
194
|
+
execute: async (client, params) => {
|
|
195
|
+
return client.automations.stop(params);
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: 'export_automation_run',
|
|
200
|
+
description: 'Export an automation run for debugging. Returns the complete run data including execution state, executor outputs, and edge values.',
|
|
201
|
+
schema: zod_1.z.object({
|
|
202
|
+
runId: zod_1.z.string().describe('Automation run ID'),
|
|
203
|
+
}),
|
|
204
|
+
execute: async (client, params) => {
|
|
205
|
+
return client.automations.exportRun(params);
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
// =========================================================================
|
|
209
|
+
// Run History & Review
|
|
210
|
+
// =========================================================================
|
|
47
211
|
{
|
|
48
212
|
name: 'list_automation_runs',
|
|
49
213
|
description: 'List runs for a specific automation template.',
|
|
@@ -69,20 +233,46 @@ exports.automationTools = [
|
|
|
69
233
|
},
|
|
70
234
|
},
|
|
71
235
|
{
|
|
72
|
-
name: '
|
|
73
|
-
description: '
|
|
236
|
+
name: 'update_automation_review',
|
|
237
|
+
description: 'Update the review status of an automation run. Approve or reject runs that require review.',
|
|
74
238
|
schema: zod_1.z.object({
|
|
75
|
-
runId: zod_1.z.string().describe('
|
|
239
|
+
runId: zod_1.z.string().describe('Automation run ID'),
|
|
240
|
+
reviewStatus: zod_1.z.enum(['approved', 'rejected']).describe('New review status'),
|
|
76
241
|
}),
|
|
77
242
|
execute: async (client, params) => {
|
|
78
|
-
return client.automations.
|
|
243
|
+
return client.automations.updateReviewStatus(params);
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: 'delete_automation_run',
|
|
248
|
+
description: 'Delete an automation run permanently.',
|
|
249
|
+
schema: zod_1.z.object({
|
|
250
|
+
runId: zod_1.z.string().describe('Automation run ID to delete'),
|
|
251
|
+
}),
|
|
252
|
+
execute: async (client, params) => {
|
|
253
|
+
return client.automations.deleteRun(params);
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
// =========================================================================
|
|
257
|
+
// Scheduling & Recurrence
|
|
258
|
+
// =========================================================================
|
|
259
|
+
{
|
|
260
|
+
name: 'get_recurrence_status',
|
|
261
|
+
description: 'Get the recurrence scheduling status for an automation. Returns whether it is published, next/last run times.',
|
|
262
|
+
schema: zod_1.z.object({
|
|
263
|
+
templateId: zod_1.z.string().describe('Automation template ID'),
|
|
264
|
+
}),
|
|
265
|
+
execute: async (client, params) => {
|
|
266
|
+
return client.automations.getRecurrenceStatus(params);
|
|
79
267
|
},
|
|
80
268
|
},
|
|
81
269
|
{
|
|
82
270
|
name: 'publish_automation',
|
|
83
|
-
description: 'Publish an automation to enable recurrence scheduling. The automation will run automatically based on
|
|
271
|
+
description: 'Publish an automation to enable recurrence scheduling. The automation will run automatically based on the provided schedule config.',
|
|
84
272
|
schema: zod_1.z.object({
|
|
85
273
|
templateId: zod_1.z.string().describe('Automation template ID to publish'),
|
|
274
|
+
scheduleConfig: scheduleConfigSchema,
|
|
275
|
+
accountIterationConfig: accountIterationConfigSchema.nullable().describe('Account iteration config, or null to disable account iteration'),
|
|
86
276
|
}),
|
|
87
277
|
execute: async (client, params) => {
|
|
88
278
|
return client.automations.publish(params);
|
|
@@ -108,14 +298,4 @@ exports.automationTools = [
|
|
|
108
298
|
return client.automations.runOnce(params);
|
|
109
299
|
},
|
|
110
300
|
},
|
|
111
|
-
{
|
|
112
|
-
name: 'get_automation_logs',
|
|
113
|
-
description: 'Get execution logs for an automation run. Returns log entries in chronological order.',
|
|
114
|
-
schema: zod_1.z.object({
|
|
115
|
-
runId: zod_1.z.string().describe('Run ID to get logs for'),
|
|
116
|
-
}),
|
|
117
|
-
execute: async (client, params) => {
|
|
118
|
-
return client.automations.getLogs(params);
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
301
|
];
|