Skip to content

Commit c0b1657

Browse files
committed
Changelog and plan
1 parent 2f4e80c commit c0b1657

27 files changed

Lines changed: 2453 additions & 60 deletions

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,7 @@ async function maybeExportSandboxFilesToWorkspace(args: {
11211121
preparedFiles.map((prepared) =>
11221122
validateWorkspaceFileWriteTarget({
11231123
workspaceId: resolvedWorkspaceId,
1124+
userId: args.authUserId,
11241125
target: prepared.target,
11251126
})
11261127
)
@@ -1205,6 +1206,7 @@ async function maybeExportSandboxFilesToWorkspace(args: {
12051206
fileId: file.id,
12061207
fileName: file.name,
12071208
vfsPath: file.vfsPath,
1209+
backingVfsPath: file.backingVfsPath,
12081210
downloadUrl: file.downloadUrl,
12091211
sandboxPath: file.sandboxPath,
12101212
})),

apps/sim/app/workspace/[workspaceId]/home/home.tsx

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { useCallback, useEffect, useRef, useState } from 'react'
3+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
44
import { createLogger } from '@sim/logger'
55
import { useParams, useRouter, useSearchParams } from 'next/navigation'
66
import { usePostHog } from 'posthog-js/react'
@@ -9,14 +9,23 @@ import { PanelLeft } from '@/components/emcn/icons'
99
import { requestJson } from '@/lib/api/client/request'
1010
import { createWorkflowContract } from '@/lib/api/contracts'
1111
import { useSession } from '@/lib/auth/auth-client'
12+
import { canonicalWorkspaceFilePath } from '@/lib/copilot/vfs/path-utils'
13+
import {
14+
buildWorkflowAliasWorkflowEntries,
15+
resolveWorkflowAliasPath,
16+
resolveWorkspacePlanAliasPath,
17+
} from '@/lib/copilot/vfs/workflow-aliases'
1218
import {
1319
LandingPromptStorage,
1420
type LandingWorkflowSeed,
1521
LandingWorkflowSeedStorage,
1622
} from '@/lib/core/utils/browser-storage'
1723
import { captureEvent } from '@/lib/posthog/client'
1824
import { persistImportedWorkflow } from '@/lib/workflows/operations/import-export'
25+
import { useFolders } from '@/hooks/queries/folders'
1926
import { useChatHistory, useMarkTaskRead } from '@/hooks/queries/tasks'
27+
import { useWorkflows } from '@/hooks/queries/workflows'
28+
import { useWorkspaceFiles } from '@/hooks/queries/workspace-files'
2029
import type { ChatContext } from '@/stores/panel'
2130
import { MothershipChat, MothershipView, TemplatePrompts, UserInput } from './components'
2231
import { getMothershipUseChatOptions, useChat, useMothershipResize } from './hooks'
@@ -34,6 +43,9 @@ export function Home({ chatId }: HomeProps = {}) {
3443
const searchParams = useSearchParams()
3544
const initialResourceId = searchParams.get('resource')
3645
const { data: session } = useSession()
46+
const { data: workspaceFiles = [] } = useWorkspaceFiles(workspaceId)
47+
const { data: workflows = [] } = useWorkflows(workspaceId)
48+
const { data: folders = [] } = useFolders(workspaceId)
3749
const posthog = usePostHog()
3850
const posthogRef = useRef(posthog)
3951
posthogRef.current = posthog
@@ -275,10 +287,59 @@ export function Home({ chatId }: HomeProps = {}) {
275287
removeResource(resolved.type, resolved.id)
276288
}
277289

290+
const workflowAliasEntries = useMemo(
291+
() =>
292+
buildWorkflowAliasWorkflowEntries(
293+
workflows.map((workflow) => ({
294+
id: workflow.id,
295+
name: workflow.name,
296+
folderId: workflow.folderId ?? null,
297+
})),
298+
folders.map((folder) => ({
299+
folderId: folder.id,
300+
folderName: folder.name,
301+
parentId: folder.parentId ?? null,
302+
}))
303+
),
304+
[folders, workflows]
305+
)
306+
307+
const resolveFileResource = useCallback(
308+
(resource: MothershipResource): MothershipResource => {
309+
if (resource.type !== 'file') return resource
310+
311+
const reference = (resource.path || resource.id).trim()
312+
const workspacePlanAlias = resolveWorkspacePlanAliasPath(reference)
313+
const workflowAlias = workspacePlanAlias
314+
? null
315+
: resolveWorkflowAliasPath(reference, workflowAliasEntries)
316+
const alias = workspacePlanAlias || workflowAlias
317+
const targetPath = alias && alias.kind !== 'plans_dir' ? alias.backingPath : reference
318+
319+
const file = workspaceFiles.find((candidate) => {
320+
const candidatePath = canonicalWorkspaceFilePath({
321+
folderPath: candidate.folderPath,
322+
name: candidate.name,
323+
})
324+
return candidate.id === reference || candidatePath === reference || candidatePath === targetPath
325+
})
326+
327+
if (!file) return resource
328+
return {
329+
...resource,
330+
id: file.id,
331+
title: resource.title || file.name,
332+
path: alias ? reference : resource.path,
333+
}
334+
},
335+
[workflowAliasEntries, workspaceFiles]
336+
)
337+
278338
function handleWorkspaceResourceSelect(resource: MothershipResource) {
279-
const wasAdded = addResource(resource)
339+
const resolvedResource = resolveFileResource(resource)
340+
const wasAdded = addResource(resolvedResource)
280341
if (!wasAdded) {
281-
setActiveResourceId(resource.id)
342+
setActiveResourceId(resolvedResource.id)
282343
}
283344
handleResourceEvent()
284345
}

apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1797,7 +1797,20 @@ export function useChat(
17971797
}
17981798

17991799
if (session.fileId && hasRenderableFilePreviewContent(session)) {
1800-
setResources((current) => current.filter((resource) => resource.id !== 'streaming-file'))
1800+
setResources((current) => {
1801+
const withoutStreaming = current.filter((resource) => resource.id !== 'streaming-file')
1802+
if (withoutStreaming.some((resource) => resource.type === 'file' && resource.id === session.fileId)) {
1803+
return withoutStreaming
1804+
}
1805+
return [
1806+
...withoutStreaming,
1807+
{
1808+
type: 'file',
1809+
id: session.fileId!,
1810+
title: session.fileName || 'File',
1811+
},
1812+
]
1813+
})
18011814
if (options?.activate !== false) {
18021815
setActiveResourceId(session.fileId)
18031816
}

apps/sim/lib/copilot/generated/tool-catalog-v1.ts

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export interface ToolCatalogEntry {
9393
| 'superagent'
9494
| 'table'
9595
| 'tool_search_tool_regex'
96+
| 'touch_plan'
9697
| 'update_job_history'
9798
| 'update_workspace_mcp_server'
9899
| 'user_memory'
@@ -188,6 +189,7 @@ export interface ToolCatalogEntry {
188189
| 'superagent'
189190
| 'table'
190191
| 'tool_search_tool_regex'
192+
| 'touch_plan'
191193
| 'update_job_history'
192194
| 'update_workspace_mcp_server'
193195
| 'user_memory'
@@ -1145,7 +1147,7 @@ export const FunctionExecute: ToolCatalogEntry = {
11451147
path: {
11461148
type: 'string',
11471149
description:
1148-
'Canonical VFS folder path, e.g. "files/Reports". By default this mounts at "/home/user/files/Reports".',
1150+
'Canonical VFS folder path, e.g. "files/Reports" or "workflows/My%20Workflow/.plans". By default this mounts at "/home/user/{path}". Workflow alias directories mount under "/home/user/workflows/...".',
11491151
},
11501152
sandboxPath: {
11511153
type: 'string',
@@ -1165,7 +1167,7 @@ export const FunctionExecute: ToolCatalogEntry = {
11651167
path: {
11661168
type: 'string',
11671169
description:
1168-
'Canonical VFS file path, e.g. "files/Reports/sales.csv". By default this mounts at "/home/user/files/Reports/sales.csv".',
1170+
'Canonical VFS file path, e.g. "files/Reports/sales.csv" or "workflows/My%20Workflow/changelog.md". By default this mounts at "/home/user/{path}". Workflow alias paths mount under "/home/user/workflows/...".',
11691171
},
11701172
sandboxPath: {
11711173
type: 'string',
@@ -1230,7 +1232,8 @@ export const FunctionExecute: ToolCatalogEntry = {
12301232
},
12311233
path: {
12321234
type: 'string',
1233-
description: 'Canonical destination VFS path, e.g. "files/Reports/chart.png".',
1235+
description:
1236+
'Canonical destination VFS path, e.g. "files/Reports/chart.png", "workflows/My%20Workflow/changelog.md", or "workflows/My%20Workflow/.plans/plan.md".',
12341237
},
12351238
sandboxPath: {
12361239
type: 'string',
@@ -1306,7 +1309,7 @@ export const GenerateImage: ToolCatalogEntry = {
13061309
path: {
13071310
type: 'string',
13081311
description:
1309-
'Canonical VFS folder path, e.g. "files/Reports". By default this mounts at "/home/user/files/Reports".',
1312+
'Canonical VFS folder path, e.g. "files/Reports" or "workflows/My%20Workflow/.plans". By default this mounts at "/home/user/{path}". Workflow alias directories mount under "/home/user/workflows/...".',
13101313
},
13111314
sandboxPath: {
13121315
type: 'string',
@@ -1326,7 +1329,7 @@ export const GenerateImage: ToolCatalogEntry = {
13261329
path: {
13271330
type: 'string',
13281331
description:
1329-
'Canonical VFS file path, e.g. "files/Reports/sales.csv". By default this mounts at "/home/user/files/Reports/sales.csv".',
1332+
'Canonical VFS file path, e.g. "files/Reports/sales.csv" or "workflows/My%20Workflow/changelog.md". By default this mounts at "/home/user/{path}". Workflow alias paths mount under "/home/user/workflows/...".',
13301333
},
13311334
sandboxPath: {
13321335
type: 'string',
@@ -1381,7 +1384,8 @@ export const GenerateImage: ToolCatalogEntry = {
13811384
},
13821385
path: {
13831386
type: 'string',
1384-
description: 'Canonical destination VFS path, e.g. "files/Reports/chart.png".',
1387+
description:
1388+
'Canonical destination VFS path, e.g. "files/Reports/chart.png", "workflows/My%20Workflow/changelog.md", or "workflows/My%20Workflow/.plans/plan.md".',
13851389
},
13861390
sandboxPath: {
13871391
type: 'string',
@@ -3050,6 +3054,48 @@ export const ToolSearchToolRegex: ToolCatalogEntry = {
30503054
},
30513055
}
30523056

3057+
export const TouchPlan: ToolCatalogEntry = {
3058+
id: 'touch_plan',
3059+
name: 'touch_plan',
3060+
route: 'sim',
3061+
mode: 'async',
3062+
parameters: {
3063+
type: 'object',
3064+
properties: {
3065+
name: {
3066+
type: 'string',
3067+
description:
3068+
'Plan file name or relative path under .plans, e.g. "implementation.md" or "phase-1/implementation.md". If no extension is supplied, ".md" is appended.',
3069+
},
3070+
title: {
3071+
type: 'string',
3072+
description: 'Optional short user-visible label for the plan creation.',
3073+
},
3074+
workflowPath: {
3075+
type: 'string',
3076+
description:
3077+
'Canonical workflow VFS path, e.g. "workflows/My%20Workflow" or "workflows/Folder/My%20Workflow". Copy from glob/read output; do not use workflow IDs.',
3078+
},
3079+
},
3080+
required: ['workflowPath', 'name'],
3081+
},
3082+
resultSchema: {
3083+
type: 'object',
3084+
properties: {
3085+
data: {
3086+
type: 'object',
3087+
description:
3088+
'Contains id, name, vfsPath, backingVfsPath, and workflowId. Use vfsPath for follow-up workspace_file calls.',
3089+
},
3090+
message: { type: 'string', description: 'Human-readable outcome.' },
3091+
success: { type: 'boolean', description: 'Whether the plan file was created.' },
3092+
},
3093+
required: ['success', 'message'],
3094+
},
3095+
requiredPermission: 'write',
3096+
capabilities: ['file_output'],
3097+
}
3098+
30533099
export const UpdateJobHistory: ToolCatalogEntry = {
30543100
id: 'update_job_history',
30553101
name: 'update_job_history',
@@ -3882,6 +3928,7 @@ export const TOOL_CATALOG: Record<string, ToolCatalogEntry> = {
38823928
[Superagent.id]: Superagent,
38833929
[Table.id]: Table,
38843930
[ToolSearchToolRegex.id]: ToolSearchToolRegex,
3931+
[TouchPlan.id]: TouchPlan,
38853932
[UpdateJobHistory.id]: UpdateJobHistory,
38863933
[UpdateWorkspaceMcpServer.id]: UpdateWorkspaceMcpServer,
38873934
[UserMemory.id]: UserMemory,

apps/sim/lib/copilot/generated/tool-schemas-v1.ts

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
938938
path: {
939939
type: 'string',
940940
description:
941-
'Canonical VFS folder path, e.g. "files/Reports". By default this mounts at "/home/user/files/Reports".',
941+
'Canonical VFS folder path, e.g. "files/Reports" or "workflows/My%20Workflow/.plans". By default this mounts at "/home/user/{path}". Workflow alias directories mount under "/home/user/workflows/...".',
942942
},
943943
sandboxPath: {
944944
type: 'string',
@@ -958,7 +958,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
958958
path: {
959959
type: 'string',
960960
description:
961-
'Canonical VFS file path, e.g. "files/Reports/sales.csv". By default this mounts at "/home/user/files/Reports/sales.csv".',
961+
'Canonical VFS file path, e.g. "files/Reports/sales.csv" or "workflows/My%20Workflow/changelog.md". By default this mounts at "/home/user/{path}". Workflow alias paths mount under "/home/user/workflows/...".',
962962
},
963963
sandboxPath: {
964964
type: 'string',
@@ -1029,7 +1029,8 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
10291029
},
10301030
path: {
10311031
type: 'string',
1032-
description: 'Canonical destination VFS path, e.g. "files/Reports/chart.png".',
1032+
description:
1033+
'Canonical destination VFS path, e.g. "files/Reports/chart.png", "workflows/My%20Workflow/changelog.md", or "workflows/My%20Workflow/.plans/plan.md".',
10331034
},
10341035
sandboxPath: {
10351036
type: 'string',
@@ -1094,7 +1095,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
10941095
path: {
10951096
type: 'string',
10961097
description:
1097-
'Canonical VFS folder path, e.g. "files/Reports". By default this mounts at "/home/user/files/Reports".',
1098+
'Canonical VFS folder path, e.g. "files/Reports" or "workflows/My%20Workflow/.plans". By default this mounts at "/home/user/{path}". Workflow alias directories mount under "/home/user/workflows/...".',
10981099
},
10991100
sandboxPath: {
11001101
type: 'string',
@@ -1114,7 +1115,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
11141115
path: {
11151116
type: 'string',
11161117
description:
1117-
'Canonical VFS file path, e.g. "files/Reports/sales.csv". By default this mounts at "/home/user/files/Reports/sales.csv".',
1118+
'Canonical VFS file path, e.g. "files/Reports/sales.csv" or "workflows/My%20Workflow/changelog.md". By default this mounts at "/home/user/{path}". Workflow alias paths mount under "/home/user/workflows/...".',
11181119
},
11191120
sandboxPath: {
11201121
type: 'string',
@@ -1175,7 +1176,8 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
11751176
},
11761177
path: {
11771178
type: 'string',
1178-
description: 'Canonical destination VFS path, e.g. "files/Reports/chart.png".',
1179+
description:
1180+
'Canonical destination VFS path, e.g. "files/Reports/chart.png", "workflows/My%20Workflow/changelog.md", or "workflows/My%20Workflow/.plans/plan.md".',
11791181
},
11801182
sandboxPath: {
11811183
type: 'string',
@@ -2805,6 +2807,47 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
28052807
},
28062808
resultSchema: undefined,
28072809
},
2810+
['touch_plan']: {
2811+
parameters: {
2812+
type: 'object',
2813+
properties: {
2814+
name: {
2815+
type: 'string',
2816+
description:
2817+
'Plan file name or relative path under .plans, e.g. "implementation.md" or "phase-1/implementation.md". If no extension is supplied, ".md" is appended.',
2818+
},
2819+
title: {
2820+
type: 'string',
2821+
description: 'Optional short user-visible label for the plan creation.',
2822+
},
2823+
workflowPath: {
2824+
type: 'string',
2825+
description:
2826+
'Canonical workflow VFS path, e.g. "workflows/My%20Workflow" or "workflows/Folder/My%20Workflow". Copy from glob/read output; do not use workflow IDs.',
2827+
},
2828+
},
2829+
required: ['workflowPath', 'name'],
2830+
},
2831+
resultSchema: {
2832+
type: 'object',
2833+
properties: {
2834+
data: {
2835+
type: 'object',
2836+
description:
2837+
'Contains id, name, vfsPath, backingVfsPath, and workflowId. Use vfsPath for follow-up workspace_file calls.',
2838+
},
2839+
message: {
2840+
type: 'string',
2841+
description: 'Human-readable outcome.',
2842+
},
2843+
success: {
2844+
type: 'boolean',
2845+
description: 'Whether the plan file was created.',
2846+
},
2847+
},
2848+
required: ['success', 'message'],
2849+
},
2850+
},
28082851
['update_job_history']: {
28092852
parameters: {
28102853
type: 'object',

0 commit comments

Comments
 (0)