Skip to content

Commit 254945f

Browse files
committed
Merge remote-tracking branch 'origin/staging' into fix/secrets-sanitization-trace-spans
2 parents 664de15 + ecf1d7d commit 254945f

103 files changed

Lines changed: 23108 additions & 455 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.

.devcontainer/docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ services:
1919
- BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:-your_auth_secret_here}
2020
- ENCRYPTION_KEY=${ENCRYPTION_KEY:-your_encryption_key_here}
2121
- COPILOT_API_KEY=${COPILOT_API_KEY}
22+
- NEXT_PUBLIC_CHAT_DISABLED=${NEXT_PUBLIC_CHAT_DISABLED:-}
2223
- SIM_AGENT_API_URL=${SIM_AGENT_API_URL}
2324
- OLLAMA_URL=${OLLAMA_URL:-http://localhost:11434}
2425
- NEXT_PUBLIC_SOCKET_URL=${NEXT_PUBLIC_SOCKET_URL:-}

apps/docs/content/docs/en/integrations/managed_agent.mdx

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,200 @@ Open a Claude Platform Managed Agent session and return the assistant response a
6464
| `inputTokens` | number | Cumulative input tokens for the session. |
6565
| `outputTokens` | number | Cumulative output tokens for the session. |
6666

67+
### `managed_agent_create_session`
68+
69+
Create a Claude Platform Managed Agent session and return its id without waiting for a reply.
70+
71+
#### Input
72+
73+
| Parameter | Type | Required | Description |
74+
| --------- | ---- | -------- | ----------- |
75+
| `agent` | string | Yes | Managed-agent id inside the linked Claude workspace. |
76+
| `environment` | string | Yes | Environment id inside the linked Claude workspace. |
77+
| `environmentType` | string | No | Environment execution model hint \('cloud' \| 'self_hosted'\). |
78+
| `userMessage` | string | No | Optional first message; seeds initial_events and starts the agent immediately. |
79+
| `vaults` | array | No | Zero or more vault ids for MCP tool auth. |
80+
| `vaultsAck` | boolean | No | Acknowledgement that the author may use the attached vaults. |
81+
| `memoryStoreId` | string | No | Optional Agent Memory Store id. |
82+
| `memoryAccess` | string | No | Memory store access mode: 'read_write' \(default\) or 'read_only'. |
83+
| `memoryInstructions` | string | No | Per-attachment guidance for how the agent should use the memory store. |
84+
| `files` | array | No | File attachments \(cloud envs only\), as \[\{fileId, mountPath?\}\]. |
85+
| `sessionParameters` | object | No | Key/value session metadata forwarded to the session. |
86+
87+
#### Output
88+
89+
| Parameter | Type | Description |
90+
| --------- | ---- | ----------- |
91+
| `sessionId` | string | Anthropic session id \(sesn_...\). |
92+
| `started` | boolean | True when a first message was seeded, so the agent is already running. |
93+
94+
### `managed_agent_send_message`
95+
96+
Send a user message to an existing Claude Platform Managed Agent session.
97+
98+
#### Input
99+
100+
| Parameter | Type | Required | Description |
101+
| --------- | ---- | -------- | ----------- |
102+
| `userMessage` | string | Yes | The user message to send to the session. |
103+
104+
#### Output
105+
106+
| Parameter | Type | Description |
107+
| --------- | ---- | ----------- |
108+
| `sessionId` | string | The session the message was sent to. |
109+
| `sent` | boolean | True when the event was accepted by the API. |
110+
111+
### `managed_agent_get_session`
112+
113+
Read a Managed Agent session: status, stop reason, token usage, metadata, and any tool calls awaiting approval.
114+
115+
#### Input
116+
117+
| Parameter | Type | Required | Description |
118+
| --------- | ---- | -------- | ----------- |
119+
120+
#### Output
121+
122+
| Parameter | Type | Description |
123+
| --------- | ---- | ----------- |
124+
| `sessionId` | string | The session that was read. |
125+
| `status` | string | Session status — 'idle', 'running', 'rescheduling', or 'terminated'. |
126+
| `stopReason` | string | Why the session last stopped, e.g. 'end_turn' or 'requires_action'. |
127+
| `requiresAction` | boolean | True when the session is waiting on a tool confirmation or custom tool result. If this is true while pendingTools is empty, the session is blocked but the API named no blocking events — surface it rather than treating the session as done. |
128+
| `pendingTools` | json | Blocking tool calls — \[\{id, eventType, kind, name, input\}\]. Route by kind: 'confirmation' ids go to Respond To Tool Confirmation, 'custom_tool_result' ids go to Respond To Custom Tool. |
129+
| `metadata` | json | Session metadata. |
130+
| `title` | string | Session title. |
131+
| `inputTokens` | number | Cumulative input tokens. |
132+
| `outputTokens` | number | Cumulative output tokens. |
133+
134+
### `managed_agent_list_events`
135+
136+
Read a Managed Agent session's event history and the agent's reply text.
137+
138+
#### Input
139+
140+
| Parameter | Type | Required | Description |
141+
| --------- | ---- | -------- | ----------- |
142+
| `eventTypes` | array | No | Optional event-type filter, e.g. \['agent.message'\]. Omit to return every event. |
143+
| `limit` | number | No | Maximum events to return, keeping the most recent \(default 500\). |
144+
145+
#### Output
146+
147+
| Parameter | Type | Description |
148+
| --------- | ---- | ----------- |
149+
| `sessionId` | string | The session that was read. |
150+
| `events` | json | Session events, oldest first. |
151+
| `count` | number | Number of events returned. |
152+
| `assistantText` | string | Concatenated text of every persisted agent.message, in order. |
153+
| `truncated` | boolean | True when the limit was hit and older events were dropped. |
154+
155+
### `managed_agent_update_session`
156+
157+
Update a Managed Agent session's title or metadata.
158+
159+
#### Input
160+
161+
| Parameter | Type | Required | Description |
162+
| --------- | ---- | -------- | ----------- |
163+
| `title` | string | No | New session title. |
164+
| `sessionParameters` | object | No | Replacement metadata map \(replaces all stored metadata, not merged\). Leaving it empty leaves the stored metadata unchanged — use clearMetadata to remove it. |
165+
| `clearMetadata` | boolean | No | Removes all of the session's stored metadata. Overrides any map supplied above. |
166+
167+
#### Output
168+
169+
| Parameter | Type | Description |
170+
| --------- | ---- | ----------- |
171+
| `sessionId` | string | The session that was updated. |
172+
| `updated` | boolean | True when the update was accepted. |
173+
| `metadata` | json | Metadata after the update. |
174+
| `title` | string | Title after the update. |
175+
176+
### `managed_agent_interrupt_session`
177+
178+
Stop a running Managed Agent session; it stays usable afterwards.
179+
180+
#### Input
181+
182+
| Parameter | Type | Required | Description |
183+
| --------- | ---- | -------- | ----------- |
184+
185+
#### Output
186+
187+
| Parameter | Type | Description |
188+
| --------- | ---- | ----------- |
189+
| `sessionId` | string | The session that was interrupted. |
190+
| `interrupted` | boolean | True when the interrupt was accepted. |
191+
192+
### `managed_agent_respond_tool_confirmation`
193+
194+
Allow or deny the tool calls a Managed Agent session is waiting on before it can continue.
195+
196+
#### Input
197+
198+
| Parameter | Type | Required | Description |
199+
| --------- | ---- | -------- | ----------- |
200+
| `toolUseIds` | array | Yes | Blocking tool-use EVENT ids, from Get Session pendingTools\[\].id where kind is 'confirmation' \(not toolu_ ids\). |
201+
| `decision` | string | Yes | 'allow' to let the tools run, or 'deny' to reject them. |
202+
| `denyMessage` | string | No | Reason surfaced to the agent. Only sent when the decision is deny. |
203+
204+
#### Output
205+
206+
| Parameter | Type | Description |
207+
| --------- | ---- | ----------- |
208+
| `sessionId` | string | The session that was answered. |
209+
| `decision` | string | The decision applied — 'allow' or 'deny'. |
210+
| `confirmedToolUseIds` | json | The tool-use event ids that were answered. |
211+
212+
### `managed_agent_respond_custom_tool`
213+
214+
Return the result of a custom tool a Managed Agent session is waiting on so it can continue.
215+
216+
#### Input
217+
218+
| Parameter | Type | Required | Description |
219+
| --------- | ---- | -------- | ----------- |
220+
| `customToolUseId` | string | Yes | The custom tool-use EVENT id being answered, from Get Session pendingTools\[\].id where kind is 'custom_tool_result'. |
221+
| `result` | string | Yes | The tool's output, returned to the agent as text. |
222+
| `isError` | boolean | No | Mark the result as a failure so the agent can adjust its approach. |
223+
224+
#### Output
225+
226+
| Parameter | Type | Description |
227+
| --------- | ---- | ----------- |
228+
| `sessionId` | string | The session that was answered. |
229+
| `answeredToolUseId` | string | The custom tool-use event id that was answered. |
230+
231+
### `managed_agent_archive_session`
232+
233+
Archive a Managed Agent session, preserving its history. Not reversible.
234+
235+
#### Input
236+
237+
| Parameter | Type | Required | Description |
238+
| --------- | ---- | -------- | ----------- |
239+
240+
#### Output
241+
242+
| Parameter | Type | Description |
243+
| --------- | ---- | ----------- |
244+
| `sessionId` | string | The session that was archived. |
245+
| `archived` | boolean | True when the archive was accepted. |
246+
247+
### `managed_agent_delete_session`
248+
249+
Permanently delete a Managed Agent session, its events, and its sandbox. Not reversible.
250+
251+
#### Input
252+
253+
| Parameter | Type | Required | Description |
254+
| --------- | ---- | -------- | ----------- |
255+
256+
#### Output
257+
258+
| Parameter | Type | Description |
259+
| --------- | ---- | ----------- |
260+
| `sessionId` | string | The session that was deleted. |
261+
| `deleted` | boolean | True when the delete was accepted. |
262+
67263

apps/docs/content/docs/en/platform/self-hosting/environment-variables.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ import { Callout } from 'fumadocs-ui/components/callout'
6464
| Variable | Description |
6565
|----------|-------------|
6666
| `API_ENCRYPTION_KEY` | Encrypts stored API keys (32 hex chars): `openssl rand -hex 32` |
67-
| `COPILOT_API_KEY` | API key for copilot features |
67+
| `COPILOT_API_KEY` | API key for Chat. Without it the Sim Chat block, scheduled prompt jobs, and Inbox cannot run |
68+
| `NEXT_PUBLIC_CHAT_DISABLED` | Set to `true` to hide the Chat module: the workspace lands on your first workflow, with no chats list, scheduled tasks, or editor Chat panel. Chat is shown when unset; `bun run setup` sets it for you if you skip the chat key |
6869
| `ADMIN_API_KEY` | Admin API key for GitOps operations |
6970
| `ALLOWED_LOGIN_DOMAINS` | Restrict signups to domains (comma-separated) |
7071
| `ALLOWED_LOGIN_EMAILS` | Restrict signups to specific emails (comma-separated) |

apps/sim/.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ NEXT_PUBLIC_APP_URL=http://localhost:3000
2121
# TRUSTED_ORIGINS=https://www.example.com,https://app.example.com # Optional: comma-separated additional public origins to trust for auth (apex+www, alias domains). Merged into Better Auth trustedOrigins.
2222
# AUTH_TRUSTED_PROXIES=10.0.0.0/24,192.0.2.10 # Optional: reverse-proxy IPs/CIDRs in front of the app. Better Auth walks x-forwarded-for right to left, skips these hops, and uses the first untrusted address as the client IP (prevents forwarded-header spoofing). Use your proxies' actual addresses, not broad private ranges that also cover clients.
2323

24+
# Chat (Optional)
25+
# COPILOT_API_KEY= # Mint one at https://sim.ai. Without it the Sim Chat block, prompt jobs, and Inbox cannot run
26+
# NEXT_PUBLIC_CHAT_DISABLED=true # Hides the Chat module: the workspace lands on your first workflow, and the chats list, scheduled tasks, and editor Chat panel are absent. Chat is shown when unset; `bun run setup` sets this for you if you skip the chat key
27+
2428
# Security (Required)
2529
ENCRYPTION_KEY=your_encryption_key # Use `openssl rand -hex 32` to generate, used to encrypt environment variables
2630
INTERNAL_API_SECRET=your_internal_api_secret # Use `openssl rand -hex 32` to generate, used to encrypt internal api routes

apps/sim/app/api/auth/oauth2/callback/instagram/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ import { getBaseUrl } from '@/lib/core/utils/urls'
1717
import { isSameOrigin } from '@/lib/core/utils/validation'
1818
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
1919
import { processCredentialDraft } from '@/lib/credentials/draft-processor'
20-
import { INSTAGRAM_GRAPH_BASE } from '@/lib/integrations/instagram/constants'
2120
import {
2221
parseInstagramLongLivedToken,
2322
parseInstagramProfile,
2423
parseInstagramShortLivedToken,
2524
} from '@/lib/oauth/instagram'
2625
import { getCanonicalScopesForProvider } from '@/lib/oauth/utils'
2726
import { safeAccountInsert } from '@/app/api/auth/oauth/utils'
27+
import { INSTAGRAM_GRAPH_BASE } from '@/tools/instagram/constants'
2828

2929
const logger = createLogger('InstagramCallback')
3030

apps/sim/app/api/mothership/events/route.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type { NextRequest } from 'next/server'
1111
import { mothershipEventsQuerySchema } from '@/lib/api/contracts/mothership-chats'
1212
import { validationErrorResponse } from '@/lib/api/server'
1313
import { chatPubSub } from '@/lib/copilot/chat-status'
14+
import { isChatEnabled } from '@/lib/core/config/env-flags'
1415
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
1516
import { createWorkspaceSSE } from '@/lib/events/sse-endpoint'
1617

@@ -37,6 +38,10 @@ const mothershipEventsHandler = createWorkspaceSSE({
3738
})
3839

3940
export const GET = withRouteHandler((request: NextRequest) => {
41+
// Closes streams held by tabs that were open when Chat was turned off; the
42+
// client hook already declines to open new ones.
43+
if (!isChatEnabled) return new Response(null, { status: 404 })
44+
4045
const validation = mothershipEventsQuerySchema.safeParse(
4146
Object.fromEntries(request.nextUrl.searchParams.entries())
4247
)

apps/sim/app/api/schedules/execute/route.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
requestUtilsMockFns,
1010
resetDbChainMock,
1111
resetEnvFlagsMock,
12+
resetEnvMock,
13+
setEnv,
1214
setEnvFlags,
1315
} from '@sim/testing'
1416
import { type NextRequest, NextResponse } from 'next/server'
@@ -275,7 +277,10 @@ function createMockRequest(): NextRequest {
275277
} as NextRequest
276278
}
277279

278-
afterAll(resetEnvFlagsMock)
280+
afterAll(() => {
281+
resetEnvFlagsMock()
282+
resetEnvMock()
283+
})
279284

280285
describe('Scheduled Workflow Execution API Route', () => {
281286
beforeEach(() => {
@@ -290,6 +295,9 @@ describe('Scheduled Workflow Execution API Route', () => {
290295
dbChainMockFns.execute.mockResolvedValue([{ acquired: true }] as never)
291296
requestUtilsMockFns.mockGenerateRequestId.mockReturnValue('test-request-id')
292297
setEnvFlags({ isTriggerDevEnabled: false, isHosted: false, isProd: false, isDev: true })
298+
// Prompt-job claims are skipped without the mothership credential; pin it so
299+
// these cases do not depend on whether the runner happens to have a .env.
300+
setEnv({ COPILOT_API_KEY: 'test-api-key' })
293301
mockShouldExecuteInline.mockReturnValue(false)
294302
mockEnqueue.mockReset()
295303
mockEnqueue.mockResolvedValue('job-id-1')

apps/sim/app/api/schedules/execute/route.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from '@/lib/billing/core/billing-attribution'
1818
import { getJobQueue, shouldExecuteInline } from '@/lib/core/async-jobs'
1919
import { JOB_STATUS, type Job } from '@/lib/core/async-jobs/types'
20+
import { env } from '@/lib/core/config/env'
2021
import { isRetryableInfrastructureError } from '@/lib/core/errors/retryable-infrastructure'
2122
import { getMaxExecutionTimeout } from '@/lib/core/execution-limits'
2223
import { runDetached } from '@/lib/core/utils/background'
@@ -1245,7 +1246,18 @@ export async function runScheduleTick(requestId: string): Promise<ScheduleTickRe
12451246
let iterations = 0
12461247
let remainingWorkflowBudget = SCHEDULE_WORKFLOW_ENQUEUE_LIMIT
12471248
let schedulesExhausted = false
1248-
let jobsExhausted = false
1249+
/**
1250+
* Prompt jobs run through the mothership, so without a key every claim ends in
1251+
* a 401. Skipping the claim entirely leaves the rows `active` and resumable;
1252+
* claiming them would burn each one through `MAX_CONSECUTIVE_FAILURES` and
1253+
* permanently disable a schedule the user can no longer see, let alone stop.
1254+
* Keyed on the credential rather than `CHAT_ENABLED` so jobs keep running for
1255+
* a deployment that only hid the UI.
1256+
*/
1257+
let jobsExhausted = !env.COPILOT_API_KEY
1258+
if (jobsExhausted) {
1259+
logger.info(`[${requestId}] COPILOT_API_KEY not set, skipping prompt job claims`)
1260+
}
12491261

12501262
while (Date.now() - tickStart < MAX_TICK_DURATION_MS) {
12511263
if (schedulesExhausted && jobsExhausted) break

apps/sim/app/api/tools/instagram/publish-carousel/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { instagramPublishCarouselContract } from '@/lib/api/contracts/tools/inst
55
import { parseRequest } from '@/lib/api/server'
66
import { checkInternalAuth } from '@/lib/auth/hybrid'
77
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
8-
import { resolveInstagramCarouselMedia } from '@/lib/integrations/instagram/resolve-media'
8+
import { resolveInstagramCarouselMedia } from '@/app/api/tools/instagram/resolve-media'
99
import {
1010
createMediaContainer,
1111
publishMediaContainer,

apps/sim/app/api/tools/instagram/publish-image/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { instagramPublishImageContract } from '@/lib/api/contracts/tools/instagr
55
import { parseRequest } from '@/lib/api/server'
66
import { checkInternalAuth } from '@/lib/auth/hybrid'
77
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
8-
import { resolveInstagramMedia } from '@/lib/integrations/instagram/resolve-media'
8+
import { resolveInstagramMedia } from '@/app/api/tools/instagram/resolve-media'
99
import {
1010
createMediaContainer,
1111
publishMediaContainer,

0 commit comments

Comments
 (0)