Skip to content

Commit be578e2

Browse files
authored
v0.5.56: batch operations, access control and permission groups, billing fixes
2 parents f415e5e + baa54b4 commit be578e2

File tree

565 files changed

+40376
-12509
lines changed

Some content is hidden

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

565 files changed

+40376
-12509
lines changed

.cursor/rules/sim-testing.mdc

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,57 @@
11
---
2-
description: Testing patterns with Vitest
2+
description: Testing patterns with Vitest and @sim/testing
33
globs: ["apps/sim/**/*.test.ts", "apps/sim/**/*.test.tsx"]
44
---
55

66
# Testing Patterns
77

8-
Use Vitest. Test files live next to source: `feature.ts` → `feature.test.ts`
8+
Use Vitest. Test files: `feature.ts` → `feature.test.ts`
99

1010
## Structure
1111

1212
```typescript
1313
/**
14-
* Tests for [feature name]
15-
*
1614
* @vitest-environment node
1715
*/
16+
import { databaseMock, loggerMock } from '@sim/testing'
17+
import { describe, expect, it, vi } from 'vitest'
1818

19-
// 1. Mocks BEFORE imports
20-
vi.mock('@sim/db', () => ({ db: { select: vi.fn() } }))
19+
vi.mock('@sim/db', () => databaseMock)
2120
vi.mock('@sim/logger', () => loggerMock)
2221

23-
// 2. Imports AFTER mocks
24-
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
25-
import { createSession, loggerMock } from '@sim/testing'
2622
import { myFunction } from '@/lib/feature'
2723

2824
describe('myFunction', () => {
2925
beforeEach(() => vi.clearAllMocks())
30-
31-
it('should do something', () => {
32-
expect(myFunction()).toBe(expected)
33-
})
34-
35-
it.concurrent('runs in parallel', () => { ... })
26+
it.concurrent('isolated tests run in parallel', () => { ... })
3627
})
3728
```
3829

3930
## @sim/testing Package
4031

41-
```typescript
42-
// Factories - create test data
43-
import { createBlock, createWorkflow, createSession } from '@sim/testing'
32+
Always prefer over local mocks.
4433

45-
// Mocks - pre-configured mocks
46-
import { loggerMock, databaseMock, fetchMock } from '@sim/testing'
47-
48-
// Builders - fluent API for complex objects
49-
import { ExecutionBuilder, WorkflowBuilder } from '@sim/testing'
50-
```
34+
| Category | Utilities |
35+
|----------|-----------|
36+
| **Mocks** | `loggerMock`, `databaseMock`, `setupGlobalFetchMock()` |
37+
| **Factories** | `createSession()`, `createWorkflowRecord()`, `createBlock()`, `createExecutorContext()` |
38+
| **Builders** | `WorkflowBuilder`, `ExecutionContextBuilder` |
39+
| **Assertions** | `expectWorkflowAccessGranted()`, `expectBlockExecuted()` |
5140

5241
## Rules
5342

5443
1. `@vitest-environment node` directive at file top
55-
2. **Mocks before imports** - `vi.mock()` calls must come first
56-
3. Use `@sim/testing` factories over manual test data
57-
4. `it.concurrent` for independent tests (faster)
44+
2. `vi.mock()` calls before importing mocked modules
45+
3. `@sim/testing` utilities over local mocks
46+
4. `it.concurrent` for isolated tests (no shared mutable state)
5847
5. `beforeEach(() => vi.clearAllMocks())` to reset state
59-
6. Group related tests with nested `describe` blocks
60-
7. Test file naming: `*.test.ts` (not `*.spec.ts`)
48+
49+
## Hoisted Mocks
50+
51+
For mutable mock references:
52+
53+
```typescript
54+
const mockFn = vi.hoisted(() => vi.fn())
55+
vi.mock('@/lib/module', () => ({ myFunction: mockFn }))
56+
mockFn.mockResolvedValue({ data: 'test' })
57+
```

