v0.7.18: landing, tools depth, media embeds in md editor, sonnet 5#5296
v0.7.18: landing, tools depth, media embeds in md editor, sonnet 5#5296waleedlatif1 wants to merge 26 commits into
Conversation
* chore(logging): remove redis-progress-markers feature flag Promote the Redis progress-marker write path to permanent behavior now that the flag is fully rolled out. Block markers always write to Redis (primary), keeping the durable jsonb_set UPDATE fallback when Redis is unavailable. Removes the flag registry entry, its REDIS_PROGRESS_MARKERS env fallback, and the per-session flag resolution in the logging session. * chore(logging): drop vestigial readProgressMarkers plumbing Follow-up to the redis-progress-markers flag removal. With the flag gone the completion fold always reads Redis markers, so the readProgressMarkers param (and its dead false branch) is removed end-to-end: - drop the param from completeWorkflowExecution and CompleteWorkflowExecutionParams - read progress markers unconditionally in the completion fold - delete the orphaned isFeatureEnabled mock and the flag-off / flag-throws marker tests (states the code can no longer produce)
…5288) * fix(workflow-renderer): validate dropbox host in note embed renderer Replace the bare url.includes('dropbox.com') check with a parsed-hostname match so attacker-controlled hosts (dropbox.com.evil.com, evil.com/?dropbox.com) no longer get treated as direct dropbox videos. Resolves CodeQL js/incomplete-url-substring-sanitization (#430). * fix(workflow-renderer): rewrite dropbox embed via parsed URL, tolerate scheme-less links Derive the direct video URL from the parsed URL object (rewrite hostname to dl.dropboxusercontent.com for any dropbox.com/*.dropbox.com host) instead of a www-only string replace, and accept scheme-less links. Fixes broken embeds for m.dropbox.com / bare-host links flagged in review.
…n util (#5290) * feat(rich-markdown-editor): live media embeds + shared embed detection util - Extract getEmbedInfo/EmbedInfo into pure @sim/utils/media-embed (carries the PR #5288 dropbox host-validation hardening); repoint the note block to it - Add LinkEmbed: a ProseMirror widget-decoration plugin that renders media players (YouTube, Vimeo, Spotify, Dropbox, …) beneath standalone links in the rich markdown editor, in both editing and read-only surfaces. The document stays a plain markdown link, so markdown round-trips stay lossless - Gate embeds behind an opt-in flag (on for the file editor, off for modal fields) - Polish the knowledge chunk editor to the file editor's centered reading frame while keeping it plaintext for exact embedding fidelity * fix(media-embed): gate provider detection on parsed hostname Validate each platform against the URL's parsed host before extracting, so a look-alike host (youtube.com.evil.com) or a provider domain in the path (evil.com/youtube.com/...) can no longer render a trusted-looking embed. Dropbox is no longer a special case — all providers share the hostMatches gate. Also consolidates the five Spotify branches and orders Twitch clip before channel. * fix(rich-markdown-editor): unique widget key per duplicate embed URL Key embed widgets by source + per-source occurrence index so two standalone links to the same URL render as two distinct players instead of collapsing into one, while keeping the key stable across unrelated edits (no iframe reload). * refactor(media-embed): tighten comments and drop a redundant guard - Drop the redundant paragraph type-check in getStandaloneLinkHref (the caller already filters to paragraphs) and rename the param for clarity - Remove an inline comment and a TSDoc sentence that restated logic documented elsewhere
…rello/Monday) + context.dev validation (#5289) * fix(context_dev): validation pass — add search numResults/country, accuracy fixes Comprehensive /validate-integration of all 22 context.dev tools against the live API docs found the integration clean (no correctness bugs). Applied the actionable items: - search: expose numResults (10-100) + country inputs (API supported them; users were silently capped at 10 results) - accuracy: scrape_html type description (+doc/docx), map meta description (+sitemapsSkipped), brand links description (+contact) - robustness: trim string query values in appendParam * feat(integrations): wave-4 tool-depth — Slack, Asana, Jira, Google Docs, Trello, Monday Deepen six existing blocks with 38 new tools, no new OAuth scopes (all under already-granted scopes), additive/backwards-compatible: - Slack (7): schedule/list/delete scheduled messages; archive/rename/set-topic/set-purpose conversation - Asana (8): create/get project, list workspaces, create subtask, delete task, add followers, create/list sections (via internal routes + contracts) - Jira (5): list/get project, get transitions, list issue types, get fields - Google Docs (6): delete content range, named ranges, paragraph bullets, update paragraph style (documents.batchUpdate) - Trello (7): create board/list, get board/card, add checklist/label/member - Monday (5): change column value, create board/column, get groups, duplicate item Route baseline 873->881 for the 8 new Asana internal routes. * fix(integrations): wave-4 validation pass — fix alignment enum, GraphQL input-object, scope/UI gaps Comprehensive /validate-integration of all 6 modified integrations (existing + new tools) vs live API docs. Fixes: - google_docs: CRITICAL alignment enum LEFT/RIGHT/JUSTIFY -> API enum START/END/JUSTIFIED (mapped); namedStyleType 'unchanged' option; 'zero-based' index wording - monday: CRITICAL search_items columns now emits GraphQL input-object with unquoted keys (was always failing the non-cursor branch) - slack: schedule_message DMs via user-id-as-channel; add channels:manage/groups:write/reactions:read scope descriptions; nextCursor optional - jira: list_projects expand=lead so lead outputs populate (was always null) - trello: get_actions limit now applies to the card path too - asana: add missing 'completed' + 'projects' subBlocks (were unsettable in UI); request permalink_url via opt_fields on create routes * fix(integrations): clamp context.dev search bounds; precise Google Docs index wording - context_dev/search: clamp numResults to the documented 10-100 range; normalize country to trimmed uppercase - google_docs: replace ambiguous '1-based'/'zero-based' index wording with the concrete fact (the document body starts at index 1), matching buildInsertLocation (index<1 appends) and buildContentRange * fix(integrations): validate context.dev country (ISO-2); regenerate google_docs docs - context_dev/search: reject non-2-letter country values with a clear error instead of forwarding them - docs: regenerate google_docs.mdx so the public index-contract wording matches the updated tool descriptions (body starts at index 1) * fix(asana): omit completed unless explicitly set (don't send false on unchecked) The new completion checkbox mapped an unchecked/untouched state to completed:false, which made update_task silently un-complete tasks and search_tasks filter to incomplete. Now only sends completed when the box is checked (undefined otherwise). * fix(slack): expose Destination toggle for schedule_message so DM scheduling is reachable The mapper already routes schedule_message DMs (user-id-as-channel); add schedule_message to the destinationType condition so users can deliberately choose Channel vs DM instead of it only triggering via leftover state.
* feat(providers): add Claude Sonnet 5 model - Add claude-sonnet-5 (1M context, 128k output, adaptive thinking with low/medium/high/xhigh/max effort) as the new flagship Anthropic Sonnet - Use introductory pricing ($2/$10 per MTok, $0.20 cached) in effect through Aug 31 2026 - Promote to recommended and set as Anthropic defaultModel; demote claude-sonnet-4-6 - Route claude-sonnet-5 through adaptive thinking in anthropic/core.ts (manual budget_tokens returns a 400) * fix(providers): expose temperature capability on claude-sonnet-5 Sonnet 5 accepts the temperature parameter (0-1, per Anthropic API docs), and it replaces claude-sonnet-4-6 as the default/recommended Anthropic model. Omitting the capability silently dropped temperature control for workflows on the default model. The request builder already strips temperature whenever thinking is active, so this only takes effect when thinking is disabled — where temperature is valid. * feat(blocks): default agent-family blocks to claude-sonnet-5 Propagate the Sonnet 5 flagship promotion to the block/executor/UI defaults so the default model is consistent everywhere: - agent/router/evaluator/pi block defaultValue + agent runtime fallback - executor AGENT/ROUTER/EVALUATOR DEFAULT_MODEL constants + pi-handler DEFAULT_MODEL - combobox model-field default fallback - update coupled tests (blocks, router/evaluator handlers, copilot model-suggestion validation) to the new default/recommended set Stagehand's anthropic model pin is left on claude-sonnet-4-6 (separate tool-internal choice, not a block default).
…lback) (#5276) * feat(db): resolve DATABASE_URL per role (DATABASE_URL_<ROLE> with fallback) * fix(db): pin realtime process to SIM_DB_ROLE=realtime so both pools share the role Without it, the realtime process left SIM_DB_ROLE unset: the shared @sim/db client defaulted role to 'web' (web pool profile + DATABASE_URL_WEB) while socketDb used 'realtime', so the two pools diverged after cutover. Set it at the process level (bootstrap + dev/start scripts), mirroring DB_APP_NAME, so the shared client and socketDb both resolve the realtime profile and URL.
… missing grammar (#5293) Consumers import { highlight, languages } from the @sim/emcn barrel, which re-exported Prism's highlight straight from prismjs. Bundlers resolved that passthrough directly from prismjs and skipped prism.ts's module body, dropping the side-effect grammar registrations so languages.json (etc.) were undefined at runtime. Prism then threw 'The language "json" has no grammar.', crashing the start-block file[] input format field and every other workflow-editor code highlighter. Own highlight as a local wrapper so the registrations stay in the dependency graph, and degrade to escaped plaintext when a grammar is missing instead of throwing.
* stash * feat(landing): mothership feature stages + pre-footer CTA Tell-then-show landing: the Mothership section defines the five capabilities (Mothership · Pod · Formation · Dispatch · Return); the Features section now shows each as a real Sim UI callout floating over a static, edge-faded platform backdrop (Linear's "callout over a faded platform" pattern). - FeatureStage template: copy + masked static LandingPreview + elevated callout - LandingPreview: static autoplay=false snapshots with per-stage view/workflowId - Callouts: Mothership chat, model picker, parallel-agents Formation graph, deploy targets, logs table - Pre-footer CTA set over the Mothership render; removed the old capabilities grid Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(landing): reusable platform-page + solutions-page layouts and routes Add config-driven, padding-safe layouts consumed by route pages: - platform-page: hero (shared CTA) + centered logos + N card rows (3|4), JSON-LD, single <h1>, server-only; Workflows route as first consumer. - solutions-page: structural mirror (kept separate to diverge later); IT, Engineering, Finance, Compliance, HR routes under /solutions. - Hoist shared LandingShell/HeroCta/Logos to components/ (top-level = shared); refactor hero to consume them. - Restructure all of (landing) to the workspace folder-per-component convention (each component in its own folder + index.ts barrel). * refactor(landing): convert hero-visual CSS-module keyframes to Tailwind Move the hero-visual + stage-home keyframe animations out of CSS modules into tailwind.config (matching the existing dash-animation pattern) and delete both module.css files. Components now use animate-hero-* utilities + arbitrary properties for the per-element delays, SVG stroke draw, and gradient shimmer; reduced-motion preserved via motion-reduce: variants. Upgrade the shimmer's hardcoded #b4b4b4 to the --text-subtle token. brand-tokens.module.css is intentionally kept: it reassigns --surface-*/ --text-* token VALUES via a doubled-class selector for specificity over .light, which Tailwind utilities cannot express. * refactor(landing): move brand palette from CSS module into LandingShell Replace brand-tokens.module.css with a BRAND_TOKENS constant of Tailwind arbitrary-property utilities applied on the LandingShell wrapper, so the brand hex lives in the component, not a stylesheet. They emit in the utilities layer and override .light (@layer base) by cascade order — verified the brand --text-primary (#121212) wins over .light (#1a1a1a). No more .module.css files remain in the landing. * chore(landing): remove Testimonials from the home page for now Drop <Testimonials /> from the landing composition (component kept for re-adding later). * feat(landing): hero send→loader→workflow animation + landing WIP Hero visual: clicking send zooms into the button, morphs the disc into the gooey thinking loader (held, then cycling), slides it straight across to a phrase indicator with the camera following (no zoom-out), then zooms back out as the reply types and the chat morphs into the GitHub→Agent→Jira workflow. The chat card holds a fixed size through the zoomed scene and the greeting reserves its space, so nothing drifts; the user bubble reveals only on zoom-out. Loader ink tweens dark→gradient via the thinking-loader stop-color/flood-color transition. Also folds in in-progress landing work: knowledge + integrations feature callouts, CTA chat, mothership + line-glyph, wordmark tweak; removes the ethos and testimonials sections. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(landing): responsive pass for iPad + mobile Make the landing page fully responsive while keeping the desktop layout byte-identical (desktop classes stay the unprefixed baseline; smaller screens layer max-* overrides on top). - Navbar: hide desktop clusters below lg, add MobileNav hamburger sheet (scroll-lock, Escape/tap close, reduced-motion aware) - Hero: collapse the absolute split (visual + logos) to a stacked column below xl so iPad-landscape avoids the headline/visual collision - Mothership: 4-col grid steps to 2 (tablet) then 1 (phone) - Features: drop the floating callout below md, show the un-masked backdrop preview full-width - CTA + Footer: scale type/padding; footer 7-col steps to 3 then 2 - Document the breakpoint strategy in the landing CLAUDE.md Also includes the in-progress mothership goo/iso brand marks and the marks-lab preview route the section depends on. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(landing): align hero visual panel to text + logos extent Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(landing): delay hero user bubble until card finishes expanding The grey user bubble's fade-in raced the card's upward grow on send. Hold the bubble's reveal until after the parent-driven grow settles so the card expands fully before the bubble appears. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(landing): isolate new landing — remove dead old-folder code + --landing-* coupling - Delete dead (landing) auth-modal (a duplicate of (home)'s, still on the old --landing-* / dark tokens) — its removal drops the new landing's last styling tie to the old landing. - Delete 5 merge-orphaned, zero-consumer callouts (deploy-callout, mothership-chat-callout, mothership-chat-preview, workflow-graph-preview, model-picker-preview). - Relocate the one live preview (logs-table-preview) into its consumer features/components/ + add a barrel; dissolve the owner-less feature-callouts/ shell. - Fix stale --landing-bg-surface reference in landing-preview-mount. (landing) now has zero (home) imports and zero --landing-* token usage. * refactor(landing): token-map hex, fix a11y/SEO, align structure Styling (within (landing)): - Replace ~90 hardcoded hex colors with the in-scope brand tokens they already equal (--surface-*/--text-*/--border*); divider edges -> --border, field/card edges -> --border-1. Delete the redundant C color-palette mirrors in the landing-preview home/sidebar and route them through tokens. - Convert static inline SVG styles (display:block/outline:none) to Tailwind. - 6 un-tokenizable hexes remain (dark send-button fills, status-green dot) — no brand token exists; left as-is. a11y / SEO: - Decorative mothership goo/iso marks: role='img'+aria-label -> aria-hidden. - Preview chrome titles <h1> -> <span> (kills duplicate client-only H1s). - sitemap.ts: add /workflows and the five /solutions/* routes. Structure: - Folder the bare logo-mark/mobile-nav leaves + barrels; complete the navbar components barrel and consolidate navbar.tsx to a single barrel import. * style(landing): restore taller hero panel with border-shadow chip chrome - Revert the right visual panel to the previous full-height framing (top-8 bottom-8) — hero text (pt-[112px]) and the logos panel are untouched, so their positions and spacing are unchanged. - Apply the canonical border-shadow chip surface: --surface-2 fill + the shared chipBorderShadowRing (1px hairline ring + soft drop shadow) from emcn, the documented chrome for a landing media panel. * feat(landing): swap Volvo for thinkproject and reposition hero logos - Replace Volvo with the thinkproject wordmark (official SVG, tagline/descriptor cropped out, all paths unified to --text-primary #1a1a1a; aspect 6.01). - Reorder the shared 6-logo set so the 3x2 hero grid reads: Rivian|VW (top-left), eXp Realty (top-center), Russell (top-right); Artie (bottom-left), thinkproject (bottom-center), Mobile Health (bottom-right). - Enlarge Rivian|VW a touch (height 15 -> 17, same aspect). - eXp Realty, Artie, Russell, Mobile Health, Rivian|VW all retained. * style(landing): size hero description with the type scale (text-lg) Replace the arbitrary text-[20px]/text-[16px] on the hero description with named scale tokens — text-lg (18px) desktop, text-md (16px) on phones — a touch smaller and the canonical lead size (1.2x the platform's 15px base). * style(landing): hero headline "for AI automations" with break after "agent" Replace "solving automations" with the higher-intent "AI automations" and move the line break after "agent" so "for AI automations." sits on the second line. * style(landing): unify CTA radius and box hero logos in cards - HeroCta email bar: rounded-[13px] -> rounded-lg, so the bar, the inset Book-a-demo chip, the Sign-up chip, and the navbar chips all share one radius. - Hero logos: box each wordmark in a bordered --surface-1 card (platform card chrome: rounded-lg + --border-1, 100px tall) on a responsive 3-up grid (2-up on phones) at a consistent gap-5 rhythm. Wide marks scale to fit (max-w-full h-auto). The platform/solutions 'row' layout stays bare wordmarks. * style(landing): concentric CTA bar radius + tighter logo cards - HeroCta email bar back to rounded-[13px] (= inner chip 8px + ~5px inset) so the Book-a-demo chip's right corners nest concentrically inside the bar. - Logo cards: smaller and tighter — h-20 (80px), px-4, gap-3 (12px, the product UI card-grid rhythm). * style(landing): restore 100px logo cards, scale icons down 15% The 80px cards read too wide-for-their-height. Restore h-[100px] (keeping the tighter gap-3/px-4) and instead shrink the wordmarks to 0.85x their optical size in the grid via GRID_ICON_SCALE — row layout unchanged. * style(landing): match sign-up radius to email bar + shrink logo icons - Sign-up chip overridden to the email bar's rounded-[13px], so the two hero CTAs share one corner radius. - Logo icons: GRID_ICON_SCALE 0.85 -> 0.65 and card padding px-4 -> px-2; card dimensions (h-[100px], gap-3) unchanged. * style(landing): shrink hero logo cards Cards read massive — too tall (100px) and stretched to fill the panel. Drop to h-16 (64px), cap width at w-[150px], and make the grid w-fit so it hugs the cards instead of stretching. gap-3 and the 0.65 icon scale unchanged. * style(landing): upscale hero logo cards ~25% Cards read too small. Bump all dimensions: h-16->h-20 (80px), w-[150px]->w-[180px], px-2->px-3, and icon scale 0.65->0.8. Grid stays content-hugging at gap-3. * style(landing): taller logo cards, larger icons, reorder top row - Card height h-20 -> h-[88px] (width w-[180px] unchanged), icon scale 0.8 -> 0.85. - Top row reordered: eXp (left), Russell (center), Rivian|VW (right). * style(landing): more card height, swap top-row Rivian/eXp back - Card height h-[88px] -> h-24 (96px); width unchanged. - Top row: Rivian|VW (left), Russell (center), eXp (right). * feat(landing): add "Trusted by technical teams at" label above hero logos Top-left, gap-3 above the logo grid (matching the grid rhythm); text-sm (navbar text size) in --text-muted (the label token). * style(landing): recolor logos to --text-body, match label gap to hero rhythm - Recolor all six customer logo SVGs to #3b3b3b (--text-body light value), so they match the Sim navbar wordmark's color. Landing is light-only, so the hardcoded value always equals var(--text-body). - Trusted-by label gap gap-3 -> gap-[22px] (the hero's description->CTA spacing). * style(landing): scale hero CTA down a hair, drop radius to the nav chip's Sign-up read too round. Take the bar + Sign-up to h-[40px] / rounded-lg (8px, the navbar chip radius), and keep the inset Book-a-demo concentric: h-[2em] + rounded (4px) with a 4px inset (8 = 4 + 4). * style(landing): round Book-a-demo to rounded-md to match the bar curve rounded (4px) read too square next to the bar's rounded-lg (8px). Bump to rounded-md (6px) — echoes the bar's curvature, still inside the 4px inset. * style(landing): match Book-a-demo proportions to the navbar chip Restore h-[2.143em] (the chip's 30/14 height ratio); with px-[0.571em] (its 8/14 padding ratio) and the 16px label, Book-a-demo now shares the navbar chip's exact height/padding/text proportions. * style(landing): equal inset around Book-a-demo (h-[30px]) Button was h-[2.143em] (34.3px) -> only ~1.9px top/bottom vs 4px right inside the bar's 38px inner box (40px minus the 1px border). Drop to h-[30px] (the nav chip height) so it centers to an equal 4px inset on top, bottom, and right. * style(landing): enlarge Book-a-demo to h-[32px], tighten inset to 3px h-[30px] read too small/airy in the bar. Bump to h-[32px] and pr-[4px] -> pr-[3px] so the inset is an equal, snugger 3px on top, bottom, and right. * style(landing): lift hero logos off the bottom again (pb-20) Restore the 80px bottom padding so the logos rest 112px above the section bottom (mirroring the hero text's 112px top) instead of sitting flush with the visual panel's bottom. max-xl:pb-0 keeps the stacked layout tight. * improvement(landing): refine hero and mothership visuals * fix(landing): cap hero fold height so it doesn't stretch on huge monitors The section was min-h-[calc(100vh-62px)], so on very tall displays both absolute panels (top-8 bottom-8) stretched — the visual panel grew gigantic and the bottom-anchored logos sank to the very bottom. Cap the fold at 960px via h-[min(calc(100vh-62px),960px)] (min-height can't be capped by max-height): the whole hero stops growing, panels/logos stay proportioned like a large laptop, and the next section just starts below. Laptops (<=16in) are unaffected; max-xl:h-auto keeps the stacked layout below xl. * refactor(landing): session cleanup — DRY CTA label, drop dead grayscale Final tidy after this session's hero/CTA/logo iteration: - hero-cta: extract the duplicated 16px label knob (px-[0.571em] + text-[16px] + font-size:inherit) into a single CTA_LABEL constant, matching the 'single knob' the TSDoc already describes — used by both Book-a-demo and Sign-up. - logos: remove the grayscale filter (now a no-op — all wordmarks were recolored to a single #3b3b3b), inline the single-use LOGO_GAP_X, and flatten the nested cn() into plain layout ternaries (dropping the now-unused cn import). * improvement(landing): animate mothership illustrations * style(landing): solid-ink branding + hero cursor/loader polish Branding: drop the bespoke BRAND_TOKENS palette and bottom-reveal from LandingShell (use the platform's own light tokens); re-ink the wordmark, logo-mark, and hero loader from the gradient+glow to a solid --text-body so the marks read as one ink with the nav text. Add a `shimmer` prop to ThinkingLoader for a static --text-body label, and stroke the squeeze arcs with the shared gradient. Hero visual: the cursor now enters from below the field and chases the send button live through the zoom (retimed beats, no arrive-then-wait); the greeting fades in gently instead of shimmer-revealing; the click ring becomes a press-dip (hero-cursor-press replaces hero-click-ring and hero-greeting-reveal). Extract BlockHandles so the morphed GitHub card carries a real edge handle in scene space; seed the compose card at its true height; pop the sent bubble in immediately. * improvement(landing): update feature iso-marks to perfected geometry Re-author the four Mothership iso-mark illustrations (Integrate, Ingest, Build, Monitor) on the refined isometric geometry, keeping the existing animation vocabulary intact: hover line-draw plus per-mark auto-motion (integrate float, ingest pulse, monitor panel-separate, build grid-flow). Map the raw exports onto the shared token palette/line weight for consistency and tune per-mark sizes for one optical weight. Build is now pure CSS (grid-flow replaces the RAF wave), so it drops 'use client' and renders as a server component. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(landing): add pricing, privacy, terms, and changelog pages - New public /pricing page: Free/Pro/Max/Enterprise cards with the full comparison breakdown transposed from shared upgrade data + JSON-LD; prices, CTAs, and features derive from shared billing constants so they can't drift from the in-app upgrade page. - Migrate /privacy, /terms, and /changelog into the (landing) route group via a shared prose-page system (single source of truth for legal/prose chrome). - Landing polish: solid-ink iso-mark illustrations + footer/cta/features/ mothership spacing and token cleanups; sitemap adds /pricing. - Audit pass: crawlable ChipLink CTAs, correct heading hierarchy, structured-data featureList derived from the visible comparison data, legal plan name Team->Max. * large edits across landing finalization * feat(auth): port OAuth-only signup + Microsoft provider from staging Align auth-page logic with origin/staging (PR #5073) while keeping the new chip-styled UI: - Add Microsoft as a better-auth social sign-in provider (auth.ts) and surface it through the OAuth provider checker, providers API + contract, login/signup forms, SocialLoginButtons, and the landing auth modal. - Gate email/password signup behind the emailSignupEnabled server flag (DISABLE_EMAIL_SIGNUP) so signup becomes OAuth-only when configured. - Add DISABLE_MICROSOFT_AUTH / DISABLE_EMAIL_SIGNUP env + feature flags. * fix(icons): render brand icons legibly when bare and on light tiles (#5292) Monochrome brand icons hardcoded a single white or black fill matched to their colored tile, so they vanished when rendered bare on the home Suggested actions list (white-on-white in light mode, black-on-black in dark mode). Convert those marks to currentColor so they adapt to context, and make tile foregrounds contrast-aware via getTileIconColorClass instead of a hardcoded text-white. Also centralize all color math in apps/sim/lib/colors (perceived brightness, hex/rgb/hsl conversion, contrast-text) and route every consumer through it: the bare-icon audit, block tiles, logs trace view, whitelabeling theming, workspace presence, and the PPTX renderer no longer carry duplicate copies. Adds a bare-icon CI audit (scripts/check-bare-icons.ts) and authoring guidance. --------- Co-authored-by: Emir Karabeg <emirkarabeg@berkeley.edu> Co-authored-by: andresdjasso <andresdjasso@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Waleed <walif6@gmail.com>
|
Too many files changed for review. ( |
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Auth moves off the dark Integrations (wave 4) adds many new blocks and matching docs: Slack (scheduled messages, conversation admin), Asana/Jira/Google Docs/Trello/Monday expansions, plus context.dev doc updates (search params, scrape types, brand Realtime DB now sets Quality gates: CI runs Cursor/rules: SEO/constitution globs shift from Agent skills: large new Reviewed by Cursor Bugbot for commit ad19f7f. Configure here. |
… polish (#5298) * chore(landing): cleanup pass — size-* shorthand, drop redundant refs/memos, changelog useInfiniteQuery - emcn: collapse 29 square h-N w-N pairs to size-* across models/integrations/blog/faq/landing-preview - landing-preview: remove redundant animationKeyRef (functional setState) + dead isDesktopRef - model-directory: hoist static provider options to a module const - auth-modal: drop useMemo over the cheap getBrandConfig() call - changelog: replace useState+fetch pagination with a co-located useInfiniteQuery hook (first page stays SSR-seeded via initialData) * feat(landing): URL-state filters via nuqs (SSR-friendly) + stars fallback bump - integrations grid, models directory: search + category/provider filters now live in the URL (nuqs useQueryStates), server-parsed via createSearchParamsCache so filtered views render server-side (crawlable, shareable) — mirrors the blog index SSR pattern. Search URL writes debounced; in-memory filtering stays instant. - pricing: billing-period toggle moves to ?billing=annual (shareable, no flash). - co-located search-params.ts per page as the single source of truth (server + client). - stars: bump fallback floor 28800 -> 28900 to track the current count. * fix(landing): use the light sim mark (not green) in the integration CTA Replace brandbook/logo/small.png — referenced only by the 'Start automating {service} today' CTA on integration pages — with the black-on-light sim mark so the tile reads as a neutral brand mark beside the partner icon instead of a green block. * fix(landing): calmer release-timeline dot hover Drop the scale-150 + brightness-75 hover (a 50% size jump plus a muddy darken) for an understated opacity-fill (0.85 -> 1) with a slight scale-110, matching the comparison chart's opacity-driven hover language. * fix(landing): keep changelog load-more when initial page is empty; drop inline comments - changelog: getNextPageParam no longer treats an empty server-seeded page 1 as end-of-feed, so a failed/empty initial GitHub fetch still surfaces 'Show more' (addresses Cursor Bugbot). - replace the inline comments added in this branch with TSDoc on the search-param caches (documents the dynamic-render → SSR-filtered behavior), per the codebase's TSDoc-only convention. * revert(landing): keep the original changelog timeline (drop useInfiniteQuery) The React Query conversion of an SSR-seeded, cross-origin, infrequently-changing paginated list introduced caching edge cases (empty-seed load-more, singleton cache serving stale page 1 on client-side nav) without real benefit. Restore the original useState(initialEntries)+fetch timeline, which is simpler, correct, and already review-clean from #5181.
…#5297) * feat(input-format): upload files in file fields via the file uploader The file field in the start-block input format only offered a raw JSON editor expecting hand-written base64 objects, which users routinely filled with junk (local paths, raw text, leftover placeholders) and which never actually fed a run. Reuse the existing FileUpload component for file-typed fields: - Add an opt-in controlled mode (value/onValueChange) to FileUpload so it can be embedded where the value lives outside a subblock; store-bound consumers (stt/vision/agent) are unchanged. - Render the uploader for file fields, with a toggle to fall back to the raw JSON editor for power users / legacy values. - Detect file fields by normalized type (file[]/files/file/image) so copilot/API-authored variants render correctly too. - Wire editor-attached files (already uploaded, run-ready) into manual runs via the executor's files channel; chat/API runs still override. Backwards compatible: the inputFormat array shape is unchanged (file values are stored as a JSON string of run-ready file objects); legacy free-form values open in JSON mode so nothing is lost. * refactor(input-format): extract file adapters, share run-input builder, harden types Follow-up cleanup from /simplify + /cleanup review: - Extract pure file adapters into input-format-files.ts (filesToControlValue, controlValueToFiles, serializeInputFormatFiles, defaultFileFieldMode) so they are unit-tested without a DOM; add tests. - Derive InputFormatFile from the canonical executor UserFile so the editor and runtime file shapes can't drift. - Consolidate the two manual run-input builders into one buildInputFormatInput helper so manual run and run-from-block handle files identically. - Narrow file-field detection to the canonical file[] (matches the field-type dropdown and the existing execution/webhook file paths) so no pre-existing non-file[] field changes behavior. - defaultFileFieldMode parses once; the file value is only parsed in upload mode. - Add lib/component unit tests (45 passing). * fix(input-format): require run-ready file shape, don't clobber named files input Addresses review (Greptile P1s): - parseInputFormatFiles now requires the full run-ready shape (id/name/url + finite size + type), so a partial file can't open in uploader mode or reach workflowInput.files only to be rejected by normalizeStartFile (which would silently drop every file). - buildInputFormatInput no longer overwrites a user field literally named 'files' with the upload channel; that reserved-name collision is left for the executor to surface. * fix(input-format): require file key, keep mixed/partial values in JSON mode Addresses review round 2 (Greptile P1 + Cursor): - parseInputFormatFiles now requires a non-empty key (the uploader always sets one); an external/signed URL with no recoverable key no longer opens uploader mode or reaches workflowInput.files only to be rejected. - defaultFileFieldMode uses the uploader only when EVERY entry is run-ready; a mixed array with any legacy/partial entry stays in JSON mode so the uploader can't drop the entries it can't represent on the next save. * fix(input-format): recover internal-url keys, gate uploader to lossless values Addresses review round 3 (Greptile P1 + Cursor): - parseInputFormatFiles accepts a key-less file when its url is an internal /api/files/serve/... url (the executor recovers the key from it, same as normalizeStartFile); only a missing key with a non-internal url is rejected. - The file field offers the uploader only when it can represent the stored value losslessly (empty or all run-ready); for mixed/legacy values it forces JSON mode and hides the toggle, so a sticky 'upload' preference can no longer drop entries the uploader cannot show on save. * fix(input-format): require non-empty id/name/url/type in parseInputFormatFiles Addresses review round 4 (Greptile): normalizeStartFile rejects falsy id/name/url/type and file normalization is all-or-nothing, so an empty-string field (e.g. hand-edited value with an empty id + internal url) would open in uploader mode and drop every file from the run. Require non-empty strings to match the executor. * fix(input-format): validate recovered internal-url keys via parseInternalFileUrl Addresses review round 5 (Greptile): isInternalFileUrl only checks the URL prefix, but the executor parses+decodes the key. A malformed internal URL (no extractable key) passed the prefix check, got collected into workflowInput.files, then normalizeStartFile rejected it and dropped the whole files array. Now mirror the executor exactly — attempt parseInternalFileUrl and require a real key. Tests use a realistic recoverable internal URL. * fix(input-format): uploaded files always own the files channel Addresses review round 6 (Greptile): files is NOT in the executor's reserved input-format names (EXECUTION_CONTROL_OUTPUT_FIELD_NAMES), so the previous guard silently dropped uploaded file[] values whenever a plain field named files coexisted. files is the start block's canonical file channel (the chat trigger names its own file field files), so uploaded files now always populate it and take precedence — dropping real attachments is the worse outcome, and making files a reserved-name error isn't viable since it's the legitimate file-field name. * chore(input-format): tighten parseInputFormatFiles comment
…e pricing credits (#5299) * refactor(landing): buildLandingMetadata helper + derive pricing credit cells - Add lib/landing/seo.ts buildLandingMetadata(), the single source of truth for the shared landing OpenGraph/Twitter/robots/canonical chrome; migrate 13 static landing pages to it (drop ~470 lines of duplicated literals). Output is identical per page (verified: rendered head tags unchanged, render mode unchanged); partners additionally gains the standard authors/creator/publisher it was missing. - Drop the now-dead PAGE_URL const + SITE_URL import from the 12 migrated pages that no longer reference them (partners keeps both for its JSON-LD). - comparison-data.ts: derive monthly/daily credit cells from CREDIT_TIERS, DEFAULT_FREE_CREDITS, DAILY_REFRESH_RATE and a new CREDITS_PER_DOLLAR constant instead of hardcoding, so they can't drift (values byte-identical). * refactor(billing): bind comparison columns to credit tiers by name Look up Pro/Max tiers by name instead of array position so the comparison table can't silently bind to the wrong tier if CREDIT_TIERS is reordered or a tier is inserted (addresses Greptile P2). Values unchanged.
* feat(broadcast): add july-1 newsletter (template, assets, font)
* fix(broadcast): rasterize email logo + flow icons to PNG for client compatibility
Gmail and Outlook strip inline <svg> and don't reliably render <img src=*.svg>,
so the header wordmark and the four flow-mark icons could render blank/broken.
Swap to hosted PNGs (logo.png + readme-*-mark.png, transparent, hi-res) with
alt text, matching the v0.5/v0.6 broadcast pattern. Remove the unused SVGs.
* improvement(broadcast): rename july-1 assets to semantic names
Drop the vestigial readme-/real- prefixes for the self-contained newsletter
folder: flow marks -> mark-{integrate,context,build,monitor}.png (context now
matches its label), screenshots -> feature-{chat,tables,knowledge,files,scheduled-tasks}.png.
* fix(broadcast): correct stale model name in newsletter copy
Claude Fable 5 was added in #4921 but removed in #5020, so it is no longer in
the model catalog. Replace it with Claude Opus 4.8 (current flagship in
providers/models.ts) so the newsletter doesn't advertise an unavailable model.
…d, typing state/duration (#5300) * improvement(sendblue): audit fixes — optional group numbers, seat_id, typing state/duration * fix(sendblue): guard group recipients and typing state/duration before request * fix(sendblue): omit empty numbers array from group message body * test(sendblue): add webhook handler tests; trim group_id and normalize empty group_id to null * fix(sendblue): trim and drop blank group recipients before target guard
) * feat(linq): audit fixes + native auto-registering webhook trigger Tools/block audit (validated against the live Linq partner API + OpenAPI spec): - create_chat: read the sent message from top-level response.message (was always null) - get_message/edit_message: expose canonical deliveryStatus; mark is_delivered/is_read deprecated - send_message: fall back to from_handle.service/preferred_service for service output - list_phone_numbers: migrate deprecated health_status to reputation; add forwardingNumber; guard JSON parse - check_imessage/check_rcs: guard response.json() parse - mark_chat_read: note 1:1-only / group no-op behavior Native webhook trigger (auto register + deregister): - 6 triggers (message received/delivered/failed/read, reaction added, all-events) - Standard Webhooks signature verification (HMAC-SHA256, whsec_ secret) - createSubscription/deleteSubscription manage the Linq subscription lifecycle - event_id idempotency; full 27-value WebhookEventType enum for all-events - regenerated docs * refactor(linq): drop phantom create_chat response path, complete deliveryStatus enum doc Final validation against the raw Linq OpenAPI spec confirmed the sent message is at chat.message (CreateChatResult exposes only chat), so the data.message fallback was dead code. Also list all 7 DeliveryStatus values in the send_message output description. * fix(linq): namespace trigger credential keys, handle edit_message 204, nullable forwardingNumber Review + final pre-merge audit fixes: - Trigger apiKey/phoneNumbers subblocks collided with the block's tool apiKey state key — rename to triggerApiKey/triggerPhoneNumbers (per the namespacing rule from #2133) and read them in the webhook handler - edit_message: the API returns 204 No Content when editing an already-deleted message; guard the empty body instead of throwing on response.json() - list_phone_numbers: mark forwardingNumber output nullable (returns null) - check_rcs: tighten address hint (RCS is phone-only, not email) - regenerated docs * fix(linq): read triggerApiKey in webhook deleteSubscription deleteSubscription still read config.apiKey after the credential rename, so undeploy would skip the DELETE and orphan the Linq subscription. Match createSubscription's triggerApiKey key. * fix(linq): mark list_phone_numbers healthStatus output nullable healthStatus returns null when Linq omits reputation/health_status; declare nullable: true to match the runtime value (same as forwardingNumber). * fix(linq): mark nullable list_webhook_subscriptions item fields phoneNumbers/createdAt/updatedAt are null-coerced by mapWebhookSubscription; declare nullable: true on the array-item schema to match runtime (consistent with the top-level webhook outputs' optional flags).
… dead weight (#5303) * perf(landing): viewport-gate the Features workflow preview The preview is code-split (ssr:false) but was mounted eagerly, so its reactflow + framer-motion chunk (~85-100 KB gz) downloaded right after hydration despite sitting below the fold. Gate the dynamic mount on an IntersectionObserver (400px preload margin, loads once), reusing the existing dimension-stable aspect-[1116/615] placeholder so there's zero CLS. * perf(landing): memoize integration-grid filtering and the row Derive the category facets and a per-integration lowercased search index once from the (stable) integration list instead of rebuilding + re-lowercasing ~3.5k strings on every keystroke, and memo IntegrationRow so the ~220 rows don't all re-render per keystroke. Match semantics are identical (per-field includes). * chore(landing): drop orphaned assets, unused fonts, and dead component Remove unreferenced public/static/mothership.gif (1.5 MB) and public/landing/sim-mothership.webp (87 KB), the unused static Season font weights (only the variable woff2 is loaded), and the unused CtaChat component. * perf(landing): subscribe the hero resize listener once via a phase ref The resize effect re-subscribed on every phase change (~30x/loop); read the current phase from a ref so the listener is added once for the component's life. * perf(landing): load preview eagerly when IntersectionObserver is unavailable Graceful degradation for browsers/WebViews without IntersectionObserver — set inView immediately instead of leaving the preview stuck on its placeholder (addresses Greptile P2).
…n the label row (#5304) The file field's mode switch was a right-aligned 'Enter JSON manually' text link on its own row, causing awkward spacing above the control. Replace it with the canonical sub-block mode toggle: a compact left-right arrows (ArrowLeftRight) icon button with a tooltip, placed on the 'Value' label row (label left, toggle right), matching the Files subblock header. Removes the extra row and aligns spacing.
* feat(forking): resource copying UX to help with setup speed * update UX nits * address comments * fix canonical modes and dependson behaviour in tool input * fix skill memory bounding;
…5305) * fix(media-embed): remove ReDoS-prone regexes in host-gated providers Replace the unbounded '.*' patterns flagged by CodeQL (js/polynomial-redos) in the YouTube, Facebook, and Giphy branches with bounded extraction off the parsed URL (pathname / searchParams). Eliminates the O(n^2) backtracking a crafted valid-host URL could trigger, with no change to matched links. * test(media-embed): lock youtu.be trailing-slash + edge parity Use the first path segment for youtu.be ids so a trailing slash still resolves (matching the previous regex), and cover extra-query-param, si-param, embed-query, and short-id cases. * fix(media-embed): dispatch YouTube id by path shape; drop inline comments - Resolve id from the /embed/ path segment before the ?v= query param so a valid embed URL with a spurious v param still embeds (was returning null) - Remove non-TSDoc inline comments from the module and its test
#5306) * fix(sidebar): suppress collapse->expand transition flash on fresh load The pre-paint script sets the correct --sidebar-width, but store rehydration re-applies it during hydration and the always-on width/slide transitions animate that re-apply, reading as a collapse->expand flash. Suppress sidebar transitions during the boot window via a new html.sidebar-booting class (mirroring html.sidebar-resizing), lifted after the first paint via double-rAF so user toggles and the fullscreen slide still animate. * chore(sidebar): convert boot-guard comment to TSDoc
) * docs(readme): n8n-style restructure — static banner + platform screenshot Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(readme): platform shot as one white window (chat left, workflow right) on off-white Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(readme): platform shot — show a chat conversation in the left pane Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(readme): platform shot — capture the REAL chat-everywhere two-pane (one window) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(readme): add workspace surface showcase + collapse tech stack Add a compact 2x2 grid after Capabilities showing the surfaces beyond the chat+workflow hero — Tables, Files, Knowledge, and Scheduled tasks — reusing the cohesive product screenshots from the July newsletter (downsized + optimized). Collapse the Tech Stack list into a <details> so the lower half stays short. Screenshots sit below the meat (Capabilities) as bar/grid imagery, not a wall up top. --------- Co-authored-by: andresdjasso <andresdjasso@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: waleed <walif6@gmail.com>
#5307) * 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 * improvement(billing): ux around on demand toggling and one-off credits * minor ux improvement * fix lint --------- 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: Theodore Li <theo@sim.ai>
#5308) - chip: move default/filled hover into active-keyed compound variants so raw chipVariants({...}) renders identically to cn(chipVariants({...})); fixes sidebar/settings-sidebar active-hover divergence (no change to cn-wrapped consumers) - integrations: 'Explore in chat' uses active chip (darkens on hover) instead of floating text - data-retention: fold the retention-policies helper into the page description; drop the redundant wrapper - settings: extract shared SettingsResourceRow (rounded icon tile + title/desc + trailing, icons normalized to 20px); migrate recently-deleted, byok, and credential-sets onto it; recently-deleted actions are now Chips
…tral design system (#5309) * improvement(emails): align transactional emails with the platform neutral design system Re-skin all ~25 transactional email templates to match the platform/newsletter: - Color tokens in _styles/base.ts now mirror globals.css light mode (#fefefe canvas, #1a1a1a text, #525252/#5c5c5c/#707070 greys, #dedede border) instead of the old lavender + green (#33C482) scheme; accent defaults to neutral #1a1a1a but still honors a whitelabel primaryColor. - Primary CTA now matches the platform's primary Chip (inverse #1a1a1a fill, white text, rounded-lg, text-sm, normal weight); links carry an underline since the neutral color no longer signals a link. - Card uses 8px radius + hairline border; info/code boxes use a subtle token fill. - Logo is the dark, text-only 'sim' wordmark (green icon removed). - Footer: LinkedIn replaces Discord. - Every template routes through the centralized colors tokens — zero hardcoded hex (payment-failed error box tokenized to platform error surface values). * fix(emails): keep card boundary robust + don't reshape custom logos - Canvas goes to #f8f8f8 (off Andres's newsletter) so the white card reads via contrast in clients that flatten inline borders, not the border alone (Greptile P2). - Logo pins exact 70x34 only for the bundled wordmark; whitelabel brand.logoUrl now constrains by height with auto width so custom logos keep their aspect (Greptile P1). * improvement(emails): use Season Sans to match the newsletter and platform Register the Season Sans web font (the woff2 shipped with the newsletter, #5302) via react-email's <Font> in the layout head, and lead the email font stack with 'Season Sans' (system stack still the fallback for clients that ignore @font-face).
…5311) * fix(emcn): promote modal overlay + content wrapper to own compositing layers The backdrop-blur overlay did not reliably paint above page content the browser had GPU-promoted (position: sticky headers and z-indexed absolutes inside a scroll container, e.g. the scheduled-tasks calendar), so those composited layers bled through the overlay despite its higher z-index. Force the overlay and the content wrapper onto their own compositing layers via translateZ(0) so the compositor honors stacking order. Inherent since the calendar shipped (#4979), not a refactor regression. * Revert "fix(emcn): promote modal overlay + content wrapper to own compositing layers" This reverts commit 52145ed. * fix(ui): import calendar icon not calendar widget from emcn * fix(ui): fix calendar icon emcn mismatch --------- Co-authored-by: Theodore Li <theo@sim.ai>
Uh oh!
There was an error while loading. Please reload this page.