SDK

SDK module methods

  • sdk.exec
  • sdk.getHostOS
  • sdk.homeDir
  • sdk.isContainer
  • sdk.log
  • sdk.user
  • sdk.getStatePath*
  • sdk.getConfigPath*
  • sdk.setState*
  • sdk.getState*
  • sdk.setConfig*
  • set.getConfig*
  • sdk.track
  • sdk.yargs

*Note: "set" and "get" state or config based SDK functions require that mountHome: true is set in the ops.yml for the Ops that use these.

sdk.exec

sdk.exec(command: string): Promise<{ stdout: string, stderr: string }>

Allows shell commands to be run on the terminal the docker container with the async/await syntax.

Note: Currently, this command does NOT pipe the stdout. If you are looking for a way to pipe the stdout, please consider using child_process or shelljs instead

Example:

On linux-based images, executing the following code:

import { sdk } from '@cto.ai/sdk'

const main = async () => {
    await sdk.exec('mkdir test-directory')
    const { stdout, stderr } = await sdk.exec('ls')

    console.log('stdout is:\n', stdout)
    console.log('stderr is:\n', stderr)
}

main()

will create a folder named test-directory on the host machine, and returns the following data to stdout and stderr.

Console logging the stdout and stderr will result as follows

stdout is:
demo.js
index.js
node_modules
package-lock.json
package.json
test-directory

stderr is:

sdk.getHostOS

sdk.getHostOS(): string

Obtains the Operating System the host is running on.

Example:

import { sdk } from '@cto.ai/sdk'

const main = async () => {
    const hostOs = sdk.getHostOS()

    console.log("Host's os is:", hostOs)
}

Output:

Host's os is: darwin

sdk.homeDir

sdk.homeDir(): string

Obtains the home directory of the host machine.

Example:

import { sdk } from '@cto.ai/sdk'

const main = async () => {
  const homeDir = sdk.homeDir()
  
  console.log("Host's home directory is:", homeDir)
}

Output:

Host's home directory is: /root

sdk.isContainer

sdk.isContainer(): boolean

Checks whether the op is running in a container or not.

Example:

import { sdk } from '@cto.ai/sdk'

const main = async () => {
  const isContainer = sdk.isContainer()
  
  console.log('Is the host running in a container?', isContainer)
}

Output:

Is the host running in a container? true

sdk.log

sdk.log(...args: any[]): void

Logs to the console in in a standardized way

Example:

import { sdk } from '@cto.ai/sdk'

const main = async () => {
  sdk.log('I am a log!', '\nI am too!')
}

Output:

I am a log!
I am too!

sdk.user

sdk.user(): Promise<UserResponse>

Gets the current user's information in the following format

UserResponse = {
  me: {
    id: string;
    username: string;
    emails: [{
      verified: boolean;
      address: string;
    }];
    firstName: string;
    lastName: string;
    createdAt: string;
    updatedAt: string;
  },
  teams: {
    id: string;
    name: string;
    createdAt: string;
    updatedAt: string;
    createdBy: string;
  }[]
}

Example:

import { sdk } from '@cto.ai/sdk'

const main = async () => {
  const me = await sdk.user()
  
  console.log(me)
}

Output:

{
  me:
    { id: '00000000-1111-2222-3333-444444444441',
      username: 'superman',
      emails: [ { verified: false, address: '[email protected]' } ],
      firstName: 'Clark',
      lastName: 'Kent',
      createdAt: '2019-04-29T22:38:22.1062Z',
      updatedAt: '2019-04-29T22:38:22.1062Z'
  },
  teams: [
    { id: '00000000-1111-2222-3333-444444444442',
      name: 'ops',
      createdBy: '00000000-1111-2222-3333-444444444443',
      createdAt: '2019-04-25T23:06:23.307382Z',
      updatedAt: '2019-04-25T23:06:23.307382Z'
    },
    { id: '00000000-1111-2222-3333-444444444444',
      name: 'superman',
      createdBy: '00000000-1111-2222-3333-444444444445',
      createdAt: '2019-04-29T22:38:22.266888Z',
      updatedAt: '2019-04-29T22:38:22.266888Z'
    }
  ]
}

sdk.getStatePath

sdk.getStatePath(): string

Obtains the path where the state folder is located.

Example:

import { sdk } from '@cto.ai/sdk'

const main = async () => {
  const statePath = sdk.getStatePath()
  
  console.log('The state path is:', statePath)
}

Output:

The state path is: /root/.config/@cto.ai/ops/superman/test-op/00000000-1111-2222-3333-444444444444

*This SDK function requires that mountHome: true is set in the ops.yml for the Ops that use this

sdk.getConfigPath

sdk.getConfigPath(): string

Obtains the path where the config folder is located.

Example:

import { sdk } from '@cto.ai/sdk'

const main = async () => {
  const configPath = sdk.getConfigPath()
  
  console.log('The config path is:', configPath)
}

Output:

The state path is: /root/.config/@cto.ai/ops/superman/test-op

*This SDK function requires that mountHome: true is set in the ops.yml for the Ops that use this

sdk.setState

sdk.setState(key: string, value: any): Promise<void>

Sets the state with a desired key-value pair.

If a value exists under the desired key, the contents would be replaced

Example:

import { sdk } from '@cto.ai/sdk'

const main = async () => {
  const key = 'test-key'
  
  // state = {}
  const initialState = await sdk.getState(key)
  console.log('Initial state', initialState)

  // state = { test-key: 'Value one' }
  await sdk.setState(key, 'Value one')
  const insertedState = await sdk.getState(key)
  console.log('Inserted state', insertedState)

  // state = { test-key: 'Value two' }
  await sdk.setState(key, 'Value two')
  const updatedState = await sdk.getState(key)
  console.log('Updated state', updatedState)
}

Output:

Initial state undefined
Inserted state Value one
Updated state Value two

*This SDK function requires that mountHome: true is set in the ops.yml for the Ops that use this

sdk.getState

sdk.getState(key: string): Promise<any>

Gets the value that is saved in the desired key

If the key is not yet set, it will return undefined

Example: See sdk.setState

*This SDK function requires that mountHome: true is set in the ops.yml for the Ops that use this

sdk.setConfig

sdk.setConfig(key: string, value: any): Promise<void>

Sets the config with a desired key-value pair.

If a value exists under the desired key, the contents would be replaced

Example:

import { sdk } from '@cto.ai/sdk'

const main = async () => {
    const key = 'test-key'

    // config = {}
    const initialConfig = await sdk.getConfig(key)
    console.log('Initial config', initialConfig)

    // config = { test-key: 'Value one' }
    await sdk.setConfig(key, 'Value one')
    const insertedConfig = await sdk.getConfig(key)
    console.log('Inserted config', insertedConfig)

    // config = { test-key: 'Value two' }
    await sdk.setConfig(key, 'Value two')
    const updatedConfig = await sdk.getConfig(key)
    console.log('Updated config', updatedConfig)
}

Output:

Initial config undefined
Inserted config Value one
Updated config Value two

*This SDK function requires that mountHome: true is set in the ops.yml for the Ops that use this

sdk.getConfig

sdk.getConfig(key: string): Promise<any>

Obtains the value that is saved in the desired key in the config

If the key is not yet set, it will return undefined

Example: See sdk.setConfig

*This SDK function requires that mountHome: true is set in the ops.yml for the Ops that use this

sdk.track

sdk.track(tags, metadata)

Send a track event to cto.ai api

  • tags: (String || String[]) Tags for the event you want to track
  • metaData: (Object) Data you want to be tracked

sdk.yargs

Parses the input using Yargs and returns the arguments and flags as and object

The simplest way to obtain the arguments would be as follows.

const arguments = sdk.yargs.argv

Example (index.js of your op):

import { sdk } from '@cto.ai/sdk'

const main = () => {
  const arguments = sdk.yargs.argv
  console.log('The parsed arguments are: ', arguments)
}

main()
$ ops run your-op-name command1 command2 --flag1 -a --flag2 flag2Value -b flag3value command3

The parsed arguments are:

{
  "_": ["command1", "command2", "command3"],
  "flag1": true,
  "a": true,
  "flag2": "flag2Value",
  "b": "flag3value",
  "$0": "src/index.js"
}

Legend

Config

A Config is a persistence layer so that your op can cache data on the host's machine.

  • The config is stored as a JSON object under the following file

    ~/.config/@cto.ai/ops/${username}/${opName}/config.json

  • Configs are persisted between different execution of the code

  • Configs are unique per op, and modifying it using this sdk.getConfig or sdk.setConfig is guaranteed to not tamper another op's configs

State

State is similar to configs, but the data is only unique per run.

  • The state is stored as a JSON object under the following file

    ~/.config/@cto.ai/ops/${username}/${opName}/${runId}/state.json

  • Data saved in state wouldn't be accessible once you terminate the op, because future executions of the op would be different runs.

  • State is useful when combining multiple ops on a workflow, it enables you to pass data one op to another without polluting the config