v0.7.32: concurrency control, seo/geo, new lib#5646
Conversation
… selections to canvas preview (#5628)
…oads all skills (#5627) * v0.6.29: login improvements, posthog telemetry (#4026) * feat(posthog): Add tracking on mothership abort (#4023) Co-authored-by: Theodore Li <theo@sim.ai> * fix(login): fix captcha headers for manual login (#4025) * fix(signup): fix turnstile key loading * fix(login): fix captcha header passing * Catch user already exists, remove login form captcha * fix: quote argument-hint YAML values so Copilot CLI ≥1.0.65 loads all skills `argument-hint: [foo]` YAML-parses as a flow sequence (array), not a string. Downstream slash-command loaders that validate `argument-hint` as a string — notably GitHub Copilot CLI ≥ 1.0.65 — silently reject the skill on load, and the command disappears from the CLI menu. Wrap the value in double quotes so it parses as a string. No behaviour change on Claude Code. --------- Co-authored-by: Waleed <walif6@gmail.com> Co-authored-by: Theodore Li <theodoreqili@gmail.com> Co-authored-by: Siddharth Ganesan <33737564+Sg312@users.noreply.github.com> Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> Co-authored-by: Theodore Li <theo@sim.ai>
* fix(invites): preserve active organization for external access Keep organization activation server-owned so failed membership checks cannot clear a valid session context. * feat(admin, billing, settings): cleanup settings visibility, billing actor resolution, new admin routes * address comments * chore(db): reset pending migrations before staging merge Remove locally generated migrations so they can be regenerated against the latest staging schema without preserving stale snapshots or numbering. * regen migrations * address comments * chore(db): reset generated migrations before staging merge Remove this branch's generated migrations so they can be regenerated against the latest staging schema with fresh numbering. * upgrade global work * fix lint * address comments * legacy callbacks correctness * address comments * update * guardrail attribution
* fix(docs): fix Core Web Vitals regressions on docs.sim.ai Empirically measured under real trace-based (devtools) CPU/network throttling against the live site: mobile Performance 59, LCP 9.2s (TTFB 745ms + 8.4s element render delay). - sidebar-components.tsx / [lang]/layout.tsx: the docs sidebar renders every page in the doc tree as a link at once. Next's default viewport-prefetch fired an RSC payload fetch for every one of them on initial load - dozens of concurrent requests competing with the page's own content for bandwidth. Wired fumadocs' documented `sidebar.prefetch` option through to the custom SidebarItem/SidebarFolder components (which were bypassing it entirely, using next/link directly with no prefetch prop) via the `useSidebar()` context hook. - video.tsx: `autoPlay` forces browsers to fetch the full video file immediately on mount regardless of `preload`. Gated actual src loading behind an IntersectionObserver so a page with several of these doesn't pull down every video up front (5MB across 3 requests, in this case). Single shared component - fixes every doc page that embeds one. - proxy.ts: the i18n middleware matcher excluded favicon/robots.txt/etc but not `icon.svg`, so every request for it got routed through i18n negotiation instead of served as a static file, 404ing in production. - next.config.ts: enable productionBrowserSourceMaps - safe since this repo's source is already fully public, real debuggability benefit, zero performance cost. - shiki 4.0.0 -> 4.3.1 (verified: syntax highlighting still renders correctly). Attempted a coordinated fumadocs-core/ui/mdx/openapi upgrade to latest; fumadocs-openapi's v11 factory function became client-only (breaking change beyond its declared peer deps, requiring a component-boundary restructure), so only the safe, verified, docs-exclusive bumps (fumadocs-core/ui/mdx, shiki) are included here - the openapi major bump needs its own dedicated migration PR. Verified via a real production build (dummy env, all 3974 pages including API reference render/build cleanly) and a clean (non-stale) local server: Performance 59 -> 71 measured under real devtools throttling, RSC prefetch requests 63 -> 11, video requests/bytes 3/5MB -> 0. A pre-existing React hydration warning (#418) was found and confirmed present on live production before any of these changes, unrelated to this diff - documented, not blocking. * fix(docs): fall back to eager video loading without IntersectionObserver The lazy-load gate from the previous commit threw before isInView could ever become true in environments lacking IntersectionObserver (older browsers, some embedded webviews), leaving videos permanently source-less instead of falling back to eager loading. * chore(docs): drop non-TSDoc inline comments Repo convention is TSDoc-only, no plain // comments. * fix(docs): accessibility and SEO defects across the docs app Audited with parallel subagents against the accessibility and SEO skill checklists, each fix verified by reading the actual code (not assumed): Accessibility: - lightbox.tsx: focus was never captured/restored on close, and Tab escaped the modal to the page behind it (no focus trap on the single focusable element) - heading.tsx: the per-heading copy-link icon only appeared on hover, invisible to keyboard-only navigation (added peer-focus-visible) - navbar.tsx: active nav tab had no aria-current - response-section.tsx: the status-code dropdown had no aria-haspopup/aria-expanded/role, and no Escape-to-close - workflow-preview.tsx: same focus-trap gap as lightbox.tsx on the expanded-canvas modal SEO: - page.tsx: generateMetadata's hreflang/canonical URLs used a naive String.replace to strip the locale prefix, which also matched "/en" inside unrelated slugs (platform/enterprise, integrations/enrich, platform/self-hosting/environment-variables), corrupting those pages' canonical and alternate-language URLs. Replaced with a prefix-only strip. - structured-data.tsx: the SoftwareApplication JSON-LD block compared url === baseUrl (no trailing slash) against the homepage's actual url (always has a trailing slash), so the condition was always false and this structured data never rendered anywhere, including the homepage. - structured-data.tsx: "Mothership" in the indexed featureList violated the constitution's required language (the agent is "Sim", the surface is "Chat") - this ships in JSON-LD search engines parse. * fix(docs): defer the Ask Sim chat widget's heavy deps until opened The chat panel (useChat from @ai-sdk/react, Streamdown + its CSS) was mounted unconditionally in the root layout on every single page, so its full weight loaded and executed even though the widget starts closed on every page view. Traced via the LCP breakdown insight under real devtools CPU/network throttling: the LCP text element (the intro paragraph) had a ~8s element render delay despite a ~13ms TTFB, and bootup-time attributed ~4.3s of scripting time to a single chunk containing React/ReactDOM's own runtime plus this widget's eagerly-bundled dependencies. Split into a lightweight ask-ai.tsx (just the toggle button + open state) and ask-ai-panel.tsx (the actual chat UI, useChat, Streamdown), loaded via next/dynamic(..., { ssr: false }) only when the user opens the widget. Verified: the panel's chunk now has zero network requests on initial page load. Measured (mobile, devtools throttling, /introduction): - Performance: 69 -> 75 - LCP: 8.0s -> 6.4s - TBT: 260ms -> 130ms The remaining ~6.4s LCP delay traces to the same shared chunk, now identified as core React/ReactDOM hydration cost for this page's sidebar/TOC/breadcrumb tree rather than an isolated bug - a real, larger initiative (hydration architecture, not a surgical fix), documented here rather than rushed. * fix(docs): preserve Ask Sim chat state across close/reopen The panel split unmounted AskAIPanel entirely on close, discarding useChat's message state - reopening always started an empty conversation, unlike the original single-component layout where useChat lived in a component that never unmounted. Fixed by keeping the panel mounted (via a hasOpened flag that never resets) once first opened, and having the panel itself return null when closed rather than being conditionally removed from the tree by its parent - hooks still run every render, so useChat's state persists across visibility toggles. The dynamic import still only fires on the first open, so the initial-load win is unchanged. Verified via a real click-through (open, type, close, reopen): input persists correctly, and the panel chunk still has zero network requests on initial page load. Performance unchanged at 75. * chore(docs): lint fixes (import order, formatting) * fix(docs): fill the Ask Sim UI gap while the panel chunk loads handleOpen set open=true synchronously, hiding the trigger button before the dynamically imported panel had a chance to render anything (next/dynamic renders null by default with no loading option) - on a slow connection neither the button nor the panel was visible. Added a loading fallback in the same fixed position so there's no gap between the button disappearing and the real panel appearing.
…ge (#5636) Google Search Console flagged every /models/{provider}/{model}/opengraph-image and /integrations/{slug}/opengraph-image URL as 404 (~230 pages total: 5 sample model pages plus ~130 more models, plus every integration). Root cause: the sibling page.tsx for each of these routes sets `dynamicParams = false`, a segment-level restriction that also blocks the metadata route (opengraph-image.tsx) from rendering any param combination it wasn't statically told about - but Next does not share generateStaticParams between a page and its sibling metadata routes. Since none of the three opengraph-image.tsx files exported their own generateStaticParams, every param was "unknown" to that restriction and 404d, for every single model and integration. Added a matching generateStaticParams to all three files, mirroring each route's own page.tsx. Note: the exact URLs in the audit report (bare /opengraph-image, no suffix) aren't the real ones - Next serves these at a build-generated hash suffix (e.g. /opengraph-image-15dal5?<hash>), which is what's actually embedded in each page's <meta property="og:image"> tag. The underlying bug the report surfaced is real regardless; verified by requesting the actual hash-suffixed URL each page embeds (previously 404, now 200) for both a model and an integration page, on a real production build.
…ison pages (#5634) * fix(landing): fix oversized HTML and severe LCP on integration/comparison pages Google Search Console flagged /integrations, /integrations/slack, and several others for exceeding Googlebot's 2MB uncompressed-HTML crawl limit, plus severe LCP on /integrations, /integrations/slack, /integrations/hubspot, /comparison/flowise, and /integrations/hugging-face. Root cause 1 - /integrations/slack was 5.2MB (measured on production). The "Agent templates" section renders every template matching getTemplatesForBlock(type) with no cap - Slack is referenced as alsoIntegrations in 445 templates (vs 52-126 for Salesforce/Gmail/ HubSpot), so its detail page embedded hundreds of full template cards in the initial HTML/RSC payload. Capped to 12, consistent with the same file's existing related-integrations cap of 4. Root cause 2 - /integrations was 1.83MB, right at the limit. The client IntegrationGrid component receives the full Integration[] as props (needed for instant client-side search), which serializes every integration's complete operations/triggers arrays - including full per-operation description sentences - into the initial payload purely to build a search index. Added IntegrationSummary + toIntegrationSummary (lib/integrations): the same searchable surface (name, description, operation names, trigger names) precomputed server-side into one lowercased string, dropping the full operations/triggers data the client never actually renders. Measured: 627KB -> 142KB of embedded integration data (77% reduction). Verified via a real production build + curl: - /integrations: 1.83MB -> 1.31MB - /integrations/slack: 5.2MB -> 355KB (93% reduction) - /integrations/hubspot: 901KB -> 452KB Verified via Lighthouse (mobile, devtools throttling, matching what real users on a typical device experience) against both live production and the fixed local build: - /integrations: 47 -> 96 (LCP unmeasured->2.1s, TBT 2,770ms->110ms) - /integrations/slack: 47 -> 96 (LCP 9.7s -> 1.9s) - /integrations/hubspot: 72 -> 97 (LCP 9.1s -> 1.9s) - /integrations/hugging-face: 72 -> 95 (LCP 9.2s -> 2.3s, reproduced twice on production before fixing - not a fluke) - /comparison/flowise: 71 -> 95 (LCP 9.8s -> 2.1s) The last two aren't Slack-style template-count outliers (4 and 0 alsoIntegrations references respectively) - shrinking the shared IntegrationGrid client bundle appears to have reduced a shared chunk loaded broadly across landing pages, benefiting pages beyond the ones directly touched. Also checked and confirmed already healthy, no action needed: /integrations/salesforce, /integrations/gmail, /integrations/amazon-dynamodb, /comparison/tines, /models/xai/grok-4-20-multi-agent-0309. * fix(landing): restore full-fidelity search and template priority Two real regressions from the previous commit, both confirmed by Greptile and Cursor Bugbot independently: - lib/integrations: IntegrationSummary.searchText joined every field into one string, so (a) it dropped operation/trigger descriptions entirely (a search for API-specific terms that only appear in an operation's description, not its name, silently stopped matching), and (b) a single joined string lets a query span a field boundary (e.g. matching across the tail of a name and the head of the next field) that the original per-field search never allowed. Reverted to a searchFields array - same content as the original per-field index (name, description, every operation's name+description, every trigger's name), just precomputed server-side instead of shipping the full Integration objects. Grid filtering goes back to `.some(field => field.includes(q))`, matching the exact original matching semantics. - blocks/registry.ts + integrations/[slug]/page.tsx: capping getTemplatesForBlock's result with a plain .slice(0, 12) kept whatever 12 templates happened to iterate first in registry insertion order - for a high-connectivity integration like Slack, that can be entirely alsoIntegrations matches from unrelated blocks, silently dropping the integration's own owned templates and any marked featured. Added an explicit isOwner flag to ScopedBlockTemplate (the registry function already computes this internally, just wasn't surfacing it) and sort owner-first, featured-second before slicing. * fix(landing): sort featured templates ahead of owned, not just as a tiebreaker The previous sort (owner-first, featured as a tiebreaker within each owner tier) meant an integration with 12+ owned templates filled the entire cap with non-featured owned templates before any featured related template (reached via alsoIntegrations) was ever considered - Slack hits this case. Swapped the sort so featured (owned or related) ranks first, then owned-but-not-featured, so a curated featured template can no longer be sliced away by a pile of ordinary owned ones.
…-source AI agent platform listings (#5633) * feat(library): add n8n alternatives, LangGraph alternatives, and open-source AI agent platform listings * fix(content): declare actual OG image dimensions instead of hardcoded 1200x630
* feat(gong): align tools with official API spec, add ask-anything, brief, unassign, and logs tools
- fix gong_list_flows: query param was flowEmailOwner (typo copied from Gong's endpoint prose); the API requires flowOwnerEmail, so every call failed
- create_call: drop phantom url output (API returns only requestId/callId) and make downloadMediaUrl optional per spec
- list_scorecards: refresh to current spec (numeric IDs, questionType/answerGuide/minRange/maxRange/answerOptions, reviewMethod)
- answered_scorecards: map selectedOptions on answers, correct score range description (1-50)
- surface requestId uniformly across all read tools; totalRecords no longer fabricated from page size
- normalize includeAvatars to a strict boolean param, uppercase aggregationPeriod, encode userId path param
- validate email/phone format before irreversible GDPR purge calls
- new tools: gong_ask_anything, gong_get_brief (AI entity Q&A/briefs), gong_unassign_flow_prospects, gong_get_logs
* fix(gong): require custom-range dates and gate param remapping by operation
- ask_anything/get_brief: entityFromDateTime/entityToDateTime now conditionally required (UI) and validated tool-side when timePeriod is CUSTOM_RANGE
- block params mapper: remaps are gated by the selected operation so stale values from previously configured operations can no longer overwrite fromDateTime/fromDate/workspaceId
* fix(gong): final spec-alignment pass, review fixes, and regenerated docs
- ask_anything/get_brief: send fromDateTime/toDateTime only for CUSTOM_RANGE; declare mcpResult brief section field
- unassign: dedicated optional unassignFlowId subblock so a stale assign-flow ID can never silently narrow an unassign to one flow
- get_logs: logType is a closed enum (AccessLog, UserActivityLog, UserCallPlay, ExternallySharedCallAccess, ExternallySharedCallPlay) - dropdown in block, enumerated in tool description
- get_folder_content: folderId optional per spec; get_call: encode callId path param
- list_trackers: drop saidInCallParts (absent from the spec's KeywordTracker schema)
- get_extensive_calls: correct declared interactionStats item shape to {name, value}
- block inputs: list all remapped subblock params; optional flags on nullable outputs; absolute types re-export
- regenerate Gong integration docs and integrations.json entries (29 operations)
…ith delete, list membership, and search tools (#5635)
…sting JSON-LD, fix TechArticle rich-result eligibility (#5638) * fix(landing): complete Organization schema, add CollectionPage/BlogPosting JSON-LD, fix TechArticle rich-result eligibility - Organization schema (site-structured-data.tsx): add brand and contactPoint.url (verified against the real /contact route); all other fields were already correct and verified against the Footer's sameAs links. foundingDate/legalName/address omitted — not verifiable from anything in this repo. - CollectionPage (blog + library index): buildCollectionPageJsonLd now takes the real posts list (same getAllPostMeta() the index page already renders from) and emits a mainEntity ItemList of BlogPosting stubs instead of omitting mainEntity entirely. - BlogPosting + TechArticle (post detail template): Google's Article rich-result eligibility only recognizes Article/NewsArticle/BlogPosting — a bare TechArticle type isn't in that allowlist. buildArticleJsonLd now emits a multi-type @type array (["BlogPosting","TechArticle"]) for genuinely technical posts, and "BlogPosting" alone for posts that are general announcements, via a new `technical` frontmatter flag (defaults true; set to false on the series-a funding-announcement post, the one post with no technical content). Also fixed a real markup/schema mismatch: the article's `speakable.cssSelector` referenced `[itemprop="description"]`, but no element carried that itemProp — added it to the description paragraph. TechArticle/BlogPosting image URLs are now made absolute (previously relative paths, invalid for crawlers). - FAQPage: audited every LandingFAQ usage (/models, /models/[provider], /models/[provider]/[model], /integrations, /integrations/[slug], /comparison, /comparison/[provider]) — all already emit matching FAQPage JSON-LD sourced from the same data passed to LandingFAQ; no gaps found, no changes needed. * fix(landing): match microdata itemType and scope collection JSON-LD to visible posts Address Greptile/Cursor review on PR #5638: - itemType now always resolves to BlogPosting (matching Greptile's exact suggested fix), since the JSON-LD graph already carries the richer TechArticle type via a multi-type array and the microdata path doesn't need to duplicate that distinction - buildCollectionPageJsonLd now receives the same tag-filtered/paginated post subset ContentIndexPage actually renders, instead of the full unfiltered catalog, via a new shared selectVisiblePosts/paginateContentPosts helper in lib/content/index-list.ts (also de-duplicates the pagination logic that previously lived only in ContentIndexPage) * fix(landing): match CollectionPage ItemList order and url to the visible filtered/paginated variant Address round-2 Cursor Bugbot findings on PR #5638: - buildCollectionPageJsonLd no longer re-sorts the given posts by date - ordering is now solely owned by the caller (selectVisiblePosts), so featured-row-first render order matches ItemList position order - buildCollectionPageJsonLd now takes an optional {tag, page} filter descriptor and reflects it in the emitted url, instead of always pointing at the bare section index regardless of which filtered/ paginated variant's posts are actually listed in mainEntity
…5637) * feat(buffer): add Buffer integration with posts, channels, and ideas * fix(buffer): return clear tool error when account lookup yields no account * fix(buffer): default schedulingType server-side so basic-mode blocks never fail validation * fix(buffer): probe Content-Type for extensionless media URLs so videos are not sent as images * feat(buffer): add get_ideas and get_idea_groups tools, harden media URL classification * fix(buffer): guard missing post on PostActionSuccess responses
…docs (#5641) * feat(flint): add Flint integration with agent task tools, block, and docs * fix(flint): forward explicit publish=false, guard missing taskId, align default params branch with tool fallback * docs(flint): add manual intro section to integration docs page * fix(flint): fail get_task on OK responses without a task ID * fix(flint): drop json-object generation type so the wand emits the pages array
* improvement(concurrency): limits configurable, docs updates * remove dead tests * limits self hosted vars
…on ambiguous media (#5642) * improvement(buffer): explicit mediaType override; error instead of guessing on ambiguous media * fix(buffer): forward validated mediaType from routes into the media resolver * fix(buffer): presign uploaded media for 7 days — Buffer fetches assets at publish time * docs(buffer): document presign lifetime bound by signing credentials * fix(buffer): always mint fresh presigned URLs from verified storage keys for media
…te, and address (#5644) Adds the three fields intentionally omitted from #5638 pending real values: - legalName: 'Sim, Inc' - matches the entity named throughout the Terms of Service (apps/sim/app/(landing)/terms) - foundingDate: '2025' - address: real registered office (80 Langton St, San Francisco, CA 94103)
|
Too many files changed for review. ( |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryLow Risk Overview New runbooks: Integration skills now consistently require no guessed API/webhook schemas, register blocks in
Reviewed by Cursor Bugbot for commit 66d1e61. Bugbot is set up for automated code reviews on this repo. Configure here. |
…eaming (#5639) * fix(mothership): keep scroll position when user scrolls up during streaming * chore(mothership): trim scroll fix comments
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8853b0c. Configure here.
…l prefix (#5607) * feat(byok): migrate agent/router/evaluator LLM keys to BYOK by model prefix * fix(script): address review — cover translate/guardrails, trim provider ids, reject mixed mapping, add key-prefix guard * fix(script): include pi block in LLM-family set, trim key-prefix value * fix(script): add router_v2 to LLM-family set, canonicalize provider ids to lowercase * fix(script): resolve overlapping model prefixes deterministically (longest match wins)
…f timestamp sort (#5647)
…claude/.cursor projections (#5609) * improvement(cleanup-skill): parallelize analysis, apply fixes sequentially * improvement(cleanup-skill): add comment-reduction pass; mirror 6 missing skills into .claude/commands * fix(cleanup-skill): substitute parsed scope into analysis passes instead of literal <scope> * fix(cleanup-skill): parse fix token anywhere; preserve pass labels through convergence for ordered apply * fix(cleanup-skill): apply Step 1 proposals content-anchored, re-derive when a prior pass invalidated the snippet * fix(babysit-skill): correct garbled --reverse explanation across all three copies * fix(skills): propagate parallel cleanup to cursor/agents copies; disambiguate babysit /ship refs in claude copy * fix(skills): port url-state + comment passes to cursor/agents; clarify converge pass-label ordering * feat(skills): canonicalize skills under .agents/skills with generated .claude/.cursor projections Establish .agents/skills/<name>/SKILL.md as the single source of truth (latest content reconciled per skill from the three drifted copies), and generate the .claude/commands and .cursor/commands projections from it via scripts/sync-skills.ts. Adds skills:sync/skills:check, a CI gate, a pre-commit regen hook, and CONTRIBUTING docs. Structurally fixes prior drift (e.g. abbreviated .claude ship -> full ship). * fix(skills): strip leaked XML tags from skill tails; clarify lint:check has no per-file target Removes stray </content>/</invoke> markup that leaked into add-block, add-connector, add-hosted-key canonical skills, and reword the cleanup skill's lint step to note bun run lint:check runs repo-wide via turbo (no per-path API). Projections regenerated via skills:sync. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjefwescJoHZ6zcc3C17FR * fix(add-block-skill): restore unknown-output stop in Final Validation Re-add the "if any tool outputs are still unknown, tell the user instead of guessing block outputs" step that was dropped when Final Validation step 5 became the BlockMeta template check. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjefwescJoHZ6zcc3C17FR --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

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