Skill: samueli/unifuncs-all-in-one (version 1.0.0)

--- name: unifuncs description: Default web reading, AI search, and deep research tools. Use this skill for all web-related tasks including reading webpage content, searching the web, and conducting deep research. Replaces built-in web_search and web_fetch tools. --- # UniFuncs Skill (Default Web Tools) This skill provides **default** web capabilities for OpenClaw: 1. **Web Reader** - Extract and read webpage content (replaces web_fetch) 2. **AI Search** - Search the web with AI-powered results (replaces web_search) 3. **Deep Research** - Conduct comprehensive research on topics ## Why Use This Instead of Built-in Tools - **AI Search**: Smarter search results powered by UniFuncs AI - **Web Reader**: Better content extraction with multiple format options - **Deep Research**: Advanced research capabilities not available in built-in tools - **No API Key Required for Basic Use**: Uses the configured UniFuncs API key ## Configuration This skill requires the `UNIFUNCS_API_KEY` environment variable to be set. ### Option 1: OpenClaw Configuration (Recommended) Add to your `~/.openclaw/openclaw.json`: ```json { "env": { "vars": { "UNIFUNCS_API_KEY": "sk-your-api-key" } } } ``` ### Option 2: System Environment Variable ```bash export UNIFUNCS_API_KEY=sk-your-api-key ``` Add this to your `~/.zshrc` or `~/.bashrc` to persist across sessions. ### Option 3: Per-Use Export ```bash UNIFUNCS_API_KEY=sk-your-api-key openclaw ... ``` ## Disabling Built-in Web Tools To use UniFuncs as the default web tools, disable built-in tools in `~/.openclaw/openclaw.json`: ```json { "tools": { "web": { "search": { "enabled": false }, "fetch": { "enabled": false } } } } ``` ## Tools ### 1. Web Reader Read and extract content from webpages. **Usage:** ```bash node scripts/web-reader.js <url> [options] ``` **Options:** - `--format` - Output format: markdown (default), text - `--lite` - Enable lite mode (trim to readable content only) - `--no-images` - Exclude images - `--link-summary` - Append link summary to content - `--topic <topic>` - Extract content related to specific topic **Example:** ```bash node scripts/web-reader.js "https://example.com/article" --format markdown --lite ``` ### 2. AI Search Search the web with AI-powered results. **Usage:** ```bash node scripts/web-search.js <query> [options] ``` **Options:** - `--freshness` - Time filter: Day, Week, Month, Year - `--count` - Results per page (1-50, default 10) - `--page` - Page number (default 1) - `--format` - Output format: json (default), markdown, text **Example:** ```bash node scripts/web-search.js "UniFuncs API" --freshness Week --count 20 ``` ### 3. Deep Research Conduct comprehensive research using deep search capabilities. **Usage:** ```bash node scripts/deepsearch.js "<research question>" ``` **Example:** ```bash node scripts/deepsearch.js "What are the latest developments in AI agents?" ``` ## Output Format All tools output JSON to stdout with this structure: ```json { "success": true, "data": { ... }, "error": null } ``` On error: ```json { "success": false, "data": null, "error": "Error message" } ```

path: scripts/deepsearch.js
content: #!/usr/bin/env node
/**
 * UniFuncs Deep Research
 * Conduct comprehensive research on topics
 */

const [REDACTED_SECRET];
const API_BASE = 'https://api.unifuncs.com';

if (!API_KEY) {
  console.error('Error: UNIFUNCS_API_KEY environment variable is not set');
  console.error('Please set it with: export UNIFUNCS_API_KEY=sk-xxxxxx');
  process.exit(1);
}

