mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
2c7b1ca54dbf1f28a0dab86bf2b81afbde73faec
633
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0075ab9cf6 |
improvement(platform): remove tour, simplify sidebar/header, drop loading skeletons (#4354)
* improvement(platform): workspace UI/UX overhaul + integrations catalog Rework the workspace around the AI-workspace model: a Mothership home, a top-level Skills route, connected-credential and integration-detail pages, and a polished sidebar/settings surface. Replace the notifications store with a unified toast system (provider-level dismiss/pause, countdown ring). Integrations & catalog: - Add a BlockMeta layer (tags + catalog templates) scoped to catalog-visible integrations; every catalog integration carries >=7 grounded templates. - Rework the taxonomy: each block declares category tools|blocks|triggers. 3rd-party services are 'tools'; first-party primitives (postgres, mysql, knowledge, file, search, stt/tts, image/video generators, thinking, etc.) are 'blocks'. Versioned blocks follow the upgrade paradigm (old hidden, latest in toolbar/docs). - Generate integrations.json + tool docs canonically from block configs. Architecture & cleanup: - Consolidate block data extraction behind a single latest-version strategy (getCanonicalBlocksByCategory; version-consistent getBlockMeta). - Unify version-suffix handling in @sim/utils/string (stripVersionSuffix / isVersionedType, with tests); registry, generate-docs, tools/utils, and integrations all route through it. - Repair latent broken barrels, remove dead code, fix BlockMeta-related type errors and 5 broken docs links. Behavior-preserving for block execution and the toolbar's tool/block listing. * refactor(platform): remove forms, templates, and creators features Remove three standalone features and their supporting code: - Forms: form-deployment pages, API routes, execution path, and docs. - Templates: the template gallery (landing + workspace) and template APIs. - Creators: creator-profile routes and contracts. Add a super-user permissions module (lib/permissions/super-user) and an organizations API contract; update the audit/db/testing packages, billing, and the session/theme providers accordingly. * test(workflows): update archiveWorkflow update count after forms removal The forms feature was removed, dropping the form-table update from archiveWorkflow. Update the stale assertion from 8 to 7 tx.update calls. * upgrade * improvement(knowledge): polish tag filter dropdowns (#4816) * improvement(logs): object storage backed tracespans (#4787) * improvement(logs): obj storage backed tracespans * fix storage write context * fix tests * address comments * address comments * chore(db): remove migration 0219 to regenerate after staging merge Drops the 0219_robust_shard SQL, its snapshot, and the journal entry so the trace-spans/cost schema migration can be regenerated on top of the latest staging migration chain (avoids a number collision with staging's migrations). Co-authored-by: Cursor <cursoragent@cursor.com> * improvement(billing): accurate per-member usage via shared ledger helper Per-member/per-user usage in the org-member routes now adds the usage_log ledger to the currentPeriodCost baseline (which is no longer incremented), via a shared getOrgMemberLedgerByUser helper to avoid repeating the subscription→period→ledger lookup across the admin and member-facing routes. Co-authored-by: Cursor <cursoragent@cursor.com> * regen migrations * update migration * address comments * more code cleanup * incorrect type cast --------- Co-authored-by: Cursor <cursoragent@cursor.com> * improvement(providers): harden OpenAI-compatible providers + add tests (#4796) * improvement(providers): harden OpenAI-compatible providers + add tests * fix(vllm): let tool-loop errors propagate instead of returning silent partial success * fix(litellm): force tool_choice 'none' on final structured-output call The deferred final call used tool_choice 'auto', so the model could emit another tool_calls round instead of the structured answer, leaving content stale. Use 'none' (matching vLLM/Fireworks) on both the streaming and non-streaming final calls so the model must return the structured response. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(providers/ollama): drop tools from post-tool streaming call Ollama ignores tool_choice (not in its supported fields), so vLLM/Fireworks' tool_choice:'none' guard is a no-op here. Omit tools from the final streaming payload instead so the summarization turn can't emit dropped tool calls. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(litellm): spread payload into deferred final call so reasoning_effort carries over The non-streaming deferred finalPayload hand-picked fields and dropped reasoning_effort (and any future payload field), diverging from the streaming path which spreads ...payload. Spread payload here too for consistency. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(providers/ollama): restore enrichment TSDoc block Keeps parity with sibling Chat Completions providers (cerebras/mistral/xai). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(fireworks): restore TSDoc on utils helpers Restore the TSDoc blocks on supportsNativeStructuredOutputs, createReadableStreamFromOpenAIStream, and checkForForcedToolUsage — TSDoc is the codebase documentation standard and should not have been stripped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(litellm): remove inline rationale comments (codebase uses TSDoc) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(providers/ollama): drop orphaned enrichment TSDoc The block documented a function that now lives in trace-enrichment.ts, so it documents nothing in this file. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * chore(copilot): deprecate mcp server (#4797) * chore(copilot): deprecate mcp * update error codes * deprecate copilot api v1 route * feat(integrations): hosted API keys for Findymail, Prospeo, and Wiza (#4777) * feat(integrations): hosted API keys for Findymail, Prospeo, and Wiza Add hosted-key support across all credit-consuming Findymail, Prospeo, and Wiza operations so Sim provides the key when a workspace has not brought its own. Register the three BYOK providers, consolidate Wiza's two-step reveal into a single polling wiza_individual_reveal op, and hide the API key field on hosted Sim for hosted operations. * fix(integrations): harden Wiza reveal polling, soften enrichment getCost guards Address Greptile + Cursor Bugbot review on #4777: return explicit failures from the Wiza individual_reveal poller instead of throwing (thrown errors were swallowed into a false queued success), short-circuit when the initial reveal is already terminal, tolerate transient 5xx/429 during polling, and return 0 (not throw) from Findymail getCost when the contacts/employees array is absent. * chore(integrations): biome formatting after wiza merge resolution * fix(wiza): type isTerminalReveal param structurally for next build typecheck * feat(enrichments): add Findymail, Prospeo, Wiza to work-email waterfall * feat(enrichments): add Wiza + Prospeo phone reveal to phone-number waterfall * feat(enrichments): opportunistic identifiers + LinkedIn URL input across work-email & phone cascades * fix(tables): reduce column header chevron size and fix sidebar shadow bleed (#4800) * feat(slack): add install + privacy section to integration landing page (#4799) * feat(slack): add install + privacy section to integration landing page Adds a hand-authored, slug-keyed landing-content module (separate from the generated integrations.json so it survives regeneration) and renders an install walkthrough + privacy-policy link on integration pages when present. Also refreshes generated docs (data-enrichment entry, icon mappings, tool mdx). * fix(landing): render privacy section independently, align CTA analytics label * docs(landing): clarify the Slack install button is behind sign-in * refactor(landing): bake integration landing content into generated json via docs-gen Moves landing content (install walkthrough + privacy) out of a render-time augment and into the generation pipeline: generate-docs reads the pure-data content map and writes landingContent into integrations.json, so the page reads a single source (integration.landingContent). Canonical types live in integrations/data/types.ts. * improvement(enrichments): align enrichments sidebar with design system (#4801) * improvement(enrichments): align enrichments sidebar with design system * fix(enrichments): consistent close button pattern and fix url link hover * fix(misc): upgrade path change for new better-auth version, billing issue for workflow block agent usage (#4803) * fix(misc): upgrade path change for new better-auth version, double-billing for workflow block agent usage * fail loudly if stripe sub id missing * fix(copilot): seq migration (#4804) * chore(db): drop redundant idx_webhook_on_workflow_id_block_id index (#4809) Removed because (workflow_id, block_id) is a left-prefix of idx_webhook_on_workflow_id_block_id_updated_at_desc, which fully covers it. The dropped index was non-unique and enforced no constraint. * perf(copilot): read chat transcripts from copilot_messages (R+1 cutover) (#4808) * perf(copilot): read chat transcripts from copilot_messages, not JSONB Flip user-facing chat reads from the legacy copilot_chats.messages JSONB array (5.7GB, 99% TOAST) to the normalized copilot_messages table via a new loadCopilotChatMessages helper ordered by seq NULLS LAST, created_at, id — the verified canonical order. Both chat-detail getters (getAccessibleCopilotChat, getAccessibleCopilotChatWithMessages) now drop the messages column from their metadata select (no more whole-array detoast on every load) and assemble the transcript from the table after authorization. This cascades to the copilot + mothership GET endpoints and to resolveOrCreateChat's conversationHistory (the LLM payload). The normalize/effective-transcript pipeline is source-agnostic (copilot_messages.content == a JSONB array element), so transcripts are byte-identical. Dual-write and the JSONB column stay in place as the internal-logic source and fallback; removing JSONB writes is a later step. Prod integrity verified before cutover: 0 messages missing, 0 NULL-seq, 0 dup keys/seq, 0 orphans, order-parity vs JSONB = 0 mismatches. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(copilot): cover auth-deny on a found row skips the messages query Address PR review: exercise the `if (!authorized) return null` contract — when the chat row exists but authorization fails, the getter returns null and never issues the copilot_messages read. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(tables): right-align run/stop in embedded toolbar; workflow cells format like normal cells (#4806) * fix(tables): right-align run/stop in the embedded table toolbar Add a right-aligned `trailing` slot to ResourceOptionsBar and move the embedded mothership table's run/stop control into it, so Filter + Sort stay left-aligned and run/stop sits opposite on the right. No-op for the search-bearing consumers (logs, resource list), which don't pass `trailing`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(tables): workflow-output cells format values like normal cells Workflow-output columns short-circuited in resolveCellRender and rendered their value as plain text, so a sim-resource URL / external URL / JSON / date produced by a workflow never got the chip, favicon link, or typed formatting a normal cell gets. Factor value formatting into a shared `resolveValueKind` helper used by both the workflow-value branch and the plain-cell branch; the workflow branch keeps the typewriter reveal for plain streaming text via a `typewriter` flag. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(tables): detect resource/URL links on workflow output regardless of column type Workflow output columns default to `json` (columnTypeForLeaf), so routing their values through the type-based formatter (a) gated chip/URL promotion behind `column.type === 'string'` — a URL produced by a json-typed output never became a chip — and (b) JSON.stringify'd plain string values, adding quotes and losing the typewriter reveal. Detect links (sim-resource chip / favicon URL) on the value string directly for workflow outputs, falling back to the plain `value` kind; plain cells keep the type-based formatting. Addresses Greptile P2 on #4806. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(icons): repair broken integration icon rendering (#4810) * fix(icons): repair broken integration icon rendering Two distinct bugs left integration icons broken on the /integrations page (visible at 32-40px, hidden at the toolbar's 16px): 1. Corrupted SVG paths (Notion, Greptile, Granola, Calendly, Grafana, Bedrock): over-minified data dropped elliptical-arc flag digits (e.g. `A1 1 0 5.9 7` instead of `A1 1 0 0 0 5.9 7`); Granola's cubic stream was truncated. Browsers abort path parsing at the first invalid arc flag, so each rendered as a fragment or blank. Replaced with correct path data from canonical sources, preserving each icon's existing fill/gradient and bgColor. 2. Invisible glyph (Bright Data): its icon uses fill='currentColor' but bgColor was '#FFFFFF', and every surface forces text-white on the glyph - white-on-white. Changed bgColor to Bright Data's brand blue (#3d7ffc) so the white glyph reads, matching the white-glyph-on-brand-chip convention. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): restore Calendly dual-tone brand colors Addresses review feedback: the previous fix replaced the broken Calendly icon with a monochrome #006BFF path, dropping the cyan #0ae8f0 accent from the original dual-tone mark. Restored the two-tone logo (blue + cyan) using clean, valid path data, cropped to a tight square viewBox so it fills the chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge icons, fix Zoom contrast and Quiver chip - Zoom: glyph was blue-on-blue (#0B5CFF on #2D8CFF chip); switched to currentColor so it renders as a white glyph on the blue chip. - Quiver: chip bgColor #000000 -> #FFFFFF to match the icon's near-white box, and enlarged the mark slightly (viewBox crop). - Enlarged (tightened viewBox, verified no clipping): RevenueCat, Prospeo, Granola, Firecrawl, Enrich.so, and the AWS icons (RDS, DynamoDB, SQS, CloudFormation, Athena, CloudWatch, SES, Bedrock, S3). - ZoomInfo left unchanged: it is a full red rounded-square logo that already fills its frame, so a crop would clip it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): use Bright Data wordmark on white chip; repair Circleback - Bright Data: replaced the flame glyph with the official two-tone 'bright data' wordmark (provided asset), centered in a symmetric viewBox. Reverted the chip bgColor from #3d7ffc to #FFFFFF since the blue wordmark is invisible on a blue chip (the wordmark is designed for a light background). - Circleback: a minifier had rounded the pattern's image scale to scale(0), collapsing the embedded logo to zero size (invisible). Restored the correct scale (1/280 = 0.00357142857) so the C. mark renders. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(docs): sync Quiver block color card to white chip Reflects the Quiver bgColor change (#000000 -> #FFFFFF) in the docs block info card. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge AWS/Cloudflare/Dagster icons, fully white Zoom - Enlarged (tighter viewBox, render-verified, no clipping): Cloudflare, Dagster, and the red AWS icons AWS IAM, Identity Center, Secrets Manager, SES, STS. Identity Center was anomalously small (filled ~32% of its frame); the group is now sized consistently (~80% fill). - Zoom: the camera lens triangle was still #0B5CFF (blue-on-blue); switched it to currentColor so the whole camera renders white on the blue chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(wiza): consolidate individual reveal into a single operation Merges the separate Start/Get Individual Reveal operations into one Individual Reveal operation in the Wiza docs and integrations data (operationCount 5 -> 4). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): size remaining AWS icons to match the set (~80% fill) Bring RDS, DynamoDB, SQS, CloudFormation, Athena, CloudWatch and S3 up to the same ~80% fill as the AWS IAM/Identity Center/Secrets Manager/SES/STS group, so all AWS icons are visually consistent. Bedrock left as-is (already ~92% fill). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): use Bright Data flame mark, enlarge ZoomInfo - Bright Data: the full 'bright data' wordmark was illegible at chip size. Replaced with just the flame-'i' brand mark (blue #4280f6 on the white chip), centered. - ZoomInfo: cropped the viewBox toward the white 'Zi' so it's larger; the red rounded-square background still fills the chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge CrowdStrike icon The falcon mark sat small in its chip because the icon used a wide 768x500 viewBox (letterboxed in the square chip). Switched to a square viewBox centered on the mark so it fills ~80%, consistent with the other icons. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(tables): serialize schema mutations to prevent parallel column clobber (#4812) * Make workflow description nullable * fix(tables): serialize schema mutations to prevent parallel column clobber * fix(tables): load workflow outside schema lock; use DbOrTx for getTableById * fix(tables): scale idle timeout in updateColumnType to avoid aborting large type changes * fix(tables): skip stale remap types when workflowId changes concurrently * fix(tables): scale idle timeout in updateColumnConstraints for large tables * fix(wait): resume live/draft async waits and preserve cell context on chained waits (#4814) * Make workflow description nullable * fix(wait): resume live/draft async waits and preserve cell context on chained waits * improvement(knowledge): polish tag filter dropdowns * improvement(knowledge): soften filter section labels * improvement(knowledge): soften list filter labels * fix(security): harden SSO domain registration, webhook path isolation, and CSV export (#4813) * fix(security): harden KB file access, SSO domain registration, webhook path isolation, env secrets, and CSV export * fix(sso): scope domain conflict query with indexed lower(domain) filter Address PR review: avoid a full-table scan on every SSO provider registration by filtering candidate rows in SQL with lower(domain) = <normalized>, keeping the in-memory ownership check. Also tighten the normalizeSSODomain TSDoc. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: condense env route security comments Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * icons update * chore(security): tighten inline comments in CSV export and KB file authorization Condense verbose comment blocks to concise TSDoc/single-line form; no behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): validate internal serve origin in KB file authorization Replace the bypassable isInternalFileUrl substring check in resolveInternalKbKey with an origin allow-list (base URL, internal API base URL, TRUSTED_ORIGINS). A crafted external host whose path is /api/files/serve/<victim-key> no longer resolves to the victim key. Relative same-origin URLs are unaffected. * style(sso): use idiomatic sql lower() comparison for domain conflict query Match the repo's prevailing `sql`lower(col) = value`` idiom for the case-insensitive SSO domain conflict lookup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): align workspace env admin gate with hasWorkspaceAdminAccess Use the same admin check the secrets UI uses (owner, admin permission, or org-admin) so owners and org-admins are not wrongly denied their own decrypted workspace secrets, while read-only members remain restricted to names only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(sso): rely on lower(domain) match for conflict detection, drop dead in-memory recheck Address PR review: the SQL `lower(domain) = <normalized>` predicate already excludes rows that the in-memory `normalizeSSODomain(...) === domain` recheck claimed to catch, making that recheck dead/misleading code. Match on the canonical lower-cased domain and filter purely by ownership. Malformed legacy values (wildcards, schemes, ports) never match an email domain at sign-in, so excluding them is not a gap. Test DB mock now applies the lower() predicate so the casing-variant case is genuinely exercised. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): scope webhook deploy path conflict to active webhooks findConflictingWebhookPathOwner omitted the isActive filter that the runtime dispatcher (findAllWebhooksForPath) applies, so an inactive but non-archived webhook from another workflow (e.g. after undeploy or failure auto-disable) would permanently block any new deployment on that path even though it never receives deliveries. Align the guard with the runtime isActive + archivedAt filter; the earliest-owner runtime check remains the authoritative cross-tenant protection. Also trims verbose TSDoc on the webhook path-isolation helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): exclude archived workflows from webhook deploy path conflict findConflictingWebhookPathOwner now joins workflow and filters isNull(workflow.archivedAt), matching the runtime dispatcher (findAllWebhooksForPath). A webhook on an archived workflow can never receive deliveries at runtime, so it must not block legitimate path reuse with a 409. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): anchor KB file ownership to earliest document in any state A KB file's owner is now the earliest document referencing its key regardless of state (active/archived/deleted/excluded); access is granted only when that owning document is still active. Closes the residual where an attacker could plant an active document to claim a file whose original document was archived or deleted. * updated greptile icon * revert(security): drop KB file authorization changes Reverts the knowledge-base file-access work (origin-pinning / owner-pinning / origin allow-list in verifyKBFileAccess) and its test. The other hardening fixes (SSO domain registration, webhook path isolation, workspace env secrets, CSV export) are unchanged. apps/sim/app/api/files/authorization.ts is restored to its origin/staging baseline. * fix(sso): treat caller's own user-scoped provider as owned during conflict check Self-hosters often register SSO user-scoped via the CLI script (no SSO_ORGANIZATION_ID). If they later enable organizations and reconfigure the same domain org-scoped through the UI, the conflict check previously treated their own user-scoped row as another tenant's and returned a misleading 409. Recognize the caller's own user-scoped provider as owned so that migration is allowed, while still blocking another user's or another org's domain. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * revert(security): remove workspace-env admin gate Defer to a credential-based access model (separate change). Restores GET /api/workspaces/[id]/environment to main behavior and removes the test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(security): consolidate webhook path-collision check into one helper Extract findConflictingWebhookPathOwner to lib/webhooks/utils.server.ts as the single source of truth for cross-tenant path-collision detection, used by both webhook creation paths (deploy sync and the manual /api/webhooks route). This also repairs two latent issues in the manual route's previous inline check, which queried with limit(1) and only webhook.archivedAt: - limit(1) inspected one arbitrary row, so a same-workflow row could mask a foreign collision (false negative). The shared helper scans all matching rows. - It omitted isActive/workflow.archivedAt, so inactive or archived-workflow webhooks (which never receive deliveries) permanently blocked path reuse. The helper mirrors the runtime dispatcher's filter. Same-workflow webhook reuse for upsert is now a separate, explicit lookup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): block private/reserved IPs for hosted 1Password Connect SSRF (#4818) * fix(security): block private/reserved IPs for hosted 1Password Connect SSRF * test(security): use real isPrivateOrReservedIP and cover IPv6 edge cases * improvement(integrations): validate and expand devin, cursor, and greptile (#4820) * improvement(integrations): validate and expand devin, cursor, and greptile - devin: fix missing org_id path segment on all session endpoints, add 7 session sub-resource tools (list messages/attachments, get/append/replace tags, archive, terminate), pagination, and is_archived output - cursor: add get_api_key_info, list_models, list_repositories tools - greptile: align block and docs - normalize array outputs to default [] and tighten types * refactor(cursor): simplify list_repositories v2 array normalization Collapse the redundant `?? []` + `Array.isArray` double-guard into a single Array.isArray check, per PR review feedback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(devin): scope session-tag mapping to tag ops and normalize array tag inputs - Only map sessionTags into the tools tags param for append/replace operations, preventing stale sessionTags state from clobbering create_session tags - Fall back to a wired tags value when sessionTags is empty for tag operations - Normalize tag inputs (string or wired string[]) via normalizeTags so array values from other blocks no longer throw on .split Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(cursor): restore base64 file data in legacy download_artifact metadata The legacy CursorBlock exposes only content + metadata (no v2 file output), so metadata.data was the only way legacy-block workflows could access downloaded artifact bytes. Restore the base64 data field and document it in the outputs/type instead of dropping it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(devin): coerce terminateArchive to archive flag for boolean-wired input * docs(integrations): regenerate tool docs for new devin and cursor operations --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(search-replace): don't auto-navigate when content edits invalidate the active match (#4819) * fix(search-replace): don't auto-navigate when content edits invalidate the active match * fix(search-replace): clear afterReplaceIndexRef on apply failure and zero matches * fix(search-replace): remove duplicate setActiveSearchTarget(null) on close * fix(search-replace): move afterReplaceIndexRef write inside handleApply past the guard * fix(search-replace): auto-navigate when hydration resolves with no prior active match * chore(search-replace): remove inline comments * fix(search-replace): revert !activeMatchId guard that caused immediate re-navigation after deselect * improvement(enrichments): limit company-info to fields both providers return (#4817) Hunter's company dataset returns null industry/foundedYear for many large companies (verified against the live API for Microsoft, Amazon, Google), so under the first-non-empty-wins cascade those columns appeared inconsistently across rows. Limit company-info outputs to employee count and description — the fields Hunter and PDL both reliably return — so every row is consistent. employeeCount is a string so Hunter's range bucket and PDL's exact count share the column. * fix(files): don't reject external URLs containing '..' in file parse validation (#4821) * fix(files): don't reject external URLs containing '..' in file parse validation The file block's file_fetch operation rejected any external URL whose path contained '..' (e.g. Slack files-pri slugs with a literal '...') with 'Access denied: path traversal detected'. Traversal checks only apply to local paths — external http(s) URLs are fetched with SSRF protection downstream and are never resolved against the filesystem, so they now short-circuit as valid. Internal /api/files/serve/ URLs keep full traversal protection. * test(files): fix external-URL assertion to handle undefined error * test(files): assert success explicitly in external-URL traversal test * fix(files): keep traversal protection for https URLs matching internal serve paths * feat(google-sheets): add row filtering to read with numeric operators (#4822) * feat(google-sheets): add row filtering to read with numeric operators Adds client-side row filtering to the Google Sheets read (v2) operation. Filter the returned rows by a header column using text operators (contains, not_contains, exact, not_equals, starts_with, ends_with) and numeric/ordering operators (gt, gte, lt, lte). Filtering lives in a pure, unit-tested helper (filterSheetRows) and runs over the fetched read range; an optional `filter` output reports whether the column was found and how many rows matched. Also hardens the surrounding tools: - trim spreadsheetId in write/update/append URL builders (matches read) - URL-encode the v1 read default range - expose valueInputOption for the update operation in the block Backwards compatible: with no filter requested, read output is byte- identical and the `filter` field is omitted. The filterMatchType union is widened additively (4 -> 10 values). * fix(google-sheets): correct filter metadata for missing column and header-only sheets - matchedRows is now 0 (not totalRows) when the filter column is not found, so it no longer contradicts applied=false / columnFound=false - columnFound now reflects an actual header lookup for empty/header-only sheets instead of being hardcoded true - add tests covering header-only and empty sheets with present/absent columns * fix(selectors): fetch all pages for paginated dropdown list routes (#4823) * fix(selectors): fetch all pages for paginated dropdown list routes Dropdown selectors fetched only the first page of paginated provider APIs, silently hiding results past page one. Add bounded server-side draining to the list routes across Microsoft Graph, Google, Notion, Atlassian, Linear, AWS CloudWatch, and offset/token REST APIs, plus a shared client-side drain cap in the selector hook. Response shapes, stored values, and tool execution are unchanged; CloudWatch list tools still honor a caller-supplied limit. Also fixes the Word file picker that was searching for .xlsx files. * fix(selectors): harden JSM and Monday pagination draining - JSM service-desk/request-type drains advance `start` by the actual row count returned (not the fixed page size) and stop on an empty page, so a short non-final page can't skip items. - Monday boards drain now checks `response.ok` per page, surfacing a mid-drain HTTP failure instead of treating it as an empty final page and returning a partial 200. * docs(selectors): clarify JSM drain advances start by actual row count The offset-advancement fix (advance `start` by the rows returned, not the fixed page size) landed in 7b19788a8; update the TSDoc to match so it no longer reads as advancing by `limit`. * fix(selectors): drain fetchPage in direct fetchList callers Making `fetchList` optional left three direct callers (outside the useSelectorOptions hook) calling it unguarded, which broke the build's type check. Route them through a shared `loadAllSelectorOptions` helper that uses `fetchList` when present and otherwise drains `fetchPage`. This also prevents a regression: `confluence.spaces` / `knowledge.documents` now paginate via `fetchPage` only, and these callers (search/replace, value resolution) would otherwise have silently returned no options. * chore(selectors): rename MAX_PAGE_PAGES to MAX_NOTION_PAGES for readability * fix(sso): re-check domain conflict before write and reject IP-address domains (#4825) * improvement(copilot): make copilot_messages the sole transcript store, remove JSONB dual-write (#4826) Stop writing/reading the legacy copilot_chats.messages JSONB column now that reads are cut over to copilot_messages. Make appendCopilotChatMessages the primary write (throws on failure instead of swallowing), repoint peripheral readers (workspace VFS, chat cleanup, data drains, fork, superuser import) to copilot_messages, and persist the assistant turn inside finalizeAssistantTurn's transaction so it commits atomically with the stream-marker clear. The column itself is dropped in a follow-up migration after this bakes. * feat(tables): expand filter operators (not-contains, starts/ends-with, not-in, empty) (#4827) Add does-not-contain ($ncontains), starts-with ($startsWith), ends-with ($endsWith), not-in-array ($nin, previously executed server-side but unexposed in the UI), and is-empty/is-not-empty ($empty) filter operators end-to-end — SQL builder, condition types, query-builder converters/constants, the filter UI, the Table tools/block descriptions, and docs. Also fix correctness bugs in the filter builder surfaced by the wider operator set: - Same-column AND rules (e.g. age > 18 AND age < 65, or name startsWith 'A' AND name endsWith 'Z') silently overwrote each other because the AND group was keyed by column name. They now merge into one operator object, which also makes Filter -> rules -> Filter round-trip losslessly for multi-operator columns. - $nin values were not split into an array like $in, and textual-match values like "123" were numeric-coerced (breaking the ILIKE path). - A non-boolean $empty operand from the raw API silently inverted the check; it now coerces 'true'/'false' strings and otherwise returns a 400. * improvement(copilot): stop persisting tool-call result outputs in transcripts (#4829) Opening a Mothership task could take many seconds because a single persisted assistant message in copilot_messages.content can reach hundreds of MB, almost entirely inside contentBlocks[].toolCall.result.output (e.g. a get_workflow_logs or run_workflow result). The DB query is ~2ms; the cost is detoasting that payload, shipping it to the browser, and parsing it. These outputs are dead weight on the Sim side: they are never rendered (the thread shows only tool name/title/status) and never replayed to the model (the upstream copilot service owns conversation memory). So drop result.output before it is persisted, keeping result.success/error plus the tool metadata. - add stripToolResultOutput() in persisted-message.ts - apply it in messages-store toRow (covers every write path) and in loadCopilotChatMessages (existing rows render fast on read) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * feat(providers): add Together AI, Baseten, and Ollama Cloud model providers (#4830) * feat(providers): add Together AI, Baseten, and Ollama Cloud model providers * fix(providers): guard Ollama streaming fast-path with hasActiveTools Match Together/Baseten/Fireworks: when tools are supplied but all are filtered out (usageControl 'none'), take the single streaming call instead of an extra non-streaming round-trip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(providers): filter non-chat model types from Together model list * refactor(providers): dedupe Ollama Cloud upstream schema ollamaCloudUpstreamResponseSchema was byte-for-byte identical to ollamaUpstreamResponseSchema (both /api/tags endpoints return the same { models: [{ name }] } shape). Drop the duplicate and reuse the shared schema. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(knowledge): calendar view sync, deduplicate popover animation classes, type-safe filter cast * cleanup(knowledge): remove TRIGGER_BORDER_CLASS duplication, inline displayLabel, drop enabledFilterParam alias --------- Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Waleed <walif6@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Theodore Li <theo@sim.ai> Co-authored-by: andresdjasso <andresdjasso@users.noreply.github.com> * feat(blocks): add BlockMeta to Quiver and Linq; fix invalid block config fields; update skills Block fixes: - Add QuiverBlockMeta (tags + 3 templates: icon generator, diagram creator, vectorizer) - Fix QuiverBlock: remove invalid tags field from BlockConfig, IntegrationType.Design → IntegrationType.AI (Design doesn't exist in the enum) - Fix GreptileBlock: remove invalid tags field from BlockConfig, IntegrationType.DeveloperTools → IntegrationType.DevOps - Fix LinqBlock: remove invalid tags field from BlockConfig (tags belong only in BlockMeta) Skills: - add-block: add dedicated BlockMeta section with structure, rules, and registration pattern; add BlockMeta checklist items - add-integration: add BlockMeta to block structure template, add rules clarifying that tags must NOT appear on BlockConfig and integrationType must be a valid enum value; update registry snippet to include blocksMeta; add checklist items * fix(integrations): fix category dropdown by defining missing LANDING_INTEGRATIONS_DATA_PATH and regenerating integrations.json The staging merge introduced landing-content.ts but forgot to define LANDING_INTEGRATIONS_DATA_PATH in generate-docs.ts, causing the script to crash before writing integrations.json. The stale JSON had integrationTypes (plural array) from an older script version, while the Integration type and workspace UI both read integrationType (singular string) — so ALL_CATEGORY_SECTIONS bucketed to undefined and the category filters never appeared in the dropdown. Fixed by adding the missing path constant and re-running the generator. integrations.json now has 192 entries with the correct integrationType field. * fix(sidebar): restore resize handle on all pages commit |
||
|
|
24a6086d95 |
feat(tables): fractional order keys for O(log n) row insert/delete (flag-gated, default off) (#4890)
* feat(tables): add order_key column, fractional-indexing util, and ordering flag (off)
* feat(tables): write order_key on insert, flag-gate delete reindex + query ordering, add backfill
Flag off (default) = identical behavior. Single-insert assigns a fractional
order_key; queryRows orders by order_key when the flag is on; deletes skip the
O(N) reindex when on. Per-table-atomic backfill script populates existing rows.
* feat(tables): write order_key on all insert paths (batch, upsert, replace, import, create, copilot)
Completes the always-write-keys prerequisite: every row insert now assigns a
fractional order_key consistent with position order, so the flag can be flipped
safely after backfill. Flag off (default) still = identical behavior.
* feat(tables): insert-by-neighbor-id + orderKey on wire + client order-by-key
Inserts express intent as afterRowId/beforeRowId (O(1) key mint via the
(table_id,order_key,id) index); orderKey is returned on every row; client
reconcile/undo place by orderKey (no neighbor bump) with position fallback.
Flag off = unchanged. 205 table tests pass.
* feat(tables): resolve position-based inserts by key ordinal under the flag
Position-based callers (mothership tool, v1 API, undo fallback, transient old
clients) resolve their insert neighbor by order_key ordinal (OFFSET) when the
flag is on — positions are gappy then, so WHERE position=N would miss. Flag off
keeps the indexed position lookup. The mothership tool itself is unchanged.
* test(tables): flag-on coverage — delete skips reindex, insert mints key + no shift
* fix lint
* chore(db): regenerate order_key migration with default drizzle name
* fix(tables): address review — guard neighbor insert + mutual-exclusion + safe reconcile
- resolveInsertByNeighbor throws when the anchor row is missing (was silently
inserting at the front) and when its order_key is null under the flag.
- insert contract: afterRowId/beforeRowId are mutually exclusive (refine).
- reconcileCreatedRow only key-sorts when every cached row is keyed, so mid-
backfill un-keyed rows aren't yanked to the front.
* fix(kb): restore non-null guard in storage-key filter (unsafe-lint regression)
* refactor(tables): extract maxOrderKey + thread import append key
- Extract maxOrderKey(executor, tableId) helper; replaces three identical
max(order_key) selects (single/batch insert append + import).
- Import: read the append anchor once up front and thread each batch's last
key forward (nextImportStartOrderKey + afterOrderKey) instead of re-scanning
max(order_key) per batch over a growing table — one scan per import, not
one per 1k-row batch.
* fix(tables): keep insert body base omittable for v1 contract
The afterRowId/beforeRowId mutual-exclusion .refine() turned the schema into a
ZodEffects, which Zod forbids .omit() on — v1's insertTableRowBodySchema.omit({
position }) threw at module load (runtime-only; tsc misses it). Split the plain
object base out, apply the shared refine on top, and have v1 omit from the base
then re-apply it.
* fix(tables): chunk backfill order-key writes
A single UPDATE … FROM (VALUES …) over a whole large table overflows the JS call
stack while drizzle assembles the VALUES list (and would blow past Postgres's
65535 bound-param limit at ~32k rows) — large tables failed with 'Maximum call
stack size exceeded'. Write in 1000-row chunks inside the same per-table
transaction so keying stays atomic.
* fix(tables): emit orderKey in insert responses
The single-row and batch insert handlers dropped orderKey from the JSON
response even though the service returns it, so reconcileCreatedRow always fell
back to position-sorting and could place neighbor inserts wrong under the
fractional-ordering flag. Serialize orderKey alongside position.
* fix(tables): restore by orderKey, not position, under fractional flag
A saved position is the gappy column value, but under the flag insert reads
position as a visual rank (OFFSET) — so position-based restore misplaces rows.
- create-row redo now goes through the batch path carrying the saved orderKey
(the single-insert API has no orderKey field); drop the now-unused single
create mutation.
- resolveBatchInsertOrderKeys appends under the flag instead of feeding gappy
positions to resolveInsertOrderKey; positions remain the flag-off path.
* perf(tables): backfill writes 5000 rows/chunk (was 1000)
5x fewer round-trips per table; ~10k bound params stays well under Postgres's
65535 ceiling and far below the single-statement size that overflows the stack.
* fix(tables): drop rowNumber from table trigger payload
position is gappy under the fractional-ordering flag, so rowNumber (= row.position)
no longer reflects a contiguous visual rank. Rather than compute-on-read, remove
it from the trigger payload, output schema, and column-execution input.
Also pin isTablesFractionalOrderingEnabled=false in update-row.test.ts so its
flag-off position-shift assertions are deterministic regardless of local env.
* chore(db): format generated 0226 migration metadata
biome check . flagged the drizzle-generated _journal.json and 0226_snapshot.json;
apply the formatter so packages/db lint:check passes in CI.
* docs(triggers): drop rowNumber from table trigger outputs
rowNumber was removed from the table trigger payload; remove it from the
documented output fields to match.
* test(tables): remove flag-on fractional-ordering unit suite
Flag-on behavior is covered by manual large-table verification; the heavily-
mocked DB-chain suite added little signal.
|
||
|
|
16954e46fe |
feat(integrations): add ClickHouse block and expand Dagster + Tinybird tools (#4883)
* feat(integrations): add ClickHouse block and expand Dagster + Tinybird tools
* fix(tinybird): fail loudly on invalid query_pipe parameters JSON
parsePipeParameters previously returned {} on any JSON parse error, so a
mistyped 'parameters' input produced a successful pipe call with the dynamic
filters silently dropped. Throw a clear error for non-empty, non-object input
instead; an omitted/empty value still means 'no parameters'.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(dagster): guard NaN numeric coercions and bound list_assets pagination
Address PR review:
- Route all block numeric coercions (list_runs limit/createdAfter/createdBefore,
get_run_logs logsLimit, list_assets assetsLimit) through a toFiniteNumber()
guard so invalid/wand-generated text becomes undefined instead of NaN.
- list_assets now applies a default page size (100) when no limit is given, so
paging stays bounded and hasMore is meaningful even when limit is omitted.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(dagster): make list_assets hasMore exact via fetch N+1
Address PR review (hasMore true on exact page): request one extra row
(pageSize + 1), use its presence as the authoritative hasMore, slice it off,
and derive the returned cursor from the last RETURNED asset's key path
(JSON-serialized; Dagster normalizes JS/Python whitespace on the way in).
This removes the false-positive hasMore when the final page is exactly full.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(clickhouse): enforce read-only query operation and harden WHERE-clause guard
* fix(dagster): make list_runs hasMore exact via fetch N+1
Address PR review (list runs false hasMore): request one extra row
(pageSize + 1), use its presence as the authoritative hasMore, and slice it
off before mapping. Removes the false-positive hasMore (and misleading cursor)
when the final page is exactly `limit` runs long. Mirrors the list_assets fix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(clickhouse): restrict DROP PARTITION to literal values to prevent SQL injection
* fix(clickhouse): reject chained statements in read-only query operation
* fix(clickhouse): force JSON output on query path and ignore comments when detecting chained statements
* fix(tinybird): encode datasource/pipe names in URL paths to prevent traversal
A user-or-llm datasource/pipe name interpolated raw into the URL path (e.g.
'real_ds/../../other') is normalized by the WHATWG URL parser and can target a
different endpoint. Wrap the path segment with encodeURIComponent in the
truncate, delete, and query_pipe URLs. Events/append pass the name via
URLSearchParams, which already encodes, so they were unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(clickhouse): block WITH-led writes/DDL in read-only query operation
* fix(clickhouse): validate column types structurally and normalize FORMAT around SETTINGS
* fix(clickhouse): balance-check ORDER BY/PARTITION BY and skip leading comments in read-only guard
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
2ccd9a3ac5 |
feat(connectors): add 7 knowledge base connectors (Google Forms, Typeform, Azure DevOps, YouTube, JSM, S3, Sentry) (#4880)
* feat(connectors): add 7 knowledge base connectors (Google Forms, Typeform, Azure DevOps, YouTube, JSM, S3, Sentry) * fix(connectors): tighten listingCapped semantics per review (WIQL cap, batch omissions, cap-vs-exhaustion) * fix(connectors): google-forms listingCapped must fire on slice regardless of hitLimit (404-null-filter gap) * fix(connectors): s3 streaming size cap for chunked responses without content-length * fix(connectors): ado byte-exact file content fetch, google-forms hash-poisoning on listing failure * fix(connectors): ado auth-failure deletion guard, jsm last-page slice flag, google-forms response cap in hash * fix(connectors): shared streaming size-cap reader for ado file hydration (promote from s3) * fix(knowledge): flag incomplete listings at engine level when pagination is truncated * fix(connectors): ado flags listing incomplete when a non-empty repo has no resolvable branch * fix(knowledge): engine truncation flag is an absolute deletion block (fullSync cannot override); s3 byte-exact size fallback; ado tsdoc accuracy * improvement(knowledge): extract shouldReconcileDeletions gate as tested pure function, tighten engine comments * test(connectors): mapTags coverage for the 7 new connectors * fix(connectors): ado probes past the wiql 20k cap before flagging; document custom-wiql full-listing behavior * fix(connectors): ado flags partial repo trees when items listing emits a continuation token * fix(connectors): ado discards foreign-phase cursors; google-forms scans all response pages for change detection * fix(connectors): audit fixes across new connectors - registry: register x connector (was dead code, never wired in) - google-docs/google-drive/google-forms: gate deletion reconciliation on Drive incompleteSearch; google-docs also now sets listingCapped on its maxDocs cap path - jsm: add read:jira-user scope so reporter resolves on requests - gong: only set listingCapped on genuine truncation, not exact-cap source exhaustion - gitlab: issues phase switched to keyset pagination (removes ~50k offset ceiling), matching the repo-tree phase - grain: parallelize recording + transcript fetch in getDocument - ashby: document updatedAt-based content-hash limitation for notes/feedback change detection - tests: mapTags coverage for x, granola, greenhouse, fathom, rootly |
||
|
|
b329c36b1a |
fix(auth): link SSO sign-in to existing same-email accounts (#4866)
* fix(auth): link SSO sign-in to existing same-email accounts SSO sign-ins failed with "account not linked" (then a cascading "Invalid callbackURL") when an account with the same email already existed. Better Auth's `@better-auth/sso` plugin hardcodes the provisioned user's `emailVerified: options?.trustEmailVerified ? <claim> : false`, so with the option unset every SSO login arrived unverified and tripped the account linking gate `(!isTrustedProvider && !userInfo.emailVerified)` whenever the provider was not in `accountLinking.trustedProviders`. - Set `trustEmailVerified: true` on the SSO plugin so the IdP's verified-email claim is honored (Okta, Entra ID, Google Workspace, Auth0 all assert it). - Trust the operator's configured provider for linking: merge `SSO_PROVIDER_ID` (when present in the app env) plus a new `SSO_TRUSTED_PROVIDER_IDS` list into `trustedProviders`. Empty/unset => no-op, so existing deployments are unchanged. - Invite callback URL: return a clean `/invite/<id>` (token already persists in sessionStorage) so an appended `?error=` cannot produce a malformed URL. - Document `SSO_TRUSTED_PROVIDER_IDS` in SSO docs, Helm values, and schema. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(auth): address review — guard trusted SSO providers, revert invite callback - Only compute additionalTrustedSsoProviders when SSO_ENABLED, so trustedProviders is exactly unchanged for non-SSO deployments. - Revert the invite getCallbackUrl change: keep the token in the callback URL (with sessionStorage/searchParams fallback) so the token survives when sessionStorage is unavailable. The account-linking fix removes the "account not linked" error that caused the malformed callback URL, so the callback cleanup is unnecessary. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(auth): guard trusted SSO providers with isSsoEnabled (isTruthy) env.SSO_ENABLED can be the string "false" (t3-env returns strings for booleans), which is truthy in JS. Use the canonical isSsoEnabled flag (isTruthy(env.SSO_ENABLED)) so SSO_ENABLED="false"/"0" correctly yields an empty trusted-provider list, matching how SSO is gated elsewhere. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
b98fbfebef | docs(slack): remove archival reference from Download files per Slack Marketplace guidelines (#4867) | ||
|
|
648a5a117d |
feat(storage): support S3-compatible endpoints (R2, MinIO, B2) for file storage (#4865)
* feat(storage): support S3-compatible endpoints (R2, MinIO, B2) for file storage Add S3_ENDPOINT and S3_FORCE_PATH_STYLE env vars, wired into the shared upload S3 client so Cloudflare R2, MinIO, Backblaze B2, and other S3-compatible stores work for self-hosted file storage. The endpoint is trusted operator config (no SSRF/HTTPS gate). Makes the multipart Location fallback endpoint-aware, extends the S3 client unit tests, and documents the new vars in Helm values, .env.example, and the English self-hosting docs (incl. browser-reachability + CORS guidance). * docs(storage): add RustFS as an S3-compatible provider example * fix(storage): address review feedback and fix env mock for CI - Add envBoolean to the shared env test mock (createEnvMock) so config.ts's forcePathStyle coercion resolves — fixes failing knowledge/utils.test.ts - Declare S3_FORCE_PATH_STYLE as z.string() (every other env var's pattern); it's coerced via envBoolean at the consumption site, avoiding a boolean type that never matches the string process.env value - Log path-style from S3_CONFIG.forcePathStyle (envBoolean) instead of a separate isTruthy call, so the startup log can't disagree with the client - Make buildObjectFallbackUrl honor forcePathStyle: virtual-hosted-style URL (bucket as subdomain) for R2, path-style only when forcePathStyle is set * docs(storage): add backlinks to S3-compatible providers (R2, MinIO, Ceph, B2, RustFS) and backends |
||
|
|
12db7da938 |
feat(connectors): add 11 knowledge base connectors (#4849)
* feat(connectors): add 11 knowledge base connectors (Gong, Grain, Fathom, Granola, incident.io, Rootly, Ashby, Greenhouse, DocuSign, Monday, GitLab) * fix(granola): restore correct calendar_event field names (event_title/organiser/calendar_event_id/scheduled_start_time/scheduled_end_time/invitees) * fix(connectors): correct Grain id field/include flags and incident.io timestamp value shape (verified vs raw API specs) * feat(connectors): add scoping filters for Gong (host users), Fathom (meeting type/domain), Granola (folder/created-after) * feat(connectors): add verified scoping filters (Grain, Rootly, Ashby, Greenhouse, DocuSign, GitLab) + clarify Monday board scope * fix(connectors): docusign sandbox source URL, greenhouse scorecard cap, gong overlap; add incident.io status/mode filters * chore(connectors): remove non-TSDoc inline comments * fix(fathom): apply 14-day overlap to incremental created_after so late transcripts are recaptured * fix(fathom): cache sourceUrl in header so getDocument preserves it; return concrete contentHash (drop omit/cast) * fix(connectors): grain check transcript before formatting; gong cache date window across cursor pages * fix(connectors): fathom skip meetings with no transcript/summary; docusign cache from_date across cursor pages * fix(fathom): return metadata from getDocument (carried via header cache) for tag consistency * fix(connectors): grain cache filter window across pages, greenhouse guard NaN page, rootly skip empty incidents * feat(connectors): final audit — add verified scoping filters (grain team/type, granola+greenhouse createdBefore, gitlab milestone, rootly service/team/env), fix incident.io paused category + rootly severity-slug copy |
||
|
|
e2c2d9add3 |
feat(apify): add run task, get dataset items, and get run tools (#4851)
* feat(apify): add run task, get dataset items, and get run tools * fix(apify): guard undefined dataset id and forward explicit offset=0 |
||
|
|
e5a46d7959 | feat(linq): add Linq iMessage/SMS/RCS integration (34 tools, block, attachment upload) (#4831) | ||
|
|
919fa5274b |
feat(tables): expand filter operators (not-contains, starts/ends-with, not-in, empty) (#4827)
Add does-not-contain ($ncontains), starts-with ($startsWith), ends-with ($endsWith), not-in-array ($nin, previously executed server-side but unexposed in the UI), and is-empty/is-not-empty ($empty) filter operators end-to-end — SQL builder, condition types, query-builder converters/constants, the filter UI, the Table tools/block descriptions, and docs. Also fix correctness bugs in the filter builder surfaced by the wider operator set: - Same-column AND rules (e.g. age > 18 AND age < 65, or name startsWith 'A' AND name endsWith 'Z') silently overwrote each other because the AND group was keyed by column name. They now merge into one operator object, which also makes Filter -> rules -> Filter round-trip losslessly for multi-operator columns. - $nin values were not split into an array like $in, and textual-match values like "123" were numeric-coerced (breaking the ILIKE path). - A non-boolean $empty operand from the raw API silently inverted the check; it now coerces 'true'/'false' strings and otherwise returns a 400. |
||
|
|
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> |
||
|
|
a8f86c0c83 |
fix(security): harden SSO domain registration, webhook path isolation, and CSV export (#4813)
* fix(security): harden KB file access, SSO domain registration, webhook path isolation, env secrets, and CSV export * fix(sso): scope domain conflict query with indexed lower(domain) filter Address PR review: avoid a full-table scan on every SSO provider registration by filtering candidate rows in SQL with lower(domain) = <normalized>, keeping the in-memory ownership check. Also tighten the normalizeSSODomain TSDoc. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: condense env route security comments Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * icons update * chore(security): tighten inline comments in CSV export and KB file authorization Condense verbose comment blocks to concise TSDoc/single-line form; no behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): validate internal serve origin in KB file authorization Replace the bypassable isInternalFileUrl substring check in resolveInternalKbKey with an origin allow-list (base URL, internal API base URL, TRUSTED_ORIGINS). A crafted external host whose path is /api/files/serve/<victim-key> no longer resolves to the victim key. Relative same-origin URLs are unaffected. * style(sso): use idiomatic sql lower() comparison for domain conflict query Match the repo's prevailing `sql`lower(col) = value`` idiom for the case-insensitive SSO domain conflict lookup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): align workspace env admin gate with hasWorkspaceAdminAccess Use the same admin check the secrets UI uses (owner, admin permission, or org-admin) so owners and org-admins are not wrongly denied their own decrypted workspace secrets, while read-only members remain restricted to names only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(sso): rely on lower(domain) match for conflict detection, drop dead in-memory recheck Address PR review: the SQL `lower(domain) = <normalized>` predicate already excludes rows that the in-memory `normalizeSSODomain(...) === domain` recheck claimed to catch, making that recheck dead/misleading code. Match on the canonical lower-cased domain and filter purely by ownership. Malformed legacy values (wildcards, schemes, ports) never match an email domain at sign-in, so excluding them is not a gap. Test DB mock now applies the lower() predicate so the casing-variant case is genuinely exercised. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): scope webhook deploy path conflict to active webhooks findConflictingWebhookPathOwner omitted the isActive filter that the runtime dispatcher (findAllWebhooksForPath) applies, so an inactive but non-archived webhook from another workflow (e.g. after undeploy or failure auto-disable) would permanently block any new deployment on that path even though it never receives deliveries. Align the guard with the runtime isActive + archivedAt filter; the earliest-owner runtime check remains the authoritative cross-tenant protection. Also trims verbose TSDoc on the webhook path-isolation helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): exclude archived workflows from webhook deploy path conflict findConflictingWebhookPathOwner now joins workflow and filters isNull(workflow.archivedAt), matching the runtime dispatcher (findAllWebhooksForPath). A webhook on an archived workflow can never receive deliveries at runtime, so it must not block legitimate path reuse with a 409. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(security): anchor KB file ownership to earliest document in any state A KB file's owner is now the earliest document referencing its key regardless of state (active/archived/deleted/excluded); access is granted only when that owning document is still active. Closes the residual where an attacker could plant an active document to claim a file whose original document was archived or deleted. * updated greptile icon * revert(security): drop KB file authorization changes Reverts the knowledge-base file-access work (origin-pinning / owner-pinning / origin allow-list in verifyKBFileAccess) and its test. The other hardening fixes (SSO domain registration, webhook path isolation, workspace env secrets, CSV export) are unchanged. apps/sim/app/api/files/authorization.ts is restored to its origin/staging baseline. * fix(sso): treat caller's own user-scoped provider as owned during conflict check Self-hosters often register SSO user-scoped via the CLI script (no SSO_ORGANIZATION_ID). If they later enable organizations and reconfigure the same domain org-scoped through the UI, the conflict check previously treated their own user-scoped row as another tenant's and returned a misleading 409. Recognize the caller's own user-scoped provider as owned so that migration is allowed, while still blocking another user's or another org's domain. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * revert(security): remove workspace-env admin gate Defer to a credential-based access model (separate change). Restores GET /api/workspaces/[id]/environment to main behavior and removes the test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(security): consolidate webhook path-collision check into one helper Extract findConflictingWebhookPathOwner to lib/webhooks/utils.server.ts as the single source of truth for cross-tenant path-collision detection, used by both webhook creation paths (deploy sync and the manual /api/webhooks route). This also repairs two latent issues in the manual route's previous inline check, which queried with limit(1) and only webhook.archivedAt: - limit(1) inspected one arbitrary row, so a same-workflow row could mask a foreign collision (false negative). The shared helper scans all matching rows. - It omitted isActive/workflow.archivedAt, so inactive or archived-workflow webhooks (which never receive deliveries) permanently blocked path reuse. The helper mirrors the runtime dispatcher's filter. Same-workflow webhook reuse for upsert is now a separate, explicit lookup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
c6d500d841 |
fix(icons): repair broken integration icon rendering (#4810)
* fix(icons): repair broken integration icon rendering Two distinct bugs left integration icons broken on the /integrations page (visible at 32-40px, hidden at the toolbar's 16px): 1. Corrupted SVG paths (Notion, Greptile, Granola, Calendly, Grafana, Bedrock): over-minified data dropped elliptical-arc flag digits (e.g. `A1 1 0 5.9 7` instead of `A1 1 0 0 0 5.9 7`); Granola's cubic stream was truncated. Browsers abort path parsing at the first invalid arc flag, so each rendered as a fragment or blank. Replaced with correct path data from canonical sources, preserving each icon's existing fill/gradient and bgColor. 2. Invisible glyph (Bright Data): its icon uses fill='currentColor' but bgColor was '#FFFFFF', and every surface forces text-white on the glyph - white-on-white. Changed bgColor to Bright Data's brand blue (#3d7ffc) so the white glyph reads, matching the white-glyph-on-brand-chip convention. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): restore Calendly dual-tone brand colors Addresses review feedback: the previous fix replaced the broken Calendly icon with a monochrome #006BFF path, dropping the cyan #0ae8f0 accent from the original dual-tone mark. Restored the two-tone logo (blue + cyan) using clean, valid path data, cropped to a tight square viewBox so it fills the chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge icons, fix Zoom contrast and Quiver chip - Zoom: glyph was blue-on-blue (#0B5CFF on #2D8CFF chip); switched to currentColor so it renders as a white glyph on the blue chip. - Quiver: chip bgColor #000000 -> #FFFFFF to match the icon's near-white box, and enlarged the mark slightly (viewBox crop). - Enlarged (tightened viewBox, verified no clipping): RevenueCat, Prospeo, Granola, Firecrawl, Enrich.so, and the AWS icons (RDS, DynamoDB, SQS, CloudFormation, Athena, CloudWatch, SES, Bedrock, S3). - ZoomInfo left unchanged: it is a full red rounded-square logo that already fills its frame, so a crop would clip it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): use Bright Data wordmark on white chip; repair Circleback - Bright Data: replaced the flame glyph with the official two-tone 'bright data' wordmark (provided asset), centered in a symmetric viewBox. Reverted the chip bgColor from #3d7ffc to #FFFFFF since the blue wordmark is invisible on a blue chip (the wordmark is designed for a light background). - Circleback: a minifier had rounded the pattern's image scale to scale(0), collapsing the embedded logo to zero size (invisible). Restored the correct scale (1/280 = 0.00357142857) so the C. mark renders. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(docs): sync Quiver block color card to white chip Reflects the Quiver bgColor change (#000000 -> #FFFFFF) in the docs block info card. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge AWS/Cloudflare/Dagster icons, fully white Zoom - Enlarged (tighter viewBox, render-verified, no clipping): Cloudflare, Dagster, and the red AWS icons AWS IAM, Identity Center, Secrets Manager, SES, STS. Identity Center was anomalously small (filled ~32% of its frame); the group is now sized consistently (~80% fill). - Zoom: the camera lens triangle was still #0B5CFF (blue-on-blue); switched it to currentColor so the whole camera renders white on the blue chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(wiza): consolidate individual reveal into a single operation Merges the separate Start/Get Individual Reveal operations into one Individual Reveal operation in the Wiza docs and integrations data (operationCount 5 -> 4). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): size remaining AWS icons to match the set (~80% fill) Bring RDS, DynamoDB, SQS, CloudFormation, Athena, CloudWatch and S3 up to the same ~80% fill as the AWS IAM/Identity Center/Secrets Manager/SES/STS group, so all AWS icons are visually consistent. Bedrock left as-is (already ~92% fill). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(icons): use Bright Data flame mark, enlarge ZoomInfo - Bright Data: the full 'bright data' wordmark was illegible at chip size. Replaced with just the flame-'i' brand mark (blue #4280f6 on the white chip), centered. - ZoomInfo: cropped the viewBox toward the white 'Zi' so it's larger; the red rounded-square background still fills the chip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * improvement(icons): enlarge CrowdStrike icon The falcon mark sat small in its chip because the icon used a wide 768x500 viewBox (letterboxed in the square chip). Switched to a square viewBox centered on the mark so it fills ~80%, consistent with the other icons. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
e1e773f487 |
feat(slack): add install + privacy section to integration landing page (#4799)
* feat(slack): add install + privacy section to integration landing page Adds a hand-authored, slug-keyed landing-content module (separate from the generated integrations.json so it survives regeneration) and renders an install walkthrough + privacy-policy link on integration pages when present. Also refreshes generated docs (data-enrichment entry, icon mappings, tool mdx). * fix(landing): render privacy section independently, align CTA analytics label * docs(landing): clarify the Slack install button is behind sign-in * refactor(landing): bake integration landing content into generated json via docs-gen Moves landing content (install walkthrough + privacy) out of a render-time augment and into the generation pipeline: generate-docs reads the pure-data content map and writes landingContent into integrations.json, so the page reads a single source (integration.landingContent). Canonical types live in integrations/data/types.ts. |
||
|
|
4b0dab4682 |
chore(copilot): deprecate mcp server (#4797)
* chore(copilot): deprecate mcp * update error codes * deprecate copilot api v1 route |
||
|
|
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> |
||
|
|
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. |
||
|
|
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> |
||
|
|
28766ddaa9 |
feat(instantly): block, trigger (#4763)
* feat(instantly): block, trigger * change bg color for icon * address comments * cleanup code * search param missplaced |
||
|
|
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 |
||
|
|
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. |
||
|
|
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 |
||
|
|
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 |
||
|
|
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 |
||
|
|
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> |
||
|
|
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 |
||
|
|
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 |
||
|
|
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 |
||
|
|
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. |
||
|
|
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 |
||
|
|
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 |
||
|
|
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 |
||
|
|
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> |
||
|
|
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 |
||
|
|
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 |
||
|
|
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
|
||
|
|
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. |
||
|
|
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> |
||
|
|
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 |
||
|
|
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> |
||
|
|
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 |
||
|
|
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 |
||
|
|
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>
|
||
|
|
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
|
||
|
|
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
|
||
|
|
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 |
||
|
|
6d4ffff327 |
fix(agiloft): correct response parsing, add EWGetChoiceLineId tool (#4477)
* fix(agiloft): correct response parsing, add EWGetChoiceLineId tool * fix(agiloft): address PR review feedback |
||
|
|
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). |
||
|
|
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> |