v0.7.17: emcn and workflow renderer isolated package, popular blocks extension, workspace forking, slack trigger extension, new README#5281
Conversation
waleedlatif1
commented
Jun 30, 2026
- feat(workspaces): fork + push/pull (feat(workspaces): fork + push/pull #5210)
- improvement(docs): flatten the academy learn/chapters panels (improvement(docs): flatten the academy learn/chapters panels #5253)
- chore(deploy): remove deploy as a2a (chore(deploy): remove deploy as a2a #5255)
- feat(integrations): extend Airtable, Google Docs, WhatsApp, and Excel tool depth (feat(integrations): extend Airtable, Google Docs, WhatsApp, and Excel tool depth #5256)
- improvement(emcn): extract design system into shared @sim/emcn package (improvement(emcn): extract design system into shared @sim/emcn package #5257)
- fix(emcn): repair app-wide crash and unstyled UI after package extraction (fix(emcn): repair unstyled UI after package extraction #5258)
- fix(knowledge): send tag filters as a JSON string so the document filter works (fix(knowledge): send tag filters as a JSON string so the document filter works #5259)
- fix(emcn): resolve Calendar icon/component barrel collision and preserve prism side effects (fix(emcn): Calendar icon collision + prism side-effect registration #5261)
- fix(prism): load prismjs core before language components (fix(prism): load prismjs core before language components #5262)
- feat(pii): add redaction timing metrics across sidecar and persist path (feat(pii): add redaction timing metrics across sidecar and persist path #5264)
- feat(workflow-renderer): extract edge, subflow, and note Views into @sim/workflow-renderer (feat(workflow-renderer): extract edge, subflow, and note Views into @sim/workflow-renderer #5263)
- perf(dev): curate SIM_DEV_MINIMAL_REGISTRY to core toolbar blocks (perf(dev): curate SIM_DEV_MINIMAL_REGISTRY to core toolbar blocks #5251)
- fix(uploads): attach compiled binary for AI-generated docs, not source (fix(uploads): attach compiled binary for AI-generated docs, not source #5266)
- feat(integrations): extend Telegram, Outlook, and Notion tool depth (feat(integrations): extend Telegram, Outlook, and Notion tool depth #5265)
- feat(workflow-renderer): extract pure WorkflowBlockView + SubBlockRowView (feat(workflow-renderer): extract pure WorkflowBlockView + SubBlockRowView #5267)
- feat(integrations): extend ElevenLabs, Google Drive, Firecrawl, Pinecone, Resend, and S3 tool depth (feat(integrations): extend ElevenLabs, Google Drive, Firecrawl, Pinecone, Resend, and S3 tool depth #5270)
- feat(mothership): add secrets input in chat (feat(mothership): add secrets input in chat #5274)
- improvement(docs): redesign README (animated hero + product demo) (docs: redesign README (animated hero + product demo) #5275)
- feat(docs): render workflow previews with the shared editor renderer (feat(docs): render workflow previews with the shared editor renderer #5277)
- improvement(settings): persistent layout + locked-down header API (improvement(settings): persistent layout + locked-down header API #5278)
- improvement(slack-trigger): expose view, message, and state on interactivity payloads (improvement(slack-trigger): expose view, message, and state on interactivity payloads #5279)
- feat(workspaces): gate workspace forking behind runtime workspace-forking feature flag (feat(workspaces): gate workspace forking behind runtime workspace-forking feature flag #5280)
* feat(workspaces): fork + push/pull * type fix * fix tests * progress on ux * remove modal section * improve UI of modal * update more ui * make rollback part of the footer * track skipped count correctly * address comments * make it workspace admin level * update skipped count * address more comments * deal with unbounded memory possibility * fix deleted kb article bug * no deployed workflow case * UI/UX cleanup * fix oauth dropdown case * fix oauth selector issue * infra work + activity log * consolidate migration * update modal state * more UI simplification * grammar * update audit report ui * perf improvements * fix tool input scenarios and add dependsOn UI handling * minor comments * fix webhook stability issues + drift detection removal * make dependsOn subblock mapping cleanly stored * fix: harden fork dependent-value mapping (clear stale rows, identity-guard first-sync fallback, perf + cleanup) * address comments * update comment * enforce admin perms for activity api * fix required + dependsOn combo
* improvement(docs): flatten the academy learn/chapters panels The "What you will learn" and "Chapters" panels were filled, bordered cards — the only boxed elements on the page. The docs design system is explicitly flat: global.css strips fumadocs cards/callouts/card-grids to transparent/divider-based, and the right-rail "On this page" TOC is small, muted, and borderless. - WhatYouWillLearn (inline): flat divider list like the FAQ, with a small panel label at the app's text scale instead of a page-h2-scale title - VideoChapters (right rail): borderless, matching the TOC — small muted label + flat hover rows, no card chrome * improvement(docs): drop the repeated per-row play icon from the chapters list The CirclePlay glyph repeated on every chapter row read as noise — a column of identical icons down the rail. The "On this page" TOC this list mirrors has no per-row icons; the timestamps already signal video chapters and the hover highlight signals they're seekable. Rows are now text + time only. * improvement(docs): drop the under-label rule on the learn callout A full-width rule under the small "What you will learn" label read as an awkward heading underline and blurred into the inter-item dividers. The label is now a quiet muted marker (matching the Chapters label and the TOC heading), with dividers only between items — so it never competes with the bold item titles or looks like an underlined heading.
* chore(deploy): remove a2a * add block
… tool depth (#5256) * feat(airtable): add delete and upsert record tools * feat(google-docs): add batchUpdate text, table, image, and style tools * feat(whatsapp): add template, media, interactive, reaction, and mark-read tools * feat(microsoft-excel): add clear, format, create-table, sort, and delete-worksheet tools * fix(integrations): address review feedback - google-docs: use camelCase fontSize field mask; normalize string booleans for bold/italic/underline and matchCase - microsoft-excel: escape OData single quotes in worksheet/table keys; validate range for clear/format - airtable: enforce batch limits (delete <=10 ids, upsert <=10 records and 1-3 merge fields) with clear errors * fix(integrations): address round-2 review - airtable: coerce upsert typecast as string-aware boolean (string "false" no longer truthy) - microsoft-excel: format_range surfaces precise partial-state error when fill PATCH fails after font (no atomic font+fill endpoint in Graph) * fix(whatsapp): treat 2xx mark-as-read as success unless body says success:false * fix(integrations): build fix, doc accuracy, and comment cleanup - google-docs: align manualDocumentId condition with the document selector so the documentId canonical group has matching conditions (fixes canonical-pair block test / build) - microsoft-excel: describe fill/font color as hex code only (Graph does not reliably accept named colors) - remove verbose explanatory inline comments from new tools (keep idiomatic section dividers) - regenerate integration docs + integrations.json catalog from the block registry * fix(integrations): harden delete-record id coercion and excel sort-column validation - airtable: coerce recordIds entries via String() so numeric JSON values don't crash on .trim() - microsoft-excel: drop the silent sortColumn default to 0 so invalid input surfaces the tool's clear validation error (both v1 and v2 blocks) * fix(airtable): coerce upsert fieldsToMergeOn entries via String() to handle non-string values
#5257) Moves apps/sim/components/emcn into a shared @sim/emcn package consumed directly by apps/sim and apps/docs. cn/keyboard/use-copy-to-clipboard move into the package; all imports become direct @sim/emcn (icons via @sim/emcn/icons, CSS via file path). ChipModal email validation is now prop-driven (quickValidateEmail stays in apps/sim, injected via validate). Docs drops its local chip/chip-dropdown/dropdown-menu mirrors and consumes @sim/emcn.
…tion (#5258) Two regressions from moving emcn into @sim/emcn: 1. optimizePackageImports['@sim/emcn'] rewrote barrel imports to direct subpaths, duplicating the toast module so ToastProvider (layout) and useToast (workspace permissions provider) resolved different ToastContext objects — useToast threw 'must be used within <ToastProvider>' on every workspace route. Removed @sim/emcn from optimizePackageImports. 2. emcn's source left apps/sim's Tailwind content globs (and docs' v4 auto-content scope, which excludes node_modules), so utility classes used only inside emcn components stopped generating and components rendered unstyled. Added the package to apps/sim's Tailwind content and a @source to docs.
…ter works (#5259) * fix(knowledge): send tag filters as a JSON string so the document filter works The document-list tag filter never reached the database. The `tagFilters` query field was a Zod `.transform()` that decoded the JSON string into an array of objects; the client's `requestJson` parses the query before serializing, so `appendQuery` received the array and emitted `tagFilters=[object Object]` into the URL. The route then failed to `JSON.parse` it and returned 400, so the list came back empty (or stale via keepPreviousData) regardless of operator or value. - Model `tagFilters` as the wire string it actually is; decode it server-side via a new `parseDocumentTagFiltersParam` helper (route maps a bad value to 400). - Harden `appendQuery`: throw on an array-of-objects query param instead of silently serializing `[object Object]`, so this whole class fails loudly. - Default the text tag-filter operator to `contains` so a partial value matches. - Tests: requestJson serializes the JSON param verbatim + the guard throws; the query schema keeps tagFilters a string; the decode helper round-trips. A full sweep of every GET/DELETE contract query field confirmed this was the only field of this class — logs filters and table filter/sort are unaffected. * fix(knowledge): reject tag-filter operators invalid for the field type Greptile P2: documentTagFilterSchema accepted any non-empty operator string, so an unsupported operator was silently dropped by the query builder instead of returning 400. Validate the operator against the field type's allowed set (single source of truth in filters/types) via superRefine. * fix(knowledge): validate tag-filter type against the slot, not the client claim Greptile P1: operator validation trusted the client-supplied fieldType, so a numeric slot could be sent with fieldType 'text' + 'contains' and slip through to build a text LIKE on a numeric column. Validate against the slot's inherent type via getFieldTypeForSlot (the source of truth): reject unknown slots and fieldType/slot mismatches at the boundary before checking the operator. * fix(knowledge): validate tag-filter values against the field type Greptile P1: value/valueTo were z.unknown(), so a number filter accepted 'abc', a date filter 'not-a-date', etc. — unusable values the query builder then silently dropped. Add a shared isValidFilterValue (single source of truth in filters/types) and reject unusable value/valueTo at the boundary, including the between upper bound. * fix(knowledge): only send a between tag filter once both bounds are set Cursor Bugbot: the strict valueTo validation made a partially-entered between filter (lower bound only) 400 and break the whole document list mid-entry. activeTagFilters now withholds a between row until both bounds are filled — consistent with already requiring the lower bound before sending any filter — so the list keeps loading while the range is being entered. * fix(knowledge): reject impossible calendar dates in tag filters Greptile P1: the date value check was format-only, so 2026-02-30 / 2026-99-99 passed the boundary and then made the document query's ::date cast throw a 500. Validate real calendar dates by round-tripping the parsed parts.
…rve prism side effects (#5261) Two post-extraction regressions: 1. The barrel resolves the Calendar name-collision to the date-picker COMPONENT (symmetric with Table). Scheduled-tasks imported Calendar from the barrel but used it as an ICON, so its header rendered a date picker. Route the icon consumers (scheduled-tasks + loading) to @sim/emcn/icons, matching the 'icons come from the /icons subpath' convention. 2. The package's new sideEffects: ['**/*.css'] marked code/prism.ts as side-effect-free, but it registers prismjs languages on the global Prism (a real JS side effect). The bundler could drop/reorder its core init, causing 'Prism is not defined'. Add code/prism.ts to sideEffects so the bundler preserves it.
prismjs language components (prismjs/components/prism-*) register on the global Prism that core installs; importing a component before core throws 'Prism is not defined' (in SSR and the client). The @sim/emcn extraction changed bundling so core no longer loaded eagerly first, exposing the latent bad order on the home (chat-content) and workflow-editor pages. - chat-content.tsx: import prismjs core first (it needs ts/bash/css/markup, which emcn does not register). - code-editor.tsx, input-format.tsx, code.tsx: drop the redundant prism-json/prism-python imports — these highlight via emcn's languages, which already registers js/json/python in the correct order.
…th (#5264) - Log per-request duration in the Presidio sidecar (/analyze, /anonymize) - Add durationMs to the mask-batch endpoint log line - Emit per-execution PII redaction timing (stringCount, totalBytes, durationMs, scrubbed)
…sim/workflow-renderer (#5263) Adds a @sim/workflow-renderer package with pure, props-driven WorkflowEdgeView, SubflowNodeView, and NoteBlockView shared by the editor and (future) docs preview. Moves block-dimensions constants into the package. Each editor node becomes a thin Container that wires stores/permissions and injects the editor-only ActionBar via a slot. No optimizePackageImports for the workspace component packages (avoids the toast-style module duplication); Tailwind scans the package source.
) Rebuild the dev-only minimal block registry from the canonical, toolbar-visible core (category blocks/triggers, not hideFromToolbar, latest version). Adds the visible workflow_input and table blocks (previously only the hidden `workflow` was present, so the Workflow block never rendered in dev:minimal), drops the superseded/hidden entries (api_trigger, chat_trigger, input_trigger, manual_trigger, router, starter, workflow), and hand-prunes the heaviest / rarely-core-dev blocks (mothership, pi, tts, stt_v2, image_generator_v2, video_generator_v3, circleback). Dev-only, gated on SIM_DEV_MINIMAL_REGISTRY=1; never aliased in production. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#5266) * fix(uploads): attach compiled binary for AI-generated docs, not source AI-generated documents (pdf/docx/pptx/xlsx) created in Chat are stored as their generation source, with the rendered binary in a separate content-addressed artifact store. Read/preview paths swap in the binary, but attachment/upload/provider paths downloaded the raw source — so a generated PDF emailed via Gmail (and 30+ other tools) arrived as the generator script renamed .pdf. - Add shared resolveServableDocBytes resolver + downloadServableFileFromStorage wrapper; the file-serve route now delegates to the same resolver so the two paths resolve identically. - Migrate ~34 attachment/upload/parse tool routes + the LLM provider attachment path to the servable download; media-only tools and source-editing paths keep the raw download intentionally. - Surface a retryable 409 (shared docNotReadyResponse) when a doc artifact is still compiling instead of shipping source. * fix(uploads): return retryable 409 for not-ready docs in slack/teams sends The slack send-message and teams write_channel/write_chat routes call download helpers that can throw DocCompileUserError while a generated doc is still compiling. Map it to the shared docNotReadyResponse 409 (matching the other migrated tool routes) instead of a generic 500. The provider attachment path is internal LLM execution (no HTTP response), so it intentionally propagates the typed error. * fix(uploads): not-ready 409 for uptimerobot, real MIME for non-doc, xlsx tests Address review findings: - uptimerobot create-psp/update-psp now map DocCompileUserError to the shared 409 (Greptile + Cursor flagged the gap alongside slack/teams). - downloadServableFileFromStorage returns the extension-derived MIME (getMimeTypeFromExtension) for non-doc files instead of an empty string when userFile.type is unset. - Add resolveServableDocBytes tests for the three xlsx branches (binary ZIP passthrough, not-ready throw under E2B+beta, no-workspaceId raw passthrough). * fix(uploads): enforce attachment size limits on resolved bytes Size limits were checked against userFile.size (source metadata) before resolution, but a generated doc resolves to a larger compiled binary — so a small-source doc could pass the pre-check yet exceed the service limit. Add a post-resolution check on the actual resolved bytes (mirroring docusign/vanta) across gmail send/draft/edit-draft, smtp, outlook send/draft, telegram, sftp, and teams; the cheap source pre-check stays as an early reject. * chore(uploads): drop extraneous inline comments from servable-file changes * fix(sftp): enforce 100MB cap on cumulative resolved bytes, not per-file The SFTP batch upload checked each resolved file against the 100MB cap individually, so multiple resolved attachments could each pass while their combined size exceeded the limit. Accumulate resolved bytes across the loop and reject once the running total exceeds the cap. * fix(sendgrid): reject attachments exceeding SendGrid's 30MB limit on resolved bytes SendGrid had no attachment-size guard, so a generated doc resolving to a large compiled binary could be sent and fail opaquely at the API. Add a post-resolution total-size check (30MB, SendGrid's documented message limit) matching the gmail/smtp/outlook routes.
…5265) * feat(telegram): add edit, forward, copy, location, contact, poll, pin, reaction, chat-action, and chat-info tools * feat(outlook): add reply, reply-all, folders, attachments, search, and message-update tools * feat(notion): add block children CRUD, comments, and users tools (v1 + v2) * docs(integrations): regenerate docs + catalog for telegram, outlook, notion tools * fix(notion): guard pageSize coercion with Number.isFinite so non-numeric input isn't forwarded as NaN * fix(telegram): normalize send_poll options (array, JSON string, or newlines) so json-typed input can't crash on .map * fix(integrations): harden outlook search quoting, notion archive default, and telegram poll options - outlook: strip embedded double quotes from the $search term so they can't break the quoted KQL query - notion: default the update_block Archive dropdown to 'Leave unchanged' so updates don't send an unintended archived:false restore flag - telegram: pass raw poll options through to the tool's normalizePollOptions (handles array/JSON-string/newlines) so the block layer no longer mishandles JSON-string input * fix(integrations): normalize outlook categories input and clamp notion pageSize - outlook: normalize update_message categories (array, JSON string, or comma/newline) so a JSON-string value isn't silently dropped - notion: clamp pageSize to Notion's 1-100 range (truncated) so out-of-range values don't hit an API error * fix(outlook): pass raw categories to the tool's normalizeCategories so the block handles JSON-string input too * fix(outlook): allow clearing message categories by passing an empty array An explicit empty array now sends categories:[] to clear all labels, a non-empty value replaces, and an absent/empty value leaves them untouched — matching the documented replace semantics. * fix(outlook): only clear categories on an explicit empty array, not a delimiter-only string A string that normalizes to no categories (e.g. just commas) is now a no-op rather than clearing all labels; clearing requires an explicit empty array. * fix(notion): clamp page_size to 1-100 at the tool layer for list comments/users and block children Adds a shared clampNotionPageSize helper so the agent-direct path is bounded to Notion's range, not just the block path. * fix(outlook): use consistent set/replace semantics for message categories Categories are replaced with the provided non-empty list and left unchanged when empty, consistent across the block and agent paths. Drops the ambiguous empty-array clear (clearing all categories isn't expressible unambiguously from the comma-separated field) and updates the description to match.
…View (#5267) * feat(workflow-renderer): extract pure SubBlockRowView from the block's summary row Splits the canvas block's collapsed subblock summary row into a pure SubBlockRowView (title + resolved displayValue + monospace flag) in @sim/workflow-renderer. The ~9 selector-name hydration hooks stay in the SubBlockRow container behind its memo comparator; the view receives only resolved strings. Byte-identical row JSX. First step toward the full WorkflowBlockView. * feat(workflow-renderer): extract pure WorkflowBlockView shell Moves the canvas block's render (header, badges, dynamic handles, ring) into a pure WorkflowBlockView in @sim/workflow-renderer. WorkflowBlock becomes a thin container that resolves all stores/hooks/permissions, builds the subblock rows + actionBar slots, and binds wouldCreateConnectionCycle (reads the edge store fresh per call to preserve cycle prevention). getHandleClasses/getHandleStyle move into the view; config.icon/bgColor, the webhook provider name, and every visual flag cross as props. Byte-identical JSX — every handle id/class/style/offset and badge guard preserved (verified by an independent adversarial audit). Container drops from 1137 to 829 lines.
…one, Resend, and S3 tool depth (#5270) * feat(firecrawl): add crawl status/cancel, batch scrape + status, extract status, credit usage tools * feat(resend): add audiences, broadcasts, and cancel-email tools * feat(pinecone): add delete/update vectors, index, and stats tools * feat(google-drive): add revisions, comments, and export tools * feat(elevenlabs): add voices, settings, models, user, sound-effects, speech-to-speech, audio-isolation tools * feat(s3): add bucket CRUD, head-object, presigned-url, and batch-delete tools * chore(api-validation): bump route baseline to 873 for wave-3 internal tool routes (s3, elevenlabs, google_drive export) * docs(integrations): regenerate docs + catalog for wave-3 tools * fix(integrations): audit fixes for wave-3 - pinecone: read camelCase vectorType/deletionProtection (with snake_case fallback) so list_indexes/describe_index populate them; make describe_index_stats casing defensive - google-drive: URL-encode fileId in the export route - remove extraneous inline/section-divider comments across new blocks/tools; convert type docs to TSDoc * fix(integrations): address review — elevenlabs settings bleed, batch-scrape job-id guard, s3 head-object existence - elevenlabs: select stability/similarityBoost by operation so a stale edit-settings value can't bleed into a TTS call - firecrawl: fail fast with a clear error when batch scrape returns no job id (avoids a misleading polling timeout) - s3: head_object on a missing key now returns exists:false instead of a generic failure * fix(s3): allow exists:false in head-object response contract (schema must match the missing-object output) * fix(pinecone): guard JSON.parse of ids/filter/values/sparseValues/setMetadata Malformed JSON-string input now throws a clear '<field> must be valid JSON' error via a shared parseJsonParam helper instead of crashing the request body builder. * fix(pinecone): enforce mutual exclusivity of ids/deleteAll/filter in delete_vectors Pinecone treats these delete selectors as mutually exclusive; the tool now requires exactly one and throws a clear error otherwise, instead of sending a conflicting body. * fix(integrations): I/O fidelity vs API docs (wave-3 audit) - pinecone: normalize describe_index_stats per-namespace vector_count -> vectorCount - firecrawl: remove phantom 'sources' from extract_status, add real creditsUsed/tokensUsed; expose batch_scrape maxConcurrency/ignoreInvalidURLs - google-drive: drop undocumented supportsAllDrives from the files.export URL - elevenlabs: add next_page_token input to list_voices (fixes pagination dead-end) - resend: surface segment_id on get_broadcast; declare replyTo + segment_id in block outputs
* feat(mship): secrets prompting t# with '#' will be ignored, and an empty message aborts the commit. * improvement(secrets): special tags improvement * fix(comments): fix pr comments
) * docs(readme): redesign README — animated hero + product demo A visual redesign of the top-level README: - Self-contained animated hero (logo, headline with cycle-loader, chat composer, and workflow + integrations peeks) baked into one looping image. - One combined demo GIF: Integrate / Ingest / Build / Monitor header over an animated product tour (chat → integrate → ingest → build → deploy → monitor). - Graphics rendered from the real product UI, full content width. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(readme): rebuild demo without dither to remove flat-area speckle artifacts Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(readme): rename feature label Ingest -> Context Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: andresdjasso <andresdjasso@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…5277) * chore(workflow-renderer): declare @sim/emcn dep + wire the package into docs Adds the missing @sim/emcn peer/dev dependency to @sim/workflow-renderer (it imports @sim/emcn in every View but resolved only via workspace hoisting). Wires apps/docs to consume @sim/workflow-renderer (dependency, transpilePackages, Tailwind @source) and adds remark-breaks (pulled transitively via the barrel's NoteBlockView export) — mirroring the @sim/emcn integration. Foundation for migrating the docs workflow-preview fork onto the shared Views. Build resolves the package/@source/remark-breaks cleanly. * feat(docs): render loop/parallel containers with the shared SubflowNodeView Replaces the forked PreviewContainerNode with a thin DocsContainerNode that maps the static preview data to SubflowNodeView's read-only (isPreview) props — no stores or hooks. Adds the block size to the preview node data so the view can size itself, and corrects the parallel example's start-edge handle id to 'parallel-start-source' (the view derives the handle id from kind). Deletes preview-container-node.tsx. Container colors/icons are now owned by the shared view (loop=blue, parallel=yellow). * feat(docs): render block nodes with the shared WorkflowBlockView Replaces the forked PreviewBlockNode with a thin DocsBlockNode that maps the static preview data to WorkflowBlockView's props — store-free, builds the subblock rows (condition/router Context+routes/default + tools + error) via SubBlockRowView, strips branch-id prefixes so the view's regenerated handle ids match, remaps router->router_v2, and keeps the framer-motion dim/stagger wrapper. Promotes resolveIcon into block-icons.tsx, adds the --workflow-edge token to docs global.css, deletes preview-block-node.tsx. The canvas diagrams now render with the real editor's view. * refactor(workflow-renderer): make editor-only WorkflowBlockView props optional The child-deploy, schedule, and webhook badge props (and their callbacks) only matter in the editor. Mark them optional and optional-chain the three callbacks so read-only consumers (docs, academy) can omit the whole group instead of passing ~18 explicit off-values. The editor still passes them, so its behavior is byte-identical (verified: apps/sim type-check clean). DocsBlockNode drops the off-props. * feat(docs): replace how-it-runs static diagrams with live WorkflowPreview Swaps the four static PNGs on the how-it-runs page for live, app-styled WorkflowPreview diagrams (concurrency, combination, condition+router branching, error path). Adds the four example workflows and renders error-port edges red to match the editor. The English page only; the translated execution/basics pages keep the PNGs. * refactor(workflow-renderer): the view owns condition/router/error rows Both the editor container and the docs adapter hand-built the condition/router/error summary rows in an order that had to stay in lockstep with the view's absolute handle-offset math — a three-way coupling with nothing enforcing it. The view now renders those rows itself from the conditionRows/routerRows it already receives (plus a routerContextValue prop for the router's Context row), so row order and handle geometry live together in one place. Both containers pass only data and their non-branch rows. Editor is byte-identical: getDisplayValue moves to where conditionRows/routerRows are built; the no-subBlock SubBlockRow path is already an exact SubBlockRowView(title, value) passthrough; the error row stays gated on shouldShowDefaultHandles. Verified apps/sim type-check clean. Docs now also renders the error row on condition/router blocks, which the real editor already did (shouldShowDefaultHandles is true for them) — an alignment fix. * refactor(docs): drop the parallel --wp-* token layer for the app/emcn tokens The workflow-preview ran a 25-token --wp-* mirror (22 were pure aliases of app tokens docs already defines) plus a .wp-scope wrapper class. Replaces every var(--wp-X) with its canonical app/emcn token (--wp-edge->--workflow-edge, --wp-highlight->--brand-secondary, badges->--badge-*, etc.), adds the one missing token (--divider), and deletes the .wp-scope blocks + class. Visually identical (aliases resolve to the same values); the preview now inherits the same design tokens as the shared views and the rest of the app instead of a hand-rolled parallel set. * refactor(docs): adopt emcn Badge + dedup resolveIcon in workflow-preview output-bundle's hand-rolled type badge (BADGE_COLORS + a styled span) becomes the emcn Badge (its green/blue/orange/purple/gray variants use the identical --badge-* tokens). resolveIcon, which had three copies, is now imported once from block-icons by output-bundle and block-inspector. * refactor(docs): rebuild the preview inspector on emcn chip primitives The lightbox inspector was a hand-rolled facsimile (raw divs + a CONTROL class string + inline dashed borders). It now composes from the same @sim/emcn primitives the live editor's sub-block controls wrap — ChipSelect/ChipInput/ChipTextarea(viewOnly)/ChipSwitch/ChipTag/FieldDivider/Label — so it reads as the real editor panel, fed example data (read-only, full opacity via readOnly/viewOnly, not greyed). Slider stays minimal (no emcn equivalent) but on app tokens. Props API and embedded/standalone modes unchanged. * refactor(docs): render the block-reference hero through the shared View Retires the hand-rolled BlockCard (a parallel reimplementation of WorkflowBlockView) and the BlockDisplaySpec data model. Each block hero is now a single-block PreviewWorkflow (block-display-workflows.ts) rendered through the same toReactFlowElements -> DocsBlockNode -> WorkflowBlockView pipeline as the diagrams, mounted in a minimal fitView ReactFlow (maxZoom 1.3, no canvas chrome). A single block can no longer drift from the canvas. * fix(docs): define sim's type scale + align the preview inspector to the editor Docs Tailwind v4 never defined sim's custom font sizes (text-small/caption/md/micro), so emcn components (Label, Badge, the shared views) fell back to inherited sizes — the inspector labels rendered huge. Adds the type scale to the docs @theme. Also aligns the inspector header to the real editor panel (surface-4 bar, size-[18px] rounded-sm icon, text-sm name) and removes the Connections section (and its now-dead prop/wiring). * fix(docs): inspector shows the full field list + dragged positions persist Inspector: shows the block type's full field list (from the reference data) with the example's values overlaid, so it reads like the editor panel instead of only the canvas summary rows. Drag: selecting another block no longer relayouts the canvas — node positions the viewer dragged are preserved across highlight/selection changes (only a different workflow relayouts). * feat(docs): highlight <> references + env vars; hide Ask AI over the lightbox; respace blocks Inspector text fields render the value with <...> block references and {{...}} environment variables highlighted in brand-secondary (a lean read-only port of the editor's formatDisplayText), in the canonical chip field chrome. The floating Ask AI widget is hidden while a preview lightbox is open. Plus the example-data respacing so the editor-faithful Error row no longer makes stacked blocks overlap. * fix(docs): make per-type field templates match the real block registry Audited every block type's field list (the source the inspector + block-reference heroes render) against apps/sim/blocks/blocks/*. Corrected drift to the registry's default-visible fields, titles, and order: agent gains Temperature; router gains Model; wait gains Async; schedule rewritten (default is Daily, not minutes); webhook_trigger expanded to its real default-visible set; human_in_the_loop notification title fixed. Provider-credential and advanced-mode fields stay hidden, matching the editor. Canvas diagrams keep their clean curated rows; the inspector now shows the full, real field list per the chosen clean-canvas/full-inspector split. * improvement(docs): taller default preview height so respaced diagrams aren't shrunk Bumps the default WorkflowPreview height 260->300 (the respaced, editor-faithful blocks are taller, so fitView was shrinking diagrams that relied on the default). The tall how-it-runs routing diagram gets 400. * improvement(docs): zoomable inline preview + taller default + themed controls The inline preview is now zoomable outside the lightbox: adds react-flow zoom/fit Controls (themed to the dark canvas chrome) and enables pinch-zoom, while keeping scroll-zoom off so the page still scrolls over the diagram. Pan-drag and click-block-to-inspect already worked. Default height 300->340. * improvement(docs): click canvas to expand; click empty lightbox to deselect Clicking the inline preview canvas opens the full lightbox; clicking empty space in the lightbox clears the selection, matching the real editor. * improvement(docs): reveal inline zoom controls on hover only The always-visible zoom controls felt heavy on the inline preview; they now fade in on hover (matching the expand button) and stay visible in the lightbox. * improvement(docs): drop zoom controls on the inline preview Inline preview keeps pinch-zoom, pan, drag, and click-to-expand; zoom buttons stay in the lightbox only. * improvement(docs): remove zoom controls from the lightbox too Both previews zoom via scroll/pinch and pan via drag; no on-canvas zoom buttons. Drops the Controls import and its theming CSS. * improvement(docs): match the real canvas — flat background + editor edge geometry Closes the last faithfulness gaps the audit found: removes the dot grid (the real editor hides its background — flat bg), aligns PreviewEdge to the editor's smoothstep math (borderRadius 8, offset 30) and 2px stroke (default + error edges), the selection ring to 1.75px, and minZoom to 0.1. Structural parity (blocks/handles/containers/colors/tokens) was already shared. Kept PreviewEdge rather than swapping to WorkflowEdgeView, which would clobber the docs-only highlight/dim/animate for no visual gain. * improvement(docs): rebrand the docs assistant as 'Ask Sim', styled like the real chat input Renames the floating assistant from 'Ask AI' to 'Ask Sim' (matching the platform's voice — you talk to Sim) and restyles the composer to mirror the home chat input: a rounded-2xl bordered field with the toolbar inside, and the same 28px circular send/stop button (the home's exact active/disabled colors + white/black arrow). Updates the lightbox hide-selector to the new label. * improvement(docs): match Ask Sim message styling to the mothership chat Aligns the user bubble (rounded-[16px] surface-5, text-base/primary, leading-23, max-w-85%) and the assistant markdown (text-base, 600 headings/strong, text-primary dashed-underline links, surface-5 code blocks) to the real mothership chat's user-message + chat-content treatment, instead of the prior generic text-sm rendering. The composer already mirrors the home user-input (rounded-2xl field + 28px circular send button). * improvement(docs): compact single-row Ask Sim composer The two-row layout left a tall dead gap (the docs widget has no toolbar buttons to fill the second row). The composer is now a single row — textarea with the circular send button inline — so it sits at the natural input height. * fix(docs): pass the router Context value to the shared view DocsBlockNode never set routerContextValue, so the view (which renders the router's Context row from that prop, not from rows) showed a blank Context even when the preview data authored a value like <start.input>. Extract it from the block's Context row and pass it through. * fix(docs): don't apply a block-type field template that doesn't match the block inspectorFieldsFor keyed the full field template purely off block.type, but some types are reused across roles (a table action block vs the table trigger, a webhook trigger vs the webhook action), so the wrong template was applied. Only use the template when the block's authored rows are actually a subset of it; otherwise fall back to the block's own rows. * fix(docs): connect preview edges to subflow container handles toReactFlowElements hardcoded targetHandle to 'target' and defaulted source handles to 'source', but Loop/Parallel containers (SubflowNodeView) expose a 'loop-end-source'/'parallel-end-source' output handle and a left input handle with no id. Edges into and out of containers therefore failed to connect. Resolve each edge end to the block's real handle based on whether it's a container. * fix(docs): don't expand the inspector template for blocks with no rows block.rows.every(...) is vacuously true for an empty rows array, so a block defined only by branches (e.g. a router in ROUTING_WORKFLOW) inherited the type template's invented field defaults. Require non-empty authored rows before applying the template. * fix(docs): render blank branch/router-context values as '-' like the editor The editor maps condition/router branch values and the router Context through getDisplayValue, which renders '-' for a blank value. DocsBlockNode mapped them to an empty string, so else branches and unset routes looked blank instead of matching the editor. Mirror getDisplayValue's empty-value handling. * fix(docs): show '-' for blank inspector branch values, matching the canvas inspectorFieldsFor passed raw branch.value into the lightbox branch fields, so an unset else route read blank in the inspector while DocsBlockNode (and the editor's getDisplayValue) render '-' on the canvas. Normalize the same way; drop the now-redundant placeholder.
) * improvement(settings): persistent layout + locked-down header API Mirror the Resource compound component's locked invariant for settings. - Move ALL page chrome (header bar, title/description, scroll region, centered max-w-[48rem] column, spacing) into the Next.js settings/[section]/layout.tsx via SettingsHeaderShell, so it persists across section navigation and never re-renders / re-lays-out. SettingsPanel becomes a thin registrar that feeds the shell its header data via a React context slot. - Lock the header API: actions is now SettingsAction[] (data only: text/icon/variant/active/onSelect/disabled, rendered as Chips) — no JSX, no <div>, no className, so a padding change is structurally impossible. Add a left 'back' slot for detail sub-views + an 'aside' escape hatch for the rare non-chip widget. - SaveDiscardActions component -> saveDiscardActions() helper returning the dirty-gated SettingsAction[]. - Migrate every panel page + the 5 in-section detail views (access-control group-detail, data-retention PolicyDetail, mcp, credential-sets, workflow-mcp) onto the layout/back-slot; they no longer hand-roll their own shells. - Chip labels are sentence case (Add override, Create server, ...); the action gap is owned once by the shell; no action <div>s. Documents the new contract in the settings rule + add-settings-page skill. * refactor(settings): cleanup pass — deref handlers, tooltip data field, parity fixes Address /cleanup + /simplify + per-page parity audit findings: - Foundation: shell dereferences action/back/search handlers from the config ref at call time, so a section re-render that changes a closure (e.g. a dirty-form onSave) can never leave the shell holding a stale handler. - Add SettingsAction.tooltip (shell renders the hover tooltip, incl. for disabled actions). Migrate the secrets-manager + workflow-mcp 'aside' tooltips to data actions — eliminates the per-page <div>-wrapped tooltip chips (Emir's no-div). - Parity: detail-view description no longer falls back to the section meta blurb (empty-description groups render blank again); secrets Save keeps no variant. - Sentence-case: group-detail back 'Access control'; empty-state prose 'Create API key' / 'Add tool' / 'Add server'. - Drop redundant array-level 'satisfies SettingsAction[]'; make SettingsPanel children optional (loading detail states drop the {null}). * docs(settings): document SettingsAction.tooltip in the settings rule * fix(settings): add key to header action chip (biome useJsxKeyInIterable) * fix(settings): address review — remove aside footgun, sticky tabs, restore tooltips - Remove the SettingsHeaderConfig 'aside' escape hatch (the last stale-prone, div-admitting path). Add SettingsAction.onPrefetch so the teammates Invite chip (hover-prefetch) is pure data — nothing renders header JSX now, so the signature-vs-ref staleness cursor flagged is gone. - useIsomorphicLayoutEffect for header registration: section switches flush the new header before paint (no stale/blank header frame). - group-detail: pin the config tabs (sticky top-0) so they stay visible while the detail body scrolls. - Restore the team-management Invite disabled-reason tooltip via the new SettingsAction.tooltip field. * refactor(settings): final audit pass — parity, sentence-case, import consistency From a line-by-line audit (+ React-docs validation of the click-time ref deref and isomorphic layout-effect patterns): - workflow-mcp detail: restore origin action order (Edit server, then the primary Add workflows) so the primary CTA stays rightmost. - Sentence-case the detail back-chip labels to match nav ('MCP tools', 'MCP servers'); fix the workflow-mcp list empty-state copy ('Add server'). - data-retention: import ArrowLeft from '@sim/emcn/icons' (canonical back-chip icon source, matching the other detail views); group-detail: import SettingsPanel from the package index, not the deep file path. - Document that scrollContainerRef is intentionally excluded from the header signature (refs are identity-stable).
…ctivity payloads (#5279) The native Slack trigger flattened every interaction into scalar event.* fields and dropped the structured objects, so view_submission and block-rewrite workflows could not read view.state.values, view.private_metadata, or message.blocks. Pass the full Slack view and message objects through, plus the top-level block_actions state (state.values), and declare them in the trigger outputs so they surface in the editor. Additive and backwards compatible: existing flattened fields are unchanged and new fields default to null.
…king feature flag (#5280) * feat(workspaces): gate workspace forking behind runtime workspace-forking feature flag * fix(workspaces): scope workspace-forking flag to AppConfig deployments to preserve self-hosted gate
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
Too many files changed for review. ( |
PR SummaryMedium Risk Overview Docs drops duplicated chip/dropdown UI and wires navbar, Ask Sim, inspectors, and badges through shared emcn chrome. Workflow documentation previews now render via README is redesigned (hero/tour GIFs, condensed quickstart). Settings authoring rules document layout-owned chrome, data-only Reviewed by Cursor Bugbot for commit 7bf8dba. Configure here. |