Skip to content

Commit d550934

Browse files
authored
Improvement/mothership (#4775)
* ff * System role in cache
1 parent cec7b0e commit d550934

13 files changed

Lines changed: 254 additions & 147 deletions

File tree

apps/sim/app/api/mcp/copilot/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import { resolveWorkflowIdForUser } from '@/lib/workflows/utils'
3838

3939
const logger = createLogger('CopilotMcpAPI')
4040
const mcpRateLimiter = new RateLimiter()
41-
const DEFAULT_COPILOT_MODEL = 'claude-opus-4-6'
41+
const DEFAULT_COPILOT_MODEL = 'claude-opus-4-8'
4242

4343
export const dynamic = 'force-dynamic'
4444
export const runtime = 'nodejs'

apps/sim/lib/copilot/chat/payload.test.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ vi.mock('@/tools/params', () => ({
5757
createUserToolSchema: mockCreateUserToolSchema,
5858
}))
5959

60-
import { buildIntegrationToolSchemas } from './payload'
60+
import { buildCopilotRequestPayload, buildIntegrationToolSchemas } from './payload'
6161

6262
describe('buildIntegrationToolSchemas', () => {
6363
beforeEach(() => {
@@ -123,3 +123,31 @@ describe('buildIntegrationToolSchemas', () => {
123123
)
124124
})
125125
})
126+
127+
describe('buildCopilotRequestPayload', () => {
128+
beforeEach(() => {
129+
vi.clearAllMocks()
130+
})
131+
132+
it('passes workspaceContext through to the Go request payload', async () => {
133+
const payload = await buildCopilotRequestPayload(
134+
{
135+
message: 'debug workspace',
136+
userId: 'user-1',
137+
userMessageId: 'msg-1',
138+
mode: 'agent',
139+
model: 'claude-opus-4-8',
140+
workspaceId: 'ws-1',
141+
workspaceContext: 'workspace inventory',
142+
},
143+
{ selectedModel: 'claude-opus-4-8' }
144+
)
145+
146+
expect(payload).toEqual(
147+
expect.objectContaining({
148+
workspaceId: 'ws-1',
149+
workspaceContext: 'workspace inventory',
150+
})
151+
)
152+
})
153+
})

apps/sim/lib/copilot/chat/post.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,17 @@ describe('handleUnifiedChatPost', () => {
167167
)
168168

169169
expect(response.status).toBe(200)
170+
expect(generateWorkspaceContext).toHaveBeenCalledWith('ws-1', 'user-1')
170171
expect(buildCopilotRequestPayload).toHaveBeenCalledWith(
171172
expect.objectContaining({
172-
model: 'claude-opus-4-7',
173+
model: 'claude-opus-4-8',
174+
workspaceContext: 'workspace context',
173175
}),
174-
{ selectedModel: 'claude-opus-4-7' }
176+
{ selectedModel: 'claude-opus-4-8' }
175177
)
176178
expect(createSSEStream).toHaveBeenCalledWith(
177179
expect.objectContaining({
178-
titleModel: 'claude-opus-4-7',
180+
titleModel: 'claude-opus-4-8',
179181
workspaceId: 'ws-1',
180182
orchestrateOptions: expect.objectContaining({
181183
workflowId: 'wf-1',
@@ -213,7 +215,7 @@ describe('handleUnifiedChatPost', () => {
213215
)
214216
expect(createSSEStream).toHaveBeenCalledWith(
215217
expect.objectContaining({
216-
titleModel: 'claude-opus-4-7',
218+
titleModel: 'claude-opus-4-8',
217219
workspaceId: 'ws-1',
218220
orchestrateOptions: expect.objectContaining({
219221
workspaceId: 'ws-1',

apps/sim/lib/copilot/chat/post.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ import type { ChatContext } from '@/stores/panel'
5050
export const maxDuration = 3600
5151

5252
const logger = createLogger('UnifiedChatAPI')
53-
const DEFAULT_MODEL = 'claude-opus-4-7'
53+
const DEFAULT_MODEL = 'claude-opus-4-8'
5454

5555
const FileAttachmentSchema = z.object({
5656
id: z.string(),
@@ -172,6 +172,7 @@ type UnifiedChatBranch =
172172
commands?: string[]
173173
prefetch?: boolean
174174
implicitFeedback?: string
175+
workspaceContext?: string
175176
}) => Promise<Record<string, unknown>>
176177
buildExecutionContext: (params: {
177178
userId: string
@@ -556,7 +557,7 @@ async function resolveBranch(params: {
556557
workflowId: resolvedWorkflowId,
557558
workflowName: resolved.workflowName,
558559
workspaceId: resolvedWorkspaceId,
559-
effectiveModel: selectedModel,
560+
effectiveModel: selectedModel,
560561
selectedModel,
561562
mode: mode ?? 'agent',
562563
provider,
@@ -582,6 +583,7 @@ async function resolveBranch(params: {
582583
chatId: payloadParams.chatId,
583584
prefetch: payloadParams.prefetch,
584585
implicitFeedback: payloadParams.implicitFeedback,
586+
workspaceContext: payloadParams.workspaceContext,
585587
userPermission: payloadParams.userPermission,
586588
userTimezone: payloadParams.userTimezone,
587589
},
@@ -852,11 +854,11 @@ export async function handleUnifiedChatPost(req: NextRequest) {
852854
// apparent "gap" before the model call. Each promise is its own
853855
// span; they run concurrently under Promise.all below.
854856
const workspaceContextPromise =
855-
branch.kind === 'workspace'
857+
workspaceId
856858
? withCopilotSpan(
857859
TraceSpan.CopilotChatBuildWorkspaceContext,
858-
{ [TraceAttr.WorkspaceId]: branch.workspaceId },
859-
() => generateWorkspaceContext(branch.workspaceId, authenticatedUserId),
860+
{ [TraceAttr.WorkspaceId]: workspaceId },
861+
() => generateWorkspaceContext(workspaceId, authenticatedUserId),
860862
activeOtelRoot.context
861863
)
862864
: Promise.resolve(undefined)
@@ -950,6 +952,7 @@ export async function handleUnifiedChatPost(req: NextRequest) {
950952
commands: body.commands,
951953
prefetch: body.prefetch,
952954
implicitFeedback: body.implicitFeedback,
955+
workspaceContext,
953956
})
954957
: branch.buildPayload({
955958
message: body.message,

apps/sim/lib/copilot/tools/handlers/function-execute.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { createLogger } from '@sim/logger'
22
import { decodeVfsPathSegments, encodeVfsPathSegments } from '@/lib/copilot/vfs/path-utils'
33
import { resolveWorkflowAliasForWorkspace } from '@/lib/copilot/vfs/workflow-alias-resolver'
44
import { isPlanAliasPath, workflowAliasSandboxPath } from '@/lib/copilot/vfs/workflow-aliases'
5+
import { isMothershipBetaFeaturesEnabled } from '@/lib/core/config/feature-flags'
56
import { getTableById, listTables, queryRows } from '@/lib/table/service'
67
import { listWorkspaceFileFolders } from '@/lib/uploads/contexts/workspace/workspace-file-folder-manager'
78
import {
@@ -71,7 +72,9 @@ async function resolveInputFiles(
7172
let totalSize = 0
7273

7374
if (inputFiles?.length && workspaceId) {
74-
const allFiles = await listWorkspaceFiles(workspaceId, { includeReservedSystemFiles: true })
75+
const allFiles = await listWorkspaceFiles(workspaceId, {
76+
includeReservedSystemFiles: isMothershipBetaFeaturesEnabled,
77+
})
7578
for (const fileRef of inputFiles) {
7679
const filePath =
7780
typeof fileRef === 'string'
@@ -124,11 +127,11 @@ async function resolveInputFiles(
124127

125128
if (inputDirectories?.length && workspaceId) {
126129
const folders = await listWorkspaceFileFolders(workspaceId, {
127-
includeReservedSystemFolders: true,
130+
includeReservedSystemFolders: isMothershipBetaFeaturesEnabled,
128131
})
129132
const allFiles = await listWorkspaceFiles(workspaceId, {
130133
folders,
131-
includeReservedSystemFiles: true,
134+
includeReservedSystemFiles: isMothershipBetaFeaturesEnabled,
132135
})
133136
for (const dirRef of inputDirectories) {
134137
const dirPath =

apps/sim/lib/copilot/tools/server/files/touch-plan.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ vi.mock('@/lib/copilot/vfs/resource-writer', () => ({
1818
writeWorkspaceFileByPath: mocks.writeWorkspaceFileByPath,
1919
}))
2020

21+
vi.mock('@/lib/core/config/feature-flags', () => ({
22+
isMothershipBetaFeaturesEnabled: true,
23+
}))
24+
2125
import { touchPlanServerTool } from './touch-plan'
2226

2327
describe('touch_plan server tool', () => {

apps/sim/lib/copilot/tools/server/files/touch-plan.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
} from '@/lib/copilot/vfs/path-utils'
1313
import { writeWorkspaceFileByPath } from '@/lib/copilot/vfs/resource-writer'
1414
import { resolveWorkflowAliasForWorkspace } from '@/lib/copilot/vfs/workflow-alias-resolver'
15+
import { isMothershipBetaFeaturesEnabled } from '@/lib/core/config/feature-flags'
1516

1617
const logger = createLogger('TouchPlanServerTool')
1718
const TOUCH_PLAN_TOOL_ID = 'touch_plan'
@@ -64,6 +65,9 @@ function normalizePlanRelativePath(name: string): string {
6465
export const touchPlanServerTool: BaseServerTool<TouchPlanArgs, TouchPlanResult> = {
6566
name: TOUCH_PLAN_TOOL_ID,
6667
async execute(params: TouchPlanArgs, context?: ServerToolContext): Promise<TouchPlanResult> {
68+
if (!isMothershipBetaFeaturesEnabled) {
69+
return { success: false, message: 'touch_plan is not available' }
70+
}
6771
if (!context?.userId) {
6872
throw new Error('Authentication required')
6973
}

apps/sim/lib/copilot/tools/server/router.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
type BaseServerTool,
2626
type ServerToolContext,
2727
} from '@/lib/copilot/tools/server/base-tool'
28+
import { isMothershipBetaFeaturesEnabled } from '@/lib/core/config/feature-flags'
2829
import { getBlocksMetadataServerTool } from '@/lib/copilot/tools/server/blocks/get-blocks-metadata-tool'
2930
import { getTriggerBlocksServerTool } from '@/lib/copilot/tools/server/blocks/get-trigger-blocks'
3031
import { searchDocumentationServerTool } from '@/lib/copilot/tools/server/docs/search-documentation'
@@ -130,7 +131,7 @@ function isWriteAction(toolName: string, action: string | undefined): boolean {
130131
}
131132

132133
/** Registry of all server tools. Tools self-declare their validation schemas. */
133-
const serverToolRegistry: Record<string, BaseServerTool> = {
134+
const baseServerToolRegistry: Record<string, BaseServerTool> = {
134135
[getBlocksMetadataServerTool.name]: getBlocksMetadataServerTool,
135136
[getTriggerBlocksServerTool.name]: getTriggerBlocksServerTool,
136137
[editWorkflowServerTool.name]: editWorkflowServerTool,
@@ -159,16 +160,25 @@ const serverToolRegistry: Record<string, BaseServerTool> = {
159160
[generateImageServerTool.name]: generateImageServerTool,
160161
}
161162

163+
function getServerToolRegistry(): Record<string, BaseServerTool> {
164+
if (isMothershipBetaFeaturesEnabled) {
165+
return baseServerToolRegistry
166+
}
167+
const registry = { ...baseServerToolRegistry }
168+
delete registry[touchPlanServerTool.name]
169+
return registry
170+
}
171+
162172
export function getRegisteredServerToolNames(): string[] {
163-
return Object.keys(serverToolRegistry)
173+
return Object.keys(getServerToolRegistry())
164174
}
165175

166176
export async function routeExecution(
167177
toolName: string,
168178
payload: unknown,
169179
context?: ServerToolContext
170180
): Promise<unknown> {
171-
const tool = serverToolRegistry[toolName]
181+
const tool = getServerToolRegistry()[toolName]
172182
if (!tool) {
173183
throw new Error(`Unknown server tool: ${toolName}`)
174184
}

apps/sim/lib/copilot/vfs/workflow-alias-resolver.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ import {
88
resolveWorkflowAliasPath,
99
type WorkflowAliasTarget,
1010
} from '@/lib/copilot/vfs/workflow-aliases'
11+
import { isMothershipBetaFeaturesEnabled } from '@/lib/core/config/feature-flags'
1112
import { canonicalizeVfsPath } from './path-utils'
1213

1314
export async function resolveWorkflowAliasForWorkspace(args: {
1415
workspaceId: string
1516
path: string
1617
}): Promise<WorkflowAliasTarget | null> {
18+
if (!isMothershipBetaFeaturesEnabled) return null
1719
if (!isPlanAliasPath(args.path)) return null
1820

1921
let canonicalPath: string

0 commit comments

Comments
 (0)