Skip to content

improvement(salesforce): align tools + block with Salesforce API and harden CRUD/analytics#5040

Merged
waleedlatif1 merged 5 commits into
stagingfrom
investigate/salesforce-tools
Jun 14, 2026
Merged

improvement(salesforce): align tools + block with Salesforce API and harden CRUD/analytics#5040
waleedlatif1 merged 5 commits into
stagingfrom
investigate/salesforce-tools

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Migrated all 4 Account tools to the shared getInstanceUrl + extractErrorMessage helpers (dropped ~40 lines of inlined idToken decode per file); every CRUD tool now uses extractErrorMessage consistently and the opportunity tools gained loggers
  • Trimmed ID path params on all update/delete/single-get tools and URL-encoded single-record field lists to prevent copy-paste 404s
  • Fixed the dashboard tools: get_dashboard/refresh_dashboard now read name/metadata from dashboardMetadata.attributes (previously always null); refresh_dashboard returns status/statusUrl defensively across both documented response shapes; dropped the no-op list_dashboards folderName filter
  • Exposed update_case origin/contact/account and update_task who/what fields end-to-end (params → body → block subBlocks)
  • Block: marked create-required fields (Name, LastName, Company, StageName, Subject) and update/delete IDs conditionally required; added account billing*/revenue/employees and contact mailing*/department subBlocks; converted includeDetails to a Yes/No dropdown; moved optional fields to advanced mode
  • Trimmed over-declared dashboard output types, made Task.Status optional, regenerated integration docs

Type of Change

  • Bug fix / improvement

Testing

Tested manually — typecheck clean (0 Salesforce errors), biome lint clean, docs regenerated. Validated every tool + the block against the live Salesforce REST/Analytics API docs via parallel subagent audits. Fully backwards-compatible: no tool IDs or input params removed (except a no-op filter), output removals are always-null phantom fields, new required/advanced flags are UI-only.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…harden CRUD/analytics

- Migrate all 4 Account tools to shared getInstanceUrl + extractErrorMessage helpers (drop ~40 lines of inlined idToken decode per file)
- Use extractErrorMessage consistently across every CRUD tool; add loggers to the opportunity tools
- Trim ID path params on all update/delete/single-get tools; URL-encode single-record field lists
- Fix dashboard tools: read name/metadata from dashboardMetadata.attributes (was always null); refresh now returns status/statusUrl defensively; drop no-op list_dashboards folderName filter
- Expose update_case origin/contact/account and update_task who/what fields end-to-end
- Block: mark create-required (Name, LastName, Company, StageName, Subject) and update/delete IDs conditionally required; add account billing*/revenue/employees and contact mailing*/department subBlocks; convert includeDetails to a Yes/No dropdown; move optional fields to advanced mode
- Trim over-declared dashboard output types; make Task.Status optional
- Regenerate integration docs
@vercel

vercel Bot commented Jun 14, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 14, 2026 3:07am

Request Review

@cursor

cursor Bot commented Jun 14, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches many CRM write/delete paths and changes some dashboard output shapes; behavior is mostly corrective but workflows depending on removed folder filters or old dashboard fields could need updates.

Overview
This PR hardens and aligns the Salesforce integration across tools, the workflow block, types, and generated docs.

Shared tooling: CRUD and query tools now route instance URLs and API errors through getInstanceUrl, extractErrorMessage, and the new requireId helper instead of duplicated idToken parsing. Record IDs are trimmed (and validated) on paths and relation fields; single-record GETs URL-encode fields. Create responses treat success/created as strictly boolean.

Analytics: list_reports / list_dashboards parse top-level API arrays correctly and drop ineffective folderName filtering; report search is name-only. get_dashboard / refresh_dashboard read names and metadata from dashboardMetadata.attributes, expose dashboardMetadata and statusUrl, and adjust output types accordingly.

