Skip to content

Commit 574eb19

Browse files
Merge origin/staging into feat/org-project-routes
The base branch's pre-merge copy of the dashboards work (#8305) resolves to staging's merged version. The classic workspace Sidebar takes staging's file as is; the project Build sidebar keeps its shared services hook. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lrd1NLD9qx2KBLVnw32c3E
2 parents 9c398c1 + 12a321a commit 574eb19

5,488 files changed

Lines changed: 957252 additions & 118270 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-preview/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ To pull an already-GA block from discovery surfaces on hosted (incident, depreca
5353
- **Clone-not-remove:** gated blocks stay in `getAllBlocks()` output as clones with `hideFromToolbar: true` — `.find`-by-type consumers rely on this. Never filter them out.
5454
- **Keys are registry block types.** Never `custom_block_*` (parse drops them — custom blocks have their own enabled/disabled lifecycle).
5555
- **The shared hidden-predicate is `isHiddenUnder`** (`apps/sim/blocks/visibility/context.ts`). Never restate the preview/disabled rule inline at a new consumer.
56-
- **Process-global caches stay ungated.** `getStaticComponentFiles` (VFS) and `getExposedIntegrationTools` build the ungated universe; per-viewer filtering happens at stamp/consumer time. Never move gating into a shared builder.
56+
- **Process-global caches stay ungated.** Shared builders such as `getExposedIntegrationTools` (`apps/sim/lib/integrations/tool-catalog.ts`) build the ungated universe; per-viewer filtering happens at consumer time via `isHiddenUnder`. Never move gating into a shared builder.
5757
- Gating is **surface hiding, not secrecy** — the full config ships in the client JS bundle. Anything truly secret cannot be a registered block.
5858

5959
## Tests

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

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export const {ServiceName}Block: BlockConfig = {
3535
docsLink: 'https://docs.sim.ai/integrations/{service}',
3636
category: 'tools', // 'tools' | 'blocks' | 'triggers'
3737
integrationType: IntegrationType.X, // Primary category (see IntegrationType enum)
38-
tags: ['oauth', 'api'], // Cross-cutting tags (see IntegrationTag type)
3938
bgColor: '#HEXCOLOR', // Brand color
4039
icon: {ServiceName}Icon,
4140

@@ -63,7 +62,7 @@ export const {ServiceName}Block: BlockConfig = {
6362
},
6463

6564
inputs: {
66-
// Optional: define expected inputs from other blocks
65+
// Required: the params the block accepts, keyed by tool param / canonical id
6766
},
6867

6968
outputs: {
@@ -74,7 +73,7 @@ export const {ServiceName}Block: BlockConfig = {
7473

7574
## SubBlock Types Reference
7675

77-
**Critical:** Every subblock `id` must be unique within the block. Duplicate IDs cause conflicts even with different conditions.
76+
**Critical:** Give every subblock a unique `id`: duplicates collide silently (the last definition wins). `blocks.test.ts` fails a duplicate within one condition unless the copies are a basic/advanced mode-swap pair, one basic plus trigger-mode copies, or all carry `canonicalParamId`. The only sanctioned cross-condition reuse is the hosted-key `apiKey` pair (`add-hosted-key` skill), where both fields deliberately share one value.
7877

7978
### Text Inputs
8079
```typescript
@@ -129,6 +128,7 @@ export const {ServiceName}Block: BlockConfig = {
129128
id: 'credential',
130129
title: 'Account',
131130
type: 'oauth-input',
131+
canonicalParamId: 'oauthCredential',
132132
serviceId: '{service}', // Must match OAuth provider service key
133133
requiredScopes: getScopesForService('{service}'), // Import from @/lib/oauth/utils
134134
placeholder: 'Select account',
@@ -177,7 +177,7 @@ When adding or changing an OAuth integration block:
177177
`packages/sim-setup/src/capability-config.ts`. The CLI catalog is exhaustively typed and checked
178178
against the runtime field list; do not infer secrecy from the field name.
179179
4. If the canonical OAuth service declares `serviceAccountProviderId`, run
180-
`bun run deployment-config:generate`; this regenerates the provider-ID facts in
180+
`bun run generate:deployment-config`; this regenerates the provider-ID facts in
181181
`packages/deployment-config/src/service-account-providers.generated.ts`. Never hand-edit that
182182
generated map. Add `deploymentRequirement` policy in
183183
`packages/deployment-config/src/service-account-metadata.ts` only when the service-account path
@@ -310,7 +310,7 @@ When several fields are mutually exclusive alternatives, mark them all `required
310310
other paths ever get a chance to supply the value.
311311

312312
**Constraints (block-wide):**
313-
- `canonicalParamId` must not equal any subblock `id` in the block.
313+
- `canonicalParamId` may equal only the `id` of a member of its own group, as `channel` does in the canonicalParamId Pattern below; it must never equal any other subblock's `id`. (`blocks.test.ts` enforces the case of a subblock with no `canonicalParamId`.)
314314
- One canonical id links exactly one basic/advanced pair for one logical parameter. Groups are keyed by canonical id across every subblock and hold one `basicId`, so two operations that each need a pair need two canonical ids.
315315
- All members of a group share the same `required` status.
316316

@@ -370,8 +370,6 @@ Declare the **canonical** id with `type: 'json'` — the subblock ids never reac
370370
```typescript
371371
inputs: {
372372
file: { type: 'json', description: 'File to upload (UserFile or reference)' },
373-
// Legacy field for backwards compatibility
374-
fileContent: { type: 'string', description: 'Legacy: base64 encoded content' },
375373
}
376374
```
377375

@@ -500,6 +498,7 @@ Controls which UI view shows the field.
500498
- `'advanced'` - Only in advanced view
501499
- `'both'` - Both views (default if not specified)
502500
- `'trigger'` - Only in trigger configuration
501+
- `'trigger-advanced'` - The advanced side of a trigger field (a canonical pair member, or a standalone field under the block-level advanced toggle)
503502

504503
### canonicalParamId Pattern
505504

@@ -563,6 +562,11 @@ Use `wandConfig` on fields that are hard to fill by hand — timestamps (`genera
563562

564563
## Tools Configuration
565564

565+
**Write operation ids and tool ids as string literals** in the `operation` dropdown `options` and
566+
`tools.access`, never through constants (`id: SEARCH`, `access: [SEARCH]`). `scripts/generate-docs.ts`
567+
reads them from source with regexes, so a constant parses as empty: the docs page loses its whole
568+
Actions section and the integration catalog ships blank operation descriptions, with no check failing.
569+
566570
**Preferred:** Use tool names directly as dropdown option IDs to avoid switch cases:
567571
```typescript
568572
// Dropdown options use tool IDs directly
@@ -611,12 +615,12 @@ tools: {
611615

612616
## Outputs Definition
613617

614-
**IMPORTANT:** Block outputs have a simpler schema than tool outputs. Block outputs do NOT support:
618+
Block outputs have a simpler schema than tool outputs. They do not support:
615619
- `optional: true` - This is only for tool outputs
616620
- `items` property - This is only for tool outputs with array types
617621

618622
Block outputs only support:
619-
- `type` - The data type ('string', 'number', 'boolean', 'json', 'array')
623+
- `type` - The data type ('string', 'number', 'boolean', 'json', 'array', 'file', 'file[]', 'any')
620624
- `description` - Human readable description
621625
- `condition` - Optional visibility condition
622626
- `hiddenFromDisplay` - Optional flag to hide from the output display
@@ -679,7 +683,7 @@ export const ServiceV2Block: BlockConfig = {
679683
access: ServiceBlock.tools?.access?.map(id => `${id}_v2`) || [],
680684
config: {
681685
tool: createVersionedToolSelector({
682-
baseToolSelector: (params) => (ServiceBlock.tools?.config as any)?.tool(params),
686+
baseToolSelector: (params) => ServiceBlock.tools.config?.tool(params) ?? 'service_default',
683687
suffix: '_v2',
684688
fallbackToolId: 'service_default_v2',
685689
}),
@@ -697,7 +701,7 @@ export const ServiceV2Block: BlockConfig = {
697701
Register the block in `apps/sim/blocks/registry-maps.ts` — add the import and an entry to each map alphabetically:
698702

699703
```typescript
700-
import { ServiceBlock, ServiceBlockMeta } from '@/blocks/blocks/service'
704+
import { ServiceBlock, ServiceBlockMeta } from '@/blocks/blocks/{service}'
701705

702706
export const BLOCK_REGISTRY: Record<string, BlockConfig> = {
703707
// ... existing blocks ...
@@ -725,12 +729,24 @@ export const ServiceBlock: BlockConfig = {
725729
longDescription: 'Full description for documentation...',
726730
docsLink: 'https://docs.sim.ai/integrations/service',
727731
category: 'tools',
728-
integrationType: IntegrationType.DeveloperTools,
729-
tags: ['oauth', 'api'],
732+
integrationType: IntegrationType.DevOps,
730733
bgColor: '#FF6B6B',
731734
icon: ServiceIcon,
732735
authMode: AuthMode.OAuth,
733736

737+
// Sentence rules: apps/sim/blocks/AGENTS.md → "Canvas sentences"
738+
canvasPresentation: {
739+
defaultTitle: 'Create Resource',
740+
sentences: {
741+
byOperation: {
742+
create: [{ text: 'Create resource', field: 'name', core: true }],
743+
read: [{ text: 'Read resource', field: 'resourceId', core: true }],
744+
update: [{ text: 'Update resource', field: 'resourceId', core: true }],
745+
delete: [{ text: 'Delete resource', field: 'resourceId', core: true }],
746+
},
747+
},
748+
},
749+
734750
subBlocks: [
735751
{
736752
id: 'operation',
@@ -748,6 +764,7 @@ export const ServiceBlock: BlockConfig = {
748764
id: 'credential',
749765
title: 'Service Account',
750766
type: 'oauth-input',
767+
canonicalParamId: 'oauthCredential',
751768
serviceId: 'service',
752769
requiredScopes: getScopesForService('service'),
753770
placeholder: 'Select account',
@@ -778,6 +795,13 @@ export const ServiceBlock: BlockConfig = {
778795
},
779796
},
780797

798+
inputs: {
799+
operation: { type: 'string', description: 'Operation to perform' },
800+
oauthCredential: { type: 'string', description: 'Service access token' },
801+
resourceId: { type: 'string', description: 'Resource ID' },
802+
name: { type: 'string', description: 'Resource name' },
803+
},
804+
781805
outputs: {
782806
id: { type: 'string', description: 'Resource ID' },
783807
name: { type: 'string', description: 'Resource name' },
@@ -935,32 +959,19 @@ Verify it with `bun run check:block-successors`.
935959
Adding a block on its own needs no **tool metadata** regeneration — a block references existing
936960
tool IDs through `tools.access` and does not change any tool's shape.
937961

938-
But if the same change also adds, edits **or removes** a tool, run `bun run tool-metadata:generate` and commit the result, or CI fails on stale artifacts. That matters here because a block's `outputs` are authored to match its tools' outputs, and the UI reads those from the generated metadata, not the executable registry — an unregenerated tool change makes the block's outputs disagree with what the panel renders. See `.agents/skills/tool-registry-boundary/SKILL.md`.
939-
940-
A visible integration block does require the generated integration catalog and docs to be refreshed.
941-
After adding or changing one, run:
942-
943-
```bash
944-
bun run scripts/generate-docs.ts
945-
bun run deployment-config:generate
946-
bun run integration-catalog:check
947-
bun run deployment-config:check
948-
bun run docs:check
949-
```
962+
But if the same change also adds, edits **or removes** a tool, run `bun run generate:tool-metadata` and commit the result, or CI fails on stale artifacts. That matters here because a block's `outputs` are authored to match its tools' outputs, and the UI reads those from the generated metadata, not the executable registry — an unregenerated tool change makes the block's outputs disagree with what the panel renders. See `.agents/skills/tool-registry-boundary/SKILL.md`.
950963

951-
The catalog check independently derives deployment metadata from the executable block registry and
952-
compares it with the committed `packages/deployment-config/src/integrations.json`. The deployment
953-
config check verifies the generated service-account facts against the canonical OAuth registry and
954-
catalog. `docs:check` re-renders every generated docs artifact in memory and fails on any committed
955-
file that differs — it runs in CI via `check:audits`, so commit the full generator output. If the
956-
generator also trues up pages an earlier PR left stale, commit that catch-up too; reverting it as
957-
"unrelated drift" makes `docs:check` fail. Review the generated diff and keep only intentional
958-
changes.
964+
A visible integration block does require the generated integration catalog and docs to be refreshed:
965+
`bun run generate:tool-metadata` (only when a tool changed), `bun run scripts/generate-docs.ts`,
966+
`bun run generate:deployment-config`, then `bun run check:audits`. Also run
967+
`bun run apps/sim/scripts/check-block-registry.ts origin/staging` (CI runs it outside `check:audits`). Commit the
968+
full generator output. For what each check verifies, see the `validate-integration` skill →
969+
Regenerate Derived Artifacts.
959970

960971
## Checklist Before Finishing
961972

962973
- [ ] `integrationType` is set to the correct `IntegrationType` enum value
963-
- [ ] `tags` array includes all applicable `IntegrationTag` values
974+
- [ ] `{Service}BlockMeta.tags` lists every applicable `IntegrationTag` (tags live on the meta, not the block)
964975
- [ ] All subBlocks have `id`, `title` (except switch), and `type`
965976
- [ ] Conditions use correct syntax (field, value, not, and)
966977
- [ ] DependsOn set for fields that need other values
@@ -975,10 +986,10 @@ changes.
975986
- [ ] Outputs match tool outputs
976987
- [ ] Block + meta registered in registry-maps.ts (`BLOCK_REGISTRY` / `BLOCK_META_REGISTRY`)
977988
- [ ] If `sunset.replacedBy` changed: regenerated and committed the block successor map; `bun run check:block-successors` passes
978-
- [ ] If any tool was added, changed or removed alongside the block: ran `bun run tool-metadata:generate` and committed the artifacts
989+
- [ ] If any tool was added, changed or removed alongside the block: ran `bun run generate:tool-metadata` and committed the artifacts
979990
- [ ] Ran `bun run scripts/generate-docs.ts`, reviewed the generated diff, and committed the integration catalog changes
980-
- [ ] `bun run integration-catalog:check` passes
981-
- [ ] `bun run docs:check` passes (CI gate — fails on any stale generated docs page)
991+
- [ ] `bun run check:integration-catalog` passes
992+
- [ ] `bun run check:docs` passes (CI gate — fails on any stale generated docs page)
982993
- [ ] If icon missing: asked user to provide SVG
983994
- [ ] If triggers exist: `triggers` config set, trigger subBlocks spread
984995
- [ ] Optional/rarely-used fields set to `mode: 'advanced'`
@@ -996,7 +1007,7 @@ Validate the block against every tool in `tools.access`:
9961007
2. **For each tool, verify the block has correct:**
9971008
- SubBlock inputs that cover all required tool params (with correct `condition` to show for that operation)
9981009
- SubBlock input types that match the tool param types (e.g., dropdown for enums, short-input for strings)
999-
- `tools.config.params` correctly maps subBlock IDs to tool param names (if they differ)
1010+
- Each subBlock (or its `canonicalParamId`) is named exactly after the tool param it fills. A required `user-only` param that is only renamed in `tools.config.params` fails `bun run apps/sim/scripts/check-block-registry.ts origin/staging`; remap only optional or `user-or-llm` params
10001011
- Type coercions in `tools.config.params` for any params that need conversion (Number(), Boolean(), JSON.parse())
10011012
3. **Verify block outputs** cover the key fields returned by all tools
10021013
4. **Verify conditions** — each subBlock should only show for the operations that actually use it

0 commit comments

Comments
 (0)