Skip to content

Commit b594378

Browse files
committed
chore(copilot): remove task VFS projection
1 parent fa25ef6 commit b594378

3 files changed

Lines changed: 2 additions & 150 deletions

File tree

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,7 @@ function unmountableNamespaceReason(filePath: string): string | null {
198198
if (path.startsWith('tables/')) {
199199
return 'tables are not mounted as files. Pass the table in inputs.tables instead and it is mounted as CSV.'
200200
}
201-
const namespace = /^(workflows|knowledgebases|components|environment|agent|tasks)\//.exec(
202-
path
203-
)?.[1]
201+
const namespace = /^(workflows|knowledgebases|components|environment|agent)\//.exec(path)?.[1]
204202
if (namespace) {
205203
return `${namespace}/ paths are VFS metadata views, not stored file bytes, so the sandbox cannot mount them. This path is correct — read or grep it and inline the values you need in code.`
206204
}

apps/sim/lib/copilot/vfs/serializers.ts

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,57 +1115,3 @@ export function serializeTriggerOverview(
11151115
lines.push('')
11161116
return lines.join('\n')
11171117
}
1118-
1119-
export function serializeTaskSession(task: {
1120-
id: string
1121-
title: string
1122-
messageCount: number
1123-
createdAt: Date
1124-
updatedAt: Date
1125-
}): string {
1126-
return [
1127-
`# ${task.title}`,
1128-
'',
1129-
`- **Chat ID:** ${task.id}`,
1130-
`- **Created:** ${task.createdAt.toISOString()}`,
1131-
`- **Updated:** ${task.updatedAt.toISOString()}`,
1132-
`- **Messages:** ${task.messageCount}`,
1133-
'',
1134-
].join('\n')
1135-
}
1136-
1137-
export function serializeTaskChat(rawMessages: unknown[]): string {
1138-
const filtered: { role: string; content: string }[] = []
1139-
1140-
for (const msg of rawMessages) {
1141-
if (!msg || typeof msg !== 'object') continue
1142-
const m = msg as Record<string, unknown>
1143-
const role = m.role as string | undefined
1144-
if (role !== 'user' && role !== 'assistant') continue
1145-
1146-
let content = ''
1147-
if (role === 'assistant' && Array.isArray(m.contentBlocks)) {
1148-
const textParts: string[] = []
1149-
for (const block of m.contentBlocks) {
1150-
if (
1151-
block &&
1152-
typeof block === 'object' &&
1153-
(block as any).type === 'text' &&
1154-
(block as any).content
1155-
) {
1156-
textParts.push((block as any).content)
1157-
}
1158-
}
1159-
content = textParts.join('')
1160-
}
1161-
1162-
if (!content && typeof m.content === 'string') {
1163-
content = m.content
1164-
}
1165-
1166-
if (!content) continue
1167-
filtered.push({ role, content })
1168-
}
1169-
1170-
return JSON.stringify(filtered, null, 2)
1171-
}

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

