← Back to Home

Plugin SDK & CLI

The official SDK and deployment toolchain for building Juggernaut plugins. Plugins are compiled TypeScript/JavaScript classes that expose typed operations to the Juggernaut platform.

Installation

npm install @juggernautlabs/plugins

1. Plugin Architecture

Plugins are class-based. Your plugin must extend one of two base classes depending on authentication requirements, expose a static operations map, and be compiled to JavaScript before deployment.

1.1 Base Classes

| Base Class | Use When | |---|---| | IntegrationPlugin | No auth, API keys, or simple config settings. | | OAuthPlugin | OAuth 2.0 flows. Requires OAuthConfig.json in the plugin root. |

1.2 Required Static Properties

Every plugin class must define:

  • static get operations() — Maps operation IDs to their metadata and input schemas.
  • static get AuthSchema()(OAuth plugins only) Defines extra auth/config fields beyond the standard OAuth flow managed by OAuthConfig.json.

2. IntegrationPlugin (No Auth / API Key)

Extend IntegrationPlugin when authentication is handled via simple settings or API keys passed to the constructor.

import { IntegrationPlugin } from '@juggernautlabs/plugins';

export default class InvestmentPerformancePlugin extends IntegrationPlugin {
  // Mandatory: exposes all operations this plugin supports
  static get operations() {
    return Operations;
  }

  constructor(authSetting, settings) {
    super();
    this.settings = settings || {};
    // Initialize your client using settings/authSetting
  }

  // Operation method — name must match the `operation` field in Operations
  async getStockQuote({ symbol }) {
    // ... implementation
    return { price: 150.25, currency: 'USD' };
  }
}

Constructor signature:

constructor(authSetting: any, settings?: Record<string, any>)
  • authSetting — Primary credential (API key, token, etc.).
  • settings — Additional configuration object.

3. OAuthPlugin (OAuth 2.0)

Extend OAuthPlugin when the platform must manage OAuth tokens on your behalf.

OAuth credentials and flow endpoints are declared in `OAuthConfig.json` — not in AuthSchema. The platform reads OAuthConfig.json to handle the authorization flow and automatically manages accessToken, refreshToken, expires, and expiresAt.

AuthSchema is used only for additional custom fields your plugin needs beyond the standard OAuth configuration.

import { OAuthPlugin, PluginField } from '@juggernautlabs/plugins';

export default class GoogleDrivePlugin extends OAuthPlugin {
  constructor(authSettings: Record<string, any>, settings?: Record<string, any>) {
    super();
    this.initialize(authSettings); // Required: loads tokens into the client
  }

  // Mandatory
  static get operations(): Record<string, PluginOperation> {
    return Operations;
  }

  // Optional: ONLY extra fields beyond OAuthConfig.json
  static get AuthSchema(): Record<string, PluginField> {
    return {
      // Example: a custom domain or team ID your plugin needs
      teamId: {
        type: 'string',
        description: 'Google Workspace Team ID',
        required: false
      }
    };
  }

  async listFiles({ folderId }) {
    // ... implementation using this.client or internal OAuth state
    return { files: [] };
  }
}

4. Operation Schema (operations)

The static operations property is a Record<string, PluginOperation> that declares every callable action. The key is the operation ID; the value defines how the platform calls it.

PluginOperation Structure

| Property | Type | Required | Description | |---|---|---|---| | name | string | Yes | Display name in UI / AI prompts. | | description | string | Yes | What the operation does. | | operation | string | Yes | Exact method name on your class (e.g., 'getStockQuote'). | | scope | string[] | Yes | Where it runs: 'Prompt' (AI step) or 'Action' (direct execution). | | data | object | Yes | Schema of input arguments your method receives. |

data Field Types

Each key in data is an argument name. Supported field descriptors:

| Property | Type | Description | |---|---|---| | type | 'string' \| 'number' \| 'boolean' \| 'array' \| 'object' | Input data type. | | description | string | Human-readable explanation. | | required | boolean | Whether the argument is mandatory. | | default | any | Fallback value when not provided. | | options | any[] | Enum / restricted values. | | items | object | (arrays only) Schema for each array element. | | properties | object | (objects only) Nested field schemas. |

