Skip to content

Commit 152e942

Browse files
committed
Merge origin/staging into feat/copilot-subagents
2 parents 3359d7b + be578e2 commit 152e942

File tree

403 files changed

+31885
-9406
lines changed

Some content is hidden

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

403 files changed

+31885
-9406
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/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.
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
---
2+
title: Form Deployment
3+
---
4+
5+
import { Callout } from 'fumadocs-ui/components/callout'
6+
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
7+
8+
Deploy your workflow as an embeddable form that users can fill out on your website or share via link. Form submissions trigger your workflow with the `form` trigger type.
9+
10+
## Overview
11+
12+
Form deployment turns your workflow's Input Format into a responsive form that can be:
13+
- Shared via a direct link (e.g., `https://sim.ai/form/my-survey`)
14+
- Embedded in any website using an iframe
15+
16+
When a user submits the form, it triggers your workflow with the form data.
17+
18+
<Callout type="info">
19+
Forms derive their fields from your workflow's Start block Input Format. Each field becomes a form input with the appropriate type.
20+
</Callout>
21+
22+
## Creating a Form
23+
24+
1. Open your workflow and click **Deploy**
25+
2. Select the **Form** tab
26+
3. Configure:
27+
- **URL**: Unique identifier (e.g., `contact-form``sim.ai/form/contact-form`)
28+
- **Title**: Form heading
29+
- **Description**: Optional subtitle
30+
- **Form Fields**: Customize labels and descriptions for each field
31+
- **Authentication**: Public, password-protected, or email whitelist
32+
- **Thank You Message**: Shown after submission
33+
4. Click **Launch**
34+
35+
## Field Type Mapping
36+
37+
| Input Format Type | Form Field |
38+
|------------------|------------|
39+
| `string` | Text input |
40+
| `number` | Number input |
41+
| `boolean` | Toggle switch |
42+
| `object` | JSON editor |
43+
| `array` | JSON array editor |
44+
| `files` | File upload |
45+
46+
## Access Control
47+
48+
| Mode | Description |
49+
|------|-------------|
50+
| **Public** | Anyone with the link can submit |
51+
| **Password** | Users must enter a password |
52+
| **Email Whitelist** | Only specified emails/domains can submit |
53+
54+
For email whitelist:
55+
56+
- Domain: `@example.com` (all emails from domain)
57+
58+
## Embedding
59+
60+
### Direct Link
61+
62+
```
63+
https://sim.ai/form/your-identifier
64+
```
65+
66+
### Iframe
67+
68+
```html
69+
<iframe
70+
src="https://sim.ai/form/your-identifier"
71+
width="100%"
72+
height="600"
73+
frameborder="0"
74+
title="Form"
75+
></iframe>
76+
```
77+
78+
## API Submission
79+
80+
Submit forms programmatically:
81+
82+
<Tabs items={['cURL', 'TypeScript']}>
83+
<Tab value="cURL">
84+
```bash
85+
curl -X POST https://sim.ai/api/form/your-identifier \
86+
-H "Content-Type: application/json" \
87+
-d '{
88+
"formData": {
89+
"name": "John Doe",
90+
"email": "[email protected]"
91+
}
92+
}'
93+
```
94+
</Tab>
95+
<Tab value="TypeScript">
96+
```typescript
97+
const response = await fetch('https://sim.ai/api/form/your-identifier', {
98+
method: 'POST',
99+
headers: { 'Content-Type': 'application/json' },
100+
body: JSON.stringify({
101+
formData: {
102+
name: 'John Doe',
103+
104+
}
105+
})
106+
});
107+
108+
const result = await response.json();
109+
// { success: true, data: { executionId: '...' } }
110+
```
111+
</Tab>
112+
</Tabs>
113+
114+
### Protected Forms
115+
116+
For password-protected forms:
117+
```bash
118+
curl -X POST https://sim.ai/api/form/your-identifier \
119+
-H "Content-Type: application/json" \
120+
-d '{ "password": "secret", "formData": { "name": "John" } }'
121+
```
122+
123+
For email-protected forms:
124+
```bash
125+
curl -X POST https://sim.ai/api/form/your-identifier \
126+
-H "Content-Type: application/json" \
127+
-d '{ "email": "[email protected]", "formData": { "name": "John" } }'
128+
```
129+
130+
## Troubleshooting
131+
132+
**"No input fields configured"** - Add Input Format fields to your Start block.
133+
134+
**Form not loading in iframe** - Check your site's CSP allows iframes from `sim.ai`.
135+
136+
**Submissions failing** - Verify the identifier is correct and required fields are filled.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"pages": ["index", "basics", "api", "logging", "costs"]
2+
"pages": ["index", "basics", "api", "form", "logging", "costs"]
33
}

apps/docs/content/docs/en/triggers/start.mdx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Reference structured values downstream with expressions such as <code>&lt;start.
4444

4545
## How it behaves per entry point
4646

47-
<Tabs items={['Editor run', 'Deploy to API', 'Deploy to chat']}>
47+
<Tabs items={['Editor run', 'Deploy to API', 'Deploy to chat', 'Deploy to form']}>
4848
<Tab>
4949
When you click <strong>Run</strong> in the editor, the Start block renders the Input Format as a form. Default values make it easy to retest without retyping data. Submitting the form triggers the workflow immediately and the values become available on <code>&lt;start.fieldName&gt;</code> (for example <code>&lt;start.sampleField&gt;</code>).
5050

@@ -64,6 +64,13 @@ Reference structured values downstream with expressions such as <code>&lt;start.
6464

6565
If you launch chat with additional structured context (for example from an embed), it merges into the corresponding <code>&lt;start.fieldName&gt;</code> outputs, keeping downstream blocks consistent with API and manual runs.
6666
</Tab>
67+
<Tab>
68+
Form deployments render the Input Format as a standalone, embeddable form page. Each field becomes a form input with appropriate UI controls—text inputs for strings, number inputs for numbers, toggle switches for booleans, and file upload zones for files.
69+
70+
When a user submits the form, values become available on <code>&lt;start.fieldName&gt;</code> just like other entry points. The workflow executes with trigger type <code>form</code>, and submitters see a customizable thank-you message upon completion.
71+
72+
Forms can be embedded via iframe or shared as direct links, making them ideal for surveys, contact forms, and data collection workflows.
73+
</Tab>
6774
</Tabs>
6875

6976
## Referencing Start data downstream

0 commit comments

Comments
 (0)