mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
feat(profound): add Profound AI visibility and analytics integration (#3849)
* feat(profound): add Profound AI visibility and analytics integration * fix(profound): fix import ordering and JSON formatting for CI lint * fix(profound): gate metrics mapping on current operation to prevent stale overrides * fix(profound): guard JSON.parse on filters, fix offset=0 falsy check, remove duplicate prompt_answers in FILTER_OPS * lint * fix(docs): fix import ordering and trailing newline for docs lint * fix(scripts): sort generated imports to match Biome's organizeImports order * fix(profound): use != null checks for limit param across all tools * fix(profound): flatten block output type to 'json' to pass block validation test * fix(profound): remove invalid 'required' field from block inputs (not part of ParamConfig) * fix(profound): rename tool files from kebab-case to snake_case for docs generator compatibility * lint * fix(docs): let biome auto-fix import order, revert custom sort in generator * fix(landing): fix import order in sim icon-mapping via biome * fix(scripts): match Biome's exact import sort order in docs generator * fix(generate-docs): produce Biome-compatible JSON output The generator wrote multi-line arrays for short string arrays (like tags) and omitted trailing newlines, causing Biome format check failures in CI. Post-process integrations.json to collapse short arrays onto single lines and add trailing newlines to both integrations.json and meta.json. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1285,6 +1285,17 @@ export function StartIcon(props: SVGProps<SVGSVGElement>) {
|
||||
)
|
||||
}
|
||||
|
||||
export function ProfoundIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg width='1em' height='1em' viewBox='0 0 55 55' xmlns='http://www.w3.org/2000/svg' {...props}>
|
||||
<path
|
||||
fill='currentColor'
|
||||
d='M0 36.685V21.349a7.017 7.017 0 0 1 2.906-5.69l19.742-14.25A7.443 7.443 0 0 1 27.004 0h.062c1.623 0 3.193.508 4.501 1.452l19.684 14.207a7.016 7.016 0 0 1 2.906 5.69v12.302a7.013 7.013 0 0 1-2.907 5.689L31.527 53.562A7.605 7.605 0 0 1 27.078 55a7.641 7.641 0 0 1-4.465-1.44c-2.581-1.859-6.732-4.855-6.732-4.855V29.777c0-.249.28-.393.482-.248l10.538 7.605c.106.077.249.077.355 0l13.005-9.386a.306.306 0 0 0 0-.496l-13.005-9.386a.303.303 0 0 0-.355 0L.482 36.933A.304.304 0 0 1 0 36.685Z'
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function PineconeIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
|
||||
@@ -126,6 +126,7 @@ import {
|
||||
PolymarketIcon,
|
||||
PostgresIcon,
|
||||
PosthogIcon,
|
||||
ProfoundIcon,
|
||||
PulseIcon,
|
||||
QdrantIcon,
|
||||
QuiverIcon,
|
||||
@@ -302,6 +303,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
||||
polymarket: PolymarketIcon,
|
||||
postgresql: PostgresIcon,
|
||||
posthog: PosthogIcon,
|
||||
profound: ProfoundIcon,
|
||||
pulse_v2: PulseIcon,
|
||||
qdrant: QdrantIcon,
|
||||
quiver: QuiverIcon,
|
||||
|
||||
@@ -121,6 +121,7 @@
|
||||
"polymarket",
|
||||
"postgresql",
|
||||
"posthog",
|
||||
"profound",
|
||||
"pulse",
|
||||
"qdrant",
|
||||
"quiver",
|
||||
|
||||
626
apps/docs/content/docs/en/tools/profound.mdx
Normal file
626
apps/docs/content/docs/en/tools/profound.mdx
Normal file
@@ -0,0 +1,626 @@
|
||||
---
|
||||
title: Profound
|
||||
description: AI visibility and analytics with Profound
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="profound"
|
||||
color="#1A1A2E"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Profound](https://tryprofound.com/) is an AI visibility and analytics platform that helps brands understand how they appear across AI-powered search engines, chatbots, and assistants. It tracks mentions, citations, sentiment, bot traffic, and referral patterns across platforms like ChatGPT, Perplexity, Google AI Overviews, and more.
|
||||
|
||||
With the Profound integration in Sim, you can:
|
||||
|
||||
- **Monitor AI Visibility**: Track share of voice, visibility scores, and mention counts across AI platforms for your brand and competitors.
|
||||
- **Analyze Sentiment**: Measure how positively or negatively your brand is discussed in AI-generated responses.
|
||||
- **Track Citations**: See which URLs are being cited by AI models and your citation share relative to competitors.
|
||||
- **Monitor Bot Traffic**: Analyze AI crawler activity on your domain, including GPTBot, ClaudeBot, and other AI agents, with hourly granularity.
|
||||
- **Track Referral Traffic**: Monitor human visits arriving from AI platforms to your website.
|
||||
- **Explore Prompt Data**: Access raw prompt-answer pairs, query fanouts, and prompt volume trends across AI platforms.
|
||||
- **Optimize Content**: Get AEO (Answer Engine Optimization) scores and actionable recommendations to improve how AI models reference your content.
|
||||
- **Manage Categories & Assets**: List and explore your tracked categories, assets (brands), topics, tags, personas, and regions.
|
||||
|
||||
These tools let your agents automate AI visibility monitoring, competitive intelligence, and content optimization workflows. To use the Profound integration, you'll need a Profound account with API access.
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
|
||||
## Usage Instructions
|
||||
|
||||
Track how your brand appears across AI platforms. Monitor visibility scores, sentiment, citations, bot traffic, referrals, content optimization, and prompt volumes with Profound.
|
||||
|
||||
|
||||
|
||||
## Tools
|
||||
|
||||
### `profound_list_categories`
|
||||
|
||||
List all organization categories in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `categories` | json | List of organization categories |
|
||||
| ↳ `id` | string | Category ID |
|
||||
| ↳ `name` | string | Category name |
|
||||
|
||||
### `profound_list_regions`
|
||||
|
||||
List all organization regions in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `regions` | json | List of organization regions |
|
||||
| ↳ `id` | string | Region ID \(UUID\) |
|
||||
| ↳ `name` | string | Region name |
|
||||
|
||||
### `profound_list_models`
|
||||
|
||||
List all AI models/platforms tracked in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `models` | json | List of AI models/platforms |
|
||||
| ↳ `id` | string | Model ID \(UUID\) |
|
||||
| ↳ `name` | string | Model/platform name |
|
||||
|
||||
### `profound_list_domains`
|
||||
|
||||
List all organization domains in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `domains` | json | List of organization domains |
|
||||
| ↳ `id` | string | Domain ID \(UUID\) |
|
||||
| ↳ `name` | string | Domain name |
|
||||
| ↳ `createdAt` | string | When the domain was added |
|
||||
|
||||
### `profound_list_assets`
|
||||
|
||||
List all organization assets (companies/brands) across all categories in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `assets` | json | List of organization assets with category info |
|
||||
| ↳ `id` | string | Asset ID |
|
||||
| ↳ `name` | string | Asset/company name |
|
||||
| ↳ `website` | string | Asset website URL |
|
||||
| ↳ `alternateDomains` | json | Alternate domain names |
|
||||
| ↳ `isOwned` | boolean | Whether this asset is owned by the organization |
|
||||
| ↳ `createdAt` | string | When the asset was created |
|
||||
| ↳ `logoUrl` | string | URL of the asset logo |
|
||||
| ↳ `categoryId` | string | Category ID the asset belongs to |
|
||||
| ↳ `categoryName` | string | Category name |
|
||||
|
||||
### `profound_list_personas`
|
||||
|
||||
List all organization personas across all categories in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `personas` | json | List of organization personas with profile details |
|
||||
| ↳ `id` | string | Persona ID |
|
||||
| ↳ `name` | string | Persona name |
|
||||
| ↳ `categoryId` | string | Category ID |
|
||||
| ↳ `categoryName` | string | Category name |
|
||||
| ↳ `persona` | json | Persona profile with behavior, employment, and demographics |
|
||||
|
||||
### `profound_category_topics`
|
||||
|
||||
List topics for a specific category in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `categoryId` | string | Yes | Category ID \(UUID\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `topics` | json | List of topics in the category |
|
||||
| ↳ `id` | string | Topic ID \(UUID\) |
|
||||
| ↳ `name` | string | Topic name |
|
||||
|
||||
### `profound_category_tags`
|
||||
|
||||
List tags for a specific category in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `categoryId` | string | Yes | Category ID \(UUID\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `tags` | json | List of tags in the category |
|
||||
| ↳ `id` | string | Tag ID \(UUID\) |
|
||||
| ↳ `name` | string | Tag name |
|
||||
|
||||
### `profound_category_prompts`
|
||||
|
||||
List prompts for a specific category in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `categoryId` | string | Yes | Category ID \(UUID\) |
|
||||
| `limit` | number | No | Maximum number of results \(default 10000, max 10000\) |
|
||||
| `cursor` | string | No | Pagination cursor from previous response |
|
||||
| `orderDir` | string | No | Sort direction: asc or desc \(default desc\) |
|
||||
| `promptType` | string | No | Comma-separated prompt types to filter: visibility, sentiment |
|
||||
| `topicId` | string | No | Comma-separated topic IDs \(UUIDs\) to filter by |
|
||||
| `tagId` | string | No | Comma-separated tag IDs \(UUIDs\) to filter by |
|
||||
| `regionId` | string | No | Comma-separated region IDs \(UUIDs\) to filter by |
|
||||
| `platformId` | string | No | Comma-separated platform IDs \(UUIDs\) to filter by |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `totalRows` | number | Total number of prompts |
|
||||
| `nextCursor` | string | Cursor for next page of results |
|
||||
| `prompts` | json | List of prompts |
|
||||
| ↳ `id` | string | Prompt ID |
|
||||
| ↳ `prompt` | string | Prompt text |
|
||||
| ↳ `promptType` | string | Prompt type \(visibility or sentiment\) |
|
||||
| ↳ `topicId` | string | Topic ID |
|
||||
| ↳ `topicName` | string | Topic name |
|
||||
| ↳ `tags` | json | Associated tags |
|
||||
| ↳ `regions` | json | Associated regions |
|
||||
| ↳ `platforms` | json | Associated platforms |
|
||||
| ↳ `createdAt` | string | When the prompt was created |
|
||||
|
||||
### `profound_category_assets`
|
||||
|
||||
List assets (companies/brands) for a specific category in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `categoryId` | string | Yes | Category ID \(UUID\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `assets` | json | List of assets in the category |
|
||||
| ↳ `id` | string | Asset ID |
|
||||
| ↳ `name` | string | Asset/company name |
|
||||
| ↳ `website` | string | Website URL |
|
||||
| ↳ `alternateDomains` | json | Alternate domain names |
|
||||
| ↳ `isOwned` | boolean | Whether the asset is owned by the organization |
|
||||
| ↳ `createdAt` | string | When the asset was created |
|
||||
| ↳ `logoUrl` | string | URL of the asset logo |
|
||||
|
||||
### `profound_category_personas`
|
||||
|
||||
List personas for a specific category in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `categoryId` | string | Yes | Category ID \(UUID\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `personas` | json | List of personas in the category |
|
||||
| ↳ `id` | string | Persona ID |
|
||||
| ↳ `name` | string | Persona name |
|
||||
| ↳ `persona` | json | Persona profile with behavior, employment, and demographics |
|
||||
|
||||
### `profound_visibility_report`
|
||||
|
||||
Query AI visibility report for a category in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `categoryId` | string | Yes | Category ID \(UUID\) |
|
||||
| `startDate` | string | Yes | Start date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `endDate` | string | Yes | End date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `metrics` | string | Yes | Comma-separated metrics: share_of_voice, mentions_count, visibility_score, executions, average_position |
|
||||
| `dimensions` | string | No | Comma-separated dimensions: date, region, topic, model, asset_name, prompt, tag, persona |
|
||||
| `dateInterval` | string | No | Date interval: hour, day, week, month, year |
|
||||
| `filters` | string | No | JSON array of filter objects, e.g. \[\{"field":"asset_name","operator":"is","value":"Company"\}\] |
|
||||
| `limit` | number | No | Maximum number of results \(default 10000, max 50000\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `totalRows` | number | Total number of rows in the report |
|
||||
| `data` | json | Report data rows with metrics and dimension values |
|
||||
| ↳ `metrics` | json | Array of metric values matching requested metrics order |
|
||||
| ↳ `dimensions` | json | Array of dimension values matching requested dimensions order |
|
||||
|
||||
### `profound_sentiment_report`
|
||||
|
||||
Query sentiment report for a category in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `categoryId` | string | Yes | Category ID \(UUID\) |
|
||||
| `startDate` | string | Yes | Start date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `endDate` | string | Yes | End date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `metrics` | string | Yes | Comma-separated metrics: positive, negative, occurrences |
|
||||
| `dimensions` | string | No | Comma-separated dimensions: theme, date, region, topic, model, asset_name, tag, prompt, sentiment_type, persona |
|
||||
| `dateInterval` | string | No | Date interval: hour, day, week, month, year |
|
||||
| `filters` | string | No | JSON array of filter objects, e.g. \[\{"field":"asset_name","operator":"is","value":"Company"\}\] |
|
||||
| `limit` | number | No | Maximum number of results \(default 10000, max 50000\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `totalRows` | number | Total number of rows in the report |
|
||||
| `data` | json | Report data rows with metrics and dimension values |
|
||||
| ↳ `metrics` | json | Array of metric values matching requested metrics order |
|
||||
| ↳ `dimensions` | json | Array of dimension values matching requested dimensions order |
|
||||
|
||||
### `profound_citations_report`
|
||||
|
||||
Query citations report for a category in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `categoryId` | string | Yes | Category ID \(UUID\) |
|
||||
| `startDate` | string | Yes | Start date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `endDate` | string | Yes | End date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `metrics` | string | Yes | Comma-separated metrics: count, citation_share |
|
||||
| `dimensions` | string | No | Comma-separated dimensions: hostname, path, date, region, topic, model, tag, prompt, url, root_domain, persona, citation_category |
|
||||
| `dateInterval` | string | No | Date interval: hour, day, week, month, year |
|
||||
| `filters` | string | No | JSON array of filter objects, e.g. \[\{"field":"hostname","operator":"is","value":"example.com"\}\] |
|
||||
| `limit` | number | No | Maximum number of results \(default 10000, max 50000\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `totalRows` | number | Total number of rows in the report |
|
||||
| `data` | json | Report data rows with metrics and dimension values |
|
||||
| ↳ `metrics` | json | Array of metric values matching requested metrics order |
|
||||
| ↳ `dimensions` | json | Array of dimension values matching requested dimensions order |
|
||||
|
||||
### `profound_query_fanouts`
|
||||
|
||||
Query fanout report showing how AI models expand prompts into sub-queries in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `categoryId` | string | Yes | Category ID \(UUID\) |
|
||||
| `startDate` | string | Yes | Start date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `endDate` | string | Yes | End date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `metrics` | string | Yes | Comma-separated metrics: fanouts_per_execution, total_fanouts, share |
|
||||
| `dimensions` | string | No | Comma-separated dimensions: prompt, query, model, region, date |
|
||||
| `dateInterval` | string | No | Date interval: hour, day, week, month, year |
|
||||
| `filters` | string | No | JSON array of filter objects |
|
||||
| `limit` | number | No | Maximum number of results \(default 10000, max 50000\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `totalRows` | number | Total number of rows in the report |
|
||||
| `data` | json | Report data rows with metrics and dimension values |
|
||||
| ↳ `metrics` | json | Array of metric values matching requested metrics order |
|
||||
| ↳ `dimensions` | json | Array of dimension values matching requested dimensions order |
|
||||
|
||||
### `profound_prompt_answers`
|
||||
|
||||
Get raw prompt answers data for a category in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `categoryId` | string | Yes | Category ID \(UUID\) |
|
||||
| `startDate` | string | Yes | Start date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `endDate` | string | Yes | End date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `filters` | string | No | JSON array of filter objects, e.g. \[\{"field":"prompt_type","operator":"is","value":"visibility"\}\] |
|
||||
| `limit` | number | No | Maximum number of results \(default 10000, max 50000\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `totalRows` | number | Total number of answer rows |
|
||||
| `data` | json | Raw prompt answer data |
|
||||
| ↳ `prompt` | string | The prompt text |
|
||||
| ↳ `promptType` | string | Prompt type \(visibility or sentiment\) |
|
||||
| ↳ `response` | string | AI model response text |
|
||||
| ↳ `mentions` | json | Companies/assets mentioned in the response |
|
||||
| ↳ `citations` | json | URLs cited in the response |
|
||||
| ↳ `topic` | string | Topic name |
|
||||
| ↳ `region` | string | Region name |
|
||||
| ↳ `model` | string | AI model/platform name |
|
||||
| ↳ `asset` | string | Asset name |
|
||||
| ↳ `createdAt` | string | Timestamp when the answer was collected |
|
||||
|
||||
### `profound_bots_report`
|
||||
|
||||
Query bot traffic report with hourly granularity for a domain in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `domain` | string | Yes | Domain to query bot traffic for \(e.g. example.com\) |
|
||||
| `startDate` | string | Yes | Start date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `endDate` | string | No | End date \(YYYY-MM-DD or ISO 8601\). Defaults to now |
|
||||
| `metrics` | string | Yes | Comma-separated metrics: count, citations, indexing, training, last_visit |
|
||||
| `dimensions` | string | No | Comma-separated dimensions: date, hour, path, bot_name, bot_provider, bot_type |
|
||||
| `dateInterval` | string | No | Date interval: hour, day, week, month, year |
|
||||
| `filters` | string | No | JSON array of filter objects, e.g. \[\{"field":"bot_name","operator":"is","value":"GPTBot"\}\] |
|
||||
| `limit` | number | No | Maximum number of results \(default 10000, max 50000\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `totalRows` | number | Total number of rows in the report |
|
||||
| `data` | json | Report data rows with metrics and dimension values |
|
||||
| ↳ `metrics` | json | Array of metric values matching requested metrics order |
|
||||
| ↳ `dimensions` | json | Array of dimension values matching requested dimensions order |
|
||||
|
||||
### `profound_referrals_report`
|
||||
|
||||
Query human referral traffic report with hourly granularity for a domain in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `domain` | string | Yes | Domain to query referral traffic for \(e.g. example.com\) |
|
||||
| `startDate` | string | Yes | Start date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `endDate` | string | No | End date \(YYYY-MM-DD or ISO 8601\). Defaults to now |
|
||||
| `metrics` | string | Yes | Comma-separated metrics: visits, last_visit |
|
||||
| `dimensions` | string | No | Comma-separated dimensions: date, hour, path, referral_source, referral_type |
|
||||
| `dateInterval` | string | No | Date interval: hour, day, week, month, year |
|
||||
| `filters` | string | No | JSON array of filter objects, e.g. \[\{"field":"referral_source","operator":"is","value":"openai"\}\] |
|
||||
| `limit` | number | No | Maximum number of results \(default 10000, max 50000\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `totalRows` | number | Total number of rows in the report |
|
||||
| `data` | json | Report data rows with metrics and dimension values |
|
||||
| ↳ `metrics` | json | Array of metric values matching requested metrics order |
|
||||
| ↳ `dimensions` | json | Array of dimension values matching requested dimensions order |
|
||||
|
||||
### `profound_raw_logs`
|
||||
|
||||
Get raw traffic logs with filters for a domain in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `domain` | string | Yes | Domain to query logs for \(e.g. example.com\) |
|
||||
| `startDate` | string | Yes | Start date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `endDate` | string | No | End date \(YYYY-MM-DD or ISO 8601\). Defaults to now |
|
||||
| `dimensions` | string | No | Comma-separated dimensions: timestamp, method, host, path, status_code, ip, user_agent, referer, bytes_sent, duration_ms, query_params |
|
||||
| `filters` | string | No | JSON array of filter objects, e.g. \[\{"field":"path","operator":"contains","value":"/blog"\}\] |
|
||||
| `limit` | number | No | Maximum number of results \(default 10000, max 50000\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `totalRows` | number | Total number of log entries |
|
||||
| `data` | json | Log data rows with metrics and dimension values |
|
||||
| ↳ `metrics` | json | Array of metric values \(count\) |
|
||||
| ↳ `dimensions` | json | Array of dimension values matching requested dimensions order |
|
||||
|
||||
### `profound_bot_logs`
|
||||
|
||||
Get identified bot visit logs with filters for a domain in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `domain` | string | Yes | Domain to query bot logs for \(e.g. example.com\) |
|
||||
| `startDate` | string | Yes | Start date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `endDate` | string | No | End date \(YYYY-MM-DD or ISO 8601\). Defaults to now |
|
||||
| `dimensions` | string | No | Comma-separated dimensions: timestamp, method, host, path, status_code, ip, user_agent, referer, bytes_sent, duration_ms, query_params, bot_name, bot_provider, bot_types |
|
||||
| `filters` | string | No | JSON array of filter objects, e.g. \[\{"field":"bot_name","operator":"is","value":"GPTBot"\}\] |
|
||||
| `limit` | number | No | Maximum number of results \(default 10000, max 50000\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `totalRows` | number | Total number of bot log entries |
|
||||
| `data` | json | Bot log data rows with metrics and dimension values |
|
||||
| ↳ `metrics` | json | Array of metric values \(count\) |
|
||||
| ↳ `dimensions` | json | Array of dimension values matching requested dimensions order |
|
||||
|
||||
### `profound_list_optimizations`
|
||||
|
||||
List content optimization entries for an asset in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `assetId` | string | Yes | Asset ID \(UUID\) |
|
||||
| `limit` | number | No | Maximum number of results \(default 10000, max 50000\) |
|
||||
| `offset` | number | No | Offset for pagination \(default 0\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `totalRows` | number | Total number of optimization entries |
|
||||
| `optimizations` | json | List of content optimization entries |
|
||||
| ↳ `id` | string | Optimization ID \(UUID\) |
|
||||
| ↳ `title` | string | Content title |
|
||||
| ↳ `createdAt` | string | When the optimization was created |
|
||||
| ↳ `extractedInput` | string | Extracted input text |
|
||||
| ↳ `type` | string | Content type: file, text, or url |
|
||||
| ↳ `status` | string | Optimization status |
|
||||
|
||||
### `profound_optimization_analysis`
|
||||
|
||||
Get detailed content optimization analysis for a specific content item in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `assetId` | string | Yes | Asset ID \(UUID\) |
|
||||
| `contentId` | string | Yes | Content/optimization ID \(UUID\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `content` | json | The analyzed content |
|
||||
| ↳ `format` | string | Content format: markdown or html |
|
||||
| ↳ `value` | string | Content text |
|
||||
| `aeoContentScore` | json | AEO content score with target zone |
|
||||
| ↳ `value` | number | AEO score value |
|
||||
| ↳ `targetZone` | json | Target zone range |
|
||||
| ↳ `low` | number | Low end of target range |
|
||||
| ↳ `high` | number | High end of target range |
|
||||
| `analysis` | json | Analysis breakdown by category |
|
||||
| ↳ `breakdown` | json | Array of scoring breakdowns |
|
||||
| ↳ `title` | string | Category title |
|
||||
| ↳ `weight` | number | Category weight |
|
||||
| ↳ `score` | number | Category score |
|
||||
| `recommendations` | json | Content optimization recommendations |
|
||||
| ↳ `title` | string | Recommendation title |
|
||||
| ↳ `status` | string | Status: done or pending |
|
||||
| ↳ `impact` | json | Impact details with section and score |
|
||||
| ↳ `suggestion` | json | Suggestion text and rationale |
|
||||
| ↳ `text` | string | Suggestion text |
|
||||
| ↳ `rationale` | string | Why this recommendation matters |
|
||||
|
||||
### `profound_prompt_volume`
|
||||
|
||||
Query prompt volume data to understand search demand across AI platforms in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `startDate` | string | Yes | Start date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `endDate` | string | Yes | End date \(YYYY-MM-DD or ISO 8601\) |
|
||||
| `metrics` | string | Yes | Comma-separated metrics: volume, change |
|
||||
| `dimensions` | string | No | Comma-separated dimensions: keyword, date, platform, country_code, matching_type, frequency |
|
||||
| `dateInterval` | string | No | Date interval: hour, day, week, month, year |
|
||||
| `filters` | string | No | JSON array of filter objects, e.g. \[\{"field":"keyword","operator":"contains","value":"best"\}\] |
|
||||
| `limit` | number | No | Maximum number of results \(default 10000, max 50000\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `totalRows` | number | Total number of rows in the report |
|
||||
| `data` | json | Volume data rows with metrics and dimension values |
|
||||
| ↳ `metrics` | json | Array of metric values matching requested metrics order |
|
||||
| ↳ `dimensions` | json | Array of dimension values matching requested dimensions order |
|
||||
|
||||
### `profound_citation_prompts`
|
||||
|
||||
Get prompts that cite a specific domain across AI platforms in Profound
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Profound API Key |
|
||||
| `inputDomain` | string | Yes | Domain to look up citations for \(e.g. ramp.com\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `data` | json | Citation prompt data for the queried domain |
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ import {
|
||||
PolymarketIcon,
|
||||
PostgresIcon,
|
||||
PosthogIcon,
|
||||
ProfoundIcon,
|
||||
PulseIcon,
|
||||
QdrantIcon,
|
||||
QuiverIcon,
|
||||
@@ -302,6 +303,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
||||
polymarket: PolymarketIcon,
|
||||
postgresql: PostgresIcon,
|
||||
posthog: PosthogIcon,
|
||||
profound: ProfoundIcon,
|
||||
pulse_v2: PulseIcon,
|
||||
qdrant: QdrantIcon,
|
||||
quiver: QuiverIcon,
|
||||
|
||||
@@ -8611,6 +8611,121 @@
|
||||
"integrationType": "analytics",
|
||||
"tags": ["data-analytics", "monitoring"]
|
||||
},
|
||||
{
|
||||
"type": "profound",
|
||||
"slug": "profound",
|
||||
"name": "Profound",
|
||||
"description": "AI visibility and analytics with Profound",
|
||||
"longDescription": "Track how your brand appears across AI platforms. Monitor visibility scores, sentiment, citations, bot traffic, referrals, content optimization, and prompt volumes with Profound.",
|
||||
"bgColor": "#1A1A2E",
|
||||
"iconName": "ProfoundIcon",
|
||||
"docsUrl": "https://docs.sim.ai/tools/profound",
|
||||
"operations": [
|
||||
{
|
||||
"name": "List Categories",
|
||||
"description": "List all organization categories in Profound"
|
||||
},
|
||||
{
|
||||
"name": "List Regions",
|
||||
"description": "List all organization regions in Profound"
|
||||
},
|
||||
{
|
||||
"name": "List Models",
|
||||
"description": "List all AI models/platforms tracked in Profound"
|
||||
},
|
||||
{
|
||||
"name": "List Domains",
|
||||
"description": "List all organization domains in Profound"
|
||||
},
|
||||
{
|
||||
"name": "List Assets",
|
||||
"description": "List all organization assets (companies/brands) across all categories in Profound"
|
||||
},
|
||||
{
|
||||
"name": "List Personas",
|
||||
"description": "List all organization personas across all categories in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Category Topics",
|
||||
"description": "List topics for a specific category in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Category Tags",
|
||||
"description": "List tags for a specific category in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Category Prompts",
|
||||
"description": "List prompts for a specific category in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Category Assets",
|
||||
"description": "List assets (companies/brands) for a specific category in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Category Personas",
|
||||
"description": "List personas for a specific category in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Visibility Report",
|
||||
"description": "Query AI visibility report for a category in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Sentiment Report",
|
||||
"description": "Query sentiment report for a category in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Citations Report",
|
||||
"description": "Query citations report for a category in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Query Fanouts",
|
||||
"description": "Query fanout report showing how AI models expand prompts into sub-queries in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Prompt Answers",
|
||||
"description": "Get raw prompt answers data for a category in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Bots Report",
|
||||
"description": "Query bot traffic report with hourly granularity for a domain in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Referrals Report",
|
||||
"description": "Query human referral traffic report with hourly granularity for a domain in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Raw Logs",
|
||||
"description": "Get raw traffic logs with filters for a domain in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Bot Logs",
|
||||
"description": "Get identified bot visit logs with filters for a domain in Profound"
|
||||
},
|
||||
{
|
||||
"name": "List Optimizations",
|
||||
"description": "List content optimization entries for an asset in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Optimization Analysis",
|
||||
"description": "Get detailed content optimization analysis for a specific content item in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Prompt Volume",
|
||||
"description": "Query prompt volume data to understand search demand across AI platforms in Profound"
|
||||
},
|
||||
{
|
||||
"name": "Citation Prompts",
|
||||
"description": "Get prompts that cite a specific domain across AI platforms in Profound"
|
||||
}
|
||||
],
|
||||
"operationCount": 24,
|
||||
"triggers": [],
|
||||
"triggerCount": 0,
|
||||
"authType": "api-key",
|
||||
"category": "tools",
|
||||
"integrationType": "analytics",
|
||||
"tags": ["seo", "data-analytics"]
|
||||
},
|
||||
{
|
||||
"type": "pulse_v2",
|
||||
"slug": "pulse",
|
||||
|
||||
406
apps/sim/blocks/blocks/profound.ts
Normal file
406
apps/sim/blocks/blocks/profound.ts
Normal file
@@ -0,0 +1,406 @@
|
||||
import { ProfoundIcon } from '@/components/icons'
|
||||
import type { BlockConfig } from '@/blocks/types'
|
||||
import { AuthMode, IntegrationType } from '@/blocks/types'
|
||||
|
||||
const CATEGORY_REPORT_OPS = [
|
||||
'visibility_report',
|
||||
'sentiment_report',
|
||||
'citations_report',
|
||||
'prompt_answers',
|
||||
'query_fanouts',
|
||||
] as const
|
||||
|
||||
const DOMAIN_REPORT_OPS = ['bots_report', 'referrals_report', 'raw_logs', 'bot_logs'] as const
|
||||
|
||||
const ALL_REPORT_OPS = [...CATEGORY_REPORT_OPS, ...DOMAIN_REPORT_OPS] as const
|
||||
|
||||
const CATEGORY_ID_OPS = [
|
||||
...CATEGORY_REPORT_OPS,
|
||||
'category_topics',
|
||||
'category_tags',
|
||||
'category_prompts',
|
||||
'category_assets',
|
||||
'category_personas',
|
||||
] as const
|
||||
|
||||
const DATE_REQUIRED_CATEGORY_OPS = [
|
||||
'visibility_report',
|
||||
'sentiment_report',
|
||||
'citations_report',
|
||||
'prompt_answers',
|
||||
'query_fanouts',
|
||||
'prompt_volume',
|
||||
] as const
|
||||
|
||||
const DATE_REQUIRED_ALL_OPS = [...DATE_REQUIRED_CATEGORY_OPS, ...DOMAIN_REPORT_OPS] as const
|
||||
|
||||
const METRICS_REPORT_OPS = [
|
||||
'visibility_report',
|
||||
'sentiment_report',
|
||||
'citations_report',
|
||||
'bots_report',
|
||||
'referrals_report',
|
||||
'query_fanouts',
|
||||
'prompt_volume',
|
||||
] as const
|
||||
|
||||
const DIMENSION_OPS = [
|
||||
'visibility_report',
|
||||
'sentiment_report',
|
||||
'citations_report',
|
||||
'bots_report',
|
||||
'referrals_report',
|
||||
'query_fanouts',
|
||||
'raw_logs',
|
||||
'bot_logs',
|
||||
'prompt_volume',
|
||||
] as const
|
||||
|
||||
const FILTER_OPS = [...ALL_REPORT_OPS, 'prompt_volume'] as const
|
||||
|
||||
export const ProfoundBlock: BlockConfig = {
|
||||
type: 'profound',
|
||||
name: 'Profound',
|
||||
description: 'AI visibility and analytics with Profound',
|
||||
longDescription:
|
||||
'Track how your brand appears across AI platforms. Monitor visibility scores, sentiment, citations, bot traffic, referrals, content optimization, and prompt volumes with Profound.',
|
||||
docsLink: 'https://docs.sim.ai/tools/profound',
|
||||
category: 'tools',
|
||||
integrationType: IntegrationType.Analytics,
|
||||
tags: ['seo', 'data-analytics'],
|
||||
bgColor: '#1A1A2E',
|
||||
icon: ProfoundIcon,
|
||||
authMode: AuthMode.ApiKey,
|
||||
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'operation',
|
||||
title: 'Operation',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'List Categories', id: 'list_categories' },
|
||||
{ label: 'List Regions', id: 'list_regions' },
|
||||
{ label: 'List Models', id: 'list_models' },
|
||||
{ label: 'List Domains', id: 'list_domains' },
|
||||
{ label: 'List Assets', id: 'list_assets' },
|
||||
{ label: 'List Personas', id: 'list_personas' },
|
||||
{ label: 'Category Topics', id: 'category_topics' },
|
||||
{ label: 'Category Tags', id: 'category_tags' },
|
||||
{ label: 'Category Prompts', id: 'category_prompts' },
|
||||
{ label: 'Category Assets', id: 'category_assets' },
|
||||
{ label: 'Category Personas', id: 'category_personas' },
|
||||
{ label: 'Visibility Report', id: 'visibility_report' },
|
||||
{ label: 'Sentiment Report', id: 'sentiment_report' },
|
||||
{ label: 'Citations Report', id: 'citations_report' },
|
||||
{ label: 'Query Fanouts', id: 'query_fanouts' },
|
||||
{ label: 'Prompt Answers', id: 'prompt_answers' },
|
||||
{ label: 'Bots Report', id: 'bots_report' },
|
||||
{ label: 'Referrals Report', id: 'referrals_report' },
|
||||
{ label: 'Raw Logs', id: 'raw_logs' },
|
||||
{ label: 'Bot Logs', id: 'bot_logs' },
|
||||
{ label: 'List Optimizations', id: 'list_optimizations' },
|
||||
{ label: 'Optimization Analysis', id: 'optimization_analysis' },
|
||||
{ label: 'Prompt Volume', id: 'prompt_volume' },
|
||||
{ label: 'Citation Prompts', id: 'citation_prompts' },
|
||||
],
|
||||
value: () => 'visibility_report',
|
||||
},
|
||||
{
|
||||
id: 'apiKey',
|
||||
title: 'API Key',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter your Profound API key',
|
||||
required: true,
|
||||
password: true,
|
||||
},
|
||||
|
||||
// Category ID - for category-based operations
|
||||
{
|
||||
id: 'categoryId',
|
||||
title: 'Category ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Category UUID',
|
||||
required: { field: 'operation', value: [...CATEGORY_ID_OPS] },
|
||||
condition: { field: 'operation', value: [...CATEGORY_ID_OPS] },
|
||||
},
|
||||
|
||||
// Domain - for domain-based operations
|
||||
{
|
||||
id: 'domain',
|
||||
title: 'Domain',
|
||||
type: 'short-input',
|
||||
placeholder: 'e.g. example.com',
|
||||
required: { field: 'operation', value: [...DOMAIN_REPORT_OPS] },
|
||||
condition: { field: 'operation', value: [...DOMAIN_REPORT_OPS] },
|
||||
},
|
||||
|
||||
// Input domain - for citation prompts
|
||||
{
|
||||
id: 'inputDomain',
|
||||
title: 'Domain',
|
||||
type: 'short-input',
|
||||
placeholder: 'e.g. ramp.com',
|
||||
required: { field: 'operation', value: 'citation_prompts' },
|
||||
condition: { field: 'operation', value: 'citation_prompts' },
|
||||
},
|
||||
|
||||
// Asset ID - for content optimization
|
||||
{
|
||||
id: 'assetId',
|
||||
title: 'Asset ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Asset UUID',
|
||||
required: { field: 'operation', value: ['list_optimizations', 'optimization_analysis'] },
|
||||
condition: { field: 'operation', value: ['list_optimizations', 'optimization_analysis'] },
|
||||
},
|
||||
|
||||
// Content ID - for optimization analysis
|
||||
{
|
||||
id: 'contentId',
|
||||
title: 'Content ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Content/optimization UUID',
|
||||
required: { field: 'operation', value: 'optimization_analysis' },
|
||||
condition: { field: 'operation', value: 'optimization_analysis' },
|
||||
},
|
||||
|
||||
// Date fields
|
||||
{
|
||||
id: 'startDate',
|
||||
title: 'Start Date',
|
||||
type: 'short-input',
|
||||
placeholder: 'YYYY-MM-DD',
|
||||
required: { field: 'operation', value: [...DATE_REQUIRED_ALL_OPS] },
|
||||
condition: { field: 'operation', value: [...DATE_REQUIRED_ALL_OPS] },
|
||||
wandConfig: {
|
||||
enabled: true,
|
||||
prompt: 'Generate a date in YYYY-MM-DD format. Return ONLY the date string.',
|
||||
generationType: 'timestamp',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'endDate',
|
||||
title: 'End Date',
|
||||
type: 'short-input',
|
||||
placeholder: 'YYYY-MM-DD',
|
||||
required: { field: 'operation', value: [...DATE_REQUIRED_CATEGORY_OPS] },
|
||||
condition: { field: 'operation', value: [...DATE_REQUIRED_ALL_OPS] },
|
||||
wandConfig: {
|
||||
enabled: true,
|
||||
prompt: 'Generate a date in YYYY-MM-DD format. Return ONLY the date string.',
|
||||
generationType: 'timestamp',
|
||||
},
|
||||
},
|
||||
|
||||
// Per-operation metrics fields
|
||||
{
|
||||
id: 'visibilityMetrics',
|
||||
title: 'Metrics',
|
||||
type: 'short-input',
|
||||
placeholder: 'share_of_voice, visibility_score, mentions_count',
|
||||
required: { field: 'operation', value: 'visibility_report' },
|
||||
condition: { field: 'operation', value: 'visibility_report' },
|
||||
},
|
||||
{
|
||||
id: 'sentimentMetrics',
|
||||
title: 'Metrics',
|
||||
type: 'short-input',
|
||||
placeholder: 'positive, negative, occurrences',
|
||||
required: { field: 'operation', value: 'sentiment_report' },
|
||||
condition: { field: 'operation', value: 'sentiment_report' },
|
||||
},
|
||||
{
|
||||
id: 'citationsMetrics',
|
||||
title: 'Metrics',
|
||||
type: 'short-input',
|
||||
placeholder: 'count, citation_share',
|
||||
required: { field: 'operation', value: 'citations_report' },
|
||||
condition: { field: 'operation', value: 'citations_report' },
|
||||
},
|
||||
{
|
||||
id: 'botsMetrics',
|
||||
title: 'Metrics',
|
||||
type: 'short-input',
|
||||
placeholder: 'count, citations, indexing, training',
|
||||
required: { field: 'operation', value: 'bots_report' },
|
||||
condition: { field: 'operation', value: 'bots_report' },
|
||||
},
|
||||
{
|
||||
id: 'referralsMetrics',
|
||||
title: 'Metrics',
|
||||
type: 'short-input',
|
||||
placeholder: 'visits, last_visit',
|
||||
required: { field: 'operation', value: 'referrals_report' },
|
||||
condition: { field: 'operation', value: 'referrals_report' },
|
||||
},
|
||||
{
|
||||
id: 'fanoutsMetrics',
|
||||
title: 'Metrics',
|
||||
type: 'short-input',
|
||||
placeholder: 'fanouts_per_execution, total_fanouts, share',
|
||||
required: { field: 'operation', value: 'query_fanouts' },
|
||||
condition: { field: 'operation', value: 'query_fanouts' },
|
||||
},
|
||||
{
|
||||
id: 'volumeMetrics',
|
||||
title: 'Metrics',
|
||||
type: 'short-input',
|
||||
placeholder: 'volume, change',
|
||||
required: { field: 'operation', value: 'prompt_volume' },
|
||||
condition: { field: 'operation', value: 'prompt_volume' },
|
||||
},
|
||||
|
||||
// Advanced fields
|
||||
{
|
||||
id: 'dimensions',
|
||||
title: 'Dimensions',
|
||||
type: 'short-input',
|
||||
placeholder: 'e.g. date, asset_name, model',
|
||||
condition: { field: 'operation', value: [...DIMENSION_OPS] },
|
||||
mode: 'advanced',
|
||||
},
|
||||
{
|
||||
id: 'dateInterval',
|
||||
title: 'Date Interval',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Day', id: 'day' },
|
||||
{ label: 'Hour', id: 'hour' },
|
||||
{ label: 'Week', id: 'week' },
|
||||
{ label: 'Month', id: 'month' },
|
||||
{ label: 'Year', id: 'year' },
|
||||
],
|
||||
condition: { field: 'operation', value: [...METRICS_REPORT_OPS] },
|
||||
mode: 'advanced',
|
||||
},
|
||||
{
|
||||
id: 'filters',
|
||||
title: 'Filters',
|
||||
type: 'long-input',
|
||||
placeholder: '[{"field":"asset_name","operator":"is","value":"Company"}]',
|
||||
condition: { field: 'operation', value: [...FILTER_OPS] },
|
||||
mode: 'advanced',
|
||||
wandConfig: {
|
||||
enabled: true,
|
||||
prompt:
|
||||
'Generate a JSON array of filter objects. Each object has "field", "operator", and "value" keys. Return ONLY valid JSON.',
|
||||
generationType: 'json-object',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'limit',
|
||||
title: 'Limit',
|
||||
type: 'short-input',
|
||||
placeholder: '10000',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: [...FILTER_OPS, 'category_prompts', 'list_optimizations'],
|
||||
},
|
||||
mode: 'advanced',
|
||||
},
|
||||
|
||||
// Category prompts specific fields
|
||||
{
|
||||
id: 'cursor',
|
||||
title: 'Cursor',
|
||||
type: 'short-input',
|
||||
placeholder: 'Pagination cursor from previous response',
|
||||
condition: { field: 'operation', value: 'category_prompts' },
|
||||
mode: 'advanced',
|
||||
},
|
||||
{
|
||||
id: 'promptType',
|
||||
title: 'Prompt Type',
|
||||
type: 'short-input',
|
||||
placeholder: 'visibility, sentiment',
|
||||
condition: { field: 'operation', value: 'category_prompts' },
|
||||
mode: 'advanced',
|
||||
},
|
||||
|
||||
// Optimization list specific
|
||||
{
|
||||
id: 'offset',
|
||||
title: 'Offset',
|
||||
type: 'short-input',
|
||||
placeholder: '0',
|
||||
condition: { field: 'operation', value: 'list_optimizations' },
|
||||
mode: 'advanced',
|
||||
},
|
||||
],
|
||||
|
||||
tools: {
|
||||
access: [
|
||||
'profound_list_categories',
|
||||
'profound_list_regions',
|
||||
'profound_list_models',
|
||||
'profound_list_domains',
|
||||
'profound_list_assets',
|
||||
'profound_list_personas',
|
||||
'profound_category_topics',
|
||||
'profound_category_tags',
|
||||
'profound_category_prompts',
|
||||
'profound_category_assets',
|
||||
'profound_category_personas',
|
||||
'profound_visibility_report',
|
||||
'profound_sentiment_report',
|
||||
'profound_citations_report',
|
||||
'profound_query_fanouts',
|
||||
'profound_prompt_answers',
|
||||
'profound_bots_report',
|
||||
'profound_referrals_report',
|
||||
'profound_raw_logs',
|
||||
'profound_bot_logs',
|
||||
'profound_list_optimizations',
|
||||
'profound_optimization_analysis',
|
||||
'profound_prompt_volume',
|
||||
'profound_citation_prompts',
|
||||
],
|
||||
config: {
|
||||
tool: (params) => `profound_${params.operation}`,
|
||||
params: (params) => {
|
||||
const result: Record<string, unknown> = {}
|
||||
const metricsMap: Record<string, string> = {
|
||||
visibility_report: 'visibilityMetrics',
|
||||
sentiment_report: 'sentimentMetrics',
|
||||
citations_report: 'citationsMetrics',
|
||||
bots_report: 'botsMetrics',
|
||||
referrals_report: 'referralsMetrics',
|
||||
query_fanouts: 'fanoutsMetrics',
|
||||
prompt_volume: 'volumeMetrics',
|
||||
}
|
||||
const metricsField = metricsMap[params.operation as string]
|
||||
if (metricsField && params[metricsField]) {
|
||||
result.metrics = params[metricsField]
|
||||
}
|
||||
if (params.limit != null) result.limit = Number(params.limit)
|
||||
if (params.offset != null) result.offset = Number(params.offset)
|
||||
return result
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
inputs: {
|
||||
apiKey: { type: 'string' },
|
||||
categoryId: { type: 'string' },
|
||||
domain: { type: 'string' },
|
||||
inputDomain: { type: 'string' },
|
||||
assetId: { type: 'string' },
|
||||
contentId: { type: 'string' },
|
||||
startDate: { type: 'string' },
|
||||
endDate: { type: 'string' },
|
||||
metrics: { type: 'string' },
|
||||
dimensions: { type: 'string' },
|
||||
dateInterval: { type: 'string' },
|
||||
filters: { type: 'string' },
|
||||
limit: { type: 'number' },
|
||||
offset: { type: 'number' },
|
||||
cursor: { type: 'string' },
|
||||
promptType: { type: 'string' },
|
||||
},
|
||||
|
||||
outputs: {
|
||||
response: {
|
||||
type: 'json',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -137,6 +137,7 @@ import { PipedriveBlock } from '@/blocks/blocks/pipedrive'
|
||||
import { PolymarketBlock } from '@/blocks/blocks/polymarket'
|
||||
import { PostgreSQLBlock } from '@/blocks/blocks/postgresql'
|
||||
import { PostHogBlock } from '@/blocks/blocks/posthog'
|
||||
import { ProfoundBlock } from '@/blocks/blocks/profound'
|
||||
import { PulseBlock, PulseV2Block } from '@/blocks/blocks/pulse'
|
||||
import { QdrantBlock } from '@/blocks/blocks/qdrant'
|
||||
import { QuiverBlock } from '@/blocks/blocks/quiver'
|
||||
@@ -357,6 +358,7 @@ export const registry: Record<string, BlockConfig> = {
|
||||
perplexity: PerplexityBlock,
|
||||
pinecone: PineconeBlock,
|
||||
pipedrive: PipedriveBlock,
|
||||
profound: ProfoundBlock,
|
||||
polymarket: PolymarketBlock,
|
||||
postgresql: PostgreSQLBlock,
|
||||
posthog: PostHogBlock,
|
||||
|
||||
@@ -1285,6 +1285,17 @@ export function StartIcon(props: SVGProps<SVGSVGElement>) {
|
||||
)
|
||||
}
|
||||
|
||||
export function ProfoundIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg width='1em' height='1em' viewBox='0 0 55 55' xmlns='http://www.w3.org/2000/svg' {...props}>
|
||||
<path
|
||||
fill='currentColor'
|
||||
d='M0 36.685V21.349a7.017 7.017 0 0 1 2.906-5.69l19.742-14.25A7.443 7.443 0 0 1 27.004 0h.062c1.623 0 3.193.508 4.501 1.452l19.684 14.207a7.016 7.016 0 0 1 2.906 5.69v12.302a7.013 7.013 0 0 1-2.907 5.689L31.527 53.562A7.605 7.605 0 0 1 27.078 55a7.641 7.641 0 0 1-4.465-1.44c-2.581-1.859-6.732-4.855-6.732-4.855V29.777c0-.249.28-.393.482-.248l10.538 7.605c.106.077.249.077.355 0l13.005-9.386a.306.306 0 0 0 0-.496l-13.005-9.386a.303.303 0 0 0-.355 0L.482 36.933A.304.304 0 0 1 0 36.685Z'
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function PineconeIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
|
||||
137
apps/sim/tools/profound/bot_logs.ts
Normal file
137
apps/sim/tools/profound/bot_logs.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundBotLogsParams, ProfoundBotLogsResponse } from './types'
|
||||
|
||||
export const profoundBotLogsTool: ToolConfig<ProfoundBotLogsParams, ProfoundBotLogsResponse> = {
|
||||
id: 'profound_bot_logs',
|
||||
name: 'Profound Bot Logs',
|
||||
description: 'Get identified bot visit logs with filters for a domain in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Domain to query bot logs for (e.g. example.com)',
|
||||
},
|
||||
startDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'End date (YYYY-MM-DD or ISO 8601). Defaults to now',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated dimensions: timestamp, method, host, path, status_code, ip, user_agent, referer, bytes_sent, duration_ms, query_params, bot_name, bot_provider, bot_types',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of filter objects, e.g. [{"field":"bot_name","operator":"is","value":"GPTBot"}]',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results (default 10000, max 50000)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/logs/raw/bots',
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
domain: params.domain,
|
||||
start_date: params.startDate,
|
||||
metrics: ['count'],
|
||||
}
|
||||
if (params.endDate) {
|
||||
body.end_date = params.endDate
|
||||
}
|
||||
if (params.dimensions) {
|
||||
body.dimensions = params.dimensions.split(',').map((d) => d.trim())
|
||||
}
|
||||
if (params.filters) {
|
||||
try {
|
||||
body.filters = JSON.parse(params.filters)
|
||||
} catch {
|
||||
throw new Error('Invalid JSON in filters parameter')
|
||||
}
|
||||
}
|
||||
if (params.limit != null) {
|
||||
body.pagination = { limit: params.limit }
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to get bot logs')
|
||||
}
|
||||
if (Array.isArray(data)) {
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.length,
|
||||
data: data.map((row: { metrics: number[]; dimensions: string[] }) => ({
|
||||
metrics: row.metrics ?? [],
|
||||
dimensions: row.dimensions ?? [],
|
||||
})),
|
||||
},
|
||||
}
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.info?.total_rows ?? 0,
|
||||
data: (data.data ?? []).map((row: { metrics: number[]; dimensions: string[] }) => ({
|
||||
metrics: row.metrics ?? [],
|
||||
dimensions: row.dimensions ?? [],
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
totalRows: {
|
||||
type: 'number',
|
||||
description: 'Total number of bot log entries',
|
||||
},
|
||||
data: {
|
||||
type: 'json',
|
||||
description: 'Bot log data rows with metrics and dimension values',
|
||||
properties: {
|
||||
metrics: { type: 'json', description: 'Array of metric values (count)' },
|
||||
dimensions: {
|
||||
type: 'json',
|
||||
description: 'Array of dimension values matching requested dimensions order',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
145
apps/sim/tools/profound/bots_report.ts
Normal file
145
apps/sim/tools/profound/bots_report.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundBotsReportParams, ProfoundBotsReportResponse } from './types'
|
||||
|
||||
export const profoundBotsReportTool: ToolConfig<
|
||||
ProfoundBotsReportParams,
|
||||
ProfoundBotsReportResponse
|
||||
> = {
|
||||
id: 'profound_bots_report',
|
||||
name: 'Profound Bots Report',
|
||||
description: 'Query bot traffic report with hourly granularity for a domain in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Domain to query bot traffic for (e.g. example.com)',
|
||||
},
|
||||
startDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'End date (YYYY-MM-DD or ISO 8601). Defaults to now',
|
||||
},
|
||||
metrics: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated metrics: count, citations, indexing, training, last_visit',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated dimensions: date, hour, path, bot_name, bot_provider, bot_type',
|
||||
},
|
||||
dateInterval: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Date interval: hour, day, week, month, year',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of filter objects, e.g. [{"field":"bot_name","operator":"is","value":"GPTBot"}]',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results (default 10000, max 50000)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v2/reports/bots',
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
domain: params.domain,
|
||||
start_date: params.startDate,
|
||||
metrics: params.metrics.split(',').map((m) => m.trim()),
|
||||
}
|
||||
if (params.endDate) {
|
||||
body.end_date = params.endDate
|
||||
}
|
||||
if (params.dimensions) {
|
||||
body.dimensions = params.dimensions.split(',').map((d) => d.trim())
|
||||
}
|
||||
if (params.dateInterval) {
|
||||
body.date_interval = params.dateInterval
|
||||
}
|
||||
if (params.filters) {
|
||||
try {
|
||||
body.filters = JSON.parse(params.filters)
|
||||
} catch {
|
||||
throw new Error('Invalid JSON in filters parameter')
|
||||
}
|
||||
}
|
||||
if (params.limit != null) {
|
||||
body.pagination = { limit: params.limit }
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to query bots report')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.info?.total_rows ?? 0,
|
||||
data: (data.data ?? []).map((row: { metrics: number[]; dimensions: string[] }) => ({
|
||||
metrics: row.metrics ?? [],
|
||||
dimensions: row.dimensions ?? [],
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
totalRows: {
|
||||
type: 'number',
|
||||
description: 'Total number of rows in the report',
|
||||
},
|
||||
data: {
|
||||
type: 'json',
|
||||
description: 'Report data rows with metrics and dimension values',
|
||||
properties: {
|
||||
metrics: {
|
||||
type: 'json',
|
||||
description: 'Array of metric values matching requested metrics order',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'json',
|
||||
description: 'Array of dimension values matching requested dimensions order',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
84
apps/sim/tools/profound/category_assets.ts
Normal file
84
apps/sim/tools/profound/category_assets.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundCategoryAssetsParams, ProfoundCategoryAssetsResponse } from './types'
|
||||
|
||||
export const profoundCategoryAssetsTool: ToolConfig<
|
||||
ProfoundCategoryAssetsParams,
|
||||
ProfoundCategoryAssetsResponse
|
||||
> = {
|
||||
id: 'profound_category_assets',
|
||||
name: 'Profound Category Assets',
|
||||
description: 'List assets (companies/brands) for a specific category in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
categoryId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Category ID (UUID)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://api.tryprofound.com/v1/org/categories/${encodeURIComponent(params.categoryId)}/assets`,
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to list category assets')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
assets: (data ?? []).map(
|
||||
(item: {
|
||||
id: string
|
||||
name: string
|
||||
website: string
|
||||
alternate_domains: string[] | null
|
||||
is_owned: boolean
|
||||
created_at: string
|
||||
logo_url: string
|
||||
}) => ({
|
||||
id: item.id ?? null,
|
||||
name: item.name ?? null,
|
||||
website: item.website ?? null,
|
||||
alternateDomains: item.alternate_domains ?? null,
|
||||
isOwned: item.is_owned ?? false,
|
||||
createdAt: item.created_at ?? null,
|
||||
logoUrl: item.logo_url ?? null,
|
||||
})
|
||||
),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
assets: {
|
||||
type: 'json',
|
||||
description: 'List of assets in the category',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Asset ID' },
|
||||
name: { type: 'string', description: 'Asset/company name' },
|
||||
website: { type: 'string', description: 'Website URL' },
|
||||
alternateDomains: { type: 'json', description: 'Alternate domain names' },
|
||||
isOwned: { type: 'boolean', description: 'Whether the asset is owned by the organization' },
|
||||
createdAt: { type: 'string', description: 'When the asset was created' },
|
||||
logoUrl: { type: 'string', description: 'URL of the asset logo' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
98
apps/sim/tools/profound/category_personas.ts
Normal file
98
apps/sim/tools/profound/category_personas.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundCategoryPersonasParams, ProfoundCategoryPersonasResponse } from './types'
|
||||
|
||||
export const profoundCategoryPersonasTool: ToolConfig<
|
||||
ProfoundCategoryPersonasParams,
|
||||
ProfoundCategoryPersonasResponse
|
||||
> = {
|
||||
id: 'profound_category_personas',
|
||||
name: 'Profound Category Personas',
|
||||
description: 'List personas for a specific category in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
categoryId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Category ID (UUID)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://api.tryprofound.com/v1/org/categories/${encodeURIComponent(params.categoryId)}/personas`,
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to list category personas')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
personas: (data.data ?? []).map(
|
||||
(item: {
|
||||
id: string
|
||||
name: string
|
||||
persona: {
|
||||
behavior: { painPoints: string | null; motivations: string | null }
|
||||
employment: {
|
||||
industry: string[]
|
||||
jobTitle: string[]
|
||||
companySize: string[]
|
||||
roleSeniority: string[]
|
||||
}
|
||||
demographics: { ageRange: string[] }
|
||||
}
|
||||
}) => ({
|
||||
id: item.id ?? null,
|
||||
name: item.name ?? null,
|
||||
persona: {
|
||||
behavior: {
|
||||
painPoints: item.persona?.behavior?.painPoints ?? null,
|
||||
motivations: item.persona?.behavior?.motivations ?? null,
|
||||
},
|
||||
employment: {
|
||||
industry: item.persona?.employment?.industry ?? [],
|
||||
jobTitle: item.persona?.employment?.jobTitle ?? [],
|
||||
companySize: item.persona?.employment?.companySize ?? [],
|
||||
roleSeniority: item.persona?.employment?.roleSeniority ?? [],
|
||||
},
|
||||
demographics: {
|
||||
ageRange: item.persona?.demographics?.ageRange ?? [],
|
||||
},
|
||||
},
|
||||
})
|
||||
),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
personas: {
|
||||
type: 'json',
|
||||
description: 'List of personas in the category',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Persona ID' },
|
||||
name: { type: 'string', description: 'Persona name' },
|
||||
persona: {
|
||||
type: 'json',
|
||||
description: 'Persona profile with behavior, employment, and demographics',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
189
apps/sim/tools/profound/category_prompts.ts
Normal file
189
apps/sim/tools/profound/category_prompts.ts
Normal file
@@ -0,0 +1,189 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundCategoryPromptsParams, ProfoundCategoryPromptsResponse } from './types'
|
||||
|
||||
export const profoundCategoryPromptsTool: ToolConfig<
|
||||
ProfoundCategoryPromptsParams,
|
||||
ProfoundCategoryPromptsResponse
|
||||
> = {
|
||||
id: 'profound_category_prompts',
|
||||
name: 'Profound Category Prompts',
|
||||
description: 'List prompts for a specific category in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
categoryId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Category ID (UUID)',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results (default 10000, max 10000)',
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pagination cursor from previous response',
|
||||
},
|
||||
orderDir: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Sort direction: asc or desc (default desc)',
|
||||
},
|
||||
promptType: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated prompt types to filter: visibility, sentiment',
|
||||
},
|
||||
topicId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated topic IDs (UUIDs) to filter by',
|
||||
},
|
||||
tagId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated tag IDs (UUIDs) to filter by',
|
||||
},
|
||||
regionId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated region IDs (UUIDs) to filter by',
|
||||
},
|
||||
platformId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated platform IDs (UUIDs) to filter by',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(
|
||||
`https://api.tryprofound.com/v1/org/categories/${encodeURIComponent(params.categoryId)}/prompts`
|
||||
)
|
||||
if (params.limit != null) url.searchParams.set('limit', String(params.limit))
|
||||
if (params.cursor) url.searchParams.set('cursor', params.cursor)
|
||||
if (params.orderDir) url.searchParams.set('order_dir', params.orderDir)
|
||||
if (params.promptType) {
|
||||
for (const pt of params.promptType.split(',').map((s) => s.trim())) {
|
||||
url.searchParams.append('prompt_type', pt)
|
||||
}
|
||||
}
|
||||
if (params.topicId) {
|
||||
for (const tid of params.topicId.split(',').map((s) => s.trim())) {
|
||||
url.searchParams.append('topic_id', tid)
|
||||
}
|
||||
}
|
||||
if (params.tagId) {
|
||||
for (const tid of params.tagId.split(',').map((s) => s.trim())) {
|
||||
url.searchParams.append('tag_id', tid)
|
||||
}
|
||||
}
|
||||
if (params.regionId) {
|
||||
for (const rid of params.regionId.split(',').map((s) => s.trim())) {
|
||||
url.searchParams.append('region_id', rid)
|
||||
}
|
||||
}
|
||||
if (params.platformId) {
|
||||
for (const pid of params.platformId.split(',').map((s) => s.trim())) {
|
||||
url.searchParams.append('platform_id', pid)
|
||||
}
|
||||
}
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to list category prompts')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.info?.total_rows ?? 0,
|
||||
nextCursor: data.info?.next_cursor ?? null,
|
||||
prompts: (data.data ?? []).map(
|
||||
(item: {
|
||||
id: string
|
||||
prompt: string
|
||||
prompt_type: string
|
||||
topic: { id: string; name: string }
|
||||
tags: Array<{ id: string; name: string }>
|
||||
regions: Array<{ id: string; name: string }>
|
||||
platforms: Array<{ id: string; name: string }>
|
||||
created_at: string
|
||||
}) => ({
|
||||
id: item.id ?? null,
|
||||
prompt: item.prompt ?? null,
|
||||
promptType: item.prompt_type ?? null,
|
||||
topicId: item.topic?.id ?? null,
|
||||
topicName: item.topic?.name ?? null,
|
||||
tags: (item.tags ?? []).map((t: { id: string; name: string }) => ({
|
||||
id: t.id ?? null,
|
||||
name: t.name ?? null,
|
||||
})),
|
||||
regions: (item.regions ?? []).map((r: { id: string; name: string }) => ({
|
||||
id: r.id ?? null,
|
||||
name: r.name ?? null,
|
||||
})),
|
||||
platforms: (item.platforms ?? []).map((p: { id: string; name: string }) => ({
|
||||
id: p.id ?? null,
|
||||
name: p.name ?? null,
|
||||
})),
|
||||
createdAt: item.created_at ?? null,
|
||||
})
|
||||
),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
totalRows: {
|
||||
type: 'number',
|
||||
description: 'Total number of prompts',
|
||||
},
|
||||
nextCursor: {
|
||||
type: 'string',
|
||||
description: 'Cursor for next page of results',
|
||||
optional: true,
|
||||
},
|
||||
prompts: {
|
||||
type: 'json',
|
||||
description: 'List of prompts',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Prompt ID' },
|
||||
prompt: { type: 'string', description: 'Prompt text' },
|
||||
promptType: { type: 'string', description: 'Prompt type (visibility or sentiment)' },
|
||||
topicId: { type: 'string', description: 'Topic ID' },
|
||||
topicName: { type: 'string', description: 'Topic name' },
|
||||
tags: { type: 'json', description: 'Associated tags' },
|
||||
regions: { type: 'json', description: 'Associated regions' },
|
||||
platforms: { type: 'json', description: 'Associated platforms' },
|
||||
createdAt: { type: 'string', description: 'When the prompt was created' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
64
apps/sim/tools/profound/category_tags.ts
Normal file
64
apps/sim/tools/profound/category_tags.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundCategoryTagsParams, ProfoundCategoryTagsResponse } from './types'
|
||||
|
||||
export const profoundCategoryTagsTool: ToolConfig<
|
||||
ProfoundCategoryTagsParams,
|
||||
ProfoundCategoryTagsResponse
|
||||
> = {
|
||||
id: 'profound_category_tags',
|
||||
name: 'Profound Category Tags',
|
||||
description: 'List tags for a specific category in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
categoryId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Category ID (UUID)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://api.tryprofound.com/v1/org/categories/${encodeURIComponent(params.categoryId)}/tags`,
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to list category tags')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
tags: (data ?? []).map((item: { id: string; name: string }) => ({
|
||||
id: item.id ?? null,
|
||||
name: item.name ?? null,
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
tags: {
|
||||
type: 'json',
|
||||
description: 'List of tags in the category',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Tag ID (UUID)' },
|
||||
name: { type: 'string', description: 'Tag name' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
64
apps/sim/tools/profound/category_topics.ts
Normal file
64
apps/sim/tools/profound/category_topics.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundCategoryTopicsParams, ProfoundCategoryTopicsResponse } from './types'
|
||||
|
||||
export const profoundCategoryTopicsTool: ToolConfig<
|
||||
ProfoundCategoryTopicsParams,
|
||||
ProfoundCategoryTopicsResponse
|
||||
> = {
|
||||
id: 'profound_category_topics',
|
||||
name: 'Profound Category Topics',
|
||||
description: 'List topics for a specific category in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
categoryId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Category ID (UUID)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://api.tryprofound.com/v1/org/categories/${encodeURIComponent(params.categoryId)}/topics`,
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to list category topics')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
topics: (data ?? []).map((item: { id: string; name: string }) => ({
|
||||
id: item.id ?? null,
|
||||
name: item.name ?? null,
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
topics: {
|
||||
type: 'json',
|
||||
description: 'List of topics in the category',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Topic ID (UUID)' },
|
||||
name: { type: 'string', description: 'Topic name' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
60
apps/sim/tools/profound/citation_prompts.ts
Normal file
60
apps/sim/tools/profound/citation_prompts.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundCitationPromptsParams, ProfoundCitationPromptsResponse } from './types'
|
||||
|
||||
export const profoundCitationPromptsTool: ToolConfig<
|
||||
ProfoundCitationPromptsParams,
|
||||
ProfoundCitationPromptsResponse
|
||||
> = {
|
||||
id: 'profound_citation_prompts',
|
||||
name: 'Profound Citation Prompts',
|
||||
description: 'Get prompts that cite a specific domain across AI platforms in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
inputDomain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Domain to look up citations for (e.g. ramp.com)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL('https://api.tryprofound.com/v1/prompt-volumes/citation-prompts')
|
||||
url.searchParams.set('input_domain', params.inputDomain)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to get citation prompts')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
data: data ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
data: {
|
||||
type: 'json',
|
||||
description: 'Citation prompt data for the queried domain',
|
||||
},
|
||||
},
|
||||
}
|
||||
144
apps/sim/tools/profound/citations_report.ts
Normal file
144
apps/sim/tools/profound/citations_report.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundCitationsReportParams, ProfoundCitationsReportResponse } from './types'
|
||||
|
||||
export const profoundCitationsReportTool: ToolConfig<
|
||||
ProfoundCitationsReportParams,
|
||||
ProfoundCitationsReportResponse
|
||||
> = {
|
||||
id: 'profound_citations_report',
|
||||
name: 'Profound Citations Report',
|
||||
description: 'Query citations report for a category in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
categoryId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Category ID (UUID)',
|
||||
},
|
||||
startDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'End date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
metrics: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated metrics: count, citation_share',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated dimensions: hostname, path, date, region, topic, model, tag, prompt, url, root_domain, persona, citation_category',
|
||||
},
|
||||
dateInterval: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Date interval: hour, day, week, month, year',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of filter objects, e.g. [{"field":"hostname","operator":"is","value":"example.com"}]',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results (default 10000, max 50000)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/reports/citations',
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
category_id: params.categoryId,
|
||||
start_date: params.startDate,
|
||||
end_date: params.endDate,
|
||||
metrics: params.metrics.split(',').map((m) => m.trim()),
|
||||
}
|
||||
if (params.dimensions) {
|
||||
body.dimensions = params.dimensions.split(',').map((d) => d.trim())
|
||||
}
|
||||
if (params.dateInterval) {
|
||||
body.date_interval = params.dateInterval
|
||||
}
|
||||
if (params.filters) {
|
||||
try {
|
||||
body.filters = JSON.parse(params.filters)
|
||||
} catch {
|
||||
throw new Error('Invalid JSON in filters parameter')
|
||||
}
|
||||
}
|
||||
if (params.limit != null) {
|
||||
body.pagination = { limit: params.limit }
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to query citations report')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.info?.total_rows ?? 0,
|
||||
data: (data.data ?? []).map((row: { metrics: number[]; dimensions: string[] }) => ({
|
||||
metrics: row.metrics ?? [],
|
||||
dimensions: row.dimensions ?? [],
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
totalRows: {
|
||||
type: 'number',
|
||||
description: 'Total number of rows in the report',
|
||||
},
|
||||
data: {
|
||||
type: 'json',
|
||||
description: 'Report data rows with metrics and dimension values',
|
||||
properties: {
|
||||
metrics: {
|
||||
type: 'json',
|
||||
description: 'Array of metric values matching requested metrics order',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'json',
|
||||
description: 'Array of dimension values matching requested dimensions order',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
24
apps/sim/tools/profound/index.ts
Normal file
24
apps/sim/tools/profound/index.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
export { profoundBotLogsTool } from './bot_logs'
|
||||
export { profoundBotsReportTool } from './bots_report'
|
||||
export { profoundCategoryAssetsTool } from './category_assets'
|
||||
export { profoundCategoryPersonasTool } from './category_personas'
|
||||
export { profoundCategoryPromptsTool } from './category_prompts'
|
||||
export { profoundCategoryTagsTool } from './category_tags'
|
||||
export { profoundCategoryTopicsTool } from './category_topics'
|
||||
export { profoundCitationPromptsTool } from './citation_prompts'
|
||||
export { profoundCitationsReportTool } from './citations_report'
|
||||
export { profoundListAssetsTool } from './list_assets'
|
||||
export { profoundListCategoriesTool } from './list_categories'
|
||||
export { profoundListDomainsTool } from './list_domains'
|
||||
export { profoundListModelsTool } from './list_models'
|
||||
export { profoundListOptimizationsTool } from './list_optimizations'
|
||||
export { profoundListPersonasTool } from './list_personas'
|
||||
export { profoundListRegionsTool } from './list_regions'
|
||||
export { profoundOptimizationAnalysisTool } from './optimization_analysis'
|
||||
export { profoundPromptAnswersTool } from './prompt_answers'
|
||||
export { profoundPromptVolumeTool } from './prompt_volume'
|
||||
export { profoundQueryFanoutsTool } from './query_fanouts'
|
||||
export { profoundRawLogsTool } from './raw_logs'
|
||||
export { profoundReferralsReportTool } from './referrals_report'
|
||||
export { profoundSentimentReportTool } from './sentiment_report'
|
||||
export { profoundVisibilityReportTool } from './visibility_report'
|
||||
85
apps/sim/tools/profound/list_assets.ts
Normal file
85
apps/sim/tools/profound/list_assets.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundListAssetsParams, ProfoundListAssetsResponse } from './types'
|
||||
|
||||
export const profoundListAssetsTool: ToolConfig<
|
||||
ProfoundListAssetsParams,
|
||||
ProfoundListAssetsResponse
|
||||
> = {
|
||||
id: 'profound_list_assets',
|
||||
name: 'Profound List Assets',
|
||||
description: 'List all organization assets (companies/brands) across all categories in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/org/assets',
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to list assets')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
assets: (data.data ?? []).map(
|
||||
(item: {
|
||||
id: string
|
||||
name: string
|
||||
website: string
|
||||
alternate_domains: string[] | null
|
||||
is_owned: boolean
|
||||
created_at: string
|
||||
logo_url: string
|
||||
category: { id: string; name: string }
|
||||
}) => ({
|
||||
id: item.id ?? null,
|
||||
name: item.name ?? null,
|
||||
website: item.website ?? null,
|
||||
alternateDomains: item.alternate_domains ?? null,
|
||||
isOwned: item.is_owned ?? false,
|
||||
createdAt: item.created_at ?? null,
|
||||
logoUrl: item.logo_url ?? null,
|
||||
categoryId: item.category?.id ?? null,
|
||||
categoryName: item.category?.name ?? null,
|
||||
})
|
||||
),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
assets: {
|
||||
type: 'json',
|
||||
description: 'List of organization assets with category info',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Asset ID' },
|
||||
name: { type: 'string', description: 'Asset/company name' },
|
||||
website: { type: 'string', description: 'Asset website URL' },
|
||||
alternateDomains: { type: 'json', description: 'Alternate domain names' },
|
||||
isOwned: {
|
||||
type: 'boolean',
|
||||
description: 'Whether this asset is owned by the organization',
|
||||
},
|
||||
createdAt: { type: 'string', description: 'When the asset was created' },
|
||||
logoUrl: { type: 'string', description: 'URL of the asset logo' },
|
||||
categoryId: { type: 'string', description: 'Category ID the asset belongs to' },
|
||||
categoryName: { type: 'string', description: 'Category name' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
57
apps/sim/tools/profound/list_categories.ts
Normal file
57
apps/sim/tools/profound/list_categories.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundListCategoriesParams, ProfoundListCategoriesResponse } from './types'
|
||||
|
||||
export const profoundListCategoriesTool: ToolConfig<
|
||||
ProfoundListCategoriesParams,
|
||||
ProfoundListCategoriesResponse
|
||||
> = {
|
||||
id: 'profound_list_categories',
|
||||
name: 'Profound List Categories',
|
||||
description: 'List all organization categories in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/org/categories',
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to list categories')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
categories: (data ?? []).map((item: { id: string; name: string }) => ({
|
||||
id: item.id ?? null,
|
||||
name: item.name ?? null,
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
categories: {
|
||||
type: 'json',
|
||||
description: 'List of organization categories',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Category ID' },
|
||||
name: { type: 'string', description: 'Category name' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
59
apps/sim/tools/profound/list_domains.ts
Normal file
59
apps/sim/tools/profound/list_domains.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundListDomainsParams, ProfoundListDomainsResponse } from './types'
|
||||
|
||||
export const profoundListDomainsTool: ToolConfig<
|
||||
ProfoundListDomainsParams,
|
||||
ProfoundListDomainsResponse
|
||||
> = {
|
||||
id: 'profound_list_domains',
|
||||
name: 'Profound List Domains',
|
||||
description: 'List all organization domains in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/org/domains',
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to list domains')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
domains: (data ?? []).map((item: { id: string; name: string; created_at: string }) => ({
|
||||
id: item.id ?? null,
|
||||
name: item.name ?? null,
|
||||
createdAt: item.created_at ?? null,
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
domains: {
|
||||
type: 'json',
|
||||
description: 'List of organization domains',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Domain ID (UUID)' },
|
||||
name: { type: 'string', description: 'Domain name' },
|
||||
createdAt: { type: 'string', description: 'When the domain was added' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
57
apps/sim/tools/profound/list_models.ts
Normal file
57
apps/sim/tools/profound/list_models.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundListModelsParams, ProfoundListModelsResponse } from './types'
|
||||
|
||||
export const profoundListModelsTool: ToolConfig<
|
||||
ProfoundListModelsParams,
|
||||
ProfoundListModelsResponse
|
||||
> = {
|
||||
id: 'profound_list_models',
|
||||
name: 'Profound List Models',
|
||||
description: 'List all AI models/platforms tracked in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/org/models',
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to list models')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
models: (data ?? []).map((item: { id: string; name: string }) => ({
|
||||
id: item.id ?? null,
|
||||
name: item.name ?? null,
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
models: {
|
||||
type: 'json',
|
||||
description: 'List of AI models/platforms',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Model ID (UUID)' },
|
||||
name: { type: 'string', description: 'Model/platform name' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
104
apps/sim/tools/profound/list_optimizations.ts
Normal file
104
apps/sim/tools/profound/list_optimizations.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundListOptimizationsParams, ProfoundListOptimizationsResponse } from './types'
|
||||
|
||||
export const profoundListOptimizationsTool: ToolConfig<
|
||||
ProfoundListOptimizationsParams,
|
||||
ProfoundListOptimizationsResponse
|
||||
> = {
|
||||
id: 'profound_list_optimizations',
|
||||
name: 'Profound List Optimizations',
|
||||
description: 'List content optimization entries for an asset in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
assetId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Asset ID (UUID)',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results (default 10000, max 50000)',
|
||||
},
|
||||
offset: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Offset for pagination (default 0)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(
|
||||
`https://api.tryprofound.com/v1/content/${encodeURIComponent(params.assetId)}/optimization`
|
||||
)
|
||||
if (params.limit != null) url.searchParams.set('limit', String(params.limit))
|
||||
if (params.offset != null) url.searchParams.set('offset', String(params.offset))
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to list optimizations')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.info?.total_rows ?? 0,
|
||||
optimizations: (data.data ?? []).map(
|
||||
(item: {
|
||||
id: string
|
||||
title: string
|
||||
created_at: string
|
||||
extracted_input: string | null
|
||||
type: string
|
||||
status: string
|
||||
}) => ({
|
||||
id: item.id ?? null,
|
||||
title: item.title ?? null,
|
||||
createdAt: item.created_at ?? null,
|
||||
extractedInput: item.extracted_input ?? null,
|
||||
type: item.type ?? null,
|
||||
status: item.status ?? null,
|
||||
})
|
||||
),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
totalRows: {
|
||||
type: 'number',
|
||||
description: 'Total number of optimization entries',
|
||||
},
|
||||
optimizations: {
|
||||
type: 'json',
|
||||
description: 'List of content optimization entries',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Optimization ID (UUID)' },
|
||||
title: { type: 'string', description: 'Content title' },
|
||||
createdAt: { type: 'string', description: 'When the optimization was created' },
|
||||
extractedInput: { type: 'string', description: 'Extracted input text' },
|
||||
type: { type: 'string', description: 'Content type: file, text, or url' },
|
||||
status: { type: 'string', description: 'Optimization status' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
96
apps/sim/tools/profound/list_personas.ts
Normal file
96
apps/sim/tools/profound/list_personas.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundListPersonasParams, ProfoundListPersonasResponse } from './types'
|
||||
|
||||
export const profoundListPersonasTool: ToolConfig<
|
||||
ProfoundListPersonasParams,
|
||||
ProfoundListPersonasResponse
|
||||
> = {
|
||||
id: 'profound_list_personas',
|
||||
name: 'Profound List Personas',
|
||||
description: 'List all organization personas across all categories in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/org/personas',
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to list personas')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
personas: (data.data ?? []).map(
|
||||
(item: {
|
||||
id: string
|
||||
name: string
|
||||
category: { id: string; name: string }
|
||||
persona: {
|
||||
behavior: { painPoints: string | null; motivations: string | null }
|
||||
employment: {
|
||||
industry: string[]
|
||||
jobTitle: string[]
|
||||
companySize: string[]
|
||||
roleSeniority: string[]
|
||||
}
|
||||
demographics: { ageRange: string[] }
|
||||
}
|
||||
}) => ({
|
||||
id: item.id ?? null,
|
||||
name: item.name ?? null,
|
||||
categoryId: item.category?.id ?? null,
|
||||
categoryName: item.category?.name ?? null,
|
||||
persona: {
|
||||
behavior: {
|
||||
painPoints: item.persona?.behavior?.painPoints ?? null,
|
||||
motivations: item.persona?.behavior?.motivations ?? null,
|
||||
},
|
||||
employment: {
|
||||
industry: item.persona?.employment?.industry ?? [],
|
||||
jobTitle: item.persona?.employment?.jobTitle ?? [],
|
||||
companySize: item.persona?.employment?.companySize ?? [],
|
||||
roleSeniority: item.persona?.employment?.roleSeniority ?? [],
|
||||
},
|
||||
demographics: {
|
||||
ageRange: item.persona?.demographics?.ageRange ?? [],
|
||||
},
|
||||
},
|
||||
})
|
||||
),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
personas: {
|
||||
type: 'json',
|
||||
description: 'List of organization personas with profile details',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Persona ID' },
|
||||
name: { type: 'string', description: 'Persona name' },
|
||||
categoryId: { type: 'string', description: 'Category ID' },
|
||||
categoryName: { type: 'string', description: 'Category name' },
|
||||
persona: {
|
||||
type: 'json',
|
||||
description: 'Persona profile with behavior, employment, and demographics',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
57
apps/sim/tools/profound/list_regions.ts
Normal file
57
apps/sim/tools/profound/list_regions.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundListRegionsParams, ProfoundListRegionsResponse } from './types'
|
||||
|
||||
export const profoundListRegionsTool: ToolConfig<
|
||||
ProfoundListRegionsParams,
|
||||
ProfoundListRegionsResponse
|
||||
> = {
|
||||
id: 'profound_list_regions',
|
||||
name: 'Profound List Regions',
|
||||
description: 'List all organization regions in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/org/regions',
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to list regions')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
regions: (data ?? []).map((item: { id: string; name: string }) => ({
|
||||
id: item.id ?? null,
|
||||
name: item.name ?? null,
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
regions: {
|
||||
type: 'json',
|
||||
description: 'List of organization regions',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Region ID (UUID)' },
|
||||
name: { type: 'string', description: 'Region name' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
161
apps/sim/tools/profound/optimization_analysis.ts
Normal file
161
apps/sim/tools/profound/optimization_analysis.ts
Normal file
@@ -0,0 +1,161 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
ProfoundOptimizationAnalysisParams,
|
||||
ProfoundOptimizationAnalysisResponse,
|
||||
} from './types'
|
||||
|
||||
export const profoundOptimizationAnalysisTool: ToolConfig<
|
||||
ProfoundOptimizationAnalysisParams,
|
||||
ProfoundOptimizationAnalysisResponse
|
||||
> = {
|
||||
id: 'profound_optimization_analysis',
|
||||
name: 'Profound Optimization Analysis',
|
||||
description: 'Get detailed content optimization analysis for a specific content item in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
assetId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Asset ID (UUID)',
|
||||
},
|
||||
contentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Content/optimization ID (UUID)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://api.tryprofound.com/v1/content/${encodeURIComponent(params.assetId)}/optimization/${encodeURIComponent(params.contentId)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to get optimization analysis')
|
||||
}
|
||||
const analysis = data.data
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content: {
|
||||
format: analysis?.content?.format ?? null,
|
||||
value: analysis?.content?.value ?? null,
|
||||
},
|
||||
aeoContentScore: analysis?.aeo_content_score
|
||||
? {
|
||||
value: analysis.aeo_content_score.value ?? 0,
|
||||
targetZone: {
|
||||
low: analysis.aeo_content_score.target_zone?.low ?? 0,
|
||||
high: analysis.aeo_content_score.target_zone?.high ?? 0,
|
||||
},
|
||||
}
|
||||
: null,
|
||||
analysis: {
|
||||
breakdown: (analysis?.analysis?.breakdown ?? []).map(
|
||||
(b: { title: string; weight: number; score: number }) => ({
|
||||
title: b.title ?? null,
|
||||
weight: b.weight ?? 0,
|
||||
score: b.score ?? 0,
|
||||
})
|
||||
),
|
||||
},
|
||||
recommendations: (analysis?.recommendations ?? []).map(
|
||||
(r: {
|
||||
title: string
|
||||
status: string
|
||||
impact: { section: string; score: number } | null
|
||||
suggestion: { text: string; rationale: string }
|
||||
}) => ({
|
||||
title: r.title ?? null,
|
||||
status: r.status ?? null,
|
||||
impact: r.impact
|
||||
? {
|
||||
section: r.impact.section ?? null,
|
||||
score: r.impact.score ?? 0,
|
||||
}
|
||||
: null,
|
||||
suggestion: {
|
||||
text: r.suggestion?.text ?? null,
|
||||
rationale: r.suggestion?.rationale ?? null,
|
||||
},
|
||||
})
|
||||
),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: {
|
||||
type: 'json',
|
||||
description: 'The analyzed content',
|
||||
properties: {
|
||||
format: { type: 'string', description: 'Content format: markdown or html' },
|
||||
value: { type: 'string', description: 'Content text' },
|
||||
},
|
||||
},
|
||||
aeoContentScore: {
|
||||
type: 'json',
|
||||
description: 'AEO content score with target zone',
|
||||
optional: true,
|
||||
properties: {
|
||||
value: { type: 'number', description: 'AEO score value' },
|
||||
targetZone: {
|
||||
type: 'json',
|
||||
description: 'Target zone range',
|
||||
properties: {
|
||||
low: { type: 'number', description: 'Low end of target range' },
|
||||
high: { type: 'number', description: 'High end of target range' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
analysis: {
|
||||
type: 'json',
|
||||
description: 'Analysis breakdown by category',
|
||||
properties: {
|
||||
breakdown: {
|
||||
type: 'json',
|
||||
description: 'Array of scoring breakdowns',
|
||||
properties: {
|
||||
title: { type: 'string', description: 'Category title' },
|
||||
weight: { type: 'number', description: 'Category weight' },
|
||||
score: { type: 'number', description: 'Category score' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recommendations: {
|
||||
type: 'json',
|
||||
description: 'Content optimization recommendations',
|
||||
properties: {
|
||||
title: { type: 'string', description: 'Recommendation title' },
|
||||
status: { type: 'string', description: 'Status: done or pending' },
|
||||
impact: { type: 'json', description: 'Impact details with section and score' },
|
||||
suggestion: {
|
||||
type: 'json',
|
||||
description: 'Suggestion text and rationale',
|
||||
properties: {
|
||||
text: { type: 'string', description: 'Suggestion text' },
|
||||
rationale: { type: 'string', description: 'Why this recommendation matters' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
141
apps/sim/tools/profound/prompt_answers.ts
Normal file
141
apps/sim/tools/profound/prompt_answers.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundPromptAnswersParams, ProfoundPromptAnswersResponse } from './types'
|
||||
|
||||
export const profoundPromptAnswersTool: ToolConfig<
|
||||
ProfoundPromptAnswersParams,
|
||||
ProfoundPromptAnswersResponse
|
||||
> = {
|
||||
id: 'profound_prompt_answers',
|
||||
name: 'Profound Prompt Answers',
|
||||
description: 'Get raw prompt answers data for a category in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
categoryId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Category ID (UUID)',
|
||||
},
|
||||
startDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'End date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of filter objects, e.g. [{"field":"prompt_type","operator":"is","value":"visibility"}]',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results (default 10000, max 50000)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/prompts/answers',
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
category_id: params.categoryId,
|
||||
start_date: params.startDate,
|
||||
end_date: params.endDate,
|
||||
}
|
||||
if (params.filters) {
|
||||
try {
|
||||
body.filters = JSON.parse(params.filters)
|
||||
} catch {
|
||||
throw new Error('Invalid JSON in filters parameter')
|
||||
}
|
||||
}
|
||||
if (params.limit != null) {
|
||||
body.pagination = { limit: params.limit }
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to get prompt answers')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.info?.total_rows ?? 0,
|
||||
data: (data.data ?? []).map(
|
||||
(row: {
|
||||
prompt: string | null
|
||||
prompt_type: string | null
|
||||
response: string | null
|
||||
mentions: string[] | null
|
||||
citations: string[] | null
|
||||
topic: string | null
|
||||
region: string | null
|
||||
model: string | null
|
||||
asset: string | null
|
||||
created_at: string | null
|
||||
}) => ({
|
||||
prompt: row.prompt ?? null,
|
||||
promptType: row.prompt_type ?? null,
|
||||
response: row.response ?? null,
|
||||
mentions: row.mentions ?? [],
|
||||
citations: row.citations ?? [],
|
||||
topic: row.topic ?? null,
|
||||
region: row.region ?? null,
|
||||
model: row.model ?? null,
|
||||
asset: row.asset ?? null,
|
||||
createdAt: row.created_at ?? null,
|
||||
})
|
||||
),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
totalRows: {
|
||||
type: 'number',
|
||||
description: 'Total number of answer rows',
|
||||
},
|
||||
data: {
|
||||
type: 'json',
|
||||
description: 'Raw prompt answer data',
|
||||
properties: {
|
||||
prompt: { type: 'string', description: 'The prompt text' },
|
||||
promptType: { type: 'string', description: 'Prompt type (visibility or sentiment)' },
|
||||
response: { type: 'string', description: 'AI model response text' },
|
||||
mentions: { type: 'json', description: 'Companies/assets mentioned in the response' },
|
||||
citations: { type: 'json', description: 'URLs cited in the response' },
|
||||
topic: { type: 'string', description: 'Topic name' },
|
||||
region: { type: 'string', description: 'Region name' },
|
||||
model: { type: 'string', description: 'AI model/platform name' },
|
||||
asset: { type: 'string', description: 'Asset name' },
|
||||
createdAt: { type: 'string', description: 'Timestamp when the answer was collected' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
138
apps/sim/tools/profound/prompt_volume.ts
Normal file
138
apps/sim/tools/profound/prompt_volume.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundPromptVolumeParams, ProfoundPromptVolumeResponse } from './types'
|
||||
|
||||
export const profoundPromptVolumeTool: ToolConfig<
|
||||
ProfoundPromptVolumeParams,
|
||||
ProfoundPromptVolumeResponse
|
||||
> = {
|
||||
id: 'profound_prompt_volume',
|
||||
name: 'Profound Prompt Volume',
|
||||
description:
|
||||
'Query prompt volume data to understand search demand across AI platforms in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
startDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'End date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
metrics: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated metrics: volume, change',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated dimensions: keyword, date, platform, country_code, matching_type, frequency',
|
||||
},
|
||||
dateInterval: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Date interval: hour, day, week, month, year',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of filter objects, e.g. [{"field":"keyword","operator":"contains","value":"best"}]',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results (default 10000, max 50000)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/prompt-volumes/volume',
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
start_date: params.startDate,
|
||||
end_date: params.endDate,
|
||||
metrics: params.metrics.split(',').map((m) => m.trim()),
|
||||
}
|
||||
if (params.dimensions) {
|
||||
body.dimensions = params.dimensions.split(',').map((d) => d.trim())
|
||||
}
|
||||
if (params.dateInterval) {
|
||||
body.date_interval = params.dateInterval
|
||||
}
|
||||
if (params.filters) {
|
||||
try {
|
||||
body.filters = JSON.parse(params.filters)
|
||||
} catch {
|
||||
throw new Error('Invalid JSON in filters parameter')
|
||||
}
|
||||
}
|
||||
if (params.limit != null) {
|
||||
body.pagination = { limit: params.limit }
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to query prompt volume')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.info?.total_rows ?? 0,
|
||||
data: (data.data ?? []).map((row: { metrics: number[]; dimensions: string[] }) => ({
|
||||
metrics: row.metrics ?? [],
|
||||
dimensions: row.dimensions ?? [],
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
totalRows: {
|
||||
type: 'number',
|
||||
description: 'Total number of rows in the report',
|
||||
},
|
||||
data: {
|
||||
type: 'json',
|
||||
description: 'Volume data rows with metrics and dimension values',
|
||||
properties: {
|
||||
metrics: {
|
||||
type: 'json',
|
||||
description: 'Array of metric values matching requested metrics order',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'json',
|
||||
description: 'Array of dimension values matching requested dimensions order',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
143
apps/sim/tools/profound/query_fanouts.ts
Normal file
143
apps/sim/tools/profound/query_fanouts.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundQueryFanoutsParams, ProfoundQueryFanoutsResponse } from './types'
|
||||
|
||||
export const profoundQueryFanoutsTool: ToolConfig<
|
||||
ProfoundQueryFanoutsParams,
|
||||
ProfoundQueryFanoutsResponse
|
||||
> = {
|
||||
id: 'profound_query_fanouts',
|
||||
name: 'Profound Query Fanouts',
|
||||
description:
|
||||
'Query fanout report showing how AI models expand prompts into sub-queries in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
categoryId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Category ID (UUID)',
|
||||
},
|
||||
startDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'End date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
metrics: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated metrics: fanouts_per_execution, total_fanouts, share',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated dimensions: prompt, query, model, region, date',
|
||||
},
|
||||
dateInterval: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Date interval: hour, day, week, month, year',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'JSON array of filter objects',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results (default 10000, max 50000)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/reports/query-fanouts',
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
category_id: params.categoryId,
|
||||
start_date: params.startDate,
|
||||
end_date: params.endDate,
|
||||
metrics: params.metrics.split(',').map((m) => m.trim()),
|
||||
}
|
||||
if (params.dimensions) {
|
||||
body.dimensions = params.dimensions.split(',').map((d) => d.trim())
|
||||
}
|
||||
if (params.dateInterval) {
|
||||
body.date_interval = params.dateInterval
|
||||
}
|
||||
if (params.filters) {
|
||||
try {
|
||||
body.filters = JSON.parse(params.filters)
|
||||
} catch {
|
||||
throw new Error('Invalid JSON in filters parameter')
|
||||
}
|
||||
}
|
||||
if (params.limit != null) {
|
||||
body.pagination = { limit: params.limit }
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to query fanouts report')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.info?.total_rows ?? 0,
|
||||
data: (data.data ?? []).map((row: { metrics: number[]; dimensions: string[] }) => ({
|
||||
metrics: row.metrics ?? [],
|
||||
dimensions: row.dimensions ?? [],
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
totalRows: {
|
||||
type: 'number',
|
||||
description: 'Total number of rows in the report',
|
||||
},
|
||||
data: {
|
||||
type: 'json',
|
||||
description: 'Report data rows with metrics and dimension values',
|
||||
properties: {
|
||||
metrics: {
|
||||
type: 'json',
|
||||
description: 'Array of metric values matching requested metrics order',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'json',
|
||||
description: 'Array of dimension values matching requested dimensions order',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
137
apps/sim/tools/profound/raw_logs.ts
Normal file
137
apps/sim/tools/profound/raw_logs.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundRawLogsParams, ProfoundRawLogsResponse } from './types'
|
||||
|
||||
export const profoundRawLogsTool: ToolConfig<ProfoundRawLogsParams, ProfoundRawLogsResponse> = {
|
||||
id: 'profound_raw_logs',
|
||||
name: 'Profound Raw Logs',
|
||||
description: 'Get raw traffic logs with filters for a domain in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Domain to query logs for (e.g. example.com)',
|
||||
},
|
||||
startDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'End date (YYYY-MM-DD or ISO 8601). Defaults to now',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated dimensions: timestamp, method, host, path, status_code, ip, user_agent, referer, bytes_sent, duration_ms, query_params',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of filter objects, e.g. [{"field":"path","operator":"contains","value":"/blog"}]',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results (default 10000, max 50000)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/logs/raw',
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
domain: params.domain,
|
||||
start_date: params.startDate,
|
||||
metrics: ['count'],
|
||||
}
|
||||
if (params.endDate) {
|
||||
body.end_date = params.endDate
|
||||
}
|
||||
if (params.dimensions) {
|
||||
body.dimensions = params.dimensions.split(',').map((d) => d.trim())
|
||||
}
|
||||
if (params.filters) {
|
||||
try {
|
||||
body.filters = JSON.parse(params.filters)
|
||||
} catch {
|
||||
throw new Error('Invalid JSON in filters parameter')
|
||||
}
|
||||
}
|
||||
if (params.limit != null) {
|
||||
body.pagination = { limit: params.limit }
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to get raw logs')
|
||||
}
|
||||
if (Array.isArray(data)) {
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.length,
|
||||
data: data.map((row: { metrics: number[]; dimensions: string[] }) => ({
|
||||
metrics: row.metrics ?? [],
|
||||
dimensions: row.dimensions ?? [],
|
||||
})),
|
||||
},
|
||||
}
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.info?.total_rows ?? 0,
|
||||
data: (data.data ?? []).map((row: { metrics: number[]; dimensions: string[] }) => ({
|
||||
metrics: row.metrics ?? [],
|
||||
dimensions: row.dimensions ?? [],
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
totalRows: {
|
||||
type: 'number',
|
||||
description: 'Total number of log entries',
|
||||
},
|
||||
data: {
|
||||
type: 'json',
|
||||
description: 'Log data rows with metrics and dimension values',
|
||||
properties: {
|
||||
metrics: { type: 'json', description: 'Array of metric values (count)' },
|
||||
dimensions: {
|
||||
type: 'json',
|
||||
description: 'Array of dimension values matching requested dimensions order',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
146
apps/sim/tools/profound/referrals_report.ts
Normal file
146
apps/sim/tools/profound/referrals_report.ts
Normal file
@@ -0,0 +1,146 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundReferralsReportParams, ProfoundReferralsReportResponse } from './types'
|
||||
|
||||
export const profoundReferralsReportTool: ToolConfig<
|
||||
ProfoundReferralsReportParams,
|
||||
ProfoundReferralsReportResponse
|
||||
> = {
|
||||
id: 'profound_referrals_report',
|
||||
name: 'Profound Referrals Report',
|
||||
description:
|
||||
'Query human referral traffic report with hourly granularity for a domain in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Domain to query referral traffic for (e.g. example.com)',
|
||||
},
|
||||
startDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'End date (YYYY-MM-DD or ISO 8601). Defaults to now',
|
||||
},
|
||||
metrics: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated metrics: visits, last_visit',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated dimensions: date, hour, path, referral_source, referral_type',
|
||||
},
|
||||
dateInterval: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Date interval: hour, day, week, month, year',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of filter objects, e.g. [{"field":"referral_source","operator":"is","value":"openai"}]',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results (default 10000, max 50000)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v2/reports/referrals',
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
domain: params.domain,
|
||||
start_date: params.startDate,
|
||||
metrics: params.metrics.split(',').map((m) => m.trim()),
|
||||
}
|
||||
if (params.endDate) {
|
||||
body.end_date = params.endDate
|
||||
}
|
||||
if (params.dimensions) {
|
||||
body.dimensions = params.dimensions.split(',').map((d) => d.trim())
|
||||
}
|
||||
if (params.dateInterval) {
|
||||
body.date_interval = params.dateInterval
|
||||
}
|
||||
if (params.filters) {
|
||||
try {
|
||||
body.filters = JSON.parse(params.filters)
|
||||
} catch {
|
||||
throw new Error('Invalid JSON in filters parameter')
|
||||
}
|
||||
}
|
||||
if (params.limit != null) {
|
||||
body.pagination = { limit: params.limit }
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to query referrals report')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.info?.total_rows ?? 0,
|
||||
data: (data.data ?? []).map((row: { metrics: number[]; dimensions: string[] }) => ({
|
||||
metrics: row.metrics ?? [],
|
||||
dimensions: row.dimensions ?? [],
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
totalRows: {
|
||||
type: 'number',
|
||||
description: 'Total number of rows in the report',
|
||||
},
|
||||
data: {
|
||||
type: 'json',
|
||||
description: 'Report data rows with metrics and dimension values',
|
||||
properties: {
|
||||
metrics: {
|
||||
type: 'json',
|
||||
description: 'Array of metric values matching requested metrics order',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'json',
|
||||
description: 'Array of dimension values matching requested dimensions order',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
144
apps/sim/tools/profound/sentiment_report.ts
Normal file
144
apps/sim/tools/profound/sentiment_report.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundSentimentReportParams, ProfoundSentimentReportResponse } from './types'
|
||||
|
||||
export const profoundSentimentReportTool: ToolConfig<
|
||||
ProfoundSentimentReportParams,
|
||||
ProfoundSentimentReportResponse
|
||||
> = {
|
||||
id: 'profound_sentiment_report',
|
||||
name: 'Profound Sentiment Report',
|
||||
description: 'Query sentiment report for a category in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
categoryId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Category ID (UUID)',
|
||||
},
|
||||
startDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'End date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
metrics: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated metrics: positive, negative, occurrences',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated dimensions: theme, date, region, topic, model, asset_name, tag, prompt, sentiment_type, persona',
|
||||
},
|
||||
dateInterval: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Date interval: hour, day, week, month, year',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of filter objects, e.g. [{"field":"asset_name","operator":"is","value":"Company"}]',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results (default 10000, max 50000)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/reports/sentiment',
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
category_id: params.categoryId,
|
||||
start_date: params.startDate,
|
||||
end_date: params.endDate,
|
||||
metrics: params.metrics.split(',').map((m) => m.trim()),
|
||||
}
|
||||
if (params.dimensions) {
|
||||
body.dimensions = params.dimensions.split(',').map((d) => d.trim())
|
||||
}
|
||||
if (params.dateInterval) {
|
||||
body.date_interval = params.dateInterval
|
||||
}
|
||||
if (params.filters) {
|
||||
try {
|
||||
body.filters = JSON.parse(params.filters)
|
||||
} catch {
|
||||
throw new Error('Invalid JSON in filters parameter')
|
||||
}
|
||||
}
|
||||
if (params.limit != null) {
|
||||
body.pagination = { limit: params.limit }
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to query sentiment report')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.info?.total_rows ?? 0,
|
||||
data: (data.data ?? []).map((row: { metrics: number[]; dimensions: string[] }) => ({
|
||||
metrics: row.metrics ?? [],
|
||||
dimensions: row.dimensions ?? [],
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
totalRows: {
|
||||
type: 'number',
|
||||
description: 'Total number of rows in the report',
|
||||
},
|
||||
data: {
|
||||
type: 'json',
|
||||
description: 'Report data rows with metrics and dimension values',
|
||||
properties: {
|
||||
metrics: {
|
||||
type: 'json',
|
||||
description: 'Array of metric values matching requested metrics order',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'json',
|
||||
description: 'Array of dimension values matching requested dimensions order',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
422
apps/sim/tools/profound/types.ts
Normal file
422
apps/sim/tools/profound/types.ts
Normal file
@@ -0,0 +1,422 @@
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
/** Shared report response shape (visibility, sentiment, citations, bots, referrals, query fanouts, prompt volume) */
|
||||
export interface ProfoundReportResponse extends ToolResponse {
|
||||
output: {
|
||||
totalRows: number
|
||||
data: Array<{
|
||||
metrics: number[]
|
||||
dimensions: string[]
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
/** Shared report query params for category-based reports */
|
||||
export interface ProfoundCategoryReportParams {
|
||||
apiKey: string
|
||||
categoryId: string
|
||||
startDate: string
|
||||
endDate: string
|
||||
metrics: string
|
||||
dimensions?: string
|
||||
dateInterval?: string
|
||||
filters?: string
|
||||
limit?: number
|
||||
}
|
||||
|
||||
/** Shared report query params for domain-based reports */
|
||||
export interface ProfoundDomainReportParams {
|
||||
apiKey: string
|
||||
domain: string
|
||||
startDate: string
|
||||
endDate?: string
|
||||
metrics: string
|
||||
dimensions?: string
|
||||
dateInterval?: string
|
||||
filters?: string
|
||||
limit?: number
|
||||
}
|
||||
|
||||
// --- Organization endpoints ---
|
||||
|
||||
export interface ProfoundListCategoriesParams {
|
||||
apiKey: string
|
||||
}
|
||||
|
||||
export interface ProfoundListCategoriesResponse extends ToolResponse {
|
||||
output: {
|
||||
categories: Array<{
|
||||
id: string
|
||||
name: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfoundListRegionsParams {
|
||||
apiKey: string
|
||||
}
|
||||
|
||||
export interface ProfoundListRegionsResponse extends ToolResponse {
|
||||
output: {
|
||||
regions: Array<{
|
||||
id: string
|
||||
name: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfoundListModelsParams {
|
||||
apiKey: string
|
||||
}
|
||||
|
||||
export interface ProfoundListModelsResponse extends ToolResponse {
|
||||
output: {
|
||||
models: Array<{
|
||||
id: string
|
||||
name: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfoundListDomainsParams {
|
||||
apiKey: string
|
||||
}
|
||||
|
||||
export interface ProfoundListDomainsResponse extends ToolResponse {
|
||||
output: {
|
||||
domains: Array<{
|
||||
id: string
|
||||
name: string
|
||||
createdAt: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfoundListAssetsParams {
|
||||
apiKey: string
|
||||
}
|
||||
|
||||
export interface ProfoundListAssetsResponse extends ToolResponse {
|
||||
output: {
|
||||
assets: Array<{
|
||||
id: string
|
||||
name: string
|
||||
website: string
|
||||
alternateDomains: string[] | null
|
||||
isOwned: boolean
|
||||
createdAt: string
|
||||
logoUrl: string
|
||||
categoryId: string
|
||||
categoryName: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfoundListPersonasParams {
|
||||
apiKey: string
|
||||
}
|
||||
|
||||
export interface ProfoundListPersonasResponse extends ToolResponse {
|
||||
output: {
|
||||
personas: Array<{
|
||||
id: string
|
||||
name: string
|
||||
categoryId: string
|
||||
categoryName: string
|
||||
persona: {
|
||||
behavior: { painPoints: string | null; motivations: string | null }
|
||||
employment: {
|
||||
industry: string[]
|
||||
jobTitle: string[]
|
||||
companySize: string[]
|
||||
roleSeniority: string[]
|
||||
}
|
||||
demographics: { ageRange: string[] }
|
||||
}
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
// --- Category-specific endpoints ---
|
||||
|
||||
export interface ProfoundCategoryTopicsParams {
|
||||
apiKey: string
|
||||
categoryId: string
|
||||
}
|
||||
|
||||
export interface ProfoundCategoryTopicsResponse extends ToolResponse {
|
||||
output: {
|
||||
topics: Array<{
|
||||
id: string
|
||||
name: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfoundCategoryTagsParams {
|
||||
apiKey: string
|
||||
categoryId: string
|
||||
}
|
||||
|
||||
export interface ProfoundCategoryTagsResponse extends ToolResponse {
|
||||
output: {
|
||||
tags: Array<{
|
||||
id: string
|
||||
name: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfoundCategoryPromptsParams {
|
||||
apiKey: string
|
||||
categoryId: string
|
||||
limit?: number
|
||||
cursor?: string
|
||||
orderDir?: string
|
||||
promptType?: string
|
||||
topicId?: string
|
||||
tagId?: string
|
||||
regionId?: string
|
||||
platformId?: string
|
||||
}
|
||||
|
||||
export interface ProfoundCategoryPromptsResponse extends ToolResponse {
|
||||
output: {
|
||||
totalRows: number
|
||||
nextCursor: string | null
|
||||
prompts: Array<{
|
||||
id: string
|
||||
prompt: string
|
||||
promptType: string
|
||||
topicId: string
|
||||
topicName: string
|
||||
tags: Array<{ id: string; name: string }>
|
||||
regions: Array<{ id: string; name: string }>
|
||||
platforms: Array<{ id: string; name: string }>
|
||||
createdAt: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfoundCategoryAssetsParams {
|
||||
apiKey: string
|
||||
categoryId: string
|
||||
}
|
||||
|
||||
export interface ProfoundCategoryAssetsResponse extends ToolResponse {
|
||||
output: {
|
||||
assets: Array<{
|
||||
id: string
|
||||
name: string
|
||||
website: string
|
||||
alternateDomains: string[] | null
|
||||
isOwned: boolean
|
||||
createdAt: string
|
||||
logoUrl: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfoundCategoryPersonasParams {
|
||||
apiKey: string
|
||||
categoryId: string
|
||||
}
|
||||
|
||||
export interface ProfoundCategoryPersonasResponse extends ToolResponse {
|
||||
output: {
|
||||
personas: Array<{
|
||||
id: string
|
||||
name: string
|
||||
persona: {
|
||||
behavior: { painPoints: string | null; motivations: string | null }
|
||||
employment: {
|
||||
industry: string[]
|
||||
jobTitle: string[]
|
||||
companySize: string[]
|
||||
roleSeniority: string[]
|
||||
}
|
||||
demographics: { ageRange: string[] }
|
||||
}
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
// --- Reports ---
|
||||
|
||||
export type ProfoundVisibilityReportParams = ProfoundCategoryReportParams
|
||||
export type ProfoundVisibilityReportResponse = ProfoundReportResponse
|
||||
|
||||
export type ProfoundSentimentReportParams = ProfoundCategoryReportParams
|
||||
export type ProfoundSentimentReportResponse = ProfoundReportResponse
|
||||
|
||||
export type ProfoundCitationsReportParams = ProfoundCategoryReportParams
|
||||
export type ProfoundCitationsReportResponse = ProfoundReportResponse
|
||||
|
||||
export type ProfoundQueryFanoutsParams = ProfoundCategoryReportParams
|
||||
export type ProfoundQueryFanoutsResponse = ProfoundReportResponse
|
||||
|
||||
export type ProfoundBotsReportParams = ProfoundDomainReportParams
|
||||
export type ProfoundBotsReportResponse = ProfoundReportResponse
|
||||
|
||||
export type ProfoundReferralsReportParams = ProfoundDomainReportParams
|
||||
export type ProfoundReferralsReportResponse = ProfoundReportResponse
|
||||
|
||||
// --- Prompts ---
|
||||
|
||||
export interface ProfoundPromptAnswersParams {
|
||||
apiKey: string
|
||||
categoryId: string
|
||||
startDate: string
|
||||
endDate: string
|
||||
filters?: string
|
||||
limit?: number
|
||||
}
|
||||
|
||||
export interface ProfoundPromptAnswersResponse extends ToolResponse {
|
||||
output: {
|
||||
totalRows: number
|
||||
data: Array<{
|
||||
prompt: string | null
|
||||
promptType: string | null
|
||||
response: string | null
|
||||
mentions: string[] | null
|
||||
citations: string[] | null
|
||||
topic: string | null
|
||||
region: string | null
|
||||
model: string | null
|
||||
asset: string | null
|
||||
createdAt: string | null
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
// --- Agent Analytics ---
|
||||
|
||||
export interface ProfoundRawLogsParams {
|
||||
apiKey: string
|
||||
domain: string
|
||||
startDate: string
|
||||
endDate?: string
|
||||
dimensions?: string
|
||||
filters?: string
|
||||
limit?: number
|
||||
}
|
||||
|
||||
export interface ProfoundRawLogsResponse extends ToolResponse {
|
||||
output: {
|
||||
totalRows: number
|
||||
data: Array<{
|
||||
metrics: number[]
|
||||
dimensions: string[]
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfoundBotLogsParams {
|
||||
apiKey: string
|
||||
domain: string
|
||||
startDate: string
|
||||
endDate?: string
|
||||
dimensions?: string
|
||||
filters?: string
|
||||
limit?: number
|
||||
}
|
||||
|
||||
export interface ProfoundBotLogsResponse extends ToolResponse {
|
||||
output: {
|
||||
totalRows: number
|
||||
data: Array<{
|
||||
metrics: number[]
|
||||
dimensions: string[]
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
// --- Content ---
|
||||
|
||||
export interface ProfoundListOptimizationsParams {
|
||||
apiKey: string
|
||||
assetId: string
|
||||
limit?: number
|
||||
offset?: number
|
||||
}
|
||||
|
||||
export interface ProfoundListOptimizationsResponse extends ToolResponse {
|
||||
output: {
|
||||
totalRows: number
|
||||
optimizations: Array<{
|
||||
id: string
|
||||
title: string
|
||||
createdAt: string
|
||||
extractedInput: string | null
|
||||
type: string
|
||||
status: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfoundOptimizationAnalysisParams {
|
||||
apiKey: string
|
||||
assetId: string
|
||||
contentId: string
|
||||
}
|
||||
|
||||
export interface ProfoundOptimizationAnalysisResponse extends ToolResponse {
|
||||
output: {
|
||||
content: {
|
||||
format: string
|
||||
value: string
|
||||
}
|
||||
aeoContentScore: {
|
||||
value: number
|
||||
targetZone: { low: number; high: number }
|
||||
} | null
|
||||
analysis: {
|
||||
breakdown: Array<{
|
||||
title: string
|
||||
weight: number
|
||||
score: number
|
||||
}>
|
||||
}
|
||||
recommendations: Array<{
|
||||
title: string
|
||||
status: string
|
||||
impact: { section: string; score: number } | null
|
||||
suggestion: { text: string; rationale: string }
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
// --- Prompt Volumes ---
|
||||
|
||||
export interface ProfoundPromptVolumeParams {
|
||||
apiKey: string
|
||||
startDate: string
|
||||
endDate: string
|
||||
metrics: string
|
||||
dimensions?: string
|
||||
dateInterval?: string
|
||||
filters?: string
|
||||
limit?: number
|
||||
}
|
||||
|
||||
export interface ProfoundPromptVolumeResponse extends ToolResponse {
|
||||
output: {
|
||||
totalRows: number
|
||||
data: Array<{
|
||||
metrics: number[]
|
||||
dimensions: string[]
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfoundCitationPromptsParams {
|
||||
apiKey: string
|
||||
inputDomain: string
|
||||
}
|
||||
|
||||
export interface ProfoundCitationPromptsResponse extends ToolResponse {
|
||||
output: {
|
||||
data: unknown
|
||||
}
|
||||
}
|
||||
145
apps/sim/tools/profound/visibility_report.ts
Normal file
145
apps/sim/tools/profound/visibility_report.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ProfoundVisibilityReportParams, ProfoundVisibilityReportResponse } from './types'
|
||||
|
||||
export const profoundVisibilityReportTool: ToolConfig<
|
||||
ProfoundVisibilityReportParams,
|
||||
ProfoundVisibilityReportResponse
|
||||
> = {
|
||||
id: 'profound_visibility_report',
|
||||
name: 'Profound Visibility Report',
|
||||
description: 'Query AI visibility report for a category in Profound',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Profound API Key',
|
||||
},
|
||||
categoryId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Category ID (UUID)',
|
||||
},
|
||||
startDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'End date (YYYY-MM-DD or ISO 8601)',
|
||||
},
|
||||
metrics: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated metrics: share_of_voice, mentions_count, visibility_score, executions, average_position',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated dimensions: date, region, topic, model, asset_name, prompt, tag, persona',
|
||||
},
|
||||
dateInterval: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Date interval: hour, day, week, month, year',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of filter objects, e.g. [{"field":"asset_name","operator":"is","value":"Company"}]',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results (default 10000, max 50000)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.tryprofound.com/v1/reports/visibility',
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'X-API-Key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
category_id: params.categoryId,
|
||||
start_date: params.startDate,
|
||||
end_date: params.endDate,
|
||||
metrics: params.metrics.split(',').map((m) => m.trim()),
|
||||
}
|
||||
if (params.dimensions) {
|
||||
body.dimensions = params.dimensions.split(',').map((d) => d.trim())
|
||||
}
|
||||
if (params.dateInterval) {
|
||||
body.date_interval = params.dateInterval
|
||||
}
|
||||
if (params.filters) {
|
||||
try {
|
||||
body.filters = JSON.parse(params.filters)
|
||||
} catch {
|
||||
throw new Error('Invalid JSON in filters parameter')
|
||||
}
|
||||
}
|
||||
if (params.limit != null) {
|
||||
body.pagination = { limit: params.limit }
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail?.[0]?.msg || 'Failed to query visibility report')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
totalRows: data.info?.total_rows ?? 0,
|
||||
data: (data.data ?? []).map((row: { metrics: number[]; dimensions: string[] }) => ({
|
||||
metrics: row.metrics ?? [],
|
||||
dimensions: row.dimensions ?? [],
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
totalRows: {
|
||||
type: 'number',
|
||||
description: 'Total number of rows in the report',
|
||||
},
|
||||
data: {
|
||||
type: 'json',
|
||||
description: 'Report data rows with metrics and dimension values',
|
||||
properties: {
|
||||
metrics: {
|
||||
type: 'json',
|
||||
description: 'Array of metric values matching requested metrics order',
|
||||
},
|
||||
dimensions: {
|
||||
type: 'json',
|
||||
description: 'Array of dimension values matching requested dimensions order',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1777,6 +1777,32 @@ import {
|
||||
posthogUpdatePropertyDefinitionTool,
|
||||
posthogUpdateSurveyTool,
|
||||
} from '@/tools/posthog'
|
||||
import {
|
||||
profoundBotLogsTool,
|
||||
profoundBotsReportTool,
|
||||
profoundCategoryAssetsTool,
|
||||
profoundCategoryPersonasTool,
|
||||
profoundCategoryPromptsTool,
|
||||
profoundCategoryTagsTool,
|
||||
profoundCategoryTopicsTool,
|
||||
profoundCitationPromptsTool,
|
||||
profoundCitationsReportTool,
|
||||
profoundListAssetsTool,
|
||||
profoundListCategoriesTool,
|
||||
profoundListDomainsTool,
|
||||
profoundListModelsTool,
|
||||
profoundListOptimizationsTool,
|
||||
profoundListPersonasTool,
|
||||
profoundListRegionsTool,
|
||||
profoundOptimizationAnalysisTool,
|
||||
profoundPromptAnswersTool,
|
||||
profoundPromptVolumeTool,
|
||||
profoundQueryFanoutsTool,
|
||||
profoundRawLogsTool,
|
||||
profoundReferralsReportTool,
|
||||
profoundSentimentReportTool,
|
||||
profoundVisibilityReportTool,
|
||||
} from '@/tools/profound'
|
||||
import { pulseParserTool, pulseParserV2Tool } from '@/tools/pulse'
|
||||
import { qdrantFetchTool, qdrantSearchTool, qdrantUpsertTool } from '@/tools/qdrant'
|
||||
import { quiverImageToSvgTool, quiverListModelsTool, quiverTextToSvgTool } from '@/tools/quiver'
|
||||
@@ -3631,6 +3657,30 @@ export const tools: Record<string, ToolConfig> = {
|
||||
google_slides_insert_text: googleSlidesInsertTextTool,
|
||||
perplexity_chat: perplexityChatTool,
|
||||
perplexity_search: perplexitySearchTool,
|
||||
profound_bot_logs: profoundBotLogsTool,
|
||||
profound_bots_report: profoundBotsReportTool,
|
||||
profound_category_assets: profoundCategoryAssetsTool,
|
||||
profound_category_personas: profoundCategoryPersonasTool,
|
||||
profound_category_prompts: profoundCategoryPromptsTool,
|
||||
profound_category_tags: profoundCategoryTagsTool,
|
||||
profound_category_topics: profoundCategoryTopicsTool,
|
||||
profound_citation_prompts: profoundCitationPromptsTool,
|
||||
profound_citations_report: profoundCitationsReportTool,
|
||||
profound_list_assets: profoundListAssetsTool,
|
||||
profound_list_categories: profoundListCategoriesTool,
|
||||
profound_list_domains: profoundListDomainsTool,
|
||||
profound_list_models: profoundListModelsTool,
|
||||
profound_list_optimizations: profoundListOptimizationsTool,
|
||||
profound_list_personas: profoundListPersonasTool,
|
||||
profound_list_regions: profoundListRegionsTool,
|
||||
profound_optimization_analysis: profoundOptimizationAnalysisTool,
|
||||
profound_prompt_answers: profoundPromptAnswersTool,
|
||||
profound_prompt_volume: profoundPromptVolumeTool,
|
||||
profound_query_fanouts: profoundQueryFanoutsTool,
|
||||
profound_raw_logs: profoundRawLogsTool,
|
||||
profound_referrals_report: profoundReferralsReportTool,
|
||||
profound_sentiment_report: profoundSentimentReportTool,
|
||||
profound_visibility_report: profoundVisibilityReportTool,
|
||||
pulse_parser: pulseParserTool,
|
||||
pulse_parser_v2: pulseParserV2Tool,
|
||||
quiver_image_to_svg: quiverImageToSvgTool,
|
||||
|
||||
@@ -205,12 +205,27 @@ async function generateIconMapping(): Promise<Record<string, string>> {
|
||||
* Write the icon mapping to the docs app
|
||||
* This file is imported by BlockInfoCard to resolve icons automatically
|
||||
*/
|
||||
/**
|
||||
* Sort strings to match Biome's organizeImports order:
|
||||
* case-insensitive character-by-character, uppercase before lowercase as tiebreaker.
|
||||
*/
|
||||
function biomeSortCompare(a: string, b: string): number {
|
||||
const minLen = Math.min(a.length, b.length)
|
||||
for (let i = 0; i < minLen; i++) {
|
||||
const al = a[i].toLowerCase()
|
||||
const bl = b[i].toLowerCase()
|
||||
if (al !== bl) return al < bl ? -1 : 1
|
||||
if (a[i] !== b[i]) return a[i] < b[i] ? -1 : 1
|
||||
}
|
||||
return a.length - b.length
|
||||
}
|
||||
|
||||
function writeIconMapping(iconMapping: Record<string, string>): void {
|
||||
try {
|
||||
const iconMappingPath = path.join(rootDir, 'apps/docs/components/ui/icon-mapping.ts')
|
||||
|
||||
// Get unique icon names
|
||||
const iconNames = [...new Set(Object.values(iconMapping))].sort()
|
||||
// Get unique icon names, sorted to match Biome's organizeImports
|
||||
const iconNames = [...new Set(Object.values(iconMapping))].sort(biomeSortCompare)
|
||||
|
||||
// Generate imports
|
||||
const imports = iconNames.map((icon) => ` ${icon},`).join('\n')
|
||||
@@ -508,7 +523,7 @@ function writeIntegrationsIconMapping(iconMapping: Record<string, string>): void
|
||||
}
|
||||
const iconMappingPath = path.join(LANDING_INTEGRATIONS_DATA_PATH, 'icon-mapping.ts')
|
||||
|
||||
const iconNames = [...new Set(Object.values(iconMapping))].sort()
|
||||
const iconNames = [...new Set(Object.values(iconMapping))].sort(biomeSortCompare)
|
||||
const imports = iconNames.map((icon) => ` ${icon},`).join('\n')
|
||||
const mappingEntries = Object.entries(iconMapping)
|
||||
.sort(([a], [b]) => a.localeCompare(b))
|
||||
@@ -664,7 +679,16 @@ async function writeIntegrationsJson(iconMapping: Record<string, string>): Promi
|
||||
integrations.sort((a, b) => a.name.localeCompare(b.name))
|
||||
|
||||
const jsonPath = path.join(LANDING_INTEGRATIONS_DATA_PATH, 'integrations.json')
|
||||
fs.writeFileSync(jsonPath, JSON.stringify(integrations, null, 2))
|
||||
// JSON.stringify always expands arrays across multiple lines. Biome's formatter
|
||||
// collapses short arrays of primitives onto single lines. Post-process to match.
|
||||
const json = JSON.stringify(integrations, null, 2).replace(
|
||||
/\[\n(\s+"[^"\n]*"(?:,\n\s+"[^"\n]*")*)\n\s+\]/g,
|
||||
(_match, inner) => {
|
||||
const items = (inner as string).split(',\n').map((s: string) => s.trim())
|
||||
return `[${items.join(', ')}]`
|
||||
}
|
||||
)
|
||||
fs.writeFileSync(jsonPath, `${json}\n`)
|
||||
console.log(`✓ Integration data written: ${integrations.length} integrations → ${jsonPath}`)
|
||||
} catch (error) {
|
||||
console.error('Error writing integrations JSON:', error)
|
||||
@@ -2813,7 +2837,7 @@ function updateMetaJson() {
|
||||
pages: items,
|
||||
}
|
||||
|
||||
fs.writeFileSync(metaJsonPath, JSON.stringify(metaJson, null, 2))
|
||||
fs.writeFileSync(metaJsonPath, `${JSON.stringify(metaJson, null, 2)}\n`)
|
||||
console.log(`Updated meta.json with ${items.length} entries`)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user