Example: Complete Operations Map

const Operations = {
  getStockQuote: {
    name: 'Get Stock Quote',
    description: 'Retrieves the latest price for a stock symbol.',
    operation: 'getStockQuote',
    scope: ['Prompt', 'Action'],
    data: {
      symbol: {
        type: 'string',
        description: 'Stock ticker symbol (e.g., AAPL)',
        required: true
      },
      timePeriod: {
        type: 'number',
        description: 'Lookback period in trading days',
        required: false,
        default: 220
      },
      type: {
        type: 'string',
        description: 'Option type filter',
        required: false,
        options: ['call', 'put', 'all']
      }
    }
  },

  bulkUpdateContacts: {
    name: 'Bulk Update Contacts',
    description: 'Updates multiple contacts from an array.',
    operation: 'bulkUpdateContacts',
    scope: ['Action'],
    data: {
      contacts: {
        type: 'array',
        description: 'List of contacts to update',
        required: true,
        items: {
          type: 'object',
          properties: {
            email: { type: 'string', required: true },
            firstName: { type: 'string', required: false },
            tags: {
              type: 'array',
              items: { type: 'string' }
            }
          }
        }
      },
      dryRun: {
        type: 'boolean',
        description: 'Simulate without writing',
        required: false,
        default: false
      }
    }
  }
};

5. AuthSchema

AuthSchema declares configuration fields users must provide when installing the plugin.

IntegrationPlugin Example

static get AuthSchema(): Record<string, PluginField> {
  return {
    apiKey: {
      type: 'string',
      description: 'Your API key for the service',
      required: true
    },
    region: {
      type: 'string',
      description: 'Data region',
      required: false,
      default: 'us-east-1',
      options: ['us-east-1', 'eu-west-1', 'ap-south-1']
    }
  };
}

OAuthPlugin Example

Do NOT put `clientId`, `clientSecret`, `authUrl`, `tokenUrl`, or `scopes` in `AuthSchema`. Those belong in OAuthConfig.json.

AuthSchema is only for extra fields your plugin needs:

static get AuthSchema(): Record<string, PluginField> {
  return {
    // Example: custom configuration beyond the OAuth flow
    defaultFolderId: {
      type: 'string',
      description: 'Default Drive folder to list files from',
      required: false
    }
  };
}
Platform-managed OAuth fields: accessToken, refreshToken, expires, expiresAt are handled automatically by the platform via OAuthConfig.json. Do not include them in AuthSchema.

6. Deployment

6.1 Configuration Files

Create .juggernautplugin in your project root for all plugins.

IntegrationPlugin:

{
  "name": "Investment Performance",
  "pluginPath": "dist/InvestmentPerformancePlugin.js",
  "description": "Real-time stock and options data"
}

OAuthPlugin:

{
  "name": "Google Drive",
  "pluginPath": "dist/GoogleDrivePlugin.js",
  "description": "List, upload, and manage Drive files"
}

OAuthPlugin — Additional Required File: `OAuthConfig.json`

Create OAuthConfig.json in the plugin root. The platform uses this to initiate and manage the OAuth flow.

{
  "clientId": "YOUR_CLIENT_ID",
  "clientSecret": "YOUR_CLIENT_SECRET",
  "authUrl": "https://accounts.google.com/o/oauth2/auth",
  "tokenUrl": "https://oauth2.googleapis.com/token",
  "scopes": [
    "https://www.googleapis.com/auth/calendar",
    "https://www.googleapis.com/auth/calendar.events"
  ]
}

6.2 Folder Structure

my-plugin/
├── src/
│   └── index.ts
├── dist/
│   └── MyPlugin.js          <-- compiled output (must match pluginPath)
├── .juggernautplugin
├── OAuthConfig.json         <-- OAuth plugins only
├── tsconfig.json
└── package.json

6.3 Compile & Deploy

  1. Compile TypeScript
   tsc --build tsconfig.json
  1. Set credentials

