v0.6.50: ppt/doc/pdf worker isolation, docs, chat, sidebar improvements#4224
v0.6.50: ppt/doc/pdf worker isolation, docs, chat, sidebar improvements#4224icecrasher321 merged 9 commits intomainfrom
Conversation
…in all resource pickers (#4215) * improvement(sidebar): interleave folders and workflows by sort order in all resource pickers - Merge folder/workflow submenus into a single Workflows tree sorted by sortOrder in both the @ plus-menu and add-resource dropdowns - Widen both dropdowns from 240px to 320px and remove type labels from search results - Fix isOpen/onSwitch regression: WorkflowFolderTreeItems now forwards node.isOpen so already-open tabs are switched to rather than duplicated - Apply same interleaved sortOrder ordering to the collapsed sidebar's root-level folder+workflow list * fix(add-resource-dropdown): align sort tiebreaker with compareByOrder, document empty-folder omission Use id.localeCompare as the sort tiebreaker in buildWorkflowFolderTree to match the sidebar's compareByOrder fallback (sortOrder → id) instead of name. Add a comment clarifying that empty folders are intentionally omitted from the tree view. * chore: remove extraneous inline comment
…atterns (#4214) * improvement(utils): add shared utility functions and replace inline patterns Add sleep, toError, safeJsonParse, isNonNull helpers and invariant/assertNever assertions. Replace all inline implementations across the codebase with these shared utilities for consistency. Zero behavioral changes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(agiloft): remove import type from .server module to fix client bundle build Turbopack resolves .server.ts modules even for type-only imports, pulling dns/promises into client bundles. Define SecureFetchResponse locally instead. * fix(agiloft): revert to client-safe imports to fix build The SSRF upgrade to input-validation.server introduced dns/promises into client bundles via tools/registry.ts. Revert to the original client-safe validateExternalUrl + fetch. The SSRF DNS-pinning upgrade for agiloft directExecution should be done via API routes in a separate PR. * feat(agiloft): add API route for retrieve_attachment, matching established file patterns Convert retrieve_attachment from directExecution to standard API route pattern, consistent with Slack download and Google Drive download tools. - Create /api/tools/agiloft/retrieve with DNS validation, auth lifecycle, and base64 file response matching the { file: { name, mimeType, data, size } } convention - Update retrieve_attachment tool to use request/transformResponse instead of directExecution, removing the dependency on executeAgiloftRequest from the tool definition - File output type: 'file' enables FileToolProcessor to store downloaded files in execution filesystem automatically * shopify * fix(agiloft): add optional flag to nullable lock record block outputs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(agiloft): revert optional flag on block outputs — property only exists on tool outputs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore(utils): remove unused utilities (asserts, safeJsonParse, isNonNull) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add pics and videos for mothership * Minimal edit
…ntity (#4218) * fix(docs): preserve gif playback position in lightbox and clean up ui components - Capture currentTime on click and seek lightbox video to match using useLayoutEffect - Convert lightboxStartTime from useState to useRef (no independent render needed) - Apply same fix to ActionVideo in action-media.tsx - Remove dead AnimatedBlocks component (zero imports) - Fix language-dropdown to derive currentLang during render instead of mirroring into state via effect - Replace template literals with cn() in faq.tsx and video.tsx * fix(chat): prevent @-mention menu focus loss and stabilize render identity Radix DropdownMenu's FocusScope was restoring focus from the search input to the content root whenever registered menu items mounted or unmounted inside the content, interrupting typing after a keystroke or two. - Keep the default tree always mounted under `hidden` instead of swapping subtrees when the filter activates. - Render filtered results as plain <button role="menuitem"> so they do not participate in Radix's menu Collection. - Add activeIndex state with ArrowUp/Down/Enter keyboard nav, mouse-hover sync, and scrollIntoView so the highlighted row stays visible and users can see what Enter will select. While tracing the cascade that compounded the bug: - Hoist `select` in useWorkflowMap / useWorkspacesQuery / useFolderMap to module scope so TanStack Query caches the select result across renders. - Guard setSelectedContexts([]) with a functional updater that bails out when already empty, preventing a fresh [] literal from invalidating consumers that key on reference identity. - Wrap WorkspaceHeader in React.memo so it bails out on parent renders once its (now-stable) props are unchanged. Made-with: Cursor * remove extraneous comments * cleanup * fix(chat): apply same setState bail-out to clearContexts for consistency Matches the invariant we already established for the message effect: calling setSelectedContexts([]) against an already-empty array emits a fresh [] reference (Object.is bails out are not reference-level), which cascades through consumers that key on selectedContexts identity. clearContexts is part of the hook's public API so callers can't know whether the list is empty — make it safe for them. Made-with: Cursor
…esizeObserver (#4220) Replaces MutationObserver on document.documentElement (watching CSS variable changes) + window resize listener with a ResizeObserver on the terminal element itself. The terminal now measures its own rendered width directly, so it responds correctly to all layout changes — sidebar, workflow panel, and mothership resize — without indirect CSS variable plumbing or cross-component coupling.
…r recommended models (#4213) * improvement(mothership): agent model dropdown validations, recommendation system * mark a few more models: * remove regex based checks' * remove dead code * remove inherited reseller flags * fix note * address bugbot comments * code cleanup
…ox (#4217) * fix(execution): run pptx/docx/pdf generation inside isolated-vm sandbox Retires the legacy doc-worker.cjs / pptx-worker.cjs pipeline that ran user DSL via node:vm + full require() in the same UID/PID namespace as the main Next.js process. User code now runs inside the existing isolated-vm pool (V8 isolate, no process / require / fs, no /proc/1/environ reachability). Introduces a first-class SandboxTask abstraction under apps/sim/sandbox-tasks/ that mirrors apps/sim/background/ — one file per task, central typed registry, kebab-case ids. Adding a new thing that runs in the isolate is one file plus one registry entry. Runtime additions in lib/execution/: - task-mode execution in isolated-vm-worker.cjs: load pre-built library bundles, run task bootstrap, run user code, run finalize, transfer Uint8Array result as base64 via IPC - named broker IPC bridge (generalizes the existing fetch bridge) with args size, result size, and per-execution call caps - cooperative AbortSignal support: cancel IPC disposes the isolate, pool slot is freed, pending broker-call timers are swept - compiled scripts + references explicitly released per execution - isolate.isDisposed used for cancellation detection (no error-string substring matching) Library bundles (pptxgenjs, docx, pdf-lib) are built into isolate-safe IIFE bundles by apps/sim/lib/execution/sandbox/bundles/build.ts and committed; next.config.ts / trigger.config.ts / Dockerfile updated to ship them instead of the deleted dist/*-worker.cjs artifacts. Call sites migrated: - app/api/workspaces/[id]/pptx/preview/route.ts - app/api/files/serve/[...path]/route.ts (+ test mock) - lib/copilot/tools/server/files/{workspace-file,edit-content}.ts All pass owner key user:<userId> for per-user pool fairness + distributed lease accounting. Made-with: Cursor * improvement(sandbox): delegate timers to Node, add phase timings + saturation logs Follow-ups on top of the isolated-vm migration (da14027): Timer delegation (laverdet/isolated-vm#136 recommended pattern): - setTimeout / setInterval / clearTimeout / clearImmediate delegate to Node's real timer heap via ivm.Reference. Real delays are honored; clearTimeout actually cancels; ms is clamped to the script timeout so callbacks can't fire after the isolate is disposed. - Per-execution timer tracking + dispose-sweep in finally. Zero stale callbacks post-dispose. - unwrapPrimitive helper normalizes ivm.Reference-wrapped primitives (arguments: { reference: true } applies uniformly to all args). - _polyfills.ts shrinks from ~130 lines to the global->globalThis alias. Timers / TextEncoder / TextDecoder / console all install per-execution from the worker via ivm bridges. AbortSignal race fix (pre-existing bug surfaced by the timer smoke): - Listener is registered after await tryAcquireDistributedLease. If the signal aborted during that ~200ms window (Redis down), AbortSignal doesn't fire listeners registered after the fact — the abort was silently missed. Now re-checks signal.aborted synchronously after addEventListener. Observability: - executeTask returns IsolatedVMTaskTimings (setup, runtimeBootstrap, bundles, brokerInstall, taskBootstrap, harden, userCode, finalize, total) in every success + error path. run-task.ts logs these with workspaceId + queueMs so 'which tenant is slow' is queryable. - Pool saturation events now emit structured logger.warn with reason codes: queue_full_global, queue_full_owner, queue_wait_timeout, distributed_lease_limit. Matches the existing broker reject pattern. Security policy: - New .cursor/rules/sim-sandbox.mdc codifies the hard rules for the worker process: no app credentials, all credentialed work goes through host-side brokers, every broker scopes by workspaceId. Pre-merge checklist for future changes to isolated-vm-worker.cjs. Measured phase breakdown (local smoke, Redis down): pptx wall=~310ms with bundles=~16ms, finalize=~83ms; docx ~290ms / 17ms / 70ms; pdf ~235ms / 17ms / 5ms. Bundle compilation is not the bottleneck — library finalize is. Made-with: Cursor * fix(sandbox): thread AbortSignal into runSandboxTask at every call site Three remaining callers of runSandboxTask were not threading a cancellation signal, so a client disconnect mid-compile left the pool slot occupied for the full 60s task timeout. Matching the pattern the pptx-preview route already uses. - apps/sim/app/api/files/serve/[...path]/route.ts — GET forwards `request.signal` into handleLocalFile / handleCloudProxy, which forward into compileDocumentIfNeeded, which forwards into runSandboxTask. - apps/sim/lib/copilot/tools/server/files/workspace-file.ts — passes `context.abortSignal` (transport/user stop) into runSandboxTask. - apps/sim/lib/copilot/tools/server/files/edit-content.ts — same. Smoke: simulated client disconnect at t=1000ms during a task that would otherwise have waited 10s. The pool slot unwinds at t=1002ms with AbortError; previously would have sat 60s until the task-level timeout. Made-with: Cursor * chore(build): raise node heap to 8GB for next build type-check Next.js's type-check worker OOMs at the default 4GB heap on Node 23 for this project's type graph size. Bumps the heap to 8GB only for the `next build` invocation inside `bun run build`. Docker builds are unaffected — `next.config.ts` sets `typescript.ignoreBuildErrors: true` when DOCKER_BUILD=1, which skips the type-check pass entirely. This only fixes local `bun run build`. No functional code changes. Made-with: Cursor * fix lint * refactor(copilot): dedup getDocumentFormatInfo across copilot file tools The same extension -> { formatName, sourceMime, taskId } mapping was duplicated in workspace-file.ts and edit-content.ts. Any future format or task-id change had to happen in two places. Exports getDocumentFormatInfo + DocumentFormatInfo from workspace-file.ts (which already owned the PPTX/DOCX/PDF source MIME constants) and imports it in edit-content.ts. Same source-of-truth pattern the file already uses for inferContentType. Made-with: Cursor * fix(sandbox): propagate empty-message broker/fetch errors Both bridges in the isolate used truthiness to detect host-side errors: if (response.error) throw new Error(response.error); // broker if (result.error) throw new Error(result.error); // fetch If a host handler ever threw `new Error('')`, err.message would be '' (falsy), so { error: '' } was silently swallowed and the isolate saw a successful null result. Existing call sites don't throw empty-message errors, but the pattern was structurally unsafe. Switch both to typeof check === 'string' and fall back to a default message if the string is empty, so all host-reported errors propagate into the isolate regardless of message content. Made-with: Cursor
…ng (#4221) * fix(fireflies): support V2 webhook payload format for meetingId mapping Fireflies V2 webhooks use snake_case field names (meeting_id, event, client_reference_id) instead of camelCase (meetingId, eventType, clientReferenceId). The formatInput handler now auto-detects V1 vs V2 payloads and maps fields correctly, fixing empty meetingId on V2 webhooks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(fireflies): guard against NaN timestamp, use stricter V2 detection Address PR review feedback: - Use Number.isFinite guard to prevent NaN timestamp propagation - Use AND instead of OR for V2 detection since both meeting_id and event are required fields in every V2 payload Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryHigh Risk Overview Security hardening and error normalization. Adds shared Docs/UI polish. Docs pages embed new videos/images; video lightbox behavior preserves playback position, Reviewed by Cursor Bugbot for commit 47519e3. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 47519e3. Configure here.
…owing same-origin blob URLs in iframe CSP (#4225) * fix(pdf): PDF previews by adding the missing preview endpoint and allowing same-origin blob URLs in iframe CSP * fixed * add preview routes and tests * follow nextjs route gen strat

Uh oh!
There was an error while loading. Please reload this page.