Lines changed: 1 addition & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { trace } from '@opentelemetry/api'
22
import { db } from '@sim/db'
33
import {
44
chat as chatTable,
5-
copilotChats,
65
customTools as customToolsTable,
76
document,
87
folder as folderTable,
@@ -17,7 +16,7 @@ import {
1716
} from '@sim/db/schema'
1817
import { createLogger } from '@sim/logger'
1918
import { toError } from '@sim/utils/errors'
20-
import { and, desc, eq, inArray, isNotNull, isNull, or, sql } from 'drizzle-orm'
19+
import { and, desc, eq, inArray, isNotNull, isNull, or } from 'drizzle-orm'
2120
import { listApiKeys } from '@/lib/api-key/service'
2221
import {
2322
buildWorkspaceContextMd,
@@ -79,8 +78,6 @@ import {
7978
serializeRecentExecutions,
8079
serializeSkill,
8180
serializeTableMeta,
82-
serializeTaskChat,
83-
serializeTaskSession,
8481
serializeTriggerOverview,
8582
serializeTriggerSchema,
8683
serializeVersions,
@@ -521,8 +518,6 @@ function getStaticComponentFiles(): Map<string, string> {
521518
* files/{name} (workspace file leaf; dynamic content on read)
522519
* files/{path}/{name}/style (dynamic — style extraction for .docx/.pptx/.pdf)
523520
* files/{path}/{name}/compiled-check (dynamic — compile generated source / validate diagrams, returns {ok,error?})
524-
* tasks/{title}/session.md
525-
* tasks/{title}/chat.json
526521
* custom-tools/{name}.json
527522
* environment/credentials.json
528523
* environment/api-keys.json
@@ -777,10 +772,6 @@ export class WorkspaceVFS {
777772
timed('workspace_row', getWorkspaceWithOwner(workspaceId)),
778773
timed('members', getUsersWithPermissions(workspaceId)),
779774
permissionConfigPromise,
780-
// Writes tasks/ files only — WORKSPACE.md has no Tasks section
781-
// (recent chats reorder every turn and would bust the cached
782-
// prompt prefix), so nothing is destructured from this one.
783-
timed('tasks', this.materializeTasks(workspaceId, userId)),
784775
])
785776

786777
const workspaceMdData = {
@@ -2116,89 +2107,6 @@ export class WorkspaceVFS {
21162107
}
21172108
}
21182109

2119-
/**
2120-
* Materialize mothership task chats as browsable conversation files under
2121-
* `tasks/{title}/`. Nothing is returned: the inventory deliberately has no
2122-
* Tasks section, so these files are reached through glob/read only.
2123-
*/
2124-
private async materializeTasks(workspaceId: string, userId: string): Promise<void> {
2125-
try {
2126-
const taskRows = await db
2127-
.select({
2128-
id: copilotChats.id,
2129-
title: copilotChats.title,
2130-
messageCount: sql<number>`COALESCE((
2131-
SELECT COUNT(*) FROM copilot_messages cm
2132-
WHERE cm.chat_id = ${copilotChats.id} AND cm.deleted_at IS NULL
2133-
), 0)`,
2134-
messages: sql<unknown[]>`COALESCE((
2135-
SELECT jsonb_agg(
2136-
jsonb_build_object(
2137-
'role', cm.content->>'role',
2138-
'content', cm.content->'content',
2139-
'contentBlocks', COALESCE((
2140-
SELECT jsonb_agg(jsonb_build_object('type', 'text', 'content', b.value->'content') ORDER BY b.ord)
2141-
FROM jsonb_array_elements(
2142-
CASE WHEN jsonb_typeof(cm.content->'contentBlocks') = 'array'
2143-
THEN cm.content->'contentBlocks'
2144-
ELSE '[]'::jsonb
2145-
END
2146-
) WITH ORDINALITY AS b(value, ord)
2147-
WHERE b.value->>'type' = 'text'
2148-
), '[]'::jsonb)
2149-
)
2150-
ORDER BY cm.seq ASC NULLS LAST, cm.created_at ASC, cm.id ASC
2151-
)
2152-
FROM copilot_messages cm
2153-
WHERE cm.chat_id = ${copilotChats.id}
2154-
AND cm.deleted_at IS NULL
2155-
AND cm.content->>'role' IN ('user', 'assistant')
2156-
), '[]'::jsonb)`,
2157-
createdAt: copilotChats.createdAt,
2158-
updatedAt: copilotChats.updatedAt,
2159-
})
2160-
.from(copilotChats)
2161-
.where(
2162-
and(
2163-
eq(copilotChats.workspaceId, workspaceId),
2164-
eq(copilotChats.userId, userId),
2165-
eq(copilotChats.type, 'mothership'),
2166-
isNull(copilotChats.deletedAt)
2167-
)
2168-
)
2169-
.orderBy(desc(copilotChats.updatedAt))
2170-
.limit(5)
2171-
2172-
for (const task of taskRows) {
2173-
const title = task.title || 'Untitled task'
2174-
const safeName = sanitizeName(title)
2175-
const prefix = `tasks/${safeName}/`
2176-
const messages = Array.isArray(task.messages) ? task.messages : []
2177-
const messageCount = Number(task.messageCount) || 0
2178-
2179-
this.files.set(
2180-
`${prefix}session.md`,
2181-
serializeTaskSession({
2182-
id: task.id,
2183-
title,
2184-
messageCount,
2185-
createdAt: task.createdAt,
2186-
updatedAt: task.updatedAt,
2187-
})
2188-
)
2189-
2190-
if (messages.length > 0) {
2191-
this.files.set(`${prefix}chat.json`, serializeTaskChat(messages))
2192-
}
2193-
}
2194-
} catch (err) {
2195-
logger.warn('Failed to materialize tasks', {
2196-
workspaceId,
2197-
error: toError(err).message,
2198-
})
2199-
}
2200-
}
2201-
22022110
private async materializeRecentlyDeleted(workspaceId: string, userId: string): Promise<void> {
22032111
try {
22042112
const [

0 commit comments

Comments
 (0)