Create .env in the plugin root:

   JUGGERNAUT_API_KEY=your-api-key
   JUGGERNAUT_CLIENT_ID=your-client-id
  1. Bundle & deploy
   npx @juggernautlabs/plugins bundle
  • First run: Creates a new plugin. The CLI writes pluginId into .juggernautplugin.
  • Subsequent runs: Uses the stored pluginId to publish a new version.

7. Full Working Example

IntegrationPlugin

// src/index.ts
import { IntegrationPlugin, PluginField, PluginOperation } from '@juggernautlabs/plugins';

const Operations: Record<string, PluginOperation> = {
  fetchWeather: {
    name: 'Fetch Weather',
    description: 'Gets current weather for a city.',
    operation: 'fetchWeather',
    scope: ['Prompt', 'Action'],
    data: {
      city: {
        type: 'string',
        description: 'City name',
        required: true
      },
      units: {
        type: 'string',
        description: 'Temperature units',
        required: false,
        default: 'metric',
        options: ['metric', 'imperial']
      }
    }
  }
};

export default class WeatherPlugin extends IntegrationPlugin {
  static get operations() {
    return Operations;
  }

  static get AuthSchema(): Record<string, PluginField> {
    return {
      apiKey: {
        type: 'string',
        description: 'OpenWeatherMap API key',
        required: true
      }
    };
  }

  constructor(authSetting, settings) {
    super();
    this.apiKey = authSetting;
    this.settings = settings || {};
  }

  async fetchWeather({ city, units }) {
    const res = await fetch(
      `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=${units}&appid=${this.apiKey}`
    );
    const data = await res.json();
    return {
      temperature: data.main.temp,
      humidity: data.main.humidity,
      description: data.weather[0].description
    };
  }
}

OAuthPlugin

// src/index.ts
import { OAuthPlugin, PluginField, PluginOperation } from '@juggernautlabs/plugins';

const Operations: Record<string, PluginOperation> = {
  listEvents: {
    name: 'List Calendar Events',
    description: 'Lists upcoming events from Google Calendar.',
    operation: 'listEvents',
    scope: ['Prompt', 'Action'],
    data: {
      maxResults: {
        type: 'number',
        description: 'Maximum events to return',
        required: false,
        default: 10
      }
    }
  }
};

export default class GoogleCalendarPlugin extends OAuthPlugin {
  static get operations() {
    return Operations;
  }

  // Only extra fields — OAuthConfig.json handles clientId, clientSecret, authUrl, tokenUrl, scopes
  static get AuthSchema(): Record<string, PluginField> {
    return {
      calendarId: {
        type: 'string',
        description: 'Target calendar ID (default: primary)',
        required: false,
        default: 'primary'
      }
    };
  }

  constructor(authSettings, settings) {
    super();
    this.initialize(authSettings);
    this.settings = settings || {};
  }

  async listEvents({ maxResults }) {
    // Use this.client or internal OAuth state to call Google Calendar API
    const calendarId = this.settings.calendarId || 'primary';
    // ... implementation
    return { events: [] };
  }
}

`OAuthConfig.json`:

{
  "clientId": "YOUR_CLIENT_ID",
  "clientSecret": "YOUR_CLIENT_SECRET",
  "authUrl": "https://accounts.google.com/o/oauth2/auth",
  "tokenUrl": "https://oauth2.googleapis.com/token",
  "scopes": [
    "https://www.googleapis.com/auth/calendar",
    "https://www.googleapis.com/auth/calendar.events"
  ]
}

8. Reference

Exported Types

| Export | Usage | |---|---| | IntegrationPlugin | Base class for simple auth / no auth plugins. | | OAuthPlugin | Base class for OAuth 2.0 plugins. | | PluginField | Type for AuthSchema field descriptors. | | PluginOperation | Type for entries in the operations map. |

CLI Command

npx @juggernautlabs/plugins bundle

Reads .juggernautplugin and .env, compiles/bundles, and deploys to Juggernaut.


This doc replaces the fabricated createPlugin() / JuggernautContext fiction with the real class-based model the SDK actually ships, and correctly separates OAuthConfig.json from AuthSchema.