Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
236 changes: 236 additions & 0 deletions docs/providers/youcom-provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
# You.com Provider Integration

The YouCom provider integrates You.com's web search into AgentOS, offering access to real-time web information and news search.

## Overview

Unlike traditional LLM providers, YouCom specializes in:
- **Real-time web search** with source URLs, descriptions, and snippets
- **News search** with timestamps and publication metadata

The provider reads credentials from `YDC_API_KEY` or `YOUCOM_API_KEY`, and you can also pass an explicit `apiKey` during initialization.

## Quick Start

```typescript
import { YouComProvider } from '@framers/agentos';

const provider = new YouComProvider();
await provider.initialize();

const results = await provider.search('What are the latest developments in AI agent frameworks?', {
count: 5,
});

for (const item of results.web ?? []) {
console.log(item.title);
console.log(item.url);
console.log(item.description);
console.log(item.snippets[0]);
}
```

## Authentication

### Environment-Based Setup
The provider reads `YDC_API_KEY` first and falls back to `YOUCOM_API_KEY` for legacy setups.

```bash
export YDC_API_KEY="your_api_key_here"
```

Get your API key at [you.com/platform/api-keys](https://you.com/platform/api-keys).

Alternative environment variable:
```bash
export YOUCOM_API_KEY="your_api_key_here"
```

### Custom Configuration

```typescript
const provider = new YouComProvider();
await provider.initialize({
searchApiUrl: 'https://ydc-index.io/v1/search',
mcpServerUrl: 'https://api.you.com/mcp',
debug: true,
});
```

## Available Models

| Model ID | Description | Use Case |
|----------|-------------|----------|
| `youcom-search` | Web search with snippets | General web search queries |
| `youcom-news` | News-focused search | Recent news and current events |

## Direct Search API

Access You.com search functionality directly:

```typescript
const provider = new YouComProvider();
await provider.initialize({
apiKey: process.env.YDC_API_KEY ?? process.env.YOUCOM_API_KEY,
});

Comment thread
coderabbitai[bot] marked this conversation as resolved.
// Web search
const results = await provider.search('TypeScript frameworks', {
count: 5,
type: 'web'
});

// News search
const news = await provider.search('AI developments', {
count: 3,
type: 'news'
});
```

## Response Format

### Web Search Results
```typescript
{
web: [
{
title: "Page title",
url: "https://example.com",
description: "Relevant excerpt from the page...",
snippets: ["Relevant excerpt from the page..."]
}
]
}
```

### News Search Results
```typescript
{
news: [
{
title: "Article title",
url: "https://news.example.com/article",
description: "Article excerpt...",
snippets: ["Article excerpt..."],
published_at: "2026-07-26T10:00:00Z"
}
]
}
```

## Error Handling

The provider handles common error scenarios gracefully:

- **Rate limiting (429)**: Returns helpful message about API key benefits
- **Network errors**: Fail-safe with informative error messages
- **Invalid queries**: Validation with suggestion prompts
- **Quota exceeded**: Clear indication of limits and upgrade paths

```typescript
try {
const results = await provider.search('query');
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (message.includes('rate limit')) {
console.log('Consider using an API key for higher quotas');
}
}
```

## Health Monitoring

Check provider connectivity and configuration:

```typescript
const health = await provider.checkHealth();
console.log('Healthy:', health.isHealthy);
console.log('API Key configured:', health.details.apiKeyConfigured);
```

## AgentOS Registry

YouCom is automatically registered in AgentOS's provider system:

```typescript
import { AIModelProviderManager } from '@framers/agentos';

const manager = new AIModelProviderManager();
await manager.initialize({
providers: [
{
providerId: 'youcom',
enabled: true,
config: {
apiKey: process.env.YDC_API_KEY ?? process.env.YOUCOM_API_KEY,
},
},
],
});
```

## MCP Server Path

You.com's MCP surface also includes content and research tooling. This provider
keeps the search integration small and optional, but if you wire the MCP server
later the corresponding tool names are:
- `you-search` for web search
- `you-contents` for URL content extraction
- `you-research` for research synthesis

Those MCP tools are not enabled by this PR.

## Limitations

- **No LLM generation**: YouCom focuses on search/tools, not text generation
- **No embeddings**: Use other providers for embedding models
- **No streaming**: Search results are returned as complete responses
- **Rate limits**: Keyless tier has daily quotas (overcome with API key)

## Best Practices

1. **Use for current information**: YouCom excels at real-time web data
2. **Combine with LLM providers**: Use YouCom for search, other providers for generation
3. **Cache results**: Avoid repeated identical searches
4. **Respect rate limits**: Monitor quota usage in production
5. **Cite sources**: Always include URLs in agent responses

## Examples

See `examples/youcom-search-example.mjs` for a complete working example demonstrating:
- Direct search and news search with YouComProvider
- Multiple query types
- Direct API access
- Error handling patterns
- Configuration examples

## Troubleshooting

### "Provider not initialized"
- Ensure `initialize()` is called before use
- Check network connectivity

### "Rate limit exceeded"
- Set `YDC_API_KEY` environment variable
- Implement request throttling
- Consider caching search results

### "Search API connectivity test failed"
- Check internet connection
- Verify You.com API endpoint accessibility
- Review firewall/proxy settings

### Integration Issues
- Confirm YouCom is registered in `AIModelProviderManager`
- Check provider configuration in AgentOS config
- Enable debug logging: `debug: true`

## Contributing

YouCom provider follows AgentOS provider standards:
- Implements full `IProvider` interface
- Comprehensive error handling
- Unit test coverage
- Documentation and examples

See [Provider Integration Guide](../contributing/new-provider.md) for details.
73 changes: 73 additions & 0 deletions examples/youcom-search-example.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env node
/**
* @fileoverview YouCom Provider Example - Demonstrates You.com integration with AgentOS
*
* This example shows how to use the YouCom provider for web search and news search.
*
* Usage:
* node examples/youcom-search-example.mjs
*
* Environment variables:
* YDC_API_KEY - You.com API key
* YOUCOM_API_KEY - Legacy fallback env var
*/

import { YouComProvider } from '@framers/agentos';

function printConfigurationExamples() {
console.log('\n📚 Configuration Examples:\n');

console.log('1. Environment-based setup:');
console.log(' export YDC_API_KEY="your-api-key-here"');
console.log(' # or export YOUCOM_API_KEY="your-api-key-here"\n');

console.log('2. Explicit initialization:');
console.log(` const provider = new YouComProvider();
await provider.initialize({
});\n`);
}

async function runYouComExample() {
console.log('🔍 YouCom Provider Example - Search with AgentOS\n');

const provider = new YouComProvider();
await provider.initialize({ debug: true });

const webQuery = 'What are the latest developments in AI agent frameworks?';
console.log(`\n📋 Web query: ${webQuery}`);
const webResults = await provider.search(webQuery, { count: 5, type: 'web' });

for (const [index, result] of (webResults.web ?? []).entries()) {
console.log(`${index + 1}. ${result.title}`);
console.log(` ${result.url}`);
console.log(` ${result.description}`);
if (result.snippets[0]) {
console.log(` ${result.snippets[0]}`);
}
}

const newsQuery = 'TypeScript 5.7 release';
console.log(`\n📰 News query: ${newsQuery}`);
const newsResults = await provider.search(newsQuery, {
count: 3,
type: 'news',
freshness: 'week',
});

for (const [index, result] of (newsResults.news ?? []).entries()) {
console.log(`${index + 1}. ${result.title}`);
console.log(` ${result.url}`);
console.log(` ${result.description}`);
if (result.published_at) {
console.log(` published: ${result.published_at}`);
}
}
}

if (import.meta.url === `file://${process.argv[1]}`) {
printConfigurationExamples();
runYouComExample().catch((error) => {
console.error('❌ YouCom example failed:', error instanceof Error ? error.message : String(error));
process.exitCode = 1;
});
}
13 changes: 13 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
allowBuilds:
'@matrix-org/matrix-sdk-crypto-nodejs': true
'@whiskeysockets/baileys': true
bcrypt: true
better-sqlite3: true
esbuild: true
ffi-napi: true
hnswlib-node: true
onnxruntime-node: true
protobufjs: true
ref-napi: true
sharp: true
tesseract.js: true
3 changes: 2 additions & 1 deletion src/api/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const ENV_KEY_MAP: Record<string, string> = {
xai: 'XAI_API_KEY',
stability: 'STABILITY_API_KEY',
replicate: 'REPLICATE_API_TOKEN',
youcom: 'YDC_API_KEY',
};

const ENV_URL_MAP: Record<string, string> = {
Expand All @@ -59,7 +60,7 @@ const ENV_URL_MAP: Record<string, string> = {
'stable-diffusion-local': 'STABLE_DIFFUSION_LOCAL_BASE_URL',
};

const KEYLESS_PROVIDER_IDS = new Set(['claude-code-cli', 'gemini-cli']);
const KEYLESS_PROVIDER_IDS = new Set(['claude-code-cli', 'gemini-cli', 'youcom']);

/**
* Splits a `provider:model` string into its constituent parts.
Expand Down
24 changes: 24 additions & 0 deletions src/api/runtime/__tests__/provider-defaults.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ describe('autoDetectProvider', () => {
'TOGETHER_API_KEY',
'MISTRAL_API_KEY',
'XAI_API_KEY',
'YDC_API_KEY',
'YOUCOM_API_KEY',
'OLLAMA_BASE_URL',
'STABILITY_API_KEY',
'REPLICATE_API_TOKEN',
Expand Down Expand Up @@ -97,6 +99,8 @@ describe('autoDetectProvider', () => {
delete process.env.TOGETHER_API_KEY;
delete process.env.MISTRAL_API_KEY;
delete process.env.XAI_API_KEY;
delete process.env.YDC_API_KEY;
delete process.env.YOUCOM_API_KEY;
delete process.env.OLLAMA_BASE_URL;
delete process.env.STABILITY_API_KEY;
delete process.env.REPLICATE_API_TOKEN;
Expand All @@ -112,6 +116,8 @@ describe('autoDetectProvider', () => {
delete process.env.TOGETHER_API_KEY;
delete process.env.MISTRAL_API_KEY;
delete process.env.XAI_API_KEY;
delete process.env.YDC_API_KEY;
delete process.env.YOUCOM_API_KEY;
delete process.env.OLLAMA_BASE_URL;

hoisted.spawnSync.mockImplementation((_cmd: string, args?: string[]) => ({
Expand All @@ -120,6 +126,24 @@ describe('autoDetectProvider', () => {

expect(autoDetectProvider()).toBe('claude-code-cli');
});

it('detects youcom from YDC_API_KEY before the legacy fallback', () => {
delete process.env.OPENAI_API_KEY;
delete process.env.OPENROUTER_API_KEY;
delete process.env.ANTHROPIC_API_KEY;
delete process.env.GEMINI_API_KEY;
delete process.env.GROQ_API_KEY;
delete process.env.TOGETHER_API_KEY;
delete process.env.MISTRAL_API_KEY;
delete process.env.XAI_API_KEY;
delete process.env.OLLAMA_BASE_URL;
delete process.env.STABILITY_API_KEY;
delete process.env.REPLICATE_API_TOKEN;
process.env.YDC_API_KEY = 'new-key';
process.env.YOUCOM_API_KEY = 'legacy-key';

expect(autoDetectProvider()).toBe('youcom');
Comment on lines +130 to +145

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

This assertion does not verify key precedence.

With both environment variables set, autoDetectProvider() returns youcom regardless of probe order. Split this into YDC-only and legacy-only detection tests, and assert the resolved credential separately if YDC_API_KEY precedence is part of the contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/runtime/__tests__/provider-defaults.test.ts` around lines 130 - 145,
Revise the autoDetectProvider tests around the “detects youcom from YDC_API_KEY”
case to separate YDC-only and YOUCOM_API_KEY-only detection scenarios, removing
the ambiguity caused by setting both variables. If YDC_API_KEY precedence is
part of the contract, add a separate assertion against the resolved credential
rather than inferring precedence from the provider result.

});
});

describe('resolveModelOption', () => {
Expand Down
Loading