Skip to content

Commit b324ac0

Browse files
Merge remote-tracking branch 'origin/staging' into improvement/table-row-deletes
# Conflicts: # apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx # apps/sim/app/workspace/[workspaceId]/tables/components/import-csv-dialog/import-csv-dialog.tsx # apps/sim/app/workspace/[workspaceId]/tables/tables.tsx # apps/sim/lib/table/import-runner.ts # apps/sim/lib/table/service.ts # packages/db/migrations/meta/0227_snapshot.json # packages/db/migrations/meta/_journal.json
2 parents 3866cad + f7811f8 commit b324ac0

1,527 files changed

Lines changed: 117851 additions & 52273 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/add-block/SKILL.md

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -627,19 +627,96 @@ export const ServiceV2Block: BlockConfig = {
627627
}
628628
```
629629

630+
## Block Metadata (BlockMeta)
631+
632+
Every integration block **must** export a `{Service}BlockMeta` object at the bottom of the block file. This metadata drives the integration catalog, tag filters, and workflow template suggestions shown to users.
633+
634+
### Structure
635+
636+
```typescript
637+
import type { BlockConfig, BlockMeta } from '@/blocks/types'
638+
639+
// ... block definition above ...
640+
641+
export const {Service}BlockMeta = {
642+
tags: ['messaging', 'automation'], // Same tags as the block's tags field
643+
templates: [ // Optional but strongly encouraged
644+
{
645+
icon: {Service}Icon,
646+
title: '{Service} use-case title',
647+
prompt: 'Build a workflow that ...',
648+
modules: ['agent', 'workflows'], // Modules the template uses
649+
category: 'productivity', // Template category
650+
tags: ['automation'], // Template-level tags
651+
alsoIntegrations: ['slack'], // Other blocks referenced in the prompt (optional)
652+
},
653+
],
654+
skills: [ // Optional but strongly encouraged
655+
{
656+
name: 'summarize-thread', // kebab-case, becomes the created skill's name
657+
description: 'One line: what it does and when to use it.',
658+
content:
659+
'# Summarize Thread\n\n...\n\n## Steps\n1. ...\n\n## Output\n...', // markdown
660+
},
661+
],
662+
} as const satisfies BlockMeta
663+
```
664+
665+
### Rules
666+
667+
- **Import `BlockMeta`** from `@/blocks/types` alongside `BlockConfig`
668+
- **`tags`** must match the `tags` array on the block config exactly
669+
- **Templates are optional** but should be added for any integration that has a recognizable use case — aim for 2–4 templates per block
670+
- **Template `prompt`** should start with "Build a workflow that..." or "Create a workflow that..." and be concrete enough to generate a real workflow in Mothership
671+
- **Template `modules`** lists the Sim modules the template relies on: `'knowledge-base' | 'tables' | 'files' | 'workflows' | 'scheduled' | 'agent'`
672+
- **Template `category`** is one of: `'popular' | 'sales' | 'support' | 'engineering' | 'marketing' | 'productivity' | 'operations'`
673+
- **`alsoIntegrations`** names other block types (e.g. `'slack'`, `'linear'`) referenced in the template prompt — helps the catalog surface this template when those blocks are selected
674+
- Place the export **after** the main `{Service}Block` export, at the very bottom of the file
675+
676+
#### `skills` — curated, ready-to-add agent skills
677+
678+
`skills` is an optional array of `SuggestedSkill` (`{ name, description, content }`) shown on the integration's detail page; users click **Add** to create the skill in their workspace. Aim for 3–5 skills for mainstream services, 2–3 for niche/low-level ones.
679+
680+
- **`name`** — kebab-case, lowercase letters/numbers/hyphens, ≤ 64 chars, unique within the integration, verb-led (e.g. `summarize-thread`).
681+
- **`description`** — one line, ≤ 1024 chars: what it does and when to use it.
682+
- **`content`** — markdown instructions for the agent (literal `\n` for newlines): a `# Title`, then `## Steps` and an output/guidance section. Keep ~600–2000 chars.
683+
- **Ground every skill in operations the block actually exposes.** Cross-check each skill's steps against the block's `tools.access` list — never describe an action the integration cannot perform (e.g. "receive messages" when the block only sends).
684+
- **Skills MUST be derived from real, popular use cases found online — never invented.** Before adding a skill, web-search the service's documented use cases (vendor use-case/solutions pages, official docs describing the workflow, reputable "top automations for X" articles). If you cannot source a use case as something people genuinely do with the service, do not add it. Do not hallucinate skills.
685+
686+
### Register in the blocksMeta object
687+
688+
After adding `{Service}BlockMeta` to the block file, register it in `apps/sim/blocks/registry.ts`:
689+
690+
```typescript
691+
// Add import (alongside the block import, alphabetically)
692+
import { ServiceBlock, ServiceBlockMeta } from '@/blocks/blocks/service'
693+
694+
// Add to blocksMeta object (alphabetically)
695+
export const blocksMeta = {
696+
// ... existing entries ...
697+
service: ServiceBlockMeta,
698+
}
699+
```
700+
630701
## Registering Blocks
631702

