Skip to content

Commit 0a2f745

Browse files
committed
Fixes
1 parent 9ac1e33 commit 0a2f745

3 files changed

Lines changed: 43 additions & 20 deletions

File tree

apps/sim/lib/copilot/tools/server/files/doc-compile.ts

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,19 @@ const DOC_COMPILE_TIMEOUT_MS = 120_000
191191
// them). Indented at column 0 so it concatenates cleanly after the user's script.
192192
const XLSX_RECALC_SNIPPET = `
193193
import subprocess as __sim_sp, shutil as __sim_sh, os as __sim_os
194-
__sim_os.makedirs("/home/user/__recalc", exist_ok=True)
195-
__sim_sp.run(
196-
["soffice", "--headless", "--convert-to", "xlsx", "--outdir", "/home/user/__recalc", "/home/user/output.xlsx"],
197-
check=True, timeout=120, capture_output=True,
198-
)
199-
__sim_sh.move("/home/user/__recalc/output.xlsx", "/home/user/output.xlsx")
194+
# Best-effort: bake cached formula values via LibreOffice. If recalc fails
195+
# (soffice crash/timeout/unsupported), keep the openpyxl workbook as-is — it's
196+
# still a valid file (formulas just lack cached values). Never fail the user's
197+
# compile over an infra recalc failure.
198+
try:
199+
__sim_os.makedirs("/home/user/__recalc", exist_ok=True)
200+
__sim_sp.run(
201+
["soffice", "--headless", "--convert-to", "xlsx", "--outdir", "/home/user/__recalc", "/home/user/output.xlsx"],
202+
check=True, timeout=120, capture_output=True,
203+
)
204+
__sim_sh.move("/home/user/__recalc/output.xlsx", "/home/user/output.xlsx")
205+
except Exception as __sim_recalc_err:
206+
print("xlsx recalc skipped:", __sim_recalc_err)
200207
`.trim()
201208

202209
interface CompileArgs {
@@ -324,19 +331,27 @@ ${finalize}
324331
outputSandboxPath,
325332
})
326333

327-
// Only treat the run as a success when the script reached the finalizer
328-
// (__DOC_OK__) AND produced the output file. A script that writes the file then
329-
// throws would otherwise persist a partial/corrupt artifact (mirrors the Python
330-
// path, which checks result.error first).
334+
// Success requires the script to reach the finalizer (__DOC_OK__) AND produce
335+
// the output file — a script that writes then throws must not persist a
336+
// partial/corrupt artifact (mirrors the Python path).
331337
const out = `${result.stdout || ''}\n${result.error || ''}`
332-
const failed = !!result.error || !out.includes('__DOC_OK__')
333-
if (!failed && result.exportedFileContent) {
338+
const errMatch = out.match(/__DOC_ERR__([\s\S]*)/)
339+
if (out.includes('__DOC_OK__') && result.exportedFileContent) {
334340
return Buffer.from(result.exportedFileContent, 'base64')
335341
}
336-
// Capture the full (possibly multi-line) error message after the marker.
337-
const m = out.match(/__DOC_ERR__([\s\S]*)/)
338-
const msg = m?.[1]?.trim() || result.error || 'the script produced no output'
339-
throw new DocCompileUserError(`${ext.toUpperCase()} generation failed: ${msg}`)
342+
if (errMatch) {
343+
// The script ran and threw — a user-code error the agent should fix.
344+
throw new DocCompileUserError(
345+
`${ext.toUpperCase()} generation failed: ${errMatch[1]?.trim() || 'unknown error'}`
346+
)
347+
}
348+
// No __DOC_OK__ and no __DOC_ERR__ → node never completed (sandbox died, command
349+
// failure, or the output couldn't be read). That's a retriable system error, not
350+
// the agent's code — surface it as a plain Error so callers don't tell the agent
351+
// to "fix its code".
352+
throw new Error(
353+
`${ext.toUpperCase()} compile did not complete in the sandbox: ${result.error || 'no output produced'}`
354+
)
340355
}
341356

342357
/**

apps/sim/lib/copilot/tools/server/files/doc-extract.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ elif ext == "xlsx":
8282
out.append(",".join("" if v is None else str(v) for v in row))
8383
8484
# Bound the transferred text so a decompression bomb can't return gigabytes.
85-
text = "\\n".join(out)[:220000]
85+
# Headroom over MAX_EXTRACT_CHARS so the TS-side truncation flag can still fire.
86+
text = "\\n".join(out)[:${MAX_EXTRACT_CHARS + 20000}]
8687
print("__SIM_RESULT__=" + json.dumps({"text": text}))
8788
`.trim()
8889

apps/sim/lib/copilot/tools/server/files/workspace-file.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,23 @@ import {
2727
performRenameWorkspaceFile,
2828
} from '@/lib/workspace-files/orchestration'
2929
import type { SandboxTaskId } from '@/sandbox-tasks/registry'
30-
import { compileDoc, DocCompileUserError, getE2BDocFormat } from './doc-compile'
30+
import {
31+
compileDoc,
32+
DOCXJS_SOURCE_MIME,
33+
DocCompileUserError,
34+
getE2BDocFormat,
35+
PPTXGENJS_SOURCE_MIME,
36+
} from './doc-compile'
3137
import { storeFileIntent } from './file-intent-store'
3238

3339
const logger = createLogger('WorkspaceFileServerTool')
3440

3541
const PPTX_MIME = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
3642
const DOCX_MIME = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
3743
const PDF_MIME = 'application/pdf'
38-
const PPTX_SOURCE_MIME = 'text/x-pptxgenjs'
39-
const DOCX_SOURCE_MIME = 'text/x-docxjs'
44+
// Single source of the JS source MIMEs is doc-compile.ts; reuse to avoid drift.
45+
const PPTX_SOURCE_MIME = PPTXGENJS_SOURCE_MIME
46+
const DOCX_SOURCE_MIME = DOCXJS_SOURCE_MIME
4047
const PDF_SOURCE_MIME = 'text/x-pdflibjs'
4148

4249
type WorkspaceFileOperation = 'create' | 'append' | 'update' | 'delete' | 'rename' | 'patch'

0 commit comments

Comments
 (0)