API Reference
Complete reference for every exported class, function, and type in chatops.js.
Robot
The central runtime. Manages commands, adapters, listeners, middleware, and state.
Constructor
new Robot(config = {})
Static Factory (recommended)
const robot = await Robot.create({
adapters: [], // Array of Adapter instances to register immediately
directory: './modules', // Path to auto-load modules from
baseUrl: import.meta.url // Base URL for resolving module paths
})
Robot.create() auto-registers the built-in help command and loads modules from the given directory.
Properties
| Property | Type | Description |
|---|---|---|
commands | CommandRegistry | Register and resolve commands |
adapters | AdapterRegistry | Register and retrieve adapters |
listeners | ListenerRegistry | Register regex pattern listeners |
Methods
| Method | Returns | Description |
|---|---|---|
robot.use(fn) | void | Register one or more middleware functions |
robot.receive(envelope) | Promise<Result> | Dispatch an inbound command envelope through the full pipeline |
robot.listen(envelope) | Promise<void> | Run pattern listeners against an envelope |
robot.load(moduleLoader) | Promise<void> | Load a module inline (moduleLoader is an async fn receiving robot) |
robot.loadModules({ directory, baseUrl }) | Promise<void> | Auto-load all .js modules from a directory |
robot.log(event, entry) | void | Emit a structured lifecycle log event |
// Register middleware
robot.use(async (ctx, next) => {
console.log('→', ctx.command.id)
await next()
})
// Dispatch a command programmatically
const result = await robot.receive({
adapter: 'cli',
type: 'message',
text: 'ping',
actor: { id: 'test', permissions: [] },
channel: { id: 'test-channel' }
})
// Load a module inline
await robot.load(async (robot) => {
robot.commands.register(new Command({ id: 'ping', handler: async () => createTextResponse('Pong!') }))
})
Command
import { Command } from '@devchitchat/chatopsjs'
new Command({
id: string, // required — canonical ID, e.g. 'tickets.create'
description: string, // optional — shown in help output
aliases: string[], // optional — alternate invocation names
args: Record<string, ArgDef>, // optional — argument schema
permissions: string[], // optional — required actor permission grants
confirm: ConfirmDef | null, // optional — confirmation policy
handler: async (ctx) => Response // optional — command handler
})
ArgDef
{
type: 'string', // currently only 'string' is supported
required: true | false
}
ConfirmDef
{
mode: 'yes-no', // confirmation mode
message: string // prompt shown to the user
}
Properties
| Property | Type | Description |
|---|---|---|
id | string | Canonical identifier |
description | string | Human-readable description for help |
aliases | string[] | Alternate invocation names |
normalizedAliases | string[] | Normalized alias variants (lowercased, trimmed) |
args | object | Argument schema map |
permissions | string[] | Required permission grants |
confirm | object | null | Confirmation configuration |
handler | function | Async handler function |
Adapter
Abstract base class for all adapters. Extend this and implement the three methods.
import { Adapter } from '@devchitchat/chatopsjs'
class MyAdapter extends Adapter {
constructor(robot, options = {}) {
super(robot, 'my-adapter') // second arg = adapter name
}
async start() {
// Bootstrap provider connection
// Call robot.receive(envelope) for each incoming message
}
async send(envelope, message) {
// Deliver response to envelope.channel.id
}
async reply(envelope, message) {
// Deliver direct reply to actor (defaults to send())
await this.send(envelope, message)
}
}
| Method | Required | Description |
|---|---|---|
start() | Required | Bootstrap the provider connection |
send(envelope, message) | Required | Deliver a response to the originating channel |
reply(envelope, message) | Optional | Deliver a direct reply to the actor. Defaults to send() |
CliAdapter
The built-in CLI adapter. Uses Node.js readline for an interactive REPL.
import { CliAdapter } from '@devchitchat/chatopsjs'
const cli = new CliAdapter(robot, {
inputStream: process.stdin, // readable stream (default: stdin)
outputStream: process.stdout, // writable stream (default: stdout)
prompt: 'chatops> ', // REPL prompt string
prefix: null, // command prefix (null = no prefix required)
actor: {
id: 'cli', // actor identity for this session
permissions: ['deploys:write'] // permission grants for this session
},
channel: {
id: 'local-shell' // channel identifier
}
})
The CLI adapter handles the confirmation flow internally — when a command requires confirmation, it prompts the user inline and waits for yes or no.
Response Builders
createTextResponse
import { createTextResponse } from '@devchitchat/chatopsjs'
createTextResponse(text: string)
// Returns: { text: string }
createMessageResponse
import { createMessageResponse } from '@devchitchat/chatopsjs'
createMessageResponse({
fallbackText: string, // Plain text fallback for adapters that can't render blocks
blocks: Block[] // Array of block objects
})
// Returns: { text: string, blocks: Block[] }
Block Types
| Type | Fields | Description |
|---|---|---|
section | text: string | A paragraph of text |
facts | items: { label, value }[] | A key/value data table |
createNativeResponse
import { createNativeResponse } from '@devchitchat/chatopsjs'
createNativeResponse({
fallbackText: string, // Shown by adapters that don't match the provider
provider: string, // Provider name: 'slack' | 'discord' | etc.
payload: object // Provider-native payload object
})
// Returns: { text: string, native: { provider, payload } }
Context (ctx)
The context object is passed to command handlers and middleware:
{
envelope: Envelope, // The original inbound message envelope
command: Command, // The resolved Command instance
args: object, // Parsed argument key/value pairs
adapter: Adapter, // The active Adapter instance
storage: {
get(key: string): Promise<any>,
set(key: string, value: any): Promise<void>
},
state: object, // Mutable per-invocation state for middleware
robot: Robot, // The Robot instance
meta: {
adapter: string, // Adapter name ('cli', 'discord', etc.)
correlationId: string // Unique UUID for this invocation
}
}
Middleware Signature
robot.use(async (ctx, next) => {
// Before handler: mutate ctx.state, add logging, etc.
await next()
// After handler: inspect result, record metrics, etc.
})
Envelope
Passed to robot.receive() by adapters. Describes an inbound message:
{
adapter: string, // Adapter name — must match a registered adapter
type: 'message', // Message type
text: string, // Command text (prefix already stripped by adapter)
actor: {
id: string, // User / actor identifier
permissions: string[] // Permission grants for this actor
},
channel: {
id: string, // Channel / room identifier
guildId?: string // Optional — guild/workspace ID
},
correlationId?: string, // Optional — auto-generated UUID if omitted
confirmation?: {
approved: true // Set by adapter when user confirms a pending command
}
// Any additional adapter-specific fields are passed through transparently
}
receive() Result
robot.receive(envelope) always resolves to a structured result object:
{
ok: boolean,
// Present when ok === true:
response?: { text, blocks?, native? },
command?: { id, aliasUsed },
context?: object,
// Present when ok === false:
error?: {
code: string,
message?: string,
errors?: object[] // Validation errors
},
// Present when confirmation is pending:
confirmation?: { commandId: string },
meta: {
adapter: string,
correlationId: string
}
}
Error Codes
| Code | Meaning |
|---|---|
unknown_command | No command matched the input text |
validation_failed | Required arguments are missing or invalid |
permission_denied | Actor lacks a required permission |
confirmation_required | Command is awaiting user confirmation |
confirmation_cancelled | User responded no to a confirmation prompt |
Registries
CommandRegistry
// Available as robot.commands
robot.commands.register(command: Command): void
robot.commands.resolve(name: string): Command | undefined
robot.commands.list(): Command[]
AdapterRegistry
// Available as robot.adapters
robot.adapters.add(adapter: Adapter): void
robot.adapters.get(name: string): Adapter | undefined
ListenerRegistry
// Available as robot.listeners
robot.listeners.register(pattern: RegExp, handler: async (envelope, match) => void): void
robot.listeners.list(): { pattern, handler }[]
robot.listeners.match(text: string): { pattern, match }[]
Utilities
parseProgramArgs(argv)
import { parseProgramArgs } from '@devchitchat/chatopsjs'
// Parses process.argv-style array for --adapter / -a flags
const args = parseProgramArgs(process.argv.slice(2))
// { adapter: './path/to/adapter.js', ... }
normalizeCommandName(name, options)
import { normalizeCommandName } from '@devchitchat/chatopsjs'
normalizeCommandName('!deploy', { prefix: '!' })
// → 'deploy'
normalizeCommandName('Deploy', {})
// → 'deploy'