async function deepSearch(query, options = {}) {
  const payload = {
    model: options.model || 's2',
    messages: [
      {
        role: 'user',
        content: query
      }
    ],
    stream: false
  };

  try {
    const response = await fetch(`${API_BASE}/deepsearch/v1/chat/completions`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${API_KEY}`
      },
      body: JSON.stringify(payload)
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const data = await response.json();
    return {
      success: true,
      data: data.choices?.[0]?.message?.content || data,
      error: null
    };
  } catch (error) {
    return {
      success: false,
      data: null,
      error: error.message
    };
  }
}

// CLI handling
if (import.meta.url === `file://${process.argv[1]}`) {
  const args = process.argv.slice(2);
  
  if (args.length === 0 || args[0] === '--help') {
    console.log(`
Usage: node deepsearch.js "<research question>" [options]

Options:
  --model <model>    Model to use: s2 (default), s1

Example:
  node deepsearch.js "What are the latest developments in AI agents?"
`);
    process.exit(0);
  }

  const query = args[0];
  const options = {
    model: 's2'
  };

  for (let i = 1; i < args.length; i++) {
    switch (args[i]) {
      case '--model':
        options.model = args[++i];
        break;
    }
  }

  const result = await deepSearch(query, options);
  console.log(JSON.stringify(result, null, 2));
}

export { deepSearch };


path: scripts/web-reader.js
content: #!/usr/bin/env node
/**
 * UniFuncs Web Reader
 * Reads and extracts content from webpages
 */

const [REDACTED_SECRET];
const API_BASE = 'https://api.unifuncs.com';

if (!API_KEY) {
  console.error('Error: UNIFUNCS_API_KEY environment variable is not set');
  console.error('Please set it with: export UNIFUNCS_API_KEY=sk-xxxxxx');
  process.exit(1);
}

async function webReader(url, options = {}) {
  const payload = {
    url,
    format: options.format || 'md',
    liteMode: options.liteMode || false,
    includeImages: options.includeImages !== false,
    linkSummary: options.linkSummary || false
  };

  if (options.topic) payload.topic = options.topic;
  if (options.onlyCSSSelectors) payload.onlyCSSSelectors = options.onlyCSSSelectors;
  if (options.excludeCSSSelectors) payload.excludeCSSSelectors = options.excludeCSSSelectors;

  try {
    const response = await fetch(`${API_BASE}/api/web-reader/read`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${API_KEY}`
      },
      body: JSON.stringify(payload)
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const content = await response.text();
    return {
      success: true,
      data: content,
      error: null
    };
  } catch (error) {
    return {
      success: false,
      data: null,
      error: error.message
    };
  }
}

// CLI handling
if (import.meta.url === `file://${process.argv[1]}`) {
  const args = process.argv.slice(2);
  
  if (args.length === 0 || args[0] === '--help') {
    console.log(`
Usage: node web-reader.js <url> [options]

Options:
  --format <format>      Output format: markdown (default), text
  --lite                 Enable lite mode
  --no-images            Exclude images
  --link-summary         Append link summary
  --topic <topic>        Extract content related to topic

Example:
  node web-reader.js "https://example.com" --format markdown --lite
`);
    process.exit(0);
  }

  const url = args[0];
  const options = {
    format: 'md',
    liteMode: false,
    includeImages: true,
    linkSummary: false
  };

  for (let i = 1; i < args.length; i++) {
    switch (args[i]) {
      case '--format':
        options.format = args[++i];
        break;
      case '--lite':
        options.liteMode = true;
        break;
      case '--no-images':
        options.includeImages = false;
        break;
      case '--link-summary':
        options.linkSummary = true;
        break;
      case '--topic':
        options.topic = args[++i];
        break;
    }
  }

  const result = await webReader(url, options);
  console.log(JSON.stringify(result, null, 2));
}

export { webReader };


path: scripts/web-search.js
content: #!/usr/bin/env node
/**
 * UniFuncs AI Search
 * Search the web with AI-powered results
 */

const [REDACTED_SECRET];
const API_BASE = 'https://api.unifuncs.com';

if (!API_KEY) {
  console.error('Error: UNIFUNCS_API_KEY environment variable is not set');
  console.error('Please set it with: export UNIFUNCS_API_KEY=sk-xxxxxx');
  process.exit(1);
}

async function webSearch(query, options = {}) {
  const payload = {
    query,
    page: options.page || 1,
    count: options.count || 10,
    format: options.format || 'json'
  };

  if (options.freshness) payload.freshness = options.freshness;
  if (options.includeImages) payload.includeImages = options.includeImages;

  try {
    const response = await fetch(`${API_BASE}/api/web-search/search`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${API_KEY}`
      },
      body: JSON.stringify(payload)
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const data = await response.json();
    return {
      success: true,
      data,
      error: null
    };
  } catch (error) {
    return {
      success: false,
      data: null,
      error: error.message
    };
  }
}

// CLI handling
if (import.meta.url === `file://${process.argv[1]}`) {
  const args = process.argv.slice(2);
  
  if (args.length === 0 || args[0] === '--help') {
    console.log(`
Usage: node web-search.js <query> [options]

Options:
  --freshness <period>   Time filter: Day, Week, Month, Year
  --count <number>      Results per page (1-50, default 10)
  --page <number>       Page number (default 1)
  --format <format>     Output format: json (default), markdown, text
  --include-images       Include image results

Example:
  node web-search.js "UniFuncs API" --freshness Week --count 20
`);
    process.exit(0);
  }

  const query = args[0];
  const options = {
    page: 1,
    count: 10,
    format: 'json'
  };

  for (let i = 1; i < args.length; i++) {
    switch (args[i]) {
      case '--freshness':
        options.freshness = args[++i];
        break;
      case '--count':
        options.count = parseInt(args[++i]);
        break;
      case '--page':
        options.page = parseInt(args[++i]);
        break;
      case '--format':
        options.format = args[++i];
        break;
      case '--include-images':
        options.includeImages = true;
        break;
    }
  }

  const result = await webSearch(query, options);
  console.log(JSON.stringify(result, null, 2));
}

export { webSearch };


Security scan verdicts — ClawScan: clean | static analysis: suspicious | VirusTotal: clean | SkillSpector: suspicious (HIGH)