Skip to content

Commit 0249ca1

Browse files
committed
Fix files
1 parent 553c376 commit 0249ca1

2 files changed

Lines changed: 53 additions & 39 deletions

File tree

apps/sim/lib/copilot/vfs/workspace-vfs.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ import {
1616
workflowMcpServer,
1717
workflowMcpTool,
1818
workspaceEnvironment,
19-
workspaceFiles,
2019
} from '@sim/db/schema'
2120
import { createLogger } from '@sim/logger'
2221
import { and, count, desc, eq, isNull } from 'drizzle-orm'
22+
import { generateWorkspaceContext } from '@/lib/copilot/workspace-context'
2323
import type { DirEntry, GrepMatch, GrepOptions, ReadResult } from '@/lib/copilot/vfs/operations'
2424
import * as ops from '@/lib/copilot/vfs/operations'
2525
import type { DeploymentData } from '@/lib/copilot/vfs/serializers'
@@ -38,6 +38,7 @@ import {
3838
serializeTableMeta,
3939
serializeWorkflowMeta,
4040
} from '@/lib/copilot/vfs/serializers'
41+
import { listWorkspaceFiles } from '@/lib/uploads/contexts/workspace'
4142
import { hasWorkflowChanged } from '@/lib/workflows/comparison'
4243
import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils'
4344
import { sanitizeForCopilot } from '@/lib/workflows/sanitization/json-sanitizer'
@@ -184,6 +185,7 @@ function getStaticComponentFiles(): Map<string, string> {
184185
* Virtual Filesystem that materializes workspace data into an in-memory Map.
185186
*
186187
* Structure:
188+
* WORKSPACE.md — workspace identity, members, inventory (auto-generated)
187189
* workflows/{name}/meta.json
188190
* workflows/{name}/state.json (sanitized blocks with embedded connections)
189191
* workflows/{name}/executions.json
@@ -217,6 +219,9 @@ export class WorkspaceVFS {
217219
this.materializeFiles(workspaceId),
218220
this.materializeEnvironment(workspaceId, userId),
219221
this.materializeCustomTools(workspaceId),
222+
generateWorkspaceContext(workspaceId, userId).then((content) => {
223+
this.files.set('WORKSPACE.md', content)
224+
}),
220225
])
221226

