mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-28 00:08:21 -05:00
* feat(claude): added rules * fix(copilot): chat loading; refactor(copilot): components, utils, hooks * fix(copilot): options selection strikethrough * fix(copilot): options render inside thinking * fix(copilot): checkpoints, user-input; improvement(code): colors * fix(copilot): scrolling, tool-call truncation, thinking ui * fix(copilot): tool call spacing and shimmer/actions on previous messages * improvement(copilot): queue * addressed comments
5.8 KiB
5.8 KiB
paths
| paths | |||
|---|---|---|---|
|
Adding Integrations
Overview
Adding a new integration typically requires:
- Tools - API operations (
tools/{service}/) - Block - UI component (
blocks/blocks/{service}.ts) - Icon - SVG icon (
components/icons.tsx) - Trigger (optional) - Webhooks/polling (
triggers/{service}/)
Always look up the service's API docs first.
1. Tools (tools/{service}/)
tools/{service}/
├── index.ts # Export all tools
├── types.ts # Params/response types
├── {action}.ts # Individual tool (e.g., send_message.ts)
└── ...
Tool file structure:
// tools/{service}/{action}.ts
import type { {Service}Params, {Service}Response } from '@/tools/{service}/types'
import type { ToolConfig } from '@/tools/types'
export const {service}{Action}Tool: ToolConfig<{Service}Params, {Service}Response> = {
id: '{service}_{action}',
name: '{Service} {Action}',
description: 'What this tool does',
version: '1.0.0',
oauth: { required: true, provider: '{service}' }, // if OAuth
params: { /* param definitions */ },
request: {
url: '/api/tools/{service}/{action}',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({ ...params }),
},
transformResponse: async (response) => {
const data = await response.json()
if (!data.success) throw new Error(data.error)
return { success: true, output: data.output }
},
outputs: { /* output definitions */ },
}
Register in tools/registry.ts:
import { {service}{Action}Tool } from '@/tools/{service}'
// Add to registry object
{service}_{action}: {service}{Action}Tool,
2. Block (blocks/blocks/{service}.ts)
import { {Service}Icon } from '@/components/icons'
import type { BlockConfig } from '@/blocks/types'
import type { {Service}Response } from '@/tools/{service}/types'
export const {Service}Block: BlockConfig<{Service}Response> = {
type: '{service}',
name: '{Service}',
description: 'Short description',
longDescription: 'Detailed description',
category: 'tools',
bgColor: '#hexcolor',
icon: {Service}Icon,
subBlocks: [ /* see SubBlock Properties below */ ],
tools: {
access: ['{service}_{action}', ...],
config: {
tool: (params) => `{service}_${params.operation}`,
params: (params) => ({ ...params }),
},
},
inputs: { /* input definitions */ },
outputs: { /* output definitions */ },
}
SubBlock Properties
{
id: 'fieldName', // Unique identifier
title: 'Field Label', // UI label
type: 'short-input', // See SubBlock Types below
placeholder: 'Hint text',
required: true, // See Required below
condition: { ... }, // See Condition below
dependsOn: ['otherField'], // See DependsOn below
mode: 'basic', // 'basic' | 'advanced' | 'both' | 'trigger'
}
SubBlock Types: short-input, long-input, dropdown, code, switch, slider, oauth-input, channel-selector, user-selector, file-upload, etc.
condition - Show/hide based on another field
// Show when operation === 'send'
condition: { field: 'operation', value: 'send' }
// Show when operation is 'send' OR 'read'
condition: { field: 'operation', value: ['send', 'read'] }
// Show when operation !== 'send'
condition: { field: 'operation', value: 'send', not: true }
// Complex: NOT in list AND another condition
condition: {
field: 'operation',
value: ['list_channels', 'list_users'],
not: true,
and: { field: 'destinationType', value: 'dm', not: true }
}
required - Field validation
// Always required
required: true
// Conditionally required (same syntax as condition)
required: { field: 'operation', value: 'send' }
dependsOn - Clear field when dependencies change
// Clear when credential changes
dependsOn: ['credential']
// Clear when authMethod changes AND (credential OR botToken) changes
dependsOn: { all: ['authMethod'], any: ['credential', 'botToken'] }
mode - When to show field
'basic'- Only in basic mode (default UI)'advanced'- Only in advanced mode (manual input)'both'- Show in both modes (default)'trigger'- Only when block is used as trigger
Register in blocks/registry.ts:
import { {Service}Block } from '@/blocks/blocks/{service}'
// Add to registry object (alphabetically)
{service}: {Service}Block,
3. Icon (components/icons.tsx)
export function {Service}Icon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
{/* SVG path from service's brand assets */}
</svg>
)
}
4. Trigger (triggers/{service}/) - Optional
triggers/{service}/
├── index.ts # Export all triggers
├── webhook.ts # Webhook handler
├── utils.ts # Shared utilities
└── {event}.ts # Specific event handlers
Register in triggers/registry.ts:
import { {service}WebhookTrigger } from '@/triggers/{service}'
// Add to TRIGGER_REGISTRY
{service}_webhook: {service}WebhookTrigger,
Checklist
- Look up API docs for the service
- Create
tools/{service}/types.tswith proper types - Create tool files for each operation
- Create
tools/{service}/index.tsbarrel export - Register tools in
tools/registry.ts - Add icon to
components/icons.tsx - Create block in
blocks/blocks/{service}.ts - Register block in
blocks/registry.ts - (Optional) Create triggers in
triggers/{service}/ - (Optional) Register triggers in
triggers/registry.ts