diff --git a/.agents/skills/adding-inbox-sources/SKILL.md b/.agents/skills/adding-inbox-sources/SKILL.md index e14b7956c43f..590a28dd0c6e 100644 --- a/.agents/skills/adding-inbox-sources/SKILL.md +++ b/.agents/skills/adding-inbox-sources/SKILL.md @@ -49,19 +49,24 @@ A new credential-based source needs **zero form code** — just route its `sourceType` and the `schemas` to sync. - Endpoint: `GET /api/environments/{projectId}/external_data_sources/wizard/?source_type=` → `Record`. Client method: `PostHogAPIClient.getExternalDataSourceConfigs`. Hook: `useSourceConfig(sourceType)`. -- `SourceConfig.fields` is a union: `input` (text/email/password/url/number/…), `select`, `switch-group`, `oauth`, `ssh-tunnel`, `file-upload`. `DynamicSourceSetup` renders input/select/switch-group and builds the `createExternalDataSource` payload from field `name`s. The backend is the single source of truth for field names/labels/required/secret, so forms never drift. +- `SourceConfig.fields` is a union: `input` (text/email/password/url/number/…), `select`, `switch-group`, `oauth`, `oauth-account-select`, `ssh-tunnel`, `file-upload`. `DynamicSourceSetup` renders input/select/switch-group **and `oauth`/`oauth-account-select`** generically, and builds the `createExternalDataSource` payload from field `name`s. The backend is the single source of truth for field names/labels/required/secret, so forms never drift. - The field `name`s become the `payload` keys — so you no longer hand-maintain them. (Jira → `subdomain`, `email`, `api_token`; all `secret:false` except the token.) -Three cases still need bespoke handling (the generic renderer flags `oauth`/`ssh-tunnel`/`file-upload` as unsupported and disables submit): - -| Case | When | Existing example | -| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | -| **Generic dynamic form** | Credential inputs only (Jira, Zendesk, Freshdesk, Front, Gorgias, Sentry, GitLab). | `DynamicSourceSetup` (route the switch case to it) | -| **OAuth + integration polling** | Source authenticates via OAuth grant (Intercom `kind=intercom`); poll `getIntegrationsForProject` for the `kind`, pass `_integration_id`. | `LinearSetup` | -| **Deep-link OAuth + resource picker** | User must pick a specific resource (repo/board) during setup. | `GitHubSetup` | - -`ZendeskSetup`/`PgAnalyzeSetup` are the _old_ hardcoded forms — leave them or -migrate them to `DynamicSourceSetup` opportunistically; don't add new ones. +**OAuth sources need NO bespoke form.** `DynamicSourceSetup` renders the `oauth` field (a +connect button that starts the flow by `kind` and polls `getIntegrationsForProject` for the new +integration, writing its id into `payload[]`) and the `oauth-account-select` field (a +server-side-searched picker over the integration's resources) generically. The connect flow is +started by the generic, `kind`-parameterized `integration` tRPC router +(`packages/host-router/src/routers/integration.router.ts` → `IntegrationService`), so any +provider in `OauthIntegration.supported_kinds` works with no per-kind service or router. So an +OAuth source (Intercom, HubSpot, Salesforce, …) is the same one-registry-entry change as a +credential source — route its `DataSourceSetup` case to `DynamicSourceSetup`. + +Only two field types still lack a generic renderer (disable submit): `ssh-tunnel` and +`file-upload`. Route those to a bespoke form. Resource pickers that must run _after_ OAuth +(GitHub's repo picker) are handled by `oauth-account-select`; the old `GitHubSetup`/`ZendeskSetup` +/`PgAnalyzeSetup` hardcoded forms remain only for historical reasons — leave them or migrate to +`DynamicSourceSetup` opportunistically; don't add new ones. Supported OAuth `kind` values (posthog `OauthIntegration.supported_kinds`, `posthog/models/integration.py`): `slack, salesforce, hubspot, google-ads, @@ -86,7 +91,7 @@ Verify exact `source_type` + `payload` key names against the posthog | Freshdesk | `Freshdesk` | `tickets` | API key | `DynamicSourceSetup` | `subdomain`, `api_key` | | Front | `Front` | `conversations` | API token | `DynamicSourceSetup` | `api_token` | | Gorgias | `Gorgias` | `tickets` | API key | `DynamicSourceSetup` | `gorgias_domain`, `email`, `api_key` | -| Intercom | `Intercom` | `conversations` | OAuth (`kind=intercom`) | Linear | `intercom_integration_id` | +| Intercom | `Intercom` | `conversations` | OAuth (`kind=intercom`) | `DynamicSourceSetup` | `intercom_integration_id` | (Zendesk `tickets`, GitHub `issues`, Linear `issues`, pganalyze `issues`+`servers`, and Jira `issues` are already shipped — copy them, don't re-add. The Jira row above @@ -119,18 +124,23 @@ source-list-relevant is a place you must add the new product. The canonical list 8. `packages/core/src/inbox/signalSourceService.ts` — mirror `SOURCE_TYPE_MAP`, `DATA_WAREHOUSE_SOURCES`, `ALL_SOURCE_PRODUCTS`, `computeSourceValues` init, plus `WarehouseSourceProduct`/`SignalSourceValues`. 9. `packages/core/src/inbox/dataSourceService.ts` — `DataSourceType`, `REQUIRED_SCHEMAS`, a `createXDataSource` method. -### OAuth plumbing — **only** for OAuth sources (Intercom); API-key sources skip this +### OAuth plumbing — NOT needed per source anymore -10. `packages/core/src/integrations/.ts` — `XIntegrationService.startFlow(region, projectId)` (clone `linear.ts`). -11. `packages/core/src/integrations/identifiers.ts` — new `X_INTEGRATION_SERVICE` symbol. -12. `packages/core/src/integrations/integrations.module.ts` — bind it. -13. `packages/host-router/src/routers/-integration.router.ts` — clone `linear-integration.router.ts`. -14. `packages/host-router/src/router.ts` — import + register the router in `appRouter`. +There is now a **generic, `kind`-parameterized** integration flow: `IntegrationService` +(`packages/core/src/integrations/integration.ts`) + the `integration` tRPC router +(`packages/host-router/src/routers/integration.router.ts`). `DynamicSourceSetup` starts any +OAuth flow through it via the field's `kind`. So a new OAuth source needs **no** per-kind +service, symbol, or router — do not clone `linear.ts`/`linear-integration.router.ts` per source. +(The old per-kind linear/slack/github routers still exist for other callers; leave them.) ### Setup-form specifics -- **Credential source:** route the `DataSourceSetup` switch case to `DynamicSourceSetup` (above). Nothing else — the fields come from the wizard endpoint. -- **OAuth form:** clone `LinearSetup`. Change the `kind` matched in the poll loop and the `_integration_id` payload key; swap `trpc.linearIntegration.startFlow` for the new router. +- **Credential source:** route the `DataSourceSetup` switch case to `DynamicSourceSetup`. Nothing else — the fields come from the wizard endpoint. +- **OAuth source:** also just route to `DynamicSourceSetup`. Its connect-form schema carries the + `oauth` field (and, if the provider needs a resource picked, an `oauth-account-select` field), + which `DynamicSourceSetup` renders generically — connect button + integration polling + account + picker, all by `kind`. No bespoke form. The provider must be in + `OauthIntegration.supported_kinds`. - Issues sources (`github`/`linear`/`jira`) force `issues` to `full_refresh` in `ensureRequiredTableSyncing` (`useSignalSourceToggles.ts`) — add the new product to that condition if it syncs an `issues` table (issues get edited/closed, so incremental append would miss updates). Ticket/conversation sources only force `should_sync=true`. ### Verify diff --git a/products/signals/backend/contracts.py b/products/signals/backend/contracts.py index fe74812934dd..59c1ae7ab55a 100644 --- a/products/signals/backend/contracts.py +++ b/products/signals/backend/contracts.py @@ -843,6 +843,35 @@ class JudgemeReviewsReviewSignalInput(SignalInputBase): extra: JudgemeReviewsReviewSignalExtra +# ── OAuth-connected support sources ─────────────────────────────────────────────── + + +class IntercomTicketSignalExtra(SignalExtraBase): + state: str | None + priority: str | None + admin_assignee_id: str | None + created_at: str | None + + +class IntercomTicketSignalInput(SignalInputBase): + source_type: Literal[SignalSourceType.TICKET] + source_product: Literal[SignalSourceProduct.INTERCOM] + extra: IntercomTicketSignalExtra + + +class HubspotTicketSignalExtra(SignalExtraBase): + hs_ticket_priority: str | None + hs_pipeline_stage: str | None + hs_ticket_category: str | None + createdate: str | None + + +class HubspotTicketSignalInput(SignalInputBase): + source_type: Literal[SignalSourceType.TICKET] + source_product: Literal[SignalSourceProduct.HUBSPOT] + extra: HubspotTicketSignalExtra + + # ── Union over all signal variants ────────────────────────────────────────────── # Discrimination is by the composite (source_product, source_type) pair, resolved via # SIGNAL_VARIANT_LOOKUP below — a single-field pydantic discriminator can't express it @@ -896,7 +925,9 @@ class JudgemeReviewsReviewSignalInput(SignalInputBase): | RetentlyFeedbackSignalInput | AppfiguresReviewSignalInput | AppfollowReviewSignalInput - | JudgemeReviewsReviewSignalInput, + | JudgemeReviewsReviewSignalInput + | IntercomTicketSignalInput + | HubspotTicketSignalInput, Field(union_mode="left_to_right"), ] @@ -948,6 +979,8 @@ class JudgemeReviewsReviewSignalInput(SignalInputBase): AppfiguresReviewSignalInput, AppfollowReviewSignalInput, JudgemeReviewsReviewSignalInput, + IntercomTicketSignalInput, + HubspotTicketSignalInput, ) diff --git a/products/signals/backend/emission/hubspot_tickets.py b/products/signals/backend/emission/hubspot_tickets.py new file mode 100644 index 000000000000..ebae843bde48 --- /dev/null +++ b/products/signals/backend/emission/hubspot_tickets.py @@ -0,0 +1,44 @@ +"""Signal emitter for hubspot `tickets` (record kind: ticket). + +HubSpot is an OAuth-connected source, but its `tickets` table is flat, so the shared factory +applies. `hs_object_id` is the record id, `subject`/`content` the text, `createdate` an ISO +string. Only the ticket properties the user selected during setup are synced; the defaults +include subject/content/createdate. +""" + +from products.signals.backend.emission._common import make_flat_emitter +from products.signals.backend.emission._prompts import TICKET_ACTIONABILITY_PROMPT, TICKET_SUMMARIZATION_PROMPT +from products.signals.backend.emission.fetchers.data_warehouse import data_warehouse_record_fetcher +from products.signals.backend.emission.registry import SignalSourceTableConfig + +HUBSPOT_FIELDS = ( + "hs_object_id", + "subject", + "content", + "hs_ticket_priority", + "hs_pipeline_stage", + "hs_ticket_category", + "createdate", +) + +HUBSPOT_CONFIG = SignalSourceTableConfig( + source_product="hubspot", + source_type="ticket", + emitter=make_flat_emitter( + source_product="hubspot", + source_type="ticket", + id_field="hs_object_id", + title_field="subject", + body_field="content", + extra_fields=("hs_ticket_priority", "hs_pipeline_stage", "hs_ticket_category", "createdate"), + ), + record_fetcher=data_warehouse_record_fetcher, + partition_field="createdate", + partition_field_is_datetime_string=True, + fields=HUBSPOT_FIELDS, + max_records=200, + first_sync_lookback_days=1, + actionability_prompt=TICKET_ACTIONABILITY_PROMPT, + summarization_prompt=TICKET_SUMMARIZATION_PROMPT, + description_summarization_threshold_chars=2000, +) diff --git a/products/signals/backend/emission/intercom_conversations.py b/products/signals/backend/emission/intercom_conversations.py new file mode 100644 index 000000000000..fefb518936e0 --- /dev/null +++ b/products/signals/backend/emission/intercom_conversations.py @@ -0,0 +1,103 @@ +"""Signal emitter for intercom `conversations` (record kind: ticket). + +Intercom is OAuth-connected and its `conversations` table isn't flat, so this is a bespoke +emitter (like Jira's): +- The opening message isn't a top-level column — it lives in the `source` JSON blob + (`source.body`, HTML). `title` is often null, so we fall back to the stripped source body. + The rest of the thread is in `conversation_parts` (a separate table we don't sync). +- `created_at` is a Unix epoch (seconds), so the partition cursor wraps it in + `fromUnixTimestamp(...)`. Verify the stored type on the first real sync. +""" + +import re +from typing import Any + +from structlog import get_logger + +from products.signals.backend.emission._prompts import TICKET_ACTIONABILITY_PROMPT, TICKET_SUMMARIZATION_PROMPT +from products.signals.backend.emission.fetchers.data_warehouse import data_warehouse_record_fetcher +from products.signals.backend.emission.registry import SignalEmitterOutput, SignalSourceTableConfig + +logger = get_logger(__name__) + +INTERCOM_IGNORED_STATES = ("closed",) + +FIELDS = ( + "id", + "title", + "state", + "priority", + "admin_assignee_id", + "created_at", + "JSONExtractString(source, 'body') AS source_body", +) + +_TAG_RE = re.compile(r"<[^>]+>") + + +def _strip_html(raw: Any) -> str: + if not raw or not isinstance(raw, str): + return "" + return _TAG_RE.sub(" ", raw).replace(" ", " ").strip() + + +def intercom_conversation_emitter(team_id: int, record: dict[str, Any]) -> SignalEmitterOutput | None: + try: + conversation_id = record["id"] + except KeyError as e: + msg = f"Intercom conversation record missing required field {e}" + logger.exception(msg, record=record, team_id=team_id, signals_type="data-import-signals") + raise ValueError(msg) from e + if not conversation_id: + msg = f"Intercom conversation record has empty id: {conversation_id!r}" + logger.exception(msg, record=record, team_id=team_id, signals_type="data-import-signals") + raise ValueError(msg) + + title = record.get("title") + body = _strip_html(record.get("source_body")) + # Prefer an explicit subject; otherwise use the opening message. Skip conversations with no + # readable text (auto-created/empty ones can't produce a useful signal). + description = title or body + if not description: + logger.info( + "Ignoring Intercom conversation without text", + team_id=team_id, + signals_type="data-import-signals", + ) + return None + if title and body: + description = f"{title}\n{body}" + + return SignalEmitterOutput( + source_product="intercom", + source_type="ticket", + source_id=str(conversation_id), + description=description, + weight=1.0, + extra={ + "state": record.get("state") or None, + "priority": record.get("priority") or None, + "admin_assignee_id": ( + str(record["admin_assignee_id"]) if record.get("admin_assignee_id") is not None else None + ), + "created_at": str(record["created_at"]) if record.get("created_at") is not None else None, + }, + ) + + +INTERCOM_CONFIG = SignalSourceTableConfig( + source_product="intercom", + source_type="ticket", + emitter=intercom_conversation_emitter, + record_fetcher=data_warehouse_record_fetcher, + # created_at is a Unix epoch (seconds). Wrap so the cursor compares as a datetime; verify the + # stored column type on the first real sync (it may already be a DateTime). + partition_field="fromUnixTimestamp(toUInt32(created_at))", + fields=FIELDS, + where_clause=f"state NOT IN ({', '.join(repr(s) for s in INTERCOM_IGNORED_STATES)})", + max_records=200, + first_sync_lookback_days=1, + actionability_prompt=TICKET_ACTIONABILITY_PROMPT, + summarization_prompt=TICKET_SUMMARIZATION_PROMPT, + description_summarization_threshold_chars=2000, +) diff --git a/products/signals/backend/emission/registry.py b/products/signals/backend/emission/registry.py index 77c689646209..10c91949fe03 100644 --- a/products/signals/backend/emission/registry.py +++ b/products/signals/backend/emission/registry.py @@ -136,6 +136,8 @@ def _register_all_emitters() -> None: from products.signals.backend.emission.gitlab_issues import GITLAB_CONFIG from products.signals.backend.emission.gorgias_tickets import GORGIAS_CONFIG from products.signals.backend.emission.honeybadger_faults import HONEYBADGER_CONFIG + from products.signals.backend.emission.hubspot_tickets import HUBSPOT_CONFIG + from products.signals.backend.emission.intercom_conversations import INTERCOM_CONFIG from products.signals.backend.emission.jira_issues import JIRA_ISSUES_CONFIG from products.signals.backend.emission.judgeme_reviews_reviews import JUDGEME_REVIEWS_CONFIG from products.signals.backend.emission.kustomer_conversations import KUSTOMER_CONFIG @@ -199,6 +201,9 @@ def _register_all_emitters() -> None: register_signal_source(ExternalDataSourceType.APPFIGURES, "reviews", APPFIGURES_CONFIG) register_signal_source(ExternalDataSourceType.APPFOLLOW, "reviews", APPFOLLOW_CONFIG) register_signal_source(ExternalDataSourceType.JUDGEMEREVIEWS, "reviews", JUDGEME_REVIEWS_CONFIG) + # OAuth-connected support sources (record kind: ticket) + register_signal_source(ExternalDataSourceType.INTERCOM, "conversations", INTERCOM_CONFIG) + register_signal_source(ExternalDataSourceType.HUBSPOT, "tickets", HUBSPOT_CONFIG) _register_all_emitters() diff --git a/products/signals/backend/emission/tests/test_tier1_registry.py b/products/signals/backend/emission/tests/test_tier1_registry.py index 51a0480a7a21..5e87b7597a96 100644 --- a/products/signals/backend/emission/tests/test_tier1_registry.py +++ b/products/signals/backend/emission/tests/test_tier1_registry.py @@ -41,6 +41,9 @@ (ExternalDataSourceType.APPFIGURES, "reviews", "appfigures", "review"), (ExternalDataSourceType.APPFOLLOW, "reviews", "appfollow", "review"), (ExternalDataSourceType.JUDGEMEREVIEWS, "reviews", "judgeme_reviews", "review"), + # OAuth-connected support sources + (ExternalDataSourceType.INTERCOM, "conversations", "intercom", "ticket"), + (ExternalDataSourceType.HUBSPOT, "tickets", "hubspot", "ticket"), ] IDS = [product for _, _, product, _ in TIER1_SOURCES] diff --git a/products/signals/backend/enums.py b/products/signals/backend/enums.py index 673d61bc23de..a981b2bd5f2c 100644 --- a/products/signals/backend/enums.py +++ b/products/signals/backend/enums.py @@ -65,6 +65,9 @@ class SignalSourceProduct(StrEnum): APPFIGURES = "appfigures" APPFOLLOW = "appfollow" JUDGEME_REVIEWS = "judgeme_reviews" + # OAuth-connected support sources + INTERCOM = "intercom" + HUBSPOT = "hubspot" class SignalSourceType(StrEnum): @@ -141,6 +144,8 @@ class SignalSourceType(StrEnum): SignalSourceProduct.APPFIGURES: "Appfigures", SignalSourceProduct.APPFOLLOW: "AppFollow", SignalSourceProduct.JUDGEME_REVIEWS: "Judge.me", + SignalSourceProduct.INTERCOM: "Intercom", + SignalSourceProduct.HUBSPOT: "HubSpot", } # The Django model's `source_product` choices, frozen-equivalent to the prior nested TextChoices so diff --git a/products/signals/backend/migrations/0065_alter_signalsourceconfig_source_product.py b/products/signals/backend/migrations/0065_alter_signalsourceconfig_source_product.py new file mode 100644 index 000000000000..0895f6f6352d --- /dev/null +++ b/products/signals/backend/migrations/0065_alter_signalsourceconfig_source_product.py @@ -0,0 +1,68 @@ +# Generated by Django 5.2.14 on 2026-07-21 11:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("signals", "0064_alter_signalsourceconfig_source_product"), + ] + + operations = [ + migrations.AlterField( + model_name="signalsourceconfig", + name="source_product", + field=models.CharField( + choices=[ + ("session_replay", "Session replay"), + ("llm_analytics", "LLM analytics"), + ("github", "GitHub"), + ("linear", "Linear"), + ("jira", "Jira"), + ("zendesk", "Zendesk"), + ("conversations", "Conversations"), + ("error_tracking", "Error tracking"), + ("pganalyze", "pganalyze"), + ("signals_scout", "Signals scout"), + ("logs", "Logs"), + ("health_checks", "Health checks"), + ("endpoints", "Endpoints"), + ("replay_vision", "Replay Vision"), + ("analytics", "Product analytics"), + ("freshdesk", "Freshdesk"), + ("freshservice", "Freshservice"), + ("front", "Front"), + ("gorgias", "Gorgias"), + ("kustomer", "Kustomer"), + ("dixa", "Dixa"), + ("plain", "Plain"), + ("gitlab", "GitLab"), + ("gitea", "Gitea"), + ("shortcut", "Shortcut"), + ("sentry", "Sentry"), + ("rollbar", "Rollbar"), + ("bugsnag", "Bugsnag"), + ("honeybadger", "Honeybadger"), + ("raygun", "Raygun"), + ("snyk", "Snyk"), + ("sonarqube", "SonarQube"), + ("semgrep", "Semgrep"), + ("rapid7_insightvm", "Rapid7 InsightVM"), + ("featurebase", "Featurebase"), + ("frill", "Frill"), + ("aha", "Aha"), + ("uservoice", "UserVoice"), + ("productboard", "Productboard"), + ("canny", "Canny"), + ("asknicely", "AskNicely"), + ("retently", "Retently"), + ("appfigures", "Appfigures"), + ("appfollow", "AppFollow"), + ("judgeme_reviews", "Judge.me"), + ("intercom", "Intercom"), + ("hubspot", "HubSpot"), + ], + max_length=100, + ), + ), + ] diff --git a/products/signals/backend/migrations/max_migration.txt b/products/signals/backend/migrations/max_migration.txt index eab24b0d2214..b9bda9dd0ccb 100644 --- a/products/signals/backend/migrations/max_migration.txt +++ b/products/signals/backend/migrations/max_migration.txt @@ -1 +1 @@ -0064_alter_signalsourceconfig_source_product +0065_alter_signalsourceconfig_source_product diff --git a/products/signals/frontend/generated/api.schemas.ts b/products/signals/frontend/generated/api.schemas.ts index b312874fe513..d975d2dae038 100644 --- a/products/signals/frontend/generated/api.schemas.ts +++ b/products/signals/frontend/generated/api.schemas.ts @@ -338,6 +338,8 @@ export interface SignalReportRefundResponseApi { * * `appfigures` - appfigures * * `appfollow` - appfollow * * `judgeme_reviews` - judgeme_reviews + * * `intercom` - intercom + * * `hubspot` - hubspot */ export type SignalSourceProductApi = (typeof SignalSourceProductApi)[keyof typeof SignalSourceProductApi] @@ -387,6 +389,8 @@ export const SignalSourceProductApi = { Appfigures: 'appfigures', Appfollow: 'appfollow', JudgemeReviews: 'judgeme_reviews', + Intercom: 'intercom', + Hubspot: 'hubspot', } as const /** @@ -937,6 +941,20 @@ export interface JudgemeReviewsReviewSignalExtraApi { created_at: string | null } +export interface IntercomTicketSignalExtraApi { + state: string | null + priority: string | null + admin_assignee_id: string | null + created_at: string | null +} + +export interface HubspotTicketSignalExtraApi { + hs_ticket_priority: string | null + hs_pipeline_stage: string | null + hs_ticket_category: string | null + createdate: string | null +} + export type SignalExtraApi = | SessionProblemSignalExtraApi | LlmEvalSignalExtraApi @@ -985,6 +1003,8 @@ export type SignalExtraApi = | AppfiguresReviewSignalExtraApi | AppfollowReviewSignalExtraApi | JudgemeReviewsReviewSignalExtraApi + | IntercomTicketSignalExtraApi + | HubspotTicketSignalExtraApi export interface SpecificityMetadataApi { /** Title of the PR the specificity gate evaluated. */ @@ -1068,7 +1088,9 @@ export interface SignalNodeApi { * * `retently` - retently * * `appfigures` - appfigures * * `appfollow` - appfollow - * * `judgeme_reviews` - judgeme_reviews */ + * * `judgeme_reviews` - judgeme_reviews + * * `intercom` - intercom + * * `hubspot` - hubspot */ source_product: SignalSourceProductApi /** Signal type within the source product. * @@ -2799,6 +2821,8 @@ export interface ForgetResponseApi { * * `appfigures` - Appfigures * * `appfollow` - AppFollow * * `judgeme_reviews` - Judge.me + * * `intercom` - Intercom + * * `hubspot` - HubSpot */ export type SignalSourceConfigSourceProductEnumApi = (typeof SignalSourceConfigSourceProductEnumApi)[keyof typeof SignalSourceConfigSourceProductEnumApi] @@ -2849,6 +2873,8 @@ export const SignalSourceConfigSourceProductEnumApi = { Appfigures: 'appfigures', Appfollow: 'appfollow', JudgemeReviews: 'judgeme_reviews', + Intercom: 'intercom', + Hubspot: 'hubspot', } as const /** diff --git a/products/signals/frontend/generated/api.zod.ts b/products/signals/frontend/generated/api.zod.ts index fd29ddc3f483..2e7c5979fd7e 100644 --- a/products/signals/frontend/generated/api.zod.ts +++ b/products/signals/frontend/generated/api.zod.ts @@ -708,9 +708,11 @@ export const SignalsSourceConfigsCreateBody = /* @__PURE__ */ zod.object({ 'appfigures', 'appfollow', 'judgeme_reviews', + 'intercom', + 'hubspot', ]) .describe( - '\* `session_replay` - Session replay\n\* `llm_analytics` - LLM analytics\n\* `github` - GitHub\n\* `linear` - Linear\n\* `jira` - Jira\n\* `zendesk` - Zendesk\n\* `conversations` - Conversations\n\* `error_tracking` - Error tracking\n\* `pganalyze` - pganalyze\n\* `signals_scout` - Signals scout\n\* `logs` - Logs\n\* `health_checks` - Health checks\n\* `endpoints` - Endpoints\n\* `replay_vision` - Replay Vision\n\* `analytics` - Product analytics\n\* `freshdesk` - Freshdesk\n\* `freshservice` - Freshservice\n\* `front` - Front\n\* `gorgias` - Gorgias\n\* `kustomer` - Kustomer\n\* `dixa` - Dixa\n\* `plain` - Plain\n\* `gitlab` - GitLab\n\* `gitea` - Gitea\n\* `shortcut` - Shortcut\n\* `sentry` - Sentry\n\* `rollbar` - Rollbar\n\* `bugsnag` - Bugsnag\n\* `honeybadger` - Honeybadger\n\* `raygun` - Raygun\n\* `snyk` - Snyk\n\* `sonarqube` - SonarQube\n\* `semgrep` - Semgrep\n\* `rapid7_insightvm` - Rapid7 InsightVM\n\* `featurebase` - Featurebase\n\* `frill` - Frill\n\* `aha` - Aha\n\* `uservoice` - UserVoice\n\* `productboard` - Productboard\n\* `canny` - Canny\n\* `asknicely` - AskNicely\n\* `retently` - Retently\n\* `appfigures` - Appfigures\n\* `appfollow` - AppFollow\n\* `judgeme_reviews` - Judge.me' + '\* `session_replay` - Session replay\n\* `llm_analytics` - LLM analytics\n\* `github` - GitHub\n\* `linear` - Linear\n\* `jira` - Jira\n\* `zendesk` - Zendesk\n\* `conversations` - Conversations\n\* `error_tracking` - Error tracking\n\* `pganalyze` - pganalyze\n\* `signals_scout` - Signals scout\n\* `logs` - Logs\n\* `health_checks` - Health checks\n\* `endpoints` - Endpoints\n\* `replay_vision` - Replay Vision\n\* `analytics` - Product analytics\n\* `freshdesk` - Freshdesk\n\* `freshservice` - Freshservice\n\* `front` - Front\n\* `gorgias` - Gorgias\n\* `kustomer` - Kustomer\n\* `dixa` - Dixa\n\* `plain` - Plain\n\* `gitlab` - GitLab\n\* `gitea` - Gitea\n\* `shortcut` - Shortcut\n\* `sentry` - Sentry\n\* `rollbar` - Rollbar\n\* `bugsnag` - Bugsnag\n\* `honeybadger` - Honeybadger\n\* `raygun` - Raygun\n\* `snyk` - Snyk\n\* `sonarqube` - SonarQube\n\* `semgrep` - Semgrep\n\* `rapid7_insightvm` - Rapid7 InsightVM\n\* `featurebase` - Featurebase\n\* `frill` - Frill\n\* `aha` - Aha\n\* `uservoice` - UserVoice\n\* `productboard` - Productboard\n\* `canny` - Canny\n\* `asknicely` - AskNicely\n\* `retently` - Retently\n\* `appfigures` - Appfigures\n\* `appfollow` - AppFollow\n\* `judgeme_reviews` - Judge.me\n\* `intercom` - Intercom\n\* `hubspot` - HubSpot' ), source_type: zod .enum([ @@ -785,9 +787,11 @@ export const SignalsSourceConfigsUpdateBody = /* @__PURE__ */ zod.object({ 'appfigures', 'appfollow', 'judgeme_reviews', + 'intercom', + 'hubspot', ]) .describe( - '\* `session_replay` - Session replay\n\* `llm_analytics` - LLM analytics\n\* `github` - GitHub\n\* `linear` - Linear\n\* `jira` - Jira\n\* `zendesk` - Zendesk\n\* `conversations` - Conversations\n\* `error_tracking` - Error tracking\n\* `pganalyze` - pganalyze\n\* `signals_scout` - Signals scout\n\* `logs` - Logs\n\* `health_checks` - Health checks\n\* `endpoints` - Endpoints\n\* `replay_vision` - Replay Vision\n\* `analytics` - Product analytics\n\* `freshdesk` - Freshdesk\n\* `freshservice` - Freshservice\n\* `front` - Front\n\* `gorgias` - Gorgias\n\* `kustomer` - Kustomer\n\* `dixa` - Dixa\n\* `plain` - Plain\n\* `gitlab` - GitLab\n\* `gitea` - Gitea\n\* `shortcut` - Shortcut\n\* `sentry` - Sentry\n\* `rollbar` - Rollbar\n\* `bugsnag` - Bugsnag\n\* `honeybadger` - Honeybadger\n\* `raygun` - Raygun\n\* `snyk` - Snyk\n\* `sonarqube` - SonarQube\n\* `semgrep` - Semgrep\n\* `rapid7_insightvm` - Rapid7 InsightVM\n\* `featurebase` - Featurebase\n\* `frill` - Frill\n\* `aha` - Aha\n\* `uservoice` - UserVoice\n\* `productboard` - Productboard\n\* `canny` - Canny\n\* `asknicely` - AskNicely\n\* `retently` - Retently\n\* `appfigures` - Appfigures\n\* `appfollow` - AppFollow\n\* `judgeme_reviews` - Judge.me' + '\* `session_replay` - Session replay\n\* `llm_analytics` - LLM analytics\n\* `github` - GitHub\n\* `linear` - Linear\n\* `jira` - Jira\n\* `zendesk` - Zendesk\n\* `conversations` - Conversations\n\* `error_tracking` - Error tracking\n\* `pganalyze` - pganalyze\n\* `signals_scout` - Signals scout\n\* `logs` - Logs\n\* `health_checks` - Health checks\n\* `endpoints` - Endpoints\n\* `replay_vision` - Replay Vision\n\* `analytics` - Product analytics\n\* `freshdesk` - Freshdesk\n\* `freshservice` - Freshservice\n\* `front` - Front\n\* `gorgias` - Gorgias\n\* `kustomer` - Kustomer\n\* `dixa` - Dixa\n\* `plain` - Plain\n\* `gitlab` - GitLab\n\* `gitea` - Gitea\n\* `shortcut` - Shortcut\n\* `sentry` - Sentry\n\* `rollbar` - Rollbar\n\* `bugsnag` - Bugsnag\n\* `honeybadger` - Honeybadger\n\* `raygun` - Raygun\n\* `snyk` - Snyk\n\* `sonarqube` - SonarQube\n\* `semgrep` - Semgrep\n\* `rapid7_insightvm` - Rapid7 InsightVM\n\* `featurebase` - Featurebase\n\* `frill` - Frill\n\* `aha` - Aha\n\* `uservoice` - UserVoice\n\* `productboard` - Productboard\n\* `canny` - Canny\n\* `asknicely` - AskNicely\n\* `retently` - Retently\n\* `appfigures` - Appfigures\n\* `appfollow` - AppFollow\n\* `judgeme_reviews` - Judge.me\n\* `intercom` - Intercom\n\* `hubspot` - HubSpot' ), source_type: zod .enum([ @@ -862,10 +866,12 @@ export const SignalsSourceConfigsPartialUpdateBody = /* @__PURE__ */ zod.object( 'appfigures', 'appfollow', 'judgeme_reviews', + 'intercom', + 'hubspot', ]) .optional() .describe( - '\* `session_replay` - Session replay\n\* `llm_analytics` - LLM analytics\n\* `github` - GitHub\n\* `linear` - Linear\n\* `jira` - Jira\n\* `zendesk` - Zendesk\n\* `conversations` - Conversations\n\* `error_tracking` - Error tracking\n\* `pganalyze` - pganalyze\n\* `signals_scout` - Signals scout\n\* `logs` - Logs\n\* `health_checks` - Health checks\n\* `endpoints` - Endpoints\n\* `replay_vision` - Replay Vision\n\* `analytics` - Product analytics\n\* `freshdesk` - Freshdesk\n\* `freshservice` - Freshservice\n\* `front` - Front\n\* `gorgias` - Gorgias\n\* `kustomer` - Kustomer\n\* `dixa` - Dixa\n\* `plain` - Plain\n\* `gitlab` - GitLab\n\* `gitea` - Gitea\n\* `shortcut` - Shortcut\n\* `sentry` - Sentry\n\* `rollbar` - Rollbar\n\* `bugsnag` - Bugsnag\n\* `honeybadger` - Honeybadger\n\* `raygun` - Raygun\n\* `snyk` - Snyk\n\* `sonarqube` - SonarQube\n\* `semgrep` - Semgrep\n\* `rapid7_insightvm` - Rapid7 InsightVM\n\* `featurebase` - Featurebase\n\* `frill` - Frill\n\* `aha` - Aha\n\* `uservoice` - UserVoice\n\* `productboard` - Productboard\n\* `canny` - Canny\n\* `asknicely` - AskNicely\n\* `retently` - Retently\n\* `appfigures` - Appfigures\n\* `appfollow` - AppFollow\n\* `judgeme_reviews` - Judge.me' + '\* `session_replay` - Session replay\n\* `llm_analytics` - LLM analytics\n\* `github` - GitHub\n\* `linear` - Linear\n\* `jira` - Jira\n\* `zendesk` - Zendesk\n\* `conversations` - Conversations\n\* `error_tracking` - Error tracking\n\* `pganalyze` - pganalyze\n\* `signals_scout` - Signals scout\n\* `logs` - Logs\n\* `health_checks` - Health checks\n\* `endpoints` - Endpoints\n\* `replay_vision` - Replay Vision\n\* `analytics` - Product analytics\n\* `freshdesk` - Freshdesk\n\* `freshservice` - Freshservice\n\* `front` - Front\n\* `gorgias` - Gorgias\n\* `kustomer` - Kustomer\n\* `dixa` - Dixa\n\* `plain` - Plain\n\* `gitlab` - GitLab\n\* `gitea` - Gitea\n\* `shortcut` - Shortcut\n\* `sentry` - Sentry\n\* `rollbar` - Rollbar\n\* `bugsnag` - Bugsnag\n\* `honeybadger` - Honeybadger\n\* `raygun` - Raygun\n\* `snyk` - Snyk\n\* `sonarqube` - SonarQube\n\* `semgrep` - Semgrep\n\* `rapid7_insightvm` - Rapid7 InsightVM\n\* `featurebase` - Featurebase\n\* `frill` - Frill\n\* `aha` - Aha\n\* `uservoice` - UserVoice\n\* `productboard` - Productboard\n\* `canny` - Canny\n\* `asknicely` - AskNicely\n\* `retently` - Retently\n\* `appfigures` - Appfigures\n\* `appfollow` - AppFollow\n\* `judgeme_reviews` - Judge.me\n\* `intercom` - Intercom\n\* `hubspot` - HubSpot' ), source_type: zod .enum([ diff --git a/services/mcp/src/api/generated.ts b/services/mcp/src/api/generated.ts index 7309ab90cdb4..21215b1941ed 100644 --- a/services/mcp/src/api/generated.ts +++ b/services/mcp/src/api/generated.ts @@ -32896,6 +32896,13 @@ export namespace Schemas { created_at: string | null; } + export interface HubspotTicketSignalExtra { + hs_ticket_priority: string | null; + hs_pipeline_stage: string | null; + hs_ticket_category: string | null; + createdate: string | null; + } + export interface IdentityMatchingError { /** Human-readable explanation of why the request could not be served. */ detail: string; @@ -33684,6 +33691,13 @@ export namespace Schemas { Recording: 'recording', } as const; + export interface IntercomTicketSignalExtra { + state: string | null; + priority: string | null; + admin_assignee_id: string | null; + created_at: string | null; + } + export interface InterestingNote { text: string; line_refs: string; @@ -40631,6 +40645,8 @@ export namespace Schemas { * * `appfigures` - Appfigures * * `appfollow` - AppFollow * * `judgeme_reviews` - Judge.me + * * `intercom` - Intercom + * * `hubspot` - HubSpot */ export type SignalSourceConfigSourceProductEnum = typeof SignalSourceConfigSourceProductEnum[keyof typeof SignalSourceConfigSourceProductEnum]; @@ -40681,6 +40697,8 @@ export namespace Schemas { Appfigures: 'appfigures', Appfollow: 'appfollow', JudgemeReviews: 'judgeme_reviews', + Intercom: 'intercom', + Hubspot: 'hubspot', } as const; /** @@ -55974,6 +55992,8 @@ export namespace Schemas { * * `appfigures` - appfigures * * `appfollow` - appfollow * * `judgeme_reviews` - judgeme_reviews + * * `intercom` - intercom + * * `hubspot` - hubspot */ export type SignalSourceProduct = typeof SignalSourceProduct[keyof typeof SignalSourceProduct]; @@ -56024,6 +56044,8 @@ export namespace Schemas { Appfigures: 'appfigures', Appfollow: 'appfollow', JudgemeReviews: 'judgeme_reviews', + Intercom: 'intercom', + Hubspot: 'hubspot', } as const; /** @@ -56192,7 +56214,7 @@ export namespace Schemas { createdDate: string | null; } - export type SignalExtra = SessionProblemSignalExtra | LlmEvalSignalExtra | LlmEvalReportSignalExtra | ZendeskTicketSignalExtra | GithubIssueSignalExtra | LinearIssueSignalExtra | JiraIssueSignalExtra | ConversationsTicketSignalExtra | ErrorTrackingSignalExtra | PgAnalyzeIssueSignalExtra | EndpointExecutionFailedSignalExtra | EndpointBreakdownLimitExceededSignalExtra | SignalsScoutSignalExtra | LogsAlertStateChangeSignalExtra | ReplayVisionScannerFindingSignalExtra | AnalyticsAnomalyInvestigationSignalExtra | HealthCheckSignalExtra | FreshdeskTicketSignalExtra | FreshserviceTicketSignalExtra | FrontConversationSignalExtra | GorgiasTicketSignalExtra | KustomerConversationSignalExtra | DixaConversationSignalExtra | PlainThreadSignalExtra | GitlabIssueSignalExtra | GiteaIssueSignalExtra | ShortcutStorySignalExtra | SentryIssueSignalExtra | RollbarItemSignalExtra | BugsnagErrorSignalExtra | HoneybadgerFaultSignalExtra | RaygunErrorGroupSignalExtra | SnykScannerFindingSignalExtra | SonarqubeScannerFindingSignalExtra | SemgrepScannerFindingSignalExtra | Rapid7InsightvmScannerFindingSignalExtra | FeaturebaseFeedbackSignalExtra | FrillFeedbackSignalExtra | AhaFeedbackSignalExtra | UservoiceFeedbackSignalExtra | ProductboardFeedbackSignalExtra | CannyFeedbackSignalExtra | AsknicelyFeedbackSignalExtra | RetentlyFeedbackSignalExtra | AppfiguresReviewSignalExtra | AppfollowReviewSignalExtra | JudgemeReviewsReviewSignalExtra; + export type SignalExtra = SessionProblemSignalExtra | LlmEvalSignalExtra | LlmEvalReportSignalExtra | ZendeskTicketSignalExtra | GithubIssueSignalExtra | LinearIssueSignalExtra | JiraIssueSignalExtra | ConversationsTicketSignalExtra | ErrorTrackingSignalExtra | PgAnalyzeIssueSignalExtra | EndpointExecutionFailedSignalExtra | EndpointBreakdownLimitExceededSignalExtra | SignalsScoutSignalExtra | LogsAlertStateChangeSignalExtra | ReplayVisionScannerFindingSignalExtra | AnalyticsAnomalyInvestigationSignalExtra | HealthCheckSignalExtra | FreshdeskTicketSignalExtra | FreshserviceTicketSignalExtra | FrontConversationSignalExtra | GorgiasTicketSignalExtra | KustomerConversationSignalExtra | DixaConversationSignalExtra | PlainThreadSignalExtra | GitlabIssueSignalExtra | GiteaIssueSignalExtra | ShortcutStorySignalExtra | SentryIssueSignalExtra | RollbarItemSignalExtra | BugsnagErrorSignalExtra | HoneybadgerFaultSignalExtra | RaygunErrorGroupSignalExtra | SnykScannerFindingSignalExtra | SonarqubeScannerFindingSignalExtra | SemgrepScannerFindingSignalExtra | Rapid7InsightvmScannerFindingSignalExtra | FeaturebaseFeedbackSignalExtra | FrillFeedbackSignalExtra | AhaFeedbackSignalExtra | UservoiceFeedbackSignalExtra | ProductboardFeedbackSignalExtra | CannyFeedbackSignalExtra | AsknicelyFeedbackSignalExtra | RetentlyFeedbackSignalExtra | AppfiguresReviewSignalExtra | AppfollowReviewSignalExtra | JudgemeReviewsReviewSignalExtra | IntercomTicketSignalExtra | HubspotTicketSignalExtra; export type SignalMatchMetadata = MatchedMetadata | NoMatchMetadata; @@ -56247,7 +56269,9 @@ export namespace Schemas { * * `retently` - retently * * `appfigures` - appfigures * * `appfollow` - appfollow - * * `judgeme_reviews` - judgeme_reviews */ + * * `judgeme_reviews` - judgeme_reviews + * * `intercom` - intercom + * * `hubspot` - hubspot */ source_product: SignalSourceProduct; /** Signal type within the source product. * diff --git a/services/mcp/src/generated/signals/api.ts b/services/mcp/src/generated/signals/api.ts index c2f567a7def7..d7a46a990192 100644 --- a/services/mcp/src/generated/signals/api.ts +++ b/services/mcp/src/generated/signals/api.ts @@ -1188,9 +1188,11 @@ export const SignalsSourceConfigsCreateBody = /* @__PURE__ */ zod.object({ 'appfigures', 'appfollow', 'judgeme_reviews', + 'intercom', + 'hubspot', ]) .describe( - '* `session_replay` - Session replay\n* `llm_analytics` - LLM analytics\n* `github` - GitHub\n* `linear` - Linear\n* `jira` - Jira\n* `zendesk` - Zendesk\n* `conversations` - Conversations\n* `error_tracking` - Error tracking\n* `pganalyze` - pganalyze\n* `signals_scout` - Signals scout\n* `logs` - Logs\n* `health_checks` - Health checks\n* `endpoints` - Endpoints\n* `replay_vision` - Replay Vision\n* `analytics` - Product analytics\n* `freshdesk` - Freshdesk\n* `freshservice` - Freshservice\n* `front` - Front\n* `gorgias` - Gorgias\n* `kustomer` - Kustomer\n* `dixa` - Dixa\n* `plain` - Plain\n* `gitlab` - GitLab\n* `gitea` - Gitea\n* `shortcut` - Shortcut\n* `sentry` - Sentry\n* `rollbar` - Rollbar\n* `bugsnag` - Bugsnag\n* `honeybadger` - Honeybadger\n* `raygun` - Raygun\n* `snyk` - Snyk\n* `sonarqube` - SonarQube\n* `semgrep` - Semgrep\n* `rapid7_insightvm` - Rapid7 InsightVM\n* `featurebase` - Featurebase\n* `frill` - Frill\n* `aha` - Aha\n* `uservoice` - UserVoice\n* `productboard` - Productboard\n* `canny` - Canny\n* `asknicely` - AskNicely\n* `retently` - Retently\n* `appfigures` - Appfigures\n* `appfollow` - AppFollow\n* `judgeme_reviews` - Judge.me' + '* `session_replay` - Session replay\n* `llm_analytics` - LLM analytics\n* `github` - GitHub\n* `linear` - Linear\n* `jira` - Jira\n* `zendesk` - Zendesk\n* `conversations` - Conversations\n* `error_tracking` - Error tracking\n* `pganalyze` - pganalyze\n* `signals_scout` - Signals scout\n* `logs` - Logs\n* `health_checks` - Health checks\n* `endpoints` - Endpoints\n* `replay_vision` - Replay Vision\n* `analytics` - Product analytics\n* `freshdesk` - Freshdesk\n* `freshservice` - Freshservice\n* `front` - Front\n* `gorgias` - Gorgias\n* `kustomer` - Kustomer\n* `dixa` - Dixa\n* `plain` - Plain\n* `gitlab` - GitLab\n* `gitea` - Gitea\n* `shortcut` - Shortcut\n* `sentry` - Sentry\n* `rollbar` - Rollbar\n* `bugsnag` - Bugsnag\n* `honeybadger` - Honeybadger\n* `raygun` - Raygun\n* `snyk` - Snyk\n* `sonarqube` - SonarQube\n* `semgrep` - Semgrep\n* `rapid7_insightvm` - Rapid7 InsightVM\n* `featurebase` - Featurebase\n* `frill` - Frill\n* `aha` - Aha\n* `uservoice` - UserVoice\n* `productboard` - Productboard\n* `canny` - Canny\n* `asknicely` - AskNicely\n* `retently` - Retently\n* `appfigures` - Appfigures\n* `appfollow` - AppFollow\n* `judgeme_reviews` - Judge.me\n* `intercom` - Intercom\n* `hubspot` - HubSpot' ), source_type: zod .enum([ @@ -1283,9 +1285,11 @@ export const SignalsSourceConfigsUpdateBody = /* @__PURE__ */ zod.object({ 'appfigures', 'appfollow', 'judgeme_reviews', + 'intercom', + 'hubspot', ]) .describe( - '* `session_replay` - Session replay\n* `llm_analytics` - LLM analytics\n* `github` - GitHub\n* `linear` - Linear\n* `jira` - Jira\n* `zendesk` - Zendesk\n* `conversations` - Conversations\n* `error_tracking` - Error tracking\n* `pganalyze` - pganalyze\n* `signals_scout` - Signals scout\n* `logs` - Logs\n* `health_checks` - Health checks\n* `endpoints` - Endpoints\n* `replay_vision` - Replay Vision\n* `analytics` - Product analytics\n* `freshdesk` - Freshdesk\n* `freshservice` - Freshservice\n* `front` - Front\n* `gorgias` - Gorgias\n* `kustomer` - Kustomer\n* `dixa` - Dixa\n* `plain` - Plain\n* `gitlab` - GitLab\n* `gitea` - Gitea\n* `shortcut` - Shortcut\n* `sentry` - Sentry\n* `rollbar` - Rollbar\n* `bugsnag` - Bugsnag\n* `honeybadger` - Honeybadger\n* `raygun` - Raygun\n* `snyk` - Snyk\n* `sonarqube` - SonarQube\n* `semgrep` - Semgrep\n* `rapid7_insightvm` - Rapid7 InsightVM\n* `featurebase` - Featurebase\n* `frill` - Frill\n* `aha` - Aha\n* `uservoice` - UserVoice\n* `productboard` - Productboard\n* `canny` - Canny\n* `asknicely` - AskNicely\n* `retently` - Retently\n* `appfigures` - Appfigures\n* `appfollow` - AppFollow\n* `judgeme_reviews` - Judge.me' + '* `session_replay` - Session replay\n* `llm_analytics` - LLM analytics\n* `github` - GitHub\n* `linear` - Linear\n* `jira` - Jira\n* `zendesk` - Zendesk\n* `conversations` - Conversations\n* `error_tracking` - Error tracking\n* `pganalyze` - pganalyze\n* `signals_scout` - Signals scout\n* `logs` - Logs\n* `health_checks` - Health checks\n* `endpoints` - Endpoints\n* `replay_vision` - Replay Vision\n* `analytics` - Product analytics\n* `freshdesk` - Freshdesk\n* `freshservice` - Freshservice\n* `front` - Front\n* `gorgias` - Gorgias\n* `kustomer` - Kustomer\n* `dixa` - Dixa\n* `plain` - Plain\n* `gitlab` - GitLab\n* `gitea` - Gitea\n* `shortcut` - Shortcut\n* `sentry` - Sentry\n* `rollbar` - Rollbar\n* `bugsnag` - Bugsnag\n* `honeybadger` - Honeybadger\n* `raygun` - Raygun\n* `snyk` - Snyk\n* `sonarqube` - SonarQube\n* `semgrep` - Semgrep\n* `rapid7_insightvm` - Rapid7 InsightVM\n* `featurebase` - Featurebase\n* `frill` - Frill\n* `aha` - Aha\n* `uservoice` - UserVoice\n* `productboard` - Productboard\n* `canny` - Canny\n* `asknicely` - AskNicely\n* `retently` - Retently\n* `appfigures` - Appfigures\n* `appfollow` - AppFollow\n* `judgeme_reviews` - Judge.me\n* `intercom` - Intercom\n* `hubspot` - HubSpot' ), source_type: zod .enum([ @@ -1369,10 +1373,12 @@ export const SignalsSourceConfigsPartialUpdateBody = /* @__PURE__ */ zod.object( 'appfigures', 'appfollow', 'judgeme_reviews', + 'intercom', + 'hubspot', ]) .optional() .describe( - '* `session_replay` - Session replay\n* `llm_analytics` - LLM analytics\n* `github` - GitHub\n* `linear` - Linear\n* `jira` - Jira\n* `zendesk` - Zendesk\n* `conversations` - Conversations\n* `error_tracking` - Error tracking\n* `pganalyze` - pganalyze\n* `signals_scout` - Signals scout\n* `logs` - Logs\n* `health_checks` - Health checks\n* `endpoints` - Endpoints\n* `replay_vision` - Replay Vision\n* `analytics` - Product analytics\n* `freshdesk` - Freshdesk\n* `freshservice` - Freshservice\n* `front` - Front\n* `gorgias` - Gorgias\n* `kustomer` - Kustomer\n* `dixa` - Dixa\n* `plain` - Plain\n* `gitlab` - GitLab\n* `gitea` - Gitea\n* `shortcut` - Shortcut\n* `sentry` - Sentry\n* `rollbar` - Rollbar\n* `bugsnag` - Bugsnag\n* `honeybadger` - Honeybadger\n* `raygun` - Raygun\n* `snyk` - Snyk\n* `sonarqube` - SonarQube\n* `semgrep` - Semgrep\n* `rapid7_insightvm` - Rapid7 InsightVM\n* `featurebase` - Featurebase\n* `frill` - Frill\n* `aha` - Aha\n* `uservoice` - UserVoice\n* `productboard` - Productboard\n* `canny` - Canny\n* `asknicely` - AskNicely\n* `retently` - Retently\n* `appfigures` - Appfigures\n* `appfollow` - AppFollow\n* `judgeme_reviews` - Judge.me' + '* `session_replay` - Session replay\n* `llm_analytics` - LLM analytics\n* `github` - GitHub\n* `linear` - Linear\n* `jira` - Jira\n* `zendesk` - Zendesk\n* `conversations` - Conversations\n* `error_tracking` - Error tracking\n* `pganalyze` - pganalyze\n* `signals_scout` - Signals scout\n* `logs` - Logs\n* `health_checks` - Health checks\n* `endpoints` - Endpoints\n* `replay_vision` - Replay Vision\n* `analytics` - Product analytics\n* `freshdesk` - Freshdesk\n* `freshservice` - Freshservice\n* `front` - Front\n* `gorgias` - Gorgias\n* `kustomer` - Kustomer\n* `dixa` - Dixa\n* `plain` - Plain\n* `gitlab` - GitLab\n* `gitea` - Gitea\n* `shortcut` - Shortcut\n* `sentry` - Sentry\n* `rollbar` - Rollbar\n* `bugsnag` - Bugsnag\n* `honeybadger` - Honeybadger\n* `raygun` - Raygun\n* `snyk` - Snyk\n* `sonarqube` - SonarQube\n* `semgrep` - Semgrep\n* `rapid7_insightvm` - Rapid7 InsightVM\n* `featurebase` - Featurebase\n* `frill` - Frill\n* `aha` - Aha\n* `uservoice` - UserVoice\n* `productboard` - Productboard\n* `canny` - Canny\n* `asknicely` - AskNicely\n* `retently` - Retently\n* `appfigures` - Appfigures\n* `appfollow` - AppFollow\n* `judgeme_reviews` - Judge.me\n* `intercom` - Intercom\n* `hubspot` - HubSpot' ), source_type: zod .enum([ diff --git a/services/mcp/tests/unit/__snapshots__/tool-schemas/inbox-source-configs-create.json b/services/mcp/tests/unit/__snapshots__/tool-schemas/inbox-source-configs-create.json index b40295330d16..8a1695deb288 100644 --- a/services/mcp/tests/unit/__snapshots__/tool-schemas/inbox-source-configs-create.json +++ b/services/mcp/tests/unit/__snapshots__/tool-schemas/inbox-source-configs-create.json @@ -6,7 +6,7 @@ "type": "boolean" }, "source_product": { - "description": "* `session_replay` - Session replay\n* `llm_analytics` - LLM analytics\n* `github` - GitHub\n* `linear` - Linear\n* `jira` - Jira\n* `zendesk` - Zendesk\n* `conversations` - Conversations\n* `error_tracking` - Error tracking\n* `pganalyze` - pganalyze\n* `signals_scout` - Signals scout\n* `logs` - Logs\n* `health_checks` - Health checks\n* `endpoints` - Endpoints\n* `replay_vision` - Replay Vision\n* `analytics` - Product analytics\n* `freshdesk` - Freshdesk\n* `freshservice` - Freshservice\n* `front` - Front\n* `gorgias` - Gorgias\n* `kustomer` - Kustomer\n* `dixa` - Dixa\n* `plain` - Plain\n* `gitlab` - GitLab\n* `gitea` - Gitea\n* `shortcut` - Shortcut\n* `sentry` - Sentry\n* `rollbar` - Rollbar\n* `bugsnag` - Bugsnag\n* `honeybadger` - Honeybadger\n* `raygun` - Raygun\n* `snyk` - Snyk\n* `sonarqube` - SonarQube\n* `semgrep` - Semgrep\n* `rapid7_insightvm` - Rapid7 InsightVM\n* `featurebase` - Featurebase\n* `frill` - Frill\n* `aha` - Aha\n* `uservoice` - UserVoice\n* `productboard` - Productboard\n* `canny` - Canny\n* `asknicely` - AskNicely\n* `retently` - Retently\n* `appfigures` - Appfigures\n* `appfollow` - AppFollow\n* `judgeme_reviews` - Judge.me", + "description": "* `session_replay` - Session replay\n* `llm_analytics` - LLM analytics\n* `github` - GitHub\n* `linear` - Linear\n* `jira` - Jira\n* `zendesk` - Zendesk\n* `conversations` - Conversations\n* `error_tracking` - Error tracking\n* `pganalyze` - pganalyze\n* `signals_scout` - Signals scout\n* `logs` - Logs\n* `health_checks` - Health checks\n* `endpoints` - Endpoints\n* `replay_vision` - Replay Vision\n* `analytics` - Product analytics\n* `freshdesk` - Freshdesk\n* `freshservice` - Freshservice\n* `front` - Front\n* `gorgias` - Gorgias\n* `kustomer` - Kustomer\n* `dixa` - Dixa\n* `plain` - Plain\n* `gitlab` - GitLab\n* `gitea` - Gitea\n* `shortcut` - Shortcut\n* `sentry` - Sentry\n* `rollbar` - Rollbar\n* `bugsnag` - Bugsnag\n* `honeybadger` - Honeybadger\n* `raygun` - Raygun\n* `snyk` - Snyk\n* `sonarqube` - SonarQube\n* `semgrep` - Semgrep\n* `rapid7_insightvm` - Rapid7 InsightVM\n* `featurebase` - Featurebase\n* `frill` - Frill\n* `aha` - Aha\n* `uservoice` - UserVoice\n* `productboard` - Productboard\n* `canny` - Canny\n* `asknicely` - AskNicely\n* `retently` - Retently\n* `appfigures` - Appfigures\n* `appfollow` - AppFollow\n* `judgeme_reviews` - Judge.me\n* `intercom` - Intercom\n* `hubspot` - HubSpot", "enum": [ "session_replay", "llm_analytics", @@ -52,7 +52,9 @@ "retently", "appfigures", "appfollow", - "judgeme_reviews" + "judgeme_reviews", + "intercom", + "hubspot" ], "type": "string" }, diff --git a/services/mcp/tests/unit/__snapshots__/tool-schemas/inbox-source-configs-partial-update.json b/services/mcp/tests/unit/__snapshots__/tool-schemas/inbox-source-configs-partial-update.json index 405583031418..59ecfa197218 100644 --- a/services/mcp/tests/unit/__snapshots__/tool-schemas/inbox-source-configs-partial-update.json +++ b/services/mcp/tests/unit/__snapshots__/tool-schemas/inbox-source-configs-partial-update.json @@ -10,7 +10,7 @@ "type": "string" }, "source_product": { - "description": "* `session_replay` - Session replay\n* `llm_analytics` - LLM analytics\n* `github` - GitHub\n* `linear` - Linear\n* `jira` - Jira\n* `zendesk` - Zendesk\n* `conversations` - Conversations\n* `error_tracking` - Error tracking\n* `pganalyze` - pganalyze\n* `signals_scout` - Signals scout\n* `logs` - Logs\n* `health_checks` - Health checks\n* `endpoints` - Endpoints\n* `replay_vision` - Replay Vision\n* `analytics` - Product analytics\n* `freshdesk` - Freshdesk\n* `freshservice` - Freshservice\n* `front` - Front\n* `gorgias` - Gorgias\n* `kustomer` - Kustomer\n* `dixa` - Dixa\n* `plain` - Plain\n* `gitlab` - GitLab\n* `gitea` - Gitea\n* `shortcut` - Shortcut\n* `sentry` - Sentry\n* `rollbar` - Rollbar\n* `bugsnag` - Bugsnag\n* `honeybadger` - Honeybadger\n* `raygun` - Raygun\n* `snyk` - Snyk\n* `sonarqube` - SonarQube\n* `semgrep` - Semgrep\n* `rapid7_insightvm` - Rapid7 InsightVM\n* `featurebase` - Featurebase\n* `frill` - Frill\n* `aha` - Aha\n* `uservoice` - UserVoice\n* `productboard` - Productboard\n* `canny` - Canny\n* `asknicely` - AskNicely\n* `retently` - Retently\n* `appfigures` - Appfigures\n* `appfollow` - AppFollow\n* `judgeme_reviews` - Judge.me", + "description": "* `session_replay` - Session replay\n* `llm_analytics` - LLM analytics\n* `github` - GitHub\n* `linear` - Linear\n* `jira` - Jira\n* `zendesk` - Zendesk\n* `conversations` - Conversations\n* `error_tracking` - Error tracking\n* `pganalyze` - pganalyze\n* `signals_scout` - Signals scout\n* `logs` - Logs\n* `health_checks` - Health checks\n* `endpoints` - Endpoints\n* `replay_vision` - Replay Vision\n* `analytics` - Product analytics\n* `freshdesk` - Freshdesk\n* `freshservice` - Freshservice\n* `front` - Front\n* `gorgias` - Gorgias\n* `kustomer` - Kustomer\n* `dixa` - Dixa\n* `plain` - Plain\n* `gitlab` - GitLab\n* `gitea` - Gitea\n* `shortcut` - Shortcut\n* `sentry` - Sentry\n* `rollbar` - Rollbar\n* `bugsnag` - Bugsnag\n* `honeybadger` - Honeybadger\n* `raygun` - Raygun\n* `snyk` - Snyk\n* `sonarqube` - SonarQube\n* `semgrep` - Semgrep\n* `rapid7_insightvm` - Rapid7 InsightVM\n* `featurebase` - Featurebase\n* `frill` - Frill\n* `aha` - Aha\n* `uservoice` - UserVoice\n* `productboard` - Productboard\n* `canny` - Canny\n* `asknicely` - AskNicely\n* `retently` - Retently\n* `appfigures` - Appfigures\n* `appfollow` - AppFollow\n* `judgeme_reviews` - Judge.me\n* `intercom` - Intercom\n* `hubspot` - HubSpot", "enum": [ "session_replay", "llm_analytics", @@ -56,7 +56,9 @@ "retently", "appfigures", "appfollow", - "judgeme_reviews" + "judgeme_reviews", + "intercom", + "hubspot" ], "type": "string" }, diff --git a/services/mcp/tests/unit/__snapshots__/tool-schemas/inbox-source-configs-update.json b/services/mcp/tests/unit/__snapshots__/tool-schemas/inbox-source-configs-update.json index 43073ebd865d..9349d4912950 100644 --- a/services/mcp/tests/unit/__snapshots__/tool-schemas/inbox-source-configs-update.json +++ b/services/mcp/tests/unit/__snapshots__/tool-schemas/inbox-source-configs-update.json @@ -10,7 +10,7 @@ "type": "string" }, "source_product": { - "description": "* `session_replay` - Session replay\n* `llm_analytics` - LLM analytics\n* `github` - GitHub\n* `linear` - Linear\n* `jira` - Jira\n* `zendesk` - Zendesk\n* `conversations` - Conversations\n* `error_tracking` - Error tracking\n* `pganalyze` - pganalyze\n* `signals_scout` - Signals scout\n* `logs` - Logs\n* `health_checks` - Health checks\n* `endpoints` - Endpoints\n* `replay_vision` - Replay Vision\n* `analytics` - Product analytics\n* `freshdesk` - Freshdesk\n* `freshservice` - Freshservice\n* `front` - Front\n* `gorgias` - Gorgias\n* `kustomer` - Kustomer\n* `dixa` - Dixa\n* `plain` - Plain\n* `gitlab` - GitLab\n* `gitea` - Gitea\n* `shortcut` - Shortcut\n* `sentry` - Sentry\n* `rollbar` - Rollbar\n* `bugsnag` - Bugsnag\n* `honeybadger` - Honeybadger\n* `raygun` - Raygun\n* `snyk` - Snyk\n* `sonarqube` - SonarQube\n* `semgrep` - Semgrep\n* `rapid7_insightvm` - Rapid7 InsightVM\n* `featurebase` - Featurebase\n* `frill` - Frill\n* `aha` - Aha\n* `uservoice` - UserVoice\n* `productboard` - Productboard\n* `canny` - Canny\n* `asknicely` - AskNicely\n* `retently` - Retently\n* `appfigures` - Appfigures\n* `appfollow` - AppFollow\n* `judgeme_reviews` - Judge.me", + "description": "* `session_replay` - Session replay\n* `llm_analytics` - LLM analytics\n* `github` - GitHub\n* `linear` - Linear\n* `jira` - Jira\n* `zendesk` - Zendesk\n* `conversations` - Conversations\n* `error_tracking` - Error tracking\n* `pganalyze` - pganalyze\n* `signals_scout` - Signals scout\n* `logs` - Logs\n* `health_checks` - Health checks\n* `endpoints` - Endpoints\n* `replay_vision` - Replay Vision\n* `analytics` - Product analytics\n* `freshdesk` - Freshdesk\n* `freshservice` - Freshservice\n* `front` - Front\n* `gorgias` - Gorgias\n* `kustomer` - Kustomer\n* `dixa` - Dixa\n* `plain` - Plain\n* `gitlab` - GitLab\n* `gitea` - Gitea\n* `shortcut` - Shortcut\n* `sentry` - Sentry\n* `rollbar` - Rollbar\n* `bugsnag` - Bugsnag\n* `honeybadger` - Honeybadger\n* `raygun` - Raygun\n* `snyk` - Snyk\n* `sonarqube` - SonarQube\n* `semgrep` - Semgrep\n* `rapid7_insightvm` - Rapid7 InsightVM\n* `featurebase` - Featurebase\n* `frill` - Frill\n* `aha` - Aha\n* `uservoice` - UserVoice\n* `productboard` - Productboard\n* `canny` - Canny\n* `asknicely` - AskNicely\n* `retently` - Retently\n* `appfigures` - Appfigures\n* `appfollow` - AppFollow\n* `judgeme_reviews` - Judge.me\n* `intercom` - Intercom\n* `hubspot` - HubSpot", "enum": [ "session_replay", "llm_analytics", @@ -56,7 +56,9 @@ "retently", "appfigures", "appfollow", - "judgeme_reviews" + "judgeme_reviews", + "intercom", + "hubspot" ], "type": "string" },