632703
After creating the block, remind the user to:
633-
1. Import in `apps/sim/blocks/registry.ts`
704+
1. Import `{Service}Block` and `{Service}BlockMeta` in `apps/sim/blocks/registry.ts`
634705
2. Add to the `registry` object (alphabetically):
706+
3. Add to the `blocksMeta` object (alphabetically):
635707

636708
```typescript
637-
import { ServiceBlock } from '@/blocks/blocks/service'
709+
import { ServiceBlock, ServiceBlockMeta } from '@/blocks/blocks/service'
638710

639711
export const registry: Record<string, BlockConfig> = {
640712
// ... existing blocks ...
641713
service: ServiceBlock,
642714
}
715+
716+
export const blocksMeta = {
717+
// ... existing entries ...
718+
service: ServiceBlockMeta,
719+
}
643720
```
644721

645722
## Complete Example
@@ -827,7 +904,11 @@ All tool IDs referenced in `tools.access` and returned by `tools.config.tool` MU
827904
- [ ] Tools.access lists all tool IDs (snake_case)
828905
- [ ] Tools.config.tool returns correct tool ID (snake_case)
829906
- [ ] Outputs match tool outputs
830-
- [ ] Block registered in registry.ts
907+
- [ ] Block registered in `registry.ts` blocks object (alphabetically)
908+
- [ ] `{Service}BlockMeta` exported at bottom of block file with `tags` and `templates`
909+
- [ ] `skills` added to `{Service}BlockMeta`, each grounded in the block's `tools.access` and derived from a real online-sourced use case (not invented)
910+
- [ ] `BlockMeta` imported from `@/blocks/types` alongside `BlockConfig`
911+
- [ ] Block meta registered in `registry.ts` blocksMeta object (alphabetically)
831912
- [ ] If icon missing: asked user to provide SVG
832913
- [ ] If triggers exist: `triggers` config set, trigger subBlocks spread
833914
- [ ] Optional/rarely-used fields set to `mode: 'advanced'`

