Skip to content

v0.7.18: landing, tools depth, media embeds in md editor, sonnet 5#5296

Open
waleedlatif1 wants to merge 23 commits into
mainfrom
staging
Open

v0.7.18: landing, tools depth, media embeds in md editor, sonnet 5#5296
waleedlatif1 wants to merge 23 commits into
mainfrom
staging

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

waleedlatif1 and others added 9 commits June 30, 2026 09:36
* 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>
@waleedlatif1 waleedlatif1 requested a review from a team as a code owner June 30, 2026 20:55
@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Too many files changed for review. (568 files found, 100 file limit)

@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 1, 2026 2:07am

Request Review

@cursor

cursor Bot commented Jun 30, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Medium risk from expanded third-party API surface (Slack/Asana/Jira/etc.), realtime DB URL/role wiring that affects production connection routing, and auth UI refactor touching every sign-in path.

Overview
v0.7.18 bundles product polish, integration breadth, infra, and agent guidance in one release.

Auth moves off the dark AuthBackground layout to a light AuthShell with shared primitives (AuthField, Chip-based submit/social/SSO, PasswordInput) and landing-aligned tokens. StatusPageLayout is removed in favor of the same shell pattern.

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 links). Claude Sonnet 5 is added as a provider with claude-sonnet-5 as the default model in the workflow combobox when available.

Realtime DB now sets SIM_DB_ROLE=realtime at bootstrap, optional DATABASE_URL_REALTIME / replica URLs in env, and resolveDbUrl for the socket pool so realtime connections use role-keyed URLs and pool profiles.

Quality gates: CI runs check:bare-icons; add-block/add-integration commands document currentColor for monochrome integration icons so bare light/dark rendering stays visible.

Cursor/rules: SEO/constitution globs shift from (home) to (landing) for landing-focused copy rules.

Agent skills: large new design-taste-frontend and emil-design-eng skill docs (plus Claude symlinks) encode anti-slop landing UI and animation polish guidance for codegen.

Reviewed by Cursor Bugbot for commit ad19f7f. Configure here.

Comment thread packages/utils/src/media-embed.ts Fixed
Comment thread packages/utils/src/media-embed.ts Fixed
Comment thread packages/utils/src/media-embed.ts Fixed
… 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants