{{ message }}
v0.7.21: tools audits and extensions, appsheet integration, hitl fix#5378
Merged
Conversation
…text (#5353) * fix(mothership): stop inlining full execution traces for the logs context Tagging a run via "Troubleshoot in Chat" (or any @-mention of a logs context) resolved through processExecutionLogFromDb, which materialized the ENTIRE execution trace (every block's input/output, nested tool-call spans) and inlined it directly into the prompt. For any non-trivial run this repeatedly blew the context window, forcing multiple compactions and eventually auto-stopping the agent before it could investigate anything. Every other context resolver in this file already avoids this by sending a lightweight pointer instead of a full inline dump (workflow/blocks/ workflow_block contexts point into the VFS). Logs contexts have no VFS materialization to point at, but the equivalent lightweight mechanism already exists as a tool: query_logs supports incremental disclosure (overview for timing/cost, full for a scoped block's input/output, or pattern to grep the trace) and is already registered for the mothership agent. Now processExecutionLogFromDb sends a compact summary (id, workflow, level, trigger, timing, cost) plus a note pointing the model at query_logs with the executionId, instead of materializing and embedding the trace. Also drops the now-unused executionData column from the select projection, so resolving a logs context no longer fetches a potentially large JSONB blob it never reads. * improvement(mothership): send a bounded block overview instead of a bare tool pointer Follow-up to the previous commit's fix (stop inlining full execution traces). A pure text pointer telling the model to call query_logs made the agent's very first useful action against a tagged run contingent on it noticing and correctly acting on prose in a JSON blob it may only skim — every sibling resolver in this file instead returns a deterministic mechanism (a VFS path) the model reads on demand. There's no VFS materialization for individual execution logs, but the same deterministic signal is available cheaply: toOverview() (the exact projection query_logs's own "overview" view already returns) walks the raw trace spans and produces a compact tree — block name/type/status/ timing/cost, no input or output — without touching large-value refs at all. The summary now includes that tree, so the model can see which block failed on the first turn, and the note narrows to what still requires a tool call: a block's actual input/output/error, or a grep. materializeExecutionData is still called, but it's a no-op for the common inline case (it only unwraps a top-level object-storage pointer for runs whose whole trace was offloaded as one blob) and was needed to reach traceSpans at all for those heavier runs — exactly the runs most worth an overview. A serialized-size cap (mirroring query-logs.ts's own truncation fallback, scaled down since this lands in the prompt unconditionally) drops the overview if a pathological span count pushes it over budget, falling back to the note alone. Extends the tests: the happy path now asserts the overview tree is present and that no raw input/output payload leaks into the serialized summary, plus a new test for the size-cap fallback.
…cs (#5362) - add wandConfig AI-autofill to expense/spend-limit filter subBlocks - surface is_ppro_enabled on get/list transfer tools - surface start_date/end_date/authorization_settings on list_spend_limits to match get_spend_limit
Tool-level get_transfer/list_transfers already returned is_ppro_enabled (confirmed present on Brex's live Transfer schema), but the block's outputs map didn't declare it, so it was unreachable from the workflow UI. Adds it alongside the other transfer output fields.
…et-template tools (#5358) * fix(loops): align integration with live API docs, add suppression + get-template tools - fix list_transactional_emails endpoint URL (was /transactional, now /transactional-emails) - fix response fields to match actual API schema (createdAt/updatedAt, not the never-existent lastUpdated) - add loops_check_contact_suppression, loops_remove_contact_suppression, loops_get_transactional_email tools - wire new tools into block operations, outputs, and registries - alphabetize tools/registry.ts loops entries * fix(loops): expose contactId output, fix stale tool description - add missing contactId block output for check_contact_suppression (Greptile P1) - fix list_transactional_emails description to mention createdAt (Greptile P2) * fix(loops): restore lastUpdated as backwards-compat alias on list_transactional_emails Final validation pass found that /api/v1/transactional (the endpoint this tool used before this PR) is a real, functional, deprecated Loops endpoint whose schema genuinely returns lastUpdated - it was not a broken/invented field. Migrating to /api/v1/transactional-emails is still correct (current endpoint, better error semantics), but dropping lastUpdated would break any existing workflow reading it from this block's output. Keep it as a deprecated alias of updatedAt alongside the new createdAt/updatedAt fields. * fix(loops): update id output description to cover get_transactional_email
…5367) * fix(ahrefs): align tool coverage and outputs with the Ahrefs API v3 - 5 of 8 tools were missing the required `select` param (API v3 rejects list-endpoint requests without it) and 3 sent a `date` param the endpoint doesn't accept - all list endpoints sent an `offset` param that doesn't exist on any Ahrefs v3 site-explorer endpoint (only `limit` is supported) - domain_rating and backlinks_stats read response fields at the wrong nesting level and always returned zeros; several other tools mapped output fields to column names the API doesn't return (position, url, traffic, backlinks, dofollow_backlinks, http_code) instead of the real ones (best_position, best_position_url, sum_traffic, links_to_target, dofollow_links, http_code_target) - keyword_overview used the wrong endpoint param entirely (`keyword` instead of `keywords`) so it always returned empty - added ahrefs_metrics (site-explorer/metrics) and ahrefs_organic_competitors (site-explorer/organic-competitors) tools - fixed docsLink to point at docs.sim.ai instead of ahrefs.com * fix(ahrefs): default metrics country to us like every other tool Greptile and Cursor Bugbot both flagged that ahrefs_metrics omitted the country when unset, unlike every other country-accepting Ahrefs tool, which silently returns global data instead of US data on direct tool calls. * fix(ahrefs): default history to all_time on backlinks and referring domains Cursor Bugbot flagged that history was only sent when explicitly set, even though the block UI defaults it to all_time — same class of gap as the metrics.ts country fix, applied for direct tool-call consistency. * feat(ahrefs): expose search intent flags on keyword overview Adds the real intents field (informational, navigational, commercial, transactional, branded, local) from keywords-explorer/overview, which was verified valid against the live API docs but not yet surfaced.
…s tool; icon/color tweaks (#5356) * fix(algolia): fix serialization-time param mutation, add geo/facet search, task status tool - move all tools.config coercion/remapping out of tool() into a proper params() function so dynamic block references aren't destroyed before variable resolution - wire facets and getRankingInfo into the search tool so those documented outputs are actually reachable - add geo-search (aroundLatLng/aroundRadius/insideBoundingBox/insidePolygon) to search and browse_records, matching delete_by_filter - fix aroundRadius param type (string, not number, since it accepts "all") - sync batch_operations description with the real action set (delete, clear) - consolidate list_indices pagination into the shared page/hitsPerPage fields instead of duplicate listPage/listHitsPerPage - add algolia_get_task_status tool so workflows can poll a taskID instead of guessing when a write is applied - trim indexName/objectID/destination before building request URLs - add ranking-tuning and index-snapshot skills to AlgoliaBlockMeta fix(dropcontact): swap icon to the official wordmark's teal swirl mark, bgColor to match chore(grafana): bgColor to white to match brand tile convention * fix(algolia): register subblock-id migration for listPage/listHitsPerPage CI's subblock-id stability check correctly flagged that consolidating list_indices pagination into the shared page/hitsPerPage fields would silently drop values from already-deployed workflows. Add the rename mapping so existing saved state migrates instead of being lost. * fix(algolia): remove fabricated pendingTask field from get_task_status Algolia's Get Task Status response (additionalProperties: false) only returns `status` (published | notPublished) — pendingTask belongs to the List Indices response, not this endpoint. Drop it from the tool's output, response type, and block outputs rather than inventing data. * fix(algolia): coerce getRankingInfo/createIfNotExists/forwardToReplicas from real booleans, not just strings A wired <Block.output> boolean (e.g. true) failed the `=== 'true'` string-only checks and silently flipped to the wrong value. Add a toBool helper that accepts both the dropdown's string values and a genuine boolean passed in via a dynamic reference. fix(dropcontact): render icon with currentColor instead of hardcoded fill The new teal swirl mark's fill (#0ABA9F) matched the block's bgColor exactly, making the icon invisible on its own tile. Use currentColor and set iconColor so the shared tile-contrast logic (getTileIconColorClass) renders it white-on-teal like the rest of the brand icon system. * fix(algolia): trim indexName in request bodies, not just URL paths Greptile caught that search.ts's body-level indexName (sent inside the multi-query POST body, not URL-encoded) wasn't trimmed like every other tool's URL-path indexName. Fixed there and in get_records.ts's per-request indexName default/override, which had the same gap. * fix(algolia): route list_indices and get_task_status GETs to the -dsn read host Verified against Algolia's official JS client source (getDefaultHosts + transporter isRead = useReadTransporter || method === 'GET'): every GET request routes to the read (-dsn) host, matching the other 14 tools in this integration (get_record, get_settings, etc). Both tools were incorrectly hitting the write host. * chore(algolia): regenerate docs to drop stale pendingTask entry The get_task_status pendingTask output was removed from code in d102129 (fabricated field, not in Algolia's real API response) but docs weren't regenerated at the time, leaving a stale entry. Also syncs the Dropcontact icon's currentColor fill into the docs mirror. * fix(algolia): correct batch_operations body requirement wording Verified against Algolia's actual batchWriteParams schema (specs/common/schemas/Batch.yml): body is a required property on every batch request item, including index-level delete/clear actions — it isn't omittable. The tool's param description previously said to omit it; corrected to say use an empty object instead.
…tch (#5354) * feat(similarweb): add page views tool, fix paid referrals field mismatch - Add similarweb_page_views tool (Total Page Views, Desktop & Mobile) - Fix paidReferrals in website overview: API Lite response key is literally "paid _referrals" (space before underscore), not caught by the existing fallback chain, so it always resolved to null - Move startDate/endDate/mainDomainOnly to advanced mode * fix(similarweb): accept both page_views key spellings in page views response Cursor Bugbot and Greptile both flagged the response field as page_views by convention, but SimilarWeb's own docs example response uses pages_views for this specific endpoint. Accept both spellings defensively so the tool works regardless of which is actually returned.
#5366) * fix(tailscale): align tool coverage and outputs with the Tailscale API - fix list_users profilePicUrl field name (API returns lowercase, was always null) - add nodeId, keyExpiryDisabled, expires to device outputs - quote the If-Match header value on ACL updates per API spec - add set_acl, expire_device_key, suspend_user, delete_user tools - add wandConfig to dnsServers/searchPaths block fields - expand BlockMeta skills/templates for ACL and key-expiry workflows * fix(tailscale): remove phantom magicDNS field from list_dns_nameservers The GET /tailnet/{tailnet}/dns/nameservers response only returns {dns: string[]} per the API spec — magicDNS is not part of this endpoint's response and was always silently false. * fix(tailscale): extend ToolResponse in expire_device_key response type Matches the pattern used by the other new tools in this PR (delete_user, suspend_user). * fix(tailscale): list_auth_keys now returns all tailnet keys GET /tailnet/{tailnet}/keys silently scopes to the caller's own keys unless all=true is passed, contradicting the tool's stated purpose of listing all auth keys in the tailnet.
…nloads (#5365) * fix(onepassword): validate integration against API docs, add file downloads - add onepassword_get_item_file tool + route for downloading item file attachments (SDK items.files.read / Connect files/{id}/content), backed by newly-exposed item.files metadata on get/create/replace/update item - fix update_item JSON Patch applying array indices instead of 1Password's documented field-ID addressing (/fields/{fieldId}/...), which silently dropped field edits in Service Account mode - fix Service Account mode's list-vaults/list-items filter to honor SCIM `eq` exact-match semantics instead of always substring-matching - expand the create-item category dropdown from 9 to 19 real, creatable 1Password categories (was missing SOFTWARE_LICENSE, EMAIL_ACCOUNT, MEMBERSHIP, PASSPORT, REWARD_PROGRAM, DRIVER_LICENSE, BANK_ACCOUNT, MEDICAL_RECORD, OUTDOOR_LICENSE, WIRELESS_ROUTER, SOCIAL_SECURITY_NUMBER) - replace the block's single opaque `response: json` output with typed, per-operation output fields matching repo convention - remove incorrect password-masking on the Vault ID field (not a secret) - re-export tool types from the onepassword barrel * fix(onepassword): honor SCIM attribute name in filter matcher matchesFilter always compared against name/title regardless of the attribute named in the eq expression, so `id eq "..."` incorrectly matched against the display name instead of the id. * fix(onepassword): close output-parity and doc-string gaps from final audit - restore a deprecated no-op 'response' output so pre-existing saved workflows referencing it fail soft (empty) instead of hard-erroring now that per-operation outputs replace it - add missing block outputs (urls, favorite, version, state, lastEditedBy) for get/create/replace/update item so all real FULL_ITEM fields are discoverable as <Block.field> references - hide Connect Server credential fields for Resolve Secret (Service Account only) instead of leaving them selectable and silently ignored - correct two doc-string enum lists that advertised values the API doesn't return (vault type TRANSFER, item state DELETED) * fix(onepassword): fix silent data loss in update_item (Service Account mode) update_item applied user JSON Patch ops (documented/typed against the Connect-shaped vocabulary get_item returns: label/type/section.id) directly onto the raw SDK item, whose vocabulary differs (title/ fieldType/sectionId, and SDK category enum strings vs Connect's SCREAMING_SNAKE_CASE). Most patches beyond /title, /tags/-, and /fields/{id}/value silently no-opped or could corrupt the item while still reporting success. Extracted the Connect->SDK item conversion already used by replace_item into a shared connectItemToSdkItem helper. update_item now normalizes the fetched item to Connect shape, applies patches to that, then converts back before calling items.put() -- matching create/replace's existing translation pattern. Found via an adversarial final-verification pass that traced concrete patch operations by hand against the SDK's actual field vocabulary. * fix(onepassword): preserve field metadata and empty-title fallback connectItemToSdkItem rebuilt every field as a bare object, dropping SDK-only metadata (e.g. password-generation details) that a raw patch/replace previously left untouched. Now merges onto the existing SDK field by id before applying the translated properties, and only starts fields bare when they're genuinely new. Also restored the || (not ??) fallback on title to match replace_item's prior behavior of treating an explicitly empty title as "not provided".
…ics (#5355) * fix(amplitude): validate integration against API docs, add funnels/retention - Fix Identify/Group Identify sending JSON instead of the form-urlencoded body Amplitude requires - Fix Send Event using snake_case product_id/revenue_type instead of Amplitude's camelCase productId/revenueType - Fix Get Revenue parsing a response shape that never matched the real Revenue LTV API - Add EU data residency support across all tools - Add missing filters/formula/segment params to Event Segmentation, groupBy/segment to Active Users and Revenue - Add first_used/last_used to User Activity output, non_active/flow_hidden to List Events output - Add real-time/hourly interval options to Event Segmentation - Add Funnels and Retention tools for conversion and retention analysis - Harden JSON-shape validation across funnels/segmentation/retention (fail loudly on malformed or partial input instead of silently degrading) - Expose every tool output field (user_profile, send_event, user_search) on the block so nothing is unreachable downstream - Update brand colors to current Amplitude guide * fix(amplitude): validate retention brackets, require formula param, add segmentation 2nd group-by - Retention now validates retentionBrackets as a JSON array and requires it when retentionMode is "bracket", matching the block UI's requirement - Event Segmentation now throws if metric is "formula" but no formula is provided, matching the block UI's requirement - Event Segmentation now supports a documented second group-by property via groupBy2/g2 - Corrected Get Active Users' group-by copy — Amplitude's docs don't document a second-property syntax for /api/2/users the way they do for segmentation's g2, so the field no longer overpromises "max two"
* fix(vercel): align integration with live Vercel REST API docs - add missing teamId/slug scoping to 29 tools (deployments, checks, projects, env vars) - add DNS SRV/HTTPS record support (nested srv/https objects) to create/update_dns_record - add decrypt/gitBranch filters to get_env_vars, autoUpdate to rerequest_check - add redirect param to create_alias, comment to create_dns_record - add missing customNameservers/userId/teamId/transferStartedAt fields to list_domains output - wire pagination filters (limit/since/until/search/app) into block subBlocks for list_deployments, list_teams, list_team_members, list_dns_records, list_project_domains - wire previously-unexposed tool params into block UI: withGitRepoInfo, gitSource, forceNew, externalId, rerequestable, output, direction, follow - fix duplicate projectId subBlock id collision between list_deployments and other project-scoped operations - fix teamId scope field incorrectly hidden for check operations * fix(vercel): address review findings on DNS/deployment param handling - fix withGitRepoInfo 'No' dropdown sending withGitRepoInfo=false instead of omitting the param - remove redundant duplicate 'Forward' option from eventsDirection dropdown - fix mxPriority being silently dropped in update_dns_record when record type is left unset * fix(vercel): fix pagination token type mismatch and clarify DNS update UX - fix list_projects nextFrom being stored as a number despite string typing, which threw TypeError on .trim() when chained into a follow-up list_projects call - clarify that the DNS update Value field has no effect on existing SRV/HTTPS records unless Record Type is explicitly reselected * fix(vercel): fix zero-value SRV/HTTPS/MX numeric fields being dropped - SRV weight/port/priority, HTTPS priority, and MX priority use truthy checks that silently drop legitimate 0 values; switch to explicit empty/null checks - add missing MX Priority field to create_dns_record block UI (tool already required it for MX records but there was no way to set it) * fix(vercel): fix stale cross-operation field leaks in block params - fix list_deployments/create_deployment/update_check/list_team_members/update_dns_record/update_env_var conditionally spreading into keys that collide with unrelated operations' non-destructured literal subBlock fields (projectId, deploymentId, target, name, search) - a stale value left over from switching operations in the UI would silently leak into the wrong tool call since the conditional spread only overrides when the current operation's own field has a value - fix now always assigns these keys directly so they deterministically override any stale base value * feat(vercel): close remaining input/output completeness gaps - add missing slug (team-slug) param to 13 domain/DNS/alias tools that were skipped in an earlier fix pass, matching the pattern used everywhere else in this integration - add rootDirectory, nodeVersion, devCommand params to create_project/update_project (verified against Vercel's live OpenAPI spec — high-value fields for monorepo support and runtime pinning) - surface rootDirectory/nodeVersion in get_project/list_projects outputs, since the API already returns them - wire all new fields into the block UI as advanced fields * fix(vercel): fix remaining No->false truthy-string dropdown bugs - checkRerequestable, checkAutoUpdate, envVarsDecrypt dropdowns used id: 'false' for their No option (a truthy non-empty string), causing the conditional spread to always fire and explicitly send false instead of omitting the param - swept the whole file for this pattern; checkBlocking correctly keeps 'false' since it's a required field that's always sent directly, not conditionally * fix(vercel): fix silent project-rename leak in update_project - update_project had no dedicated rename field and just returned base directly, so a stale value from create_deployment's unrelated 'name' subBlock (Project Name for the deployment) could silently flow through and rename a project on update - add a dedicated 'New Project Name' field for update_project, wired with a direct override so it always takes precedence over any stale leaked value
* v0.6.29: login improvements, posthog telemetry (#4026) * feat(posthog): Add tracking on mothership abort (#4023) Co-authored-by: Theodore Li <theo@sim.ai> * fix(login): fix captcha headers for manual login (#4025) * fix(signup): fix turnstile key loading * fix(login): fix captcha header passing * Catch user already exists, remove login form captcha * feat(langsmith): add run update, get run, and feedback tools - add langsmith_update_run (PATCH /runs/{id}) to complete the create-then-patch tracing lifecycle - add langsmith_get_run (GET /runs/{id}) to read a run back - add langsmith_create_feedback (POST /feedback) to attach scores/corrections to runs - wire all three into the LangSmith block, reusing shared subBlocks across operations - fix feedback-capture template to use real feedback API instead of faking it via tagged runs - switch manual Object.fromEntries filtering to filterUndefined per repo convention * fix(langsmith): reject non-numeric feedback score instead of silently sending null Number() on an invalid score string produces NaN, which serializes to JSON null and would still be sent to LangSmith. Throw instead, matching the existing parseJsonValue error pattern. * fix(langsmith): harden error handling and validation on new run tools - update_run, get_run, create_feedback now check response.ok before parsing/returning, matching the cloudwatch/zoom convention instead of silently returning success on a 4xx/404 - block outputs schema now exposes inputs/outputs for Get Run - update_run requires at least one field to patch, matching the batch-ingest guard for post/patch * fix(langsmith): align get_run/update_run outputs and narrow feedback score type - get_run now also outputs runId (alias of id) so workflows can read the run identifier consistently across all operations on the block - update_run now parses and surfaces the response message instead of discarding the body entirely, matching create_run's pattern - narrow LangsmithCreateFeedbackParams.score to number — the tool param is declared as JSON-schema 'number' and the block's parseScore never produces a boolean, so the wider type was dead and misleading * fix(langsmith): reject empty-string patch fields and empty PATCH bodies - block mapper now normalizes blank name/end_time/status/error inputs to undefined instead of forwarding empty strings, which would clear those fields on the LangSmith run - update_run tool now throws if the filtered PATCH body is empty, guarding direct/programmatic tool calls that bypass the block's own "at least one field" check * fix(langsmith): normalize empty-string patch fields at the tool layer too Direct/agent tool calls bypass the block's own emptyToUndefined guard, so update_run now normalizes blank name/end_time/status/error itself before filtering, matching the block-level fix. --------- Co-authored-by: Theodore Li <theodoreqili@gmail.com> Co-authored-by: Siddharth Ganesan <33737564+Sg312@users.noreply.github.com> Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> Co-authored-by: Theodore Li <theo@sim.ai>
…e encoding, add missing endpoints (#5371) * fix(supabase): remove non-functional SQL introspection path, harden storage URL encoding, add missing storage endpoints - introspect.ts no longer attempts raw SQL via a nonexistent PostgREST RPC endpoint (always failed); now uses the OpenAPI-spec path directly with honest heuristic/best-effort documentation for PK/FK/index fields - storage tools now trim + URL-encode bucket/path segments before building request URLs (download, list, get_public_url, create_signed_url, delete_bucket, delete, and the upload API route) - storage_create_signed_url guards against a missing signedURL field in the response instead of silently building a broken URL - add supabase_storage_create_signed_upload_url, supabase_storage_update_bucket, and supabase_storage_empty_bucket tools + block wiring - change insert/upsert `data` param type from 'array' to 'json' to match actual accepted shapes (array or single object) - bump tool versions to semver (1.0 -> 1.0.0) - rewrite a BlockMeta template that implied unsupported Supabase Auth Admin user-provisioning (cherry picked from commit 52b655a) * fix(supabase): address review feedback on update-bucket, signed upload url, and introspect - storage_update_bucket now fetches the bucket's current config first and only overrides isPublic/fileSizeLimit/allowedMimeTypes when the caller explicitly provides them, instead of silently forcing public: false on every update (the Storage API's PUT is a full replace, not a patch) - storage_create_signed_upload_url and storage_empty_bucket now check response.ok before surfacing an error, so a non-2xx response reports Supabase's actual error instead of a misleading parse-side message - introspect.ts drops the spurious ?select=* query param from the OpenAPI spec request (meaningless on the root spec endpoint) (cherry picked from commit 557e407) * fix(supabase): tri-state bucket visibility on update, empty-string param coercion, introspect schema header - introspect.ts now sends Accept-Profile when a schema param is given, matching the convention used by the other DB tools, so schema-scoped introspection actually reads from that schema's spec - storage_update_bucket.ts treats an empty-string param the same as "not provided" (e.g. an untouched file size limit input no longer coerces to 0) - the shared "Public Bucket" dropdown always sent an explicit true/false for storage_update_bucket (its default masked "not touched"), which could still flip a public bucket private; added a dedicated "Keep Current / True / False" control for the update operation so omitting a choice genuinely omits the isPublic override (cherry picked from commit c80567b) * fix(supabase): check response.ok before parsing storage_create_signed_url Matches the pattern already applied to the new signed-upload-url tool this session — a non-2xx response now surfaces Supabase's actual error message instead of the generic "did not return a signed URL path" one. (cherry picked from commit 9f40427) * fix(supabase): correct download param semantics, echoed path field, and schema hint mismatch Found by a second, per-tool parallel validation pass against live Supabase/PostgREST docs and source: - storage_get_public_url.ts and storage_create_signed_url.ts sent download=true literally, which Supabase's Storage API treats as a filename override (renaming the downloaded file to "true") rather than a boolean flag; forcing a download while keeping the original filename requires an empty download= value - storage_create_signed_url.ts also sent download in the POST body, which the sign endpoint ignores entirely — forcing download only works as a query param on the returned URL - storage_create_signed_upload_url.ts read a `path` field from the API response that doesn't exist there; it now echoes the caller-supplied path, matching the official storage-js client - introspect.ts's nullable heuristic didn't disclose that a NOT NULL column with a default is misreported as nullable (PostgREST omits it from the OpenAPI required list in that case); documented alongside the other already-disclosed heuristics, and removed a tautological schema-filter check left over from an earlier revision - insert.ts/upsert.ts's `data` param reverted from 'json' back to 'array': the 'json' type mapped to an LLM-facing JSON-schema type of 'object', which contradicted the param's own description ("array of objects or a single object")
…wnload tools (#5369) * feat(sharepoint): validate against Graph API and add delete/update/download tools - Fix bugs found validating existing tools against live Graph docs: malformed nested $expand syntax in get_list, reversed site-resolution precedence in create_list, unsanitized field fallback in add_list_items, missing URL encoding in read_page, and an incorrect root/serverRelativeUrl field shape - Fix V1 block gaps vs V2: upload_file required flag, missing required on pageName/listDisplayName, wrong site-picker mimeType, dead subBlock refs - Add 8 new tools within already-granted scopes for CRUD completion: delete_list_item, get_list_item, delete_page, update_page, publish_page, download_file, delete_file, get_drive_item - Add opt-in stripAuthOnRedirect option to secureFetchWithPinnedIP so the SharePoint file-download route doesn't resend the bearer token to the preauthenticated redirect target (default off, no behavior change elsewhere) - Dedupe read-only list-item field sanitization into a shared utils helper * fix(sharepoint): encode siteId consistently and fix create_page precedence - URL-encode siteId/groupId everywhere it's interpolated into a Graph request path (Graph site IDs like "host,guid,guid" contain commas that must be encoded) - addresses Cursor Bugbot findings on update_page, delete_page, publish_page, and applies the same fix consistently across every other sharepoint tool for consistency - Fix create_page's site-resolution precedence (was siteSelector before siteId, inconsistent with every sibling tool) * fix(sharepoint): escape HTML in page content and stop fallback from throwing - create_page/update_page only escaped quotes when building innerHtml; add a shared escapeHtml() helper that also escapes &, <, > so page content with angle brackets/ampersands doesn't corrupt the canvas layout - add_list_items' fields fallback (sanitized re-derivation when Graph's response omits fields) could throw on a malformed fallback input after the item was already created successfully; catch and fall back to undefined instead of failing an already-successful response * fix(sharepoint): scope columnDefinitions->pageContent mapping to create_list Both V1 and V2 tools.config.params mapped columnDefinitions onto pageContent whenever columnDefinitions was truthy, with no operation check. Stale list-column JSON left in block state after switching to create_page/ update_page would silently replace the user's intended page text. Gate the mapping on operation === create_list (V1) / sharepoint_create_list (V2). * fix(sharepoint): cap download-file content fetch at MAX_FILE_SIZE Greptile flagged the content fetch as unbounded - a large file would buffer entirely in memory before base64-encoding into the JSON response. Pass maxResponseBytes: MAX_FILE_SIZE (100MB, same constant used by the upload path) to secureFetchWithPinnedIP so oversized files reject early with a clear PayloadSizeLimitError instead of exhausting memory. * fix(sharepoint): close V1 block input/output gaps and encode upload URLs Final validation pass (4 parallel audit agents against live Graph docs) surfaced remaining gaps: - apps/sim/app/api/tools/sharepoint/upload/route.ts: siteId/driveId were not encodeURIComponent-ed in the Graph upload URL, unlike every other sharepoint route/tool - same encoding-gap class fixed everywhere else - read_page.ts: transformResponse recomputed siteId with a raw `||` in 3 spots instead of the optionalTrim(...) || optionalTrim(...) || 'root' precedence used by request.url and every sibling tool - SharepointBlock (V1, legacy/hidden-from-toolbar but still executable for existing saved workflows): listItemFields and listItemId were missing `required` for update_list despite the tool requiring them; maxPages/groupId/includeColumns/includeItems/nextPageUrl subBlocks were entirely absent, making those tool params unreachable from the UI; block-level outputs were missing site/pages/content/totalPages/ nextPageUrl/lists/skippedFiles/skippedCount/errors even though the underlying tools return them - V2 already covered all of these
Fixes GHSA-fgmj-fm8m-jvvx / CVE-2026-45249 — Lines series tooltip rendering could execute raw HTML from series.data[i].name when no custom tooltip.formatter is set.
…n, and security tools (#5364) * feat(clerk): expand Clerk integration with org, membership, moderation, and security tools - fix 4 validate-integration warnings: missing .trim() on org/session IDs, incomplete session-status dropdown, missing list_users/list_organizations filter subBlocks - add organization update/delete tools - add organization membership CRUD (list, add, update role, remove) - add organization invitation create/list - add user ban/unban/lock/unlock and OAuth access token retrieval - add allowlist/blocklist identifier management - add JWT template list/get - add actor token create/revoke (impersonation) - add matching webhook triggers for session ended/removed/revoked, organization updated/deleted, and membership updated/deleted - wire all 23 new tools into the block, tool registry, and trigger registry * fix(clerk): I/O completeness fixes from final validation pass - remove dead limit/offset params from list_blocklist_identifiers (Clerk API accepts zero params on this endpoint, verified across 6 spec versions) - expose publicMetadata on OAuth access token output (was silently dropped) - expose inviter email/first/last name (public_inviter_data) on organization invitation create/list outputs - add missing orderBy param to list_organization_invitations
…ead-field bugs (#5360) * feat(wordpress): add category/tag CRUD tools, fix delete-status and dead-field bugs - Add wordpress_{get,update,delete}_category and _tag tools for full taxonomy parity - Fix `deleted: data.deleted || true` always evaluating true across all 6 delete tools (posts/pages/media/comments/categories/tags) - Remove dead `force` param from delete_media (endpoint always force-deletes; param had zero effect) - Remove unwired `hideEmpty` block input - Normalize search_content perPage/page visibility to user-or-llm for consistency * fix(wordpress): use ?? instead of || for zero-valued numeric fields in delete_category/tag count and parent can legitimately be 0 (empty term, top-level category); || was dropping those values, same antipattern already fixed for `deleted` in this PR. Flagged independently by Greptile and Cursor Bugbot. * fix(wordpress): use ?? for zero-valued numeric fields across all delete tools Same || antipattern already fixed for category/tag delete tools was still present in delete_post/page/comment/media for id, author, featured_media, menu_order, parent, post — all legitimately 0 in common cases (no featured image, top-level page/comment). Found by a final independent validation pass. * fix(wordpress): don't drop categoryParent=0 (root-level category) in block param mapping Truthy check on params.categoryParent treated a resolved numeric 0 (root-level, no parent) as unset. Flagged by Cursor Bugbot on create_category/update_category. * fix(wordpress): don't clear category/tag description on update when field left blank description used !== undefined (numeric-field convention) instead of a truthy check (string-field convention used everywhere else in this codebase, e.g. update_post/update_page excerpt), so an untouched empty description field silently wiped existing text on every update. Flagged by Cursor Bugbot. * fix(wordpress): fix search type/subtype mislabeling, complete I/O exposure gaps - search_content.ts: type param was mislabeled with subtype's vocabulary (post/page/attachment); real WP type enum is post/term/post-format. Rewired the block's Content Type dropdown to map to subtype (which is what post/page/attachment actually filter), not type. - Widened subBlock conditions so params already read by tools.config.params are actually reachable in the UI: commentPostId for list_comments, categories/tags for list_posts, parent for list_pages. - Added missing subBlocks for tool params with no UI path: comment parent/authorName/authorEmail/authorUrl (create_comment), media description (upload_media), author filter (list_posts). - Extended the ?? / !== undefined fix (already applied to categoryParent) to the same class of param across the block: featuredMedia, page parent, menuOrder, and the new commentParent/listAuthor mappings. - Fixed featuredMedia/parent truthy-check inconsistency in create_post, update_post, create_page, update_page, create_category, create_comment body builders to match the !== undefined convention used elsewhere. Found by an independent final validation pass across 3 parallel agents. * fix(wordpress): keep searchType subBlock id to preserve saved-workflow compat The type/subtype fix should only change which API param the field feeds (subtype, not type) — renaming the subBlock id to searchSubtype broke already-saved workflows with a search content-type filter set, since the block would stop reading the old searchType key. Reverted the id rename, kept the underlying subtype mapping fix. Flagged by Cursor Bugbot. * fix(wordpress): remove invalid Attachment search subtype, fix listAuthor input type - Search Content's "Content Type" dropdown offered Attachment, which maps to subtype=attachment. WP core's WP_REST_Post_Search_Handler explicitly excludes attachment from valid subtypes (media isn't searchable via /search) — selecting it guaranteed a 400 rest_invalid_param. Removed the option; only Post/Page (the only valid subtypes) remain. - listAuthor was declared type: 'string' in the inputs catalog despite being Number()-coerced before use, inconsistent with every other ID-like field (postId, pageId, categoryId, commentParent, etc. are all 'number'). Found by an independent final pre-merge validation pass, requested before merge to be certain of full API alignment.
* feat(trello): expand tool coverage and fix API gaps - add delete card, remove label/member, update list, add/update checklist item, list members, and search tools - add filter support to list lists/cards, since/before paging to get actions, member assignment on card creation - promote move-to-list field out of advanced mode * fix(trello): address review feedback on checklist item tooling - idChecklist can be absent on Trello checkItem responses, so stop treating it as required - validate state/name is provided before building the update-checklist-item request URL - reject Update Checklist Item at the block level when neither State nor New Item Name is set - add missing idOrganization field to search's board output schema
…ion/wandConfig consistency (#5361) * improvement(gong): tighten pagination optionality and add wandConfig to ID list fields - mark cursor output optional:true on aggregate_activity, interaction_stats, list_flows for consistency with list_calls - add wandConfig to comma-separated ID fields (callIds, primaryUserIds, userIds, scorecardIds, reviewedUserIds) matching repo convention for CSV inputs * fix(gong): request context data for get_extensive_calls contentSelector.context/contextTiming were never set on the /v2/calls/extensive request, so the documented context (CRM/external-system links) output was silently always empty even though the field is declared in the tool's outputs. * feat(gong): add data privacy erase and Engage flow prospect tools - gong_purge_email_address / gong_purge_phone_number: POST /v2/data-privacy/erase-data-for-*, the write-half pairing with the existing lookup_email/lookup_phone read tools - gong_assign_flow_prospects: POST /v2/flows/prospects/assign, enrolls CRM prospects into an Engage flow - gong_get_prospect_flows: POST /v2/flows/prospects, looks up which flows a prospect is in Field names verified against an OpenAPI-generator-produced client (cedricziel/gong-rs) whose serde rename attributes mirror Gong's published spec, since Gong's interactive Swagger docs require an authenticated session and can't be fetched directly. * fix(gong): require human-entered target for data-erase tools emailAddress/phoneNumber on the purge tools were user-or-llm, letting an agent autonomously pick the erasure target for an irreversible operation with no human confirmation. Match the user-only visibility already used for credentials.
…84 (#5375) The pinned totalRoutes/zodRoutes baseline (883) went stale after a legitimate new Zod-contract-compliant route merged without the required ratchet bump, breaking check:api-validation:strict on staging HEAD itself. Actual count is 884 total / 884 zod / 0 non-zod routes — a pure headcount update, no policy violation.
…ilters (#5359) * feat(fathom): add list meeting types tool and missing list-meetings filters - Add fathom_list_meeting_types tool (GET /meeting_types) - Add missing list-meetings params: includeHighlights, meetingType, calendarInviteesDomains, calendarInviteesDomainsType - Add missing meeting response fields: meeting_type, meeting_url, shared_with, highlights - Wire new operation and filters into the Fathom block * fix(fathom): expose meeting_url/highlights in outputs, stop force-sending domain type default - Add meeting_url and highlights to list_meetings outputs schema so they're addressable from downstream blocks (Greptile P1) - Drop the forced 'all' default on calendarInviteesDomainsType so the filter is only sent when a user explicitly picks a value (Greptile P2) * fix(fathom): never send calendar_invitees_domains_type=all to the API Match the existing Fathom connector's guard (meetingType !== 'all') so the request omits the param entirely when the value is the API's own default, regardless of what the dropdown shows selected in the UI. * fix(fathom): fully expose list_meetings meeting fields in outputs schema transformResponse already returned meeting_title, scheduled/recording times, recorded_by, calendar_invitees, default_summary, transcript, action_items, and crm_matches, but outputs.meetings.items.properties only documented a curated subset, leaving these fields unaddressable from downstream workflow blocks. Complete the schema to match the full Meeting object Fathom's API returns. * fix(fathom): mark recording_id optional in list_meetings outputs transformResponse maps recording_id as meeting.recording_id ?? null and the response type already types it number | null; the outputs schema now reflects that nullability. * fix(fathom): mark calendar_invitees email optional in list_meetings outputs Fathom's docs mark Invitee.email as nullable; the outputs schema now reflects that instead of declaring it as always-present.
#5372) * feat(hex): expand API coverage, fix ID trimming, add cursor pagination - Add hex_update_collection, hex_create_group, hex_update_group, hex_delete_group, hex_deactivate_user tools + block wiring - Add missing run_project fields (viewId, notifications) and get_project_runs runTriggerFilter - Add after/before cursor pagination to list_projects, list_groups, list_data_connections, list_collections - Add .trim() on all interpolated ID path params to guard against copy-paste whitespace * fix(hex): guard JSON.parse on user-supplied array/object params Wrap JSON.parse calls for memberUserIds, addUserIds, removeUserIds, inputParams, and notifications in try/catch so malformed input throws a clear error instead of an opaque parse exception. * fix(hex): forward empty collection description on update update_collection's params() mapping only copied collectionDescription when truthy, so clearing it to an empty string in the UI never reached the API. Untouched fields resolve to null (not undefined), so use a loose null check to distinguish "cleared" from "never touched" without sending description: null on every unrelated update. * fix(hex): close remaining API coverage gaps found via raw OpenAPI spec Pulled Hex's actual OpenAPI spec (static.hex.site/openapi.json) as ground truth for a final verification pass: - list_users was missing after/before cursor pagination and the userIds filter, which the spec confirms it supports (an earlier doc-summary pass had incorrectly flagged this as unverifiable) - list_users response also exposes lastLoginDate per user, not previously surfaced - list_projects was missing includeComponents, includeTrashed, creatorEmail, ownerEmail, collectionId, categories, sortBy, and sortDirection filters that the spec confirms are real query params * fix(hex): trim remaining user-suppliable IDs for consistency Trim collectionId (list_projects filter), viewId (run_project body), and group member UUIDs (create_group/update_group) to match the .trim() convention already applied to path-segment IDs elsewhere. * fix(hex): validate parsed JSON is actually an array before iterating categories, memberUserIds, addUserIds, and removeUserIds could parse as valid JSON that isn't an array (e.g. an object), which would throw an opaque "not iterable"/"map is not a function" error deeper in the call. Validate Array.isArray after parsing and fail with a clear message instead. * fix(hex): validate array element types, send explicit ALL trigger filter - notifications now gets the same Array.isArray guard already applied to categories/memberUserIds/addUserIds/removeUserIds - member/category array elements are now validated as strings before .trim()/append, instead of crashing on non-string entries - runTriggerFilter "All" option now sends the documented ALL enum value explicitly instead of relying on omission
…put typing (#5368) * fix(sendgrid): fix active field coercion, add pagination, tighten output typing - Fix active field for create_template_version being sent as the string "true"/"false" instead of the SendGrid-required int 0/1 - Add missing authMode: ApiKey on SendGridBlock - Add pageToken/nextPageToken pagination support to list_templates and list_all_lists (SendGrid page_token cursor, parsed from _metadata.next) - Fix nullable output fields to use ?? null / ?? [] with optional: true across get_contact, search_contacts, remove_contacts_from_list, create_template_version, add_contact, send_mail - Remove dead data.templates fallback in list_templates (API only ever returns result) - Remove unused UpdateContactParams/UpdateListParams/UpdateTemplateParams dead types; make CreateTemplateParams.generation optional to match actual tool behavior * fix(sendgrid): address Cursor Bugbot findings on pagination and active coercion - Gate listPageToken/templatePageToken remap on operation so a stale token from the other list operation can't override the intended one - Fix active coercion to also treat a real boolean true (from a dynamic <Block.output> reference) as active, not just the dropdown string 'true' * fix(sendgrid): coerce active to int at the tool layer too Per Greptile: the block-level active coercion only covered the UI path. A direct sendgrid_create_template_version tool invocation with a boolean active would still send a raw boolean to SendGrid. Coerce to 0/1 in the tool's own request body so both paths are correct. * fix(sendgrid): always send page_size on list_templates SendGrid's GET /v3/templates requires page_size on every request (no server-side default) — omitting it errors. Default to 20 to match our own documented default when the caller doesn't set one. * fix(sendgrid): explicit false/'false' check for active flag Per Cursor Bugbot: params.active ? 1 : 0 treated any truthy string (including "false") as active. Extracted a toActiveFlag helper that only treats real false or the string 'false' as inactive, everything else (including unset) defaults to active — matches the tool's documented default. * fix(sendgrid): handle numeric 0 in toActiveFlag Per Greptile: the block coerces active to a number (0/1) before calling the tool, but toActiveFlag only checked for false/'false', so the block's inactive selection (0) fell through to the "active" branch. Check against an explicit inactive-values set covering the boolean, string, and numeric forms. * fix(sendgrid): nest add_contact custom fields under custom_fields Pre-existing bug (predates this PR): custom fields were merged onto the contact object as top-level sibling keys via safeAssign/Object.assign, but SendGrid's PUT /v3/marketing/contacts requires them nested under a custom_fields object. SendGrid silently drops unrecognized top-level keys, so the documented customFields param never actually reached SendGrid. Caught during a final adversarial re-verification pass before merge. * fix(sendgrid): document consistent page_size requirement for list_templates pagination Per Cursor Bugbot: list_templates always defaults page_size to 20 when unset (required by SendGrid), so a follow-up pageToken-only call after a first call with a larger pageSize would silently shrink to 20 and desync page boundaries. This is inherent to a stateless tool call (SendGrid requires page_size on every request, and the tool has no way to remember the prior call's value), so clarify via param description and UI placeholder that callers must repeat the same pageSize across paginated calls. * chore(api-validation): bump stale route-count ratchet baseline 883->884 Unrelated to the SendGrid work in this branch. staging's own HEAD already has 884 compliant Zod-backed API routes (0 non-Zod), but this ratchet baseline was never bumped when that route landed, so any PR rebasing onto current staging fails check:api-validation:strict with "route count increased from 883 to 884". All routes remain fully Zod-backed; this is a mechanical counter update, not a policy change. * fix(sendgrid): dedupe active coercion between block and tool Per Cursor Bugbot: the block's pre-coercion only recognized the dropdown string 'true' or boolean true as active, so a dynamic reference producing numeric 1 or string '1' fell through to 0 and silently created an inactive template version. Exported the tool's toActiveFlag and reused it in the block instead of duplicating the inactive-value logic, so both layers can no longer drift out of sync.
…potency (#5377) - verifyAuth now rejects with 401 when no token is configured instead of silently allowing unauthenticated requests through - formatInput falls back to the legacy formId providerConfig key (pre-#3141 rename to triggerFormId) so old deployments keep working - add extractIdempotencyId keyed on formId:responseId to dedupe retried Apps Script deliveries
* feat(google-appsheet): add Google AppSheet integration
- 4 tools (find/add/edit/delete rows) against the AppSheet Action API
- API key auth via Application Access Key (no OAuth/scopes needed)
- Block with operation dropdown, region selector, and Selector expression support
- Generated docs
* improvement(google-appsheet): harden response parsing, add wand config and skills
- Guard against empty/non-JSON AppSheet response bodies (Delete may return no body)
- Add wandConfig to the Selector field for AI-assisted expression generation
- Add 3 skills grounded in attested AppSheet/Zapier automation patterns
- Tighten json output descriptions to describe inner shape
* fix(google-appsheet): validate region against allow-list, encode appId, validate rows shape
- Reject unrecognized region values instead of interpolating them into the
request host (a caller could otherwise redirect the Application Access
Key to an arbitrary domain)
- URL-encode appId, not just tableName, in the Action endpoint path
- Reject non-array Rows input in tools.config.params instead of forwarding
a single object to the AppSheet Action API
- Drop the mismatched json-object generationType on the rows wand config
(that enricher appends "must start with { and end with }", which
conflicts with the JSON-array shape the field expects)
- Add utils.test.ts covering region validation and response-body parsing
* docs(google-appsheet): add manual intro/getting-started section
Match the MANUAL-CONTENT convention used by other integration docs
(Airtable, Ahrefs, Google PageSpeed) — an overview of the service, what
the Sim integration lets agents do, and how to get an Application
Access Key.
* docs: sync generated integration docs with current source
Regenerate docs for integrations whose tools/blocks changed upstream
without a matching docs regen (ahrefs, algolia, amplitude, brex, clerk,
gong, hex, langsmith, loops, onepassword, sendgrid, sharepoint,
similarweb, supabase, tailscale, trello, vercel, wordpress), plus the
integrations.json catalog.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
* improvement(forking): fork time ux * add storage quota * address comments * merge latest staging * address comments
…sume page (#5381) * fix(resume): fix click-blocking footer overlay + hardening on HITL resume page - SupportFooter rendered position:absolute with no space reserved for it in InterfacesShell/AuthShell/file-share auth gate, silently overlapping and eating clicks on whatever content ended up in its ~50px footprint (on the resume page, the Resume Execution button itself) - Applied the same fix to /invite and /f/[token], which shared the identical absolute-positioning pattern - handleResume no longer fails silently on validation errors or unexpected exceptions - getPauseContextDetail no longer duplicates a pause point's full response payload in the same API response - Oversized HITL display-data values are now truncated in the resume page preview instead of rendering unbounded * fix(resume): use consistent string for truncation-notice length The object-branch truncation notice sliced from the prettified JSON.stringify(value, null, 2) but reported the total against the compact JSON.stringify(value).length, which could show a nonsensical "5,000 of 4,800 characters shown" when the compact form is shorter than the prettified slice. Derive both from the same string. * fix(resume): show em dash for empty-string display data values renderStructuredValuePreview only treated null/undefined as empty; an empty string fell through to the plain-text branch and rendered as a bordered, padded, contentless pill that reads as a stray UI element (e.g. an unstyled toggle) in the Display Data table.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

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