222227
// Merge static component files
@@ -460,25 +465,16 @@ export class WorkspaceVFS {
460465
*/
461466
private async materializeFiles(workspaceId: string): Promise<void> {
462467
try {
463-
const fileRows = await db
464-
.select({
465-
id: workspaceFiles.id,
466-
originalName: workspaceFiles.originalName,
467-
contentType: workspaceFiles.contentType,
468-
size: workspaceFiles.size,
469-
uploadedAt: workspaceFiles.uploadedAt,
470-
})
471-
.from(workspaceFiles)
472-
.where(eq(workspaceFiles.workspaceId, workspaceId))
468+
const files = await listWorkspaceFiles(workspaceId)
473469

474-
for (const file of fileRows) {
475-
const safeName = sanitizeName(file.originalName)
470+
for (const file of files) {
471+
const safeName = sanitizeName(file.name)
476472
this.files.set(
477473
`files/${safeName}/meta.json`,
478474
serializeFileMeta({
479475
id: file.id,
480-
name: file.originalName,
481-
contentType: file.contentType,
476+
name: file.name,
477+
contentType: file.type,
482478
size: file.size,
483479
uploadedAt: file.uploadedAt,
484480
})

apps/sim/lib/copilot/workspace-context.ts

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,35 @@ import {
55
userTableDefinitions,
66
userTableRows,
77
workflow,
8-
workspaceFiles,
8+
workspace,
99
} from '@sim/db/schema'
1010
import { createLogger } from '@sim/logger'
1111
import { and, count, eq, isNull } from 'drizzle-orm'
12+
import { listWorkspaceFiles } from '@/lib/uploads/contexts/workspace'
13+
import { getUsersWithPermissions } from '@/lib/workspaces/permissions/utils'
1214

1315
const logger = createLogger('WorkspaceContext')
1416

1517
/**
1618
* Generate WORKSPACE.md content from actual database state.
17-
* This is injected into the system prompt — the LLM never writes it directly.
19+
* Auto-injected into the system prompt and served as a top-level VFS file.
20+
* The LLM never writes it directly.
1821
*/
1922
export async function generateWorkspaceContext(
2023
workspaceId: string,
2124
userId: string
2225
): Promise<string> {
2326
try {
24-
const [workflows, kbs, tables, files, credentials] = await Promise.all([
27+
const [wsRow, members, workflows, kbs, tables, files, credentials] = await Promise.all([
28+
db
29+
.select({ id: workspace.id, name: workspace.name, ownerId: workspace.ownerId })
30+
.from(workspace)
31+
.where(eq(workspace.id, workspaceId))
32+
.limit(1)
33+
.then((rows) => rows[0] ?? null),
34+
35+
getUsersWithPermissions(workspaceId),
36+
2537
db
2638
.select({
2739
id: workflow.id,
@@ -51,15 +63,7 @@ export async function generateWorkspaceContext(
5163
.from(userTableDefinitions)
5264
.where(eq(userTableDefinitions.workspaceId, workspaceId)),
5365

54-
db
55-
.select({
56-
id: workspaceFiles.id,
57-
originalName: workspaceFiles.originalName,
58-
contentType: workspaceFiles.contentType,
59-
size: workspaceFiles.size,
60-
})
61-
.from(workspaceFiles)
62-
.where(eq(workspaceFiles.workspaceId, workspaceId)),
66+
listWorkspaceFiles(workspaceId),
6367

6468
db
6569
.select({
@@ -72,6 +76,22 @@ export async function generateWorkspaceContext(
7276

7377
const sections: string[] = []
7478

79+
// Workspace identity
80+
if (wsRow) {
81+
sections.push(
82+
`## Workspace\n- **Name**: ${wsRow.name}\n- **ID**: ${wsRow.id}\n- **Owner**: ${wsRow.ownerId}`
83+
)
84+
}
85+
86+
// Members & permissions
87+
if (members.length > 0) {
88+
const lines = members.map((m) => {
89+
const display = m.name ? `${m.name} (${m.email})` : m.email
90+
return `- ${display}${m.permissionType}`
91+
})
92+
sections.push(`## Members\n${lines.join('\n')}`)
93+
}
94+
7595
// Workflows
7696
if (workflows.length > 0) {
7797
const lines = workflows.map((wf) => {
@@ -83,9 +103,9 @@ export async function generateWorkspaceContext(
83103
if (flags.length > 0) parts[0] += ` — ${flags.join(', ')}`
84104
return parts.join('\n')
85105
})
86-
sections.push(`## Workflows\n${lines.join('\n')}`)
106+
sections.push(`## Workflows (${workflows.length})\n${lines.join('\n')}`)
87107
} else {
88-
sections.push('## Workflows\n(none)')
108+
sections.push('## Workflows (0)\n(none)')
89109
}
90110

91111
// Knowledge Bases
@@ -95,9 +115,9 @@ export async function generateWorkspaceContext(
95115
if (kb.description) line += ` — ${kb.description}`
96116
return line
97117
})
98-
sections.push(`## Knowledge Bases\n${lines.join('\n')}`)
118+
sections.push(`## Knowledge Bases (${kbs.length})\n${lines.join('\n')}`)
99119
} else {
100-
sections.push('## Knowledge Bases\n(none)')
120+
sections.push('## Knowledge Bases (0)\n(none)')
101121
}
102122

103123
// Tables (live row counts)
@@ -116,19 +136,17 @@ export async function generateWorkspaceContext(
116136
if (t.description) line += `, ${t.description}`
117137
return line
118138
})
119-
sections.push(`## Tables\n${lines.join('\n')}`)
139+
sections.push(`## Tables (${tables.length})\n${lines.join('\n')}`)
120140
} else {
121-
sections.push('## Tables\n(none)')
141+
sections.push('## Tables (0)\n(none)')
122142
}
123143

124144
// Files
125145
if (files.length > 0) {
126-
const lines = files.map(
127-
(f) => `- **${f.originalName}** (${f.contentType}, ${formatSize(f.size)})`
128-
)
129-
sections.push(`## Files\n${lines.join('\n')}`)
146+
const lines = files.map((f) => `- **${f.name}** (${f.type}, ${formatSize(f.size)})`)
147+
sections.push(`## Files (${files.length})\n${lines.join('\n')}`)
130148
} else {
131-
sections.push('## Files\n(none)')
149+
sections.push('## Files (0)\n(none)')
132150
}
133151

134152
// Credentials
@@ -145,7 +163,7 @@ export async function generateWorkspaceContext(
145163
workspaceId,
146164
error: err instanceof Error ? err.message : String(err),
147165
})
148-
return '## Workflows\n(unavailable)\n\n## Knowledge Bases\n(unavailable)\n\n## Tables\n(unavailable)\n\n## Files\n(unavailable)\n\n## Credentials\n(unavailable)'
166+
return '## Workspace\n(unavailable)\n\n## Workflows\n(unavailable)\n\n## Knowledge Bases\n(unavailable)\n\n## Tables\n(unavailable)\n\n## Files\n(unavailable)\n\n## Credentials\n(unavailable)'
149167
}
150168
}
151169

0 commit comments

Comments
 (0)