mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-22 05:19:54 +08:00
48c1b453dfd659707a1f876ca5ffdc63ca59067d
226
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bcf6a804f9 |
improvement(emcn): extract design system into shared @sim/emcn package (#5257)
Moves apps/sim/components/emcn into a shared @sim/emcn package consumed directly by apps/sim and apps/docs. cn/keyboard/use-copy-to-clipboard move into the package; all imports become direct @sim/emcn (icons via @sim/emcn/icons, CSS via file path). ChipModal email validation is now prop-driven (quickValidateEmail stays in apps/sim, injected via validate). Docs drops its local chip/chip-dropdown/dropdown-menu mirrors and consumes @sim/emcn. |
||
|
|
d878f15815 |
feat(integrations): extend Airtable, Google Docs, WhatsApp, and Excel tool depth (#5256)
* feat(airtable): add delete and upsert record tools * feat(google-docs): add batchUpdate text, table, image, and style tools * feat(whatsapp): add template, media, interactive, reaction, and mark-read tools * feat(microsoft-excel): add clear, format, create-table, sort, and delete-worksheet tools * fix(integrations): address review feedback - google-docs: use camelCase fontSize field mask; normalize string booleans for bold/italic/underline and matchCase - microsoft-excel: escape OData single quotes in worksheet/table keys; validate range for clear/format - airtable: enforce batch limits (delete <=10 ids, upsert <=10 records and 1-3 merge fields) with clear errors * fix(integrations): address round-2 review - airtable: coerce upsert typecast as string-aware boolean (string "false" no longer truthy) - microsoft-excel: format_range surfaces precise partial-state error when fill PATCH fails after font (no atomic font+fill endpoint in Graph) * fix(whatsapp): treat 2xx mark-as-read as success unless body says success:false * fix(integrations): build fix, doc accuracy, and comment cleanup - google-docs: align manualDocumentId condition with the document selector so the documentId canonical group has matching conditions (fixes canonical-pair block test / build) - microsoft-excel: describe fill/font color as hex code only (Graph does not reliably accept named colors) - remove verbose explanatory inline comments from new tools (keep idiomatic section dividers) - regenerate integration docs + integrations.json catalog from the block registry * fix(integrations): harden delete-record id coercion and excel sort-column validation - airtable: coerce recordIds entries via String() so numeric JSON values don't crash on .trim() - microsoft-excel: drop the silent sortColumn default to 0 so invalid input surfaces the tool's clear validation error (both v1 and v2 blocks) * fix(airtable): coerce upsert fieldsToMergeOn entries via String() to handle non-string values |
||
|
|
c59631698f |
chore(deploy): remove deploy as a2a (#5255)
* chore(deploy): remove a2a * add block |
||
|
|
66315f19e7 |
improvement(docs): flatten the academy learn/chapters panels (#5253)
* improvement(docs): flatten the academy learn/chapters panels The "What you will learn" and "Chapters" panels were filled, bordered cards — the only boxed elements on the page. The docs design system is explicitly flat: global.css strips fumadocs cards/callouts/card-grids to transparent/divider-based, and the right-rail "On this page" TOC is small, muted, and borderless. - WhatYouWillLearn (inline): flat divider list like the FAQ, with a small panel label at the app's text scale instead of a page-h2-scale title - VideoChapters (right rail): borderless, matching the TOC — small muted label + flat hover rows, no card chrome * improvement(docs): drop the repeated per-row play icon from the chapters list The CirclePlay glyph repeated on every chapter row read as noise — a column of identical icons down the rail. The "On this page" TOC this list mirrors has no per-row icons; the timestamps already signal video chapters and the hover highlight signals they're seekable. Rows are now text + time only. * improvement(docs): drop the under-label rule on the learn callout A full-width rule under the small "What you will learn" label read as an awkward heading underline and blurred into the inter-item dividers. The label is now a quiet muted marker (matching the Chapters label and the TOC heading), with dividers only between items — so it never competes with the bold item titles or looks like an underlined heading. |
||
|
|
3143a15dde |
feat(uptimerobot): add UptimeRobot v3 integration (#5229)
* feat(uptimerobot): add UptimeRobot v3 integration
- 24 tools across monitors, incidents, maintenance windows, alert contacts,
public status pages, and account (UptimeRobot v3 REST API, Bearer auth)
- Block with operation-scoped subBlocks, status-page logo/icon file uploads
via internal multipart routes, and BlockMeta templates + skills
- Registered tools/block, added icon, generated docs
- Updated add-integration/add-block/validate-integration docs links to /integrations
* fix(uptimerobot): address review — heartbeat URL, file/JSON edge cases
- Block: URL is not required for HEARTBEAT monitors (no URL)
- buildMonitorBody: throw on malformed assignedAlertContacts/customHttpHeaders
JSON instead of silently dropping the field
- PSP route: error (400) when a supplied logo/icon cannot be resolved to a
stored file instead of silently omitting the image
- PSP route: guard success-path JSON parsing; return a controlled 502 on a
non-JSON provider response instead of an uncaught 500
* fix(uptimerobot): spec-conformance audit fixes
- pause/start monitor: send Content-Type: application/json (v3 spec requires it
on these POSTs even with an empty body)
- update maintenance window: drop autoAddMonitors (not in UpdateMaintenanceWindowDto);
gate the block field to create only
* fix(uptimerobot): rename monitor timeout param to avoid reserved name
The tool runner treats a top-level `timeout` param as the outbound HTTP-client
timeout (ms), so a monitor check-timeout of e.g. 30s would abort the API call in
30ms. Rename the input to `checkTimeout` (block subBlock, tool params, inputs,
numeric coercion) and map it to the API body's `timeout` key in buildMonitorBody.
* fix(uptimerobot): reject empty/non-object PSP responses
A successful PSP create/update must return the PspDto object; an empty or
non-object body now returns a controlled 502 instead of mapping a phantom
status page (id: 0, empty name, null images) back to the workflow.
* fix(uptimerobot): validate core PSP fields before mapping
Reject successful PSP responses that lack a positive numeric id and non-empty
friendlyName (a {} or metadata envelope) with a controlled 502, instead of
mapping a phantom status page.
|
||
|
|
35acc42d2b | feat(downdetector): add Downdetector outage-monitoring integration (#5228) | ||
|
|
c7eda5b217 |
feat(rich-editor): rich markdown field + @ mentions for skill & deploy modals (#5215)
* feat(rich-editor): rich markdown field + @ mentions for skill & deploy modals
- Add controlled, file-less RichMarkdownField (sibling of the file editor) used for
skill Content and deploy version descriptions; placeholder/typography match chip fields
- Add @-mention menu (TipTap suggestion) inserting portable [label](sim:kind/id) links;
wired into the field and the file viewer via a shared useEditorMentions hook
- Extract a shared suggestion-popup renderer + menu chrome (slash + mention)
- Fix false dirty-on-open: normalize the editor's dirty baseline to canonical markdown
- Always show the deployment version number (v3 · name) so named versions keep a short ref
- Skill import: drop the paste box (Create-tab editor auto-destructures a pasted SKILL.md),
reorder GitHub → Upload
* fix(rich-editor): address review feedback on modal field
- RichMarkdownField reports the original value when the doc matches its canonical
form, so a non-canonical input never reads as a false unsaved change (skill +
version description modals)
- Add sim: mention link navigation (Cmd/Ctrl-click) to the modal field
- versions: keep the v{n} fallback as the rename guard/seed so re-submitting the
displayed token is a no-op (no redundant "v3 · v3"); document the clear-name no-op
- Clarify the lazy query-gating comment in useMarkdownMentions
* fix(skills): re-seed Content editor when initialValues changes
Bump the field's remount key in the reset guard so the seed-once rich editor
re-seeds when content is reset from a changed initialValues (same skill id keeps
the React key otherwise stable), keeping the editor and saved value in sync.
* feat(rich-editor): render mentions as icon chips + menu/limit polish
- Render @ mentions as an inline chip node (entity icon + label) instead of a
blue link; still serializes to the portable [label](sim:kind/id) markdown so
it round-trips and stays agent-readable (shared mentionIcon resolver)
- Cap the mention/slash menu height + width and scroll it, matching the chat menu
- Give the version description editor more height; lift the 2000-char limit to a
high anti-abuse cap (client + contract) and drop the visible counter
* fix(rich-editor): make suggestion menus scrollable inside modals
- Mount the slash/@ menu popup inside the host dialog (when present) instead of
document.body: Radix's scroll-lock blocks wheel events outside the dialog
subtree, so a body-level popup couldn't scroll in a modal. position:fixed keeps
it viewport-positioned (the modal centers via flex, no transform) so it isn't clipped
- Fix the invalid max-w arbitrary value (calc needs spaces) that left the menu uncapped
- Match the version-description editor's dynamic-import loading height to the field
so the modal doesn't grow when the chunk loads
* fix(rich-editor): escape bracketed mention labels + disable images in field editors
- Escape/unescape `[`/`]` in mention labels so an entity named e.g. `data[1].csv`
round-trips into a chip instead of degrading to a plain link
- Hide the `/Image` command where image upload isn't wired (the skill + version
description field editors), so images can't be inserted there; the file viewer
keeps image support
* fix(rich-editor): keep suggestion keyboard nav working after async items load
The suggestion plugin captures the list's onKeyDown handle via ReactRenderer.ref
once at mount. The mention list's items arrive asynchronously from the workspace
store, so the captured handle closed over an empty `flat` and returned false for
arrow/enter — letting the editor move the caret instead of navigating the menu.
Read live values through a ref so the mount-time handle always sees current
items/activeIndex. Hardened the slash list the same way.
* test(rich-editor): cover suggestion keyboard nav through ReactRenderer; drop inline comments
Adds a test that drives the real ReactRenderer path the suggestion plugin uses:
the captured onKeyDown handle returns false while the store is empty and true
once async workspace items land, and arrow+enter select the right item. Removes
the explanatory inline comments from the two imperative handles.
* fix(rich-editor): suggestion menus keep arrow keys when a divider is adjacent
The leaf-selection keymap (ArrowUp/Down selects an adjacent divider/image) runs at
priority 1000, above the suggestion plugins, so it stole ArrowDown to select the
next horizontal rule instead of moving the open @/ menu selection. It now yields
while a mention or slash menu is active, detected via the plugins' exported keys.
* feat(rich-editor): Tab accepts a suggestion; unify list keyboard nav; match chip styling
- Extract useSuggestionKeyboard: one hook owns the @/ menus' active-row state,
scroll-into-view, and arrow/enter/tab handling (removes the duplication between
the two list components)
- Tab now accepts the active item like Enter, matching the chat composer
- Render the mention chip like the chat input's mention token: borderless inline
icon + label (no pill), 12px icon with brand color via getBareIconStyle, so the
styling is consistent across surfaces
* fix(rich-editor): harden editor edge cases found in full audit
- Skill paste: only auto-destructure on a real YAML name key, so a stray `---`
break or heading snippet no longer overwrites all three fields (parseSkillMarkdown
reports nameFromFrontmatter)
- Skill modal: reset by skill id, not object identity, so a background refetch of
the open skill can't clobber in-progress edits
- Field editor: claim Mod+K (inline link editor wins over global search) and
swallow file drops so the browser doesn't navigate away from the modal
- File editor: swallow non-image file drops (same navigation guard)
- Frontmatter: a leading `---` thematic break (e.g. a changelog) is no longer
mistaken for frontmatter and hidden from the editor
- Mention chip: renderText emits the portable link so copying a chip into a
plain-text target (e.g. chat) pastes back as a mention
- Suggestion nav: clamp a one-frame stale active index on Enter/Tab
* style(rich-editor): selected link reads as normal text, not standout blue
Follows the standard MD-editor convention (Linear, Slack): a highlighted link
takes the primary text color so the selection stays legible, instead of keeping
its blue on the selection highlight. Scoped to selected links only — no effect on
unselected links, regular text, the selection background, or any other surface.
* fix(rich-editor): guard async suggestion + generate lifecycles against teardown
- Suggestion onStart can fire after the editor is destroyed (the update awaits
items()), throwing on its now-gone view/storage — e.g. a modal closing while the
menu opens. Bail when the editor is destroyed; optional-chain mention storage.
This also removes the unhandled rejections the headless keymap test surfaced.
- Generate version description: thread an AbortSignal so closing the modal
mid-stream aborts the diff fetches + SSE read instead of streaming into a gone
component.
* refactor(rich-editor): fold inline comments into TSDoc; display-only chip; polish
- Convert the editor's inline `//` comments to TSDoc on the nearest declaration and
drop the self-explanatory ones (no logic change)
- Mention chip is now display-only (icon + label), matching the chat input exactly:
removes select-none (so a range selection highlights the label), the cursor-pointer
over-promise, and the cmd-click nav that could route away from a modal mid-edit
- Don't log a deliberate generate-abort as an error
- Selected strike-through text reads in the primary color so the selection is uniform
* fix(rich-editor): clean selection for the mention chip
The chip is an inline atom, so a range selection now highlights it as a whole unit
(the prior select-none left it an un-highlighted gap). A direct click selects it
with a subtle fill instead of the block-leaf outline ring meant for dividers/images.
* feat(rich-editor): Cmd/Ctrl-click a mention to its resource in the file viewer
Threads a `navigable` flag through the mention storage: the file viewer opts in so
a chip routes to its file/table/workflow/etc., while modal fields stay inert so a
click can't navigate away from an unsaved edit. Styling is identical either way.
* fix(rich-editor): icon fallback for removed integrations; smoother divider nav
- A mention to a since-removed integration falls back to a generic icon so the chip
is never icon-less (indistinguishable from prose)
- Arrowing from a selected divider/image to an adjacent one selects it directly
instead of stopping on the gap cursor between them, so stepping through a run of
dividers is one press each
* fix(rich-editor): integration mentions are display-only; robust chip selection
- An integration mention's id is a block type (gmail_v2), not a routable resource —
/integrations/[block] expects a slug and a type maps to zero-or-many credentials —
so it no longer links to a 404. The chip only shows a pointer/navigates on kinds
that resolve to a real page.
- Scope the block-leaf selection ring off the mention chip robustly (covers a
node-view wrapper via :has), so a selected chip shows a subtle fill, not the outline.
* feat(icypeas): update brand icon and bgColor; regenerate integration docs
* fix(rich-editor): remove the misfiring chip selection fill (full-width gray band)
The :has fill could paint a full-width band; drop it. A selected chip just skips the
block-leaf outline ring and uses the same native text-selection highlight as the prose.
* feat(rich-editor): show an "Uploading…" toast while an image uploads
A persistent progress toast appears per image during upload and is dismissed once
it settles, when the upload hook's "Uploaded"/"Failed" toast takes over — previously
nothing showed until the upload finished.
* refactor(rich-editor): drop inline comments (TSDoc on the declarations instead)
Fold the image-upload toast note into the insert function's TSDoc and remove the
remaining inline // comments.
* refactor(rich-editor): cleanup + simplify pass over the markdown editor
- Delete dead parseSimHref (+ barrel/test); mentions parse via the node tokenizer
- Extract serializeMarkdownDocument — one canonical serialize pipeline shared by the
dirty-check baseline and the round-trip-safety probe (was inlined in both)
- Extract selectLeafAcross — shared tail of the two arrow leaf-selection handlers
- Reset the suggestion active-row during render (prevX idiom) instead of an effect
- Inline the skill modal's trivial hasChanges (drop the useMemo)
- image.tsx: cn() over a template-literal className
* refactor(rich-editor): share the suggestion-list shell and link-URL editor
- Extract SuggestionList: the grouped-list surface, empty state, listbox/option a11y
structure, and active-row/hover/select wiring shared by the @ and / menus. Each menu
keeps only its own grouping + itemKey/renderItem.
- Extract link-editing (LinkUrlInput + applyLink): the inline link field and the
normalize→extendMarkRange→set/unset commit logic, shared by the bubble menu and the
link hover card.
* improvement(settings): align access-control detail UI + nav-driven docs link
- Move permission-group Save/Discard into the detail header (matching
secrets/whitelabeling) and delete the one-off sticky 'Unsaved changes' bar
- Convert the Platform and Blocks config tabs to SettingsSection (drop the
custom multi-column masonry + hand-rolled section labels); add an optional
far-right action slot to SettingsSection for the per-section Select All
- Replace the file-share auth-mode checkboxes with a multi-select ChipDropdown
- Normalize per-tab spacing to gap-7, align the expand-chevron token to
--text-icon, and match the list-row arrow size to the integrations precedent
- Add a nav docsLink surfaced as a header 'Docs' ChipLink by SettingsPanel,
wired for the six enterprise settings pages
* feat(rich-editor): copy-link button shows a checkmark on copy
Use the shared useCopyToClipboard hook so the link hover card's Copy button swaps to a
Check for ~2s after copying, matching the rest of the platform.
* fix(rich-editor): RichMarkdownField falls back to raw text for lossy markdown
Mirror the file editor's safety gate: decide once from the initial value via
isRoundTripSafe — round-trip-safe content opens in the WYSIWYG editor, while lossy
markdown (raw HTML, footnotes, comments) edits as raw text, so an edit can't silently
drop those constructs.
* feat(rich-editor): divider/leaf editing — backspace, select-all, gap cursor
- Backspace at the start of an empty block whose previous sibling is a divider/image removes the
blank line (instead of deleting the leaf) and selects the divider above; a non-empty block selects
the leaf so a second Backspace deletes it (highlight-before-delete).
- Select-all (and any range selection) now visibly highlights dividers/images, which the native text
highlight skips because leaves carry no text — via a decoration that paints a selection band.
- The gap cursor between two adjacent leaves no longer draws its stray caret (matching Linear); the
position stays functional. Leading/trailing gap cursors keep their caret.
- Unit tests for the backspace + select-all behavior.
* refactor(rich-editor): decouple headless bundle, fix linked-image round-trip, a11y
- Split mention-node into the schema-only `MarkdownMention` (mention-node.ts, no React/registry)
and the live `MentionChip` node view (mention-chip.tsx); move the live factory to
editor-extensions.ts and inject node views via DI. The headless round-trip path
(markdown-parse/normalize-content/round-trip-safety) no longer pulls the 269-block registry —
it now bundles for the browser with zero node-builtin deps.
- A sized + linked image serializes as `[](href)` (dropping the unrepresentable size)
instead of `[<img>](href)`, which the tokenizer can't reparse — the link is preserved, no silent
data loss. Also escape the href title symmetrically.
- Wire the suggestion menus as an ARIA combobox: while open, the editor gets
aria-haspopup/expanded/controls and an aria-activedescendant tracking the active option, so screen
readers announce it; cleared on close. Empty state is a role=status live region.
* fix(rich-editor): exempt an active @-mention query from the per-group cap
The per-group MAX_PER_GROUP limit is meant to keep the unfiltered menu from flooding; applying it
while a query is active hid matches past the eighth in a category, so search couldn't reach them.
Cap only when there's no query. Adds a regression test (12 matches shown when searching).
* fix(rich-editor): mention icon fallback + typed sim-link input rule
- mentionIcon never returns undefined: an empty/unrecognized kind (schema default '', or a future
kind on a sim: link) falls back to a generic icon instead of crashing the chip's render. Adds tests.
- Add a mention input rule so typing `[label](sim:kind/id)` becomes a chip on the closing paren —
matching the paste/load path (the tokenizer), which previously left typed syntax as literal text.
A plain InputRule (full-range replace) is used; nodeInputRule would keep the surrounding brackets.
* fix(rich-editor): raw-fallback paste hook + bound the filtered mention list
- RawMarkdownField now honors onPasteText (e.g. skill SKILL.md destructuring), so a full-document
paste is intercepted in the raw fallback too, not only the WYSIWYG path.
- Bound the @-mention list while filtering (MAX_WHEN_FILTERED) so lifting the per-group cap for search
can't render thousands of rows in the non-virtualized menu on a broad query; search still reaches
deep matches well before the bound. Adds a test.
- Tighten an extensions.ts doc comment (the headless path omits the registry + node-view construction,
not React itself).
|
||
|
|
954de0559b |
improvement(docs): align components with the platform design system (#5227)
* improvement(docs): align components with the platform design system Bring the docs app's chrome in line with the main Sim design system, validated against the canonical emcn source in apps/sim. - ask-ai: fix undefined tokens (--text-base x6, --text-link) that broke the send-button fill and link/text colors; send button now matches the canonical primary fill (text-primary/text-inverse, dark:bg-white); use --shadow-medium and chip gap rhythm - not-found: replace the hand-rolled brand pill with <ChipLink variant='brand'> and swap fumadocs tokens for platform tokens - search-trigger: compose the exported chip chrome constants instead of re-spelling them (single source of truth) - what-you-will-learn, video-chapters: fumadocs fd-* tokens -> platform tokens - workflow-preview: add --wp-highlight token; route the #33b4ff highlight, #ef4444 error dots, and toggle/slider green through tokens - video-placeholder: tokenize the status pill (bespoke illustration art intentionally left as-is) dropdown-menu, faq, theme-toggle, and page-type-badge were deliberately left at their canonical values (14px row icons, rounded-md badge) after validation showed those match the platform, not the chip-pill, standard. * improvement(docs): neutral primary chip for nav CTA + fix cluster spacing Align the docs navbar with the main app, which reserves green for accents/status and uses a neutral high-contrast CTA in nav. - add a canonical `primary` chip variant (inverse fill: dark in light mode, white in dark mode), mirroring the emcn chip's primary action - "Get started" and the 404 "Go home" now use variant='primary' instead of the green brand surface - retire the now-unused `brand` chip variant (no parallel path left behind) - fix navbar right-cluster spacing: gap-2 to match the landing navbar and drop the asymmetric ml-1 on the CTA |
||
|
|
a1d5870681 |
feat(settings): unify all settings pages under a shared SettingsPanel layout (#5219)
* feat(settings): add SettingsPanel layout with nav-driven page titles Introduce a SettingsPanel scaffold that owns the standard settings chrome (fixed header bar with right-aligned actions, scroll region, centered content column) and renders a consistent page title + description pulled from the active section's navigation metadata. Adds a description to every nav item and a SettingsSectionProvider in the shell so the title is required-by-default without per-page wiring. Migrate the account/subscription pages (general, secrets, teammates, team-management, billing) to SettingsPanel, removing their hand-rolled shells and title blocks. * feat(settings): migrate all settings pages to SettingsPanel + bake in search Extend SettingsPanel with a `search` prop (canonical search field with optional anti-autofill hardening) so the repeated per-page search input is owned by the layout. Migrate every settings page — account, subscription, tools, system, enterprise, and superuser — onto SettingsPanel so each renders a consistent nav-driven title + description, header actions, and search with zero hand-rolled shell. Drill-down detail sub-views (MCP server, workflow MCP server, credential set, permission group) keep their own back-button chrome. Normalize all nav descriptions to a consistent voice and length. * refactor(settings): drop unnecessary search anti-autofill; document SettingsPanel Remove the preventAutofill prop from SettingsPanel — the shared search field no longer needs the read-only-until-focus hack, so secrets uses the plain search like every other page. Pre-existing honeypot inputs are untouched. Add .claude/rules/sim-settings-pages.md (auto-scoped to settings pages) and a settings-page skill documenting the SettingsPanel convention + add/audit procedure. * refactor(settings): extract SettingsEmptyState + RowActionsMenu, dedupe usages Encapsulate two more repeated settings patterns into shared components: - SettingsEmptyState — the muted empty/no-results/gate message (fill | inline), replacing ~42 hand-rolled status divs and normalizing stragglers that used text-small / text-tertiary back to the canonical text-muted + text-sm. - RowActionsMenu — the trailing '...' row-actions dropdown, replacing ~11 per-page DropdownMenu+MoreHorizontal blocks with a props-driven actions list. Pure presentational refactor: every message, action, handler, disabled, and destructive flag preserved (verified by diff review). Document both in .claude/rules/sim-settings-pages.md. * fix(settings): set autoComplete=off on the shared settings search field Keeps browsers from offering saved-credential autofill in a filter box — the lightweight standard guard, distinct from the removed read-only/preventAutofill machinery. Matters most on the secrets page. * chore(settings): strip non-TSDoc inline comments from touched files Remove JSX label comments, section/explanatory // comments, separator block comments, and copilot's commented-out MCP scaffold across the migrated files, per the repo's no-non-TSDoc-comments standard. TSDoc and functional directives kept. Comment-only deletions — no code or behavior changed. * chore(skills): rename settings-page skill to add-settings-page Aligns with the verb-prefixed naming of the other skills (add-integration, etc.). * feat(icons): Thrive icon-only black mark on white Drop the wordmark from ThriveIcon (tighten viewBox to the logo bounds), set the mark to pure black; the block bgColor is already white. Synced the docs icon copy. |
||
|
|
6355c8e699 |
improvement(docs): Ask AI chat grounded in the docs vector store (#5172)
* docs: Ask AI chat grounded in the docs vector store Adds an Ask AI chat to the docs site. A floating launcher opens a chat panel backed by the Vercel AI SDK (OpenAI provider, OPENAI_API_KEY from the environment). A searchDocs tool runs locale-scoped vector/keyword search over the existing docs embeddings so answers cite real pages. The public endpoint is hardened: per-request size/token/step caps, message sanitization (no client-injected tool results or system prompts), origin checks, and a per-IP rate limit. Non-English retrieval uses keyword search; English vector search applies a similarity threshold. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: harden Ask AI retrieval + fix stale loading state - searchDocs: wrap the keyword query in try/catch too, so each retrieval path (keyword, vector) is independent best-effort - ask-ai: gate the loading ellipsis to the in-progress (last) message so older empty bubbles don't re-show it while a later request streams Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
d20deedf99 |
improvement(docs): add Academy learning surface (#5213)
Adds the Academy section to the docs: video-first lessons (self-hosted MP4 on Vercel Blob), organized into Workflows, Agents, Tables, Files, and Knowledge Bases, each linking back to the reference docs. Lessons use a course layout (hero video with chapter seek, "what you'll learn", block diagrams). Docs only — no runtime or auth changes. The content may move to a separate CMS or its own site (academy.sim.ai) later; the docs are a starting point. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
371cc94851 |
feat(thrive): add Thrive Learning integration (47 tools + block) (#5214)
* feat(thrive): add Thrive Learning integration (47 tools + block) Add a full Thrive Learning (LMS) integration covering the public REST API: users lifecycle, audiences with members/managers, assignments and enrolments, completions, content and activity records, CPD, tags, and skills. Uses HTTP Basic auth (Tenant ID + API key) with a region selector for the v1/v2 hosts. * fix(thrive): surface malformed JSON errors, drop redundant limit param - parseThriveArray/parseThriveJsonObject now throw a descriptive error on malformed JSON instead of silently sending an empty/omitted value - additionalFields parse errors are surfaced to the caller - remove the redundant 'limit' query param (perPage already covers paging and the API prioritises perPage over limit) from the five list tools and block * fix(thrive): use a single status dropdown instead of reused canonicalParamId The block test forbids reusing a canonicalParamId across different operation conditions. Replace the two canonical status subblocks (search_users vs list_enrolments) with one 'status' dropdown whose options are labelled by context, fixing the canonical-pair validation failures. * fix(thrive): split status into context-specific user/enrolment dropdowns Addresses review feedback that one shared status dropdown mixed user lifecycle values (active/inactive/expired/new) with enrolment values (archived/complete/open/...). Use separate userStatus and enrolmentStatus dropdowns (no canonicalParamId) remapped to the tool's 'status' param so each operation only offers valid options. |
||
|
|
77976bcb8b |
feat(billing): unify upgrade routing with reason context + storage/tables limit emails (#5171)
* feat(billing): unify upgrade routing with reason context + storage/tables limit emails * fix(billing): re-arm limit-notification dedup on usage drops (prior-usage + decrement) * fix(billing): isolate per-admin email failures in org limit notifications * fix(billing): re-arm limit dedup at zero usage and zero prior usage (full clear / wipe-rebuild) * fix(billing): make storage-decrement notification re-arm only (never send on a shrink) * fix(billing): resolve recipients before claiming so opt-outs don't burn the dedup threshold * fix(billing): fire table limit emails on upsert inserts via shared notifyTableRowUsage * chore(billing): only log a limit email as sent when a recipient actually received it * chore(billing): match to_jsonb int cast between claim and re-arm for consistency * fix(billing): notify table limits post-commit so a rolled-back insert never emails or burns the claim * feat(pi): swap Pi Coding Agent icon to the pi glyph and use a black bgColor * fix(billing): drop priorUsage re-arm to make dedup a single atomic claim (no duplicate-email race) * docs(billing): move limit-notification rationale to TSDoc, correct tables warn-once behavior * docs(db): note limit_notifications dedup is per-account, not per-table * perf(billing): cut redundant subscription fetches and edge-gate notify to slash DB load * docs(billing): drop self-explanatory inline comments from the notification path |
||
|
|
e5f3965ed1 |
feat(mship): add parallel subagents, improve streaming performance (#5122)
* feat(subagents): add support for parallel subagents * fix(subagents): address parallel-subagent bugs * progress on streaming refactor * improvement(subagents): update comment to reflect new go feature flag * debug mode progress * remove debug logs * fix(validation): add escape annotation * improvement(code): remove dead fallbacks * fix subagent lane fallback issue * fix(mothership): increase default redis event limit to 100k from 5k * fix(mothership): streaming invariant projection enforcement --------- Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai> |
||
|
|
8b93e43037 |
improvement(integrations): validate BigQuery/Forms/PageSpeed + regenerate integration docs (#5109)
* improvement(integrations): validate BigQuery/Forms/PageSpeed + regenerate integration docs - BigQuery: mark null-defaulted outputs optional (get_table type/numRows/numBytes/creationTime/lastModifiedTime/location, list_datasets location, list_tables type, query totalBytesProcessed) - Google Forms: add response pagination (pageToken + filter params, nextPageToken output), fix pageSize visibility, advanced-mode pagination subBlocks + filter wandConfig - PageSpeed: add a 7th BlockMeta template (competitor benchmark) - Regenerate integration docs; add manual intro sections to new datagma/dropcontact/enrow/icypeas/leadmagic pages * fix(docs-gen): preserve apostrophes in tool descriptions when generating docs The doc generator extracted tool descriptions with a character class that excluded both quote types (['"]([^'"]...)['"]), so a double-quoted description containing an apostrophe (e.g. "Find someone's email") was truncated at the apostrophe — the generated docs/catalog showed stubs like "Find someone". Anchor extraction on the actual opening quote (single/double/backtick), matching the existing extractDescription helper, in both buildToolDescriptionMap and extractToolInfo. Regenerated docs restore full descriptions across all affected integrations (Apollo, Ahrefs, LeadMagic, Findymail, OpenAI, Slack, etc.). * fix(docs-gen): resolve tools defined in a sibling file + scope params per tool The doc generator located a tool's definition only by filename convention (decompress.ts / index.ts), so file_decompress — which lives in compress.ts alongside file_compress — fell back to index.ts and rendered an empty Input table. It also read the params block from the first tool in a multi-tool file, so every tool in such a file inherited the first tool's inputs/outputs. - getToolInfo: when no candidate file declares the exact tool ID, scan the whole tool-prefix directory for the file that does. - extractToolInfo: read the params block scoped to the specific tool, falling back to the full file for tools that inherit params via spread. Regenerated docs eliminate ~50 empty/incorrect input tables across integrations (clickhouse, rb2b, reddit, file, etc.); param-less OAuth-only tools correctly keep an empty input table. |
||
|
|
05e8c7cd71 |
refactor(connectors): split client metadata from server runtime (#5076)
* refactor(connectors): split client metadata from server runtime + cover node:net in client bundle The browser build broke with `Cannot find module 'node:net'`. Server-only SSRF code in `input-validation.server.ts` (`dns/promises`, and since PR #5060 `undici` → `node:net`/`node:tls`) is statically reachable from the client bundle via the tool/connector registries, which the workflow editor imports for metadata. Node networking builtins have no browser shim, so Turbopack cannot compile them for the client. Two changes: 1. Split each connector's client-safe declarative metadata into a sibling `meta.ts` (`<name>ConnectorMeta`), mirroring the `XBlockMeta` / `BLOCK_META_REGISTRY` pattern. `connectors/registry.ts` is now the client-safe `CONNECTOR_META_REGISTRY` (+ `getConnectorMeta` / `getAllConnectorMeta`); the full registry with runtime fns moves to `connectors/registry.server.ts`. Client components consume the meta registry; the sync engine and knowledge API routes consume the server registry. This removes connectors from the client's server-only graph. Connector metadata is byte-for-byte identical before/after; runtime fns are untouched. 2. Extend the existing #4899 `turbopack.resolveAlias` browser stub — which already mapped `dns`/`dns/promises` to an empty module for the browser — to also cover `net`/`tls` (+ `node:` variants), since `undici` now pulls those in. The remaining tool/provider definitions still reach `input-validation.server` server-side; the browser-only stub keeps those Node builtins out of the client bundle while the real modules stay on the server, so SSRF validation and IP pinning are unaffected. Connector authoring/validation skills updated to teach the meta.ts split. * fix(icons): use Square logo glyph only, drop wordmark * fix(connectors): share Discord max-messages default across meta and runtime Discord defined DEFAULT_MAX_MESSAGES separately in meta.ts (config placeholder) and discord.ts (sync behavior), which could drift. Export it from meta.ts and import it in the runtime, matching the single-source pattern used by the other connectors (e.g. gmail, intercom). * refactor(tools): route grafana/agiloft egress server-side, drop SSRF browser shim Move the server-only SSRF-pinned fetch out of the grafana (update_dashboard, update_alert_rule) and agiloft (11 record/search tools) definitions and into internal API routes, the same pattern the rest of the server-side tools (and agiloft's own attach/retrieve) already use. The tool definitions are now purely declarative (request → internal route), so they no longer import `input-validation.server` and the tools registry is fully client-safe. With connectors (meta split) and these tools no longer reaching server-only code from the client bundle, the browser no longer pulls in `dns`/`net`/`tls`: - Add `import 'server-only'` to `input-validation.server.ts` so any future client import fails loudly at build time instead of silently bloating the bundle. - Remove the `turbopack.resolveAlias` browser stub and delete `empty-node-fallback.browser.ts` — the root cause is fixed, the shim is gone. Behavior is unchanged: each route runs the exact merge/validation/fetch logic the tool ran before (every header, param branch, JSON-parse guard, error string, and SSRF pinning preserved); only the location of execution moved from the client- bundled definition to a server route. * fix(connectors): move onedrive tagDefinitions into meta; drop server-only guard - onedrive's tagDefinitions lived in the runtime file, so the client meta registry returned undefined for it and the add-connector tag opt-out section stopped rendering for onedrive. Move it into meta.ts like the other connectors so client and server see identical metadata (verified across all 50). - Remove the 'server-only' import from input-validation.server.ts: the meta/route split already keeps it out of the client bundle, and blocks/tools registries don't use the guard either. * fix(grafana): surface upstream error when the prefetch GET fails Check response.ok on the existing-resource GET in both update routes and return the upstream status/body, matching how the tool framework surfaced GET errors before the move to internal routes (the framework checks response.ok before transformResponse). Without this, a failed prefetch produced a generic 'Failed to fetch existing ...' message and dropped Grafana's error detail. * fix(grafana): reject invalid panels JSON instead of silently ignoring it Grafana's dashboard API treats panels as a required array and returns 400 on invalid JSON; this route already errors on every other JSON param. Return 'Invalid JSON for panels parameter' instead of swallowing the parse error and proceeding with a misleading success. * fix(grafana): trim dashboard/alert-rule UID in route URLs (carry over #5082) PR #5082 added .trim() on dashboardUid/alertRuleUid in the original tool URL builders. Those tools now build their URLs in the internal routes, so apply the same trim there to preserve that behavior. * fix(grafana): route update_folder egress server-side (carry over #5082) #5082 added a grafana update_folder tool that does SSRF-pinned fetch in its postProcess, re-introducing the client-bundle leak. Convert it to the internal API route pattern like the other update tools so the def is declarative and input-validation.server stays out of the client bundle. * fix(grafana): surface route failures in transformResponse instead of masking them The grafana update tools' transformResponse hardcoded success: true and dropped the route's error, so an upstream/validation failure (HTTP 200 with { success: false, error }) was reported to the workflow as a success. Forward data.success and data.error (matching the agiloft tools) so failures propagate as before the move to internal routes. |
||
|
|
324189ed39 |
feat(grafana): validate integration and add folder, health, and contact-point tools (#5082)
* feat(grafana): validate integration and add folder, health, and contact-point tools - Require alert-rule title/ruleGroup/data in the block (create would 400 without them) - Trim UID path params across dashboard and alert-rule tools to avoid copy-paste 404s - Use Grafana brand color for the block background - Surface previously-unsettable list params (limit, starred, annotation type) - Add get/update/delete folder, check data source health, get health, and create contact point tools - Strip non-TSDoc comments; regenerate docs and integrations.json * fix(grafana): scope block param remaps per operation to prevent cross-operation leaks |
||
|
|
940506ad09 |
feat(square): add Square integration with 34 commerce operations (#5053)
* feat(square): add Square integration with 34 commerce operations Add a Square integration (API-key auth via personal access token) covering payments, refunds, customers, locations, orders, invoices, catalog, and inventory. Catalog image upload routes through an internal API endpoint using the shared UserFile handling pattern. Adds a dedicated square-errors extractor. * fix(square): correct catalog image part name and address review feedback - Fix catalog image upload: Square's multipart part for the binary is `file`, not `image_file` (per the live API cURL examples); this would have caused upload failures - Catalog image route: check response.ok before parsing, drop the unreachable legacy base64 path, derive MIME from the uploaded file - Block: split the search query field per operation so placeholders match each endpoint's schema; parse each JSON field individually so errors name the field - Round out coverage: complete_payment version_token; customer nickname/birthday; batch inventory states/updated_after/limit * fix(square): correct canonical file param usage and revert query split - Read the catalog image file from the canonical `params.file` (the basic/advanced inputs are collapsed before the params function runs) instead of the raw uploadFile/fileRef ids, which no longer exist at that point — fixes the Canonical Param Validation test and a latent upload bug - Revert the per-operation query split: canonicalParamId is only valid for basic/advanced pairs under one condition. Use a single query field with a schema-neutral placeholder and a wand prompt that covers each search operation * chore(square): trigger fresh review * fix(square): single-location invoice search and guard numeric coercion - SearchInvoices: Square's invoice filter accepts only one location, so take a single locationId (string) instead of an array and wrap it as query.filter.location_ids: [locationId] - Block: fail locally with a clear "<field> must be a valid number" error when amount/limit/version/orderVersion are non-numeric instead of forwarding NaN * fix(square): accept real booleans for autocomplete/includeRelatedObjects Coerce these from both the dropdown's string values and actual booleans (which can arrive via connected blocks or templated inputs), so true is not silently flipped to false. * fix(square): validate parsed JSON field shapes (array vs object) parseJsonField now enforces the expected shape so a valid-but-wrong-type value (e.g. a JSON string where an array is expected for locationIds/objectTypes/ paymentIds/catalogObjectIds/states, or a non-object for order/invoice/etc.) fails locally with a clear message instead of a confusing Square API error. |
||
|
|
57b58fd117 |
feat(context-dev): add Context.dev web + brand data integration (#5048)
* feat(context-dev): add Context.dev web + brand data integration * feat(context-dev): add brand variants, products, fonts, styleguide, images, prefetch Expands coverage to all relevant Context.dev endpoints (22 tools): brand by name/email/ticker, simplified brand, transaction identifier, single + catalog product extraction, fonts, styleguide, image discovery, and prefetch utilities. Shared brand output schema and transform helper; verified against the live API. * fix(context-dev): wire includeFrames, split crawl/extract maxPages, derive screenshot MIME Addresses review feedback: - includeFrames is now a block subblock + param for scrape_markdown/scrape_html - crawl and extract use separate Max Pages fields (crawl 1-500, extract 1-50) so a crawl value can no longer be forwarded to extract beyond its limit - screenshot file MIME type and extension are derived from the returned URL instead of being hardcoded to PNG |
||
|
|
6282b16c4f |
feat(hubspot): add notes, emails, properties & associations tools (#5037)
* feat(hubspot): add notes, emails, properties & associations tools - Add 11 tools: get_properties (read property/enum options), notes (create/get/list/search), email engagements (create/get/list/search), and v4 associations (list/create) - Add scopes: crm.objects.notes.read/write, crm.objects.emails.read/write, sales-email-read (required for email engagement content) - Wire new operations into the HubSpot block (subBlocks, conditions, tool mapping, outputs, BlockMeta templates/skills) - Fix pre-existing bugs found in validation: list_marketing_events list URL (/marketing/marketing-events/v3), appointment property names (hs_appointment_*), get_users output shape (CRM envelope), create_list response unwrap, and stringified-associations parsing in create tools - Regenerate integration docs * fix(hubspot): drop non-grantable notes/emails scopes; remove inline comments - crm.objects.notes.*/crm.objects.emails.* are not grantable HubSpot scopes (would break the OAuth authorize flow). Notes/emails engagement and association endpoints are authorized by crm.objects.contacts.*; sales-email-read remains for email-engagement content - Remove non-TSDoc inline comments from new tool files * fix(hubspot): address review comments - Forward the properties param for the Get Users operation (block param mapping + Properties-to-Return field now include get_users) - Use Record<string, unknown> for create_note/create_email request bodies - Only send Content-Type on create_association when a body is sent (default-association PUT has no body) - Remove stray duplicate JSDoc opener in types.ts |
||
|
|
746520c1a7 |
fix(mothership): streaming completion-flash fix + Tavily brand icon (#5030)
* fix(mothership): keep isAnimating latched so completed messages don't flash The streamed-text reveal latches `mode` and `animated` via `keepStreamingTree` to avoid the streaming→static handoff flash, but `isAnimating` was still wired to `isRevealing`, which flips false the instant the reveal catches up. Streamdown treats `isAnimating: false` as "streaming over" and rebuilds the whole message without the per-word animation spans — that DOM rebuild is a visible flash when a message finishes. Wire `isAnimating` to the same `keepStreamingTree` latch so all three Streamdown props stay constant across completion. Content is stable once revealed, so a permanently-true `isAnimating` has no new tokens to fade and never re-animates. * feat(tavily): official brand icon and white block background Replace the Tavily block icon with the official brand mark and set the block bgColor to white. Ran generate-docs so the docs app icon, the Tavily docs page, and the integrations catalog pick up the new icon/color. |
||
|
|
58cff68b5e |
feat(deployments): add v1 deployment endpoints and Deployments block (#5009)
* feat(deployments): add v1 deployment endpoints and Deployments block * fix(deployments): require deployed workflow for rollback, normalize warnings, guard orphaned workspaceId * fix(deployments): workspace-bound tool routes, optional-body parsing, version bounds, and 404 masking - Tool routes now require the executing workspace ID and reject cross-workspace targets - v1 deploy/rollback read optional bodies via parseOptionalJsonBody (size-capped, 400 on malformed JSON) - Version numbers bounded to the Postgres integer range - v1 mutation routes mask access failures as 404, matching the v1 detail route - listWorkflowVersions returns description and normalizes admin-api deployedByName (parity with mothership get_deployment_log) - Workflow selector no longer auto-selects the first workflow (new autoSelectFirstOption opt-out) - Shared deployment version metadata field schemas across UI/v1/tool contracts * chore(api-validation): bump route baseline for rebased staging (826) * fix(docs): use real ID formats in OpenAPI examples Workflow, workspace, folder, knowledge-base, document, and execution IDs are plain UUIDv4; workspace file IDs are wf_<shortId>; table and row IDs are tbl_/row_ + de-dashed UUID. Replaces all fake prefixed example IDs (wf_abc123, ws_xyz789, exec_..., kb_..., etc.) accordingly and marks the deploy body description as nullable to match the shared schema. * feat(deployments): resolve workflow names in block UI, add workflow_undeployed Sim trigger event - Deployments block now uses the workflow-selector subblock (same as the Workflow block), so the canvas tile shows the workflow name instead of the raw ID; reverts the now-unneeded dropdown autoSelectFirstOption prop - Adds workflow_undeployed to the Sim workspace-event trigger, emitted by performFullUndeploy through a shared lifecycle-event dispatch loop |
||
|
|
3db7161b1c |
feat(integrations): add Vanta integration with compliance, evidence file, people, vendor, vulnerability, and risk tools (#4993)
* feat(integrations): add Vanta integration with compliance, evidence file, people, vendor, vulnerability, and risk tools * fix(integrations): use write-only scope for vanta document submit and stream-cap document downloads * fix(integrations): vanta review feedback - unique svg ids, mime type for base64 uploads, auth check consistency * fix(integrations): bound vanta base64 fileContent size at the contract level * improvement(integrations): cache vanta tokens and retry once on revocation to avoid concurrent token races * improvement(integrations): deduplicate in-flight vanta token exchanges * fix(integrations): hash vanta client secret in token cache keys * improvement(integrations): expose vanta upload mime type in block and align fileContent bound with the 100MB cap * chore: resolve api-validation baseline after rebase onto staging (816 + 3 vanta routes) |
||
|
|
c3b98eb1c4 |
feat(integrations): add Daytona integration with sandbox lifecycle, code execution, and file tools (#4987)
* feat(integrations): add Daytona integration with sandbox lifecycle, code execution, and file tools * fix(daytona): address review feedback and harden edge cases - Pre-check file size via userFile.size before downloading from storage in the upload route - Tolerate empty response bodies in delete/start/stop sandbox tools - Preserve explicit timeout 0 for run_code and execute_command - Default missing exitCode to -1 so unknown state is distinguishable from success - Reject blank sandbox IDs, clamp list limit to 1-200, trim destination path - Clarify that toolbox operations require the sandbox ID (not name) - Bump contract route baseline to 812 for the new daytona upload route * fix(daytona): cap download size at 100MB and preserve sandbox identity on empty lifecycle responses * improvement(notion): black icon on white background to match brand * fix(daytona): reject oversized base64 uploads before decoding * improvement(landing): move integration last-updated below CTAs and de-emphasize it * fix(daytona): forward explicit zero cpu/memory/disk values in create sandbox |
||
|
|
8e960368d4 |
feat(integrations): add Quartr integration with company, event, document, audio, and live event tools (#4986)
* feat(integrations): add Quartr integration with company, event, document, audio, and live event tools * fix(quartr): address review findings — null-safe query building, string boolean toggles, accurate descriptions, NestJS validation error extractor |
||
|
|
9ab64e55e3 |
feat(integrations): add Convex integration with function execution and data export tools (#4981)
* feat(integrations): add Convex integration with function execution and data export tools * fix(convex): separate List Documents page cursor from deltas cursor and surface HTTP errors in transforms * fix(convex): rename List Documents pagination cursor to pageCursor end-to-end for unambiguous chaining * fix(convex): validate deployment URL with shared SSRF guard * improvement(convex): polish from final validation pass — reject query strings in deployment URL, validate object args, fix sync skill wording * docs(convex): note streaming export plan requirement on data-export tools (verified via live E2E) |
||
|
|
5ab6d0d1ab |
feat(integrations): add Brex integration (#4983)
* feat(integrations): add Brex integration with expenses, receipts, transactions, team, budgets, and payments tools * fix(brex): reject whitespace-only expense IDs in receipt upload instead of silently falling back to receipt match * fix(brex): trim receipt name in contract so whitespace-only overrides are rejected * fix(brex): align spend limit balance shape, enum descriptions, and pagination metadata with Brex API specs * improvement(brex): validate pre-signed upload URL with DNS pinning and harden API key input * fix(brex): correct shared limit placeholder to reflect the 100-item cap on list expenses * fix(brex): normalize timezone-suffixed timestamps for transactions date filters (Brex rejects offsets) |
||
|
|
493c64fe08 |
feat(latex): add LaTeX integration with PDF compilation tool, block, and docs (#4972)
* feat(latex): add LaTeX integration with PDF compilation tool, block, and docs * fix(latex): surface extracted TeX errors on all failed compile responses * improvement(latex): add compile timeout, cap upstream error code, reject empty resource payloads * feat(latex): add package search/lookup and font listing tools * improvement(latex): address review findings — path traversal guard, http(s)-only resource urls, timeout abort handling, typed pdf output, NaN-safe maxResults, empty-query rejection, third-party disclosure * fix(latex): fail compile/package lookups that return no payload * improvement(latex): guard lookup tool responses against upstream errors * improvement(latex): reject whitespace-only package names at the block boundary * improvement(latex): make relatedPackages fallback explicit |
||
|
|
5028ef3b16 |
feat(temporal): add Temporal integration with workflow, schedule, and task queue tools (#4976)
* feat(temporal): add Temporal integration with workflow, schedule, and task queue tools * improvement(temporal): send requestId on all dedupe-capable write operations |
||
|
|
354653b82f |
feat(integrations): add Trigger.dev integration (#4974)
* feat(integrations): add Trigger.dev integration * feat(integrations): cover the full Trigger.dev management API surface Adds batch retrieve/results, run result/events/trace/tags, queue list and concurrency override/reset, deployments, TRQL query + schema, waitpoint tokens, env var import, and timezones (44 tools total). Marks deduplicationKey required on create schedule and switches list-run filters to the documented comma-separated form, both per the OpenAPI spec. * fix(executor): strip dots from normalized block names so dotted names resolve References split on '.', so a block named "Hunter.io 1" could never be resolved (the first path segment cut the name at the dot). normalizeName now strips dots on both the tag-generation and lookup sides, which cannot break any previously working reference. Aligns the inline normalizers in connection drag-drop, deploy modal, output select, and tag dropdown, and renames Cal Com to Cal.com now that dotted display names work. * improvement(integrations): address Trigger.dev review feedback Reads the delete schedule response instead of hardcoding success, and adds explicit plaintext-secret warnings to the env var read operations and docs. * fix(integrations): scope Trigger.dev block params to the selected operation Advanced sub-block values with non-empty content are serialized regardless of their operation condition, so values left over from a previously selected operation could leak into another operation's API call (e.g., a trigger-task idempotency key filtering the waitpoint list). The params function now routes every shared or remapped param by the selected operation and clears it otherwise. Also derives delete env var success from the response like delete schedule, via a shared helper. * improvement(executor): dot-free names keep reference ownership on legacy collisions Name uniqueness is enforced at the normalized level on create and rename, so new collisions cannot be created. For legacy workflows that already contain names differing only by dots, the resolver now lets the dot-free name own the reference key regardless of block order, so previously working references never change targets. |
||
|
|
e5d655b1be |
feat(persona): add Persona identity verification integration (#4967)
* feat(persona): add Persona identity verification integration * feat(persona): complete API coverage — inquiry lifecycle, account update/redact, report listing, template discovery * improvement(persona): explicit HTTP error handling in all transforms, fix tags wand generation type * chore(persona): align docs path and docsLink with staging structure * improvement(persona): fail-closed file access gate on import route, explicit error when one-time link missing * improvement(persona): validate report template ID before request * improvement(persona): reject unexpected import response bodies instead of returning an empty importer * improvement(persona): require session token on resume per API contract |
||
|
|
aa39974d7b |
improvement(docs): align docs UI with the platform emcn design system (#4962)
* improvement(docs): align docs UI with the platform emcn design system * improvement(docs): build language dropdown options in render scope |
||
|
|
bc55fc3b50 |
improvement(docs): builder-first IA reorganization of the English docs (#4896)
* docs: reorganize into topic/ontology IA with a builder-first rewrite Restructure the English docs from internal product categories into a topic-based information architecture, and rewrite the conceptual pages to install a mental model first rather than enumerate features. Structure & navigation - Reorder the sidebar to follow how someone builds: Get Started -> Workflows -> Tables -> Files -> Knowledge Bases -> Logs -> Building agents -> Mothership -> Workspaces -> Platform -> Reference. - Demote the generated blocks/tools/triggers catalogs to a Reference section at the bottom. - Break up the monolithic execution/ folder into deployment/ and logs-debugging/; collapse connections/* and variables/* into single pages under workflows/. - Rename capabilities/ to building-agents/; relabel the integration catalog as "Integrations". Remove deprecated copilot and form deployment. Redirects added in next.config.ts for every moved URL. Conceptual rewrites - Workflows core (index, how-it-runs, data-flow, connections, variables): one mental model, one running example, terser prose. - New building-agents overview distinguishes an agent (a workflow you build) from an Agent block (one reasoning step), plus a "choosing what to use" guide. - Concept-trim passes on Knowledge Base, Tables, Blocks, Triggers overviews; new task pages for KB, Tables, and Files. - New code-verified Alerts page. Infrastructure - pageType frontmatter (concept/guide/reference) + badge render. - WorkflowPreview / OutputBundle components to embed real, app-styled workflow diagrams (adds framer-motion + reactflow to apps/docs). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(docs): spec-driven BlockPreview for block reference heroes Replace the static screenshot hero on each block reference page with a <BlockPreview> that renders the block exactly as the builder canvas shows it — header icon, sub-block rows, and branch/error handles — from a hand-authored display spec. Static and non-interactive (no ReactFlow), so it can't be panned or dragged, and self-updating to edit. - block-display-specs.ts: one editable spec per block (rows, branches, handles) - block-preview.tsx: static scaled card renderer with decorative handles - block-icons.tsx: brand glyphs for the core block types; icons.tsx adds WaitIcon - 14 block + 3 trigger pages swapped from <Image> to <BlockPreview> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(docs): correct stale navigation and removed-feature references Audited the docs against the product changelog (GitHub releases / staging git history) for content that misleads readers — features that moved, were renamed, or removed — rather than cosmetic drift. Fixes: - Skills: no longer a Settings tab. It was promoted to its own workspace page (#4354), so "Settings → Skills under the Tools section" sent readers to a tab that no longer exists. (skills/index.mdx) - Env vars: the workspace tab is "Secrets", not "Environment Variables" (credentials→secrets rename, #4364). (quick-reference/index.mdx) - Mothership FAQ pointed to "Settings → Credentials" for integration connections; integrations moved to their own page and there is no Credentials tab. (mothership/tasks.mdx) - Vision block was retired (#4684); a tip still named it. Reworded to "an Agent using a vision-capable model". (files/passing-files.mdx) - Getting-started FAQ told new users to "use the Copilot feature" to build in natural language — that surface is Mothership. (getting-started) - Removed the dead "Mod+Y → Go to templates" shortcut; the templates gallery was removed (#4354). (keyboard-shortcuts) Note: MCP "tools" (Settings → Tools, for consuming) and MCP "servers" (Settings → System, for exposing) are distinct surfaces — both doc references are correct and were intentionally left as-is. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(docs): repair broken /docs-prefixed enterprise links The enterprise overview linked to /docs/enterprise/* (access-control, sso, whitelabeling, audit-logs, data-retention, data-drains), but the docs site is served at root — those 6 links 404'd. Now root-relative /enterprise/*. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(docs): refresh stale workflow-preview example blocks The /workflows diagram blocks are hand-authored (separate from the spec-driven BlockPreview heroes) and had drifted from the real UI: - Agent color purple #6f3dfa -> green #33C482 (the var(--brand) rebrand) - Model gpt-4o -> claude-sonnet-4-6 (current default) - "Prompt" row -> "Messages" (the actual agent sub-block) - Start color #34B5FF -> #2FB3FF (real starter bgColor) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(docs): align BlockPreview input/output handles to the card edge The header (input/output) handles are positioned relative to the card and used a -16px offset, so they floated 8px past the edge. Row/error handles are -16px relative to a row that's already inset 8px by content padding, so they sit correctly. Header handles are now -8px, so every handle sticks out the same 8px and hugs the block edge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): rewrite Agent reference to match the current block The page documented the old UI (System/User Prompt, no Files or Skills, Memory taught as a separate block — contradicting its own FAQ). Rewritten to the real sub-blocks (Messages, Model, Files, Tools, Skills, Memory, Response Format) in the builder voice of the workflows exemplars: oriented opening, agent vs Agent-block callout, outputs table, a live WorkflowPreview example, FAQ kept and corrected (tool control "Force", not "Required"). pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): rewrite API reference to match the current block Tightened to the builder voice and the real config (URL, Method, Query Params, Headers, Body + Advanced timeout/retries/backoff). Dropped the off-topic "Dynamic URL Construction" / "Response Validation" sections (those are Function-block techniques, not API config). Outputs table, FAQ kept. The example is now a live WorkflowPreview (new API_FETCH_WORKFLOW in examples.ts, exported via the barrel). pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): rewrite Condition reference to match the current block Tightened to the builder voice: oriented opening (branches on boolean expressions, no model call, vs Router), the real branch model (if / else if / else, checked top to bottom), connection-tag expression examples, an error-path callout, outputs table, and a live branching WorkflowPreview example (CONDITION_ROUTE_WORKFLOW). FAQ kept. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): restore Best Practices + multi-example workflows on Condition Recalibration: reference pages keep genuine substance (Best Practices, every distinct example), cutting only redundancy and verbose register. Restores the Best Practices section and turns the three use cases into three rendered WorkflowPreview examples (route by priority, moderate content, branch onboarding). Adds CONDITION_MODERATE_WORKFLOW and CONDITION_ONBOARD_WORKFLOW. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): restore Best Practices on Agent reference Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): restore Best Practices on API reference Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): rewrite Function reference to match the current block Fixed the verbose register and dropped the duplicated outputs section + the stale Python screenshot/TODO, while keeping the real substance: JS vs Python (local vs E2B sandbox), the large-inputs sim.files/sim.values helpers, the worked loyalty-score example, and Best Practices. The use cases are now two rendered WorkflowPreview examples (reshape an API response, validate input). Adds FUNCTION_RESHAPE_WORKFLOW and FUNCTION_VALIDATE_WORKFLOW. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): rewrite Router reference to match the current block Cleaned the register, generalized the drifting model list, and folded the Router-vs-Condition guidance into a callout. Kept the substance (routes as output ports, NO_MATCH error path, all seven outputs, Best Practices, FAQ). The three same-shape use cases collapse to one rendered triage WorkflowPreview (ROUTER_TRIAGE_WORKFLOW), which the prose notes stands for the pattern. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): restore the classify and lead-qual examples on Router I wrongly folded two distinct Router scenarios into a note. Restored all three as their own rendered WorkflowPreview examples: triage a support ticket, classify feedback (to child workflows), qualify a lead (sales vs self-serve). Adds ROUTER_CLASSIFY_WORKFLOW and ROUTER_LEAD_WORKFLOW. (Also exports RESPONSE_API_WORKFLOW for the next page.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): rewrite Response reference to match the current block Cleaned the register and broadened "Variable References" to connection tags (any output, not just workflow variables). Kept the substance: exit-point semantics, Builder/Editor mode, status codes, headers, the parallel-branch warning, Best Practices, FAQ. All three use cases are now rendered WorkflowPreview examples (API endpoint, webhook ack, status-per-branch). Adds RESPONSE_API/WEBHOOK/ERROR_WORKFLOW. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): rewrite Variables reference to match the current block Cleaned the register, corrected the outputs (each assignment is also exposed as <variables.name>, not "no outputs"), and kept the substance: assignments reference earlier outputs and current values, global <variable.name> access, Best Practices, FAQ. Two use cases now render as WorkflowPreview examples (count retries, hold config). Adds VARIABLES_RETRY_WORKFLOW and VARIABLES_CONFIG_WORKFLOW. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): rewrite Wait reference to match the current block Corrected a real staleness: the block now has an Async mode that suspends the run for minutes/hours/days (not a hard 10-minute cap), plus a resumeAt output. Documents Wait Amount / Unit / Async, the sync-vs-async distinction, all three outputs, Best Practices, and updated FAQ. Two rendered WorkflowPreview examples (space out API calls, delayed follow-up). Adds WAIT_RATELIMIT_WORKFLOW and WAIT_FOLLOWUP_WORKFLOW. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): polish Credential reference (frontmatter, fold redundant tabs) The page was already accurate to the block (Select/List operations, the outputs tabs, the wiring steps). Light touch only: added description + pageType, made the header consistent, and folded the two identical Gmail/Slack "how to wire" tabs into one line. Examples stay as labeled flows + the List/ForEach screenshot, since they use integration blocks and a Loop the WorkflowPreview can't render. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): render the shared-credential example + icon fallback for integrations Addressing the gap: WorkflowPreview block nodes now fall back to the integration icon map, so diagrams can show Gmail/Drive/Slack/etc. with their real glyphs, not just core blocks. Renders the Credential "share one account across blocks" example as a WorkflowPreview (CREDENTIAL_SHARE_WORKFLOW). The multi-account and List+ForEach examples stay as labeled flows + screenshot (the latter uses a Loop container the preview can't render). Also exports EVALUATOR_GATE_WORKFLOW for the next page. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): rewrite Evaluator reference to match the current block Cleaned the register, generalized the drifting model list, and documented the per-metric outputs (<evaluator.metricname>), which the page omitted. Kept the substance (metrics with name/description/range, structured-output guarantee, Best Practices, FAQ). The quality-gate example renders as a WorkflowPreview; the same shape covers the parallel-variations and support-QC patterns, noted in prose. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): render the Credential route-by-logic example too The icon fallback unblocked it: the "route to a different account by logic" example now renders as a WorkflowPreview (CREDENTIAL_ROUTE_WORKFLOW), a Condition selecting a production vs staging credential. The List + ForEach example stays a screenshot because it nests blocks in a Loop container the flat WorkflowPreview can't represent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): render Guardrails examples + light accuracy pass Kept the full substance (four validation types, PII entity/language detail, the PII screenshot and video, outputs, Best Practices, FAQ). Light fixes: frontmatter, and generalized the drifting model names (GPT-4o / Claude 3.7) to "a strong reasoning model" with the current default. The three use cases now render as WorkflowPreview examples (validate JSON, check grounding, block PII). Adds GUARDRAILS_JSON/HALLUCINATION/PII_WORKFLOW. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): render Human-in-the-Loop examples + frontmatter Kept all the substance (Display Data, Notification, Resume Form, the Approval Methods and API Execute Behavior tabs, outputs, the paused/resume example). Added frontmatter and rendered the use cases as WorkflowPreview examples (approve before publish, two-stage approval, verify extracted data); Quality Control folds into the approval note as the same approve-then-act shape. Adds HITL_APPROVAL/MULTISTAGE/VALIDATE_WORKFLOW. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): render Webhook examples + frontmatter The page was already accurate (Webhook URL/Payload/Signing Secret/Headers, the automatic-headers table, HMAC details, outputs, POST-only callout, FAQ). Added frontmatter and rendered the two use cases as WorkflowPreview examples (notify a service, fire on a check). Adds WEBHOOK_NOTIFY_WORKFLOW and WEBHOOK_TRIGGER_WORKFLOW. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): add example + pageType to Workflow block reference The page was already accurate and well-structured (Configure It, outputs, deployment-status badge, execution notes, FAQ). Added pageType: reference and a rendered WorkflowPreview example showing a parent calling the child workflow enrich-lead and reading its result. Adds WORKFLOW_CALL_WORKFLOW. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): container rendering for Loop/Parallel + render the Loop example Adds subflow/container support to WorkflowPreview, modeled on the app's subflow-node.tsx: a solid-bordered box with a header (icon + name), an internal "Start" pill whose handle feeds the first nested block, and target/source handles at the vertical center. PreviewBlock gains size/parentId; edges gain an optional sourceHandle; nodes render nested children via React Flow parentNode. Renders the Loop reference's ForEach example (LOOP_WORKFLOW) and keeps the four loop-type sections + inside/outside referencing + caps. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): fix the Loop container's Start-pill connector The Start pill -> first-block edge wasn't rendering: it was a React Flow parent->child edge (unreliable), and the opaque container body hid it. Nested blocks now render as absolute-positioned top-level nodes (container below at zIndex 0, blocks above at zIndex 1), so the connector is an ordinary edge, and the container body is see-through so it's visible. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): render the Parallel example + frontmatter (last core block) Reuses the container rendering for the Parallel reference. Kept all substance (count/collection types, inside/outside referencing, batch size of 20, instance isolation, the Parallel-vs-Loop table, Best Practices, FAQ). Added frontmatter and a rendered container WorkflowPreview (PARALLEL_WORKFLOW: distribute tasks, call concurrently, aggregate <parallel.results>); the two use cases stay as labeled flows. Adds PARALLEL_WORKFLOW. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): prose glow-up for Guardrails to match the agent/condition voice Rewrote the listy register (**Use Cases:** / **How It Works:** / **Configuration:** scaffolding, "Use this when you need to..." filler) into the plain builder voice, matching the depth of the Agent/Condition/Function rewrites. Kept every validation type, option, range, the full PII entity/region list, the screenshot and video, the outputs table, the rendered examples, Best Practices, and FAQ. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): prose glow-up for Loop to match the agent/condition voice Rewrote into the plain builder voice and cut the filler: dropped the "Use this when you need to..." lines and the ASCII "Example: Iteration 1, 2, 3" pseudo-code, and folded the duplicated Inputs/Outputs tabs into Configuration + Referencing sections. Kept all four loop types with their screenshots, the inside/outside reference rules, the 1,000-iteration cap, sequential-vs-parallel guidance, the rendered example, and FAQ. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): prose glow-up for Parallel to match the agent/condition voice Same treatment as Loop: plain builder voice, dropped the ASCII pseudo-code and the duplicated Inputs/Outputs tabs, folded the verbose Advanced Features into tight Configuration + Referencing sections. Kept both types with screenshots, the batch-size-of-20 cap, instance isolation, large-result indexing, the Parallel-vs-Loop table, the rendered example, and FAQ. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): prose glow-up for Human-in-the-Loop Tightened the register: folded the pause sentence into the intro, made the section headers consistent (Configuration, Outputs), converted the bold-list Block Outputs into a table, condensed the Notification channel bullets to a line, and renamed the second "Example" so it no longer collides with the rendered Examples. Kept all the substance — Display Data / Notification / Resume Form, the Approval Methods and API Execute Behavior tabs, the portal video, and FAQ. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): re-enrich Loop prose (fuller, explanatory — not terse) The first glow-up overcorrected into terse fragments. Restored proper docs-quality prose at the Agent/Condition level: each loop type now explains what it does, when to use it, and the relevant reference; Configuration, Referencing, nesting, and Best Practices give context and the "why," not just bullets. Same substance, readable depth. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): re-balance Parallel prose to the Agent/Condition register Calibrated to the level signed off on elsewhere: each concept explained in a couple of clear sentences with a concrete detail — informative, not terse, not padded. Kept both types with screenshots, batch-size cap, isolation, large-result indexing, the Parallel-vs-Loop table, the rendered example, and FAQ. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): restore the Notification channel detail on HITL The glow-up over-compressed: it flattened the five notification channels (each with what they do) into one sentence. Restored them as a list in plain voice — tightening register shouldn't drop genuinely useful reference detail. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): builder-voice polish on the Credential intro Light touch only — the page was already well-structured and explanatory, so just led the intro with what the block does (and bolded the name) to match the other references. No content changed elsewhere. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(triggers): rewrite Start trigger in the builder voice Tightened the register, swapped the <code><></code> noise for backticks, added pageType + an outputs table, and kept all substance: Input Format types, chat-only outputs (input/conversationId/files), the editor/API/chat tabs, and best practices. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(triggers): rewrite Schedule trigger in the builder voice Plain voice and clean markdown (dropped the raw <ul>/<div> lists). Kept all substance: simple intervals, cron examples, timezone, deploy-tied activation, the 100-failure auto-disable, and FAQ. Added pageType. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(triggers): refocus Webhook trigger on the generic (native) trigger Rewrote in the builder voice and separated out the integration content: the page now documents the generic Webhook trigger (URL, Input Format, auth, custom response, outputs, dedup/rate-limit/deploy/no-auto-disable). The "trigger mode for service blocks" section is reduced to a short pointer + the demo video, and the long supported-services catalog and vague use-case bullets are dropped in favor of the Triggers index. Fixed the title (Webhook) and added pageType. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(triggers): builder-voice glow-up for RSS Light pass: added pageType + description, tightened the intro, and presented the output fields as an <rss.*> outputs table. Kept the polling config, use cases, the published-after-save callout, and the FAQ (poll cadence, dedup, 25-item cap, auto-disable, Atom support). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(triggers): rewrite Table trigger off the auto-generated card Replaced the BlockInfoCard/'provides 1 trigger' auto-gen format with a real builder-voice page: a spec-driven BlockPreview hero (added a 'table' spec), plain-language Configuration (table, event type, watch columns, include headers), and a full <table.*> outputs table. pageType: reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(triggers): frame the index around native triggers + separate the catalog Reframed "generic" as native (no connected account) and promoted RSS and Table into the native set alongside Start/Schedule/Webhook — cards, comparison table, and integration paragraph updated to match. In the sidebar, grouped the five native triggers under a "Native triggers" header and divided the ~44 service triggers under "Integration triggers" (nav-only — no files moved, URLs stable; the move to integrations/ is a later, separate change). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: promote Core Blocks + Core Triggers into the Workflows area Restructured the Documentation sidebar (meta-only — no files moved, URLs stable): after Deployment, the 16 core block pages now live under a "Core Blocks" section and the 5 native trigger pages under "Core Triggers", instead of buried in the bottom Reference catalog. Removed the now-redundant blocks tree from Reference, and retitled the Reference triggers tree "Integration triggers" so it holds just the service catalog (the native ones are promoted up top). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: merge block/trigger overviews into the Workflows overview; Core accordions Restructured the sidebar and overview hub (meta + content only, no integration files moved): - Folded the /blocks and /triggers overview pages into /workflows: the overview now carries the core-block catalog (do work / direct flow / shape run), the Integrations-and-triggers families framing, the native + integration trigger framing, the trigger comparison, manual-run priority, and email-polling groups. Deleted blocks/index.mdx and triggers/index.mdx as redundant. - Promoted the 16 core blocks into a "Core Blocks" folder accordion and the native triggers into a "Core Triggers" accordion, both under Workflows after Deployment. Integration triggers stay inside Core Triggers under a labeled divider, temporary until they move to integrations/<service> (tabs) later. - Repointed every /blocks and /triggers index link to the /workflows#blocks and /workflows#triggers sections. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: split integration triggers into their own Reference accordion Core Triggers is now the 5 native triggers only. Moved the 43 service triggers out of triggers/ into a new integration-triggers/ folder, surfaced as an "Integration triggers" accordion under Reference (an accordion must be its own folder in Fumadocs). In Workflows, Core Triggers now sits before Core Blocks. URLs: /triggers/<service> -> /integration-triggers/<service> (native /triggers/* unchanged); the integrations/<service> tabbed-page migration remains the later step. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(workflows): trim the overview back to an introduction It had drifted from a concept intro into a catalog. Kept the spine (the four parts with their previews, how-it-runs, workflows-in-context) and compressed the merged-in material: the full 16-block enumeration becomes a three-kind taxonomy with examples, the trigger section a short native/integration framing. Cut the anxious in-between — manual-run trigger priority, the niche email-polling-groups feature (belongs on the Gmail/Outlook trigger pages), the redundant block-def line, the Start-outputs callout half, the connections video, and the catalog-y FAQ items. Dropped the unused Video import. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: relocate email-polling + trigger-priority out of the overview Moved the two bits cut from the workflows overview to durable, generator-safe homes: email-polling groups -> the Integrations (connecting accounts) page; manual-run trigger priority -> the Start trigger page. Also added 'table' to the generator's HANDWRITTEN_TRIGGER_DOCS / SKIP_TRIGGER_PROVIDERS so the hand-written Table trigger page is no longer overwritten by generate-docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(docs-gen): emit per-service integration pages (actions + Trigger section) Rewrites the generator to output one page per service under integrations/ instead of split tools/ + triggers/. Block pass writes the service's actions; trigger pass appends a '## Triggers' section (badged) to the same page, or writes a standalone page for trigger-only services. Meta is written after both passes; hand-written integration pages are preserved; docsUrl repointed to /integrations. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(docs): unify tools + triggers into per-service /integrations pages Encodes the ontology "everything is a block; some blocks are triggers." The generator now emits one page per service under integrations/ — the service's Actions plus, when it has one, a Triggers section on the same page — replacing the split tools/<service> + triggers/<service>. No "Tools" terminology. - generate-docs.ts: output to integrations/, merge trigger sections into each service page (standalone for trigger-only services), Actions heading, table block now generated, docsUrl -> /integrations, hand-written pages preserved. - Nuked tools/ (213) and the interim integration-triggers/ (43); moved the custom-tools guide to building-agents/; knowledge/memory/file/table links and meta repointed to /integrations. - Sidebar: integrations catalog now under Reference (was tools); removed the Workspaces integrations entry and the integration-triggers tree. - block-icons: wait uses lucide Clock (the generated icons.tsx no longer carries a hand-added WaitIcon). Landing integrations data regenerated. No redirects (fresh start). Native Core Blocks/Core Triggers unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(docs): recover the hand-written manual-content intros on integration pages The tools->integrations relocation generated fresh pages, so the generator never saw the old tools/<service>.mdx to preserve its {/* MANUAL-CONTENT */} sections — 198 curated intros (AgentMail, etc.) were dropped. Reseeded each integrations page from the pre-move tools page in git, re-ran the generator (which now merges the manual intro into the new Actions/Triggers format), and repointed /tools/ links inside the recovered prose. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(scripts): rewrite the generator README for the integrations model Brings scripts/README.md current: integration pages are derived from the apps/sim block/tool/trigger registry (canonical-sources map), the golden rule not to hand-edit generated pages, the MANUAL-CONTENT escape hatch, which pages are hand-written/skipped, and the icons.tsx-overwrite gotcha. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: regenerate integration docs from staging-synced apps/sim After merging staging, regenerated so the integration pages reflect current source: correct block colors/configs (e.g. Gmail #FFFFFF), the new integrations (sendblue, millionverifier, neverbounce, zerobounce), and staging's icon set. Pages for integrations staging hid are removed; manual-content intros preserved. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(docs-gen): don't let stale-doc cleanup delete hand-written integration pages Staging's cleanupStaleToolDocs removes any integrations/*.mdx that isn't a visible tools block — it only guarded `index`, so it deleted the hand-written google/atlassian service-account pages. Now guards all HANDWRITTEN_INTEGRATION_DOCS. Restored the two pages, and repointed /integrations/file links to /files (staging hides the file block, so it has no integration page). Note: staging recategorized a2a/mysql/postgresql tools -> 'blocks' (and hid file), so they correctly drop out of the integration catalog and are currently undocumented — an IA decision to revisit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(docs-gen): stop cleanup/writer filter mismatch from eating manual content Comprehensive-review findings, all generator-consistency bugs: - cleanup used staging's isIntegrationBlock while the writer kept the legacy filter, so integrations/{knowledge,memory,table}.mdx were deleted then regenerated without their manual intros every run. Both now honor a shared NATIVE_RESOURCE_BLOCK_TYPES set; intros reseeded. - Trigger-only services (imap, circleback; category 'triggers') were likewise deleted each run; the canonical set now includes visible trigger-category blocks, the standalone writer preserves manual content, and their intros are reseeded. - Mapped jsm -> jira_service_management, so JSM triggers merge into the JSM integration page instead of an orphan jsm.mdx (removed). - Repointed lingering bare /tools links to /integrations; added missing pageType to integrations/index and building-agents/custom-tools. Double-regen is now churn-free (idempotent) with all manual content intact. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(docs): recover staging's enriched Table doc + never drop manual content The merge resolution deleted staging's relocated blocks/table.mdx, which carried substantial enrichment our integrations/table.mdx (reseeded from the older tools/ version) lacked: Creating Tables (column types/constraints), Filter Operators, Combining Filters, Sort Specification, Built-in Columns, Limits, and Notes. Recomposed integrations/table.mdx with that content — Creating Tables inside the intro manual section, the reference tail in a notes manual section. Generator fix uncovered en route: a manual section whose insertion anchor is missing in the generated markdown (e.g. notes with no "## Notes" heading) was silently dropped on regen. Unplaceable sections now append at the end instead — manual content is never lost. Verified idempotent across double regeneration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(workspaces): de-philosophize the fundamentals prose Rewrote in the plain register of the workflows overview: 'draws the boundary for access' / 'Nothing crosses the boundary' / 'follow the same edge' become direct statements (only members can access it; a workflow in one workspace cannot read a table in another). '## The boundary' is now '## Access and isolation'. All substance kept: every resource type, permission levels, personal/organization/grandfathered kinds, deployments callout, VISUAL markers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(docs): restore #blocks and #triggers anchors on the workflows overview The editorial trim renamed '## Blocks' -> '## Kinds of blocks' and '## Triggers' -> '## How a workflow starts', silently breaking the ten /workflows#blocks and /workflows#triggers anchor links pointed there when the old index pages were folded in. Pinned the original ids with explicit heading anchors. Found by the comparative prose review. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: restore the genuinely useful reference bits the rewrite dropped From the comparative prose review, restored in guidance register (no spec dumps): temperature tiers on Agent (low/middle/high with ranges), loop/parallel iteration references in the variables syntax-at-a-glance table, and a short "Test it" section on the Webhook trigger (curl + check the run in Logs). The fourth flagged loss (tag-resolver mechanics on connections) turned out to be already covered — name normalization, case-sensitive paths, missing-output behavior, and value formatting are all on the page; only the internal resolver precedence chain was dropped, deliberately. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): rework the Agent intro — encyclopedia register Replaced the flat opening with a denser, factual one (no metaphor): what the block does, and its centrality stated as fact — 'Most workflows are built around one or more Agent blocks.' The agent-vs-Agent-block disambiguation moves from an info callout into a second paragraph on the block's role in building agents. Dropped the now-unused Callout import. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(integrations): add the HubSpot setup guide for the Marketplace listing Addresses HubSpot Marketplace review item A1: a public, HubSpot-specific setup guide following their template — what the app does, install + connect through the current flow (sidebar Integrations page -> HubSpot -> Add to Sim -> connect dialog -> HubSpot OAuth), with real screenshots of each step and a placeholder for the scope-approval shot; configure in a workflow (one-click skills/templates + the HubSpot block + trigger mode), use, disconnect (with data consequences), uninstall from the HubSpot side, troubleshooting. Capability wording is by CRM object rather than scope enumeration, so it stays accurate after the A2 scope trim. Lives at /integrations/hubspot-setup, guarded as hand-written, cross-linked from the HubSpot reference page's intro. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(integrations): rewrite the Integrations guide for the sidebar flow Integrations moved out of Settings to a top-level sidebar page. Rewrote the guide to the current journey: the Integrations page (Connected/Featured/search), service pages with one-click skills and templates, + Add to Sim -> connect dialog (display name + permissions) -> provider OAuth. Replaced the four Settings-era screenshots with current captures (connect dialog illustrated via HubSpot); block-side screenshots (account selector, manual credential ID) kept; one VISUAL marker for the connection detail view pending a fresh capture. Members/roles, credential-ID, reconnect/disconnect, email polling, and FAQ substance unchanged apart from navigation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: move Building agents directly after Workflows in the sidebar The agent-building journey follows straight from workflows (blocks, triggers, deployment) rather than after the tour of every resource type. Tables/Files/ Knowledge Bases/Logs now follow it. Meta-only reorder. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: fill the visual slots coverable by existing components Six VISUAL markers filled with no new captures needed: - building-agents overview: rendered the minimal lead-scoring agent (Start -> Agent with tool chips -> Response, Agent highlighted) as a WorkflowPreview (BUILD_AGENT_WORKFLOW) - files guide: the read -> summarize -> write chain as a WorkflowPreview (FILE_SUMMARY_WORKFLOW) - tables guide: the query -> classify -> write-back roundtrip as a WorkflowPreview (TABLE_ROUNDTRIP_WORKFLOW) - choosing guide: the six-kind comparison grid as a markdown table - knowledgebase guide: the Knowledge block's output as an OutputBundle - workspace fundamentals: removed a duplicate nesting-diagram marker 42 -> 39 VISUAL markers remaining (screenshots + designed diagrams). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(components): run-inspector OutputBundle + lightbox with block inspector Two visual-component upgrades, both mirroring the real app: - OutputBundle is now a miniature of the run inspector: a Logs column (block rows with icon chips and durations, source selected) beside the Output panel's typed tree — keys with the app's type-badge semantics (string green, number blue, object gray, array purple, boolean orange), chevrons, indent guides, primitive values. Styling lifted from the terminal's structured-output. Dropped the "Read one value by name" footer (the prose teaches the tag). The three usages (data-flow, tables, knowledgebase) get real typed trees; data-flow's stale purple/gpt-4o example corrected en route. - WorkflowPreview gains a lightbox + read-only block inspector: clicking a block (or the expand control) opens a 92vw/86vh overlay with zoom and pan, and a right-hand inspector panel showing the selected block's full configuration — canvas rows truncate, the inspector doesn't. Fields render as app-style controls (dropdown/textarea/input by heuristic) with dashed dividers, tool chips, and a Connections footer computed from the edges. Selection rings without dimming (new selectedBlock option in workflow-data). Esc/backdrop closes; body scroll locks while open. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: regenerate after staging merge — AppConfig joins integrations/ Staging's new AWS AppConfig integration (#4928) generated its docs into the old tools/ layout; re-homed to integrations/appconfig.mdx (Actions heading, meta entry) via the generator. tools/ stays deleted. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: redirect the retired tools/ and trigger URLs to integrations/ Revises the earlier fresh-start call: /tools/* are ~200 live, indexed URLs referenced by deployed app versions' docsLink fields and marketplace listings, so dropping them cold would 404 from the live product. next.config now 308s: - /tools -> /integrations, /tools/:slug -> /integrations/:slug (custom-tools -> building-agents/custom-tools first) - old /triggers/<service> -> /integrations/<service>, enumerated so the native trigger pages keep resolving; provider-slug mappings for jsm and the hyphenated Google/Microsoft slugs - /blocks and /triggers index URLs -> the workflows overview anchors Verified every class + native passthroughs against the dev server. Spec updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(getting-started): rewrite — current UI, cut the post-tutorial padding The last old-guard page. Accuracy: Agent config now uses Messages (System/User message) instead of the removed System Prompt/User Prompt fields, the default model instead of GPT-4o, the banned 'no-code' phrasing is gone, the deploy card points at /deployment, and frontmatter gets description + pageType. Weight: cut the 'What You've Built' checklist, the 'Key Concepts You Learned' re-teach section, the duplicate 'Resources' links, the Start-block hand-holding, and ten dead icon imports; tightened every step preamble. 203 -> 113 lines with the full 5-step tutorial, videos, and FAQ intact. (Videos still show the old UI until the re-recording pass.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: de-fluff the Tier-1 heavy pages (logging, mcp, passing-files, permissions) From the exhaustive fluff audit, keeping all substance: - logging: merged the duplicated Console/Logs-page structure, snapshot concept stated once instead of three times, cut the generic Best Practices, trivial tab walkthrough condensed. Frontmatter added. - mcp: intro + "What is MCP?" generic bullets folded into two sentences, cut the Common Use Cases catalog and the verify-your-config Troubleshooting checklists, merged the twice-stated Refresh behavior, security kept as one real warning. - passing-files: marketing opener replaced with a factual lead, fixed the stale retired-Vision-block reference (now Agent with a vision model), dropped the FAQ item that restated the block catalog verbatim. - permissions: heading-restating intro replaced with the two-layer model, cut the three "Perfect for: stakeholders..." persona lines and the generic Best Practices section, dropped the FAQ restating the limits table. - connectors: audit over-flagged it — the categorized support matrix, API-key table, and config examples are genuine reference; frontmatter only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: tier-2 fluff trims (costs, enterprise, mailer, skills) Conservative sweep from the audit, unambiguous cuts only: the costs CYA opener and formula restatement, the enterprise marketing intro (now a functional summary), mailer's restated convenience line and chat-upload comparison, and skills' third restatement of progressive disclosure. Audit flags screened out as misfires: mothership/tasks (immediate-vs-scheduled are two facts, not a duplicate), self-hosting telemetry (real sizing data), and the recently approved credential/HITL/workflow-block/trigger pages. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(skills): update to the Skills tab on the Integrations page + document import Skills moved again — they now live on the Integrations page's Skills tab in the workspace sidebar (the doc said "Open the Skills page"). Updated the create flow (+ Add to Sim -> Add Skill dialog) with fresh screenshots of the tab and both dialog tabs, and documented the previously-missing Import flow: upload a .md with YAML frontmatter or a .zip containing SKILL.md, fetch from a GitHub URL, or paste SKILL.md content (verified against the import route/component; name 64 / description 1024 limits verified against the contract). Noted the curated skills suggested on integration pages, cross-linked the Skills tab from the Integrations guide, and refreshed the location FAQ. Mechanics (progressive disclosure, load_skill, agent-block attachment) unchanged and still accurate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(building-agents): render the lead-scorer running example on choosing The page narrated its running example through six sections without ever showing it. Authored LEAD_SCORER_WORKFLOW (Start -> Enrich workflow-as-tool -> Function reshape -> Agent with Search/Send Email/CRM tool chips -> Google Sheets append) and rendered it after the intro, with highlightBlock re-renders in the three sections that map to a node (deterministic block -> the Sheets append, agent tool -> the Agent, workflow-as-tool -> Enrich) — the same pattern as the workflows overview. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(tables): rewrite workflow columns around the real lead-scoring example Rebuilt the page on the ai_startup_customers screenshots instead of captioning them onto the old hypothetical: one running example throughout — Company Domain fills domain, Company Info reads it into employee_count/description, Lead Score Enrichment writes lead_score/priority/score_reasoning. Every section now describes the actual UI: the grid with group headers, per-row run buttons, and the 21-running toolbar; the Configure workflow panel (picker, column inputs, output selection, Auto-run, Run after); the Company Info input/output mapping; Not found cells explained where the screenshot shows them; the cascade section describes the example itself. All placeholder markers on the page resolved. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: regenerate after staging merge — Slack trigger update + file block re-visible Staging's mothership v0.2 (#4923) expanded the Slack trigger payload (interactivity, slash commands: event_type, command, action_id/value/actions, response_url, trigger_id, callback_id, ...) — regenerated so it lands on the unified integrations/slack page; the old-layout triggers/slack.mdx from staging's generator was dropped in the merge. The file block is visible again upstream, so integrations/file.mdx is back in the catalog. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(tables): playbook prose pass on workflow columns + restore File block links Workflow columns, against the docs-writing playbook: killed the banned 'Term — desc' bullets in the Configure list (term + verb form), restored the one universal analog (spreadsheet macro), fixed the clipped 'On,/Off,' fragments, replaced an invented <start.companyDomain> tag with the verified description, and thinned em-dashes to four page-wide with no clustering. Also repointed [File] block mentions back to /integrations/file now that the page exists again (FileV5 is visible upstream); the Files-store links stay on /files. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(tables): per-row execution inspection on workflow columns Two new captures: the cell menu (View execution, Re-run cell, row actions) and the Log Details trace for a single row's run. New 'Inspecting a row's run' section ties cell values to real, traceable runs; corrected the re-run guidance now that Re-run cell exists (the page previously said Run all rows was the only way to retry). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(workflows): drop the confusing 'order by hand' sentence 'You never set the order by hand' read wrong (wiring connections is setting it by hand), and the replacement was over-explanation. The first sentence already carries it: Sim works out the order from the connections. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(workflows): fix the over-claim about independent blocks 'Two blocks that don't depend on each other run at the same time' is wrong — independent blocks at different depths run at different times. Concurrency follows from readiness, not independence: blocks whose dependencies have all finished run together. Reworded to say that, tied to the image's two agents. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(workflows): accuracy audit of how-it-runs against the executor Verified every claim on the page against apps/sim/executor. One claim was materially false: "a failed block stops its own path but leaves independent paths running" — in the engine, an unhandled block failure sets the error flag and stops scheduling entirely (in-flight blocks finish, nothing new starts); only a connected error port routes the failure and keeps the run alive. Now says that. Two imprecisions tightened: a join waits for every feeder *that is going to run* (deactivated-branch feeders don't hold it up, per the edge-manager cascade), and Loop also repeats while a condition holds. Confirmed accurate: per-block readiness scheduling (readyQueue + race, not layers), branch-skip cascade and empty tags, the 25-hop call-chain cap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(logs): real captures on the overview + prose matched to the UI The logs-debugging overview had six visual placeholders and no visuals. Three real captures placed: the workspace Logs page as the hero (rows with status, credits, trigger, duration), Log Details' Trace tab at the blocks section (the CRM sync run's spans, with a one-line read of where the time went), and the editor's live run console at the input/output section. Prose corrected to what the UI shows: cost is in credits, failed runs are badged Error (dropped the five-state enum the list doesn't display), and the Trace tab is named. The row-anatomy marker is covered by the hero; the two designed-diagram markers (debug-loop flowchart, failed-vs-success comparison) remain. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(workflows): one reference syntax, named sources — untangle variables vs connection tags An exhaustive sweep of "connection tag" found the docs asserting both that a workflow variable is a connection tag (response.mdx used it as the umbrella for all angle-bracket references) and that it isn't (variables.mdx). Ruled the narrow definition canonical — a connection tag reads a block's output; the name follows the connection — and restructured around the real model: - variables.mdx: new "One syntax, named sources" section states that everything in angle brackets is one mechanism whose first segment names the source, with the load-bearing fact stated plainly: `variable` is literal, a connection tag starts with the block's own name. The syntax table drops the redundant dot-notation row, gets one row per source, and is ordered by resolution precedence with the order explained beneath it (absorbing the old Name conflicts section). The credentials pointer folds into the env-var section; trimmed the "never appears in outputs" overclaim. - response.mdx: no longer calls a workflow variable a connection tag. - connections.mdx: the owner page closes the loop — same syntax also reads variables and loop/parallel context; a connection tag is the block-output case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(workflows): verify the reference model against the resolver; fix one imprecision Checked every claim in the new 'One syntax, named sources' section against apps/sim/executor/variables: resolver chain order is Loop -> Parallel -> WorkflowVariables -> Env -> Block (matches the table); 'variable'/'loop'/ 'parallel' are literal prefixes (REFERENCE.PREFIX); block names normalize via toLowerCase + strip spaces; an unmatched reference is genuinely left in place (resolver returns undefined -> the replacer emits the raw match). One claim tightened: {{KEY}} is a different syntax and can never collide with angle-bracket references, so the precedence sentence now scopes collisions to the angle-bracket sources with a concrete example (a block named 'variable'). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(building-agents): workflow-as-tool is agent-decided, not the Workflow block The choosing page defined workflow-as-tool as the Workflow block (path-decided), contradicting its own name and the comparison table's premise. Verified against the product: workflow_executor is an agent tool — you pick the workflow in the Agent block's tool list, the model decides when to call it and supplies the inputMapping (user-or-llm), inputs arrive at the child's Start trigger. Rewritten agent-first: the section defines it as a workflow handed to an agent as one callable tool, the lead scorer gains a Deep Enrich workflow tool chip on the agent (diagram updated), and the deterministic Workflow block becomes the explicit contrast in a callout — same child workflow, the difference is who decides, mirroring the block/agent-tool contrast. Table row corrected to "The agent"; the summary paragraph follows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: theme-aware previews + enrichments vs workflow groups split Light-mode support for every preview component (WorkflowPreview canvas, nodes, containers, edges, lightbox, BlockPreview, OutputBundle, BlockInspector): a wp-scope token block in the docs global stylesheet whose values mirror the OG repository's globals.css in both modes (surfaces, borders, --workflow-edge, text tiers, the --badge-* type-badge palette). Every hardcoded hex swapped to a --wp-* var; brand colors, selection blue, and error red stay literal. tables/workflow-columns: separated the two group kinds per the contract's workflowGroupType enum ('manual' | 'enrichment'). New "Two kinds of groups" section opens with the + New column menu capture (Enrichments above the types, Workflow below); Enrichments documented from the code-defined registry (company domain, company info, email verification, phone number, work email) including the provider-cascade behavior that produces Not found cells; the Company Info panel capture is now correctly labeled as an enrichment config; workflow groups keep the Configure workflow panel. Shared machinery generalized under "How groups run"; the cascade section names which stage is which kind; the two portrait screenshots render smaller. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(tables): don't enumerate the enrichment catalog; don't assert a group's kind Two corrections on workflow columns: the prose no longer lists the enrichment catalog (growable, not procedurally tracked — it now describes the category and points at the Enrichments panel; the provider-cascade/Not-found explanation stays, it's behavior not catalog), and the page no longer asserts which kind the example's Company Domain / Company Info groups are (Company Info may be a user-built workflow, not the built-in). The input/output bindings capture moved to "How groups run" as the kind-agnostic illustration; only Lead Score — whose panel shows the workflow picker — is named as a workflow group. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(components): per-branch source handles — conditions and routers finally branch WorkflowPreview's node only ever had one header source handle, so every condition/router example fanned both edges out of a single point and never showed the if/else rows the real canvas (and the BlockPreview hero specs) render. PreviewBlock now supports `branches` (each rendered as a row with its own right-edge source handle, id `branch-<id>`) and `showError` (red error handle), mirroring the executor's per-branch condition-true/condition-false and router-<route> handle model. A block with branches emits from them, not the header. Every affected example rewired (13 workflows): the three condition examples, status-per-branch, credential routing, and the webhook-trigger check route their edges through branch-if/branch-else with the expression on the If row and an explicit else; the three router examples list their actual routes as branch rows (Sales/Support/Billing, Product/Bug report, Enterprise/Self-serve); the terminal gates (variables retry, evaluator gate, the three guardrails gates) show dangling if/else branch rows like the canvas does. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(components): inspector shows branch rows Moving condition expressions from rows into branches emptied the lightbox inspector for condition/router blocks — it only mapped rows to fields. Branches now map too: each branch renders as a field (If with its expression as code, else as an empty control, router routes by name). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(components): branch handle ids match the app's workflow representation Verified against the source after the branch-handles work: the canvas emits condition-${cond.id} handles per condition row (workflow-block.tsx) and Router V2 uses router-${routeId} port handles, and edges carry those ids as sourceHandle — the docs' invented branch- prefix was a gratuitous divergence that the planned fromWorkflowState() adapter would have had to translate. The node now uses the authored branch id as the handle id directly, and every example authors ids in the app's own scheme (condition-if/condition-else, router-<route>), so example edges now match real workflow edges verbatim. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: agent skills mint /integrations/ docs links and describe the new output The add-integration/add-block/validate-integration skills — what Claude Code follows when integrations land on staging — still taught the old layout: docsLink templates pointing at docs.sim.ai/tools/{service} and 'generates tools/{service}.mdx'. Updated so that once this PR merges, the instructions on staging produce the new way by themselves: /integrations/ docsLinks, the per-service page description, and the don't-hand-edit/manual-content pointer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(workflows): execution semantics, not simultaneity The concurrency section drifted into 'run at the same time' framing across two accuracy passes — but the semantics are non-blocking execution: a block starts the moment its dependencies finish and waits on nothing else. Section retitled 'Blocks run as soon as they can', the rule stated in two plain sentences, the duplicated pre-image example narration gone (the post-image caption carries it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(workflows): errors are execution semantics — own section on how-it-runs Failure behavior was buried inside 'Watching a run' (the live-UI section). Now a first-class 'When a block fails' section in the execution story: an error fails the run (in-flight blocks finish, nothing new starts) unless the block's error port is connected, in which case the run follows the error path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: data-driven additions from the platform-metrics read Three targeted edits from the sim-internals analysis, each carrying an inline {/* why */} provenance comment so future editorial passes know the data behind it: - workflows/how-it-runs gains "How long a run can take" — run timeouts are the only hard-error class provable at scale (2,415 five-minute timeouts in 14 days); limits verified in lib/core/execution-limits/types.ts (5 min free / 50 min paid sync, 90 min async, env-overridable). - getting-started gains an "if the run doesn't go green" callout at the Test step — the largest funnel drop is created-workflow -> first-successful-run (92% -> 49%), and this is the stall point. - function/api Best Practices: the existing error-path bullets get a guard comment (<1% of deployed workflows connect an error port — under-adopted, not under-needed) instead of duplicate bullets. - visuals manifest: capture priority reordered by integration adoption (Sheets, Gmail, Telegram, WhatsApp, ...). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: regenerate after staging merge (integration validation batch + Gong tools) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: rename Building agents -> Agents; URLs match the settled IA The section's pages now live where the sidebar says they do: building-agents/ -> agents/, and the stray top-level /mcp and /skills fold in as /agents/mcp and /agents/skills (they were always part of the agents story — the URLs predated the IA settling). Sidebar section header is now "Agents", link labels updated, and every old URL 308s: /building-agents(/*) -> /agents(/*), /mcp, /skills, plus the existing capabilities/ and tools/custom-tools redirect destinations retargeted. Verified: all five new pages render and every old-URL class redirects correctly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(workflows): connections gets its video, an FAQ, and accurate output examples The reorg dropped two things from the old tags page that belonged on the connections reference: the connections.mp4 walkthrough (restored after the intro) and the FAQ (rebuilt in the robust JSX form — resolver order, name normalization, env-var syntax pointer, didn't-run behavior, array indexing, Function-block formatting; answers aligned with the since-verified resolver facts, including unmatched-references-left-in-place). Editorial/accuracy pass on the output-shape tabs while in there: stale gpt-4o and gpt-5 examples now claude-sonnet-4-6, the Agent tokens shape corrected to the verified { input, output, total } (the page contradicted blocks/agent), and the dubious cost: [] line dropped — the example now matches the real run inspector. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: regenerate after staging merge — sim trigger, enrichment + logs blocks, re-shown DB integrations Staging's #4941 added the Sim workspace-event trigger (hand-written page adopted into Core Triggers), the Enrichment and Logs blocks (category 'blocks' — added to NATIVE_RESOURCE_BLOCK_TYPES so they live in the integrations catalog like table/knowledge/memory), and re-categorized mysql/postgresql/sftp/smtp/ssh back to visible tools (their pages return to the catalog). Generator sets merged as the union of both sides (sim in HANDWRITTEN_TRIGGER_DOCS + SKIP_TRIGGER_PROVIDERS, enrichment in the icon allowlist). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: regenerate after staging merge (CodePipeline); suppress sim trigger from catalog The native Sim workspace-event trigger is documented at triggers/sim — the block writer no longer emits an integrations page for it (skip + canonical-set exclusion). CodePipeline (#4945) lands in the catalog in the Actions format. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(blocks): cross-link the Memory block from the Agent memory section Final loss audit found the old page's pointer from built-in agent memory to the standalone Memory block had been dropped; one line restores it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: URLs now mirror the sidebar — sections own their pages Every page lives at a path matching its meta.json section, done now while none of these URLs are publicly live (the last free window before merge): - Workflows owns its accordions: /blocks/* -> /workflows/blocks/*, /triggers/{start,schedule,webhook,rss,table,sim} -> /workflows/triggers/*, /deployment/* -> /workflows/deployment/* - Mothership owns Mailer: /mailer -> /mothership/mailer - Workspaces & Access folds into Platform, sequenced concept-first with the reference tail last: /platform/{workspaces,organization,permissions, credentials,costs}, then platform/self-hosting/*, platform/enterprise/* (from /workspaces/fundamentals+organization, /permissions/roles-and- permissions, /credentials, /costs, /self-hosting/*, /enterprise/*) All internal links swept (0 broken in a full-tree resolver sweep), root meta.json repointed, and every previously-live URL 308s to its new home — including retargeted destinations of existing redirects so chains stay single-hop (verified: /execution/chat reaches /workflows/deployment/chat in one hop), and the native-trigger rule ordered after the enumerated integration-trigger redirects so /triggers/gmail still reaches /integrations/gmail. Production build passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: untrack .plans/ (local agent planning files) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(preview): tool chips use the EMCN ChipTag chrome The canvas previews' tool chips were ad-hoc (5px radius, header surface, plain border). The app's canonical chip chrome is the ChipTag family: 20px tall, rounded-md, px-1, gap-1.5, --surface-5 light / --surface-4 dark with an inset --border-1 ring and --text-body label. Mirrored those values into --wp-chip-* tokens (both modes) and restyled the chip; the integration's brand-color icon square stays, sized to the chip. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(blocks): one-time shift of all docsLinks to the new docs URLs Block definitions are the patterns coding agents copy from, so redirects alone leave new blocks minting dead conventions. Every docs.sim.ai link in apps/sim now points at the final URL scheme: /tools/<slug> -> /integrations/<slug> (433 links), /blocks/<core> -> /workflows/blocks/<core> (knowledge/enrichment/ logs -> /integrations/*), native /triggers/* -> /workflows/triggers/*, /mcp -> /agents/mcp, /self-hosting + /enterprise -> /platform/*, plus the llms.txt listings and the blocks.test.ts assertions. Verified every rewritten target against the docs tree: all resolve except ten hidden blocks (vision, spotify, thinking, tts...) and a2a whose links were already dead pre-reorg — no regressions introduced. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: ignore .plans/ (local agent planning files) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(files): align every File-block claim with the shipped file_v5 block Accuracy audit against apps/sim/blocks/blocks/file.ts (FileV5Block, the visible block) and tools/file/*: - The block has FIVE operations, not four — Get Content was missing entirely. - Read outputs file objects only; the page claimed it also returned extracted text. Text comes from Get Content (contents, per file) or Fetch (combinedContent) — table, prose, and the Fetch callout corrected. - Functions CAN read files: sim.files.readText/readBase64 exist in the sandbox (isolated-vm-worker.cjs), so "doesn't reach into workspace storage" is gone; the section now teaches Get Content text or sim.files on the file object. - Workspace file IDs are wf_<shortId> (workspace-file-manager.ts:511), not f_. - Stale "such as Claude or GPT-4o" vision parenthetical dropped. - "File block reference" card pointed at /files (the section overview); now /integrations/file. - FILE_SUMMARY example agent consumed <file.combinedContent>, which Read never produces — now binds the file object to the Files input. - passing-files.mdx: combinedContent scoped to Fetch, contents documented. Verified intact: Write's numeric-suffix collision behavior, Fetch's auth headers, Append-by-name, and the file-object shape. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: keyboard-shortcuts audited against the command registry; cut legacy workspace detail Every binding verified against commands-utils.ts (the global registry), workflow.tsx, and table-grid.tsx. Three fixes: tables Mod+A (select all rows) doesn't exist — the real bindings are Shift+Space (select row, was misworded as a toggle) and the undocumented Mod+Space (select column); the global Mod+Shift+A row conflated two commands — add-agent (Mod+Shift+A) and add-workflow (Mod+Shift+P) are separate. All 29 other documented shortcuts confirmed accurate, including tables clipboard (native copy/cut/paste events) and Mod+Y redo (tables only — correctly absent from the workflow editor section). Also drops the grandfathered_shared workspace paragraph — internal billing taxonomy, not something a reader can act on. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: apply Theodore's accuracy feedback - getting-started: workflow creation is the + button next to Workflows in the sidebar (no "New Workflow" button exists); Exa/Linkup no longer need user-supplied API keys on hosted Sim (apiKey is hideWhenHosted in the Exa block) — step and FAQ updated. - workflows overview: chat and API are entry points of the Start trigger, not separate triggers — the "swap in a chat/API trigger" sentence now matches triggers/start's own model. - variables: names cannot contain periods — the resolver reads everything after the first dot as a path into the value (executor/variables/resolvers/ workflow.ts splits on dots) — constraint now stated where name normalization is taught. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: Python sandbox package list (verified) + agent/agents cross-linking Function block: the Python callout's "common packages like matplotlib" becomes the actual package list, grouped by use. Sources verified 2026-06-10 and cited in an inline provenance comment: E2B's code-interpreter template requirements (the base Sim's mothership-shell template builds from) plus Sim's three pip additions (awscli/yq/csvkit, per the copilot repo's template.ts via sim-internals). Versions omitted so the list doesn't rot on routine bumps. Agent surfaces deduplicated by direction: blocks/agent's Tools section now links custom tools and MCP and points at the Agents concept page for tool sourcing; agents/index drops its duplicated Auto/Force/None enumeration in favor of the block reference, which owns config mechanics. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1ff445ae80 |
feat(codepipeline): add AWS CodePipeline integration with tools and block (#4945)
* feat(codepipeline): add AWS CodePipeline integration with tools and block * fix(codepipeline): address review feedback on input coercion and error statuses * chore(hooks): restore use-inline-rename onSave type accidentally swept into previous commit |
||
|
|
3cedac8e82 |
fix(security): authz, IDOR, and abuse-prevention fixes (#4944)
* fix(knowledge): require write access for batch chunk operations The PATCH /api/knowledge/[id]/documents/[documentId]/chunks handler performs enable/disable/delete operations but authorized callers with only read-level access (checkDocumentAccess). This let read-only workspace members destroy or disable indexed chunks. Switch to checkDocumentWriteAccess (write/admin required), matching the sibling POST/PUT/DELETE chunk mutation endpoints. * fix(env): restrict decrypted workspace env vars to secret admins GET /api/workspaces/:id/environment returned decrypted workspace environment variables to any member, including read-only collaborators, leaking API tokens, database URLs, and other secrets. Mask workspace variable values for non-admin viewers while preserving the variable names, so editor autocomplete and conflict detection keep working. A value is revealed only when the caller is a credential admin of that key, or — for legacy keys with no per-secret ACL — holds workspace admin permission. This mirrors the per-key edit gating already enforced by PUT/DELETE: if you can administer a secret, you can read it. Personal variables and execution-time resolution are unchanged. * fix(files): block cross-tenant deletion via client-controlled context POST /api/files/delete trusted a client-supplied `context`, letting any authenticated user delete another tenant's file by naming an arbitrary key with `context: "og-images"`. verifyFileAccess() short-circuited the three public contexts (profile-pictures, og-images, workspace-logos) to `true` before any ownership/requireWrite check. - Derive the storage context strictly from the trusted key prefix in the delete route; reject a supplied `context` that disagrees with the key. - Gate the public-context short-circuit to reads only. Destructive ops (requireWrite) now prove ownership via verifyPublicAssetWriteAccess: workspace-logos require write/admin on the bound workspace, profile-pictures require an exact owner match, og-images always deny. Reads of public assets are unchanged. * fix(telegram): verify X-Telegram-Bot-Api-Secret-Token on inbound webhooks Telegram triggers accepted any forged update from anyone who knew the webhook URL path: verifyAuth was a no-op that always returned null, and setWebhook registered no secret_token. Generate a per-webhook secret in createSubscription, register it with Telegram as secret_token, and persist it to providerConfig. verifyAuth now fails closed — rejects when no token is configured, when the X-Telegram-Bot-Api-Secret-Token header is absent, or when it does not match via constant-time safeCompare. * fix(security): pin DNS for Agiloft directExecution and Grafana update tools The Agiloft directExecution tools (read/create/search/update/delete/lock/ saved_search/select/get_choice_line_id/remove_attachment/attachment_info) and the Grafana update_dashboard/update_alert_rule postProcess hooks issued outbound HTTP to a fully user-controlled host (instanceUrl/baseUrl) via the global fetch(), guarded only by the synchronous validateExternalUrl() — which never resolves DNS, so a hostname resolving to an internal/reserved IP passed validation (SSRF). Route all of these through the codebase's standard SSRF-safe path: - Agiloft: moved executeAgiloftRequest into utils.server.ts where the existing pinned helpers live. It now resolves+validates the instance URL once and pins every hop (login, operation, logout) to that IP via secureFetchWithPinnedIP. The 11 tool configs now import it from utils.server; URL builders stay in the client-safe utils.ts. - Grafana: the postProcess POST/PUT now uses validateUrlWithDNS + secureFetchWithPinnedIP, matching the already-pinned initial GET. This completes the Agiloft SSRF pinning started in #4639 (which covered the attach/retrieve API routes) by closing the directExecution path, and extends the same guard to the Grafana update tools. * fix(api): enforce workspace allowPersonalApiKeys policy on v1 surface The external v1 API authenticated API keys without evaluating the per-workspace allowPersonalApiKeys setting, so a personal API key could read and mutate a workspace's resources (workflows, tables, files, knowledge, logs) even when the workspace had explicitly disabled personal keys. The same control is already enforced on the workflow-execution surface. Enforce the policy in checkWorkspaceScope (covering validateWorkspaceAccess too): reject personal keys with 403 when the workspace has allowPersonalApiKeys=false. checkWorkspaceScope becomes async; all v1 route callsites updated to await it. * fix(billing): close usage-cap admission race with atomic reservation The server-side usage-limit gate read already-recorded cost, but cost is only written when an execution finishes. A burst of concurrent executions all observed the same pre-burst usage, all passed the cap, and all ran — collectively spending far past the limit before any cost landed in the ledger (free-tier abuse / hard-cap defeat). manual/chat triggers also skip rate limiting, removing the only throttle. Add an atomic check-then-reserve admission step (Redis Lua) that bounds in-flight, un-costed executions per billing entity by both a per-plan concurrency cap and remaining usage headroom, so recordedUsage + reservedSlots * estimate <= limit always holds. The slot is released at execution completion via LoggingSession (skipped on pause; TTL self-heals crashes). Runs for all trigger types, covering the previously-unthrottled manual/chat paths. Fails open when billing is disabled or Redis is unavailable, matching the rate limiter — a Redis blip can't turn into an execution outage, and the recorded-usage gate still runs. * fix(workflows): validate folderId belongs to workflow's workspace on create/update/reorder Reject a folderId that references a folder in a different workspace (or an archived/non-existent folder) before writing it to workflow.folderId. Previously create, update, and reorder only checked workspace permission on the workflow and the folder's lock status, never that the folder lived in the workflow's own workspace, allowing a dangling cross-workspace folder reference. Adds isFolderInWorkspace/assertFolderInWorkspace + FolderNotFoundError to @sim/workflow-authz (mirroring assertTargetFolderMutable in the duplicate path), enforced in performCreateWorkflow, performUpdateWorkflow, and the reorder route. Invalid folders now return 400. * fix(folders): validate parentId against workspace on create/update/reorder Folder write endpoints accepted a caller-supplied parentId and persisted it without verifying the parent existed in the same workspace, and the create and reorder paths had no cycle guard. A workspace member with write access could reparent a folder to a foreign-workspace folder, a non-existent id, or (via reorder) into a cycle, hiding the folder and its workflows from all members. - performCreateFolder: reject self-parenting and validate the parent exists in the workspace and is not archived (mirrors the duplicate route). - performUpdateFolder: add the same workspace/archived parent check alongside the existing circular-reference guard. - folders/reorder: validate every target parent against the workspace, detect cycles in the resulting parent graph (catches batch cycles), and normalize falsy parentId to null to prevent orphaning. Adds tests for cross-workspace parent rejection and batch-cycle rejection. * chore(knowledge): drop non-TSDoc inline comments from chunks route * fix(webhooks): fail closed when HMAC signing secret is not configured Inbound webhook signature verification failed open for HMAC providers (GitHub, Intercom, Jira, JSM, Confluence, Cal.com, Notion, Greenhouse, Typeform, Fireflies, Circleback): when no signing secret was stored, verifyAuth returned null and the workflow executed on a fully attacker-controlled body. Reject these deliveries with 401 instead, matching the fail-closed Stripe/WhatsApp/Vercel providers. Run provider reachability/verification handshakes (Notion verification_token, Grain/Intercom ping) ahead of auth so the pre-secret setup handshake still completes — those return a canned 200 without executing the workflow, and real event payloads fall through to fail-closed verification. Update the trigger secret-field copy to state the secret is required for deliveries to be accepted (was misleadingly marked optional). * style(files): trim verbose inline comments on delete authorization fix * fix(auth): close account-enumeration oracle on email sign-up The custom before-hook pre-check threw a distinguishing 422/USER_ALREADY_EXISTS for already-registered emails, letting an unauthenticated attacker enumerate accounts — defeating better-auth's own OWASP enumeration protection (active under requireEmailVerification). Remove the pre-check and rely on better-auth's generic duplicate-sign-up response, wiring: - onExistingUserSignUp: notify the real account owner out-of-band, mirroring the privacy-preserving forget-password flow. - customSyntheticUser: include admin (role/banned/banReason/banExpires) and Stripe (stripeCustomerId, billing-gated) user fields so the fake response shape is byte-identical to a real new-user response. Adds an ExistingAccountEmail template + 'existing-account' subject. * style(tools): drop non-TSDoc inline comments from Grafana/Agiloft SSRF tools * chore(api): trim extraneous inline comments in v1 logs/files routes Remove a redundant size annotation and two verbose multi-line materialization comments whose intent is already clear from the code. Load-bearing comments (race-condition and key-translation notes) kept. * fix(billing): exclude table-cell dispatch from admission reservation Table-cell dispatch is row-bounded, async rate-limited, and already surfaces a graceful usage state. Applying the in-flight concurrency reservation there turned its 429 into a hard cell error on a normal >15-concurrent-cell run (only 402 was handled gracefully). Skip the reservation for that surface via a new skipConcurrencyReservation option (the usage-cost cap is still enforced), and tidy the reservation comments to TSDoc. * fix(chat): rate-limit and constant-time password auth for public chats Password-protected public chat (POST /api/chat/[identifier]) had no throttling on the password check and compared with a non-constant-time !==, allowing unlimited brute-force and per-character timing leaks. - Add per-IP rate limiting (10 / 15min) to the password branch of validateChatAuth, mirroring the OTP/SSO endpoints; return 429 with Retry-After. Only explicit unlock attempts consume tokens — message sends carry no password and ride the auth cookie. - Replace password !== decrypted with safeCompare. - Fails open on rate-limiter storage errors; no availability regression. * fix(security): cap JSON request body size and gate public chat endpoint The shared parseJsonBody helper (behind parseRequest, used by nearly every contract route) read request bodies with no size limit, buffering the full body into memory before validation. The unauthenticated public deployed-chat endpoint reached this sink with no admission gate, enabling an anonymous memory-exhaustion DoS. - parseRequest/parseJsonBody now enforce a byte cap via a size-limited stream read (content-length precheck + streamed cap), returning 413. Default is API_MAX_JSON_BODY_BYTES (50 MB), overridable per route via maxBodyBytes. Decoding uses TextDecoder to match request.json() BOM handling. - Public chat POST is wrapped with the admission gate (tryAdmit) and passes an explicit CHAT_MAX_REQUEST_BYTES (20 MB) cap. - Chat body contract gains .max() bounds on input, password, conversationId, file data/name/type, and files array length. - Admin bulk workspace import opts into a higher 100 MB cap to avoid regressing large multi-workflow imports. * fix(chat): rate-limit and constant-time password auth for public chats Password-protected public chat (POST /api/chat/[identifier]) had no throttling on the password check and compared with a non-constant-time !==, allowing unlimited brute-force and per-character timing leaks. - Add per-IP rate limiting (10 / 15min) to the password branch of validateChatAuth, mirroring the OTP/SSO endpoints; return 429 with Retry-After. Only explicit unlock attempts consume tokens — message sends carry no password and ride the auth cookie. - Replace password !== decrypted with safeCompare. - Fails open on rate-limiter storage errors; no availability regression. Reinstates the fix reverted by an intervening commit. * fix(billing): never block a lone execution on usage headroom The admission reservation tapered allowed concurrency by remaining usage headroom. With under one credit of headroom left (but not yet over the cap), floor(headroom / estimate) hit zero and rejected even a single, zero-concurrency execution — stricter than the recorded-usage gate, which would have allowed that last run, and with a misleading "too many concurrent executions" message. Floor the headroom term at 1 so a lone execution is governed only by the cost gate; concurrency above the first slot still tapers with headroom. * refactor(env): document workspace env masking, drop inline comments Extract the workspace-env value masking into a TSDoc-documented maskWorkspaceEnvForViewer helper and remove the redundant inline comments from the GET handler and its test. No behavior change. * refactor(env): convert PUT/DELETE authz comments to TSDoc Move the tiered-authorization rationale for the workspace env upsert and delete handlers into TSDoc blocks and drop the inline comments. No behavior change. * fix(telegram): keep legacy webhooks working via Telegram source-IP fallback The secret-token check rejected every webhook registered before secret_token support, breaking live triggers until re-saved. Fall back to verifying the request originates from Telegram's published webhook IP ranges when no secret is configured, so existing triggers keep firing with no re-save or migration while forged updates from arbitrary hosts are still rejected. Webhooks with a registered secret continue to use strict constant-time token verification. * fix(chat): restore constant-time password auth and IP rate limit A billing commit ( |
||
|
|
6abcf82db2 |
feat(workflows): sim trigger, logs v2 block, toolbar renaming (#4941)
* feat(workflows): sim trigger, logs v2 block, toolbar renaming * fix(review): bound rule queries, canonical logs params, watched-workflow SQL scoping Code-review fixes: read the canonical workflowIds param in logs_v2 (the serializer deletes the source pair ids), aggregate failure-rate in the DB and switch rule windows to the indexed startedAt column, clamp rule config to the legacy contract bounds, push no_activity watch scoping into SQL before the LIMIT, fix the generated sim icon-map key, normalize docs wording, and drop dead exports. Co-authored-by: Cursor <cursoragent@cursor.com> * address comments * fix(review): integer rule rounding, success-gated workflow labels, display module hygiene Second-pass review fixes: round integer rule fields so fractional input never reaches SQL LIMIT, gate workflow-name readiness on a successful non-placeholder load in both editor and preview (errored loads mislabeled valid workflows as deleted), lazily read the variables store in preview rows, move the filter-field JSON preview into the shared display module and unexport its single-consumer helpers, and align >= boundary copy (failure rate, error count, cooldown window) with implementation. Co-authored-by: Cursor <cursoragent@cursor.com> * chore: sync lockfile after staging merge Co-authored-by: Cursor <cursoragent@cursor.com> * fix(workspace-events): keyset-paginate the no_activity subscription scan A fixed LIMIT 500 with no ORDER BY silently starved subscriptions beyond the cap once the global count exceeded it. The poll now pages by webhook id so every subscription is visited each cycle; pagination bounds memory, not total work. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(workspace-events): keyset-paginate the watched-workflow scan The 500-row LIMIT silently and deterministically excluded high-id workflows from no_activity coverage in watch-everything subscriptions on large workspaces. The scan now pages by workflow id, mirroring the subscription scan; per-workflow checks move into a helper so the pagination loop stays flat. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(workspace-events): skip no_activity subscriptions on the execution-completion path no_activity is poller-owned and can never fire from a completed execution, but it passed into the rule branch and cost a pointless cooldown point-read per subscription on the hottest path. Early-continue alongside the workflow_deployed guard. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(sim-trigger): note failure-based alert conditions evaluate on failed runs Co-authored-by: Cursor <cursoragent@cursor.com> * fix(blocks): recategorize Data Enrichment as a core block It's a Sim-native capability (registry enrichments over a managed provider cascade, like Search), not a third-party integration. Moves it to Core Blocks in the toolbar, out of the integrations catalog, and relocates its docs page to blocks/ with the icon-map allowlist keeping the docs card icon. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(blocks): recategorize MySQL, PostgreSQL, SFTP, SMTP, SSH as integrations External-system connectors with host/credential auth belong under Integrations, not Core Blocks — consistent with MongoDB, Redis, ClickHouse, and the other datastore integrations. They already carried integrationType and /tools docsLinks; the regenerated docs pages turn those previously-dangling links into real pages, and the blocks join the integrations catalog and icon maps. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
62c48bfd31 |
improvement(tools): validate integrations, add Gong activity tools, regenerate docs (#4937)
* improvement(tools): validate integrations, add Gong activity tools, regenerate docs * fix(servicenow): give list-attachments limit a unique subBlock id Read Records and List Attachments shared the subBlock id 'limit', so the single-value-per-id store could bleed the value across operations. Rename the new list-attachments field to attachmentLimit and map it back to the tool's limit param. * fix(servicenow): type upload-attachment response json to fix build typecheck secureFetchWithValidation's response.json() resolves to unknown under the build's stricter typecheck; cast the parsed body so data.result is accessible. * refactor(servicenow): type upload-attachment response per file-route convention Match the SharePoint/OneDrive upload pattern: import the named ServiceNowAttachment type from the tool's types, cast response.json() to it, and extract specific fields with ?? null instead of passing data.result through as an opaque unknown blob. * fix(servicenow): remove invalid 'custom' generationType from groupBy wandConfig 'custom' is not a member of the GenerationType union, breaking the build typecheck. No valid type fits a comma-separated field list, so drop the wandConfig (consistent with the block's other field-list inputs). * fix(servicenow): drop redundant hidden fileContent param from upload attachment Per project rule, visibility:'hidden' is reserved for framework-injected tokens, not user-supplied data. fileContent was a copied-over legacy fallback with no caller (the block uploads via the canonical file/UserFile path), so remove it from the tool, types, contract, and route. * fix(dub): require a link selector for bulk update links Bulk Update Links could run with only Update Data and no Link IDs or External IDs, sending Dub a request with no target links and producing a confusing API error. Guard the tool to throw a clear validation error when neither selector is provided, and clarify the block placeholder. |
||
|
|
efa4f27006 |
fix(agent): unique tool ids for multi-instance tools + icon updates (#4933)
* fix(agent): resolve canonical resource id when building unique tool ids Multi-instance agent tools (table, knowledge base, workflow) get a unique id by suffixing the resource id (e.g. table_query_rows_<tableId>). The suffix code read the canonical param key (tableId/knowledgeBaseId) directly from stored params, but selector subblocks persist their value under the subblock id (tableSelector/knowledgeBaseSelector). Tools stored in that state never got a suffix, so two of them collapsed to the same name. Resolve the canonical resource id from the source subblock first — mirroring the execution-time paramsTransform — so the unique id is derived the same way the tool actually runs. Non-destructive; no-op when the canonical key is already present. * test(agent): cover knowledge-base selector resolution for unique tool ids * improvement(icons): new 1Password icon on white bg, enlarge Prospeo and Neo4j glyphs |
||
|
+1 |
39418f9615 |
improvement(mothership): v0.2 (#4923)
* CONTRACTS * updates * Prompt caching * Fix regression * updates to prompt caching * Prompt caching trace * VFS updates * Changelog and plan * VFS update * Improvement/mothership (#4775) * ff * System role in cache * Fixes * Add dynamic user info * Improve tool search * improvement(platform): workspace UI/UX overhaul + integrations catalog Rework the workspace around the AI-workspace model: a Mothership home, a top-level Skills route, connected-credential and integration-detail pages, and a polished sidebar/settings surface. Replace the notifications store with a unified toast system (provider-level dismiss/pause, countdown ring). Integrations & catalog: - Add a BlockMeta layer (tags + catalog templates) scoped to catalog-visible integrations; every catalog integration carries >=7 grounded templates. - Rework the taxonomy: each block declares category tools|blocks|triggers. 3rd-party services are 'tools'; first-party primitives (postgres, mysql, knowledge, file, search, stt/tts, image/video generators, thinking, etc.) are 'blocks'. Versioned blocks follow the upgrade paradigm (old hidden, latest in toolbar/docs). - Generate integrations.json + tool docs canonically from block configs. Architecture & cleanup: - Consolidate block data extraction behind a single latest-version strategy (getCanonicalBlocksByCategory; version-consistent getBlockMeta). - Unify version-suffix handling in @sim/utils/string (stripVersionSuffix / isVersionedType, with tests); registry, generate-docs, tools/utils, and integrations all route through it. - Repair latent broken barrels, remove dead code, fix BlockMeta-related type errors and 5 broken docs links. Behavior-preserving for block execution and the toolbar's tool/block listing. * refactor(platform): remove forms, templates, and creators features Remove three standalone features and their supporting code: - Forms: form-deployment pages, API routes, execution path, and docs. - Templates: the template gallery (landing + workspace) and template APIs. - Creators: creator-profile routes and contracts. Add a super-user permissions module (lib/permissions/super-user) and an organizations API contract; update the audit/db/testing packages, billing, and the session/theme providers accordingly. * New doc setup * Fixes * Fixes * Logs tools * test(workflows): update archiveWorkflow update count after forms removal The forms feature was removed, dropping the form-table update from archiveWorkflow. Update the stale assertion from 8 to 7 tx.update calls. * Add finalization on error * Fixes * change dev CI to bun run db:push * Updates Please enter the commit message for your changes. Lines starting * Contrat update * improvement(nested): subagents * updates * upgrade * improvement(knowledge): polish tag filter dropdowns (#4816) * improvement(logs): object storage backed tracespans (#4787) * improvement(logs): obj storage backed tracespans * fix storage write context * fix tests * address comments * address comments * chore(db): remove migration 0219 to regenerate after staging merge Drops the 0219_robust_shard SQL, its snapshot, and the journal entry so the trace-spans/cost schema migration can be regenerated on top of the latest staging migration chain (avoids a number collision with staging's migrations). Co-authored-by: Cursor <cursoragent@cursor.com> * improvement(billing): accurate per-member usage via shared ledger helper Per-member/per-user usage in the org-member routes now adds the usage_log ledger to the currentPeriodCost baseline (which is no longer incremented), via a shared getOrgMemberLedgerByUser helper to avoid repeating the subscription→period→ledger lookup across the admin and member-facing routes. Co-authored-by: Cursor <cursoragent@cursor.com> * regen migrations * update migration * address comments * more code cleanup * incorrect type cast --------- Co-authored-by: Cursor <cursoragent@cursor.com> * improvement(providers): harden OpenAI-compatible providers + add tests (#4796) * improvement(providers): harden OpenAI-compatible providers + add tests * fix(vllm): let tool-loop errors propagate instead of returning silent partial success * fix(litellm): force tool_choice 'none' on final structured-output call The deferred final call used tool_choice 'auto', so the model could emit another tool_calls round instead of the structured answer, leaving content stale. Use 'none' (matching vLLM/Fireworks) on both the streaming and non-streaming final calls so the model must return the structured response. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(providers/ollama): drop tools from post-tool streaming call Ollama ignores tool_choice (not in its supported fields), so vLLM/Fireworks' tool_choice:'none' guard is a no-op here. Omit tools from the final streaming payload instead so the summarization turn can't emit dropped tool calls. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(litellm): spread payload into deferred final call so reasoning_effort carries over The non-streaming deferred finalPayload hand-picked fields and dropped reasoning_effort (and any future payload field), diverging from the streaming path which spreads ...payload. Spread payload here too for consistency. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(providers/ollama): restore enrichment TSDoc block Keeps parity with sibling Chat Completions providers (cerebras/mistral/xai). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(fireworks): restore TSDoc on utils helpers Restore the TSDoc blocks on supportsNativeStructuredOutputs, createReadableStreamFromOpenAIStream, and checkForForcedToolUsage — TSDoc is the codebase documentation standard and should not have been stripped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(litellm): remove inline rationale comments (codebase uses TSDoc) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(providers/ollama): drop orphaned enrichment TSDoc The block documented a function that now lives in trace-enrichment.ts, so it documents nothing in this file. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * chore(copilot): deprecate mcp server (#4797) * chore(copilot): deprecate mcp * update error codes * deprecate copilot api v1 route * feat(integrations): hosted API keys for Findymail, Prospeo, and Wiza (#4777) * feat(integrations): hosted API keys for Findymail, Prospeo, and Wiza Add hosted-key support across all credit-consuming Findymail, Prospeo, and Wiza operations so Sim provides the key when a workspace has not brought its own. Register the three BYOK providers, consolidate Wiza's two-step reveal into a single polling wiza_individual_reveal op, and hide the API key field on hosted Sim for hosted operations. * fix(integrations): harden Wiza reveal polling, soften enrichment getCost guards Address Greptile + Cursor Bugbot review on #4777: return explicit failures from the Wiza individual_reveal poller instead of throwing (thrown errors were swallowed into a false queued success), short-circuit when the initial reveal is already terminal, tolerate transient 5xx/429 during polling, and return 0 (not throw) from Findymail getCost when the contacts/employees array is absent. * chore(integrations): biome formatting after wiza merge resolution * fix(wiza): type isTerminalReveal param structurally for next build typecheck * feat(enrichments): add Findymail, Prospeo, Wiza to work-email waterfall * feat(enrichments): add Wiza + Prospeo phone reveal to phone-number waterfall * feat(enrichments): opportunistic identifiers + LinkedIn URL input across work-email & phone cascades * fix(tables): reduce column header chevron size and fix sidebar shadow bleed (#4800) * feat(slack): add install + privacy section to integration landing page (#4799) * feat(slack): add install + privacy section to integration landing page Adds a hand-authored, slug-keyed landing-content module (separate from the generated integrations.json so it survives regeneration) and renders an install walkthrough + privacy-policy link on integration pages when present. Also refreshes generated docs (data-enrichment entry, icon mappings, tool mdx). * fix(landing): render privacy section independently, align CTA analytics label * docs(landing): clarify the Slack install button is behind sign-in * refactor(landing): bake integration landing content into generated json via docs-gen Moves landing content (install walkthrough + privacy) out of a render-time augment and into the generation pipeline: generate-docs reads the pure-data content map and writes landingContent into integrations.json, so the page reads a single source (integration.landingContent). Canonical types live in integrations/data/types.ts. * improvement(enrichments): align enrichments sidebar with design system (#4801) * improvement(enrichments): align enrichments sidebar with design system * fix(enrichments): consistent close button pattern and fix url link hover * fix(misc): upgrade path change for new better-auth version, billing issue for workflow block agent usage (#4803) * fix(misc): upgrade path change for new better-auth version, double-billing for workflow block agent usage * fail loudly if stripe sub id missing * fix(copilot): seq migration (#4804) * chore(db): drop redundant idx_webhook_on_workflow_id_block_id index (#4809) Removed because (workflow_id, block_id) is a left-prefix of idx_webhook_on_workflow_id_block_id_updated_at_desc, which fully covers it. The dropped index was non-unique and enforced no constraint. * perf(copilot): read chat transcripts from copilot_messages (R+1 cutover) (#4808) * perf(copilot): read chat transcripts from copilot_messages, not JSONB Flip user-facing chat reads from the legacy copilot_chats.messages JSONB array (5.7GB, 99% TOAST) to the normalized copilot_messages table via a new loadCopilotChatMessages helper ordered by seq NULLS LAST, created_at, id — the verified canonical order. Both chat-detail getters (getAccessibleCopilotChat, getAccessibleCopilotChatWithMessages) now drop the messages column from their metadata select (no more whole-array detoast on every load) and assemble the transcript from the table after authorization. This cascades to the copilot + mothership GET endpoints and to resolveOrCreateChat's conversationHistory (the LLM payload). The normalize/effective-transcript pipeline is source-agnostic (copilot_messages.content == a JSONB array element), so transcripts are byte-identical. Dual-write and the JSONB column stay in place as the internal-logic source and fallback; removing JSONB writes is a later step. Prod integrity verified before cutover: 0 messages missing, 0 NULL-seq, 0 dup keys/seq, 0 orphans, order-parity vs JSONB = 0 mismatches. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(copilot): cover auth-deny on a found row skips the messages query Address PR review: exercise the `if (!authorized) return null` contract — when the chat row exists but authorization fails, the getter returns null and never issues the copilot_messages read. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(tables): right-align run/stop in embedded toolbar; workflow cells format like normal cells (#4806) * fix(tables): right-align run/stop in the embedded table toolbar Add a right-aligned `trailing` slot to ResourceOptionsBar and move the embedded mothership table's run/stop control into it, so Filter + Sort stay left-aligned and run/stop sits opposite on the right. No-op for the search-bearing consumers (logs, resource list), which don't pass `trailing`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(tables): workflow-output cells format values like normal cells Workflow-output columns short-circuited in resolveCellRender and rendered their value as plain text, so a sim-resource URL / external URL / JSON / date produced by a workflow never got the chip, favicon link, or typed formatting a normal cell gets. Factor value formatting into a shared `resolveValueKind` helper used by both the workflow-value branch and the plain-cell branch; the workflow branch keeps the typewriter reveal for plain streaming text via a `typewriter` flag. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(tables): detect resource/URL links on workflow output regardless of column type Workflow output columns default to `json` (columnTypeForLeaf), so routing their values through the type-based formatter (a) gated chip/URL promotion behind `column.type === 'string'` — a URL produced by a json-typed output never became a chip — and (b) JSON.stringify'd plain string values, adding quotes and losing the typewriter reveal. Detect links (sim-resource chip / favicon URL) on the value string directly for workflow outputs, falling back to the plain `value` kind; plain cells keep the type-based formatting. Addresses Greptile P2 on #4806. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(icons): repair broken integration icon rendering (#4810) * fix(icons): repair broken integration icon rendering Two distinct bugs left integration icons broken on the /integrations page (visible at 32-40px, hidden at the toolbar's 16px): 1. Corrupted SVG paths (Notion, Greptile, Granola, Calendly, Grafana, Bedrock): over-minified data dropped elliptical-arc flag digits (e.g. `A1 1 0 5.9 7` instead of `A1 1 0 0 0 5.9 7`); Granola's cubic stream was truncated. Browsers abort path parsing at the first invalid arc flag, so each rendered as a fragment or blank. Replaced with correct path data from canonical sources, preserving each icon's existing fill/gradient and bgColor. 2. Invisible glyph (Bright Data): its icon uses fill='currentColor' but bgColor was '#FFFFFF', and every surface forces text-white on the glyph - white-on-white. Changed bgColor to Bright Data's brand blue (#3d7ffc) so the white glyph reads, matching the white-glyph-on-brand-chip convention. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): restore Calendly dual-tone brand colors Addresses review feedback: the previous fix replaced the broken Calendly icon with a monochrome #006BFF path, dropping the cyan #0ae8f0 accent from the original dual-tone mark. Restored the two-tone logo (blue + cyan) using clean, valid path data, cropped to a tight square viewBox so it fills the chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge icons, fix Zoom contrast and Quiver chip - Zoom: glyph was blue-on-blue (#0B5CFF on #2D8CFF chip); switched to currentColor so it renders as a white glyph on the blue chip. - Quiver: chip bgColor #000000 -> #FFFFFF to match the icon's near-white box, and enlarged the mark slightly (viewBox crop). - Enlarged (tightened viewBox, verified no clipping): RevenueCat, Prospeo, Granola, Firecrawl, Enrich.so, and the AWS icons (RDS, DynamoDB, SQS, CloudFormation, Athena, CloudWatch, SES, Bedrock, S3). - ZoomInfo left unchanged: it is a full red rounded-square logo that already fills its frame, so a crop would clip it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): use Bright Data wordmark on white chip; repair Circleback - Bright Data: replaced the flame glyph with the official two-tone 'bright data' wordmark (provided asset), centered in a symmetric viewBox. Reverted the chip bgColor from #3d7ffc to #FFFFFF since the blue wordmark is invisible on a blue chip (the wordmark is designed for a light background). - Circleback: a minifier had rounded the pattern's image scale to scale(0), collapsing the embedded logo to zero size (invisible). Restored the correct scale (1/280 = 0.00357142857) so the C. mark renders. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(docs): sync Quiver block color card to white chip Reflects the Quiver bgColor change (#000000 -> #FFFFFF) in the docs block info card. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge AWS/Cloudflare/Dagster icons, fully white Zoom - Enlarged (tighter viewBox, render-verified, no clipping): Cloudflare, Dagster, and the red AWS icons AWS IAM, Identity Center, Secrets Manager, SES, STS. Identity Center was anomalously small (filled ~32% of its frame); the group is now sized consistently (~80% fill). - Zoom: the camera lens triangle was still #0B5CFF (blue-on-blue); switched it to currentColor so the whole camera renders white on the blue chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(wiza): consolidate individual reveal into a single operation Merges the separate Start/Get Individual Reveal operations into one Individual Reveal operation in the Wiza docs and integrations data (operationCount 5 -> 4). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): size remaining AWS icons to match the set (~80% fill) Bring RDS, DynamoDB, SQS, CloudFormation, Athena, CloudWatch and S3 up to the same ~80% fill as the AWS IAM/Identity Center/Secrets Manager/SES/STS group, so all AWS icons are visually consistent. Bedrock left as-is (already ~92% fill). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): use Bright Data flame mark, enlarge ZoomInfo - Bright Data: the full 'bright data' wordmark was illegible at chip size. Replaced with just the flame-'i' brand mark (blue #4280f6 on the white chip), centered. - ZoomInfo: cropped the viewBox toward the white 'Zi' so it's larger; the red rounded-square background still fills the chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge CrowdStrike icon The falcon mark sat small in its chip because the icon used a wide 768x500 viewBox (letterboxed in the square chip). Switched to a square viewBox centered on the mark so it fills ~80%, consistent with the other icons. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(tables): serialize schema mutations to prevent parallel column clobber (#4812) * Make workflow description nullable * fix(tables): serialize schema mutations to prevent parallel column clobber * fix(tables): load workflow outside schema lock; use DbOrTx for getTableById * fix(tables): scale idle timeout in updateColumnType to avoid aborting large type changes * fix(tables): skip stale remap types when workflowId changes concurrently * fix(tables): scale idle timeout in updateColumnConstraints for large tables * fix(wait): resume live/draft async waits and preserve cell context on chained waits (#4814) * Make workflow description nullable * fix(wait): resume live/draft async waits and preserve cell context on chained waits * improvement(knowledge): polish tag filter dropdowns * improvement(knowledge): soften filter section labels * improvement(knowledge): soften list filter labels * fix(security): harden SSO domain registration, webhook path isolation, and CSV export (#4813) * fix(security): harden KB file access, SSO domain registration, webhook path isolation, env secrets, and CSV export * fix(sso): scope domain conflict query with indexed lower(domain) filter Address PR review: avoid a full-table scan on every SSO provider registration by filtering candidate rows in SQL with lower(domain) = <normalized>, keeping the in-memory ownership check. Also tighten the normalizeSSODomain TSDoc. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: condense env route security comments Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * icons update * chore(security): tighten inline comments in CSV export and KB file authorization Condense verbose comment blocks to concise TSDoc/single-line form; no behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): validate internal serve origin in KB file authorization Replace the bypassable isInternalFileUrl substring check in resolveInternalKbKey with an origin allow-list (base URL, internal API base URL, TRUSTED_ORIGINS). A crafted external host whose path is /api/files/serve/<victim-key> no longer resolves to the victim key. Relative same-origin URLs are unaffected. * style(sso): use idiomatic sql lower() comparison for domain conflict query Match the repo's prevailing `sql`lower(col) = value`` idiom for the case-insensitive SSO domain conflict lookup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): align workspace env admin gate with hasWorkspaceAdminAccess Use the same admin check the secrets UI uses (owner, admin permission, or org-admin) so owners and org-admins are not wrongly denied their own decrypted workspace secrets, while read-only members remain restricted to names only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(sso): rely on lower(domain) match for conflict detection, drop dead in-memory recheck Address PR review: the SQL `lower(domain) = <normalized>` predicate already excludes rows that the in-memory `normalizeSSODomain(...) === domain` recheck claimed to catch, making that recheck dead/misleading code. Match on the canonical lower-cased domain and filter purely by ownership. Malformed legacy values (wildcards, schemes, ports) never match an email domain at sign-in, so excluding them is not a gap. Test DB mock now applies the lower() predicate so the casing-variant case is genuinely exercised. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): scope webhook deploy path conflict to active webhooks findConflictingWebhookPathOwner omitted the isActive filter that the runtime dispatcher (findAllWebhooksForPath) applies, so an inactive but non-archived webhook from another workflow (e.g. after undeploy or failure auto-disable) would permanently block any new deployment on that path even though it never receives deliveries. Align the guard with the runtime isActive + archivedAt filter; the earliest-owner runtime check remains the authoritative cross-tenant protection. Also trims verbose TSDoc on the webhook path-isolation helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): exclude archived workflows from webhook deploy path conflict findConflictingWebhookPathOwner now joins workflow and filters isNull(workflow.archivedAt), matching the runtime dispatcher (findAllWebhooksForPath). A webhook on an archived workflow can never receive deliveries at runtime, so it must not block legitimate path reuse with a 409. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): anchor KB file ownership to earliest document in any state A KB file's owner is now the earliest document referencing its key regardless of state (active/archived/deleted/excluded); access is granted only when that owning document is still active. Closes the residual where an attacker could plant an active document to claim a file whose original document was archived or deleted. * updated greptile icon * revert(security): drop KB file authorization changes Reverts the knowledge-base file-access work (origin-pinning / owner-pinning / origin allow-list in verifyKBFileAccess) and its test. The other hardening fixes (SSO domain registration, webhook path isolation, workspace env secrets, CSV export) are unchanged. apps/sim/app/api/files/authorization.ts is restored to its origin/staging baseline. * fix(sso): treat caller's own user-scoped provider as owned during conflict check Self-hosters often register SSO user-scoped via the CLI script (no SSO_ORGANIZATION_ID). If they later enable organizations and reconfigure the same domain org-scoped through the UI, the conflict check previously treated their own user-scoped row as another tenant's and returned a misleading 409. Recognize the caller's own user-scoped provider as owned so that migration is allowed, while still blocking another user's or another org's domain. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * revert(security): remove workspace-env admin gate Defer to a credential-based access model (separate change). Restores GET /api/workspaces/[id]/environment to main behavior and removes the test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(security): consolidate webhook path-collision check into one helper Extract findConflictingWebhookPathOwner to lib/webhooks/utils.server.ts as the single source of truth for cross-tenant path-collision detection, used by both webhook creation paths (deploy sync and the manual /api/webhooks route). This also repairs two latent issues in the manual route's previous inline check, which queried with limit(1) and only webhook.archivedAt: - limit(1) inspected one arbitrary row, so a same-workflow row could mask a foreign collision (false negative). The shared helper scans all matching rows. - It omitted isActive/workflow.archivedAt, so inactive or archived-workflow webhooks (which never receive deliveries) permanently blocked path reuse. The helper mirrors the runtime dispatcher's filter. Same-workflow webhook reuse for upsert is now a separate, explicit lookup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): block private/reserved IPs for hosted 1Password Connect SSRF (#4818) * fix(security): block private/reserved IPs for hosted 1Password Connect SSRF * test(security): use real isPrivateOrReservedIP and cover IPv6 edge cases * improvement(integrations): validate and expand devin, cursor, and greptile (#4820) * improvement(integrations): validate and expand devin, cursor, and greptile - devin: fix missing org_id path segment on all session endpoints, add 7 session sub-resource tools (list messages/attachments, get/append/replace tags, archive, terminate), pagination, and is_archived output - cursor: add get_api_key_info, list_models, list_repositories tools - greptile: align block and docs - normalize array outputs to default [] and tighten types * refactor(cursor): simplify list_repositories v2 array normalization Collapse the redundant `?? []` + `Array.isArray` double-guard into a single Array.isArray check, per PR review feedback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(devin): scope session-tag mapping to tag ops and normalize array tag inputs - Only map sessionTags into the tools tags param for append/replace operations, preventing stale sessionTags state from clobbering create_session tags - Fall back to a wired tags value when sessionTags is empty for tag operations - Normalize tag inputs (string or wired string[]) via normalizeTags so array values from other blocks no longer throw on .split Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(cursor): restore base64 file data in legacy download_artifact metadata The legacy CursorBlock exposes only content + metadata (no v2 file output), so metadata.data was the only way legacy-block workflows could access downloaded artifact bytes. Restore the base64 data field and document it in the outputs/type instead of dropping it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(devin): coerce terminateArchive to archive flag for boolean-wired input * docs(integrations): regenerate tool docs for new devin and cursor operations --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(search-replace): don't auto-navigate when content edits invalidate the active match (#4819) * fix(search-replace): don't auto-navigate when content edits invalidate the active match * fix(search-replace): clear afterReplaceIndexRef on apply failure and zero matches * fix(search-replace): remove duplicate setActiveSearchTarget(null) on close * fix(search-replace): move afterReplaceIndexRef write inside handleApply past the guard * fix(search-replace): auto-navigate when hydration resolves with no prior active match * chore(search-replace): remove inline comments * fix(search-replace): revert !activeMatchId guard that caused immediate re-navigation after deselect * improvement(enrichments): limit company-info to fields both providers return (#4817) Hunter's company dataset returns null industry/foundedYear for many large companies (verified against the live API for Microsoft, Amazon, Google), so under the first-non-empty-wins cascade those columns appeared inconsistently across rows. Limit company-info outputs to employee count and description — the fields Hunter and PDL both reliably return — so every row is consistent. employeeCount is a string so Hunter's range bucket and PDL's exact count share the column. * fix(files): don't reject external URLs containing '..' in file parse validation (#4821) * fix(files): don't reject external URLs containing '..' in file parse validation The file block's file_fetch operation rejected any external URL whose path contained '..' (e.g. Slack files-pri slugs with a literal '...') with 'Access denied: path traversal detected'. Traversal checks only apply to local paths — external http(s) URLs are fetched with SSRF protection downstream and are never resolved against the filesystem, so they now short-circuit as valid. Internal /api/files/serve/ URLs keep full traversal protection. * test(files): fix external-URL assertion to handle undefined error * test(files): assert success explicitly in external-URL traversal test * fix(files): keep traversal protection for https URLs matching internal serve paths * feat(google-sheets): add row filtering to read with numeric operators (#4822) * feat(google-sheets): add row filtering to read with numeric operators Adds client-side row filtering to the Google Sheets read (v2) operation. Filter the returned rows by a header column using text operators (contains, not_contains, exact, not_equals, starts_with, ends_with) and numeric/ordering operators (gt, gte, lt, lte). Filtering lives in a pure, unit-tested helper (filterSheetRows) and runs over the fetched read range; an optional `filter` output reports whether the column was found and how many rows matched. Also hardens the surrounding tools: - trim spreadsheetId in write/update/append URL builders (matches read) - URL-encode the v1 read default range - expose valueInputOption for the update operation in the block Backwards compatible: with no filter requested, read output is byte- identical and the `filter` field is omitted. The filterMatchType union is widened additively (4 -> 10 values). * fix(google-sheets): correct filter metadata for missing column and header-only sheets - matchedRows is now 0 (not totalRows) when the filter column is not found, so it no longer contradicts applied=false / columnFound=false - columnFound now reflects an actual header lookup for empty/header-only sheets instead of being hardcoded true - add tests covering header-only and empty sheets with present/absent columns * fix(selectors): fetch all pages for paginated dropdown list routes (#4823) * fix(selectors): fetch all pages for paginated dropdown list routes Dropdown selectors fetched only the first page of paginated provider APIs, silently hiding results past page one. Add bounded server-side draining to the list routes across Microsoft Graph, Google, Notion, Atlassian, Linear, AWS CloudWatch, and offset/token REST APIs, plus a shared client-side drain cap in the selector hook. Response shapes, stored values, and tool execution are unchanged; CloudWatch list tools still honor a caller-supplied limit. Also fixes the Word file picker that was searching for .xlsx files. * fix(selectors): harden JSM and Monday pagination draining - JSM service-desk/request-type drains advance `start` by the actual row count returned (not the fixed page size) and stop on an empty page, so a short non-final page can't skip items. - Monday boards drain now checks `response.ok` per page, surfacing a mid-drain HTTP failure instead of treating it as an empty final page and returning a partial 200. * docs(selectors): clarify JSM drain advances start by actual row count The offset-advancement fix (advance `start` by the rows returned, not the fixed page size) landed in 7b19788a8; update the TSDoc to match so it no longer reads as advancing by `limit`. * fix(selectors): drain fetchPage in direct fetchList callers Making `fetchList` optional left three direct callers (outside the useSelectorOptions hook) calling it unguarded, which broke the build's type check. Route them through a shared `loadAllSelectorOptions` helper that uses `fetchList` when present and otherwise drains `fetchPage`. This also prevents a regression: `confluence.spaces` / `knowledge.documents` now paginate via `fetchPage` only, and these callers (search/replace, value resolution) would otherwise have silently returned no options. * chore(selectors): rename MAX_PAGE_PAGES to MAX_NOTION_PAGES for readability * fix(sso): re-check domain conflict before write and reject IP-address domains (#4825) * improvement(copilot): make copilot_messages the sole transcript store, remove JSONB dual-write (#4826) Stop writing/reading the legacy copilot_chats.messages JSONB column now that reads are cut over to copilot_messages. Make appendCopilotChatMessages the primary write (throws on failure instead of swallowing), repoint peripheral readers (workspace VFS, chat cleanup, data drains, fork, superuser import) to copilot_messages, and persist the assistant turn inside finalizeAssistantTurn's transaction so it commits atomically with the stream-marker clear. The column itself is dropped in a follow-up migration after this bakes. * feat(tables): expand filter operators (not-contains, starts/ends-with, not-in, empty) (#4827) Add does-not-contain ($ncontains), starts-with ($startsWith), ends-with ($endsWith), not-in-array ($nin, previously executed server-side but unexposed in the UI), and is-empty/is-not-empty ($empty) filter operators end-to-end — SQL builder, condition types, query-builder converters/constants, the filter UI, the Table tools/block descriptions, and docs. Also fix correctness bugs in the filter builder surfaced by the wider operator set: - Same-column AND rules (e.g. age > 18 AND age < 65, or name startsWith 'A' AND name endsWith 'Z') silently overwrote each other because the AND group was keyed by column name. They now merge into one operator object, which also makes Filter -> rules -> Filter round-trip losslessly for multi-operator columns. - $nin values were not split into an array like $in, and textual-match values like "123" were numeric-coerced (breaking the ILIKE path). - A non-boolean $empty operand from the raw API silently inverted the check; it now coerces 'true'/'false' strings and otherwise returns a 400. * improvement(copilot): stop persisting tool-call result outputs in transcripts (#4829) Opening a Mothership task could take many seconds because a single persisted assistant message in copilot_messages.content can reach hundreds of MB, almost entirely inside contentBlocks[].toolCall.result.output (e.g. a get_workflow_logs or run_workflow result). The DB query is ~2ms; the cost is detoasting that payload, shipping it to the browser, and parsing it. These outputs are dead weight on the Sim side: they are never rendered (the thread shows only tool name/title/status) and never replayed to the model (the upstream copilot service owns conversation memory). So drop result.output before it is persisted, keeping result.success/error plus the tool metadata. - add stripToolResultOutput() in persisted-message.ts - apply it in messages-store toRow (covers every write path) and in loadCopilotChatMessages (existing rows render fast on read) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * feat(providers): add Together AI, Baseten, and Ollama Cloud model providers (#4830) * feat(providers): add Together AI, Baseten, and Ollama Cloud model providers * fix(providers): guard Ollama streaming fast-path with hasActiveTools Match Together/Baseten/Fireworks: when tools are supplied but all are filtered out (usageControl 'none'), take the single streaming call instead of an extra non-streaming round-trip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(providers): filter non-chat model types from Together model list * refactor(providers): dedupe Ollama Cloud upstream schema ollamaCloudUpstreamResponseSchema was byte-for-byte identical to ollamaUpstreamResponseSchema (both /api/tags endpoints return the same { models: [{ name }] } shape). Drop the duplicate and reuse the shared schema. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(knowledge): calendar view sync, deduplicate popover animation classes, type-safe filter cast * cleanup(knowledge): remove TRIGGER_BORDER_CLASS duplication, inline displayLabel, drop enabledFilterParam alias --------- Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Waleed <walif6@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Theodore Li <theo@sim.ai> Co-authored-by: andresdjasso <andresdjasso@users.noreply.github.com> * feat(blocks): add BlockMeta to Quiver and Linq; fix invalid block config fields; update skills Block fixes: - Add QuiverBlockMeta (tags + 3 templates: icon generator, diagram creator, vectorizer) - Fix QuiverBlock: remove invalid tags field from BlockConfig, IntegrationType.Design → IntegrationType.AI (Design doesn't exist in the enum) - Fix GreptileBlock: remove invalid tags field from BlockConfig, IntegrationType.DeveloperTools → IntegrationType.DevOps - Fix LinqBlock: remove invalid tags field from BlockConfig (tags belong only in BlockMeta) Skills: - add-block: add dedicated BlockMeta section with structure, rules, and registration pattern; add BlockMeta checklist items - add-integration: add BlockMeta to block structure template, add rules clarifying that tags must NOT appear on BlockConfig and integrationType must be a valid enum value; update registry snippet to include blocksMeta; add checklist items * fix(integrations): fix category dropdown by defining missing LANDING_INTEGRATIONS_DATA_PATH and regenerating integrations.json The staging merge introduced landing-content.ts but forgot to define LANDING_INTEGRATIONS_DATA_PATH in generate-docs.ts, causing the script to crash before writing integrations.json. The stale JSON had integrationTypes (plural array) from an older script version, while the Integration type and workspace UI both read integrationType (singular string) — so ALL_CATEGORY_SECTIONS bucketed to undefined and the category filters never appeared in the dropdown. Fixed by adding the missing path constant and re-running the generator. integrations.json now has 192 entries with the correct integrationType field. * fix(sidebar): restore resize handle on all pages commit |
||
|
|
540835a7a5 |
feat(integrations): add AWS AppConfig integration with tools, block, and docs (#4928)
* feat(integrations): add AWS AppConfig integration with tools, block, and docs * fix(integrations): preserve latestVersionNumber 0 and tighten locationUri type in AppConfig * fix(integrations): use valid IntegrationTag values in AppConfig BlockMeta * feat(appconfig): add list_hosted_configuration_versions operation * fix(appconfig): stringify configurationVersion in block params * feat(appconfig): add full CRUD for applications, environments, and configuration profiles Adds get/update/delete for applications, environments, and configuration profiles, plus delete_hosted_configuration_version — 10 tools rounding out the integration to management-grade CRUD completeness. --------- Co-authored-by: Theodore Li <theo@sim.ai> |
||
|
|
24f04162fb |
feat(integrations): expand tool coverage, audit integrations, regen docs (#4920)
* feat(integrations): expand tool coverage, audit integrations, regen docs Integrations - Audit and expand Railway, Reddit, Vercel, Sentry, Granola, LaunchDarkly, Infisical, Intercom, Luma, 1Password, NeverBounce, and ZeroBounce tools against their live API docs; correct request/response shapes and outputs - Add new tools across Railway (services, deployment lifecycle, variables), Reddit (mod actions, user/subreddit reads, messaging), Vercel (domains, webhooks, edge config, deployment promotion), Sentry (teams), and Granola (folders); register all in the tool registry - Infisical: fix delete to send params in the JSON body and complete the secret output fields (actor, metadata isEncrypted, rotation/reminder fields) UI - Update the user-input tooltip copy - Adjust the feedback modal textarea sizing Docs - Regenerate tool/trigger docs to match current source * rm comments from registry * feat(integrations): expand Kalshi, Luma, Rootly, Polymarket, Railway tools; regen docs - Add and refine tools across Kalshi, Luma, Rootly, Polymarket, Railway, LaunchDarkly, and Sentry; register all new tools - Regenerate tool docs to match the updated source * chore(integrations): update Kalshi get_balance, drop polymarket test, regen docs * chore(integrations): update Kalshi get_events and subblock migrations, regen docs |
||
|
|
a72e35e2f4 |
feat(sendblue): add Sendblue iMessage/SMS integration with tools and triggers (#4917)
* feat(sendblue): add Sendblue iMessage/SMS integration with tools and triggers * fix(sendblue): address review — status-aware webhook dedup, shared routing map, uniform output casing, api-key authType * fix(docs-gen): skip nested array `items` descriptor in tool input tables * chore(sendblue): use SendblueSendStyle type, trim URL identifiers * fix(sendblue): keep is_outbound routing map local to the webhook handler Avoids a webhook-providers -> triggers cross-subgraph import (single source of truth in the handler, its only runtime consumer). * fix(sendblue): remove invalid `tags` from block config (belongs on BlockMeta) |
||
|
|
25771358d0 |
feat(enrichment): add ZeroBounce, NeverBounce, and MillionVerifier email verification (#4854)
* feat(enrichment): add ZeroBounce, NeverBounce, and MillionVerifier email verification * docs gen * mdx * fix(zerobounce): handle 200-status API errors and guard JSON parsing * fix(byok): render new email-verify providers + raise hosted rate limits - Add zerobounce/neverbounce/millionverifier to the Enrichment PROVIDER_SECTIONS so they render in the workspace BYOK settings UI (they were in PROVIDERS + the API allowlist but no section listed them). - Raise ZeroBounce and MillionVerifier hosted per-workspace rate limits from 60 to 1200 req/min, sized against documented upstream ceilings (ZeroBounce 80k/10s; MillionVerifier 160/sec). NeverBounce stays at 60 pending its account-configured throttle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Theodore Li <theo@sim.ai> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
0075ab9cf6 |
improvement(platform): remove tour, simplify sidebar/header, drop loading skeletons (#4354)
* improvement(platform): workspace UI/UX overhaul + integrations catalog Rework the workspace around the AI-workspace model: a Mothership home, a top-level Skills route, connected-credential and integration-detail pages, and a polished sidebar/settings surface. Replace the notifications store with a unified toast system (provider-level dismiss/pause, countdown ring). Integrations & catalog: - Add a BlockMeta layer (tags + catalog templates) scoped to catalog-visible integrations; every catalog integration carries >=7 grounded templates. - Rework the taxonomy: each block declares category tools|blocks|triggers. 3rd-party services are 'tools'; first-party primitives (postgres, mysql, knowledge, file, search, stt/tts, image/video generators, thinking, etc.) are 'blocks'. Versioned blocks follow the upgrade paradigm (old hidden, latest in toolbar/docs). - Generate integrations.json + tool docs canonically from block configs. Architecture & cleanup: - Consolidate block data extraction behind a single latest-version strategy (getCanonicalBlocksByCategory; version-consistent getBlockMeta). - Unify version-suffix handling in @sim/utils/string (stripVersionSuffix / isVersionedType, with tests); registry, generate-docs, tools/utils, and integrations all route through it. - Repair latent broken barrels, remove dead code, fix BlockMeta-related type errors and 5 broken docs links. Behavior-preserving for block execution and the toolbar's tool/block listing. * refactor(platform): remove forms, templates, and creators features Remove three standalone features and their supporting code: - Forms: form-deployment pages, API routes, execution path, and docs. - Templates: the template gallery (landing + workspace) and template APIs. - Creators: creator-profile routes and contracts. Add a super-user permissions module (lib/permissions/super-user) and an organizations API contract; update the audit/db/testing packages, billing, and the session/theme providers accordingly. * test(workflows): update archiveWorkflow update count after forms removal The forms feature was removed, dropping the form-table update from archiveWorkflow. Update the stale assertion from 8 to 7 tx.update calls. * upgrade * improvement(knowledge): polish tag filter dropdowns (#4816) * improvement(logs): object storage backed tracespans (#4787) * improvement(logs): obj storage backed tracespans * fix storage write context * fix tests * address comments * address comments * chore(db): remove migration 0219 to regenerate after staging merge Drops the 0219_robust_shard SQL, its snapshot, and the journal entry so the trace-spans/cost schema migration can be regenerated on top of the latest staging migration chain (avoids a number collision with staging's migrations). Co-authored-by: Cursor <cursoragent@cursor.com> * improvement(billing): accurate per-member usage via shared ledger helper Per-member/per-user usage in the org-member routes now adds the usage_log ledger to the currentPeriodCost baseline (which is no longer incremented), via a shared getOrgMemberLedgerByUser helper to avoid repeating the subscription→period→ledger lookup across the admin and member-facing routes. Co-authored-by: Cursor <cursoragent@cursor.com> * regen migrations * update migration * address comments * more code cleanup * incorrect type cast --------- Co-authored-by: Cursor <cursoragent@cursor.com> * improvement(providers): harden OpenAI-compatible providers + add tests (#4796) * improvement(providers): harden OpenAI-compatible providers + add tests * fix(vllm): let tool-loop errors propagate instead of returning silent partial success * fix(litellm): force tool_choice 'none' on final structured-output call The deferred final call used tool_choice 'auto', so the model could emit another tool_calls round instead of the structured answer, leaving content stale. Use 'none' (matching vLLM/Fireworks) on both the streaming and non-streaming final calls so the model must return the structured response. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(providers/ollama): drop tools from post-tool streaming call Ollama ignores tool_choice (not in its supported fields), so vLLM/Fireworks' tool_choice:'none' guard is a no-op here. Omit tools from the final streaming payload instead so the summarization turn can't emit dropped tool calls. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(litellm): spread payload into deferred final call so reasoning_effort carries over The non-streaming deferred finalPayload hand-picked fields and dropped reasoning_effort (and any future payload field), diverging from the streaming path which spreads ...payload. Spread payload here too for consistency. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(providers/ollama): restore enrichment TSDoc block Keeps parity with sibling Chat Completions providers (cerebras/mistral/xai). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(fireworks): restore TSDoc on utils helpers Restore the TSDoc blocks on supportsNativeStructuredOutputs, createReadableStreamFromOpenAIStream, and checkForForcedToolUsage — TSDoc is the codebase documentation standard and should not have been stripped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(litellm): remove inline rationale comments (codebase uses TSDoc) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(providers/ollama): drop orphaned enrichment TSDoc The block documented a function that now lives in trace-enrichment.ts, so it documents nothing in this file. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * chore(copilot): deprecate mcp server (#4797) * chore(copilot): deprecate mcp * update error codes * deprecate copilot api v1 route * feat(integrations): hosted API keys for Findymail, Prospeo, and Wiza (#4777) * feat(integrations): hosted API keys for Findymail, Prospeo, and Wiza Add hosted-key support across all credit-consuming Findymail, Prospeo, and Wiza operations so Sim provides the key when a workspace has not brought its own. Register the three BYOK providers, consolidate Wiza's two-step reveal into a single polling wiza_individual_reveal op, and hide the API key field on hosted Sim for hosted operations. * fix(integrations): harden Wiza reveal polling, soften enrichment getCost guards Address Greptile + Cursor Bugbot review on #4777: return explicit failures from the Wiza individual_reveal poller instead of throwing (thrown errors were swallowed into a false queued success), short-circuit when the initial reveal is already terminal, tolerate transient 5xx/429 during polling, and return 0 (not throw) from Findymail getCost when the contacts/employees array is absent. * chore(integrations): biome formatting after wiza merge resolution * fix(wiza): type isTerminalReveal param structurally for next build typecheck * feat(enrichments): add Findymail, Prospeo, Wiza to work-email waterfall * feat(enrichments): add Wiza + Prospeo phone reveal to phone-number waterfall * feat(enrichments): opportunistic identifiers + LinkedIn URL input across work-email & phone cascades * fix(tables): reduce column header chevron size and fix sidebar shadow bleed (#4800) * feat(slack): add install + privacy section to integration landing page (#4799) * feat(slack): add install + privacy section to integration landing page Adds a hand-authored, slug-keyed landing-content module (separate from the generated integrations.json so it survives regeneration) and renders an install walkthrough + privacy-policy link on integration pages when present. Also refreshes generated docs (data-enrichment entry, icon mappings, tool mdx). * fix(landing): render privacy section independently, align CTA analytics label * docs(landing): clarify the Slack install button is behind sign-in * refactor(landing): bake integration landing content into generated json via docs-gen Moves landing content (install walkthrough + privacy) out of a render-time augment and into the generation pipeline: generate-docs reads the pure-data content map and writes landingContent into integrations.json, so the page reads a single source (integration.landingContent). Canonical types live in integrations/data/types.ts. * improvement(enrichments): align enrichments sidebar with design system (#4801) * improvement(enrichments): align enrichments sidebar with design system * fix(enrichments): consistent close button pattern and fix url link hover * fix(misc): upgrade path change for new better-auth version, billing issue for workflow block agent usage (#4803) * fix(misc): upgrade path change for new better-auth version, double-billing for workflow block agent usage * fail loudly if stripe sub id missing * fix(copilot): seq migration (#4804) * chore(db): drop redundant idx_webhook_on_workflow_id_block_id index (#4809) Removed because (workflow_id, block_id) is a left-prefix of idx_webhook_on_workflow_id_block_id_updated_at_desc, which fully covers it. The dropped index was non-unique and enforced no constraint. * perf(copilot): read chat transcripts from copilot_messages (R+1 cutover) (#4808) * perf(copilot): read chat transcripts from copilot_messages, not JSONB Flip user-facing chat reads from the legacy copilot_chats.messages JSONB array (5.7GB, 99% TOAST) to the normalized copilot_messages table via a new loadCopilotChatMessages helper ordered by seq NULLS LAST, created_at, id — the verified canonical order. Both chat-detail getters (getAccessibleCopilotChat, getAccessibleCopilotChatWithMessages) now drop the messages column from their metadata select (no more whole-array detoast on every load) and assemble the transcript from the table after authorization. This cascades to the copilot + mothership GET endpoints and to resolveOrCreateChat's conversationHistory (the LLM payload). The normalize/effective-transcript pipeline is source-agnostic (copilot_messages.content == a JSONB array element), so transcripts are byte-identical. Dual-write and the JSONB column stay in place as the internal-logic source and fallback; removing JSONB writes is a later step. Prod integrity verified before cutover: 0 messages missing, 0 NULL-seq, 0 dup keys/seq, 0 orphans, order-parity vs JSONB = 0 mismatches. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(copilot): cover auth-deny on a found row skips the messages query Address PR review: exercise the `if (!authorized) return null` contract — when the chat row exists but authorization fails, the getter returns null and never issues the copilot_messages read. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(tables): right-align run/stop in embedded toolbar; workflow cells format like normal cells (#4806) * fix(tables): right-align run/stop in the embedded table toolbar Add a right-aligned `trailing` slot to ResourceOptionsBar and move the embedded mothership table's run/stop control into it, so Filter + Sort stay left-aligned and run/stop sits opposite on the right. No-op for the search-bearing consumers (logs, resource list), which don't pass `trailing`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(tables): workflow-output cells format values like normal cells Workflow-output columns short-circuited in resolveCellRender and rendered their value as plain text, so a sim-resource URL / external URL / JSON / date produced by a workflow never got the chip, favicon link, or typed formatting a normal cell gets. Factor value formatting into a shared `resolveValueKind` helper used by both the workflow-value branch and the plain-cell branch; the workflow branch keeps the typewriter reveal for plain streaming text via a `typewriter` flag. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(tables): detect resource/URL links on workflow output regardless of column type Workflow output columns default to `json` (columnTypeForLeaf), so routing their values through the type-based formatter (a) gated chip/URL promotion behind `column.type === 'string'` — a URL produced by a json-typed output never became a chip — and (b) JSON.stringify'd plain string values, adding quotes and losing the typewriter reveal. Detect links (sim-resource chip / favicon URL) on the value string directly for workflow outputs, falling back to the plain `value` kind; plain cells keep the type-based formatting. Addresses Greptile P2 on #4806. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(icons): repair broken integration icon rendering (#4810) * fix(icons): repair broken integration icon rendering Two distinct bugs left integration icons broken on the /integrations page (visible at 32-40px, hidden at the toolbar's 16px): 1. Corrupted SVG paths (Notion, Greptile, Granola, Calendly, Grafana, Bedrock): over-minified data dropped elliptical-arc flag digits (e.g. `A1 1 0 5.9 7` instead of `A1 1 0 0 0 5.9 7`); Granola's cubic stream was truncated. Browsers abort path parsing at the first invalid arc flag, so each rendered as a fragment or blank. Replaced with correct path data from canonical sources, preserving each icon's existing fill/gradient and bgColor. 2. Invisible glyph (Bright Data): its icon uses fill='currentColor' but bgColor was '#FFFFFF', and every surface forces text-white on the glyph - white-on-white. Changed bgColor to Bright Data's brand blue (#3d7ffc) so the white glyph reads, matching the white-glyph-on-brand-chip convention. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): restore Calendly dual-tone brand colors Addresses review feedback: the previous fix replaced the broken Calendly icon with a monochrome #006BFF path, dropping the cyan #0ae8f0 accent from the original dual-tone mark. Restored the two-tone logo (blue + cyan) using clean, valid path data, cropped to a tight square viewBox so it fills the chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge icons, fix Zoom contrast and Quiver chip - Zoom: glyph was blue-on-blue (#0B5CFF on #2D8CFF chip); switched to currentColor so it renders as a white glyph on the blue chip. - Quiver: chip bgColor #000000 -> #FFFFFF to match the icon's near-white box, and enlarged the mark slightly (viewBox crop). - Enlarged (tightened viewBox, verified no clipping): RevenueCat, Prospeo, Granola, Firecrawl, Enrich.so, and the AWS icons (RDS, DynamoDB, SQS, CloudFormation, Athena, CloudWatch, SES, Bedrock, S3). - ZoomInfo left unchanged: it is a full red rounded-square logo that already fills its frame, so a crop would clip it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): use Bright Data wordmark on white chip; repair Circleback - Bright Data: replaced the flame glyph with the official two-tone 'bright data' wordmark (provided asset), centered in a symmetric viewBox. Reverted the chip bgColor from #3d7ffc to #FFFFFF since the blue wordmark is invisible on a blue chip (the wordmark is designed for a light background). - Circleback: a minifier had rounded the pattern's image scale to scale(0), collapsing the embedded logo to zero size (invisible). Restored the correct scale (1/280 = 0.00357142857) so the C. mark renders. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(docs): sync Quiver block color card to white chip Reflects the Quiver bgColor change (#000000 -> #FFFFFF) in the docs block info card. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge AWS/Cloudflare/Dagster icons, fully white Zoom - Enlarged (tighter viewBox, render-verified, no clipping): Cloudflare, Dagster, and the red AWS icons AWS IAM, Identity Center, Secrets Manager, SES, STS. Identity Center was anomalously small (filled ~32% of its frame); the group is now sized consistently (~80% fill). - Zoom: the camera lens triangle was still #0B5CFF (blue-on-blue); switched it to currentColor so the whole camera renders white on the blue chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(wiza): consolidate individual reveal into a single operation Merges the separate Start/Get Individual Reveal operations into one Individual Reveal operation in the Wiza docs and integrations data (operationCount 5 -> 4). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): size remaining AWS icons to match the set (~80% fill) Bring RDS, DynamoDB, SQS, CloudFormation, Athena, CloudWatch and S3 up to the same ~80% fill as the AWS IAM/Identity Center/Secrets Manager/SES/STS group, so all AWS icons are visually consistent. Bedrock left as-is (already ~92% fill). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): use Bright Data flame mark, enlarge ZoomInfo - Bright Data: the full 'bright data' wordmark was illegible at chip size. Replaced with just the flame-'i' brand mark (blue #4280f6 on the white chip), centered. - ZoomInfo: cropped the viewBox toward the white 'Zi' so it's larger; the red rounded-square background still fills the chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge CrowdStrike icon The falcon mark sat small in its chip because the icon used a wide 768x500 viewBox (letterboxed in the square chip). Switched to a square viewBox centered on the mark so it fills ~80%, consistent with the other icons. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(tables): serialize schema mutations to prevent parallel column clobber (#4812) * Make workflow description nullable * fix(tables): serialize schema mutations to prevent parallel column clobber * fix(tables): load workflow outside schema lock; use DbOrTx for getTableById * fix(tables): scale idle timeout in updateColumnType to avoid aborting large type changes * fix(tables): skip stale remap types when workflowId changes concurrently * fix(tables): scale idle timeout in updateColumnConstraints for large tables * fix(wait): resume live/draft async waits and preserve cell context on chained waits (#4814) * Make workflow description nullable * fix(wait): resume live/draft async waits and preserve cell context on chained waits * improvement(knowledge): polish tag filter dropdowns * improvement(knowledge): soften filter section labels * improvement(knowledge): soften list filter labels * fix(security): harden SSO domain registration, webhook path isolation, and CSV export (#4813) * fix(security): harden KB file access, SSO domain registration, webhook path isolation, env secrets, and CSV export * fix(sso): scope domain conflict query with indexed lower(domain) filter Address PR review: avoid a full-table scan on every SSO provider registration by filtering candidate rows in SQL with lower(domain) = <normalized>, keeping the in-memory ownership check. Also tighten the normalizeSSODomain TSDoc. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: condense env route security comments Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * icons update * chore(security): tighten inline comments in CSV export and KB file authorization Condense verbose comment blocks to concise TSDoc/single-line form; no behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): validate internal serve origin in KB file authorization Replace the bypassable isInternalFileUrl substring check in resolveInternalKbKey with an origin allow-list (base URL, internal API base URL, TRUSTED_ORIGINS). A crafted external host whose path is /api/files/serve/<victim-key> no longer resolves to the victim key. Relative same-origin URLs are unaffected. * style(sso): use idiomatic sql lower() comparison for domain conflict query Match the repo's prevailing `sql`lower(col) = value`` idiom for the case-insensitive SSO domain conflict lookup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): align workspace env admin gate with hasWorkspaceAdminAccess Use the same admin check the secrets UI uses (owner, admin permission, or org-admin) so owners and org-admins are not wrongly denied their own decrypted workspace secrets, while read-only members remain restricted to names only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(sso): rely on lower(domain) match for conflict detection, drop dead in-memory recheck Address PR review: the SQL `lower(domain) = <normalized>` predicate already excludes rows that the in-memory `normalizeSSODomain(...) === domain` recheck claimed to catch, making that recheck dead/misleading code. Match on the canonical lower-cased domain and filter purely by ownership. Malformed legacy values (wildcards, schemes, ports) never match an email domain at sign-in, so excluding them is not a gap. Test DB mock now applies the lower() predicate so the casing-variant case is genuinely exercised. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): scope webhook deploy path conflict to active webhooks findConflictingWebhookPathOwner omitted the isActive filter that the runtime dispatcher (findAllWebhooksForPath) applies, so an inactive but non-archived webhook from another workflow (e.g. after undeploy or failure auto-disable) would permanently block any new deployment on that path even though it never receives deliveries. Align the guard with the runtime isActive + archivedAt filter; the earliest-owner runtime check remains the authoritative cross-tenant protection. Also trims verbose TSDoc on the webhook path-isolation helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): exclude archived workflows from webhook deploy path conflict findConflictingWebhookPathOwner now joins workflow and filters isNull(workflow.archivedAt), matching the runtime dispatcher (findAllWebhooksForPath). A webhook on an archived workflow can never receive deliveries at runtime, so it must not block legitimate path reuse with a 409. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): anchor KB file ownership to earliest document in any state A KB file's owner is now the earliest document referencing its key regardless of state (active/archived/deleted/excluded); access is granted only when that owning document is still active. Closes the residual where an attacker could plant an active document to claim a file whose original document was archived or deleted. * updated greptile icon * revert(security): drop KB file authorization changes Reverts the knowledge-base file-access work (origin-pinning / owner-pinning / origin allow-list in verifyKBFileAccess) and its test. The other hardening fixes (SSO domain registration, webhook path isolation, workspace env secrets, CSV export) are unchanged. apps/sim/app/api/files/authorization.ts is restored to its origin/staging baseline. * fix(sso): treat caller's own user-scoped provider as owned during conflict check Self-hosters often register SSO user-scoped via the CLI script (no SSO_ORGANIZATION_ID). If they later enable organizations and reconfigure the same domain org-scoped through the UI, the conflict check previously treated their own user-scoped row as another tenant's and returned a misleading 409. Recognize the caller's own user-scoped provider as owned so that migration is allowed, while still blocking another user's or another org's domain. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * revert(security): remove workspace-env admin gate Defer to a credential-based access model (separate change). Restores GET /api/workspaces/[id]/environment to main behavior and removes the test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(security): consolidate webhook path-collision check into one helper Extract findConflictingWebhookPathOwner to lib/webhooks/utils.server.ts as the single source of truth for cross-tenant path-collision detection, used by both webhook creation paths (deploy sync and the manual /api/webhooks route). This also repairs two latent issues in the manual route's previous inline check, which queried with limit(1) and only webhook.archivedAt: - limit(1) inspected one arbitrary row, so a same-workflow row could mask a foreign collision (false negative). The shared helper scans all matching rows. - It omitted isActive/workflow.archivedAt, so inactive or archived-workflow webhooks (which never receive deliveries) permanently blocked path reuse. The helper mirrors the runtime dispatcher's filter. Same-workflow webhook reuse for upsert is now a separate, explicit lookup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): block private/reserved IPs for hosted 1Password Connect SSRF (#4818) * fix(security): block private/reserved IPs for hosted 1Password Connect SSRF * test(security): use real isPrivateOrReservedIP and cover IPv6 edge cases * improvement(integrations): validate and expand devin, cursor, and greptile (#4820) * improvement(integrations): validate and expand devin, cursor, and greptile - devin: fix missing org_id path segment on all session endpoints, add 7 session sub-resource tools (list messages/attachments, get/append/replace tags, archive, terminate), pagination, and is_archived output - cursor: add get_api_key_info, list_models, list_repositories tools - greptile: align block and docs - normalize array outputs to default [] and tighten types * refactor(cursor): simplify list_repositories v2 array normalization Collapse the redundant `?? []` + `Array.isArray` double-guard into a single Array.isArray check, per PR review feedback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(devin): scope session-tag mapping to tag ops and normalize array tag inputs - Only map sessionTags into the tools tags param for append/replace operations, preventing stale sessionTags state from clobbering create_session tags - Fall back to a wired tags value when sessionTags is empty for tag operations - Normalize tag inputs (string or wired string[]) via normalizeTags so array values from other blocks no longer throw on .split Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(cursor): restore base64 file data in legacy download_artifact metadata The legacy CursorBlock exposes only content + metadata (no v2 file output), so metadata.data was the only way legacy-block workflows could access downloaded artifact bytes. Restore the base64 data field and document it in the outputs/type instead of dropping it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(devin): coerce terminateArchive to archive flag for boolean-wired input * docs(integrations): regenerate tool docs for new devin and cursor operations --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(search-replace): don't auto-navigate when content edits invalidate the active match (#4819) * fix(search-replace): don't auto-navigate when content edits invalidate the active match * fix(search-replace): clear afterReplaceIndexRef on apply failure and zero matches * fix(search-replace): remove duplicate setActiveSearchTarget(null) on close * fix(search-replace): move afterReplaceIndexRef write inside handleApply past the guard * fix(search-replace): auto-navigate when hydration resolves with no prior active match * chore(search-replace): remove inline comments * fix(search-replace): revert !activeMatchId guard that caused immediate re-navigation after deselect * improvement(enrichments): limit company-info to fields both providers return (#4817) Hunter's company dataset returns null industry/foundedYear for many large companies (verified against the live API for Microsoft, Amazon, Google), so under the first-non-empty-wins cascade those columns appeared inconsistently across rows. Limit company-info outputs to employee count and description — the fields Hunter and PDL both reliably return — so every row is consistent. employeeCount is a string so Hunter's range bucket and PDL's exact count share the column. * fix(files): don't reject external URLs containing '..' in file parse validation (#4821) * fix(files): don't reject external URLs containing '..' in file parse validation The file block's file_fetch operation rejected any external URL whose path contained '..' (e.g. Slack files-pri slugs with a literal '...') with 'Access denied: path traversal detected'. Traversal checks only apply to local paths — external http(s) URLs are fetched with SSRF protection downstream and are never resolved against the filesystem, so they now short-circuit as valid. Internal /api/files/serve/ URLs keep full traversal protection. * test(files): fix external-URL assertion to handle undefined error * test(files): assert success explicitly in external-URL traversal test * fix(files): keep traversal protection for https URLs matching internal serve paths * feat(google-sheets): add row filtering to read with numeric operators (#4822) * feat(google-sheets): add row filtering to read with numeric operators Adds client-side row filtering to the Google Sheets read (v2) operation. Filter the returned rows by a header column using text operators (contains, not_contains, exact, not_equals, starts_with, ends_with) and numeric/ordering operators (gt, gte, lt, lte). Filtering lives in a pure, unit-tested helper (filterSheetRows) and runs over the fetched read range; an optional `filter` output reports whether the column was found and how many rows matched. Also hardens the surrounding tools: - trim spreadsheetId in write/update/append URL builders (matches read) - URL-encode the v1 read default range - expose valueInputOption for the update operation in the block Backwards compatible: with no filter requested, read output is byte- identical and the `filter` field is omitted. The filterMatchType union is widened additively (4 -> 10 values). * fix(google-sheets): correct filter metadata for missing column and header-only sheets - matchedRows is now 0 (not totalRows) when the filter column is not found, so it no longer contradicts applied=false / columnFound=false - columnFound now reflects an actual header lookup for empty/header-only sheets instead of being hardcoded true - add tests covering header-only and empty sheets with present/absent columns * fix(selectors): fetch all pages for paginated dropdown list routes (#4823) * fix(selectors): fetch all pages for paginated dropdown list routes Dropdown selectors fetched only the first page of paginated provider APIs, silently hiding results past page one. Add bounded server-side draining to the list routes across Microsoft Graph, Google, Notion, Atlassian, Linear, AWS CloudWatch, and offset/token REST APIs, plus a shared client-side drain cap in the selector hook. Response shapes, stored values, and tool execution are unchanged; CloudWatch list tools still honor a caller-supplied limit. Also fixes the Word file picker that was searching for .xlsx files. * fix(selectors): harden JSM and Monday pagination draining - JSM service-desk/request-type drains advance `start` by the actual row count returned (not the fixed page size) and stop on an empty page, so a short non-final page can't skip items. - Monday boards drain now checks `response.ok` per page, surfacing a mid-drain HTTP failure instead of treating it as an empty final page and returning a partial 200. * docs(selectors): clarify JSM drain advances start by actual row count The offset-advancement fix (advance `start` by the rows returned, not the fixed page size) landed in 7b19788a8; update the TSDoc to match so it no longer reads as advancing by `limit`. * fix(selectors): drain fetchPage in direct fetchList callers Making `fetchList` optional left three direct callers (outside the useSelectorOptions hook) calling it unguarded, which broke the build's type check. Route them through a shared `loadAllSelectorOptions` helper that uses `fetchList` when present and otherwise drains `fetchPage`. This also prevents a regression: `confluence.spaces` / `knowledge.documents` now paginate via `fetchPage` only, and these callers (search/replace, value resolution) would otherwise have silently returned no options. * chore(selectors): rename MAX_PAGE_PAGES to MAX_NOTION_PAGES for readability * fix(sso): re-check domain conflict before write and reject IP-address domains (#4825) * improvement(copilot): make copilot_messages the sole transcript store, remove JSONB dual-write (#4826) Stop writing/reading the legacy copilot_chats.messages JSONB column now that reads are cut over to copilot_messages. Make appendCopilotChatMessages the primary write (throws on failure instead of swallowing), repoint peripheral readers (workspace VFS, chat cleanup, data drains, fork, superuser import) to copilot_messages, and persist the assistant turn inside finalizeAssistantTurn's transaction so it commits atomically with the stream-marker clear. The column itself is dropped in a follow-up migration after this bakes. * feat(tables): expand filter operators (not-contains, starts/ends-with, not-in, empty) (#4827) Add does-not-contain ($ncontains), starts-with ($startsWith), ends-with ($endsWith), not-in-array ($nin, previously executed server-side but unexposed in the UI), and is-empty/is-not-empty ($empty) filter operators end-to-end — SQL builder, condition types, query-builder converters/constants, the filter UI, the Table tools/block descriptions, and docs. Also fix correctness bugs in the filter builder surfaced by the wider operator set: - Same-column AND rules (e.g. age > 18 AND age < 65, or name startsWith 'A' AND name endsWith 'Z') silently overwrote each other because the AND group was keyed by column name. They now merge into one operator object, which also makes Filter -> rules -> Filter round-trip losslessly for multi-operator columns. - $nin values were not split into an array like $in, and textual-match values like "123" were numeric-coerced (breaking the ILIKE path). - A non-boolean $empty operand from the raw API silently inverted the check; it now coerces 'true'/'false' strings and otherwise returns a 400. * improvement(copilot): stop persisting tool-call result outputs in transcripts (#4829) Opening a Mothership task could take many seconds because a single persisted assistant message in copilot_messages.content can reach hundreds of MB, almost entirely inside contentBlocks[].toolCall.result.output (e.g. a get_workflow_logs or run_workflow result). The DB query is ~2ms; the cost is detoasting that payload, shipping it to the browser, and parsing it. These outputs are dead weight on the Sim side: they are never rendered (the thread shows only tool name/title/status) and never replayed to the model (the upstream copilot service owns conversation memory). So drop result.output before it is persisted, keeping result.success/error plus the tool metadata. - add stripToolResultOutput() in persisted-message.ts - apply it in messages-store toRow (covers every write path) and in loadCopilotChatMessages (existing rows render fast on read) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * feat(providers): add Together AI, Baseten, and Ollama Cloud model providers (#4830) * feat(providers): add Together AI, Baseten, and Ollama Cloud model providers * fix(providers): guard Ollama streaming fast-path with hasActiveTools Match Together/Baseten/Fireworks: when tools are supplied but all are filtered out (usageControl 'none'), take the single streaming call instead of an extra non-streaming round-trip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(providers): filter non-chat model types from Together model list * refactor(providers): dedupe Ollama Cloud upstream schema ollamaCloudUpstreamResponseSchema was byte-for-byte identical to ollamaUpstreamResponseSchema (both /api/tags endpoints return the same { models: [{ name }] } shape). Drop the duplicate and reuse the shared schema. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(knowledge): calendar view sync, deduplicate popover animation classes, type-safe filter cast * cleanup(knowledge): remove TRIGGER_BORDER_CLASS duplication, inline displayLabel, drop enabledFilterParam alias --------- Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Waleed <walif6@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Theodore Li <theo@sim.ai> Co-authored-by: andresdjasso <andresdjasso@users.noreply.github.com> * feat(blocks): add BlockMeta to Quiver and Linq; fix invalid block config fields; update skills Block fixes: - Add QuiverBlockMeta (tags + 3 templates: icon generator, diagram creator, vectorizer) - Fix QuiverBlock: remove invalid tags field from BlockConfig, IntegrationType.Design → IntegrationType.AI (Design doesn't exist in the enum) - Fix GreptileBlock: remove invalid tags field from BlockConfig, IntegrationType.DeveloperTools → IntegrationType.DevOps - Fix LinqBlock: remove invalid tags field from BlockConfig (tags belong only in BlockMeta) Skills: - add-block: add dedicated BlockMeta section with structure, rules, and registration pattern; add BlockMeta checklist items - add-integration: add BlockMeta to block structure template, add rules clarifying that tags must NOT appear on BlockConfig and integrationType must be a valid enum value; update registry snippet to include blocksMeta; add checklist items * fix(integrations): fix category dropdown by defining missing LANDING_INTEGRATIONS_DATA_PATH and regenerating integrations.json The staging merge introduced landing-content.ts but forgot to define LANDING_INTEGRATIONS_DATA_PATH in generate-docs.ts, causing the script to crash before writing integrations.json. The stale JSON had integrationTypes (plural array) from an older script version, while the Integration type and workspace UI both read integrationType (singular string) — so ALL_CATEGORY_SECTIONS bucketed to undefined and the category filters never appeared in the dropdown. Fixed by adding the missing path constant and re-running the generator. integrations.json now has 192 entries with the correct integrationType field. * fix(sidebar): restore resize handle on all pages commit |
||
|
|
16954e46fe |
feat(integrations): add ClickHouse block and expand Dagster + Tinybird tools (#4883)
* feat(integrations): add ClickHouse block and expand Dagster + Tinybird tools
* fix(tinybird): fail loudly on invalid query_pipe parameters JSON
parsePipeParameters previously returned {} on any JSON parse error, so a
mistyped 'parameters' input produced a successful pipe call with the dynamic
filters silently dropped. Throw a clear error for non-empty, non-object input
instead; an omitted/empty value still means 'no parameters'.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(dagster): guard NaN numeric coercions and bound list_assets pagination
Address PR review:
- Route all block numeric coercions (list_runs limit/createdAfter/createdBefore,
get_run_logs logsLimit, list_assets assetsLimit) through a toFiniteNumber()
guard so invalid/wand-generated text becomes undefined instead of NaN.
- list_assets now applies a default page size (100) when no limit is given, so
paging stays bounded and hasMore is meaningful even when limit is omitted.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(dagster): make list_assets hasMore exact via fetch N+1
Address PR review (hasMore true on exact page): request one extra row
(pageSize + 1), use its presence as the authoritative hasMore, slice it off,
and derive the returned cursor from the last RETURNED asset's key path
(JSON-serialized; Dagster normalizes JS/Python whitespace on the way in).
This removes the false-positive hasMore when the final page is exactly full.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(clickhouse): enforce read-only query operation and harden WHERE-clause guard
* fix(dagster): make list_runs hasMore exact via fetch N+1
Address PR review (list runs false hasMore): request one extra row
(pageSize + 1), use its presence as the authoritative hasMore, and slice it
off before mapping. Removes the false-positive hasMore (and misleading cursor)
when the final page is exactly `limit` runs long. Mirrors the list_assets fix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(clickhouse): restrict DROP PARTITION to literal values to prevent SQL injection
* fix(clickhouse): reject chained statements in read-only query operation
* fix(clickhouse): force JSON output on query path and ignore comments when detecting chained statements
* fix(tinybird): encode datasource/pipe names in URL paths to prevent traversal
A user-or-llm datasource/pipe name interpolated raw into the URL path (e.g.
'real_ds/../../other') is normalized by the WHATWG URL parser and can target a
different endpoint. Wrap the path segment with encodeURIComponent in the
truncate, delete, and query_pipe URLs. Events/append pass the name via
URLSearchParams, which already encodes, so they were unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(clickhouse): block WITH-led writes/DDL in read-only query operation
* fix(clickhouse): validate column types structurally and normalize FORMAT around SETTINGS
* fix(clickhouse): balance-check ORDER BY/PARTITION BY and skip leading comments in read-only guard
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
e5a46d7959 | feat(linq): add Linq iMessage/SMS/RCS integration (34 tools, block, attachment upload) (#4831) | ||
|
|
a8f86c0c83 |
fix(security): harden SSO domain registration, webhook path isolation, and CSV export (#4813)
* fix(security): harden KB file access, SSO domain registration, webhook path isolation, env secrets, and CSV export * fix(sso): scope domain conflict query with indexed lower(domain) filter Address PR review: avoid a full-table scan on every SSO provider registration by filtering candidate rows in SQL with lower(domain) = <normalized>, keeping the in-memory ownership check. Also tighten the normalizeSSODomain TSDoc. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: condense env route security comments Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * icons update * chore(security): tighten inline comments in CSV export and KB file authorization Condense verbose comment blocks to concise TSDoc/single-line form; no behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): validate internal serve origin in KB file authorization Replace the bypassable isInternalFileUrl substring check in resolveInternalKbKey with an origin allow-list (base URL, internal API base URL, TRUSTED_ORIGINS). A crafted external host whose path is /api/files/serve/<victim-key> no longer resolves to the victim key. Relative same-origin URLs are unaffected. * style(sso): use idiomatic sql lower() comparison for domain conflict query Match the repo's prevailing `sql`lower(col) = value`` idiom for the case-insensitive SSO domain conflict lookup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): align workspace env admin gate with hasWorkspaceAdminAccess Use the same admin check the secrets UI uses (owner, admin permission, or org-admin) so owners and org-admins are not wrongly denied their own decrypted workspace secrets, while read-only members remain restricted to names only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(sso): rely on lower(domain) match for conflict detection, drop dead in-memory recheck Address PR review: the SQL `lower(domain) = <normalized>` predicate already excludes rows that the in-memory `normalizeSSODomain(...) === domain` recheck claimed to catch, making that recheck dead/misleading code. Match on the canonical lower-cased domain and filter purely by ownership. Malformed legacy values (wildcards, schemes, ports) never match an email domain at sign-in, so excluding them is not a gap. Test DB mock now applies the lower() predicate so the casing-variant case is genuinely exercised. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): scope webhook deploy path conflict to active webhooks findConflictingWebhookPathOwner omitted the isActive filter that the runtime dispatcher (findAllWebhooksForPath) applies, so an inactive but non-archived webhook from another workflow (e.g. after undeploy or failure auto-disable) would permanently block any new deployment on that path even though it never receives deliveries. Align the guard with the runtime isActive + archivedAt filter; the earliest-owner runtime check remains the authoritative cross-tenant protection. Also trims verbose TSDoc on the webhook path-isolation helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): exclude archived workflows from webhook deploy path conflict findConflictingWebhookPathOwner now joins workflow and filters isNull(workflow.archivedAt), matching the runtime dispatcher (findAllWebhooksForPath). A webhook on an archived workflow can never receive deliveries at runtime, so it must not block legitimate path reuse with a 409. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): anchor KB file ownership to earliest document in any state A KB file's owner is now the earliest document referencing its key regardless of state (active/archived/deleted/excluded); access is granted only when that owning document is still active. Closes the residual where an attacker could plant an active document to claim a file whose original document was archived or deleted. * updated greptile icon * revert(security): drop KB file authorization changes Reverts the knowledge-base file-access work (origin-pinning / owner-pinning / origin allow-list in verifyKBFileAccess) and its test. The other hardening fixes (SSO domain registration, webhook path isolation, workspace env secrets, CSV export) are unchanged. apps/sim/app/api/files/authorization.ts is restored to its origin/staging baseline. * fix(sso): treat caller's own user-scoped provider as owned during conflict check Self-hosters often register SSO user-scoped via the CLI script (no SSO_ORGANIZATION_ID). If they later enable organizations and reconfigure the same domain org-scoped through the UI, the conflict check previously treated their own user-scoped row as another tenant's and returned a misleading 409. Recognize the caller's own user-scoped provider as owned so that migration is allowed, while still blocking another user's or another org's domain. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * revert(security): remove workspace-env admin gate Defer to a credential-based access model (separate change). Restores GET /api/workspaces/[id]/environment to main behavior and removes the test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(security): consolidate webhook path-collision check into one helper Extract findConflictingWebhookPathOwner to lib/webhooks/utils.server.ts as the single source of truth for cross-tenant path-collision detection, used by both webhook creation paths (deploy sync and the manual /api/webhooks route). This also repairs two latent issues in the manual route's previous inline check, which queried with limit(1) and only webhook.archivedAt: - limit(1) inspected one arbitrary row, so a same-workflow row could mask a foreign collision (false negative). The shared helper scans all matching rows. - It omitted isActive/workflow.archivedAt, so inactive or archived-workflow webhooks (which never receive deliveries) permanently blocked path reuse. The helper mirrors the runtime dispatcher's filter. Same-workflow webhook reuse for upsert is now a separate, explicit lookup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
c6d500d841 |
fix(icons): repair broken integration icon rendering (#4810)
* fix(icons): repair broken integration icon rendering Two distinct bugs left integration icons broken on the /integrations page (visible at 32-40px, hidden at the toolbar's 16px): 1. Corrupted SVG paths (Notion, Greptile, Granola, Calendly, Grafana, Bedrock): over-minified data dropped elliptical-arc flag digits (e.g. `A1 1 0 5.9 7` instead of `A1 1 0 0 0 5.9 7`); Granola's cubic stream was truncated. Browsers abort path parsing at the first invalid arc flag, so each rendered as a fragment or blank. Replaced with correct path data from canonical sources, preserving each icon's existing fill/gradient and bgColor. 2. Invisible glyph (Bright Data): its icon uses fill='currentColor' but bgColor was '#FFFFFF', and every surface forces text-white on the glyph - white-on-white. Changed bgColor to Bright Data's brand blue (#3d7ffc) so the white glyph reads, matching the white-glyph-on-brand-chip convention. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): restore Calendly dual-tone brand colors Addresses review feedback: the previous fix replaced the broken Calendly icon with a monochrome #006BFF path, dropping the cyan #0ae8f0 accent from the original dual-tone mark. Restored the two-tone logo (blue + cyan) using clean, valid path data, cropped to a tight square viewBox so it fills the chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge icons, fix Zoom contrast and Quiver chip - Zoom: glyph was blue-on-blue (#0B5CFF on #2D8CFF chip); switched to currentColor so it renders as a white glyph on the blue chip. - Quiver: chip bgColor #000000 -> #FFFFFF to match the icon's near-white box, and enlarged the mark slightly (viewBox crop). - Enlarged (tightened viewBox, verified no clipping): RevenueCat, Prospeo, Granola, Firecrawl, Enrich.so, and the AWS icons (RDS, DynamoDB, SQS, CloudFormation, Athena, CloudWatch, SES, Bedrock, S3). - ZoomInfo left unchanged: it is a full red rounded-square logo that already fills its frame, so a crop would clip it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): use Bright Data wordmark on white chip; repair Circleback - Bright Data: replaced the flame glyph with the official two-tone 'bright data' wordmark (provided asset), centered in a symmetric viewBox. Reverted the chip bgColor from #3d7ffc to #FFFFFF since the blue wordmark is invisible on a blue chip (the wordmark is designed for a light background). - Circleback: a minifier had rounded the pattern's image scale to scale(0), collapsing the embedded logo to zero size (invisible). Restored the correct scale (1/280 = 0.00357142857) so the C. mark renders. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(docs): sync Quiver block color card to white chip Reflects the Quiver bgColor change (#000000 -> #FFFFFF) in the docs block info card. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge AWS/Cloudflare/Dagster icons, fully white Zoom - Enlarged (tighter viewBox, render-verified, no clipping): Cloudflare, Dagster, and the red AWS icons AWS IAM, Identity Center, Secrets Manager, SES, STS. Identity Center was anomalously small (filled ~32% of its frame); the group is now sized consistently (~80% fill). - Zoom: the camera lens triangle was still #0B5CFF (blue-on-blue); switched it to currentColor so the whole camera renders white on the blue chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(wiza): consolidate individual reveal into a single operation Merges the separate Start/Get Individual Reveal operations into one Individual Reveal operation in the Wiza docs and integrations data (operationCount 5 -> 4). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): size remaining AWS icons to match the set (~80% fill) Bring RDS, DynamoDB, SQS, CloudFormation, Athena, CloudWatch and S3 up to the same ~80% fill as the AWS IAM/Identity Center/Secrets Manager/SES/STS group, so all AWS icons are visually consistent. Bedrock left as-is (already ~92% fill). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): use Bright Data flame mark, enlarge ZoomInfo - Bright Data: the full 'bright data' wordmark was illegible at chip size. Replaced with just the flame-'i' brand mark (blue #4280f6 on the white chip), centered. - ZoomInfo: cropped the viewBox toward the white 'Zi' so it's larger; the red rounded-square background still fills the chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge CrowdStrike icon The falcon mark sat small in its chip because the icon used a wide 768x500 viewBox (letterboxed in the square chip). Switched to a square viewBox centered on the mark so it fills ~80%, consistent with the other icons. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
e1e773f487 |
feat(slack): add install + privacy section to integration landing page (#4799)
* feat(slack): add install + privacy section to integration landing page Adds a hand-authored, slug-keyed landing-content module (separate from the generated integrations.json so it survives regeneration) and renders an install walkthrough + privacy-policy link on integration pages when present. Also refreshes generated docs (data-enrichment entry, icon mappings, tool mdx). * fix(landing): render privacy section independently, align CTA analytics label * docs(landing): clarify the Slack install button is behind sign-in * refactor(landing): bake integration landing content into generated json via docs-gen Moves landing content (install walkthrough + privacy) out of a render-time augment and into the generation pipeline: generate-docs reads the pure-data content map and writes landingContent into integrations.json, so the page reads a single source (integration.landingContent). Canonical types live in integrations/data/types.ts. |
||
|
|
f2c17d8072 |
feat(integrations): add RB2B integration (#4784)
* make zoominfo icon a bit bigger * feat(integrations): add RB2B integration Add the RB2B AI workspace integration for person-level visitor identification and B2B enrichment via the RB2B API (api.rb2b.com). - 15 tools: credit check, IP to HEM/MAID/company, email/HEM to business profile/best LinkedIn/LinkedIn slug/MAID, email to last active date, and LinkedIn to business profile/best personal email/personal email/hashed emails/mobile phone, plus LinkedIn slug search - Single API-key block with an operation dropdown, conditional inputs, and outputs covering every tool - RB2B icon and generated docs * fix(integrations): address RB2B PR review - email_to_activity now has its own plaintext Email field (canonicalParamId) instead of sharing the Email-or-MD5 input, since it does not accept MD5 hashes - RB2BIcon uses useId() for its clipPath id instead of a hardcoded id, matching the convention used by other icons * fix(integrations): map RB2B email_to_activity input via params, not canonicalParamId The canonical-pair validation test requires canonical members to share the same condition. Replace the cross-operation canonicalParamId reuse with two distinct subblock ids (email for HEM ops, emailAddress for email_to_activity) and a small tools.config.params remap to the email tool param. |