Updates & UI: update_case and update_task gain origin/contact/account and who/what fields end-to-end. The Salesforce block adds account billing and contact mailing fields, operation-scoped required IDs and create fields, advanced mode for optional inputs, removes folder filter UI, and uses a Yes/No dropdown for includeDetails.

Docs: Integration MDX and integrations.json reflect the parameter and output changes.

Reviewed by Cursor Bugbot for commit e4cb146. Configure here.

Comment thread apps/sim/tools/salesforce/delete_account.ts
Comment thread apps/sim/tools/salesforce/get_opportunities.ts Outdated
Comment thread apps/sim/tools/salesforce/create_lead.ts
@greptile-apps

greptile-apps Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR hardens the Salesforce integration by centralising instance URL resolution and error extraction into shared helpers, trimming ID path params across all CRUD tools to prevent copy-paste 404s, fixing dashboard metadata field paths (dashboardMetadata.attributes), and extending update_case/update_task with origin/contact/account and who/what fields end-to-end.

  • Shared utilities: All Account tools (create/update/delete/get) now use getInstanceUrl + extractErrorMessage, removing ~120 lines of inline idToken decoding; a new requireId() helper trims and validates every record ID before it enters a URL.
  • Dashboard fixes: get_dashboard/refresh_dashboard now read name and metadata from dashboardMetadata.attributes (previously always null); refresh_dashboard defensively covers both dashboardStatus and status response shapes and surfaces statusUrl; the no-op folderName filters on list endpoints are removed.
  • Block improvements: Create-required fields are flagged required, update/delete IDs are conditionally required, new billing/mailing/revenue/employee subBlocks are exposed, and includeDetails is converted to a Yes/No dropdown.

Confidence Score: 4/5

Safe to merge after fixing the dashboard ID trimming gap — all other changes are clean refactors and additive features.

Both get_dashboard and refresh_dashboard validate the dashboard ID by calling .trim() to check for blank input, but then pass the original (untrimmed) value directly into the URL path. A whitespace-padded ID like " 01Zxxx " clears the guard and produces a malformed URL that Salesforce rejects with a 404. The requireId() helper introduced by this PR was designed for exactly this case and is applied consistently everywhere else, making this a straightforward two-line fix in each file.

apps/sim/tools/salesforce/get_dashboard.ts and apps/sim/tools/salesforce/refresh_dashboard.ts — both need requireId applied to dashboardId in their url() functions.

Important Files Changed

Filename Overview
apps/sim/tools/salesforce/utils.ts Adds requireId() helper that trims and validates ID params, consolidating a pattern previously duplicated across 10+ tools.
apps/sim/tools/salesforce/get_dashboard.ts Fixes dashboardMetadata field extraction in transformResponse, but the url() function validates dashboardId via trim() then injects the untrimmed value into the URL path — a whitespace-padded ID will pass the guard and hit Salesforce with a malformed request.
apps/sim/tools/salesforce/refresh_dashboard.ts Correctly handles dual response shapes (dashboardStatus vs status, componentData vs componentStatus), but has the same untrimmed dashboardId-in-URL bug as get_dashboard.ts.
apps/sim/tools/salesforce/list_dashboards.ts Correctly handles both bare-array and dashboards-wrapper response shapes from the analytics API; removes no-op folderName filter.
apps/sim/tools/salesforce/update_case.ts Adds origin/contactId/accountId params, uses requireId for caseId trimming, and switches to extractErrorMessage — all correct.
apps/sim/tools/salesforce/update_task.ts Adds whoId/whatId fields with proper trimming and exposes them in the block; uses requireId and extractErrorMessage consistently.
apps/sim/tools/salesforce/types.ts Output types trimmed to remove always-null phantom fields (folderId, refreshDate); dashboard metadata and statusUrl correctly added; Task.Status marked optional; new case/task params added to interfaces.
apps/sim/blocks/blocks/salesforce.ts Adds conditionally-required flags for create/update/delete IDs, exposes billing/mailing/revenue/employee subBlocks, converts includeDetails to dropdown, moves optional fields to advanced mode — all consistent with the tool params.
apps/sim/tools/salesforce/create_account.ts Removes 30-line inline idToken decode, delegates to getInstanceUrl/extractErrorMessage; now uses data.success === true for created/success fields.
apps/sim/tools/salesforce/list_reports.ts Removes folderName filter (field absent from list API response) and narrows searchTerm to name-only match; correctly handles bare-array response.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Tool request params] --> B{instanceUrl provided?}
    B -- Yes --> C[getInstanceUrl returns instanceUrl]
    B -- No --> D{idToken provided?}
    D -- Yes --> E[Decode JWT payload]
    E --> F{profile or sub claim?}
    F -- profile --> G[Extract host from profile]
    F -- sub --> H[Extract host from sub]
    G --> C
    H --> C
    D -- No --> I[Throw: instance URL required]

    C --> J{ID param present?}
    J -- Yes --> K[requireId: trim + validate]
    K -- empty --> L[Throw: ID required]
    K -- valid --> M[Build URL with trimmed ID]
    J -- No --> N[Build list/create URL]

    M --> O[Fetch Salesforce API]
    N --> O
    O --> P{response.ok?}
    P -- No --> Q[extractErrorMessage]
    Q --> R[Throw Error]
    P -- Yes --> S[transformResponse]
    S --> T[Return structured output]
