Commit Graph
622 Commits
Author SHA1 Message Date
WaleedandClaude Opus 4.8 20a8d85e15 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>
2026-05-30 18:53:29 -07:00
WaleedandClaude Opus 4.8 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>
2026-05-30 17:35:48 -07:00
WaleedandClaude Opus 4.8 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>
2026-05-30 11:44:05 -07:00
Waleed 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.
2026-05-29 16:33:30 -07:00
Vikhyath Mondreti 4b0dab4682 chore(copilot): deprecate mcp server (#4797)
* chore(copilot): deprecate mcp

* update error codes

* deprecate copilot api v1 route
2026-05-29 14:34:15 -07:00
Theodore LiandClaude Opus 4.7 7f24ae12fd feat(block): Add data enrichment block (#4774)
* feat(enrichment): workflow Enrichment block + /api/tools/enrichment/run

Add a generic Enrichment workflow block that runs a code-defined enrichment
(Work Email, Phone Number, Company Domain, Company Info, …) and returns its
outputs — usable in workflows, not just tables.

- New internal endpoint POST /api/tools/enrichment/run (checkInternalAuth +
  contract) runs the same runEnrichment provider cascade; injects the
  workspace's hosted/BYOK key via executeTool.
- New tool enrichment_run posts to it and surfaces hosted-key cost on the
  output so the workflow logging session bills it.
- New block blocks/blocks/enrichment.ts generated from the enrichment registry:
  operation dropdown = enrichments, per-enrichment conditional inputs, union of
  conditional outputs. New registry entries appear automatically.
- EnrichmentRunContext.tableId/rowId made optional (workflow path has no row).
- Register tool + block; bump api-validation route baseline; add EnrichmentIcon
  and generated docs page.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: re-trigger CI

* refactor(enrichment): share mapFieldType helper between block and tool

* fix(enrichment): reserved output keys (matched/provider) win over enrichment outputs

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 22:19:08 -04:00
Waleed 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.
2026-05-28 18:04:55 -07:00
WaleedandClaude Opus 4.8 c898e2e623 feat(integrations): add ZoomInfo, align Wiza, audit Apollo, refresh docs (#4776)
* feat(integrations): add ZoomInfo, align Wiza, audit Apollo, refresh docs

- Add ZoomInfo integration: search/enrich contacts & companies, intent, news (6 tools), proxy route, block, and icon
- Validate and align Wiza tools/block/outputs against live API docs
- Audit Apollo tools: tighten params, outputs, and types
- Update tool docs (.mdx), icons, icon mappings, and integrations.json

* fix(zoominfo): use useId for ZoomInfoIcon clipPath to avoid duplicate DOM ids

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(apollo): address PR review on sequence add and bulk enrich

- sequence_add_contacts: send large contact_ids/label_names arrays in the
  POST body (Rails merges query + body params) to avoid reverse-proxy URL
  length limits; keep scalar settings in the query string
- organization_bulk_enrich: add back-compat shim mapping the legacy
  `organizations` ({name, domain}[]) subBlock value to the new `domains`
  string array so saved workflows keep running

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(integrations): unique ZoomInfo icon clip id, numeric employee range filters

- ZoomInfoIcon: derive clipPath id from useId() so multiple instances don't collide
- ZoomInfo company search: send employeeRangeMin/Max as numbers, matching revenueMin/Max

* fix(zoominfo): send employeeRange filters as strings per API schema

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(zoominfo): send contactAccuracyScoreMin as string per Contacts Search schema

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(apollo): harden people_search pagination, correct bulk-update output docs

- people_search: read pagination from both the nested `pagination` object
  (legacy /mixed_people/search) and top-level fields, avoiding silent
  fallback to defaults
- account_bulk_update: correct output descriptions — accounts support up to
  1000 per request and async is opt-in (not auto-triggered at 100 like contacts)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(wiza): correct company enrichment credits shape in output docs

Company enrichment returns api_credits { total, company_credits }, not the email/phone/scrape breakdown used by individual reveals. Description-only fix verified against docs.wiza.co.

* fix(apollo): send sequence add contact_ids/label_names as query params per docs

Apollo documents every field for emailer_campaigns/:id/add_contact_ids as a query parameter with no request body. Append contact_ids[]/label_names[] to the query string instead of the JSON body to match the documented contract.

* feat(apollo): expose account_stage_id uniform field for bulk update accounts

Apollo documents account_stage_id as a Body Param for /accounts/bulk_update ('when using account_ids, apply this account stage to all accounts'). Adds it to the tool params, body builder, type, block subBlock, and params mapper alongside name/owner_id.

* docs(apollo): correct contact_update typed_custom_fields description

Apollo's update-a-contact endpoint documents typed_custom_fields, so drop
the inaccurate "not officially documented" caveat.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(zoominfo): default required outputFields on enrich; parse nested API error object

- ZoomInfo enrich endpoints require outputFields; send a curated default set when omitted so requests don't fail
- extractZoomInfoError now reads the GTM REST nested error object ({error:{code,message}}) instead of dropping it to a generic HTTP message

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* improvement(wiza): add wandConfig to complex prospect-search filter fields

Adds AI-assist wandConfig (json-object) with format examples to the structured filter inputs (job_title, job_company, past_company, company_industry, location, company_location) and the full filters object, completing the wandConfig checklist item for the Wiza block.

* fix(findymail): surface API .error messages and alphabetize registry

- transformResponse error branches now fall back to the response body's
  `error` field before the generic status string, so Findymail's actual
  messages ("Not enough credits" on 402, "Subscription is paused" on 423,
  "One identifier is required..." on 422) reach the user instead of a
  bare "Findymail API error: <status>". Applied to all 11 tools.
- alphabetize the findymail entries in tools/registry.ts to match the
  already-alphabetical import block and the integration guideline.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-28 15:30:25 -07:00
Vikhyath Mondreti 28766ddaa9 feat(instantly): block, trigger (#4763)
* feat(instantly): block, trigger

* change bg color for icon

* address comments

* cleanup code

* search param missplaced
2026-05-27 16:36:21 -07:00
Vikhyath Mondreti 4fab03c595 improvement(media-gen): retire vision block, add hosted key for fal ai for image/video gen, search visibility in cmd-k (#4684)
* improvement(media-gen): retire vision block, add hosted key for fal ai for image/video gen

* address comments
2026-05-23 12:54:14 -07:00
Waleed 952eb1216f feat(mailer): add AWS SES and SMTP providers with auto-detect fallback (#4710)
* feat(mailer): add AWS SES and SMTP providers with auto-detect fallback

* fix(mailer): cast SES options to bridge duplicate @aws-sdk type identities

* fix(mailer): dedupe aws-sdk-sesv2, address review feedback

- Force a single @aws-sdk/client-sesv2 install via root package.json overrides; @types/nodemailer pulled in a nested copy whose nominal class brand made the two SDK type identities incompatible, breaking the CI build. With one install the cast disappears.
- Batch result message now reports successCount instead of sendable.length when entries are skipped, so "5 emails sent" no longer overstates delivery on partial failures.
- SMTP provider now warns when SMTP_HOST is set without SMTP_PORT, and when only one of SMTP_USER/SMTP_PASS is set — both previously silent misconfigurations.
- SMTP_SECURE schema is z.boolean() to match every other boolean in env.ts; runtime parsing is still handled by envBoolean.
- Strip the verbose TSDoc comments I had added.

* fix(mailer): exact sent counts in batch results, restore SES type cast

- mergeBatchResults: data.count and the message now report only emails that were actually delivered, not skipped-unsubscribed ones (they returned success: true and inflated the count). Empty-sendable branch distinguishes "all unsubscribed" from "mixed skip/failure" so the message stops lying when some entries fail validation.
- ses.ts: revert the package.json override approach (bun honors it locally but CI still installs a nested @types/nodemailer copy). Reinstate the `as unknown as` cast with a single-line WHY comment.

* fix(mailer): annotate double-cast in ses provider for strict api-validation

* fix(mailer): batch degrades isUnsubscribed errors to per-entry failures

A transient DB error in isUnsubscribed used to abort the whole batch
because the call sat outside the per-email try/catch in prepareBatch.
Wrap the unsubscribe check inside the same catch so a rejection becomes
a per-recipient failure, matching sendEmail's behavior. Lock it in
with a regression test.
2026-05-21 19:27:33 -07:00
Waleed 21c956cf97 improvement(hubspot): OAuth-native polling trigger replacing webhook flow (#4705)
* improvement(hubspot): OAuth-native polling trigger replacing webhook flow

* feat(hubspot): property autocomplete, multi-filter, property-changed, list-membership, pipeline/owner dropdowns

* fix(hubspot): freeze cursor on failure + request full OAuth scopes

* chore(api): bump API route baseline from 749 to 753 for HubSpot selector routes

* fix(hubspot): make eventType required conditional on visibility

* improvement(hubspot): align trigger name and longDescription with poll-trigger conventions

* fix(hubspot): encodeURIComponent on search path segment for defense-in-depth

* fix(hubspot): cursor-based seed for list_membership polling

* fix(hubspot): Map-backed property snapshot + drop redundant filter parse
2026-05-21 17:25:19 -07:00
Vikhyath Mondreti 974a18dd61 improvement(media-blocks): new versions of image and video gen with latest models + fixes (#4667)
* improvement(media-blocks): new versions of image and video gen with latest models + fixes

* respect versioning for icons

* fix integration routes

* address comments

* address api mismatches

* more ltx 2.3 durations

* typing tightness
2026-05-19 16:42:04 -07:00
Waleed 6c755cbb59 feat(integrations): add Gong incident.io Railway and New Relic (#4663)
* feat(integrations): add Gong incident.io Railway and New Relic

* fix(railway): preserve explicit empty variable values

* fix(incidentio): fail on invalid workflow JSON

* fix(new-relic): validate custom attributes JSON

* fix(integrations): address incident workflow review fixes

* chore(docs): apply lint formatting

* chore: refresh integration docs and validation fixes

* more

* fix(integrations): address PR review comments

* fix(gong): align list calls block validation
2026-05-19 14:12:28 -07:00
df1e2ddc2e feat(azure-devops): block and trigger (#4664)
* azure devops logo on white

* generated ADO tool docs

* generated ADO tool docs

* added ADO to registries

* ADO workflow triggers

* ADO workflow triggers

* tool layer for ADO, checks passed and manual verified

* ADO workflow triggers

* block layer for ADO

* ADO icon svg

* generated docs for ADO triggers

* committing the tests for azure devops tools and blocks

* Update apps/sim/triggers/azure_devops/utils.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Update apps/sim/tools/azure_devops/update_work_item.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Update apps/sim/triggers/azure_devops/utils.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* comma syntax error patched

* azure devops: validate-integration fixes + manual description

- bgColor switched from white to Azure DevOps brand color #0078D4 (block + mdx)
- WIQL query_work_items: hydrate ALL matched IDs by chunking through batches
  of 200 instead of silently truncating; check response.ok on the follow-up
  fetch and surface a clear error on 4xx/5xx; trim org/project; expose
  totalMatched in metadata so users can see pre-hydration count
- Add MANUAL-CONTENT-START:intro section to the azure_devops.mdx docs page
- Update unit tests for new chunking behavior and update-work-item validation

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* azure_devops: second-pass audit fixes + formatter cleanup

- Add types barrel export to tools/azure_devops/index.ts
- Normalize comment endpoint path casing (/workItems/ -> /workitems/)
- Update test assertions to match normalized path
- Biome formatter reflow across tools, triggers, registry, and docs icon

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* azure_devops: address PR review comments

- Fix bgColor #FFFFFF -> #0078D4 in integrations.json and triggers/azure_devops.mdx
- Bump File tool operationCount from 4 to 5 (Read, Fetch, Get, Write, Append)
- Apply .trim() to org/project across all 15 remaining tools (consistency with query_work_items)
- Fix Found ${data.count} -> Found ${data.count ?? items.length} fallback in list_builds, list_pipelines, list_pipeline_runs content strings

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* idemtpotency

* azure_devops: address bugbot review comments

- triggers/utils: match build.complete result case-insensitively, accept stopped/cancelled in addition to failed/canceled/partiallySucceeded so PascalCase and legacy Azure DevOps payloads aren't dropped
- get_work_items_batch: chunk comma-separated IDs into 200-batch loops with proper status checks (was failing or returning incomplete data on >200 IDs)
- Add tests for both behaviors

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* azure_devops: address additional bugbot comments

- Block update_work_item now forwards areaPath; the Area Path subblock condition expanded to include update operation
- get_build_timeline.failedRecords now also flags partiallySucceeded and succeededWithIssues, normalized case-insensitively. Output description and added a focused test

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* azure_devops: address more bugbot comments

- Webhook provider extractIdempotencyId returns null when subscriptionId or notificationId is missing/empty, preventing the literal "azure_devops:undefined:undefined" key from collapsing unrelated deliveries into duplicates
- Get Work Items Batch validates that at least one non-empty ID is supplied before issuing the API request, throwing a clear error instead of hitting an empty ids= query
- Tests cover both behaviors

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* azure_devops: pin add_comment to documented api-version 7.0-preview.3

Microsoft's Add Comments docs only publish 7.0-preview.3 (the 7.2 view falls back to the 7.0 page). Get Comments stays on the documented 7.2-preview.4. Matches what's strictly in the Azure DevOps REST API reference rather than relying on undocumented version behavior.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Marcus Chandra <mzxchandra@gmail.com>
Co-authored-by: mzxchandra <129460234+mzxchandra@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 14:10:42 -07:00
Waleed b98164fd3d feat(wiza): add Wiza integration for B2B prospect enrichment and search (#4662)
* feat(wiza): add Wiza integration for B2B prospect enrichment and search

* fix(wiza): coerce reveal id to string, skip empty filters in prospect search

* fix(wiza): throw on invalid JSON in advanced filter fields instead of silently dropping
2026-05-19 12:06:19 -07:00
Vikhyath Mondreti 279010a2e7 improvement(execution): memory usage for aggregated results (#4650)
* improvement(execution): memory usage for aggregated results

* progress

* address comments

* loop/parallel results compaction

* address comment

* remove build files, harden edge cases

* remove hotpath serialiazation

* display change to make use of only preview

* materialize refs before sending in response block

* preserve exact large-value access through workflow materialization

* address comments

* progress

* fix notif error + sync manifest undefined exit

* fix streaming ref materialization

* fix tests
2026-05-18 23:55:06 -07:00
Waleed 0c1167d76b improvement(workspace): fix resource table column proportions and toast stacking (#4655)
* improvement(workspace): fix resource table column proportions and toast stacking

* fix(resource): restore scrollbar-gutter stable on table scroll container

* fix(resource): remove scrollbar-gutter stable — single-table layout doesn't need it

* fixed files cols

* fix(findymail): add required enabled field to wandConfig entries

* fix(findymail): remove optional from block outputs — not valid on BlockConfig output type

* fixes

* fix(files): use folderSizeMap for sort value so size sort matches display

* files ref
2026-05-18 17:49:51 -07:00
Waleed f3cf8fc55d feat(findymail): add Findymail B2B contact data integration (#4654)
* feat(findymail): add Findymail B2B contact data integration

Adds 11 tools covering verified email lookup (by name, LinkedIn, domain
roles), email verification, reverse email lookup with profile enrichment,
company info, employee discovery, phone lookup, technology stack
detection, and credit checks. Single API-key block with operation
dropdown, gradient-rendered icon, and generated docs.

* fix(findymail): handle HTTP errors and surface last_detected_at

- All 11 tools now check response.ok and return success:false with the API error message on non-2xx responses
- search_technologies now maps last_detected_at to match lookup_technologies and the shared output schema
- Restore file_v3 in docs icon-mapping (translated docs still reference it)

* improvement(findymail): exclude operation from params transform

Match the convention used by enrich/apify/box/calendly — destructure out
operation before forwarding the rest to the tool call, so the operation
key doesn't leak into the tool payload.
2026-05-18 12:53:32 -07:00
Waleed b276672867 feat(prospeo): add Prospeo integration for B2B contact enrichment and search (#4653)
* feat(prospeo): add Prospeo integration for B2B contact enrichment and search

Adds 8 operations: enrich person/company, bulk enrich person/company,
search person/company, search suggestions, and account information.
Uses X-KEY header auth.

* refactor(prospeo): extract shared parse helpers into utils.ts
2026-05-18 12:08:00 -07:00
Theodore Li fffb87901d feat(wait): Async toggle, chained-wait resume fix, execution status API (#4514)
* fix(wait): poll partially_resumed rows so chained waits resume

The chained-pause flow leaves a row in 'partially_resumed' status (wait1 done, wait2 still waiting). The poll's WHERE filter only matched 'paused', so wait2 was never picked up. Include 'partially_resumed' in the filter.

* feat(wait): make in-process threshold env-overridable for local testing

Adds WAIT_INPROCESS_MAX_MS env var (default 300000ms = 5 min). Lower it locally (e.g. 5000) to exercise the suspend/cron-resume path with short waits.

* feat(wait): add Suspend Workflow toggle, restore 5-min in-process default

* fix(wait): address bot review — setNextResumeAt + suspend unit default

- setNextResumeAt now matches paused OR partially_resumed; otherwise the
  cron poller can't null nextResumeAt after dispatching a chained-wait
  row, so it keeps reappearing in every poll batch until execution ends
  (flagged by both greptile and bugbot)
- Suspend mode now defaults missing timeUnitLong to 'minutes' instead of
  falling back to 'seconds' and immediately erroring (flagged by bugbot)

* improvement(wait): hint the wait-amount cap on the input

Restores the pre-#4331 description on the Wait Amount field so the limit is visible before submit instead of only at runtime. Mentions both the 5 min default and the 30 day cap with Suspend Workflow.

* refactor(wait): rename Suspend Workflow toggle to Async

* fix(wait): reword cap errors to say 'async mode'

* feat(workflows): add GET /workflows/[id]/executions/[executionId] status endpoint

Normalized status (pending|running|paused|completed|failed|cancelled)
across workflowExecutionLogs and pausedExecutions in a single response.
Surfaces paused-state details (resumeAt, pauseKind, blockedOnBlockId)
when a row exists in pausedExecutions, and the error string for failed
runs. finalOutput is opt-in via ?includeOutput=true.

* feat(workflows): support ?selectedOutputs= on execution status endpoint

Returns per-block outputs filtered by selectedOutputs paths (same
shape as the execute endpoint). Reads from executionData.traceSpans,
walks children recursively, and resolves dot-paths into each block's
output. Bare blockId returns the full output.

* fix(wait): drop dead tooltip prop on Async switch

Switch sub-blocks return null from renderLabel (sub-block.tsx:238), so
the tooltip never reached the user. The trade-off explanation already
lives in longDescription and bestPractices. Flagged by bugbot.

* docs(api): document GET /workflows/[id]/executions/[executionId]

Adds the WorkflowExecutionStatus schema and the getWorkflowExecution
operation to the OpenAPI spec, including completed/paused/failed
response examples and the includeOutput + selectedOutputs query params.
Registers the page in the Workflows section of the API reference.

* docs(api): tighten getWorkflowExecution descriptions
2026-05-15 22:09:06 -04:00
Waleed 11fa96cac0 chore(deps): bump next to 16.2.5 for CVE-2026-44578 SSRF fix (#4606)
* chore(deps): bump next to 16.2.5 for CVE-2026-44578 SSRF fix

* chore(deps): bump next to 16.2.6 for full May 2026 security release coverage
2026-05-14 14:34:05 -07:00
WaleedandClaude Opus 4.7 c21bb915f7 improvement(grafana): align tools and block with Grafana API spec (#4574)
* improvement(grafana): align tools and block with official Grafana API spec

Validates and corrects the Grafana integration against the official API
docs: fixes wire-format field naming for provisioned alert rules
(missing_series_evals_to_resolve, keepFiringFor, orgID), adds
X-Disable-Provenance support, expands alert-rule params (isPaused,
notificationSettings, record, annotations, labels), corrects defaults
(execErrState=Error, dashboard overwrite=false), and centralizes alert-rule
output mapping in a shared utils module.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(grafana): correct wire-format casing for provisioned alert rule fields

Grafana's ProvisionedAlertRule schema (verified against upstream Go source
and swagger spec) uses keep_firing_for (snake_case) and
missingSeriesEvalsToResolve (camelCase) — the opposite of what prior audit
rounds assumed. POST/PUT bodies now send the correct field names; mapAlertRule
reads the correct primary names with the old casings kept as fallbacks.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(grafana): address PR review feedback

- Drop hardcoded orgID: 1 fallback; only send orgID when organizationId is
  provided, so token-scoped org context drives rule placement.
- Surface invalid JSON for notificationSettings/record on alert rule
  create/update instead of silently dropping the input.
- Fix execErrState description in update_alert_rule to include Error.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(grafana): surface invalid JSON for annotations/labels/data on alert rules

Match the behavior of other JSON params (data, notificationSettings, record):
return a descriptive error instead of silently falling back to {} (create)
or keeping the existing value (update).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(grafana): expose alert-rule output fields in generated docs

Move ALERT_RULE_OUTPUT_FIELDS from utils.ts to types.ts and rename to
SCREAMING_SNAKE_CASE so scripts/generate-docs.ts (which only resolves const
references from types.ts matching [A-Z][A-Z_0-9]+) can inline the per-field
rows into the generated alert-rule output tables.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 19:42:20 -07:00
Vikhyath Mondreti 43f53bb7d3 feat(execution): payload size bottlenecks with lazy execution value hydration, safer materialization, and batched parallel execution (#4560)
* improvement(resolver): lazy resolution for underlying fields greater than 10MB

* progress

* feat(parallel): batching

* codegen to allow inline substitution

* address comments

* ui inconsistencies

* cleanup redundant code

* address more comments

* address comments

* replace helper

* fix tests
2026-05-12 14:57:32 -07:00
Waleed f6b246ba44 fix(docs): restore media centering and full-width intro image (#4570)
* fix(docs): restore media centering and full-width intro image

* fix(docs): drop overflow-hidden from intro media wrappers so focus ring is not clipped

* fix(docs): use inset focus ring on lightbox media so parent overflow-hidden cannot clip it

* fix(docs): drop focus ring on lightbox media to match original UI
2026-05-12 14:56:19 -07:00
Waleed 39f74aa353 feat(data-drains): add GCS, Azure Blob, BigQuery, Snowflake, and Datadog destinations (#4552)
* feat(data-drains): add GCS, Azure Blob, BigQuery, Snowflake, and Datadog destinations

* fix(data-drains): address PR review comments

* fix(data-drains): extract sleepUntilAborted, honor abort across all destinations

* fix(data-drains): widen BigQuery projectId max and dedupe parseServiceAccount

* fix(data-drains): tighten GCS bucket contract and expose Azure endpointSuffix

* improvement(data-drains): extract normalizePrefix and buildObjectKey to shared utils

* fix(data-drains): retry BigQuery network errors; tighten Azure accountKey contract

- BigQuery insertAll now wraps the fetch in try/catch inside the retry loop so DNS failures, socket resets, and timeouts are retried with backoff instead of propagating immediately.
- Align azureBlobCredentialsBodySchema with the runtime schema (min 64 / max 120 / base64 regex) so obviously invalid keys are rejected at the API boundary rather than at drain-run time.

* improvement(data-drains): consolidate parseRetryAfter; add Datadog NDJSON line context

- Extract a single parseRetryAfter helper (capped at 30s, returns number | null) into lib/data-drains/destinations/utils.ts and remove the five local copies in bigquery, datadog, gcs, snowflake, and webhook.
- Datadog parseNdjson now wraps JSON.parse in try/catch and surfaces the failing line index, matching BigQuery's parser.

* fix(data-drains): correct Datadog size guard and Snowflake VARIANT limit

- Datadog payload guard now checks the uncompressed size against the 5 MB limit and the wire size against the 6 MB compressed limit, so gzip cannot smuggle an oversized body past the client-side check.
- Snowflake VARIANT limit is 16 MiB (16,777,216 bytes), not 16,000,000 bytes — small payloads between 16 MB and 16 MiB were being rejected unnecessarily.
- Drop the unused apiKey field on Datadog PostInput; the key is already embedded in the prepared request headers.

* improvement(data-drains): consolidate backoffWithJitter into shared utils

Datadog, GCS, and webhook each had byte-identical backoff helpers (BASE 500ms, MAX 30s, jitter ±20%, Retry-After floor). Lift the helper into lib/data-drains/destinations/utils.ts alongside parseRetryAfter and sleepUntilAborted, and drop the per-file copies and their BASE_BACKOFF_MS/MAX_BACKOFF_MS constants.

* fix(data-drains): align destinations with live provider specs

Audited every destination against live AWS/GCS/Azure/BigQuery/Snowflake/
Datadog/webhook docs and applied spec-correctness fixes:

- S3: reserved bucket prefix amzn-s3-demo-, suffixes --x-s3/--table-s3;
  metadata byte formula excludes x-amz-meta- prefix per AWS spec
- GCS: reject -./.- adjacency; UTF-8 prefix cap; forbid .well-known/
  acme-challenge/ prefix; ASCII-only x-goog-meta-* enforcement
- BigQuery: insertId is 128 chars (not bytes); split DATASET_RE (ASCII)
  and TABLE_RE (Unicode L/M/N + connectors); UTF-8 byte cap on tableId
- Snowflake: disambiguate org-account vs legacy locator account formats;
  requestId+retry=true for idempotent retries; server-side timeout=600;
  default column DATA uppercase to match unquoted canonical form
- Azure: endpoint suffix allowlist (4 sovereign clouds); accountKey
  length(88) base64
- Webhook: url max(2048); CRLF/NUL rejection on bearer/secret/sig header

* fix(data-drains): address PR review on snowflake poll + shared NDJSON parsing

- snowflake pollStatement: per-attempt timeout via AbortSignal.any, retry on 429/5xx with Retry-After + jitter
- bigquery parseNdjson error messages now 1-indexed
- consolidate parseNdjson variants into shared parseNdjsonLines/parseNdjsonObjects in utils

* fix(data-drains): per-attempt fetch timeouts in gcs/bigquery, snowflake poll double-sleep

- gcs.fetchWithRetry + bigquery.postInsertAll now use AbortSignal.any with a per-attempt timeout so a hung TCP connection cannot stall the drain
- snowflake.pollStatement skips the next interval sleep when it just slept for retry backoff

* fix(data-drains): bigquery probe timeout + jittered retries, align Snowflake column default UI/docs

- bigquery test() probe now uses AbortSignal.any + per-attempt timeout
- bigquery insertAll retry switches to backoffWithJitter for thundering-herd avoidance
- Snowflake column placeholder + docs say DATA (uppercase) to match the code default

* fix(data-drains): mirror webhook signingSecret min length in form gate

isComplete now requires signingSecret >= 32 to match the contract/runtime
schema so the Save button can't enable on a value that will fail server-side.

* fix(data-drains): validate JSON client-side for Snowflake before binding

Switch Snowflake to parseNdjsonObjects so malformed rows are caught locally
with 1-indexed line numbers instead of failing the whole INSERT server-side.
Re-stringify each parsed object before binding to PARSE_JSON(?).
Drop the now-unused parseNdjsonLines helper.

* fix(data-drains): cross-cutting audit pass against live provider docs

- Azure: bound retryOptions on BlobServiceClient (SDK default tryTimeoutInMs is per-try unbounded; cap at 30s x 5 tries)
- Webhook contract: mirror runtime — signingSecret.max(512), bearerToken.max(4096) + CRLF/NUL refine, signatureHeader charset + CRLF/NUL refine
- S3 (lib + contract): reject bucket names with dash adjacent to dot; require https:// endpoint at the schema layer
- Snowflake: bind original NDJSON line bytes (re-stringifying a JSON.parse'd value loses bigint precision beyond 2^53-1); check pollStatement 200 body for the SQL error envelope (sqlState/code)
- Datadog: entry builder writes defaults first then user attrs then forced ddtags/message so user rows can't clobber routing fields; validate config.tags as comma-separated key:value pairs
- registry.tsx: tighten isComplete predicates to mirror contract minimums (GCS bucket >= 3, Azure containerName >= 3 / accountKey === 88, BigQuery projectId >= 6, Snowflake account >= 3)

* fix(data-drains): force ddsource/service overrides on Datadog entries

Previous fix placed ddsource/service before ...attrs, leaving them clobberable
by a user row field. Per Datadog docs, service + ddsource pick the processing
pipeline, so a drain's routing config must not be overridable per-row. Spread
attrs first, then force all four reserved fields (ddsource, service, ddtags,
message).

* fix(data-drains): preserve row-distinguishing index when BigQuery insertId overflows

Truncating from the left dropped the index suffix, so any overflow would
collapse all rows in a chunk to the same insertId and BigQuery would silently
dedupe them. Path is unreachable today (UUIDs keep raw ~85 chars), but the
overflow branch is now correct: hash the prefix, keep the index intact.

* fix(data-drains): refresh GCS token per retry, tighten Azure key regex

- gcs: rebuild Authorization header per attempt via buildHeaders so token
  refresh from google-auth-library kicks in if a 5xx retry crosses the
  hour-long token lifetime
- azure_blob: pin account-key regex to {0,2} trailing '=' (base64 of 64
  bytes = exactly 88 chars with up to two '=' pad chars)

* fix(data-drains): address bugbot review of 6336948f6

- gcs: allow 1-char dot-separated bucket components (e.g. "a.bucket")
  to match GCS naming rules — overall name is 3-63 (or up to 222 with
  dots), but per-component minimum is 1 per Google's spec
- bigquery: drain the 401 response body before re-issuing the request
  with a refreshed token so undici can return the socket to the
  keep-alive pool
- snowflake: hoist getJwt() above the perAttempt timer in
  executeStatement so JWT signing doesn't eat the network budget
  (matches the order already used in pollStatement)

* fix(data-drains): allow org-account Snowflake identifier with region suffix

The account validation rejected `<orgname>-<acctname>.<region>.<cloud>`
because `ACCOUNT_LOCATOR_RE`'s first segment forbade hyphens, while
`ACCOUNT_ORG_RE` forbade dots. `normalizeAccountForJwt` already handles
this composite form. Widen the first segment of `ACCOUNT_LOCATOR_RE` to
allow hyphens so the boundary contract and the runtime schema accept
what the JWT layer was already designed to process.

* fix(data-drains): drain retryable response bodies in datadog/gcs loops

Mirrors the bigquery 401 fix. Without consuming the body before
sleeping, undici can't return the socket to the keep-alive pool, so
each retry leaks a TCP connection instead of reusing it.

* fix(data-drains): drain snowflake poll bodies on 202 and retryable status

Mirrors the bigquery/datadog/gcs drains. Long async statements can poll
many times against the same connection; without consuming the body
undici can't return the socket to the keep-alive pool, so each iteration
leaks a connection until GC.

* fix(data-drains): consume success bodies; check Snowflake sqlState on 200

- gcs: drain the body on success paths so undici can return the socket
  to the keep-alive pool
- snowflake: drain the body on synchronous 200 OK and run the same
  sqlState envelope check pollStatement already does — otherwise a
  statement-level failure that completes synchronously would silently
  return success

* fix(data-drains): drain datadog and bigquery probe success bodies

Same undici keep-alive issue as the prior fixes: postWithRetries
returned the Response on success without draining (callers only read
headers); the BigQuery `test()` probe returned without consuming the
body. Both now drain before returning.

* chore(data-drains): regenerate enum migration as 0206 after staging rebase

* fix(data-drains): cap snowflake poll retries; tighten datadog tags min length
2026-05-11 17:37:10 -07:00
Waleed ae680afab2 improvement(data-drains): docs page, screenshots, and search/UI polish (#4547)
Adds the enterprise data-drains docs page with two screenshots, a
search bar over the drains table, and a UI cleanup pass on the
settings component (size-*, useMemo removal, text-sm fixes).

The previously-proposed env-var reference feature has been dropped —
drain credentials remain raw values, encrypted at rest by the
existing pipeline.
2026-05-10 13:43:25 -07:00
WaleedandCursor 3ed8615b5d chore(cleanup): react-doctor dead code elimination, landing + docs overhaul, component modernization (#4544)
* fix(react-doctor): remove unused export types, useEffect clearTimeout missing, a11y fixes

* fix(react-doctor): strip unused export types from contracts, copilot, stores, and components

Remove export keyword from type/interface declarations confirmed to have zero importers
across lib/api/contracts/tools/aws/, lib/api/contracts/*.ts, lib/copilot/generated/,
stores/workflows/workflow/types.ts, ee/access-control, ee/data-retention, lib/logs/types.ts,
and app/workspace component files. TypeScript and API validation both pass clean.

Reduces unused-types count from 394 → 181 and fully eliminates the ✗ critical
dead-code categories (exports, types, files now show as ⚠ warnings not ✗ errors).

* docs improvements

* fix(react-doctor): delete 50 unused files (dead barrels, unreachable components, stale utilities)

Remove confirmed-unused barrel index.ts files across stores/, connectors/, executor/,
lib/, and app/workspace/ that had zero importers. Also delete unreachable components
(chat-history-skeleton, trace-spans, logs-list, template-profile, enterprise landing
sections), stale utilities (buffered-stream, blob-to-data-url, queued-workflow-execution,
compute-edit-sequence), and obsolete generated/contract files. TypeScript passes clean.

* remove dead code

* cleanup

* more

* fix(blog): restore DiffControlsDemo for v0-5 blog post

* fix: restore ContactButton for enterprise blog post, export WIKIPEDIA_PAGE_CONTENT_OUTPUT_PROPERTIES

* fix(react-doc): restore stripped exports and remove server-only dependency

* chore(deps): update lockfile after removing server-only

* added back some exports

* docs

* more

* fix type issues

* tc

* fix docs search route

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(tag-dropdown): add missing isEqual import from es-toolkit

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 12:00:05 -07:00
Waleed cb3a876d3e feat(knowledge): include sourceUrl in KB search results (#4533)
* feat(knowledge): include sourceUrl in KB search results

* improvement(kb-search): mark sourceUrl nullable and cover non-null happy path in tests
2026-05-08 23:08:52 -07:00
WaleedandClaude Opus 4.7 9e9ddaa1aa feat(peopledatalabs): add People Data Labs integration (#4513)
* feat(peopledatalabs): add People Data Labs integration

Add 11 PDL operations: person enrich/identify/search/bulk, company
enrich/search/bulk/clean, location/school cleaners, and autocomplete.
All endpoints, params, and response shapes verified against official
PDL docs (scroll_token pagination, top-level likelihood on company
enrich, per-item likelihood on bulk company, full autocomplete field
enum).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(peopledatalabs): narrow conditions for fields not used by every operation

- min_likelihood now only shows for pdl_person_enrich (Person Identify ignores it)
- ticker, pdl_id, company_location now only show for pdl_company_enrich
  (Company Cleaner only accepts name/website/profile)

Addresses Greptile P1 review on PR #4513.

* fix(peopledatalabs): scope param renames to their operation

Param renames (company_profile→profile, company_location→location,
school_*→*, bulk_*_requests→requests, autocomplete_size→size, etc.)
now run only when the matching operation is selected, and stale
alternate-operation values are stripped from the request. This
prevents values left over from a prior operation switch from leaking
into the current API call (e.g. a company LinkedIn URL overwriting
a person profile, or a stale search size overwriting autocomplete
size).

Addresses Cursor Bugbot review on PR #4513.

* fix(peopledatalabs): use currentColor for icon fill

The PeopleDataLabsIcon was hardcoded to white, leaving it invisible
on light backgrounds when rendered outside its bgColor container
(e.g., search results, menus, docs). Switch to currentColor so it
inherits the surrounding text color.

Addresses Cursor Bugbot review on PR #4513.

* fix(peopledatalabs): scope shared fields (profile/location/name/website) per operation

The block has subBlocks whose raw IDs collide with PDL API param names
(profile, location for person; name, website for company). Their values
persist across operation switches even though the UI hides them, so a
person LinkedIn URL could leak into a Company Enrich request, etc.
Reset these shared targets and repopulate them only from inputs that
belong to the active operation.

Addresses Greptile P1 review on PR #4513.

* fix(peopledatalabs): scope `size` to search and autocomplete operations

`size` is shared by the person/company search subBlock and the
autocomplete_size alias. The previous logic still forwarded a stale
search `size` to operations that don't accept it (e.g. enrich, clean,
identify), and the autocomplete branch only cleared it when
autocomplete_size was unset. Reset `size` up front and only repopulate
it for the three operations that actually accept it.

Found via final integration audit of PR #4513.

* fix(peopledatalabs): restore `location` for Person Identify

Person Identify's tool accepts `location`, and the subBlock is shown
for both Enrich and Identify, but the prior reset only repopulated
`result.location` for Enrich — so any value entered on Identify was
silently dropped before reaching the API.

Addresses Greptile P1 review on PR #4513.

* fix(peopledatalabs): align endpoints + outputs with PDL API

- person_identify: short-circuit on PDL 404 (no-match), matching
  the person_enrich pattern
- company_search: drop unsupported `dataset` param (PDL company
  search docs do not list it)
- block: expose `min_likelihood` for `pdl_company_enrich` (PDL
  Company Enrichment supports min_likelihood)
- location_clean: surface `subregion`; drop phantom `latitude`/
  `longitude` (PDL only returns `geo` as a "lat,lon" string)
- school_clean: surface `domain` and `location_continent` from
  the nested `location` object
- docs icon: switch fill to `currentColor` so the icon renders
  on light backgrounds

* fix(peopledatalabs): restore `name` for Person Enrich / Identify

The shared `name` reset at the top of `tools.config.params` was
only repopulated for the company-side operations, so any
programmatic `name` input to `pdl_person_enrich` or
`pdl_person_identify` was silently dropped. Both PDL endpoints
accept `name` as a full-name match parameter.

* fix(peopledatalabs): restore `name` for Person Enrich

Add the `name` parameter to `PdlPersonEnrichParams`, the tool's
params definition, and the URL builder. PDL Person Enrichment
accepts `name` as a full-name match alternative to first_name +
last_name; without it, programmatic `name` input was silently
dropped before reaching the API.

* fix(peopledatalabs): isolate company `name` UI from person ops

Rename Company Name subBlock id from `name` to `company_name` so a
stale company value can't leak into Person Enrich/Identify when the
user switches operations.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(peopledatalabs): honor programmatic inputs for clean_location/school

`pdl_clean_location` and `pdl_clean_school` were only restoring values
from UI subBlock IDs (`clean_location_input`, `school_*`). Programmatic
callers using the declared `location`/`name`/`website`/`profile` inputs
had their values dropped after the shared-field reset. Add fallbacks so
both UI and programmatic inputs flow through.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(peopledatalabs): programmatic input fallbacks + required autocomplete text

- Company Enrich and Clean Company now fall back to programmatic
  `params.profile` / `params.location` when the UI-scoped
  `company_profile` / `company_location` are absent. Mirrors the
  fallback pattern already used for `name`.
- Autocomplete `text` subBlock is now required when operation is
  autocomplete — PDL requires it for nearly all field values.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 11:01:13 -07:00
Vikhyath Mondreti 6cb779601a feat(search-replace): search & replace, cut, deploy modal ui flicker (#4507)
* feat(search): workflow search and replace

* fix alignment

* fix hidden fields bug

* fix loops/parallel badge case

* resource resolver

* add cut

* update docs

* address comments

* make source code for func blocks dispay resolved code instead

* fix match issue

* fix padding
2026-05-07 20:34:53 -07:00
Waleed 235a62fd95 fix(hunter): align tools, block, and outputs with Hunter.io v2 API spec (#4511)
* fix(hunter): align tools, block, and outputs with Hunter.io v2 API spec

* fix(hunter): match documented Discover response and coerce numeric employees
2026-05-07 20:01:35 -07:00
WaleedandClaude Opus 4.7 6a006851fa improvement(apollo): align tools and block with Apollo API docs (#4487)
* improvement(apollo): align tools and block with Apollo API docs

* improvement(apollo): fix tool outputs to match Apollo API response shapes

* chore(apollo): regenerate docs for output changes

* fix(apollo): address PR review comments

* fix(apollo): allow skipped_contact_ids as hash per Apollo docs

* docs

* fix(apollo): add runtime guard for account_bulk_update empty body

* fix(apollo): require contact_attributes for bulk_update

* fix(apollo): add subblock id migrations for renamed opportunity fields

* fix(apollo): tighten account_bulk_update guard and accept object attrs

* fix(apollo): require contact_ids with object-form contact_attributes

* docs(apollo): clarify contact_bulk_update parameter requirements

* fix(apollo): handle flat and wrapped contact response shapes

* validate

* fix(apollo): mirror bulk_update guard, preserve update fields in migration, expose account_bulk_create options

* fix(apollo): don't clobber user contact_attributes in migration; simplify task_create created flag

* fix(apollo): drop undocumented task type, preserve mixed-array IDs, migrate note→task_notes

* fix(apollo): align tools and block with live API docs

Final pass over the Apollo integration after a per-tool forensic audit
against Apollo.io docs. Notable fixes:

- organization_enrich: GET+querystring -> POST+JSON body (canonical, non
  master-key)
- organization_bulk_enrich: ?domains[]= -> JSON body { organizations }
- people_search: declare/forward organization_num_employees_ranges; fix
  contact_email_status placeholder ("likely to engage", with spaces)
- account_bulk_create: surface failed_accounts and failed count
- contact_bulk_create: expand documented per-contact fields (CRM IDs,
  phone_numbers, contact_emails, typed_custom_fields, etc.)
- sequence_add_contacts: surface remaining documented filter params
- task_create: confirm wire field name (note) and remap from task_notes
- types: tighten params/responses for the above

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs

* fix(apollo): add _removed_* migrations for retired opportunity subblocks

* fix(apollo): expose webhook_url subblock for people enrich phone reveal

* fix(apollo): drop colliding account_ids migration, enforce contact bulk limit, expose async toggle for accounts

* fix(apollo): cap account_attributes at 1000 in bulk update

* fix(apollo): drop bare-id merging in bulk update migration to avoid empty attribute objects

* fix(apollo): reject ambiguous account/contact_ids + array-form attributes

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 19:39:48 -07:00
Waleed 38cbefdc3b fix(revenuecat): align tools and block with REST v1 API spec (#4488)
* fix(revenuecat): align tools and block with REST v1 API spec

- Validated all 10 tools and the block against context7 REST v1 docs
- Unwrap {value:{subscriber}} envelope across post-receipts, attributes,
  entitlements, and Google subscription endpoints
- Trim entitlement output to documented fields (expires_date,
  grace_period_expires_date, product_identifier, purchase_date)
- Add subscriber output fields: last_seen, original_application_version,
  other_purchases, subscriber_attributes
- create_purchase: productId optional (Google-only required); add
  introductoryPrice, attributes, updated_at_ms; surface customer + subscriber;
  X-Platform required; presentedOfferingIdentifier and paymentMode
- update_subscriber_attributes: read response and surface subscriber;
  note required updated_at_ms
- defer_google_subscription: enforce XOR(extendByDays, expiryTimeMs) and
  1-365 range; expiryTimeMs as one-of alternative
- grant_entitlement: duration optional, added endTimeMs (one-of)
- refund_google_subscription: corrected endpoint to
  /transactions/{storeTransactionId}/refund
- delete_customer: read 'deleted' field (was 'was_deleted')
- list_offerings: corrected X-Platform values
- get_customer: count active subscriptions by expiry/refund
- Added shared throwIfRevenueCatError helper for {code, message} envelope
- Moved type coercions from tools.config.tool to tools.config.params to
  preserve dynamic refs

* docs

* fix(revenuecat): address PR review feedback

- create_purchase: wrap JSON.parse(attributes) with try/catch and clear error
- update_subscriber_attributes: drop subscriber output (endpoint returns
  empty body) and guard JSON.parse on attributes
- grant_entitlement: throw when both duration and endTimeMs are provided,
  matching defer_google_subscription behavior

* fix(revenuecat): tighten docs after sub-segment validation

- delete_customer: drop dead was_deleted fallback (docs specify 'deleted')
- grant_entitlement: mark duration + startTimeMs as deprecated, clarify
  startTimeMs only affects expiration calc (not grant time)
- list_offerings: replace vague platform description with documented
  X-Platform enum (ios, android, amazon, stripe, roku, paddle)

* docs

* fix(revenuecat): clear duration default when endTimeMs is provided

The duration dropdown defaults to 'monthly' so any user filling in the
advanced endTimeMs field would otherwise hit the XOR guard. Clear
duration in the params mapper so endTimeMs takes precedence.

* fix(revenuecat): clear extendByDays default when expiryTimeMs is provided

Mirror the duration/endTimeMs fix from 8204e89: when expiryTimeMs is
populated, clear extendByDays in the params mapper so the empty-string
form value does not trip the XOR guard. Also harden the tool-level XOR
checks in defer_google_subscription and grant_entitlement to treat empty
strings as undefined for direct (non-block) callers.

* fix(revenuecat): guard NaN in time-ms mappers and require integer days

- Block params mapper: only clear duration/extendByDays when the parsed
  endTimeMs/expiryTimeMs is finite, so invalid input does not silently
  discard the user's valid companion default
- defer_google_subscription: validate extendByDays as integer (was
  Number.isFinite), matching the error message

* fix(revenuecat): fall back to Date.now() when request_date is malformed

A malformed request_date would parse to NaN, making every entitlement
and subscription compare false and silently zero active counts. Fall
back to Date.now() when the parsed value is not finite.

* fix(revenuecat): unwrap value envelope in list_offerings response

* improvement(revenuecat): include updated_at_ms in attributes placeholder and wand prompt
2026-05-07 13:06:13 -07:00
WaleedandClaude Opus 4.7 a251e45400 feat(sap): add SAP Concur integration block and SAP S/4HANA validation fixes (#4483)
* feat(sap): add SAP Concur integration block and SAP S/4HANA validation fixes

* added

* fix(sap_s4hana): preserve raw Set-Cookie array for CSRF cookie join

SecureFetchHeaders previously collapsed multi-value Set-Cookie headers
with ", ", forcing consumers to re-split via a fragile regex. Cookie
values containing "=" or "," (e.g., Base64 session tokens) could be
misparsed and produce malformed Cookie strings on CSRF-protected
mutations.

Add SecureFetchHeaders.getSetCookie() that returns the raw array, and
update the S/4HANA OData proxy's joinSetCookies to consume it directly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(sap-concur): rename misleading exchange-rate tool, drop unusable refresh_token grant, validate geolocation host

- Rename sap_concur_get_exchange_rate to sap_concur_upload_exchange_rates (POST bulk upload, not GET)
- Remove refresh_token from SapConcurGrantType / Zod enum / block dropdown / docs (no implementation)
- Validate Concur geolocation hostname against SAP_CONCUR_ALLOWED_DATACENTERS

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* finished

* docs

* fix(docs): escape braces in tool/trigger description prose for MDX

Tool and trigger descriptions can contain URL path placeholders like
{reportId} or JSON-shape hints like { Items, NextPage }. When rendered
as MDX prose (not table cells), these were emitted unescaped and MDX
parsed them as JSX expressions, failing prerender with
"ReferenceError: reportId is not defined".

Escape { and } in the operation-level description and trigger
description renderers, matching the existing escaping in table-cell
descriptions.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(sap-concur): align with live API on travel-profile, itineraries, and context types

- list_travel_profiles_summary: rename Status query to Active with 1/0 values, tighten LastModifiedDate format hint
- list_itineraries / get_itinerary: use documented userid_type / userid_value / ItemsPerPage / Page query keys
- create_report_comment: contextType allows MANAGER (move to EXPENSE_READ_CONTEXT_TYPE_OPS)
- get_list_item: drop unused listId from block (tool only needs itemId)
- Tighten description copy on list_expenses/get_itemizations/associate_attendees/remove_all_attendees

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(sap-concur): correct Cash Advance v4.1 paths, add SCIM filter param

- Update Cash Advance create/get/issue tools from /cashadvance/v4/ to /cashadvance/v4.1/ to match the live API
- Add filter query param to list_users (SCIM v4.1 supports filtering by userName, employeeNumber, externalId)
- Regenerate docs MDX

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(sap-concur): drop SCIM list_users filter param (not supported on v4.1 GET)

SCIM Identity v4.1 GET /Users does not accept a filter query parameter — filtering
is only supported via POST /Users/.search (already exposed by sap_concur_search_users).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(sap-concur): final live-API alignment

Verified against live SAP Concur docs (concur/developer.concur.com preview branch):

- Revert Cash Advance paths to /cashadvance/v4/ (v4.1 endpoints do not exist; live spec is v4)
- Travel Profile v2 summary has no Active/Status query param — drop the filter from tool, types, and block
- Report Comments v4 contextType is TRAVELER or PROXY only (NOT MANAGER) — move create_report_comment + list_report_comments into the TRAVELER/PROXY context group
- Trip v1.1 query keys: userid_type / userid_value / ItemsPerPage / Page (snake/Pascal per docs) — already correct, kept

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs

* fix(sap-concur): restore Cash Advance v4.1 paths

Re-verified against live developer.concur.com docs at /api-reference/cash-advance/v4-1.cash-advance.html — only v4.1 endpoints are documented:
- POST /cashadvance/v4.1/cashadvances
- GET /cashadvance/v4.1/cashadvances/{cashAdvanceId}
- POST /cashadvance/v4.1/cashadvances/{cashAdvanceId}/issue

The /cashadvance/v4/ docs page returns 404. Reverts the prior local rollback in 9ef3a11d7.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-06 19:32:27 -07:00
Vikhyath Mondreti 79ffccc140 feat(emailbison): block, tools, sharepoint v2 block with cleaner code (#4470)
* feat(emailbison): block, tools

* type improvments

* typecheck issue

* add email bison trigger, cleanup sharepoint block

* address comments

* fix tests

* error on partial upload failures
2026-05-06 12:44:17 -07:00
Waleed 6d4ffff327 fix(agiloft): correct response parsing, add EWGetChoiceLineId tool (#4477)
* fix(agiloft): correct response parsing, add EWGetChoiceLineId tool

* fix(agiloft): address PR review feedback
2026-05-06 11:55:11 -07:00
Waleed 48331451b0 chore(deps): upgrade next.js to 16.2.4 (#4460)
* chore(deps): upgrade next.js to 16.2.4

- Bump next and @next/env to 16.2.4 across root, apps/sim, apps/docs
- Replace next-runtime-env's env() helper (calls unstable_noStore(), rejected by Next 16.2 outside request scope) with a direct window.__ENV / process.env getter
- Add export const dynamic = 'force-dynamic' on landing /privacy and /terms pages so NEXT_PUBLIC_* runtime env reads aren't baked at build

* fix(whitelabel): force dynamic rendering for manifest.ts

Without this, NEXT_PUBLIC_BRAND_* values are baked into the manifest at build time. Pairs with the next-runtime-env removal in the prior commit, restoring Docker runtime injection for whitelabel deployments.

* fix(oauth): wrap consent page useSearchParams in Suspense

Next 16.2's stricter prerender check fails the build when useSearchParams() is used without a Suspense boundary. Splits the client component into an outer wrapper and inner body.

* fix(whitelabel): force dynamic rendering for landing segment

Client components in (landing) (e.g. Navbar) read NEXT_PUBLIC_BRAND_* via getEnv. Without this, SSR prerender would bake the build-time process.env values into HTML, mismatching window.__ENV after hydration in Docker runtime-env deployments. Cascades to all landing routes via the layout.

* revert(whitelabel): drop force-dynamic from landing layout

Cascading force-dynamic neutered dynamicParams = false + generateStaticParams on /blog/[slug], /integrations/[slug], /models/[provider], /models/[provider]/[model] — killing static prerender for SEO-critical pages. The hydration concern only materializes for whitelabel Docker deployments where build-time and runtime NEXT_PUBLIC_BRAND_* differ; those deployments can set the vars at build instead. Keeping force-dynamic on /privacy, /terms, and /manifest where it actually matters.

* fix(prerender): wrap useSearchParams callsites for Next 16.2

Next 16.2 fails the build when a client component using useSearchParams() is statically prerendered without a Suspense boundary.

- Wrap landing Navbar in Suspense (imported by /oauth/consent and other pages)
- Add force-dynamic to reset-password, invite/[id], and unsubscribe pages whose client bodies call useSearchParams

* fix(navbar): preserve SSR HTML, drop Suspense bailout

Reading useSearchParams() forced a Suspense fallback that emitted no navbar HTML during SSR — leaving crawlers and no-JS users without nav. The 'home' query param only affects client-side link targets, so read it from window.location in an effect after hydration. Restores full SSR navbar markup.

* chore: trim verbose comments in next.js upgrade

The force-dynamic export name is self-documenting; the remaining env.ts comment is tightened to the essential WHY (why we don't use next-runtime-env's helper).
2026-05-06 11:08:01 -07:00
WaleedandClaude Opus 4.7 d721dc3358 feat(enterprise): add data drains for continuous export to S3 / webhook (#4440)
* feat(enterprise): add data drains for continuous export to S3 / webhook

* chore(data-drains): regenerate migration on top of staging + bump route baseline

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(data-drains): clarify retention pairing is user-coupled, not enforced

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(data-drains): preserve explicit forcePathStyle=false + reserve x-sim-signature

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(data-drains): drift guard ensures every webhook header is reserved

Asserts that any header buildHeaders writes is rejected when reused as a
custom signatureHeader. Adding a new metadata header without mirroring it
into RESERVED_SIGNATURE_HEADER_NAMES now fails CI.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 18:04:02 -07:00
Waleed d517415c77 chore(docs): upgrade fumadocs to latest minor versions (#4462)
* chore(docs): upgrade fumadocs to latest minor versions

- fumadocs-core: 16.6.7 -> 16.8.5
- fumadocs-ui: 16.6.7 -> 16.8.5
- fumadocs-mdx: 14.2.8 -> 14.3.2
- fumadocs-openapi: 10.3.13 -> 10.8.1
- migrate deprecated sidebar.tabs to top-level tabs prop
- fix pre-existing typo (slots.paremeters) surfaced by stricter openapi types

* fix(docs): revert sidebar.tabs migration to keep deploy compat

The top-level tabs prop is only on fumadocs-ui 16.7+; deploy env was
still resolving an older type and failing typecheck. sidebar.tabs is
deprecated but still functional — keep it for now.
2026-05-05 17:54:18 -07:00
0337ccd7f3 feat(credentials): add Atlassian service account credentials (#4432)
* 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(credentials): add Atlassian service account credentials

* improvement(credentials): tighten Atlassian service account plumbing

- Collapse fetchOAuthTokenBundle into fetchOAuthToken (returns the bundle)
- Reuse serviceAccountJsonSchema in the JSON form instead of hand-rolled checks
- Use parseAtlassianErrorMessage for log details; drop one-line bearer helper
- Extract ATLASSIAN_SERVICE_ACCOUNT_PROVIDER_ID/_SECRET_TYPE constants
- Use Drizzle .returning() instead of post-insert SELECT
- Helper for the duplicated 401/403 + non-OK pattern in the validator

* docs(credentials): add Atlassian service account setup guide

- New /integrations/atlassian-service-account doc covers token creation,
  scope selection, and adding the credential to Sim
- Form's "View setup guide" link now points at the doc
- Fix the existing Google form link that pointed to the wrong path

Screenshot TODOs left inline as MDX comments for the docs team.

* docs(credentials): add Atlassian service account screenshots

- Auth type picker, Sim add-credential modal, Jira block credential dropdown
- Scope-picker screenshot still TODO

* docs(credentials): add Atlassian scope picker screenshot

* fix(credentials): address greptile feedback on Atlassian SA

- Drop stale 'email and API token' copy from the service description
  (we only collect a token + domain, no email field)
- Move duplicate display-name check inside the create transaction so
  concurrent POSTs can't both pass the check and insert duplicates

* fix(docs): move Atlassian screenshots to docs/public

Docs site serves /static/* from apps/docs/public, not apps/sim/public —
matches the existing google-service-account screenshot convention.

* fix(credentials): address review feedback on Atlassian SA

- SSRF: only accept *.atlassian.net / *.jira-dev.com hosts before fetching
  tenant_info, blocking probes against localhost/internal IPs
- Confluence spaces selector: pull cloudId from the SA secret instead of
  calling accessible-resources, which 401s for scoped service-account tokens
- Case-insensitive https?:// strip so HTTPS://team.atlassian.net normalizes
  correctly

* chore: merge staging and bump API validation route baseline to 727

* perf(credentials): single-resolve in confluence spaces selector

Atlassian SAs were hitting resolveOAuthAccountId twice (once via
refreshAccessTokenIfNeeded, once directly to read cloudId) and
decrypting the secret twice (via getAtlassianServiceAccountToken
inside refresh, then again via getAtlassianServiceAccountSecret).

Resolve once up front and branch the whole flow on the result —
SA path skips refresh entirely and pulls token+cloudId from a
single secret read.

* refactor(credentials): consolidate Atlassian SA creation into /api/credentials

Atlassian service-account creation lived in its own route, contract, and
mutation hook, copy-pasting ~140 lines of insert/membership/audit/posthog
boilerplate from /api/credentials. Two endpoints means two authz paths,
two audit shapes, two TOCTOU stories — they will drift.

Fold Atlassian into the existing service_account branch of /api/credentials,
dispatching by providerId. The Atlassian validator (tenant_info + Bearer
/myself, SSRF host allowlist, typed error codes) lives in
lib/credentials/atlassian-service-account.ts and is the only Atlassian-
specific piece left. AtlassianValidationError maps to a {code, error} 400
in the existing catch block; the rest of the flow (transaction, members,
audit, posthog, dup-check) is now shared with Google SA + env credentials.

Delete:
- /api/auth/atlassian-service-account route
- contracts/atlassian-service-account.ts + barrel export
- useCreateAtlassianServiceAccount hook
- API audit baseline 727 → 726

Both forms (Google JSON-key, Atlassian token+domain) now call
useCreateWorkspaceCredential with the appropriate body shape.

* fix(credentials): close TOCTOU and restore typed errors after consolidation

- Add inner duplicate-guard inside the create transaction (DuplicateCredentialError)
  to close the race that the outer findExistingCredentialBySource leaves open.
  service_account rows have no DB-level unique index on (workspaceId, providerId,
  displayName), so this is the actual safety net. Tx-internal check applies to
  Google + env_workspace too — race-safety win for all credential types.
- Re-emit {code: 'duplicate_display_name', error: ...} on conflict so the form's
  ERROR_MESSAGES.duplicate_display_name mapping is reachable again.
- Thread Atlassian-specific audit metadata (atlassianDomain, atlassianCloudId)
  back into recordAudit; consolidation had dropped them.
- Use ATLASSIAN_SERVICE_ACCOUNT_PROVIDER_ID constant in contract superRefine.
- Drop `error: any` in catch in favor of `error: unknown` + getPostgresErrorCode.

* chore(credentials): drop dead createWorkspaceCredentialBodySchema + updateWorkspaceCredentialBodySchema

Both shadowed the actually-used schemas (createCredentialBodySchema /
updateCredentialByIdBodySchema) and were missing the apiToken/domain
Atlassian fields. A future change could pick the wrong one and silently
drop those fields. Confirmed zero non-definition references in the repo
(grep across apps/, packages/, scripts/ minus build artifacts).

* fix(credentials): scope inner duplicate re-check to service_account

OAuth dedupes by accountId, env_* by envKey — both have DB-level partial
unique indexes that surface as 23505. The previous inner re-check fired
for all types and always threw DuplicateCredentialError, which mapped to
'duplicate_display_name' in the UI even when the real conflict was a
duplicate OAuth account or env key. Restrict the in-tx re-check to
service_account (the only type without a DB-level index) and let the
23505 handler emit a generic message for everything else.

---------

Co-authored-by: Waleed <walif6@gmail.com>
Co-authored-by: Siddharth Ganesan <33737564+Sg312@users.noreply.github.com>
Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com>
2026-05-05 18:55:27 -04:00
Waleed 6bc34c5a68 feat(exa): add date filters to search (#4451) 2026-05-05 11:53:27 -07:00
Waleed 6d044a924c feat(image-generator): add gpt-image-2 model support (#4437)
* feat(image-generator): add gpt-image-2 model support

* docs
2026-05-04 15:26:47 -07:00
Vikhyath Mondreti 20ee07c6da improvement(blocks): depends on misalignments audit (#4409)
* fix(blocks): depends on misalignment

* fix overclearing finds
2026-05-02 11:29:50 -07:00
Waleed 8b6307aea4 feat(gmail): add edit draft and update label tools (#4374)
* feat(gmail): add edit draft and update label tools

* fix(gmail): correct legacy block access list and docs heading for edit_draft_v2

* fix(gmail): use shared contract for edit-draft route

* regen docs

* fix(knowledge): inline reranker model list in description for doc generator

* resolve
2026-04-30 19:51:02 -07:00
Waleed 0c25fc4ee1 fix(auth): resolve CORS errors for self-hosted deployments behind reverse proxies (#4369)
* fix(auth): resolve CORS errors for self-hosted deployments behind reverse proxies

- auth client now uses browser origin first, falling back to NEXT_PUBLIC_APP_URL
- socket client falls back to page origin when served from non-localhost (assumes /socket.io is proxied)
- add TRUSTED_ORIGINS env var to extend Better Auth trustedOrigins (apex+www, alias hostnames)
- warn at startup when NEXT_PUBLIC_APP_URL is localhost in production
- preprocess empty NEXT_PUBLIC_SOCKET_URL so docker-compose ${VAR:-} works
- migrate remaining uuid/nanoid/randomUUID usages to @sim/utils generateId/generateShortId
- extend generateShortId with optional alphabet param (rejection sampling)
- document TRUSTED_ORIGINS in .env.example, docker-compose.prod.yml, and helm values.yaml

Fixes simstudioai/sim#1243

* fix(auth): address PR review comments

* chore(env): drop unnecessary NEXT_PUBLIC_SOCKET_URL preprocess (skipValidation is true)

* fix(docker): include @sim/utils in migrations image

Migration scripts now import generateId from @sim/utils/id; without copying packages/utils into the image, bun install fails to resolve the workspace dep at build time and the import fails at runtime.

* fix(helm): remove unused NEXT_PUBLIC_SOCKET_URL from realtime sections

The realtime service never reads NEXT_PUBLIC_SOCKET_URL — its env schema
only includes BETTER_AUTH_URL, NEXT_PUBLIC_APP_URL, ALLOWED_ORIGINS,
BETTER_AUTH_SECRET, INTERNAL_API_SECRET, DATABASE_URL, and REDIS_URL.
Remove the dead config from all helm values files and the values schema.

* fix(helm): allow empty NEXT_PUBLIC_SOCKET_URL in values schema

The default in values.yaml is now "" (empty string), which falls back to
the page origin at runtime. The schema previously required a valid URI,
which would reject the default. Mirror the INTERNAL_API_BASE_URL pattern
using anyOf with const "". Also add TRUSTED_ORIGINS to the schema.

* docs(self-hosting): mark NEXT_PUBLIC_SOCKET_URL as optional

The page-origin fallback in getSocketUrl() means self-hosters no longer
need to set NEXT_PUBLIC_SOCKET_URL when realtime is on the same origin
as the app. Update docs to reflect this:

- Remove NEXT_PUBLIC_SOCKET_URL from .env scaffolding examples in
  docker.mdx, platforms.mdx, environment-variables.mdx
- Mark the variable as Optional in the env vars table with the new
  default behavior described
- Update troubleshooting to point at reverse-proxy /socket.io routing
  rather than the env var
- Flip dev docker-compose defaults (local, ollama, devcontainer) from
  http://localhost:3002 to empty for consistency with prod.yml; the
  in-code localhost fallback handles the dev case identically

Applied across all 6 documentation languages (en/fr/de/ja/es/zh).

* chore: untrack and ignore .claude/scheduled_tasks.lock
2026-04-30 19:26:19 -07:00
Waleed 220f8c8b10 feat(knowledge): add chunking strategies and regex strict boundaries (#4368)
* feat(knowledge): add chunking strategies and regex strict boundaries

- Add Token, Sentence, Recursive, and Regex chunkers with strategy selection in create-base modal
- Add opt-in strict boundaries mode for regex chunker so each match becomes its own chunk
- Add chunking strategies docs page with industry references

* fix(chunkers): strip capturing groups and validate strictBoundaries scope

- Convert capturing groups to non-capturing in regex chunker so split() doesn't surface delimiter text as spurious chunks
- Reject strictBoundaries in chunkingConfigSchema when strategy is not regex

* fix(chunkers): also strip named capture groups in regex patterns

Named groups (?<name>...) are still capturing groups so split() interleaves
their matched text. Convert them to non-capturing alongside plain ( groups.

* fix(chunkers): exclude lookbehind from named-group rewrite

Tighten NAMED_GROUP_PREFIX with negative lookahead so patterns like
(?<=<tag>) are not misidentified as named capture groups.
2026-04-30 18:33:52 -07:00
WaleedandClaude Opus 4.7 d94f4c9943 feat(knowledge): add embedding model selection and Cohere reranker (#4349)
* feat(knowledge): add embedding model selection and Cohere reranker

* fix(knowledge): split reranker model constants into client-safe module

* fix(knowledge): bill rerank on every successful API call and fix MDX docs literal

* test(knowledge): align embedding tests with provider abstraction changes

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): require explicit Azure deployment per OpenAI embedding model

Greptile P1: when AZURE_OPENAI_* was set, every OpenAI embedding model was
routed to the single KB_OPENAI_MODEL_NAME deployment. A KB created with
text-embedding-3-large would be embedded by whatever model that deployment
serves while billing tracked 3-large pricing — and chunks ingested via Azure
versus queried via real OpenAI would land in mismatched vector spaces.

Now require AZURE_OPENAI_DEPLOYMENT_TEXT_EMBEDDING_3_(SMALL|LARGE) per model.
Falls back to KB_OPENAI_MODEL_NAME only for text-embedding-3-small (legacy).
If no deployment is configured for the chosen model, route to direct OpenAI
instead of silently routing to the wrong deployment.

Also fix type predicate in search/route.ts to use KnowledgeBaseAccessResult
so the build passes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): skip platform reranker billing for BYOK Cohere keys

Cursor bugbot found that resolveCohereKey discarded BYOK status, so the
search route always added platform rerankerCost even when the workspace
supplied its own Cohere key.

Now resolveCohereKey returns { apiKey, isBYOK } and rerank() returns
{ results, isBYOK }. The search route checks rerankIsBYOK before adding
rerankerCost or emitting the rerankerCost/rerankerSearchUnits fields,
mirroring how generateEmbeddings handles BYOK billing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): match search tokenizer to embedding provider; remove dead var

Cursor bugbot:
- Token estimation was hardcoded to 'openai' for every embedding model.
  For gemini-embedding-001 the cost was computed against an OpenAI-tokenized
  count, producing wrong input.tokens.prompt and (slightly) wrong cost.
  Now derive the tokenizer provider from the embedding model's provider.
- rerankApplied was set but never read. Removed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): match chunk tokenizer to KB embedding provider

Cursor bugbot: createChunk and updateChunk hardcoded the 'openai' tokenizer
when computing the stored tokenCount. For KBs using gemini-embedding-001 the
count was estimated with the wrong heuristic, leading to inaccurate stored
counts (and any billing derived from them). Now derive the tokenizer from
the KB's embedding model provider, matching the search route.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(knowledge): centralize tokenizer mapping on EmbeddingModelInfo

Add tokenizerProvider directly to EmbeddingModelInfo so callers read it
from the registry instead of reimplementing the gemini→google / openai→openai
map at each call site. Removes the local helper in chunks/service.ts and
the inline ternary in search/route.ts.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(knowledge): lock embedding model to KB_EMBEDDING_MODEL env var

Remove the user-facing model picker from the KB create modal and the
embeddingModel field from the create/update API schemas. The active model
is now selected server-side via KB_EMBEDDING_MODEL, which collapses Azure
routing to a single deployment (KB_OPENAI_MODEL_NAME) and drops the
per-model AZURE_OPENAI_DEPLOYMENT_TEXT_EMBEDDING_3_* env vars and
SUPPORTED_EMBEDDING_MODEL_IDS / UI-only label+description registry fields.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): use provider tokenizer for chunks and bound rerank indices

- documents/service.ts: replace ceil(len/4) heuristic with estimateTokenCount using the embedding model's tokenizerProvider so token counts match billing
- reranker.ts: filter Cohere rerank results to valid indices before mapping to defend against malformed responses
- utils.test.ts: add embeddingModel to kb fixture so getEmbeddingModelInfo resolves

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): use .count from estimateTokenCount return value

estimateTokenCount returns a TokenEstimate object, not a number — access
.count so the integer token count is stored instead of an object.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): only enforce single embedding model when query is present

Tag-only searches don't generate a query embedding, so two KBs with
different embedding models can be filtered together. Gate the guard on
hasQuery so cross-model tag-only queries no longer 400.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): use getConfiguredEmbeddingModel in copilot KB creation

Copilot-created KBs were hardcoded to text-embedding-3-small, ignoring
KB_EMBEDDING_MODEL. This caused cross-KB searches mixing copilot- and
API-created KBs to hit the embedding-model-mismatch guard.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): make EMBEDDING_DIMENSIONS a literal type

CreateKnowledgeBaseData.embeddingDimension is typed as the literal 1536,
so EMBEDDING_DIMENSIONS needs `as const` to satisfy it after the copilot
path switched to passing the constant.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): use per-KB embedding model in v1 search route

The v1 search endpoint was passing undefined to generateSearchEmbedding,
which silently fell back to text-embedding-3-small. KBs created while
KB_EMBEDDING_MODEL=gemini-embedding-001 (or any non-default) would have
their queries embedded with the wrong model. Now resolves the model from
the KB rows like the internal route, with the same multi-model guard.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(knowledge): polish embedding/reranker implementation

- Drop unused supportsCustomDimensions from EmbeddingModelInfo (every
  registered model supports it; OpenAI/Azure paths now always send
  dimensions: 1536).
- Type SUPPORTED_EMBEDDING_MODELS as Partial<Record<...>> so index lookups
  surface as possibly-undefined in the type system instead of relying on
  runtime null checks alone.
- Require AZURE_OPENAI_API_VERSION in the Azure routing gate. Missing
  api-version no longer slips through as ?api-version=undefined; it now
  falls back to direct OpenAI.
- Use the embedding provider's tokenizer (estimateTokenCount) for the
  Gemini fallback token estimate instead of len/4, so billing matches
  the model's tokenization.
- Drop unreachable 'text-embedding-3-small' fallback in the manual chunk
  upload route — accessCheck.knowledgeBase is non-null after the access
  guard.
- docs-chunker now reads getConfiguredEmbeddingModel() so Sim's docs
  ingestion respects KB_EMBEDDING_MODEL like the user-facing paths.
- Add v1 search route test covering per-KB model resolution and the
  cross-KB mixed-model rejection.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): resolve type errors and unhandled rejection in search routes

- Use accessCheck.knowledgeBase.embeddingModel directly in chunks response
- Narrow access-check predicate to KnowledgeBaseAccessResult in v1 search
- Move inaccessible-KB 404 check before query embedding promise creation

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): pass Gemini API key via x-goog-api-key header

URLs end up in server access logs, proxy logs, and APM tools, so embedding
the key as a query param risks accidental exposure. Google explicitly
recommends the header form for the Gemini REST API.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): default Azure deployment name to embedding model name

Restore the prior fallback so existing Azure deployments — which conventionally
name the deployment after the model — continue to route through Azure when
KB_OPENAI_MODEL_NAME is unset. Before this fix, those deployments silently fell
through to direct OpenAI.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): cap Gemini batches at 100 items, add singular GEMINI_API_KEY fallback

- Gemini's batchEmbedContents API rejects requests with more than 100
  items. The token-based batcher could pack hundreds of short chunks
  into a single request, causing 400s. Add maxItemsPerRequest on
  ResolvedProvider and split token batches further when set.
- Mirror resolveOpenAIKey by accepting GEMINI_API_KEY (singular) as a
  fallback before requiring the rotating GEMINI_API_KEY_1/2/3 keys.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(knowledge): prefer singular Cohere key before rotation

Match resolveOpenAIKey/resolveGeminiKey order: check the singular
COHERE_API_KEY before falling back to rotating keys.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 01:45:56 -07:00
WaleedandClaude Opus 4.7 0c69302369 fix(integrations): harden jira, jsm, ashby, google drive, slack, confluence, notion (#4345)
* fix(integrations): validate and harden jira, jsm, ashby, google drive, slack, confluence, notion

Audit and fix contract drift, input validation, and error handling across integrations:

- Jira: NaN guards on worklog seconds, JSON.parse try/catch on internal API responses,
  domain normalization (strip leading https://), JQL injection prevention via project
  key validation, ADF helper consolidation, /search/jql nextPageToken pagination,
  defensive .trim() on ID path params, encodeURIComponent on watcher account IDs,
  resolveAssigneeAccountId helper, parent-as-object wrapping, summary fallback,
  add read-bulk operation. Restored total field (always null) to preserve contract.
- JSM: customer/organization route validation
- Ashby: types and tool output cleanup across all 30+ tools
- Google Drive: tighter response handling across read/write/share tools
- Slack: types and tool fixes (canvas, reactions, messaging, members)
- Confluence: update tool and types
- Docs: regenerated mdx for all touched integrations

* fix(ashby): add subblock migrations for removed expand form definition fields

* fix(slack): restore canvas_id fallback to data.id for backwards compat

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(jsm): explicit 400 when deprecated `emails` param is sent

Address greptile review on PR #4345: instead of silently dropping
`emails` and falling through to list-customers, return a 400 telling
the caller to use `accountIds`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(google_drive): include HTTP status in fallback error messages

Address greptile review on PR #4345: when Google Drive returns a non-JSON
error body, surface the response status/statusText so failures are
diagnosable instead of falling through to a generic message.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(ashby): drop stray websiteUrl→website remap for update_candidate

The update_candidate tool reads params.websiteUrl directly; mapping it
to result.website added a confusing dead field. The websiteUrl subBlock
auto-passes through with the matching name.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(google_drive): rename canonical params to avoid subBlock ID clash

`mimeType`, `query`, and `pageSize` canonical IDs collided with existing
subBlock IDs in the same block (failing the canonical-param validation
test). Drop the canonicalParamId from search/get_content single-input
fields and route them to tool params explicitly in tools.config.params.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(ashby): remove filterCandidateId from removed-subblock migrations

The candidate-id filter was reintroduced as a valid Ashby subBlock, but
the migration map still rewrote it to _removed_filterCandidateId on every
workflow load, silently breaking the field. Drop the entry so user values
persist.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(ashby): restore documented response fields dropped during refactor

Restore three fields that exist in Ashby's API responses but were dropped
during the recent refactor: applicationLimitCalloutHtml on /jobPosting.info,
compensation on /job.info (and add the `compensation` expand), and managerId
on /user.list.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* correctness

* updated types

* fix(ashby): gate operation-specific param mappings to prevent stale overwrites

Multiple subBlocks share the same target tool param (createdAt is set by
appCreatedAt/candidateCreatedAt/noteCreatedAt; candidateId by appCandidateId/
filterCandidateId). Because subBlock values persist across operation switches,
a stale value from a prior operation could silently overwrite the correct one.
Guard each mapping with an explicit operation check.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(ashby): gate offerApplicationId mapping by operation

Same shared-target hazard as the prior fix: offerApplicationId maps to
result.applicationId without an operation guard, so a stale value from
list_offers could overwrite the active applicationId on get_application,
change_application_stage, or list_interviews.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(ashby): include list_locations in includeArchived condition

Ashby's /location.list accepts includeArchived per the API docs, and the
docs page already documents the toggle for list_locations. Add the missing
operation value so the toggle renders.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(jira): forward explicit notifyUsers=true query param on issue update

Block now distinguishes true/false/undefined for notifyUsers, but the route
collapsed true and undefined into a no-param request. Forward the explicit
true intent so it survives any future API default change or proxy override.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(jira): quote project key in JQL to defend against injection

* fix(jira): quote project key in bulk_read JQL for defense in depth

The alphanumeric regex check above already blocks injection, but quoting
the project key matches the pattern used elsewhere (issues/route.ts) and
hardens the path against future regex changes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 19:08:23 -07:00
Waleed 7d8ec24768 feat(firecrawl): add parse operation and revert short-input selection style (#4340)
* feat(firecrawl): add parse operation and revert short-input selection style

* chore(firecrawl): regenerate docs and integrations data for parse

* fix(firecrawl): forward firecrawl error body in parse route response

* fix(firecrawl): add pricing config to parse tool hosting
2026-04-29 12:04:12 -07:00