⌘K

Kotlin action compiler

Nativeblocks provides compiler to connect any codes with its core SDK

The Nativeblocks compiler is a tool that generates server-driven blocks and actions based on Kotlin code. It produces JSON and Kotlin files for each block and action, preparing them for upload to Nativeblocks servers.

How it works

Before starting we need to add necessary dependencies

Add KSP

implementation("io.nativeblocks:nativeblocks-compiler-android:1.1.0")
ksp("io.nativeblocks:nativeblocks-compiler-android:1.1.0")

Then it needed to provide ksp compiler arguments

ksp {
    arg("basePackageName", "io.nativeblocks.sampleapp")
    arg("moduleName", "Demo")
}

Usage

Actions are functions that can be invoked within a Nativeblocks Studio to perform specific tasks or operations. These annotations provide metadata and define configurable properties, data inputs, and events for your actions, making them usable as building actions in a visual editor.

@NativeAction

Purpose: Marks a class or function as an action.

Parameters:

  • name: The display name of the action in the visual editor.
  • keyType: A unique key used to identify the action type.
  • description: A brief description of the action's functionality.

Example:

@NativeAction(
    keyType = "CUSTOM_BOT",
    name = "Custom bot",
    description = "This is a bot"
)

@NativeActionProp

Purpose: Defines a configurable property for the action. These properties can be set visually in the editor.

Parameters:

  • description: (Optional) A description of the property.
  • valuePicker: (Optional) Specifies the type of UI element used to edit the property (e.g., dropdown, text field).
  • valuePickerGroup: (Optional) Specifies the group name of the property to group all related properties.
  • valuePickerOptions: (Optional) Provides options for dropdown value pickers.

Example:

@NativeActionProp(description = "api key") apiKey: String

@NativeActionData

Purpose: Marks a parameter as a data input for the action. This data can be provided directly without visual configuration, often from other actions or data sources.

Parameters:

  • description: (Optional) A description of the data input.

Example:

@NativeActionData(description = "user input value") userPrompt: String

@NativeActionEvent

Purpose: Defines an event that the action can trigger, such as success, failure, or next updates.

Parameters:

  • description: (Optional) A description of the data input.
  • then: Specifies when the event should be triggered (e.g., success, failure, next, end).
  • dataBinding: (Optional) An array of data input names to bind to the event handler parameters.

Example:

@NativeActionEvent(
    then = Then.SUCCESS,
    dataBinding = ["result"]
)

This example demonstrates a bot action with configurable properties (apiKey, aiModelId), data inputs (userPrompt, result, errorMessage), and events for success (onMessageStream) and failure (onError).

@NativeAction(
    keyType = "CUSTOM_BOT",
    name = "Custom bot",
    description = "This is a bot"
)
class CustomBot {

    @NativeActionParameter
    data class Parameters(
        @NativeActionProp
        val apiKey: String,
        @NativeActionProp
        val aiModelId: String,
        @NativeActionData
        val userPrompt: String,
        @NativeActionData
        val result: String,
        @NativeActionData
        val errorMessage: String,
        @NativeActionEvent(
            then = Then.SUCCESS,
            dataBinding = ["result"]
        )
        val onMessageStream: (String) -> Unit,
        @NativeActionEvent(
            then = Then.FAILURE,
            dataBinding = ["errorMessage"]
        )
        val onError: (String) -> Unit
    )

    @NativeActionFunction
    suspend fun ask(parameters: Parameters) {
        // ... Action implementation ...
    }
}

Generated files

After providing annotations for blocks and actions, the project generates Kotlin code and corresponding JSON files upon building. These can then be initialize in MainActivity or via dependency injection

Note: The prefix for the provider name comes from the module name that provided by KSP argument. In this case, since we provided "Demo," the compiler generates with "Demo" prefix.

DemoActionProvider.provideActions(customBot)

For actions, all dependencies must be provided during initialization. To optimize performance, consider using dependency injection for scoped or lazy instances.