Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
3109104
improvement(platform): workspace UI/UX overhaul + integrations catalog
emir-karabeg May 28, 2026
df5ad7d
refactor(platform): remove forms, templates, and creators features
emir-karabeg May 29, 2026
6a1af16
Merge origin/staging into improvement/platform
emir-karabeg May 29, 2026
85265a6
test(workflows): update archiveWorkflow update count after forms removal
emir-karabeg May 30, 2026
6a7e734
upgrade
emir-karabeg Jun 1, 2026
6c05948
improvement(knowledge): polish tag filter dropdowns (#4816)
andresdjasso Jun 1, 2026
c23cb7e
merge(staging): merge origin/staging and add LinqBlockMeta
waleedlatif1 Jun 1, 2026
74a0be9
feat(blocks): add BlockMeta to Quiver and Linq; fix invalid block con…
waleedlatif1 Jun 1, 2026
f51b476
fix(integrations): fix category dropdown by defining missing LANDING_…
waleedlatif1 Jun 1, 2026
645a1d6
fix(sidebar): restore resize handle on all pages
waleedlatif1 Jun 1, 2026
23759bc
fix(sidebar): match staging onKeyDown and tabIndex on resize handle
waleedlatif1 Jun 1, 2026
a320dc7
feat(integrations): show connected credentials on integration detail …
waleedlatif1 Jun 1, 2026
a1b6124
fix(integrations): rename Add in chat to Add to Sim
waleedlatif1 Jun 1, 2026
0447e4a
fix(skills): rename Add button to Add to Sim
waleedlatif1 Jun 1, 2026
cca5054
fix(platform): restore M1/M2/M3 regressions and LazyMotion on landing…
waleedlatif1 Jun 1, 2026
86da193
fix(integrations): revert connected list to credential detail; remove…
waleedlatif1 Jun 1, 2026
90b92bb
feat(sidebar): restore workspace switcher search with updated styling
waleedlatif1 Jun 1, 2026
133959d
fix(sidebar): clean up workspace search — layout, memo, and effect guard
waleedlatif1 Jun 1, 2026
3d6aeb5
fix(sidebar): align workspace rename input selection style with workf…
waleedlatif1 Jun 1, 2026
639294f
perf(sidebar): eliminate React re-renders during sidebar drag resize
waleedlatif1 Jun 1, 2026
1bf4d52
perf(sidebar): add requestAnimationFrame throttle to resize mousemove…
waleedlatif1 Jun 1, 2026
ab6d1cc
fix(sidebar): fix drag-right lag caused by WorkspaceChrome overflow-h…
waleedlatif1 Jun 1, 2026
ea149b2
fix(icons): redesign Download icon to match Upload style; fix Upload/…
waleedlatif1 Jun 1, 2026
977d5de
fix(icons): replace Upload with Download on all remaining export/down…
waleedlatif1 Jun 1, 2026
e641dbb
fix(icons): fix remaining Upload→Download on download actions in file…
waleedlatif1 Jun 1, 2026
04e271a
updated block skills, settings pages, modals, buttons -> chips, block…
waleedlatif1 Jun 2, 2026
590250b
updated skill modal
waleedlatif1 Jun 2, 2026
9c4a5e1
Merge branch 'staging' into improvement/platform
icecrasher321 Jun 2, 2026
621d424
improvement(resource-header): refine breadcrumb truncation ux
andresdjasso Jun 2, 2026
8d0e9dc
improvement(resource): add floating overflow text tooltips
andresdjasso Jun 2, 2026
92da21e
wire up credits counter
icecrasher321 Jun 2, 2026
8c165bb
improvement(resource-header): mute path dropdown title
andresdjasso Jun 2, 2026
8da7e34
refactor(resource-header): share floating-tooltip engine, prune dead …
waleedlatif1 Jun 2, 2026
74705a7
refactor(emcn,resource-header): address PR #4844 review feedback
waleedlatif1 Jun 2, 2026
c190d2c
Merge branch 'improvement/platform' of github.com:simstudioai/sim int…
icecrasher321 Jun 2, 2026
f94052c
upgrade table and styling upgrade
emir-karabeg Jun 2, 2026
8a8d77f
Merge branch 'improvement/platform' of github.com:simstudioai/sim int…
icecrasher321 Jun 2, 2026
72fd5e0
Merge branch 'staging' into improvement/platform
icecrasher321 Jun 2, 2026
2555137
fix schema to include integration
icecrasher321 Jun 2, 2026
350c5be
fix(files): align delete icon with tables view (Trash → Trash2)
waleedlatif1 Jun 2, 2026
21ecc58
fix(mothership): preserve blockType for integration contexts in sent …
waleedlatif1 Jun 2, 2026
13f2cc7
fix(mothership): allow 'integration' resource type in chat resources API
waleedlatif1 Jun 2, 2026
79907b1
fix(ui): Add "File" title next to file resource header
TheodoreSpeaks Jun 3, 2026
a0587a7
fix(ui): fix resource header columns being bolded
TheodoreSpeaks Jun 3, 2026
0f9ea0a
fix(resource): keep the floating tooltip from jumping on click
andresdjasso Jun 3, 2026
59197ad
perf(sidebar): eliminate unnecessary re-renders in workspace switcher…
waleedlatif1 Jun 3, 2026
ad6ced8
feat(search): context-aware cmd-k results on the integrations page
waleedlatif1 Jun 3, 2026
9c96fff
refactor(emcn): make the floating tooltip the one canonical Tooltip
andresdjasso Jun 3, 2026
7a30999
style(emcn): put tooltip text on the design scale (text-caption)
andresdjasso Jun 3, 2026
2df6d39
feat(sidebar): add empty task state and inline task creation
waleedlatif1 Jun 3, 2026
b448f77
invite, billing, home
emir-karabeg Jun 3, 2026
7b32a85
improvement(seats): auto purchase seats on invitations into workspace…
icecrasher321 Jun 3, 2026
eaefa56
feat(knowledge): align connector UI with integrations page styling
waleedlatif1 Jun 3, 2026
b06f757
fix(icons): trim Folder SVG viewBox to remove right-side whitespace
waleedlatif1 Jun 3, 2026
3ad3710
fix(user-input): restore draft text synchronously to preserve context…
waleedlatif1 Jun 3, 2026
9c71774
fix(queue): render context chips in queued messages
waleedlatif1 Jun 3, 2026
c2c2738
fix(mothership): remove integrations from add-resource dropdown
waleedlatif1 Jun 3, 2026
f24ea25
fix(mothership): comment out integrations from add-resource dropdown
waleedlatif1 Jun 3, 2026
598692b
chore(db): drop form, templates, template_creators, template_stars ta…
waleedlatif1 Jun 3, 2026
1a509c0
chore(db): add migration metadata for 0224 drop tables
waleedlatif1 Jun 3, 2026
b102d4f
block icons, sidebar, toolbar
emir-karabeg Jun 3, 2026
8f6a048
chore: remove remaining dead code for template-profile feature
waleedlatif1 Jun 3, 2026
e495979
fix(multi-select): preserve anchor on range selection for tasks and f…
waleedlatif1 Jun 3, 2026
b9cc9bc
feat(emcn): add SearchInput component and unify search bars platform-…
waleedlatif1 Jun 3, 2026
254af5c
fix(files,tables): restore new-file editor autofocus and CSV import e…
waleedlatif1 Jun 3, 2026
107a98e
feat(home): score suggested actions by workspace signals
waleedlatif1 Jun 3, 2026
91bfc08
billing, teammates
emir-karabeg Jun 3, 2026
314dcb0
improvement(credentials): credentials invites, secrets tab wiring up …
icecrasher321 Jun 4, 2026
c501c53
refactor(ui): migrate settings & workspace UI to chip design system
waleedlatif1 Jun 4, 2026
3518b99
feat(tables): background import for large CSVs with live progress (#4…
TheodoreSpeaks Jun 4, 2026
52739a3
fix(mothership): restore integrations to useAvailableResources for @ …
waleedlatif1 Jun 4, 2026
c3189a7
refactor(settings): chip design-system consistency pass across all tabs
waleedlatif1 Jun 4, 2026
4076d76
chore(api-key): remove legacy scan+decrypt auth fallback (#4876)
TheodoreSpeaks Jun 4, 2026
f6c1d3c
feat(settings): unify filter dropdowns on ChipSelect (integrations st…
waleedlatif1 Jun 4, 2026
a79b3f4
fix(mentions): require explicit @ for integration mentions; decorate …
waleedlatif1 Jun 4, 2026
b3b86c8
refactor(settings): section the API keys page like secrets
waleedlatif1 Jun 4, 2026
243d2a3
fix(settings): ChipSelect renders above modals + full-width form mode
waleedlatif1 Jun 4, 2026
fe770ee
fix(emcn): ChipSelect uses the emcn flat chevron, not lucide's square…
waleedlatif1 Jun 4, 2026
e5bf7ba
fix(emcn): ChipSelect trigger hugs its content (w-fit)
waleedlatif1 Jun 4, 2026
0dffb7d
fix(emcn): ChipSelect uses a square lucide chevron
waleedlatif1 Jun 4, 2026
c165f54
renamed tasks to chats
emir-karabeg Jun 4, 2026
c620fdc
fix(security): chat attachment XSS, MCP OAuth SSRF guards, Teams clie…
waleedlatif1 Jun 4, 2026
402472e
chore(readme): refresh demo GIFs from docs, lead with Mothership (#4878)
waleedlatif1 Jun 4, 2026
469781f
rename and file change
emir-karabeg Jun 4, 2026
d80f0c6
fix(mcp): enforce tool name validation in deploy modal (#4879)
waleedlatif1 Jun 4, 2026
e761043
chore(skills): mirror model/enrichment/hosted-key/council skills into…
waleedlatif1 Jun 4, 2026
71f6936
fix(polling-tools): pass plan execution timeout to internal polling t…
icecrasher321 Jun 4, 2026
5505076
chore(db): drop legacy copilot_chats.messages JSONB column (#4886)
waleedlatif1 Jun 4, 2026
2ccd9a3
feat(connectors): add 7 knowledge base connectors (Google Forms, Type…
waleedlatif1 Jun 4, 2026
16954e4
feat(integrations): add ClickHouse block and expand Dagster + Tinybir…
waleedlatif1 Jun 4, 2026
80ea0dd
fix(autolayout): relocate notes that overlap blocks after layout (#4888)
waleedlatif1 Jun 4, 2026
7c455ce
improvement(billing): wire up billing, org, teammates tabs + remove d…
icecrasher321 Jun 4, 2026
0b0f84e
chore(db): remove migration 0224 to regenerate on top of staging
icecrasher321 Jun 4, 2026
4b0a4c8
Merge remote-tracking branch 'origin/staging' into improvement/platform
icecrasher321 Jun 4, 2026
0187f81
fix type errors and regen migration?
icecrasher321 Jun 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
68 changes: 65 additions & 3 deletions .agents/skills/add-block/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -627,19 +627,78 @@ export const ServiceV2Block: BlockConfig = {
}
```

## Block Metadata (BlockMeta)

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.

### Structure

```typescript
import type { BlockConfig, BlockMeta } from '@/blocks/types'

// ... block definition above ...

export const {Service}BlockMeta = {
tags: ['messaging', 'automation'], // Same tags as the block's tags field
templates: [ // Optional but strongly encouraged
{
icon: {Service}Icon,
title: '{Service} use-case title',
prompt: 'Build a workflow that ...',
modules: ['agent', 'workflows'], // Modules the template uses
category: 'productivity', // Template category
tags: ['automation'], // Template-level tags
alsoIntegrations: ['slack'], // Other blocks referenced in the prompt (optional)
},
],
} as const satisfies BlockMeta
```

### Rules

- **Import `BlockMeta`** from `@/blocks/types` alongside `BlockConfig`
- **`tags`** must match the `tags` array on the block config exactly
- **Templates are optional** but should be added for any integration that has a recognizable use case — aim for 2–4 templates per block
- **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
- **Template `modules`** lists the Sim modules the template relies on: `'knowledge-base' | 'tables' | 'files' | 'workflows' | 'scheduled' | 'agent'`
- **Template `category`** is one of: `'popular' | 'sales' | 'support' | 'engineering' | 'marketing' | 'productivity' | 'operations'`
- **`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
- Place the export **after** the main `{Service}Block` export, at the very bottom of the file

### Register in the blocksMeta object

After adding `{Service}BlockMeta` to the block file, register it in `apps/sim/blocks/registry.ts`:

```typescript
// Add import (alongside the block import, alphabetically)
import { ServiceBlock, ServiceBlockMeta } from '@/blocks/blocks/service'

// Add to blocksMeta object (alphabetically)
export const blocksMeta = {
// ... existing entries ...
service: ServiceBlockMeta,
}
```

## Registering Blocks

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

```typescript
import { ServiceBlock } from '@/blocks/blocks/service'
import { ServiceBlock, ServiceBlockMeta } from '@/blocks/blocks/service'

export const registry: Record<string, BlockConfig> = {
// ... existing blocks ...
service: ServiceBlock,
}

export const blocksMeta = {
// ... existing entries ...
service: ServiceBlockMeta,
}
```

## Complete Example
Expand Down Expand Up @@ -827,7 +886,10 @@ All tool IDs referenced in `tools.access` and returned by `tools.config.tool` MU
- [ ] Tools.access lists all tool IDs (snake_case)
- [ ] Tools.config.tool returns correct tool ID (snake_case)
- [ ] Outputs match tool outputs
- [ ] Block registered in registry.ts
- [ ] Block registered in `registry.ts` blocks object (alphabetically)
- [ ] `{Service}BlockMeta` exported at bottom of block file with `tags` and `templates`
- [ ] `BlockMeta` imported from `@/blocks/types` alongside `BlockConfig`
- [ ] Block meta registered in `registry.ts` blocksMeta object (alphabetically)
- [ ] If icon missing: asked user to provide SVG
- [ ] If triggers exist: `triggers` config set, trigger subBlocks spread
- [ ] Optional/rarely-used fields set to `mode: 'advanced'`
Expand Down
142 changes: 142 additions & 0 deletions .agents/skills/add-enrichment/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
---
name: add-enrichment
description: Add a code-defined table enrichment (registry entry) under `apps/sim/enrichments/` backed by an ordered provider cascade, ensuring every provider tool it calls has hosted-key support. Use when adding a per-row table enrichment that fills cells via existing Sim tools.
---

# Adding a Table Enrichment

Enrichments are code-defined entries in `apps/sim/enrichments/` that run **directly per table row** (no workflow). Each enrichment declares inputs, outputs, and an ordered list of **providers**; the cascade runner tries providers in order and the first non-empty result fills the cell. Each provider calls one existing Sim tool via `executeTool`, which injects the workspace's BYOK key or a **hosted key** and bills usage automatically.

Because enrichments run on Sim's hosted keys by default, **every provider tool you reference must have hosted-key support** — otherwise it can only run when the workspace brings its own key. This command makes that check a required step.

## Overview

| Step | What | Where |
|------|------|-------|
| 1 | Pick the data-source tool(s) for each output | `tools/{service}/` + `tools/registry.ts` |
| 2 | **Verify each tool has `hosting`; if not, run `/add-hosted-key`** | `tools/{service}/{action}.ts` |
| 3 | Write the enrichment definition | `enrichments/{name}/{name}.ts` + `index.ts` |
| 4 | Register it | `enrichments/registry.ts` |
| 5 | Verify | tsc / biome / manual run |

## Architecture (what you're plugging into)

- **`enrichments/types.ts`** — `EnrichmentConfig { id, name, description, icon, inputs, outputs, providers }` and `EnrichmentProvider { id, label, toolId, buildParams, mapOutput }`. Providers are **plain data** (no `@/tools` import) so the catalog stays client-safe.
- **`enrichments/providers.ts`** — `toolProvider(...)` (typed passthrough) plus shared input helpers: `str(v)`, `normalizeDomain(v)`, `firstNonEmpty(arr)`, `splitName(fullName)`.
- **`enrichments/run.ts`** — the server-only cascade runner. Calls `executeTool(provider.toolId, { ...params, _context: { workspaceId } })`, accumulates hosted-key cost, returns the first non-empty mapped result. **You do not edit this** — it works for any registry entry.
- **`enrichments/registry.ts`** — `ENRICHMENT_REGISTRY` / `ALL_ENRICHMENTS` / `getEnrichment`. Register new entries here.

Outputs automatically become table columns; billing, the catalog/sidebar UI, the column meta-header icon, and per-row execution all work with no extra wiring.

## Step 1: Pick the data-source tool(s)

For each output the enrichment produces, decide which existing tool provides it. Look up the service's API and the tool in `apps/sim/tools/{service}/` (e.g. `hunter_email_finder`, `pdl_person_enrich`, `pdl_company_enrich`). Confirm:

- The tool id is registered in `apps/sim/tools/registry.ts`.
- Its `params` accept what you can derive from table columns (read the tool's `params`).
- Its `outputs` / `transformResponse` actually expose the field you need (read the real output shape — don't assume).

Order providers **cheapest / most-likely-to-hit first**; the cascade stops at the first non-empty result. Apollo / LinkedIn are not hosted-safe (ToS) — don't use them.

## Step 2: Verify hosted-key support — chain to `/add-hosted-key` if missing

**This is the required gate.** For every tool a provider calls, open `apps/sim/tools/{service}/{action}.ts` and check for a `hosting` block:

```typescript
hosting: {
envKeyPrefix: 'SERVICE_API_KEY',
apiKeyParam: 'apiKey',
byokProviderId: 'service',
pricing: { /* ... */ },
rateLimit: { /* ... */ },
}
```

- **If `hosting` is present** — good. Note the `envKeyPrefix`; the deployment needs `{PREFIX}_COUNT` + `{PREFIX}_1..N` env vars set for the hosted key to actually resolve at runtime (ops concern, not code). If those env vars aren't set in the target environment, the provider will only run with a workspace BYOK key.
- **If `hosting` is absent** — the tool can't use a Sim-provided key, so the enrichment would silently produce blank cells on hosted Sim. **Stop and run `/add-hosted-key <service>`** to add hosted-key support to that tool first, then come back. Do this for every provider tool that lacks it.

Why it matters: the cascade runner only bills (and only reads `output.cost.total`) when `executeTool` injected a hosted key, which requires the tool's `hosting` config. No `hosting` → no hosted key → the enrichment depends entirely on per-workspace BYOK.

## Step 3: Write the enrichment definition

Create `apps/sim/enrichments/{name}/{name}.ts` and a barrel `index.ts`. Mirror the existing entries (`work-email`, `phone-number`, `company-domain`, `company-info`).

```typescript
import { SomeIcon } from 'lucide-react'
import { filterUndefined } from '@sim/utils/object'
import { normalizeDomain, splitName, str, toolProvider } from '@/enrichments/providers'
import type { EnrichmentConfig } from '@/enrichments/types'

export const myEnrichment: EnrichmentConfig = {
id: 'my-enrichment',
name: 'My Enrichment',
description: 'One concise sentence describing what it finds.',
icon: SomeIcon,
inputs: [
// Person enrichments take a single canonical `fullName` (Clay-style);
// split it with splitName() for tools that need first/last.
{ id: 'fullName', name: 'Full name', type: 'string', required: true },
{ id: 'companyDomain', name: 'Company domain', type: 'string' },
],
outputs: [{ id: 'value', name: 'value', type: 'string' }],
providers: [
toolProvider({
id: 'provider-a',
label: 'Provider A',
toolId: 'service_action', // must have `hosting` (Step 2)
buildParams: (inputs) => {
// Return null when there aren't enough inputs → cascade skips this provider.
const name = splitName(inputs.fullName)
const domain = normalizeDomain(inputs.companyDomain)
if (!name || !domain) return null
return { domain, first_name: name.firstName, last_name: name.lastName }
},
mapOutput: (output) => {
// Return { [outputId]: value } on a hit, or null to fall through.
const value = str(output.value)
return value ? { value } : null
},
}),
// ...additional fallback providers, in priority order.
],
}
```

```typescript
// apps/sim/enrichments/{name}/index.ts
export { myEnrichment } from './my-enrichment'
```

Rules:
- Keep the file **client-safe**: import only `lucide-react`, `@sim/utils/*`, `@/enrichments/providers`, and the types. **Never import `@/tools`** here — the runner does the tool call.
- `buildParams` returns `null` when inputs are insufficient (provider skipped). `mapOutput` returns `null`/empty for a miss (falls through). Use `filterUndefined` when assembling optional tool params; coerce numbers explicitly (don't pass `''` to number outputs).
- Output `id`s are the keys `mapOutput` returns; output `name`s are the default column names (the user can rename them in the config).

## Step 4: Register it

In `apps/sim/enrichments/registry.ts`, import and add the entry (catalog order is registration order):

```typescript
import { myEnrichment } from '@/enrichments/my-enrichment'

export const ENRICHMENT_REGISTRY: EnrichmentRegistry = {
// ...existing
[myEnrichment.id]: myEnrichment,
}
```

## Step 5: Verify

1. `bunx tsc --noEmit` (from `apps/sim`, `NODE_OPTIONS=--max-old-space-size=8192`) and `bunx biome check` on the changed files.
2. In a table → **+ New column → Enrichments** → pick the new enrichment, map its inputs to columns, name the output column(s), Save. Confirm it appears in the catalog with its icon/description.
3. With hosted keys (or a workspace BYOK key) configured for each provider's service, run a row and confirm the cell fills; the dev-server log shows `Enrichment hit { provider }`. A row whose providers all miss completes blank; a row where every provider errored shows an error cell.

## Checklist

- [ ] Each output mapped to a real tool field (verified against the tool's `params`/`outputs`)
- [ ] **Every provider tool has a `hosting` block — ran `/add-hosted-key` for any that didn't**
- [ ] Providers ordered cheapest / most-likely-first; Apollo/LinkedIn not used
- [ ] Enrichment file is client-safe (no `@/tools` import); uses `toolProvider` + shared helpers
- [ ] `buildParams` returns `null` on insufficient inputs; `mapOutput` returns `null` on a miss
- [ ] Registered in `enrichments/registry.ts`
- [ ] tsc + biome clean; created and ran the column end-to-end
5 changes: 5 additions & 0 deletions .agents/skills/add-enrichment/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
interface:
display_name: "Add Enrichment"
short_description: "Build a table enrichment cascade"
brand_color: "#16A34A"
default_prompt: "Use $add-enrichment to add a code-defined Sim table enrichment backed by a provider cascade."
Loading
Loading