Omnitool.ai
  • Welcome to Omnitool.ai
    • Key Features
  • Getting Started
    • Installation
    • Configuration
    • FAQ
  • Tutorial
    • Glossary
    • UI Overview
    • Adding API Keys
    • Blocks
      • Omnitool
      • OpenAI
      • Replicate
      • HuggingFace
      • ElevenLabs
      • OpenRouter
      • Sharp Image Processing
  • Contributing
  • Advanced
    • Run Recipe via REST API
    • Create New Blocks
      • Add a New Block via Composition API
      • Adding New Block via Extension
      • Adding new Block via OpenAPI Spec
    • Create New Extension
    • Use Local Models
  • License
Powered by GitBook
On this page
  • Step 1: Import Necessary Components
  • Step 2: Create a New Component Instance
  • Step 3: Define Component Characteristics
  • Step 4: Create and Add Inputs and Outputs
  • Step 5: Create and Add Controls (Optional)
  • Step 6: Define Execution Macro
  • Step 8: Export the Component
  • Step 9: Add the Component to App Blocks
  • Optional Settings:
  • Composing Patches
  • Dependencies

Was this helpful?

Edit on GitHub
Export as PDF
  1. Advanced
  2. Create New Blocks

Add a New Block via Composition API

Step 1: Import Necessary Components

Import the necessary components

import { OAIBaseComponent, type OmniComponentFormat, WorkerContext, OmniComponentMacroTypes } from "./path_to_file"

Step 2: Create a New Component Instance

Instantiate the ComponentComposer and initialize your component by defining its namespace and operationId using the .create(displayNamespace, displayOperationId) method.

Set the namespace to const NS_OMNI

const NS_OMNI = 'your_namespace'
let component = OAIBaseComponent.create(NS_OMNI, 'your_operationId')

Step 3: Define Component Characteristics

Further define the characteristics of your component using provided methods. You can set the title, description, method, and category.

component
    .fromScratch()
    .set('description', 'Your description')
    .set('title', 'Your title')
    .set('category', 'Your category')
    .setMethod('Your Method')
    .setMeta({
        source: {
            summary: 'A standard text input component with built-in URL fetching, enabling it to be connected to File (Image/Audio/Document) sockets',
            authors: ['Mercenaries.ai Team'],
            links: {
                'Mercenaries.ai': 'https://mercenaries.ai'
            }
        }
    })

Instead of using the fromScratch() method, you can also utilize the fromJSON() method with a valid Partial<OmniComponentFormat> JSON. This must include both the displayNamespace/operationID and apiNamespace/operationId.

const partialComponentFormat: Partial < OmniComponentFormat > = {
    displayNamespace: 'your_display_namespace',
    displayOperationId: 'your_display_operationId',
    apiNamespace: 'your_api_namespace',
    apiOperationId: 'your_api_operationId',
    // other properties can be added as needed
};
component.fromJSON(partialComponentFormat)

Step 4: Create and Add Inputs and Outputs

For inputs and outputs, you'll first create an IOComposer using the .createInput(name, type, customSocket) or .createOutput(name, type, customSocket) methods. You can further define their properties, including setting up controls which can be automatically selected or overridden.

Inputs always have controls associated with them, and they can be defined directly within the input creation process. Here's an example of defining an input with a control:

const input = component.addInput(
  component.createInput('input_name', 'input_type', 'input_x-type')
    .set('title', 'Input title')
    .set('description', 'Input description')
    .setDefault('default value')
    .setConstraints(min value, max value)
    .setChoice([])
    .setRequired(true)
    .allowMultiple(true) // enable an input to accept multiple connections. 
    .setControl({
        controlType: 'alpine control type' 
      }) // Override the automatically selected control
    .toOmniIO()
);

Note:

When using .allowMultiple() in conjunction with { array: true }, the input array is flattened into a single array:

component.createInput('input_name', 'input_type', 'input_x-type', {array:true})

You can define which characters are used for joining (or separating on input) an array (default is \n) via a custom setting (specific to the Text Socket):

{array: true, customSettings: {array_separator = '-------' }};

Alternatively, you can also define inputs and outputs in an array:

const inputs = [
  { name: 'text', type: 'string', description: 'A string', customSocket: 'text' },
  // More input definitions...
  { name: 'usSocialSecurityNumber', type: 'boolean', default: true }
];

inputs.forEach(({ name, type, customSocket, description, default: defaultValue }) => {
  component.addInput(
    component.createInput(name, type, customSocket)
      .set('description', description)
      .setDefault(defaultValue)
      .toOmniIO()
  );
});

You also have the option to directly write the JSON if that's your preference.

Step 5: Create and Add Controls (Optional)

Controls are created using the ControlComposer and are added similarly to inputs/outputs.

let controlComposer = component.createControl('controlName')

component
  .addControl(
    controlComposer
      .setRequired(true)
      .setControlType('alpineControlType')
      .toOmniControl()
  );

Or

component.addControl(
  component
    .createControl("controlName")
    .setRequired(true)
    .setControlType("alpineControlType")
    .toOmniControl()
);

Step 6: Define Execution Macro

You can define the behavior of your component using a macro. In this case, the OmniComponentMacroTypes.EXEC macro type is used.

component.setMacro(OmniComponentMacroTypes.EXEC, (payload: any, ctx: WorkerContext) => {
  // define your function here
})

Step 8: Export the Component

Finally, convert the component to JSON and export it.

const YourComponent = component.toJSON() 
export default YourComponent

Step 9: Add the Component to App Blocks

app.blocks.addBlock(component)

Note: extensions don’t need to call addBlock. they just need to export the createComponent function.

Optional Settings:

Composing Patches

To compose a patch with a valid OmniComponentPatch, the same format applies:

let patch= OAIBaseComponent
  .createPatch(NS_ONMI, "text_replace")
  .fromComponent(apiNamespace, apiOperationId)
  ....
  .toJSON() //<-- OmnicomponentPatch

app.blocks.addPatch(patch)

Dependencies

Use .dependsOn(string[]) to specify dependencies, indicating if a block relies on other blocks (for instance, when using runblock internally). For example:

component.dependsOn(['automatic1111.interrogateapi_sdapi_v1_interrogate_post', 'automatic1111.simpleImage2Image']);

PreviousCreate New BlocksNextAdding New Block via Extension

Last updated 1 year ago

Was this helpful?