CLAUDE.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,21 +173,21 @@ Use Vitest. Test files: `feature.ts` → `feature.test.ts`
173173
/**
174174
* @vitest-environment node
175175
*/
176+
import { databaseMock, loggerMock } from '@sim/testing'
177+
import { describe, expect, it, vi } from 'vitest'
176178

177-
// Mocks BEFORE imports
178-
vi.mock('@sim/db', () => ({ db: { select: vi.fn() } }))
179+
vi.mock('@sim/db', () => databaseMock)
180+
vi.mock('@sim/logger', () => loggerMock)
179181

180-
// Imports AFTER mocks
181-
import { describe, expect, it, vi } from 'vitest'
182-
import { createSession, loggerMock } from '@sim/testing'
182+
import { myFunction } from '@/lib/feature'
183183

184184
describe('feature', () => {
185185
beforeEach(() => vi.clearAllMocks())
186186
it.concurrent('runs in parallel', () => { ... })
187187
})
188188
```
189189

190-
Use `@sim/testing` factories over manual test data.
190+
Use `@sim/testing` mocks/factories over local test data. See `.cursor/rules/sim-testing.mdc` for details.
191191

192192
## Utils Rules
193193

apps/docs/components/icons.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4575,3 +4575,22 @@ export function FirefliesIcon(props: SVGProps<SVGSVGElement>) {
45754575
</svg>
45764576
)
45774577
}
4578+
4579+
export function BedrockIcon(props: SVGProps<SVGSVGElement>) {
4580+
return (
4581+
<svg {...props} viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'>
4582+
<defs>
4583+
<linearGradient id='bedrock_gradient' x1='80%' x2='20%' y1='20%' y2='80%'>
4584+
<stop offset='0%' stopColor='#6350FB' />
4585+
<stop offset='50%' stopColor='#3D8FFF' />
4586+
<stop offset='100%' stopColor='#9AD8F8' />
4587+
</linearGradient>
4588+
</defs>
4589+
<path
4590+
d='M13.05 15.513h3.08c.214 0 .389.177.389.394v1.82a1.704 1.704 0 011.296 1.661c0 .943-.755 1.708-1.685 1.708-.931 0-1.686-.765-1.686-1.708 0-.807.554-1.484 1.297-1.662v-1.425h-2.69v4.663a.395.395 0 01-.188.338l-2.69 1.641a.385.385 0 01-.405-.002l-4.926-3.086a.395.395 0 01-.185-.336V16.3L2.196 14.87A.395.395 0 012 14.555L2 14.528V9.406c0-.14.073-.27.192-.34l2.465-1.462V4.448c0-.129.062-.249.165-.322l.021-.014L9.77 1.058a.385.385 0 01.407 0l2.69 1.675a.395.395 0 01.185.336V7.6h3.856V5.683a1.704 1.704 0 01-1.296-1.662c0-.943.755-1.708 1.685-1.708.931 0 1.685.765 1.685 1.708 0 .807-.553 1.484-1.296 1.662v2.311a.391.391 0 01-.389.394h-4.245v1.806h6.624a1.69 1.69 0 011.64-1.313c.93 0 1.685.764 1.685 1.707 0 .943-.754 1.708-1.685 1.708a1.69 1.69 0 01-1.64-1.314H13.05v1.937h4.953l.915 1.18a1.66 1.66 0 01.84-.227c.931 0 1.685.764 1.685 1.707 0 .943-.754 1.708-1.685 1.708-.93 0-1.685-.765-1.685-1.708 0-.346.102-.668.276-.937l-.724-.935H13.05v1.806zM9.973 1.856L7.93 3.122V6.09h-.778V3.604L5.435 4.669v2.945l2.11 1.36L9.712 7.61V5.334h.778V7.83c0 .136-.07.263-.184.335L7.963 9.638v2.081l1.422 1.009-.446.646-1.406-.998-1.53 1.005-.423-.66 1.605-1.055v-1.99L5.038 8.29l-2.26 1.34v1.676l1.972-1.189.398.677-2.37 1.429V14.3l2.166 1.258 2.27-1.368.397.677-2.176 1.311V19.3l1.876 1.175 2.365-1.426.398.678-2.017 1.216 1.918 1.201 2.298-1.403v-5.78l-4.758 2.893-.4-.675 5.158-3.136V3.289L9.972 1.856zM16.13 18.47a.913.913 0 00-.908.92c0 .507.406.918.908.918a.913.913 0 00.907-.919.913.913 0 00-.907-.92zm3.63-3.81a.913.913 0 00-.908.92c0 .508.406.92.907.92a.913.913 0 00.908-.92.913.913 0 00-.908-.92zm1.555-4.99a.913.913 0 00-.908.92c0 .507.407.918.908.918a.913.913 0 00.907-.919.913.913 0 00-.907-.92zM17.296 3.1a.913.913 0 00-.907.92c0 .508.406.92.907.92a.913.913 0 00.908-.92.913.913 0 00-.908-.92z'
4591+
fill='url(#bedrock_gradient)'
4592+
fillRule='nonzero'
4593+
/>
4594+
</svg>
4595+
)
4596+
}

apps/docs/content/docs/de/execution/costs.mdx

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -49,40 +49,40 @@ Die Modellaufschlüsselung zeigt:
4949

5050
<Tabs items={['Hosted Models', 'Bring Your Own API Key']}>
5151
<Tab>
52-
**Gehostete Modelle** - Sim stellt API-Schlüssel mit einem 2-fachen Preismultiplikator bereit:
52+
**Hosted Models** - Sim bietet API-Schlüssel mit einem 1,4-fachen Preismultiplikator für Agent-Blöcke:
5353

5454
**OpenAI**
55-
| Modell | Basispreis (Eingabe/Ausgabe) | Gehosteter Preis (Eingabe/Ausgabe) |
55+
| Modell | Basispreis (Eingabe/Ausgabe) | Hosted-Preis (Eingabe/Ausgabe) |
5656
|-------|---------------------------|----------------------------|
57-
| GPT-5.1 | 1,25 $ / 10,00 $ | 2,50 $ / 20,00 $ |
58-
| GPT-5 | 1,25 $ / 10,00 $ | 2,50 $ / 20,00 $ |
59-
| GPT-5 Mini | 0,25 $ / 2,00 $ | 0,50 $ / 4,00 $ |
60-
| GPT-5 Nano | 0,05 $ / 0,40 $ | 0,10 $ / 0,80 $ |
61-
| GPT-4o | 2,50 $ / 10,00 $ | 5,00 $ / 20,00 $ |
62-
| GPT-4.1 | 2,00 $ / 8,00 $ | 4,00 $ / 16,00 $ |
63-
| GPT-4.1 Mini | 0,40 $ / 1,60 $ | 0,80 $ / 3,20 $ |
64-
| GPT-4.1 Nano | 0,10 $ / 0,40 $ | 0,20 $ / 0,80 $ |
65-
| o1 | 15,00 $ / 60,00 $ | 30,00 $ / 120,00 $ |
66-
| o3 | 2,00 $ / 8,00 $ | 4,00 $ / 16,00 $ |
67-
| o4 Mini | 1,10 $ / 4,40 $ | 2,20 $ / 8,80 $ |
57+
| GPT-5.1 | $1.25 / $10.00 | $1.75 / $14.00 |
58+
| GPT-5 | $1.25 / $10.00 | $1.75 / $14.00 |
59+
| GPT-5 Mini | $0.25 / $2.00 | $0.35 / $2.80 |
60+
| GPT-5 Nano | $0.05 / $0.40 | $0.07 / $0.56 |
61+
| GPT-4o | $2.50 / $10.00 | $3.50 / $14.00 |
62+
| GPT-4.1 | $2.00 / $8.00 | $2.80 / $11.20 |
63+
| GPT-4.1 Mini | $0.40 / $1.60 | $0.56 / $2.24 |
64+
| GPT-4.1 Nano | $0.10 / $0.40 | $0.14 / $0.56 |
65+
| o1 | $15.00 / $60.00 | $21.00 / $84.00 |
66+
| o3 | $2.00 / $8.00 | $2.80 / $11.20 |
67+
| o4 Mini | $1.10 / $4.40 | $1.54 / $6.16 |
6868

6969
**Anthropic**
70-
| Modell | Basispreis (Eingabe/Ausgabe) | Gehosteter Preis (Eingabe/Ausgabe) |
70+
| Modell | Basispreis (Eingabe/Ausgabe) | Hosted-Preis (Eingabe/Ausgabe) |
7171
|-------|---------------------------|----------------------------|
72-
| Claude Opus 4.5 | 5,00 $ / 25,00 $ | 10,00 $ / 50,00 $ |
73-
| Claude Opus 4.1 | 15,00 $ / 75,00 $ | 30,00 $ / 150,00 $ |
74-
| Claude Sonnet 4.5 | 3,00 $ / 15,00 $ | 6,00 $ / 30,00 $ |
75-
| Claude Sonnet 4.0 | 3,00 $ / 15,00 $ | 6,00 $ / 30,00 $ |
76-
| Claude Haiku 4.5 | 1,00 $ / 5,00 $ | 2,00 $ / 10,00 $ |
72+
| Claude Opus 4.5 | $5.00 / $25.00 | $7.00 / $35.00 |
73+
| Claude Opus 4.1 | $15.00 / $75.00 | $21.00 / $105.00 |
74+
| Claude Sonnet 4.5 | $3.00 / $15.00 | $4.20 / $21.00 |
75+
| Claude Sonnet 4.0 | $3.00 / $15.00 | $4.20 / $21.00 |
76+
| Claude Haiku 4.5 | $1.00 / $5.00 | $1.40 / $7.00 |
7777

7878
**Google**
79-
| Modell | Basispreis (Eingabe/Ausgabe) | Gehosteter Preis (Eingabe/Ausgabe) |
79+
| Modell | Basispreis (Eingabe/Ausgabe) | Hosted-Preis (Eingabe/Ausgabe) |
8080
|-------|---------------------------|----------------------------|
81-
| Gemini 3 Pro Preview | 2,00 $ / 12,00 $ | 4,00 $ / 24,00 $ |
82-
| Gemini 2.5 Pro | 1,25 $ / 10,00 $ | 2,50 $ / 20,00 $ |
83-
| Gemini 2.5 Flash | 0,30 $ / 2,50 $ | 0,60 $ / 5,00 $ |
81+
| Gemini 3 Pro Preview | $2.00 / $12.00 | $2.80 / $16.80 |
82+
| Gemini 2.5 Pro | $1.25 / $10.00 | $1.75 / $14.00 |
83+
| Gemini 2.5 Flash | $0.30 / $2.50 | $0.42 / $3.50 |
8484

85-
*Der 2x-Multiplikator deckt Infrastruktur- und API-Verwaltungskosten ab.*
85+
*Der 1,4-fache Multiplikator deckt Infrastruktur- und API-Verwaltungskosten ab.*
8686
</Tab>
8787

8888
<Tab>

apps/docs/content/docs/en/blocks/router.mdx

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import { Callout } from 'fumadocs-ui/components/callout'
66
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
77
import { Image } from '@/components/ui/image'
88

9-
The Router block uses AI to intelligently route workflows based on content analysis. Unlike Condition blocks that use simple rules, Routers understand context and intent.
9+
The Router block uses AI to intelligently route workflows based on content analysis. Unlike Condition blocks that use simple rules, Routers understand context and intent. Each route you define creates a separate output port, allowing you to connect different paths to different downstream blocks.
1010

1111
<div className="flex justify-center">
1212
<Image
1313
src="/static/blocks/router.png"
14-
alt="Router Block with Multiple Paths"
14+
alt="Router Block with Multiple Route Ports"
1515
width={500}
1616
height={400}
1717
className="my-6"
@@ -32,21 +32,23 @@ The Router block uses AI to intelligently route workflows based on content analy
3232

3333
## Configuration Options
3434

35-
### Content/Prompt
35+
### Context
3636

37-
The content or prompt that the Router will analyze to make routing decisions. This can be:
37+
The context that the Router will analyze to make routing decisions. This is the input data that gets evaluated against your route descriptions. It can be:
3838

3939
- A direct user query or input
4040
- Output from a previous block
4141
- A system-generated message
42+
- Any text content that needs intelligent routing
4243

43-
### Target Blocks
44+
### Routes
4445

45-
The possible destination blocks that the Router can select from. The Router will automatically detect connected blocks, but you can also:
46+
Define the possible paths that the Router can take. Each route consists of:
4647

47-
- Customize the descriptions of target blocks to improve routing accuracy
48-
- Specify routing criteria for each target block
49-
- Exclude certain blocks from being considered as routing targets
48+
- **Route Title**: A name for the route (e.g., "Sales", "Support", "Technical")
49+
- **Route Description**: A clear description of when this route should be selected (e.g., "Route here when the query is about pricing, purchasing, or sales inquiries")
50+
51+
Each route you add creates a **separate output port** on the Router block. Connect each port to the appropriate downstream block for that route.
5052

5153
### Model Selection
5254

@@ -66,35 +68,46 @@ Your API key for the selected LLM provider. This is securely stored and used for
6668

6769
## Outputs
6870

69-
- **`<router.prompt>`**: Summary of the routing prompt
70-
- **`<router.selected_path>`**: Chosen destination block
71+
- **`<router.context>`**: The context that was analyzed
72+
- **`<router.selectedRoute>`**: The ID of the selected route
73+
- **`<router.selected_path>`**: Details of the chosen destination block
7174
- **`<router.tokens>`**: Token usage statistics
7275
- **`<router.cost>`**: Estimated routing cost
7376
- **`<router.model>`**: Model used for decision-making
7477

7578
## Example Use Cases
7679

7780
**Customer Support Triage** - Route tickets to specialized departments
81+
7882
```
79-
Input (Ticket) → Router → Agent (Engineering) or Agent (Finance)
83+
Input (Ticket) → Router
84+
├── [Sales Route] → Agent (Sales Team)
85+
├── [Technical Route] → Agent (Engineering)
86+
└── [Billing Route] → Agent (Finance)
8087
```
8188

8289
**Content Classification** - Classify and route user-generated content
90+
8391
```
84-
Input (Feedback) → Router → Workflow (Product) or Workflow (Technical)
92+
Input (Feedback) → Router
93+
├── [Product Feedback] → Workflow (Product Team)
94+
└── [Bug Report] → Workflow (Technical Team)
8595
```
8696

8797
**Lead Qualification** - Route leads based on qualification criteria
98+
8899
```
89-
Input (Lead) → Router → Agent (Enterprise Sales) or Workflow (Self-serve)
100+
Input (Lead) → Router
101+
├── [Enterprise] → Agent (Enterprise Sales)
102+
└── [Self-serve] → Workflow (Automated Onboarding)
90103
```
91104

92-
93105
## Best Practices
94106

95-
- **Provide clear target descriptions**: Help the Router understand when to select each destination with specific, detailed descriptions
96-
- **Use specific routing criteria**: Define clear conditions and examples for each path to improve accuracy
97-
- **Implement fallback paths**: Connect a default destination for when no specific path is appropriate
98-
- **Test with diverse inputs**: Ensure the Router handles various input types, edge cases, and unexpected content
99-
- **Monitor routing performance**: Review routing decisions regularly and refine criteria based on actual usage patterns
100-
- **Choose appropriate models**: Use models with strong reasoning capabilities for complex routing decisions
107+
- **Write clear route descriptions**: Each route description should clearly explain when that route should be selected. Be specific about the criteria.
108+
- **Make routes mutually exclusive**: When possible, ensure route descriptions don't overlap to prevent ambiguous routing decisions.
109+
- **Include an error/fallback route**: Add a catch-all route for unexpected inputs that don't match other routes.
110+
- **Use descriptive route titles**: Route titles appear in the workflow canvas, so make them meaningful for readability.
111+
- **Test with diverse inputs**: Ensure the Router handles various input types, edge cases, and unexpected content.
112+
- **Monitor routing performance**: Review routing decisions regularly and refine route descriptions based on actual usage patterns.
113+
- **Choose appropriate models**: Use models with strong reasoning capabilities for complex routing decisions.

apps/docs/content/docs/en/enterprise/index.mdx

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Enterprise
3-
description: Enterprise features for organizations with advanced security and compliance requirements
3+
description: Enterprise features for business organizations
44
---
55

66
import { Callout } from 'fumadocs-ui/components/callout'
@@ -9,6 +9,28 @@ Sim Studio Enterprise provides advanced features for organizations with enhanced
99

1010
---
1111

12+
## Access Control
13+
14+
Define permission groups to control what features and integrations team members can use.
15+
16+
### Features
17+
18+
- **Allowed Model Providers** - Restrict which AI providers users can access (OpenAI, Anthropic, Google, etc.)
19+
- **Allowed Blocks** - Control which workflow blocks are available
20+
- **Platform Settings** - Hide Knowledge Base, disable MCP tools, or disable custom tools
21+
22+
### Setup
23+
24+
1. Navigate to **Settings****Access Control** in your workspace
25+
2. Create a permission group with your desired restrictions
26+
3. Add team members to the permission group
27+
28+
<Callout type="info">
29+
Users not assigned to any permission group have full access. Permission restrictions are enforced at both UI and execution time.
30+
</Callout>
31+
32+
---
33+
1234
## Bring Your Own Key (BYOK)
1335

1436
Use your own API keys for AI model providers instead of Sim Studio's hosted keys.
@@ -61,15 +83,38 @@ Enterprise authentication with SAML 2.0 and OIDC support for centralized identit
6183

6284
---
6385

64-
## Self-Hosted
86+
## Self-Hosted Configuration
87+
88+
For self-hosted deployments, enterprise features can be enabled via environment variables without requiring billing.
6589

66-
For self-hosted deployments, enterprise features can be enabled via environment variables:
90+
### Environment Variables
6791

6892
| Variable | Description |
6993
|----------|-------------|
94+
| `ORGANIZATIONS_ENABLED`, `NEXT_PUBLIC_ORGANIZATIONS_ENABLED` | Enable team/organization management |
95+
| `ACCESS_CONTROL_ENABLED`, `NEXT_PUBLIC_ACCESS_CONTROL_ENABLED` | Permission groups for access restrictions |
7096
| `SSO_ENABLED`, `NEXT_PUBLIC_SSO_ENABLED` | Single Sign-On with SAML/OIDC |
7197
| `CREDENTIAL_SETS_ENABLED`, `NEXT_PUBLIC_CREDENTIAL_SETS_ENABLED` | Polling Groups for email triggers |
7298

73-
<Callout type="warn">
74-
BYOK is only available on hosted Sim Studio. Self-hosted deployments configure AI provider keys directly via environment variables.
75-
</Callout>
99+
### Organization Management
100+
101+
When billing is disabled, use the Admin API to manage organizations:
102+
103+
```bash
104+
# Create an organization
105+
curl -X POST https://your-instance/api/v1/admin/organizations \
106+
-H "x-admin-key: YOUR_ADMIN_API_KEY" \
107+
-H "Content-Type: application/json" \
108+
-d '{"name": "My Organization", "ownerId": "user-id-here"}'
109+
110+
# Add a member
111+
curl -X POST https://your-instance/api/v1/admin/organizations/{orgId}/members \
112+
-H "x-admin-key: YOUR_ADMIN_API_KEY" \
113+
-H "Content-Type: application/json" \
114+
-d '{"userId": "user-id-here", "role": "admin"}'
115+
```
116+
117+
### Notes
118+
119+
- Enabling `ACCESS_CONTROL_ENABLED` automatically enables organizations, as access control requires organization membership.
120+
- BYOK is only available on hosted Sim Studio. Self-hosted deployments configure AI provider keys directly via environment variables.

0 commit comments

Comments
 (0)