From 7e3d10f81498d28e00b27cdb4bb7f1ede704ecd0 Mon Sep 17 00:00:00 2001 From: Patrick Donohoe Date: Wed, 10 Jun 2026 12:44:00 -0400 Subject: [PATCH] feat(you): add You.com integration (search, contents, research, finance research) Adds a You.com block with four tools: you_search (web/news via GET ydc-index.io/v1/search), you_contents (Markdown/HTML extraction via POST ydc-index.io/v1/contents), and you_research / you_finance (agentic research via api.you.com). All four support Sim hosted keys plus workspace BYOK (envKeyPrefix YOU_API_KEY, byokProviderId 'you'), priced per You.com's PayGo rates: search $0.005/call (+$0.001/livecrawl page), contents $0.001/page, research lite/standard/deep/exhaustive ($0.012/$0.05/$0.10/$0.45), finance deep/exhaustive ($0.11/$0.50). Research and finance expose user-selectable effort levels. Registers the 'you' BYOK provider in the settings UI and adds generated docs with a manual intro. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/docs/components/icons.tsx | 28 ++ apps/docs/components/ui/icon-mapping.ts | 2 + .../content/docs/en/integrations/meta.json | 1 + .../docs/content/docs/en/integrations/you.mdx | 150 +++++++ .../settings/components/byok/byok.tsx | 9 + apps/sim/blocks/blocks/you.ts | 384 ++++++++++++++++++ apps/sim/blocks/registry.ts | 3 + apps/sim/components/icons.tsx | 28 ++ apps/sim/lib/api/contracts/byok-keys.ts | 1 + apps/sim/lib/integrations/icon-mapping.ts | 2 + apps/sim/lib/integrations/integrations.json | 35 ++ apps/sim/tools/registry.ts | 10 + apps/sim/tools/types.ts | 1 + apps/sim/tools/you/contents.ts | 146 +++++++ apps/sim/tools/you/finance.ts | 122 ++++++ apps/sim/tools/you/index.ts | 11 + apps/sim/tools/you/research.ts | 125 ++++++ apps/sim/tools/you/search.ts | 224 ++++++++++ apps/sim/tools/you/types.ts | 93 +++++ 19 files changed, 1375 insertions(+) create mode 100644 apps/docs/content/docs/en/integrations/you.mdx create mode 100644 apps/sim/blocks/blocks/you.ts create mode 100644 apps/sim/tools/you/contents.ts create mode 100644 apps/sim/tools/you/finance.ts create mode 100644 apps/sim/tools/you/index.ts create mode 100644 apps/sim/tools/you/research.ts create mode 100644 apps/sim/tools/you/search.ts create mode 100644 apps/sim/tools/you/types.ts diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index 13fa62588b..052099c4bf 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -940,6 +940,34 @@ export function YouTubeIcon(props: React.SVGProps) { ) } +export function YouIcon(props: React.SVGProps) { + const id = useId() + const gradientId = `you_gradient_${id}` + + return ( + + + + + + + + + + ) +} + export function PeopleDataLabsIcon(props: SVGProps) { return ( = { wordpress: WordpressIcon, workday: WorkdayIcon, x: xIcon, + you: YouIcon, youtube: YouTubeIcon, zendesk: ZendeskIcon, zep: ZepIcon, diff --git a/apps/docs/content/docs/en/integrations/meta.json b/apps/docs/content/docs/en/integrations/meta.json index 5e08cf704b..2649f9a829 100644 --- a/apps/docs/content/docs/en/integrations/meta.json +++ b/apps/docs/content/docs/en/integrations/meta.json @@ -226,6 +226,7 @@ "wordpress", "workday", "x", + "you", "youtube", "zendesk", "zep", diff --git a/apps/docs/content/docs/en/integrations/you.mdx b/apps/docs/content/docs/en/integrations/you.mdx new file mode 100644 index 0000000000..ce9e1bc3d7 --- /dev/null +++ b/apps/docs/content/docs/en/integrations/you.mdx @@ -0,0 +1,150 @@ +--- +title: You.com +description: Web search and research with You.com +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[You.com](https://you.com) provides web search APIs built for AI, letting agents search the web, extract clean content, and generate grounded, well-cited answers from real-time results. Its APIs go beyond a single query, returning clean web and news results, full-page content extraction, and multi-step research with cited sources, including a dedicated mode for financial topics. + +With You.com, you can: + +- **Search the web and news**: Retrieve fresh, ranked web and news results with titles, URLs, descriptions, and query-relevant snippets +- **Extract clean page content**: Pull Markdown, HTML, and structured metadata from one or many URLs in a single call +- **Run agentic research**: Pose a complex question and get a synthesized, well-cited answer that autonomously runs multiple searches and reads across sources +- **Research financial topics**: Generate cited answers grounded in SEC filings, earnings reports, and company financials +- **Target and filter results**: Constrain by domain allowlists or blocklists, freshness windows, country, and language, and use search operators like `site:`, `filetype:`, and boolean logic +- **Tune depth versus speed**: Pick a research effort level (lite, standard, deep, or exhaustive) to balance latency against thoroughness + +In Sim, the You.com integration lets your agents search, read, and research the web programmatically. This powers automations such as real-time market and competitor monitoring, lead and account enrichment, content extraction pipelines, and cited research briefs, all as part of your workflows. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Search the web for real-time, LLM-ready results, extract clean content from any URL, and run web or finance research that returns grounded, well-cited answers. + + + +## Actions + +### `you_search` + +Search the web with You.com. Returns LLM-ready web and news results with titles, URLs, descriptions, and query-relevant snippets. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `query` | string | Yes | The search query. Supports operators: site:domain.com, filetype:pdf, +term, -term, AND/OR/NOT, lang:en | +| `count` | number | No | Maximum number of results per section \(1-100, default: 10\) | +| `offset` | number | No | Pagination offset \(0-9, default: 0\) | +| `freshness` | string | No | Freshness filter: day, week, month, year, or a YYYY-MM-DDtoYYYY-MM-DD range | +| `country` | string | No | Two-letter country code to localize results \(e.g., US, GB, JP\) | +| `language` | string | No | BCP 47 language code \(e.g., EN, FR, DE\). Default: EN | +| `safesearch` | string | No | Safe search filter level: off, moderate, or strict | +| `livecrawl` | string | No | Live-crawl sections for full page content: web, news, or all | +| `include_domains` | string | No | Comma-separated allowlist of domains \(mutually exclusive with exclude_domains\) | +| `exclude_domains` | string | No | Comma-separated blocklist of domains to exclude from results | +| `apiKey` | string | Yes | You.com API Key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `search_uuid` | string | Unique identifier for this search request | +| `web` | array | Web search results | +| ↳ `url` | string | The URL of the result | +| ↳ `title` | string | The title of the result | +| ↳ `description` | string | Brief summary of the page | +| ↳ `snippets` | array | Query-relevant text excerpts from the page | +| ↳ `page_age` | string | Publication timestamp \(ISO 8601\) | +| ↳ `author` | string | Primary content author | +| ↳ `favicon_url` | string | URL of the site's favicon | +| ↳ `thumbnail_url` | string | Preview image URL | +| ↳ `contents` | json | Full page content \(only when livecrawl is enabled\) | +| `news` | array | News search results | +| ↳ `url` | string | The URL of the article | +| ↳ `title` | string | The article headline | +| ↳ `description` | string | Content summary | +| ↳ `page_age` | string | Publication timestamp \(UTC\) | +| ↳ `thumbnail_url` | string | Preview image URL | +| ↳ `contents` | json | Full page content \(only when livecrawl is enabled\) | + +### `you_contents` + +Extract clean page content from one or more URLs with You.com. Returns Markdown and/or HTML plus structured metadata for each page. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `urls` | string | Yes | Comma-separated list of webpage URLs to extract content from \(up to 100\) | +| `format` | string | No | Output format: markdown \(default\), html, or both | +| `crawl_timeout` | number | No | Maximum seconds to wait per page \(1-60, default: 10\) | +| `apiKey` | string | Yes | You.com API Key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `results` | array | Extracted content for each requested URL | +| ↳ `url` | string | The webpage URL | +| ↳ `title` | string | The page title | +| ↳ `markdown` | string | Markdown content \(if requested\) | +| ↳ `html` | string | HTML content \(if requested\) | +| ↳ `metadata` | json | Structured metadata \(site_name, favicon_url\) for each page | + +### `you_research` + +Run agentic web research with You.com. Takes a complex question, autonomously runs multiple searches, reads sources, and returns a synthesized, well-cited Markdown answer. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `input` | string | Yes | The research question or complex query \(up to 40,000 characters\) | +| `research_effort` | string | No | Depth of research: lite \(fastest\), standard \(default\), deep, or exhaustive \(most thorough\) | +| `apiKey` | string | Yes | You.com API Key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `content` | string | The synthesized research answer \(Markdown with inline citations\) | +| `content_type` | string | Type of the content field: text or object | +| `sources` | array | Web sources used to generate the answer | +| ↳ `url` | string | The source URL | +| ↳ `title` | string | The source title | +| ↳ `snippets` | array | Relevant snippets extracted from the source | + +### `you_finance` + +Run agentic financial research with You.com. Returns a synthesized, well-cited answer drawn from SEC filings, earnings reports, and company financials. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `input` | string | Yes | The finance research question \(up to 40,000 characters\) | +| `research_effort` | string | No | Depth of research: deep \(default\) or exhaustive \(most thorough\) | +| `apiKey` | string | Yes | You.com API Key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `content` | string | The synthesized finance research answer \(Markdown with inline citations\) | +| `content_type` | string | Type of the content field: text or object | +| `sources` | array | Financial sources used to generate the answer | +| ↳ `url` | string | The source URL | +| ↳ `title` | string | The source title | +| ↳ `snippets` | array | Relevant snippets extracted from the source | + + diff --git a/apps/sim/app/workspace/[workspaceId]/settings/components/byok/byok.tsx b/apps/sim/app/workspace/[workspaceId]/settings/components/byok/byok.tsx index 8d4b5e527f..fce8a31c2f 100644 --- a/apps/sim/app/workspace/[workspaceId]/settings/components/byok/byok.tsx +++ b/apps/sim/app/workspace/[workspaceId]/settings/components/byok/byok.tsx @@ -33,6 +33,7 @@ import { SerperIcon, TogetherIcon, WizaIcon, + YouIcon, ZeroBounceIcon, } from '@/components/icons' import { MAX_BYOK_KEYS_PER_PROVIDER } from '@/lib/api/contracts/byok-keys' @@ -144,6 +145,13 @@ const PROVIDERS: (BYOKManagerProvider & { id: BYOKProviderId })[] = [ description: 'Web search, extraction, and deep research', placeholder: 'Enter your Parallel AI API key', }, + { + id: 'you', + name: 'You.com', + icon: YouIcon, + description: 'Web search, content extraction, and research', + placeholder: 'Enter your You.com API key', + }, { id: 'perplexity', name: 'Perplexity', @@ -293,6 +301,7 @@ const PROVIDER_SECTIONS: BYOKProviderSection[] = [ 'serper', 'linkup', 'parallel_ai', + 'you', 'perplexity', 'jina', 'google_cloud', diff --git a/apps/sim/blocks/blocks/you.ts b/apps/sim/blocks/blocks/you.ts new file mode 100644 index 0000000000..a92f4c7831 --- /dev/null +++ b/apps/sim/blocks/blocks/you.ts @@ -0,0 +1,384 @@ +import { YouIcon } from '@/components/icons' +import { AuthMode, type BlockConfig, type BlockMeta, IntegrationType } from '@/blocks/types' +import type { ToolResponse } from '@/tools/types' + +export const YouBlock: BlockConfig = { + type: 'you', + name: 'You.com', + description: 'Web search and research with You.com', + authMode: AuthMode.ApiKey, + longDescription: + 'Search the web for real-time, LLM-ready results, extract clean content from any URL, and run web or finance research that returns grounded, well-cited answers.', + docsLink: 'https://docs.sim.ai/integrations/you', + category: 'tools', + integrationType: IntegrationType.Search, + bgColor: '#0B0B0F', + icon: YouIcon, + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + { label: 'Search', id: 'search' }, + { label: 'Get Contents', id: 'contents' }, + { label: 'Research', id: 'research' }, + { label: 'Finance Research', id: 'finance' }, + ], + value: () => 'search', + }, + { + id: 'query', + title: 'Search Query', + type: 'long-input', + placeholder: 'What do you want to search for?', + required: true, + condition: { field: 'operation', value: 'search' }, + }, + { + id: 'urls', + title: 'URLs', + type: 'long-input', + placeholder: 'Enter URLs separated by commas (e.g., https://example.com, https://other.com)', + required: true, + condition: { field: 'operation', value: 'contents' }, + }, + { + id: 'research_input', + title: 'Research Query', + type: 'long-input', + placeholder: 'Enter your research question (up to 40,000 characters)', + required: true, + condition: { field: 'operation', value: 'research' }, + }, + { + id: 'finance_input', + title: 'Finance Research Query', + type: 'long-input', + placeholder: 'e.g., What was Apple revenue in Q3 fiscal 2025?', + required: true, + condition: { field: 'operation', value: 'finance' }, + }, + { + id: 'count', + title: 'Number of Results', + type: 'short-input', + placeholder: '10', + condition: { field: 'operation', value: 'search' }, + mode: 'advanced', + }, + { + id: 'offset', + title: 'Offset', + type: 'short-input', + placeholder: '0', + condition: { field: 'operation', value: 'search' }, + mode: 'advanced', + }, + { + id: 'freshness', + title: 'Freshness', + type: 'short-input', + placeholder: 'day, week, month, year, or YYYY-MM-DDtoYYYY-MM-DD', + condition: { field: 'operation', value: 'search' }, + mode: 'advanced', + }, + { + id: 'safesearch', + title: 'Safe Search', + type: 'dropdown', + options: [ + { label: 'Default', id: 'none' }, + { label: 'Off', id: 'off' }, + { label: 'Moderate', id: 'moderate' }, + { label: 'Strict', id: 'strict' }, + ], + value: () => 'none', + condition: { field: 'operation', value: 'search' }, + mode: 'advanced', + }, + { + id: 'country', + title: 'Country', + type: 'short-input', + placeholder: 'Two-letter code (e.g., US, GB, JP)', + condition: { field: 'operation', value: 'search' }, + mode: 'advanced', + }, + { + id: 'language', + title: 'Language', + type: 'short-input', + placeholder: 'BCP 47 code (e.g., EN, FR, DE)', + condition: { field: 'operation', value: 'search' }, + mode: 'advanced', + }, + { + id: 'livecrawl', + title: 'Live Crawl', + type: 'dropdown', + options: [ + { label: 'Off', id: 'none' }, + { label: 'Web', id: 'web' }, + { label: 'News', id: 'news' }, + { label: 'All', id: 'all' }, + ], + value: () => 'none', + condition: { field: 'operation', value: 'search' }, + mode: 'advanced', + }, + { + id: 'include_domains', + title: 'Include Domains', + type: 'short-input', + placeholder: 'Comma-separated domains to include', + condition: { field: 'operation', value: 'search' }, + mode: 'advanced', + }, + { + id: 'exclude_domains', + title: 'Exclude Domains', + type: 'short-input', + placeholder: 'Comma-separated domains to exclude', + condition: { field: 'operation', value: 'search' }, + mode: 'advanced', + }, + { + id: 'format', + title: 'Content Format', + type: 'dropdown', + options: [ + { label: 'Markdown', id: 'markdown' }, + { label: 'HTML', id: 'html' }, + { label: 'Both', id: 'both' }, + ], + value: () => 'markdown', + condition: { field: 'operation', value: 'contents' }, + mode: 'advanced', + }, + { + id: 'crawl_timeout', + title: 'Crawl Timeout (seconds)', + type: 'short-input', + placeholder: '10', + condition: { field: 'operation', value: 'contents' }, + mode: 'advanced', + }, + { + id: 'research_effort', + title: 'Research Effort', + type: 'dropdown', + options: [ + { label: 'Lite', id: 'lite' }, + { label: 'Standard', id: 'standard' }, + { label: 'Deep', id: 'deep' }, + { label: 'Exhaustive', id: 'exhaustive' }, + ], + value: () => 'standard', + condition: { field: 'operation', value: 'research' }, + mode: 'advanced', + }, + { + id: 'finance_effort', + title: 'Research Effort', + type: 'dropdown', + options: [ + { label: 'Deep', id: 'deep' }, + { label: 'Exhaustive', id: 'exhaustive' }, + ], + value: () => 'deep', + condition: { field: 'operation', value: 'finance' }, + mode: 'advanced', + }, + { + id: 'apiKey', + title: 'API Key', + type: 'short-input', + placeholder: 'Enter your You.com API key', + password: true, + required: true, + hideWhenHosted: true, + }, + ], + tools: { + access: ['you_search', 'you_contents', 'you_research', 'you_finance'], + config: { + tool: (params) => { + switch (params.operation) { + case 'search': + return 'you_search' + case 'contents': + return 'you_contents' + case 'research': + return 'you_research' + case 'finance': + return 'you_finance' + default: + return 'you_search' + } + }, + params: (params) => { + const result: Record = {} + const operation = params.operation + + if (operation === 'search') { + if (params.count) result.count = Number(params.count) + if (params.offset) result.offset = Number(params.offset) + if (params.freshness) result.freshness = params.freshness + if (params.safesearch && params.safesearch !== 'none') { + result.safesearch = params.safesearch + } + if (params.country) result.country = params.country + if (params.language) result.language = params.language + if (params.livecrawl && params.livecrawl !== 'none') { + result.livecrawl = params.livecrawl + } + if (params.include_domains) result.include_domains = params.include_domains + if (params.exclude_domains) result.exclude_domains = params.exclude_domains + } + + if (operation === 'contents') { + if (params.format) result.format = params.format + if (params.crawl_timeout) result.crawl_timeout = Number(params.crawl_timeout) + } + + if (operation === 'research') { + if (params.research_input) result.input = params.research_input + if (params.research_effort) result.research_effort = params.research_effort + } + + if (operation === 'finance') { + if (params.finance_input) result.input = params.finance_input + if (params.finance_effort) result.research_effort = params.finance_effort + } + + return result + }, + }, + }, + inputs: { + operation: { type: 'string', description: 'Operation type' }, + query: { type: 'string', description: 'Search query' }, + urls: { type: 'string', description: 'Comma-separated URLs to extract content from' }, + research_input: { type: 'string', description: 'Research question' }, + finance_input: { type: 'string', description: 'Finance research question' }, + count: { type: 'number', description: 'Maximum number of results per section' }, + offset: { type: 'number', description: 'Pagination offset (0-9)' }, + freshness: { type: 'string', description: 'Freshness filter' }, + safesearch: { type: 'string', description: 'Safe search level' }, + country: { type: 'string', description: 'Country code' }, + language: { type: 'string', description: 'Language code' }, + livecrawl: { type: 'string', description: 'Live-crawl sections' }, + include_domains: { type: 'string', description: 'Domains to include (search)' }, + exclude_domains: { type: 'string', description: 'Domains to exclude (search)' }, + format: { type: 'string', description: 'Content output format' }, + crawl_timeout: { type: 'number', description: 'Crawl timeout in seconds' }, + research_effort: { type: 'string', description: 'Research effort level' }, + finance_effort: { type: 'string', description: 'Finance research effort level' }, + apiKey: { type: 'string', description: 'You.com API key' }, + }, + outputs: { + web: { type: 'json', description: 'Web search results (for search)' }, + news: { type: 'json', description: 'News search results (for search)' }, + search_uuid: { type: 'string', description: 'Search request ID (for search)' }, + results: { type: 'json', description: 'Extracted page contents (for contents)' }, + content: { + type: 'string', + description: 'Synthesized research answer (for research and finance)', + }, + content_type: { type: 'string', description: 'Type of the content field (for research)' }, + sources: { + type: 'json', + description: 'Cited sources with url, title, and snippets (for research and finance)', + }, + }, +} + +export const YouBlockMeta = { + tags: ['web-scraping', 'agentic', 'llm'], + templates: [ + { + icon: YouIcon, + title: 'You.com research brief generator', + prompt: + 'Build a workflow that takes a topic, runs You.com Research at deep effort, and writes a structured, fully cited brief to a file for the team to review.', + modules: ['agent', 'files', 'workflows'], + category: 'operations', + tags: ['research', 'reporting', 'automation'], + }, + { + icon: YouIcon, + title: 'You.com competitor news monitor', + prompt: + 'Create a scheduled workflow that uses You.com Search with a freshness window to find recent announcements from a list of competitors and posts a cited digest to Slack each morning.', + modules: ['scheduled', 'agent', 'workflows'], + category: 'marketing', + tags: ['research', 'monitoring', 'reporting'], + alsoIntegrations: ['slack'], + }, + { + icon: YouIcon, + title: 'You.com URL content extractor', + prompt: + 'Build a workflow that reads a table of source URLs, uses You.com Get Contents to pull clean Markdown for each page, and writes the extracted text back to the table.', + modules: ['tables', 'agent', 'workflows'], + category: 'operations', + tags: ['web-scraping', 'automation', 'enrichment'], + }, + { + icon: YouIcon, + title: 'You.com equity research assistant', + prompt: + 'Create a workflow that takes a ticker or company name, runs You.com Finance Research at deep effort over SEC filings and earnings, and emails a cited summary of revenue, margins, and guidance.', + modules: ['agent', 'workflows'], + category: 'operations', + tags: ['research', 'analysis', 'reporting'], + alsoIntegrations: ['gmail'], + }, + { + icon: YouIcon, + title: 'You.com lead enrichment pipeline', + prompt: + 'Build a workflow that runs You.com Search on each new inbound lead to find company size, industry, and recent news, then updates the CRM record with the enriched profile and citations.', + modules: ['agent', 'workflows'], + category: 'sales', + tags: ['sales', 'enrichment', 'automation'], + alsoIntegrations: ['hubspot'], + }, + { + icon: YouIcon, + title: 'You.com market landscape report', + prompt: + 'Create a workflow that runs You.com Research on a market category, synthesizes the players, pricing, and trends into a Markdown report file, and shares the link with the strategy team.', + modules: ['agent', 'files', 'workflows'], + category: 'operations', + tags: ['research', 'analysis', 'reporting'], + }, + { + icon: YouIcon, + title: 'You.com daily topic digest', + prompt: + 'Build a scheduled daily workflow that uses You.com Search across the topics a team follows, extracts the key facts from the top results, and emails a concise cited digest each morning.', + modules: ['scheduled', 'agent', 'workflows'], + category: 'productivity', + tags: ['research', 'reporting', 'automation'], + alsoIntegrations: ['gmail'], + }, + ], + skills: [ + { + name: 'web-search-with-youcom', + description: + 'Use You.com Search to answer a question with fresh, cited web and news results.', + content: + '# Web Search With You.com\n\nAnswer a question grounded in current web sources.\n\n## Steps\n1. Use the Search operation and provide a clear Query. You.com supports operators like site:, filetype:, +term, -term, and AND/OR/NOT.\n2. Optionally narrow results with Freshness, Include or Exclude Domains, Country, and Language.\n3. Enable Live Crawl when you need full page content rather than snippets.\n\n## Output\nA direct answer followed by the supporting web and news results, each with title, URL, and the relevant snippet.', + }, + { + name: 'agentic-research-with-youcom', + description: + 'Run You.com Research to produce a synthesized, well-cited answer to a complex question.', + content: + '# Agentic Research With You.com\n\nProduce a thorough, sourced answer to a hard question.\n\n## Steps\n1. Use the Research operation and state the full question in the Research Query.\n2. Pick a Research Effort: lite for speed, standard for balance, deep or exhaustive when accuracy matters most.\n3. Read the synthesized content and verify each claim against the cited sources.\n\n## Output\nA Markdown answer with inline citations plus the list of sources, each with URL, title, and supporting snippets.', + }, + ], +} as const satisfies BlockMeta diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index 96d2f7f2f6..9278215b10 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -319,6 +319,7 @@ import { WorkdayBlock, WorkdayBlockMeta } from '@/blocks/blocks/workday' import { WorkflowBlock } from '@/blocks/blocks/workflow' import { WorkflowInputBlock } from '@/blocks/blocks/workflow_input' import { XBlock, XBlockMeta } from '@/blocks/blocks/x' +import { YouBlock, YouBlockMeta } from '@/blocks/blocks/you' import { YouTubeBlock, YouTubeBlockMeta } from '@/blocks/blocks/youtube' import { ZendeskBlock, ZendeskBlockMeta } from '@/blocks/blocks/zendesk' import { ZepBlock, ZepBlockMeta } from '@/blocks/blocks/zep' @@ -627,6 +628,7 @@ const BLOCK_REGISTRY: Record = { workflow: WorkflowBlock, workflow_input: WorkflowInputBlock, x: XBlock, + you: YouBlock, youtube: YouTubeBlock, zendesk: ZendeskBlock, zep: ZepBlock, @@ -871,6 +873,7 @@ const BLOCK_META_REGISTRY: Record = { wordpress: WordPressBlockMeta, workday: WorkdayBlockMeta, x: XBlockMeta, + you: YouBlockMeta, youtube: YouTubeBlockMeta, zendesk: ZendeskBlockMeta, zep: ZepBlockMeta, diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index 13fa62588b..052099c4bf 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -940,6 +940,34 @@ export function YouTubeIcon(props: React.SVGProps) { ) } +export function YouIcon(props: React.SVGProps) { + const id = useId() + const gradientId = `you_gradient_${id}` + + return ( + + + + + + + + + + ) +} + export function PeopleDataLabsIcon(props: SVGProps) { return ( = { wordpress: WordpressIcon, workday: WorkdayIcon, x: xIcon, + you: YouIcon, youtube: YouTubeIcon, zendesk: ZendeskIcon, zep: ZepIcon, diff --git a/apps/sim/lib/integrations/integrations.json b/apps/sim/lib/integrations/integrations.json index 2ff2b8f785..61c67ea9c3 100644 --- a/apps/sim/lib/integrations/integrations.json +++ b/apps/sim/lib/integrations/integrations.json @@ -17191,6 +17191,41 @@ "integrationType": "communication", "tags": ["marketing", "messaging"] }, + { + "type": "you", + "slug": "you-com", + "name": "You.com", + "description": "Web search and research with You.com", + "longDescription": "Search the web for real-time, LLM-ready results, extract clean content from any URL, and run web or finance research that returns grounded, well-cited answers.", + "bgColor": "#0B0B0F", + "iconName": "YouIcon", + "docsUrl": "https://docs.sim.ai/tools/you", + "operations": [ + { + "name": "Search", + "description": "Search the web with You.com. Returns LLM-ready web and news results with titles, URLs, descriptions, and query-relevant snippets." + }, + { + "name": "Get Contents", + "description": "Extract clean page content from one or more URLs with You.com. Returns Markdown and/or HTML plus structured metadata for each page." + }, + { + "name": "Research", + "description": "Run agentic web research with You.com. Takes a complex question, autonomously runs multiple searches, reads sources, and returns a synthesized, well-cited Markdown answer." + }, + { + "name": "Finance Research", + "description": "Run agentic financial research with You.com. Returns a synthesized, well-cited answer drawn from SEC filings, earnings reports, and company financials." + } + ], + "operationCount": 4, + "triggers": [], + "triggerCount": 0, + "authType": "api-key", + "category": "tools", + "integrationType": "search", + "tags": ["web-scraping", "agentic", "llm"] + }, { "type": "youtube", "slug": "youtube", diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index 4bc16046b9..8109a9d7e8 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -3699,6 +3699,12 @@ import { xUserTool, xWriteTool, } from '@/tools/x' +import { + youContentsTool, + youFinanceTool, + youResearchTool, + youSearchTool, +} from '@/tools/you' import { youtubeChannelInfoTool, youtubeChannelPlaylistsTool, @@ -4495,6 +4501,10 @@ export const tools: Record = { typeform_create_form: typeformCreateFormTool, typeform_update_form: typeformUpdateFormTool, typeform_delete_form: typeformDeleteFormTool, + you_search: youSearchTool, + you_contents: youContentsTool, + you_research: youResearchTool, + you_finance: youFinanceTool, youtube_channel_info: youtubeChannelInfoTool, youtube_channel_playlists: youtubeChannelPlaylistsTool, youtube_channel_videos: youtubeChannelVideosTool, diff --git a/apps/sim/tools/types.ts b/apps/sim/tools/types.ts index dcce33cbe2..d83762a3d7 100644 --- a/apps/sim/tools/types.ts +++ b/apps/sim/tools/types.ts @@ -28,6 +28,7 @@ export type BYOKProviderId = | 'prospeo' | 'wiza' | 'zerobounce' + | 'you' | 'neverbounce' | 'millionverifier' | 'datagma' diff --git a/apps/sim/tools/you/contents.ts b/apps/sim/tools/you/contents.ts new file mode 100644 index 0000000000..744e53b40b --- /dev/null +++ b/apps/sim/tools/you/contents.ts @@ -0,0 +1,146 @@ +import type { ToolConfig } from '@/tools/types' +import type { YouContentsParams, YouContentsResponse } from '@/tools/you/types' + +function parseUrls(urls: string): string[] { + return urls + .split(',') + .map((url) => url.trim()) + .filter((url) => url.length > 0) +} + +function resolveFormats(format?: string): string[] { + switch (format) { + case 'html': + return ['html', 'metadata'] + case 'both': + return ['markdown', 'html', 'metadata'] + default: + return ['markdown', 'metadata'] + } +} + +export const contentsTool: ToolConfig = { + id: 'you_contents', + name: 'You.com Contents', + description: + 'Extract clean page content from one or more URLs with You.com. Returns Markdown and/or HTML plus structured metadata for each page.', + version: '1.0.0', + + hosting: { + envKeyPrefix: 'YOU_API_KEY', + apiKeyParam: 'apiKey', + byokProviderId: 'you', + pricing: { + type: 'custom', + getCost: (_params, output) => { + if (!Array.isArray(output.results)) { + throw new Error('You.com contents response missing results array') + } + // You.com Contents: $1/1k pages + // https://you.com/pricing + const pageCount = output.results.length + const cost = pageCount * 0.001 + return { cost, metadata: { pageCount } } + }, + }, + rateLimit: { + mode: 'per_request', + requestsPerMinute: 60, + }, + }, + + params: { + urls: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Comma-separated list of webpage URLs to extract content from (up to 100)', + }, + format: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'Output format: markdown (default), html, or both', + }, + crawl_timeout: { + type: 'number', + required: false, + visibility: 'user-only', + description: 'Maximum seconds to wait per page (1-60, default: 10)', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'You.com API Key', + }, + }, + + request: { + url: 'https://ydc-index.io/v1/contents', + method: 'POST', + headers: (params) => ({ + 'Content-Type': 'application/json', + 'X-API-Key': params.apiKey, + }), + body: (params) => { + const body: Record = { + urls: parseUrls(params.urls), + formats: resolveFormats(params.format), + } + if (params.crawl_timeout) body.crawl_timeout = Number(params.crawl_timeout) + return body + }, + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`You.com contents failed: ${response.status} - ${errorText}`) + } + + const data = await response.json() + const items = (Array.isArray(data) ? data : (data.output ?? data.results ?? [])) as Record< + string, + unknown + >[] + + return { + success: true, + output: { + results: items.map((item) => ({ + url: (item.url as string | undefined) ?? null, + title: (item.title as string | undefined) ?? null, + markdown: (item.markdown as string | undefined) ?? null, + html: (item.html as string | undefined) ?? null, + metadata: (item.metadata as Record | undefined) ?? null, + })), + }, + } + }, + + outputs: { + results: { + type: 'array', + description: 'Extracted content for each requested URL', + items: { + type: 'object', + properties: { + url: { type: 'string', description: 'The webpage URL' }, + title: { type: 'string', description: 'The page title', optional: true }, + markdown: { + type: 'string', + description: 'Markdown content (if requested)', + optional: true, + }, + html: { type: 'string', description: 'HTML content (if requested)', optional: true }, + metadata: { + type: 'json', + description: 'Structured metadata (site_name, favicon_url) for each page', + optional: true, + }, + }, + }, + }, + }, +} diff --git a/apps/sim/tools/you/finance.ts b/apps/sim/tools/you/finance.ts new file mode 100644 index 0000000000..8b386113fe --- /dev/null +++ b/apps/sim/tools/you/finance.ts @@ -0,0 +1,122 @@ +import type { ToolConfig } from '@/tools/types' +import type { YouFinanceParams, YouFinanceResponse } from '@/tools/you/types' + +export const financeTool: ToolConfig = { + id: 'you_finance', + name: 'You.com Finance Research', + description: + 'Run agentic financial research with You.com. Returns a synthesized, well-cited answer drawn from SEC filings, earnings reports, and company financials.', + version: '1.0.0', + + hosting: { + envKeyPrefix: 'YOU_API_KEY', + apiKeyParam: 'apiKey', + byokProviderId: 'you', + pricing: { + type: 'custom', + getCost: (params) => { + // You.com Finance Research, per effort tier (CPM / 1000) + // https://you.com/pricing + const rates: Record = { + deep: 0.11, + exhaustive: 0.5, + } + const effort = (params.research_effort as string) || 'deep' + const cost = rates[effort] ?? rates.deep + return { cost, metadata: { effort } } + }, + }, + rateLimit: { + mode: 'per_request', + requestsPerMinute: 15, + }, + }, + + params: { + input: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The finance research question (up to 40,000 characters)', + }, + research_effort: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'Depth of research: deep (default) or exhaustive (most thorough)', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'You.com API Key', + }, + }, + + request: { + url: 'https://api.you.com/v1/finance_research', + method: 'POST', + headers: (params) => ({ + 'Content-Type': 'application/json', + 'X-API-Key': params.apiKey, + }), + body: (params) => { + const body: Record = { + input: params.input, + } + if (params.research_effort) body.research_effort = params.research_effort + return body + }, + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`You.com finance research failed: ${response.status} - ${errorText}`) + } + + const data = await response.json() + const output = data.output ?? {} + + return { + success: true, + output: { + content: (output.content as string | undefined) ?? null, + content_type: (output.content_type as string | undefined) ?? null, + sources: ((output.sources ?? []) as Record[]).map((source) => ({ + url: (source.url as string | undefined) ?? null, + title: (source.title as string | undefined) ?? null, + snippets: (source.snippets as string[] | undefined) ?? [], + })), + }, + } + }, + + outputs: { + content: { + type: 'string', + description: 'The synthesized finance research answer (Markdown with inline citations)', + }, + content_type: { + type: 'string', + description: 'Type of the content field: text or object', + optional: true, + }, + sources: { + type: 'array', + description: 'Financial sources used to generate the answer', + items: { + type: 'object', + properties: { + url: { type: 'string', description: 'The source URL' }, + title: { type: 'string', description: 'The source title' }, + snippets: { + type: 'array', + description: 'Relevant snippets extracted from the source', + items: { type: 'string' }, + }, + }, + }, + }, + }, +} diff --git a/apps/sim/tools/you/index.ts b/apps/sim/tools/you/index.ts new file mode 100644 index 0000000000..f9dfde2e2e --- /dev/null +++ b/apps/sim/tools/you/index.ts @@ -0,0 +1,11 @@ +import { contentsTool } from '@/tools/you/contents' +import { financeTool } from '@/tools/you/finance' +import { researchTool } from '@/tools/you/research' +import { searchTool } from '@/tools/you/search' + +export const youSearchTool = searchTool +export const youContentsTool = contentsTool +export const youResearchTool = researchTool +export const youFinanceTool = financeTool + +export * from './types' diff --git a/apps/sim/tools/you/research.ts b/apps/sim/tools/you/research.ts new file mode 100644 index 0000000000..cba9f229e2 --- /dev/null +++ b/apps/sim/tools/you/research.ts @@ -0,0 +1,125 @@ +import type { ToolConfig } from '@/tools/types' +import type { YouResearchParams, YouResearchResponse } from '@/tools/you/types' + +export const researchTool: ToolConfig = { + id: 'you_research', + name: 'You.com Research', + description: + 'Run agentic web research with You.com. Takes a complex question, autonomously runs multiple searches, reads sources, and returns a synthesized, well-cited Markdown answer.', + version: '1.0.0', + + hosting: { + envKeyPrefix: 'YOU_API_KEY', + apiKeyParam: 'apiKey', + byokProviderId: 'you', + pricing: { + type: 'custom', + getCost: (params) => { + // You.com Research, per effort tier (CPM / 1000) + // https://you.com/pricing + const rates: Record = { + lite: 0.012, + standard: 0.05, + deep: 0.1, + exhaustive: 0.45, + } + const effort = (params.research_effort as string) || 'standard' + const cost = rates[effort] ?? rates.standard + return { cost, metadata: { effort } } + }, + }, + rateLimit: { + mode: 'per_request', + requestsPerMinute: 30, + }, + }, + + params: { + input: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The research question or complex query (up to 40,000 characters)', + }, + research_effort: { + type: 'string', + required: false, + visibility: 'user-only', + description: + 'Depth of research: lite (fastest), standard (default), deep, or exhaustive (most thorough)', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'You.com API Key', + }, + }, + + request: { + url: 'https://api.you.com/v1/research', + method: 'POST', + headers: (params) => ({ + 'Content-Type': 'application/json', + 'X-API-Key': params.apiKey, + }), + body: (params) => { + const body: Record = { + input: params.input, + } + if (params.research_effort) body.research_effort = params.research_effort + return body + }, + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`You.com research failed: ${response.status} - ${errorText}`) + } + + const data = await response.json() + const output = data.output ?? {} + + return { + success: true, + output: { + content: (output.content as string | undefined) ?? null, + content_type: (output.content_type as string | undefined) ?? null, + sources: ((output.sources ?? []) as Record[]).map((source) => ({ + url: (source.url as string | undefined) ?? null, + title: (source.title as string | undefined) ?? null, + snippets: (source.snippets as string[] | undefined) ?? [], + })), + }, + } + }, + + outputs: { + content: { + type: 'string', + description: 'The synthesized research answer (Markdown with inline citations)', + }, + content_type: { + type: 'string', + description: 'Type of the content field: text or object', + optional: true, + }, + sources: { + type: 'array', + description: 'Web sources used to generate the answer', + items: { + type: 'object', + properties: { + url: { type: 'string', description: 'The source URL' }, + title: { type: 'string', description: 'The source title' }, + snippets: { + type: 'array', + description: 'Relevant snippets extracted from the source', + items: { type: 'string' }, + }, + }, + }, + }, + }, +} diff --git a/apps/sim/tools/you/search.ts b/apps/sim/tools/you/search.ts new file mode 100644 index 0000000000..79c2cfaf1a --- /dev/null +++ b/apps/sim/tools/you/search.ts @@ -0,0 +1,224 @@ +import type { ToolConfig } from '@/tools/types' +import type { YouSearchParams, YouSearchResponse } from '@/tools/you/types' + +export const searchTool: ToolConfig = { + id: 'you_search', + name: 'You.com Search', + description: + 'Search the web with You.com. Returns LLM-ready web and news results with titles, URLs, descriptions, and query-relevant snippets.', + version: '1.0.0', + + hosting: { + envKeyPrefix: 'YOU_API_KEY', + apiKeyParam: 'apiKey', + byokProviderId: 'you', + pricing: { + type: 'custom', + getCost: (_params, output) => { + // You.com Search: $5/1k calls, livecrawl adds $1/1k crawled pages + // https://you.com/pricing + const countCrawled = (section: unknown): number => + Array.isArray(section) ? section.filter((result) => result?.contents != null).length : 0 + const crawledPages = countCrawled(output.web) + countCrawled(output.news) + const cost = 0.005 + crawledPages * 0.001 + return { cost, metadata: { crawledPages } } + }, + }, + rateLimit: { + mode: 'per_request', + requestsPerMinute: 60, + }, + }, + + params: { + query: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: + 'The search query. Supports operators: site:domain.com, filetype:pdf, +term, -term, AND/OR/NOT, lang:en', + }, + count: { + type: 'number', + required: false, + visibility: 'user-only', + description: 'Maximum number of results per section (1-100, default: 10)', + }, + offset: { + type: 'number', + required: false, + visibility: 'user-only', + description: 'Pagination offset (0-9, default: 0)', + }, + freshness: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Freshness filter: day, week, month, year, or a YYYY-MM-DDtoYYYY-MM-DD range', + }, + country: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'Two-letter country code to localize results (e.g., US, GB, JP)', + }, + language: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'BCP 47 language code (e.g., EN, FR, DE). Default: EN', + }, + safesearch: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'Safe search filter level: off, moderate, or strict', + }, + livecrawl: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'Live-crawl sections for full page content: web, news, or all', + }, + include_domains: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Comma-separated allowlist of domains (mutually exclusive with exclude_domains)', + }, + exclude_domains: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Comma-separated blocklist of domains to exclude from results', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'You.com API Key', + }, + }, + + request: { + url: (params) => { + const searchParams = new URLSearchParams({ query: params.query }) + + // 'none' is the block's "unset" sentinel for these enum dropdowns; the API rejects it + const isSet = (value?: string): value is string => Boolean(value) && value !== 'none' + + if (params.count) searchParams.set('count', String(Number(params.count))) + if (params.offset) searchParams.set('offset', String(Number(params.offset))) + if (params.freshness) searchParams.set('freshness', params.freshness) + if (params.country) searchParams.set('country', params.country) + if (params.language) searchParams.set('language', params.language) + if (isSet(params.safesearch)) searchParams.set('safesearch', params.safesearch) + if (isSet(params.livecrawl)) searchParams.set('livecrawl', params.livecrawl) + if (params.include_domains) searchParams.set('include_domains', params.include_domains) + if (params.exclude_domains) searchParams.set('exclude_domains', params.exclude_domains) + + return `https://ydc-index.io/v1/search?${searchParams.toString()}` + }, + method: 'GET', + headers: (params) => ({ + 'X-API-Key': params.apiKey, + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`You.com search failed: ${response.status} - ${errorText}`) + } + + const data = await response.json() + const results = data.results ?? {} + + return { + success: true, + output: { + search_uuid: (data.metadata?.search_uuid as string | undefined) ?? null, + web: ((results.web ?? []) as Record[]).map((result) => ({ + url: (result.url as string | undefined) ?? null, + title: (result.title as string | undefined) ?? null, + description: (result.description as string | undefined) ?? null, + snippets: (result.snippets as string[] | undefined) ?? [], + page_age: (result.page_age as string | undefined) ?? null, + author: Array.isArray(result.authors) ? ((result.authors[0] as string) ?? null) : null, + favicon_url: (result.favicon_url as string | undefined) ?? null, + thumbnail_url: (result.thumbnail_url as string | undefined) ?? null, + contents: (result.contents as Record | undefined) ?? null, + })), + news: ((results.news ?? []) as Record[]).map((result) => ({ + url: (result.url as string | undefined) ?? null, + title: (result.title as string | undefined) ?? null, + description: (result.description as string | undefined) ?? null, + page_age: (result.page_age as string | undefined) ?? null, + thumbnail_url: (result.thumbnail_url as string | undefined) ?? null, + contents: (result.contents as Record | undefined) ?? null, + })), + }, + } + }, + + outputs: { + search_uuid: { + type: 'string', + description: 'Unique identifier for this search request', + optional: true, + }, + web: { + type: 'array', + description: 'Web search results', + items: { + type: 'object', + properties: { + url: { type: 'string', description: 'The URL of the result' }, + title: { type: 'string', description: 'The title of the result' }, + description: { type: 'string', description: 'Brief summary of the page' }, + snippets: { + type: 'array', + description: 'Query-relevant text excerpts from the page', + items: { type: 'string' }, + }, + page_age: { + type: 'string', + description: 'Publication timestamp (ISO 8601)', + optional: true, + }, + author: { type: 'string', description: 'Primary content author', optional: true }, + favicon_url: { type: 'string', description: "URL of the site's favicon", optional: true }, + thumbnail_url: { type: 'string', description: 'Preview image URL', optional: true }, + contents: { + type: 'json', + description: 'Full page content (only when livecrawl is enabled)', + optional: true, + }, + }, + }, + }, + news: { + type: 'array', + description: 'News search results', + items: { + type: 'object', + properties: { + url: { type: 'string', description: 'The URL of the article' }, + title: { type: 'string', description: 'The article headline' }, + description: { type: 'string', description: 'Content summary' }, + page_age: { + type: 'string', + description: 'Publication timestamp (UTC)', + optional: true, + }, + thumbnail_url: { type: 'string', description: 'Preview image URL', optional: true }, + contents: { + type: 'json', + description: 'Full page content (only when livecrawl is enabled)', + optional: true, + }, + }, + }, + }, + }, +} diff --git a/apps/sim/tools/you/types.ts b/apps/sim/tools/you/types.ts new file mode 100644 index 0000000000..8afb0c8cba --- /dev/null +++ b/apps/sim/tools/you/types.ts @@ -0,0 +1,93 @@ +import type { ToolResponse } from '@/tools/types' + +export interface YouSearchParams { + query: string + count?: number + offset?: number + freshness?: string + country?: string + language?: string + safesearch?: string + livecrawl?: string + include_domains?: string + exclude_domains?: string + apiKey: string +} + +interface YouWebResult { + url: string | null + title: string | null + description: string | null + snippets: string[] + page_age: string | null + author: string | null + favicon_url: string | null + thumbnail_url: string | null + contents: Record | null +} + +interface YouNewsResult { + url: string | null + title: string | null + description: string | null + page_age: string | null + thumbnail_url: string | null + contents: Record | null +} + +export interface YouSearchResponse extends ToolResponse { + output: { + search_uuid: string | null + web: YouWebResult[] + news: YouNewsResult[] + } +} + +export interface YouContentsParams { + urls: string + format?: string + crawl_timeout?: number + apiKey: string +} + +interface YouContentsResult { + url: string | null + title: string | null + markdown: string | null + html: string | null + metadata: Record | null +} + +export interface YouContentsResponse extends ToolResponse { + output: { + results: YouContentsResult[] + } +} + +interface YouResearchSource { + url: string | null + title: string | null + snippets: string[] +} + +export interface YouResearchParams { + input: string + research_effort?: string + apiKey: string +} + +export interface YouResearchResponse extends ToolResponse { + output: { + content: string | null + content_type: string | null + sources: YouResearchSource[] + } +} + +export interface YouFinanceParams { + input: string + research_effort?: string + apiKey: string +} + +export type YouFinanceResponse = YouResearchResponse