.agents/skills/add-integration/SKILL.md

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export const {service}{Action}Tool: ToolConfig<Params, Response> = {
128128
### Block Structure
129129
```typescript
130130
import { {Service}Icon } from '@/components/icons'
131-
import type { BlockConfig } from '@/blocks/types'
131+
import type { BlockConfig, BlockMeta } from '@/blocks/types'
132132
import { AuthMode } from '@/blocks/types'
133133
import { getScopesForService } from '@/lib/oauth/utils'
134134

@@ -177,8 +177,32 @@ export const {Service}Block: BlockConfig = {
177177

178178
outputs: { /* ... */ },
179179
}
180+
181+
export const {Service}BlockMeta = {
182+
tags: ['tag1', 'tag2'], // IntegrationTag values matching the service's capabilities
183+
templates: [
184+
{
185+
icon: {Service}Icon,
186+
title: '{Service} use-case title',
187+
prompt: 'Build a workflow that ...',
188+
modules: ['agent', 'workflows'],
189+
category: 'productivity',
190+
tags: ['automation'],
191+
alsoIntegrations: ['slack'], // Optional: other blocks referenced in the prompt
192+
},
193+
],
194+
} as const satisfies BlockMeta
180195
```
181196

197+
### BlockMeta rules
198+
199+
- **Tags**: Use `IntegrationTag` values from `@/blocks/types`. Do NOT add a `tags` field to the `BlockConfig` object — tags belong only in `BlockMeta`.
200+
- **`integrationType`**: Must be a valid `IntegrationType` enum value (AI, Analytics, Commerce, Communication, Databases, DevOps, Documents, Email, HR, Marketing, Observability, Productivity, Sales, Search, Security, Support). Never invent a value that doesn't exist in the enum.
201+
- **Templates**: Aim for 2–4 templates per integration. Prompts should be concrete enough to generate a real workflow in Mothership. Start with "Build a workflow that..." or "Create a workflow that...".
202+
- **`alsoIntegrations`**: List other block type IDs referenced in the template prompt (e.g. `'slack'`, `'linear'`).
203+
- Place `{Service}BlockMeta` at the very bottom of the file, after the main block export.
204+
- Register it in both the import and the `blocksMeta` object in `registry.ts`.
205+
182206
### Key SubBlock Patterns
183207

184208
**Condition-based visibility:**
@@ -359,14 +383,20 @@ export const tools: Record<string, ToolConfig> = {
359383
### Block Registry (`apps/sim/blocks/registry.ts`)
360384

361385
```typescript
362-
// Add import (alphabetically)
363-
import { {Service}Block } from '@/blocks/blocks/{service}'
386+
// Add import (alphabetically) — include BlockMeta
387+
import { {Service}Block, {Service}BlockMeta } from '@/blocks/blocks/{service}'
364388

365-
// Add to registry (alphabetically)
389+
// Add to blocks registry (alphabetically)
366390
export const registry: Record<string, BlockConfig> = {
367391
// ... existing blocks ...
368392
{service}: {Service}Block,
369393
}
394+
395+
// Add to blocksMeta registry (alphabetically)
396+
export const blocksMeta = {
397+
// ... existing entries ...
398+
{service}: {Service}BlockMeta,
399+
}
370400
```
371401

372402
### Trigger Registry (`apps/sim/triggers/registry.ts`) - If triggers exist
@@ -433,7 +463,12 @@ If creating V2 versions (API-aligned outputs):
433463
- [ ] Configured tools.access with all tool IDs
434464
- [ ] Configured tools.config.tool selector
435465
- [ ] Defined outputs matching tool outputs
436-
- [ ] Registered block in `blocks/registry.ts`
466+
- [ ] `integrationType` uses a valid `IntegrationType` enum value (no invented values)
467+
- [ ] No `tags` field on the `BlockConfig` object (tags live only in `BlockMeta`)
468+
- [ ] `{Service}BlockMeta` exported at bottom of file with `tags` and `templates`
469+
- [ ] `BlockMeta` type imported from `@/blocks/types` alongside `BlockConfig`
470+
- [ ] Block registered in `blocks/registry.ts` blocks object (alphabetically)
471+
- [ ] Block meta registered in `blocks/registry.ts` blocksMeta object (alphabetically)
437472
- [ ] If triggers: set `triggers.enabled` and `triggers.available`
438473
- [ ] If triggers: spread trigger subBlocks with `getTrigger()`
439474

.agents/skills/validate-integration/SKILL.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,12 @@ For **each tool** in `tools.access`:
207207
- [ ] `authMode` is set correctly (`AuthMode.OAuth` or `AuthMode.ApiKey`)
208208
- [ ] Block is registered in `blocks/registry.ts` alphabetically
209209

210+
### BlockMeta Skills (catalog)
211+
- [ ] `{Service}BlockMeta.skills` is present (3–5 for mainstream services, 2–3 for niche/low-level)
212+
- [ ] **Every skill is grounded** — its steps only use operations the block exposes in `tools.access`; flag any skill that implies an unsupported action (e.g. "receive messages" when the block only sends)
213+
- [ ] **Every skill is real, not hallucinated** — web-search the service and confirm each skill maps to a popular use case attested online (vendor use-case/solutions pages, official docs describing the workflow, reputable "top automations for X" articles). Rewrite or remove any skill you cannot source as something people genuinely do with the service.
214+
- [ ] Each skill has a kebab-case `name` (≤64 chars, unique), a one-line `description`, and markdown `content` with `# Title` + `## Steps` + an output/guidance section
215+
210216
### Block Inputs
211217
- [ ] `inputs` section lists all subBlock params that the block accepts
212218
- [ ] Input types match the subBlock types

.claude/commands/add-block.md

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ Maps multiple UI fields to a single serialized parameter:
429429

430430
**Critical constraints:**
431431
- `canonicalParamId` must NOT match any other subblock's `id` in the same block (causes conflicts)
432-
- `canonicalParamId` must be unique per block (only one basic/advanced pair per canonicalParamId)
432+
- A `canonicalParamId` links exactly one basic/advanced pair for a single logical parameter. Do NOT reuse the same `canonicalParamId` for different parameters, even under mutually-exclusive conditions/operations
433433
- ONLY use `canonicalParamId` to link basic/advanced mode alternatives for the same logical parameter
434434
- Do NOT use it for any other purpose
435435

@@ -519,7 +519,10 @@ tools: {
519519
Block outputs only support:
520520
- `type` - The data type ('string', 'number', 'boolean', 'json', 'array')
521521
- `description` - Human readable description
522-
- Nested object structure (for complex types)
522+
- `condition` - Optional visibility condition
523+
- `hiddenFromDisplay` - Optional flag to hide from the output display
524+
525+
**Nested object/`properties` outputs are tool-output-only and will fail TypeScript at build time on block outputs.** For complex shapes use `type: 'json'` and describe the inner fields in the `description` string.
523526

524527
```typescript
525528
outputs: {
@@ -542,7 +545,7 @@ outputs: {
542545

543546
### Typed JSON Outputs
544547

545-
When using `type: 'json'` and you know the object shape in advance, **describe the inner fields in the description** so downstream blocks know what properties are available. For well-known, stable objects, use nested output definitions instead:
548+
When using `type: 'json'` and you know the object shape in advance, **describe the inner fields in the description** so downstream blocks know what properties are available. Block outputs have no nested `properties` form — always keep the output flat and put the shape in the `description`:
546549

547550
```typescript
548551
outputs: {
@@ -554,26 +557,10 @@ outputs: {
554557
type: 'json',
555558
description: 'Zone plan information (id, name, price, currency, frequency, is_subscribed)',
556559
},
557-
558-
// BEST: Use nested output definition when the shape is stable and well-known
559-
plan: {
560-
id: { type: 'string', description: 'Plan identifier' },
561-
name: { type: 'string', description: 'Plan name' },
562-
price: { type: 'number', description: 'Plan price' },
563-
currency: { type: 'string', description: 'Price currency' },
564-
},
565560
}
566561
```
567562

568-
Use the nested pattern when:
569-
- The object has a small, stable set of fields (< 10)
570-
- Downstream blocks will commonly access specific properties
571-
- The API response shape is well-documented and unlikely to change
572-
573-
Use `type: 'json'` with a descriptive string when:
574-
- The object has many fields or a dynamic shape
575-
- It represents a list/array of items
576-
- The shape varies by operation
563+
Nested object outputs (`plan: { id: { type: 'string' }, ... }`) are a **tool-output** feature only — `OutputFieldDefinition` for blocks does not allow them and they fail TypeScript at build time.
577564

578565
## V2 Block Pattern
579566

@@ -798,6 +785,47 @@ Use `wandConfig` for fields that are hard to fill out manually, such as timestam
798785

799786
All tool IDs referenced in `tools.access` and returned by `tools.config.tool` MUST use `snake_case` (e.g., `x_create_tweet`, `slack_send_message`). Never use camelCase or PascalCase.
800787

788+
## BlockMeta (Required)
789+
790+
Every block file must export a `{Service}BlockMeta` alongside the block — **minimum 7 templates**. Look at existing examples in `apps/sim/blocks/blocks/` (e.g. `browser_use.ts`, `google_sheets.ts`) for the pattern.
791+
792+
```typescript
793+
import type { BlockMeta } from '@/blocks/types'
794+
795+
export const {Service}BlockMeta = {
796+
tags: ['tag1', 'tag2'], // IntegrationTag[]
797+
templates: [
798+
{
799+
icon: {Service}Icon,
800+
title: '{Service} <use-case>', // 2–5 words
801+
prompt: 'Build a workflow that...', // specific use case, 1–3 sentences
802+
modules: ['agent', 'workflows'], // 'agent' | 'workflows' | 'tables' | 'files' | 'scheduled' | 'knowledge-base'
803+
category: 'operations', // 'operations' | 'marketing' | 'sales' | 'engineering' | 'productivity' | 'support' | 'popular'
804+
tags: ['automation'],
805+
alsoIntegrations: ['slack'], // optional — other block IDs referenced in the prompt
806+
featured: true, // optional
807+
},
808+
// ... at least 6 more
809+
],
810+
skills: [ // SuggestedSkill[] — 3–5 mainstream, 2–3 niche
811+
{
812+
name: 'summarize-thread', // kebab-case, ≤64 chars, unique, verb-led
813+
description: 'One line: what it does and when to use it.', // ≤1024 chars
814+
content:
815+
'# Summarize Thread\n\n...\n\n## Steps\n1. ...\n\n## Output\n...', // markdown
816+
},
817+
// ... more
818+
],
819+
} as const satisfies BlockMeta
820+
```
821+
822+
Derive templates from the service's real use cases. Each prompt should name a concrete trigger, transformation, and output — not a generic description of what the service does.
823+
824+
`skills` are curated, ready-to-add agent skills shown on the integration's detail page (users click **Add** to create them in their workspace). Two hard rules:
825+
826+
- **Ground every skill in operations the block actually exposes** — cross-check each skill's steps against `tools.access`. Never describe an action the integration cannot perform.
827+
- **Derive skills from real, popular use cases found online — never invent them.** Web-search the service's documented use cases (vendor use-case/solutions pages, official docs describing the workflow, reputable "top automations for X" articles) and only add a skill you can source as something people genuinely do with the service. Do not hallucinate skills.
828+
801829
## Checklist Before Finishing
802830

803831
- [ ] `integrationType` is set to the correct `IntegrationType` enum value
@@ -816,6 +844,8 @@ All tool IDs referenced in `tools.access` and returned by `tools.config.tool` MU
816844
- [ ] If triggers exist: `triggers` config set, trigger subBlocks spread
817845
- [ ] Optional/rarely-used fields set to `mode: 'advanced'`
818846
- [ ] Timestamps and complex inputs have `wandConfig` enabled
847+
- [ ] Exported `{Service}BlockMeta` with at least 7 templates
848+
- [ ] `skills` added to `{Service}BlockMeta`, each grounded in `tools.access` and sourced from a real online use case (not invented)
819849

820850
## Final Validation (Required)
821851

@@ -829,3 +859,4 @@ After creating the block, you MUST validate it against every tool it references:
829859
- Type coercions in `tools.config.params` for any params that need conversion (Number(), Boolean(), JSON.parse())
830860
3. **Verify block outputs** cover the key fields returned by all tools
831861
4. **Verify conditions** — each subBlock should only show for the operations that actually use it
862+
5. **Verify `{Service}BlockMeta` is exported** with at least 7 templates, each having `icon`, `title`, `prompt`, `modules`, `category`, and `tags`

0 commit comments

Comments
 (0)