Loading

Comments Outside Diff (1)

  1. apps/sim/tools/salesforce/get_dashboard.ts, line 43-48 (link)

    P1 The validation checks params.dashboardId.trim() to catch blank input, but then builds the URL with the original, untrimmed params.dashboardId. If a caller passes a dashboard ID with leading or trailing whitespace (e.g. " 01Zxxx ") the empty-string guard passes, but the space is embedded in the URL path, causing Salesforce to return a 404. Every other tool in this PR uses requireId() for exactly this reason — the helper both validates and returns the trimmed value.

Reviews (5): Last reviewed commit: "fix(salesforce): trim accountId in updat..." | Re-trigger Greptile

Comment thread apps/sim/tools/salesforce/get_opportunities.ts
Comment thread apps/sim/tools/salesforce/create_account.ts
- list_dashboards: GET /analytics/dashboards returns a bare top-level array, not a {dashboards} wrapper (fixes always-empty result)
- refresh_dashboard: statusUrl is returned at the top level of the PUT response, read it there first
- list_reports: the list resource only returns report name/id/url/describeUrl/instancesUrl, so drop the no-op folderName filter and match searchTerm on name only

Validated tool-by-tool against the live Salesforce REST/Analytics/Object-Reference docs (API v67.0).
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/tools/salesforce/create_account.ts Outdated
- Add shared requireId() guard so whitespace-only IDs fail fast instead of producing malformed /sobjects/Object/ empty-path requests (all update/delete/single-get tools)
- URL-encode the fields query value in get_opportunities and get_tasks single-record GETs (matching the other get_* tools)
- Reflect the Salesforce API success flag consistently across all create tools (success/created use data.success === true)
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/tools/salesforce/update_account.ts
Comment thread apps/sim/tools/salesforce/update_case.ts Outdated
- update/delete tools now return output.id from the trimmed ID so chained workflows never receive whitespace-padded IDs
- trim relation reference IDs (AccountId, ContactId, WhoId, WhatId) in create/update bodies to avoid Salesforce reference errors from copy-pasted whitespace
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/tools/salesforce/update_contact.ts
Last remaining untrimmed relation reference ID — update_contact now trims AccountId like the other create/update tools.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit e4cb146. Configure here.

@waleedlatif1 waleedlatif1 merged commit 32b380f into staging Jun 14, 2026
15 checks passed
@waleedlatif1 waleedlatif1 deleted the investigate/salesforce-tools branch June 14, 2026 03:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant