v0.6.61: SAP integration, live URLs for browser use, 5xx error categorizations, mothership positional table row insertion, CI improvements, org-external users, file viewer improvements#4330
Conversation
…arallel node-gyp (#4310)
…nt (#4312) * fix(security): rate limit chat OTP endpoint to prevent email bombing * fix(security): validate mothership proxy endpoint to block path traversal * fix(security): address greptile feedback on OTP rate limiting
* feat(integrations): SAP S/4HANA tools, block, and proxy with multi-deployment support * fix(sap_s4hana): address PR review comments - Validate baseUrl/tokenUrl in Zod schema and at runtime to prevent SSRF (https-only, deny loopback/link-local/cloud-metadata hosts) - Cap proxy token cache at 500 entries with LRU eviction - Add 30s timeout to outbound token, CSRF, and OData fetches - Make parseJsonInput return T | undefined so missing input is type-safe - Reset authType when deploymentType changes and surface OAuth fields whenever auth is not basic, so cloud_public users always see clientId/ clientSecret after switching from a basic-auth private deployment - Reject OData service names that are not uppercase identifiers and paths containing ".." or "." traversal segments Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(sap_s4hana): allow versioned service names; tighten proxy SSRF defenses - Permit ";v=NNNN" suffix on ServiceName regex so the four delivery tools (API_OUTBOUND_DELIVERY_SRV;v=0002, API_INBOUND_DELIVERY_SRV;v=0002) pass schema validation - Restrict subdomain to RFC 1123 label characters and region to lowercase alphanumeric short codes; run the constructed cloud_public host through assertSafeExternalUrl so a crafted subdomain (e.g. "evil.com#") cannot redirect requests carrying SAP credentials - Block RFC-1918 (10/8, 172.16/12, 192.168/16), 127/8, 169.254/16, and 0.0.0.0 via isPrivateIPv4, plus IPv4-mapped IPv6 variants (::ffff:10.0.0.1, ::10.0.0.1) so private internal hosts cannot be reached from baseUrl, tokenUrl, or the resolved cloud_public URL Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(sap_s4hana): catch hex-form IPv4-mapped IPv6 in SSRF check The WHATWG URL parser normalizes IPv4-mapped IPv6 addresses to hex form (e.g. [::ffff:169.254.169.254] → [::ffff:a9fe:a9fe]), which slipped past the dotted-decimal-only extractor. Decode the trailing two 16-bit hex groups back into IPv4 octets and run them through isPrivateIPv4. Also add isPrivateOrLoopbackIPv6 so pure IPv6 loopback (::, ::1), unique local addresses (fc00::/7), and link-local (fe80::/10) cannot be reached. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(sap_s4hana): scope CSRF metadata fetch and isolate token cache by secret - buildOdataUrl skips request query params when called with an internal pathOverride so the /$metadata CSRF probe never carries user OData options ($filter, $top, $select), which were causing write operations through the generic odata_query tool to fail. - tokenCacheKey now mixes a sha256 hash of clientSecret into the cache key so two tenants sharing the same tokenUrl + clientId but different secrets get isolated entries (no cross-tenant token leak). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(sap_s4hana): reject ?/# in service path; trim long update tool descriptions - ServicePath validator now rejects "?" and "#" so a caller can't smuggle query options through the path field (e.g., "/A_BusinessPartner?$format=atomsvc"); the Zod refine now reports ".." / "." segments, "?", and "#" together. - Update Customer / Update Supplier / Update Purchase Requisition tool descriptions exceeded the docs generator's 600-char regex window, so they were rendering with empty descriptions on the integrations landing page. Trimmed them to fit while keeping the limited-fields note and the If-Match guidance, then regenerated integrations.json and tool docs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(sap_s4hana): reject percent-encoded path traversal; widen Set-Cookie split - ServicePath now also rejects %2e/%2E, %2f/%2F, %5c/%5C, %3f/%3F, %23 so a caller cannot smuggle ".." / "." / "/" / "\" / "?" / "#" past the validator and have SAP's ABAP/ICM gateway decode them server-side. - joinSetCookies fallback regex now allows the ", " separator that's used when multiple Set-Cookie values are folded onto one header line (older runtimes without Headers.getSetCookie). Prevents CSRF cookies from being concatenated into a single value during write operations. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(sap_s4hana): preserve $ in OData query params; reject empty items array - buildOdataUrl now constructs query strings manually with encodeURIComponent and restores literal "$" so OData system options ($filter, $top, $select, $expand, $orderby, $skip, $format) reach SAP and any intermediary proxies/WAFs as-is, not as "%24filter". URLSearchParams was percent-encoding "$" to "%24" which most ICMs decode but some intermediaries silently drop, returning unfiltered results. - create_sales_order now rejects an empty items array (matches create_purchase_requisition) so callers get a clear client-side error instead of an opaque SAP validation failure on the deep-insert. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(sap_s4hana): ignore baseUrl on cloud_public to prevent token redirection Why: resolveHost previously preferred baseUrl unconditionally. A caller sending deploymentType=cloud_public with a baseUrl pointing elsewhere would obtain a real SAP UAA token, then forward it as Bearer to the attacker host. Zod superRefine did not validate baseUrl for cloud_public. Fix: resolveHost now constructs the SAP host from subdomain when deploymentType is cloud_public and only uses baseUrl for cloud_private and on_premise (where it is already SSRF-checked in superRefine). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(icons): use useId for SapS4HanaIcon and PipedriveIcon gradients Why: hardcoded SVG gradient/mask IDs collide when an icon renders more than once on a page (e.g. integrations listing). All other icons in this file use React's useId() — these were inconsistent. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * icons * fix(icons): use useId for AWS-style icon gradients Why: IAMIcon, IdentityCenterIcon, STSIcon, SESIcon, and SecretsManagerIcon all used hardcoded `id='xxxGradient'` values that collide when an icon renders more than once on a page (e.g. integrations listing). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(sap_s4hana): ignore tokenUrl on cloud_public to prevent UAA redirection Why: resolveTokenUrl previously honored caller-supplied tokenUrl regardless of deploymentType, mirroring the same redirection class as the prior baseUrl bug. A cloud_public caller could send tokenUrl to an attacker host, causing the proxy to POST clientId:clientSecret as Basic auth to it. superRefine for cloud_public did not validate tokenUrl. Fix: derive UAA URL from subdomain+region for cloud_public; only honor tokenUrl for cloud_private/on_premise (already SSRF-checked). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(icons): remove unused mask in PipedriveIcon Why: the <mask> element had no consumer (no mask='url(#...)' anywhere in the SVG), so both it and the maskId variable were dead code. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ui): display file upload messages * Address pr comments
* improvement(browser-use,stagehand): expose live session URLs and align with latest API specs - Browser Use: switch to v2 camelCase schema, fetch live URL from sessions endpoint, add startUrl/maxSteps/allowedDomains/vision/flashMode/thinking/systemPromptExtension/structuredOutput/metadata params, surface liveUrl/shareUrl/sessionId outputs - Stagehand: fetch Browserbase debug URL, add mode/maxSteps params, surface liveViewUrl/sessionId outputs, bump @browserbasehq/stagehand to ^3.2.1, update to claude-sonnet-4-6 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(browser-use): respect API default for highlightElements Only send highlightElements when user explicitly toggles it; previously defaulted to true which silently overrode the v2 API default of false. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(browser-use,stagehand): address PR review feedback - Browser Use: fetch liveUrl during polling once sessionId is known, instead of immediately after task creation. Handles tasks started without profile_id (where sessionId isn't returned in create response) and ensures session is active before fetching. - Stagehand: coerce empty/whitespace maxSteps strings to undefined so they're dropped from the request body instead of failing zod validation as ''. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(stagehand): preserve liveViewUrl and sessionId on agent error If the agent throws after Browserbase session init succeeds, callers can still surface the live view / session ID for debugging. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(browser-use): coerce empty maxSteps strings to undefined Mirrors the Stagehand block's handling so a cleared field doesn't pass through as ''. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(browser-use): skip metadata when empty --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* fix(vm): categorize user or server side errors * recategorize function syntax errors as 4xx
* feat(governance): external workspace users from outside org * update docs * address comments * edge case improvements * remove unused fallback * address comments * add outbox for seat reduction * fix edge case with org join after invite * add server side batch invites for workspace * use zod schema for route
…key order (#4317) * fix(sap_s4hana): require non-empty items in create_purchase_order Why: SAP A_PurchaseOrder POST silently fails or returns opaque errors without to_PurchaseOrderItem entries. Block already required this body but the tool marked it optional and didn't validate items presence — mismatched contract with create_sales_order / create_purchase_requisition. Also clarifies the deliveryDocument placeholder to show both outbound and inbound number ranges. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(sap_s4hana): add get_material_document and fix supplier invoice key order Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(sap_s4hana): align material doc key order in description and require purchase order body type --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
) * v0.6.29: login improvements, posthog telemetry (#4026) * feat(posthog): Add tracking on mothership abort (#4023) Co-authored-by: Theodore Li <theo@sim.ai> * fix(login): fix captcha headers for manual login (#4025) * fix(signup): fix turnstile key loading * fix(login): fix captcha header passing * Catch user already exists, remove login form captcha * fix(short-input): hide selected text to prevent overlay collision The ShortInput component uses a transparent input layer beneath a formatted overlay. When users selected text and scrolled horizontally, the browser's ::selection pseudo-element overrode `color: transparent`, making raw unformatted text visible and causing visual collision with the overlay. Adding `selection:text-transparent` keeps the input text invisible under selection, while the overlay continues to display the correctly formatted highlighted text. Fixes #3389 Co-Authored-By: Octopus <liyuan851277048@icloud.com> --------- Co-authored-by: Waleed <walif6@gmail.com> Co-authored-by: Theodore Li <theodoreqili@gmail.com> Co-authored-by: Siddharth Ganesan <33737564+Sg312@users.noreply.github.com> Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> Co-authored-by: Theodore Li <theo@sim.ai> Co-authored-by: octo-patch <octo-patch@github.com>
* fix(api): return 499 on copilot mcp user aborts * fix(mcp): fix copilot mcp response
* perf(docker): refactor app.Dockerfile to use turbo prune Replaces manual workspace package.json copies with `turbo prune sim --docker`, matching the canonical Vercel/Turborepo monorepo pattern (and the existing realtime.Dockerfile). - New `pruner` stage emits `out/json` (manifests + lockfile) and `out/full` (sources) for only the packages sim actually depends on. - `deps` stage installs from the pruned manifest, so cache invalidates only when package.json/bun.lock change — not on source edits. - Drops 24 lines of brittle manual COPYs (one per workspace package). - Single full install in deps (no --omit=dev) so build-time devDeps like tailwindcss/postcss are available — replaces the earlier hotfix that did a second install in the builder stage. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(docker): pin turbo to 2.9.6 in pruner stage Match the version locked in package.json so pruner output is reproducible across builds. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…review (#4316) * feat(files): extract PDF viewer behind SSR boundary and polish file preview ## Core architectural fix Move all react-pdf / pdfjs-dist code into a new pdf-viewer.tsx module and import it exclusively via next/dynamic({ ssr: false }). pdfjs-dist v5 references DOMMatrix at module evaluation time, which crashed SSR. The previous workaround (a DOMMatrix polyfill in instrumentation.ts) is removed in favour of this proper hard module boundary. ## PDF viewer improvements - Cursor-anchored zoom: Ctrl/⌘+wheel and trackpad-pinch now zoom toward the cursor instead of the top-left corner. Toolbar ± buttons anchor to the viewport centre. Uses the canonical scroll-adjust formula used by map and canvas viewers. - Horizontal scroll: dropping flex-col from the scroll container lets the zoomed pages wrapper overflow naturally and produces a horizontal scrollbar at zoom > 1×. - Loading skeleton: replaced the conditional inline skeleton with an absolute inset-0 overlay so it fills the scroll container correctly in all layout contexts. - Shadow tokens: fixed shadow-[var(--shadow-medium)] and shadow-[var(--shadow-card)] to use the Tailwind utility classes shadow-medium and shadow-card directly. ## File viewer cleanup - data-table.tsx: wrap setInputRef in useCallback([]) so the ref callback has a stable identity across renders. Previously the inline function got a new identity on every keystroke (because editValue state changed), causing React to teardown/remount the ref and re-run node.select() on every character typed. - preview-panel.tsx: keep useMemo on ctxValue passed to Context.Provider — Context uses Object.is, so a new object every render causes unnecessary consumer re-renders. - resource-content.tsx: remove unnecessary useCallback/useMemo wrappers on handlers and derived values that have no memoization observers. ## API route - Wrap content route with withRouteHandler for automatic request-ID tracking via AsyncLocalStorage; remove manual generateRequestId() calls. - Add resourceName to audit record; add encoding param support (base64 / utf-8). ## Query hooks - Include key (storage object key) in both useWorkspaceFileContent and useWorkspaceFileBinary query key tuples so the cache is correctly busted when a file is re-uploaded with a new storage key. ## Other - Add Suspense boundaries to files/page.tsx and files/[fileId]/page.tsx (required for useSearchParams inside the Files component). - Add mmd to SUPPORTED_CODE_EXTENSIONS (Mermaid diagrams). - Add https: to CSP img-src. - Remove ==== separator comments from lib/copilot/constants.ts. - New dependencies: pdfjs-dist 5.4.296, mermaid 11.14.0, monaco-editor 0.55.1, @monaco-editor/react 4.7.0. * fix(files): replace instanceof Error checks with toError() and fix skeleton tokens - Use toError() from @sim/utils/errors across all catch blocks in file-viewer.tsx, preview-panel.tsx, and route.ts instead of the prohibited `err instanceof Error ? err.message : fallback` pattern - Fix loading skeleton in files.tsx: bg-white → bg-[var(--surface-2)] and shadow-[var(--shadow-medium)] → shadow-medium * fix(files): address PR review findings - csp.ts: revert bare https: from img-src — it defeats the existing domain allowlist and opens info-leakage vectors - files/page.tsx + files/[fileId]/page.tsx: add explicit fallback={null} to <Suspense> to make intent clear (React defaults to null, but omitting it looks like an oversight) - preview-panel.tsx: restore pre passthrough in STATIC_MARKDOWN_COMPONENTS so Streamdown's wrapping <pre> doesn't nest inside the custom code block <div>, which produced invalid HTML and broken styling - file-viewer.tsx: add 'webm' to VIDEO_PREVIEWABLE_EXTENSIONS to match 'video/webm' in VIDEO_PREVIEWABLE_MIME_TYPES * chore(files): revert accidental pptxgenjs.cjs re-minification The bundle was regenerated non-deterministically during development (same pptxgenjs 4.0.1, different variable names in minifier output). No functional change — restore the prior version to keep the diff clean. * fix(files): fix Monaco stale closure, XLSX Ctrl+S data loss, and async workbook mutation Three bugs from Cursor Bugbot follow-up review: 1. Stale closure in handleEditorMount (Medium): useCallback([], []) captured content='' at first render. When Monaco mounts after content loads (e.g. switching from preview to editor mode), lastSyncedContentRef was never initialized and external content changes stopped syncing. Fixed by keeping a contentRef updated on every render and reading it inside handleEditorMount. 2. XLSX Ctrl+S discards active cell edit (Medium): handleSave read from workbookRef.current before DataTable's in-progress editValue was committed. Fixed by exposing commitEdit() from DataTable via useImperativeHandle (using an always-current editStateRef so the handle stays stable) and calling it at the top of handleSave. 3. Async workbook mutation fragility (Low): handleCellChange / handleHeaderChange updated the workbook inside import('xlsx').then(), creating microtask-order coupling with handleSave. Fixed by caching the xlsx module in xlsxModuleRef on first parse and using it synchronously in both handlers. * refactor(files): cleanup anti-patterns across file viewer components Six-pass cleanup over the file-viewer directory: Effects (you-might-not-need-an-effect): - AudioPreview, VideoPreview: replace reset useEffect with key={file.id} so the component remounts on file change — React's canonical solution - DocxPreview: same key-prop fix; removes a 5-setState reset effect that was also clearing containerRef.current.innerHTML unnecessarily Callbacks (you-might-not-need-a-callback): - handleEditorMount, handleEditorChange: remove useCallback — MonacoEditor is dynamic(), not React.memo, so reference stability has no observer - markSavedContent: remove useCallback — called only through an onSaveRef, never directly observed - DataTable.setInputRef: remove useCallback — callback refs on native elements are called regardless of reference identity Design tokens (emcn-design-review): - VideoPreview: bg-black → bg-[var(--surface-inverted)] - HtmlPreview iframe: bg-white → bg-[var(--surface-2)] useMemo, useState, and react-query passes found no issues. * improvement(files): replace stock Monaco theme with Sim design system theme Define sim-dark and sim-light Monaco themes using Sim's exact design tokens instead of the default vs/vs-dark which looked identical to stock VSCode. Chrome changes (both themes): - Background, gutter use --bg (not VSCode's near-black / pure-white defaults) - Line numbers use --text-muted instead of VSCode gray - Cursor switches to --brand-secondary (#33b4ff) - Selection highlight is brand blue at 15% opacity - Scrollbar shadow removed, track uses surface tokens - Bracket match, word highlight, find match all keyed to brand blue - Suggestion/hover widgets use --surface-2 / --border tokens - All hardcoded shadows removed (scrollbar.shadow = transparent) Syntax token changes (inherit: true — base handles unlisted tokens): - Comments: muted gray + italic (vs VSCode's bright green) - Strings: #3ab872 dark / #16825d light (vs VSCode orange-red) - Numbers: warm amber / warm orange (both readable on their backgrounds) - Keywords: #33b4ff dark / #0078d4 light (brand blue family) - Types: complementary blue-gray / purple * fix(files): bump light theme comment color to #888888 for WCAG contrast * fix(files): fix dark mode comment contrast #4a4a4a → #606060 (~1.9:1 → ~2.9:1) * improvement(files): cursor to default color, video background to surface-1 - Monaco cursor: #33b4ff (brand blue) → #e6e6e6 dark / #1a1a1a light (text cursor should be neutral, not loud) - VideoPreview background: var(--surface-inverted) → var(--surface-1) (consistent with PDF viewer, fits workspace context over cinema-black) * fix(files): stabilize setInputRef callback and guard against double-commit in DataTable Wrap setInputRef in useCallback([], []) so React doesn't tear down and re-mount the input ref on every keystroke. Without stable identity, every editValue state change caused node.focus()/node.select() to fire, resetting the cursor selection to "select all" on each character typed. Add isCommittedRef to guard both the imperative commitEdit handle and the inline commitEdit (called by onBlur) against double-application. The ref is cleared in startEdit and set to true on the first commit, so a concurrent onBlur cannot re-apply the same edit. * fix(files): preserve scroll position during Mothership streaming edits Two fixes to the Monaco auto-scroll logic: 1. At streaming start, initialize textareaStuckRef from the editor's actual scroll position (isAtBottom check) instead of unconditionally setting true. Previously every streaming session jumped the viewport to the last line on the very first content update, even when the user was reading mid-file. 2. Replace the wheel-only DOM listener with editor.onDidScrollChange(), the proper Monaco API. This covers trackpad, scrollbar drag, and keyboard scroll — not just mouse wheel. As a bonus, scrolling back to the bottom during streaming now re-engages follow mode (matching iTerm2/xterm.js behavior). 3. Save and restore view state around model.setValue() during streaming when the user has scrolled away from the bottom. This prevents Monaco from resetting the viewport on each content replacement. When the user is at the bottom, view state is not saved so Effect 3 can scroll to the new bottom. * fix(files): fix two scroll logic bugs introduced in previous streaming scroll fix The prior fix introduced a regression for the "user was at bottom" case and a false-disengagement bug from programmatic scroll events. Bug 1 — Effect ordering: all three effects fire on the same render when isStreamInteractionLocked flips true. Effect 2 called isAtBottom() AFTER Effect 1 had already called model.setValue(), which grew scrollHeight. The old "at bottom" scroll position was now 200px short of the new bottom, so isAtBottom() returned false, textareaStuckRef was set false, and Effect 3 never called revealLine. Users at the bottom stopped following the stream. Fix: measure isAtBottom() in Effect 1 BEFORE setValue, while scrollHeight is still accurate. Set textareaStuckRef = true only (never false here). Effect 2 no longer initializes the ref — only the listener disengages it. Bug 2 — onDidScrollChange fires during model.setValue: Monaco fires onDidScrollChange when scroll dimensions change, including when setValue grows the document. This caused the listener to disengage auto-scroll on every content update even with no user interaction. Fix: add suppressScrollListenerRef, set true before setValue/restoreViewState and false after. The listener exits early when suppressed, so only genuine user scroll events (wheel, trackpad, keyboard, scrollbar) can disengage. Both refs moved to the component's ref block for conventional placement. * chore(files): remove extraneous comments from file viewer and data table * refactor(files): split 2281-line file-viewer.tsx into focused modules TextEditor, DocxPreview, PptxPreview, XlsxPreview, ImagePreview each moved to their own files. Shared utilities (PreviewError, resolvePreviewError, shouldSuppressStreamingDocumentError, PDF_PAGE_SKELETON) extracted to preview-shared.tsx. file-viewer.tsx is now the orchestrator + MIME constants + small stateless previews (~495 lines). * fix(files): remove unnecessary TextEditorProps export * refactor(files): four stellar-quality improvements to file-viewer split - Extract useBlobUrl hook shared by AudioPreview and VideoPreview, eliminating ~30 lines of duplicated state/effect logic - Stabilize markSavedContent with useCallback (matches setDraftContent) - Stabilize handleEditorChange with useCallback([setDraftContent]) - Fix pptx static render effect deps: drop redundant dataUpdatedAt (already encoded in cacheKey) and unused workspaceId * test(files): extract pure modules and add 122-test suite for file viewer logic Extract TextEditorContentState machine and file category resolution into plain .ts modules (text-editor-state.ts, file-category.ts) so they can be unit-tested without React or Next.js overhead. Update component files to import from the extracted modules, eliminating code duplication. Add two test files: - text-editor-state.test.ts: 32 tests covering resolveStreamingEditorContent, the reducer (edit / save-success), and syncTextEditorContentState across all phases (uninitialized, ready, streaming, reconciling) including reference-equality short-circuit checks for zero-allocation paths - file-category.test.ts: 90 tests covering MIME-type routing for all 8 categories, extension fallback, MIME-priority-over-extension, and case-insensitive extension handling * fix(files): add key to IframePreview and use monotonic seq for streaming PDF key - Add key={file.id} to IframePreview so React remounts on file switch, preventing stale renderError from persisting across different files - Replace key={streamingBuffer.byteLength} with a monotonic sequence counter so same-size successive PDF compilations still trigger a remount * fix(files): restore getFileExtension import dropped during refactor * fix(files): clear loadError on PDF success and fix streaming null-flash - pdf-viewer: add setLoadError(null) in onLoadSuccess so the toolbar is not permanently hidden after a failed-then-successful PDF load - file-viewer: consolidate streaming-mode rendering so the debounce period (before rendering=true) shows a skeleton instead of null * refactor(files): cleanup pass — effect, callback, state, and design fixes - text-editor: replace sync-external useEffect with "adjust during render" pattern so the state machine advances immediately instead of after a paint - text-editor: remove unnecessary useCallback from markSavedContent (no observer) - files: narrow deleteTargetFile state to {id, name} — only those fields are used - files: remove uploadFile (mutation object) from useCallback deps — .mutateAsync is stable - files: remove unnecessary useCallback from handleNavigateToFiles (no observer) - files: replace raw <button> with emcn Button for "Clear all filters" action
* fix(docker): use full bun.lock and copy it into builder The staging build for app.Dockerfile (commit dc20229, PR #4322) is failing in two ways after switching to turbo prune: 1. turbo 2.9.6's pruned bun.lock is malformed for bun 1.3.x: error: Failed to resolve prod dependency 'wrap-ansi' for package 'log-update' at bun.lock:2688:5 Bun ignores it and falls back to a fresh resolve (~7m install). 2. Next.js 16.1.6's Turbopack production build can't infer the workspace root because /app/bun.lock doesn't exist in the builder stage: Error: We couldn't find the Next.js package (next/package.json) from the project directory: /app/apps/sim This blocks the build entirely. Fix: - deps stage: use the full bun.lock from /app/bun.lock (the original lockfile after `COPY . .` in pruner) instead of the broken /app/out/bun.lock that turbo prune emits. - builder stage: also copy the full bun.lock to /app/bun.lock so Turbopack and turborepo can detect the workspace root. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(ci): bump deprecated Node.js 20 actions to Node.js 24 versions GitHub Actions runners emit deprecation warnings for actions still on the Node.js 20 runtime. Node.js 20 will be force-upgraded by GitHub on 2026-06-02 and removed on 2026-09-16. Bumps to the latest stable major versions, all of which use Node.js 24: - actions/cache: v4 -> v5 - actions/setup-node: v4 -> v6 - aws-actions/configure-aws-credentials: v4 -> v6 - docker/login-action: v3 -> v4 All require GHA runner v2.327.1+ which Blacksmith already runs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* fix(workflow): throw 4xx on variable resolution failures * Switch spread order
* fix(copilot): use different chats for different workflows * remove use effect * trim comments
…llow GA doubleclick in CSP (#4328) * fix(billing): gate org billing query to invite modal open state and allow GA doubleclick in CSP * fix(csp): drop redundant stats.g.doubleclick.net entry
The POST /api/table/[tableId]/rows handler called handleBatchInsert without await, so ZodError rejections (e.g. empty rows array) bypassed the route's try/catch and were caught by withRouteHandler as an unhandled error, returning a generic 500 "Internal server error". Add await so validation errors surface as 400s with the actual message.
…4326) * feat(table): expose position parameter for row insertion via copilot * fix(table): validate positions length matches rows before service call * chore(table): regenerate tool types from updated copilot contract * fix(table): validate no duplicate positions in batch_insert_rows * chore(table): regenerate tool types with integer position schema
…ons, and execution improvements (#4292) * improvement(trace-spans): rewrite trace span pipeline with per-iteration enrichment Unify tool calls under span.children, capture dual-clock timing, and surface per-iteration model content (assistant text, thinking, tool calls, finish reason, tokens, cost, ttft, provider, errors) across all 12 LLM providers. UI renders the new fields on model child spans; old logs degrade gracefully since every field is optional. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * improvement(logs): add Trace tab with two-pane tree+detail view - Wrap log-details drawer in Overview | Trace tabs; Overview unchanged - New TraceView with hierarchical tree on the left and detail pane on the right - Keyboard nav, span filter, expand/collapse all - Bump min drawer width 400->600 and clamp persisted widths on rehydrate Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(logs): retry failed runs + show workflow input in detail Brings PR #4181 inline: persists workflowInput on successful runs, adds useRetryExecution mutation (streaming read-one-chunk-and-cancel), Retry entrypoints in the row context menu and the detail sidebar, and extractRetryInput with fallback to starter block state for older logs. Also surfaces the captured input in a new "Workflow Input" section above Workflow Output in the detail Overview tab, guarded so older logs without the field don't render an empty block. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(ui): use inverted popover scheme for usage-control popovers Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): trace view chevron padding, section state leak, and tab-scoped keyboard nav - Pad tree rows from panel edge so the root chevron isn't visually clipped. - Key DetailCodeSection by label so collapse state belongs to the section purpose, preventing isOpen from leaking across span changes when positional slots happened to align. - Ignore log-to-log arrow-key nav while the Trace tab is active so TraceView owns span navigation; filter inputs keep native caret movement. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): align trace tree rows to 14px content grid Chevron at depth 0 and the timeline bars now sit on the same 14px left/right grid as the trace view's header strip and the rest of the log details panel, removing the stagger where bars extended further left than chevrons and the chevron appeared cramped against the panel edge. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): restore scroll in log-details panel Overview tab's scroll container (SModalTabsContent) was wrapped around a non-overflow inner div that held the scrollAreaRef, so the scroll-reset on log change targeted a non-scrolling element. Collapse the wrapper into the Tabs.Content element itself and move the ref there. Add min-h-0 to the Trace detail pane wrapper so its scrolling child can shrink inside the horizontal-flex row. * fix(logs): hide inactive Overview tab panel Tailwind's `.flex` utility overrides the UA `[hidden]` rule, so applying `flex` to SModalTabsContent caused the inactive Overview panel to still participate in the Tabs flex column and push the Trace view down. Keep SModalTabsContent as a plain overflow container (no `flex` class) with the scroll ref on it, and restore the inner flex-col wrapper for the Overview content so it still stacks with gap spacing. * fix(logs): trace view padding, section cutoff, keyboard visibility - Tree pane now has top padding so the first row has breathing room under the header strip instead of sitting flush against the border. - DetailCodeSection dropped its wrapper `overflow-hidden`. Per CSS, a flex item with `overflow: hidden` resolves `min-height: auto` to `0`, so when Input and Output were both expanded the flex algorithm shrank each section below its content, cutting off rows. Without the clip, sections size to content and the surrounding pane's `overflow-y-auto` takes over. - Selected span row now scrolls into view on selection change, so arrow-key navigation always keeps the active row visible in the tree pane. * fix(logs): inline Workflow State row and lift search dropdown z-index Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): use emcn Button for View Snapshot action Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * minor improvements * fix(logs): trace view resizable split, bar visibility, provider icons, cleanup - Resizable tree/detail split in trace view (default 360px, drag to resize) - Resizable right panel in preview snapshot (280–600px) - Fix Gantt bar invisibility for late-run spans (clamp offsetPct to 100-MIN_BAR_PCT) - Propagate model+provider to child model spans in span-factory for correct icons - Fix icon contrast on light provider backgrounds (luminance-based color class) - Replace custom status badges with emcn Badge component - Lighten jump-to-error button to ghost variant - Remove double X button in modal snapshot (showBlockCloseButton prop) - Fix emcn subpath imports → barrel in trace-view, log-details, execution-snapshot - Fix hover: → hover-hover: on resize handles - Add body style cleanup on resize unmount - Fix React Query key factory naming (stats/stat convention) - Remove unnecessary useCallback/useMemo in preview and execution-snapshot * fix(ui): scroll guard, credentials UX, design token fixes, input padding - logs: only scroll-into-view on keyboard nav, not on click selection - resource: stable scrollbar gutter, wider first column - credentials: toast success/error feedback, remove useMemo for personalEnvData, allow editing conflict rows, fix disabled state visibility, use --text-error token - integrations: use --text-error token for error state - input: increase right padding (px-2 → pl-2 pr-3) * chore(skills): add /ship command to claude, cursor, and agents * fix(input): add scroll-pr-1 to keep caret visible when text overflows * fix(logs): address PR review — iteration name guard, cost race, mothership retry * improvement(logs): cleanup pass — remove anti-patterns, fix design tokens, simplify state * fix(trace-spans): extend final model segment by position not by stale constant name * fix(modal): restore sidebar-width padding on non-workflow pages * fix(secrets): eliminate slow save by parallelizing DB ops and fixing stuck button Sequential per-variable, per-workspace DB round-trips in syncPersonalEnvCredentialsForUser caused O(W×K) latency (800–1600ms for 10 workspaces). Replaced with parallel workspace processing and batched upserts. Also parallelized secret decryption in the GET handler. On the client, removed the changeToken bug that left the Save button permanently disabled after a failed save, split the shared hasSavedRef into two independent flags to eliminate ordering races, and moved ref updates to after mutation success so optimistic state can never get stuck. * updated sap block * fix(sap): remove slash from S4HANA name, set white bgColor, regenerate docs * fix(logs): prevent log-row arrow navigation when trace tab is active * fix(logs): aggregate cost onto workflow root span; stabilize onActiveTabChange callback * improvement(logs): fix Gantt time bounds to walk full span tree; cleanup effects, memos, callbacks, React Query mutations * fix(logs): reset detail panel tab to overview on log switch * chore(logs): remove extraneous comments * fix(logs): restore useEffect for async setActiveWorkflow and useMemo on rowProps - resource-content.tsx: revert render-time setActiveWorkflow call to useEffect; the store action is async and performs network ops, calling it during render violates React purity - logs-list.tsx: restore useMemo on rowProps to prevent virtualized list rows from re-rendering on every parent render * fix(queries): forward AbortSignal in mothership-admin query functions All queryFn callbacks must forward signal for request cancellation per project React Query standards. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…4327) * fix(knowledge): skip sync and document processing when KB is deleted * fix(knowledge): mark connector errored and document failed when KB is deleted * fix(knowledge): mark connector errored in dispatchSync when KB is deleted
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Hardens backend/admin surfaces: Improves reliability/consistency across UI and infra: GitHub Actions versions are bumped (AWS creds, Docker login, cache, setup-node), several SVG icons switch to Reviewed by Cursor Bugbot for commit ed7786d. Bugbot is set up for automated code reviews on this repo. Configure here. |
… + snapshot styling (#4333) * fix(files): stop markdown preview auto-scrolling during copilot patch streams fix(snapshot): use surface-4 background for input/output code blocks in light mode * fix(files): separate auto-scroll gate from streaming render mode in MarkdownPreview
* fix(ui): adjust docx and code rendering * fix(ui): address PR feedback on docx fit and Monaco type cast Use computed padding from `.docx-wrapper` instead of a hardcoded 60px so the fit calculation survives docx-preview library changes. Replace the inline `import()` cast for ShowLightbulbIconMode with a top-level type import. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix lint --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(files): suppress transient streaming preview errors for docx and pptx
* feat(files): add OOXML style extraction for uploaded docx/pptx files
New GET /api/workspaces/[id]/files/[fileId]/style endpoint + VFS read
path files/by-id/{id}/style that returns a compact JSON style summary
from an uploaded binary .docx or .pptx: theme name, 12-slot color
palette, major/minor font pair, and key named styles (Normal, H1-H3,
Title). Logic lives in a shared lib/copilot/vfs/document-style.ts so
both the REST API and the VFS read handler reuse the same parsing code.
* chore(files): polish style extraction — type narrowing + empty-styles guard
Explicit 'docx' | 'pptx' type annotation after the extension guard in
both route.ts and workspace-vfs.ts so TypeScript sees the narrowed type
rather than string. Only set summary.styles when the parsed array is
non-empty so the JSON response doesn't include "styles": []. Remove
redundant inline WHAT-comments from parseColorSlot.
* fix(files): tighten streaming preview invariant and component consistency
- Apply structural invariant to PDF streaming path: never surface errors
while streamingContent is defined; only log at info level
- Remove redundant setRenderError(null) from DOCX streaming effect — the
gate at the display layer already suppresses errors during streaming
- Wrap PptxPreview in memo for consistency with DocxPreview
- Add key={file.id} to PptxPreview mount site (was missing, DocxPreview
had it) so the component resets when the viewed file changes
- Fix --text-body → --text-primary across PreviewError, UnsupportedPreview,
and MermaidDiagram error label; --text-body is not a valid EMCN token
* fix(files): remove setRenderError(null) from PPTX and PDF streaming paths
* feat(files): add compiled-check endpoint and VFS path for binary document self-verification
* fix(files): remove dead renderError state from IframePreview
* refactor(files): hoist BINARY_DOC_TASKS to module scope in compiled-check route and VFS handler
* fix(files): deduplicate BINARY_DOC_TASKS and add size guard to VFS compiled-check
Uh oh!
There was an error while loading. Please reload this page.