mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
Fix files
This commit is contained in:
@@ -16,10 +16,10 @@ import {
|
||||
workflowMcpServer,
|
||||
workflowMcpTool,
|
||||
workspaceEnvironment,
|
||||
workspaceFiles,
|
||||
} from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, count, desc, eq, isNull } from 'drizzle-orm'
|
||||
import { generateWorkspaceContext } from '@/lib/copilot/workspace-context'
|
||||
import type { DirEntry, GrepMatch, GrepOptions, ReadResult } from '@/lib/copilot/vfs/operations'
|
||||
import * as ops from '@/lib/copilot/vfs/operations'
|
||||
import type { DeploymentData } from '@/lib/copilot/vfs/serializers'
|
||||
@@ -38,6 +38,7 @@ import {
|
||||
serializeTableMeta,
|
||||
serializeWorkflowMeta,
|
||||
} from '@/lib/copilot/vfs/serializers'
|
||||
import { listWorkspaceFiles } from '@/lib/uploads/contexts/workspace'
|
||||
import { hasWorkflowChanged } from '@/lib/workflows/comparison'
|
||||
import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils'
|
||||
import { sanitizeForCopilot } from '@/lib/workflows/sanitization/json-sanitizer'
|
||||
@@ -184,6 +185,7 @@ function getStaticComponentFiles(): Map<string, string> {
|
||||
* Virtual Filesystem that materializes workspace data into an in-memory Map.
|
||||
*
|
||||
* Structure:
|
||||
* WORKSPACE.md — workspace identity, members, inventory (auto-generated)
|
||||
* workflows/{name}/meta.json
|
||||
* workflows/{name}/state.json (sanitized blocks with embedded connections)
|
||||
* workflows/{name}/executions.json
|
||||
@@ -217,6 +219,9 @@ export class WorkspaceVFS {
|
||||
this.materializeFiles(workspaceId),
|
||||
this.materializeEnvironment(workspaceId, userId),
|
||||
this.materializeCustomTools(workspaceId),
|
||||
generateWorkspaceContext(workspaceId, userId).then((content) => {
|
||||
this.files.set('WORKSPACE.md', content)
|
||||
}),
|
||||
])
|
||||
|
||||
// Merge static component files
|
||||
@@ -460,25 +465,16 @@ export class WorkspaceVFS {
|
||||
*/
|
||||
private async materializeFiles(workspaceId: string): Promise<void> {
|
||||
try {
|
||||
const fileRows = await db
|
||||
.select({
|
||||
id: workspaceFiles.id,
|
||||
originalName: workspaceFiles.originalName,
|
||||
contentType: workspaceFiles.contentType,
|
||||
size: workspaceFiles.size,
|
||||
uploadedAt: workspaceFiles.uploadedAt,
|
||||
})
|
||||
.from(workspaceFiles)
|
||||
.where(eq(workspaceFiles.workspaceId, workspaceId))
|
||||
const files = await listWorkspaceFiles(workspaceId)
|
||||
|
||||
for (const file of fileRows) {
|
||||
const safeName = sanitizeName(file.originalName)
|
||||
for (const file of files) {
|
||||
const safeName = sanitizeName(file.name)
|
||||
this.files.set(
|
||||
`files/${safeName}/meta.json`,
|
||||
serializeFileMeta({
|
||||
id: file.id,
|
||||
name: file.originalName,
|
||||
contentType: file.contentType,
|
||||
name: file.name,
|
||||
contentType: file.type,
|
||||
size: file.size,
|
||||
uploadedAt: file.uploadedAt,
|
||||
})
|
||||
|
||||
@@ -5,23 +5,35 @@ import {
|
||||
userTableDefinitions,
|
||||
userTableRows,
|
||||
workflow,
|
||||
workspaceFiles,
|
||||
workspace,
|
||||
} from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, count, eq, isNull } from 'drizzle-orm'
|
||||
import { listWorkspaceFiles } from '@/lib/uploads/contexts/workspace'
|
||||
import { getUsersWithPermissions } from '@/lib/workspaces/permissions/utils'
|
||||
|
||||
const logger = createLogger('WorkspaceContext')
|
||||
|
||||
/**
|
||||
* Generate WORKSPACE.md content from actual database state.
|
||||
* This is injected into the system prompt — the LLM never writes it directly.
|
||||
* Auto-injected into the system prompt and served as a top-level VFS file.
|
||||
* The LLM never writes it directly.
|
||||
*/
|
||||
export async function generateWorkspaceContext(
|
||||
workspaceId: string,
|
||||
userId: string
|
||||
): Promise<string> {
|
||||
try {
|
||||
const [workflows, kbs, tables, files, credentials] = await Promise.all([
|
||||
const [wsRow, members, workflows, kbs, tables, files, credentials] = await Promise.all([
|
||||
db
|
||||
.select({ id: workspace.id, name: workspace.name, ownerId: workspace.ownerId })
|
||||
.from(workspace)
|
||||
.where(eq(workspace.id, workspaceId))
|
||||
.limit(1)
|
||||
.then((rows) => rows[0] ?? null),
|
||||
|
||||
getUsersWithPermissions(workspaceId),
|
||||
|
||||
db
|
||||
.select({
|
||||
id: workflow.id,
|
||||
@@ -51,15 +63,7 @@ export async function generateWorkspaceContext(
|
||||
.from(userTableDefinitions)
|
||||
.where(eq(userTableDefinitions.workspaceId, workspaceId)),
|
||||
|
||||
db
|
||||
.select({
|
||||
id: workspaceFiles.id,
|
||||
originalName: workspaceFiles.originalName,
|
||||
contentType: workspaceFiles.contentType,
|
||||
size: workspaceFiles.size,
|
||||
})
|
||||
.from(workspaceFiles)
|
||||
.where(eq(workspaceFiles.workspaceId, workspaceId)),
|
||||
listWorkspaceFiles(workspaceId),
|
||||
|
||||
db
|
||||
.select({
|
||||
@@ -72,6 +76,22 @@ export async function generateWorkspaceContext(
|
||||
|
||||
const sections: string[] = []
|
||||
|
||||
// Workspace identity
|
||||
if (wsRow) {
|
||||
sections.push(
|
||||
`## Workspace\n- **Name**: ${wsRow.name}\n- **ID**: ${wsRow.id}\n- **Owner**: ${wsRow.ownerId}`
|
||||
)
|
||||
}
|
||||
|
||||
// Members & permissions
|
||||
if (members.length > 0) {
|
||||
const lines = members.map((m) => {
|
||||
const display = m.name ? `${m.name} (${m.email})` : m.email
|
||||
return `- ${display} — ${m.permissionType}`
|
||||
})
|
||||
sections.push(`## Members\n${lines.join('\n')}`)
|
||||
}
|
||||
|
||||
// Workflows
|
||||
if (workflows.length > 0) {
|
||||
const lines = workflows.map((wf) => {
|
||||
@@ -83,9 +103,9 @@ export async function generateWorkspaceContext(
|
||||
if (flags.length > 0) parts[0] += ` — ${flags.join(', ')}`
|
||||
return parts.join('\n')
|
||||
})
|
||||
sections.push(`## Workflows\n${lines.join('\n')}`)
|
||||
sections.push(`## Workflows (${workflows.length})\n${lines.join('\n')}`)
|
||||
} else {
|
||||
sections.push('## Workflows\n(none)')
|
||||
sections.push('## Workflows (0)\n(none)')
|
||||
}
|
||||
|
||||
// Knowledge Bases
|
||||
@@ -95,9 +115,9 @@ export async function generateWorkspaceContext(
|
||||
if (kb.description) line += ` — ${kb.description}`
|
||||
return line
|
||||
})
|
||||
sections.push(`## Knowledge Bases\n${lines.join('\n')}`)
|
||||
sections.push(`## Knowledge Bases (${kbs.length})\n${lines.join('\n')}`)
|
||||
} else {
|
||||
sections.push('## Knowledge Bases\n(none)')
|
||||
sections.push('## Knowledge Bases (0)\n(none)')
|
||||
}
|
||||
|
||||
// Tables (live row counts)
|
||||
@@ -116,19 +136,17 @@ export async function generateWorkspaceContext(
|
||||
if (t.description) line += `, ${t.description}`
|
||||
return line
|
||||
})
|
||||
sections.push(`## Tables\n${lines.join('\n')}`)
|
||||
sections.push(`## Tables (${tables.length})\n${lines.join('\n')}`)
|
||||
} else {
|
||||
sections.push('## Tables\n(none)')
|
||||
sections.push('## Tables (0)\n(none)')
|
||||
}
|
||||
|
||||
// Files
|
||||
if (files.length > 0) {
|
||||
const lines = files.map(
|
||||
(f) => `- **${f.originalName}** (${f.contentType}, ${formatSize(f.size)})`
|
||||
)
|
||||
sections.push(`## Files\n${lines.join('\n')}`)
|
||||
const lines = files.map((f) => `- **${f.name}** (${f.type}, ${formatSize(f.size)})`)
|
||||
sections.push(`## Files (${files.length})\n${lines.join('\n')}`)
|
||||
} else {
|
||||
sections.push('## Files\n(none)')
|
||||
sections.push('## Files (0)\n(none)')
|
||||
}
|
||||
|
||||
// Credentials
|
||||
@@ -145,7 +163,7 @@ export async function generateWorkspaceContext(
|
||||
workspaceId,
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
})
|
||||
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)'
|
||||
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)'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user