Skip to content

Commit ac7e938

Browse files
committed
Merge staging into fix/router
2 parents f1b8745 + baa54b4 commit ac7e938

File tree

440 files changed

+33332
-9340
lines changed

Some content is hidden

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

440 files changed

+33332
-9340
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/content/docs/en/blocks/router.mdx

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

8-
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.
8+
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.
99

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

3232
## Configuration Options
3333

34-
### Content/Prompt
34+
### Context
3535

36-
The content or prompt that the Router will analyze to make routing decisions. This can be:
36+
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:
3737

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

42-
### Target Blocks
43+
### Routes
4344

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

46-
- Customize the descriptions of target blocks to improve routing accuracy
47-
- Specify routing criteria for each target block
48-
- Exclude certain blocks from being considered as routing targets
47+
- **Route Title**: A name for the route (e.g., "Sales", "Support", "Technical")
48+
- **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")
49+
50+
Each route you add creates a **separate output port** on the Router block. Connect each port to the appropriate downstream block for that route.
4951

5052
### Model Selection
5153

@@ -65,30 +67,40 @@ Your API key for the selected LLM provider. This is securely stored and used for
6567

6668
## Outputs
6769

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

7477
## Example Use Cases
7578

7679
**Customer Support Triage** - Route tickets to specialized departments
80+
7781
```
78-
Input (Ticket) → Router → Agent (Engineering) or Agent (Finance)
82+
Input (Ticket) → Router
83+
├── [Sales Route] → Agent (Sales Team)
84+
├── [Technical Route] → Agent (Engineering)
85+
└── [Billing Route] → Agent (Finance)
7986
```
8087

8188
**Content Classification** - Classify and route user-generated content
89+
8290
```
83-
Input (Feedback) → Router → Workflow (Product) or Workflow (Technical)
91+
Input (Feedback) → Router
92+
├── [Product Feedback] → Workflow (Product Team)
93+
└── [Bug Report] → Workflow (Technical Team)
8494
```
8595

8696
**Lead Qualification** - Route leads based on qualification criteria
97+
8798
```
88-
Input (Lead) → Router → Agent (Enterprise Sales) or Workflow (Self-serve)
99+
Input (Lead) → Router
100+
├── [Enterprise] → Agent (Enterprise Sales)
101+
└── [Self-serve] → Workflow (Automated Onboarding)
89102
```
90103

91-
92104
## Error Handling
93105

94106
When the Router cannot determine an appropriate route for the given context, it will route to the **error path** instead of arbitrarily selecting a route. This happens when:
@@ -98,9 +110,10 @@ When the Router cannot determine an appropriate route for the given context, it
98110

99111
## Best Practices
100112

101-
- **Provide clear target descriptions**: Help the Router understand when to select each destination with specific, detailed descriptions
102-
- **Use specific routing criteria**: Define clear conditions and examples for each path to improve accuracy
103-
- **Connect an error path**: Handle cases where no route matches by connecting an error handler for graceful fallback behavior
104-
- **Test with diverse inputs**: Ensure the Router handles various input types, edge cases, and unexpected content
105-
- **Monitor routing performance**: Review routing decisions regularly and refine criteria based on actual usage patterns
106-
- **Choose appropriate models**: Use models with strong reasoning capabilities for complex routing decisions
113+
- **Write clear route descriptions**: Each route description should clearly explain when that route should be selected. Be specific about the criteria.
114+
- **Make routes mutually exclusive**: When possible, ensure route descriptions don't overlap to prevent ambiguous routing decisions.
115+
- **Connect an error path**: Handle cases where no route matches by connecting an error handler for graceful fallback behavior.
116+
- **Use descriptive route titles**: Route titles appear in the workflow canvas, so make them meaningful for readability.
117+
- **Test with diverse inputs**: Ensure the Router handles various input types, edge cases, and unexpected content.
118+
- **Monitor routing performance**: Review routing decisions regularly and refine route descriptions based on actual usage patterns.
119+
- **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)