@@ -58,6 +58,7 @@ import {
5858 getAccessibleOAuthCredentials ,
5959} from '@/lib/credentials/environment'
6060import { getPersonalAndWorkspaceEnv } from '@/lib/environment/utils'
61+ import { runSandboxTask , SandboxUserCodeError } from '@/lib/execution/sandbox/run-task'
6162import { getKnowledgeBases } from '@/lib/knowledge/service'
6263import { listTables } from '@/lib/table/service'
6364import {
@@ -79,6 +80,7 @@ import {
7980} from '@/lib/workspaces/permissions/utils'
8081import { getAllBlocks } from '@/blocks/registry'
8182import { CONNECTOR_REGISTRY } from '@/connectors/registry'
83+ import type { SandboxTaskId } from '@/sandbox-tasks/registry'
8284import { tools as toolRegistry } from '@/tools/registry'
8385import { getLatestVersionTools , stripVersionSuffix } from '@/tools/utils'
8486import { TRIGGER_REGISTRY } from '@/triggers/registry'
@@ -313,6 +315,8 @@ function getStaticComponentFiles(): Map<string, string> {
313315 * tables/{name}/meta.json
314316 * files/{name}/meta.json
315317 * files/by-id/{id}/meta.json
318+ * files/by-id/{id}/style (dynamic — OOXML theme/font extraction for .docx/.pptx)
319+ * files/by-id/{id}/compiled-check (dynamic — compile JS source via sandbox, returns {ok,error?})
316320 * jobs/{title}/meta.json
317321 * jobs/{title}/history.json
318322 * jobs/{title}/executions.json
@@ -451,10 +455,52 @@ export class WorkspaceVFS {
451455 /**
452456 * Attempt to read dynamic workspace file content from storage.
453457 * Handles images (base64), parseable documents (PDF, etc.), and text files.
454- * Also handles `files/by-id/{id}/style` for OOXML theme/style extraction.
458+ * Also handles:
459+ * `files/by-id/{id}/style` — OOXML theme/style extraction (.docx / .pptx only)
460+ * `files/by-id/{id}/compiled-check` — sandbox compile check for JS-source binary files
455461 * Returns null if the path doesn't match `files/{name}` / `files/by-id/{id}` or the file isn't found.
456462 */
457463 async readFileContent ( path : string ) : Promise < FileReadResult | null > {
464+ // Handle compiled-check path: files/by-id/{id}/compiled-check
465+ const compiledCheckMatch = path . match ( / ^ f i l e s \/ b y - i d \/ ( [ ^ / ] + ) \/ c o m p i l e d - c h e c k $ / )
466+ if ( compiledCheckMatch ) {
467+ const fileId = compiledCheckMatch [ 1 ]
468+ try {
469+ const record = await getWorkspaceFile ( this . _workspaceId , fileId )
470+ if ( ! record ) return null
471+ const ext = record . name . split ( '.' ) . pop ( ) ?. toLowerCase ( ) ?? ''
472+ const EXT_TASK : Record < string , SandboxTaskId > = {
473+ docx : 'docx-generate' ,
474+ pptx : 'pptx-generate' ,
475+ pdf : 'pdf-generate' ,
476+ }
477+ const taskId = EXT_TASK [ ext ]
478+ if ( ! taskId ) return null
479+ const buffer = await downloadWorkspaceFile ( record )
480+ const code = buffer . toString ( 'utf-8' )
481+ let result : { ok : boolean ; error ?: string ; errorName ?: string }
482+ try {
483+ await runSandboxTask ( taskId , { code, workspaceId : this . _workspaceId } )
484+ result = { ok : true }
485+ } catch ( err ) {
486+ if ( err instanceof SandboxUserCodeError ) {
487+ result = { ok : false , error : toError ( err ) . message , errorName : err . name }
488+ } else {
489+ throw err
490+ }
491+ }
492+ const json = JSON . stringify ( result )
493+ return { content : json , totalLines : 1 }
494+ } catch ( err ) {
495+ logger . warn ( 'Compiled check failed via VFS' , {
496+ workspaceId : this . _workspaceId ,
497+ fileId,
498+ error : toError ( err ) . message ,
499+ } )
500+ return null
501+ }
502+ }
503+
458504 // Handle style extraction path: files/by-id/{id}/style
459505 const styleMatch = path . match ( / ^ f i l e s \/ b y - i d \/ ( [ ^ / ] + ) \/ s t y l e $ / )
460506 if ( styleMatch ) {
0 commit comments