[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M77Q7AMJRHTJ41DFBTP7TSPF":3,"skill-same:01M77Q7AMJRHTJ41DFBTP7TSPF":56},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":15,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":13,"repositoryHtmlUrl":27,"repositoryHomepageUrl":6,"ownerHtmlUrl":28,"ownerBlogUrl":6,"ownerDescription":29,"updatedAt":30,"install":31,"resources":44},"01M77Q7AMJRHTJ41DFBTP7TSPF","web-search",null,"Implement web search capabilities using the z-ai-web-dev-sdk. Use this skill when the user needs to search for real-time information from the web, retrieve up-to-date content beyond the knowledge cutoff, or find the latest news and data. Returns structured search results with URLs, snippets, and metadata.","nordeim\u002Fstory-into-video","nordeim","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F194583642?v=4","01M75CZEV8C3V4DDQNPQ1EA7QJ","01M77NXQ9G1G1YWJMQTCEFSG23",0,"MIT","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fweb-search\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fweb-search\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: web-search\ndescription: Implement web search capabilities using the z-ai-web-dev-sdk. Use this skill when the user needs to search for real-time information from the web, retrieve up-to-date content beyond the knowledge cutoff, or find the latest news and data. Returns structured search results with URLs, snippets, and metadata.\nlicense: MIT\n---\n\n# Web Search Skill\n\nThis skill guides the implementation of web search functionality using the z-ai-web-dev-sdk package, enabling applications to search the web and retrieve current information.\n\n## Installation Path\n\n**Recommended Location**: `{project_path}\u002Fskills\u002Fweb-search`\n\nExtract this skill package to the above path in your project.\n\n**Reference Scripts**: Example test scripts are available in the `{project_path}\u002Fskills\u002Fweb-search\u002Fscripts\u002F` directory for quick testing and reference. See `{project_path}\u002Fskills\u002Fweb-search\u002Fscripts\u002Fweb_search.ts` for a working example.\n\n## Overview\n\nThe Web Search skill allows you to build applications that can search the internet, retrieve current information, and access real-time data from web sources.\n\n**IMPORTANT**: z-ai-web-dev-sdk MUST be used in backend code only. Never use it in client-side code.\n\n## Prerequisites\n\nThe z-ai-web-dev-sdk package is already installed. Import it as shown in the examples below.\n\n## CLI Usage (For Simple Tasks)\n\nFor simple web search queries, you can use the z-ai CLI instead of writing code. This is ideal for quick information retrieval, testing search functionality, or command-line automation.\n\n### Basic Web Search\n\n```bash\n# Simple search query\nz-ai function --name \"web_search\" --args '{\"query\": \"artificial intelligence\"}'\n\n# Using short options\nz-ai function -n web_search -a '{\"query\": \"latest tech news\"}'\n```\n\n### Search with Custom Parameters\n\n```bash\n# Limit number of results\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"machine learning\", \"num\": 5}'\n\n# Search with recency filter (results from last N days)\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"cryptocurrency news\", \"num\": 10, \"recency_days\": 7}'\n```\n\n### Save Search Results\n\n```bash\n# Save results to JSON file\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"climate change research\", \"num\": 5}' \\\n  -o search_results.json\n\n# Recent news with file output\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"AI breakthroughs\", \"num\": 3, \"recency_days\": 1}' \\\n  -o ai_news.json\n```\n\n### Advanced Search Examples\n\n```bash\n# Search for specific topics\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"quantum computing applications\", \"num\": 8}' \\\n  -o quantum.json\n\n# Find recent scientific papers\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"genomics research\", \"num\": 5, \"recency_days\": 30}' \\\n  -o genomics.json\n\n# Technology news from last 24 hours\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"tech industry updates\", \"recency_days\": 1}' \\\n  -o today_tech.json\n```\n\n### CLI Parameters\n\n- `--name, -n`: **Required** - Function name (use \"web_search\")\n- `--args, -a`: **Required** - JSON arguments object with:\n  - `query` (string, required): Search keywords\n  - `num` (number, optional): Number of results (default: 10)\n  - `recency_days` (number, optional): Filter results from last N days\n- `--output, -o \u003Cpath>`: Optional - Output file path (JSON format)\n\n### Search Result Structure\n\nEach result contains:\n- `url`: Full URL of the result\n- `name`: Title of the page\n- `snippet`: Preview text\u002Fdescription\n- `host_name`: Domain name\n- `rank`: Result ranking\n- `date`: Publication\u002Fupdate date\n- `favicon`: Favicon URL\n\n### When to Use CLI vs SDK\n\n**Use CLI for:**\n- Quick information lookups\n- Testing search queries\n- Simple automation scripts\n- One-off research tasks\n\n**Use SDK for:**\n- Dynamic search in applications\n- Multi-step search workflows\n- Custom result processing and filtering\n- Production applications with complex logic\n\n## Search Result Type\n\nEach search result is a `SearchFunctionResultItem` with the following structure:\n\n```typescript\ninterface SearchFunctionResultItem {\n  url: string;          \u002F\u002F Full URL of the result\n  name: string;         \u002F\u002F Title of the page\n  snippet: string;      \u002F\u002F Preview text\u002Fdescription\n  host_name: string;    \u002F\u002F Domain name\n  rank: number;         \u002F\u002F Result ranking\n  date: string;         \u002F\u002F Publication\u002Fupdate date\n  favicon: string;      \u002F\u002F Favicon URL\n}\n```\n\n## Basic Web Search\n\n### Simple Search Query\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function searchWeb(query) {\n  const zai = await ZAI.create();\n\n  const results = await zai.functions.invoke('web_search', {\n    query: query,\n    num: 10\n  });\n\n  return results;\n}\n\n\u002F\u002F Usage\nconst searchResults = await searchWeb('What is the capital of France?');\nconsole.log('Search Results:', searchResults);\n```\n\n### Search with Custom Result Count\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function searchWithLimit(query, numberOfResults) {\n  const zai = await ZAI.create();\n\n  const results = await zai.functions.invoke('web_search', {\n    query: query,\n    num: numberOfResults\n  });\n\n  return results;\n}\n\n\u002F\u002F Usage - Get top 5 results\nconst topResults = await searchWithLimit('artificial intelligence news', 5);\n\n\u002F\u002F Usage - Get top 20 results\nconst moreResults = await searchWithLimit('JavaScript frameworks', 20);\n```\n\n### Formatted Search Results\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function getFormattedResults(query) {\n  const zai = await ZAI.create();\n\n  const results = await zai.functions.invoke('web_search', {\n    query: query,\n    num: 10\n  });\n\n  \u002F\u002F Format results for display\n  const formatted = results.map((item, index) => ({\n    position: index + 1,\n    title: item.name,\n    url: item.url,\n    description: item.snippet,\n    domain: item.host_name,\n    publishDate: item.date\n  }));\n\n  return formatted;\n}\n\n\u002F\u002F Usage\nconst results = await getFormattedResults('climate change solutions');\nresults.forEach(result => {\n  console.log(`${result.position}. ${result.title}`);\n  console.log(`   ${result.url}`);\n  console.log(`   ${result.description}`);\n  console.log('');\n});\n```\n\n## Advanced Use Cases\n\n### Search with Result Processing\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nclass SearchProcessor {\n  constructor() {\n    this.zai = null;\n  }\n\n  async initialize() {\n    this.zai = await ZAI.create();\n  }\n\n  async search(query, options = {}) {\n    const {\n      num = 10,\n      filterDomain = null,\n      minSnippetLength = 0\n    } = options;\n\n    const results = await this.zai.functions.invoke('web_search', {\n      query: query,\n      num: num\n    });\n\n    \u002F\u002F Filter results\n    let filtered = results;\n\n    if (filterDomain) {\n      filtered = filtered.filter(item => \n        item.host_name.includes(filterDomain)\n      );\n    }\n\n    if (minSnippetLength > 0) {\n      filtered = filtered.filter(item => \n        item.snippet.length >= minSnippetLength\n      );\n    }\n\n    return filtered;\n  }\n\n  extractDomains(results) {\n    return [...new Set(results.map(item => item.host_name))];\n  }\n\n  groupByDomain(results) {\n    const grouped = {};\n    \n    results.forEach(item => {\n      if (!grouped[item.host_name]) {\n        grouped[item.host_name] = [];\n      }\n      grouped[item.host_name].push(item);\n    });\n\n    return grouped;\n  }\n\n  sortByDate(results, ascending = false) {\n    return results.sort((a, b) => {\n      const dateA = new Date(a.date);\n      const dateB = new Date(b.date);\n      return ascending ? dateA - dateB : dateB - dateA;\n    });\n  }\n}\n\n\u002F\u002F Usage\nconst processor = new SearchProcessor();\nawait processor.initialize();\n\nconst results = await processor.search('machine learning tutorials', {\n  num: 15,\n  minSnippetLength: 50\n});\n\nconsole.log('Domains found:', processor.extractDomains(results));\nconsole.log('Grouped by domain:', processor.groupByDomain(results));\nconsole.log('Sorted by date:', processor.sortByDate(results));\n```\n\n### News Search\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function searchNews(topic, timeframe = 'recent') {\n  const zai = await ZAI.create();\n\n  \u002F\u002F Add time-based keywords to query\n  const timeKeywords = {\n    recent: 'latest news',\n    today: 'today news',\n    week: 'this week news',\n    month: 'this month news'\n  };\n\n  const query = `${topic} ${timeKeywords[timeframe] || timeKeywords.recent}`;\n\n  const results = await zai.functions.invoke('web_search', {\n    query: query,\n    num: 10\n  });\n\n  \u002F\u002F Sort by date (most recent first)\n  const sortedResults = results.sort((a, b) => {\n    return new Date(b.date) - new Date(a.date);\n  });\n\n  return sortedResults;\n}\n\n\u002F\u002F Usage\nconst aiNews = await searchNews('artificial intelligence', 'today');\nconst techNews = await searchNews('technology', 'week');\n\nconsole.log('Latest AI News:');\naiNews.forEach(item => {\n  console.log(`${item.name} (${item.date})`);\n  console.log(`${item.snippet}\\n`);\n});\n```\n\n### Research Assistant\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nclass ResearchAssistant {\n  constructor() {\n    this.zai = null;\n  }\n\n  async initialize() {\n    this.zai = await ZAI.create();\n  }\n\n  async researchTopic(topic, depth = 'standard') {\n    const numResults = {\n      quick: 5,\n      standard: 10,\n      deep: 20\n    };\n\n    const results = await this.zai.functions.invoke('web_search', {\n      query: topic,\n      num: numResults[depth] || 10\n    });\n\n    \u002F\u002F Analyze results\n    const analysis = {\n      topic: topic,\n      totalResults: results.length,\n      sources: this.extractDomains(results),\n      topResults: results.slice(0, 5).map(r => ({\n        title: r.name,\n        url: r.url,\n        summary: r.snippet\n      })),\n      dateRange: this.getDateRange(results)\n    };\n\n    return analysis;\n  }\n\n  extractDomains(results) {\n    const domains = {};\n    results.forEach(item => {\n      domains[item.host_name] = (domains[item.host_name] || 0) + 1;\n    });\n    return domains;\n  }\n\n  getDateRange(results) {\n    const dates = results\n      .map(r => new Date(r.date))\n      .filter(d => !isNaN(d));\n\n    if (dates.length === 0) return null;\n\n    return {\n      earliest: new Date(Math.min(...dates)),\n      latest: new Date(Math.max(...dates))\n    };\n  }\n\n  async compareTopics(topic1, topic2) {\n    const [results1, results2] = await Promise.all([\n      this.zai.functions.invoke('web_search', { query: topic1, num: 10 }),\n      this.zai.functions.invoke('web_search', { query: topic2, num: 10 })\n    ]);\n\n    const domains1 = new Set(results1.map(r => r.host_name));\n    const domains2 = new Set(results2.map(r => r.host_name));\n\n    const commonDomains = [...domains1].filter(d => domains2.has(d));\n\n    return {\n      topic1: {\n        name: topic1,\n        results: results1.length,\n        uniqueDomains: domains1.size\n      },\n      topic2: {\n        name: topic2,\n        results: results2.length,\n        uniqueDomains: domains2.size\n      },\n      commonDomains: commonDomains\n    };\n  }\n}\n\n\u002F\u002F Usage\nconst assistant = new ResearchAssistant();\nawait assistant.initialize();\n\nconst research = await assistant.researchTopic('quantum computing', 'deep');\nconsole.log('Research Analysis:', research);\n\nconst comparison = await assistant.compareTopics(\n  'renewable energy',\n  'solar power'\n);\nconsole.log('Topic Comparison:', comparison);\n```\n\n### Search Result Validation\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function validateSearchResults(query) {\n  const zai = await ZAI.create();\n\n  const results = await zai.functions.invoke('web_search', {\n    query: query,\n    num: 10\n  });\n\n  \u002F\u002F Validate and score results\n  const validated = results.map(item => {\n    let score = 0;\n    let flags = [];\n\n    \u002F\u002F Check snippet quality\n    if (item.snippet && item.snippet.length > 50) {\n      score += 20;\n    } else {\n      flags.push('short_snippet');\n    }\n\n    \u002F\u002F Check date availability\n    if (item.date && item.date !== 'N\u002FA') {\n      score += 20;\n    } else {\n      flags.push('no_date');\n    }\n\n    \u002F\u002F Check URL validity\n    try {\n      new URL(item.url);\n      score += 20;\n    } catch (e) {\n      flags.push('invalid_url');\n    }\n\n    \u002F\u002F Check domain quality (not perfect, but basic check)\n    if (!item.host_name.includes('spam') && \n        !item.host_name.includes('ads')) {\n      score += 20;\n    } else {\n      flags.push('suspicious_domain');\n    }\n\n    \u002F\u002F Check title quality\n    if (item.name && item.name.length > 10) {\n      score += 20;\n    } else {\n      flags.push('short_title');\n    }\n\n    return {\n      ...item,\n      qualityScore: score,\n      validationFlags: flags,\n      isHighQuality: score >= 80\n    };\n  });\n\n  \u002F\u002F Sort by quality score\n  return validated.sort((a, b) => b.qualityScore - a.qualityScore);\n}\n\n\u002F\u002F Usage\nconst validated = await validateSearchResults('best programming practices');\nconsole.log('High quality results:', \n  validated.filter(r => r.isHighQuality).length\n);\n```\n\n## Best Practices\n\n### 1. Query Optimization\n\n```javascript\n\u002F\u002F Bad: Too vague\nconst bad = await searchWeb('information');\n\n\u002F\u002F Good: Specific and targeted\nconst good = await searchWeb('JavaScript async\u002Fawait best practices 2024');\n\n\u002F\u002F Good: Include context\nconst goodWithContext = await searchWeb('React hooks tutorial for beginners');\n```\n\n### 2. Error Handling\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function safeSearch(query, retries = 3) {\n  let lastError;\n\n  for (let attempt = 1; attempt \u003C= retries; attempt++) {\n    try {\n      const zai = await ZAI.create();\n\n      const results = await zai.functions.invoke('web_search', {\n        query: query,\n        num: 10\n      });\n\n      if (!Array.isArray(results) || results.length === 0) {\n        throw new Error('No results found or invalid response');\n      }\n\n      return {\n        success: true,\n        results: results,\n        attempts: attempt\n      };\n    } catch (error) {\n      lastError = error;\n      console.error(`Attempt ${attempt} failed:`, error.message);\n\n      if (attempt \u003C retries) {\n        \u002F\u002F Wait before retry (exponential backoff)\n        await new Promise(resolve => setTimeout(resolve, 1000 * attempt));\n      }\n    }\n  }\n\n  return {\n    success: false,\n    error: lastError.message,\n    attempts: retries\n  };\n}\n```\n\n### 3. Result Caching\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nclass CachedSearch {\n  constructor(cacheDuration = 3600000) { \u002F\u002F 1 hour default\n    this.cache = new Map();\n    this.cacheDuration = cacheDuration;\n    this.zai = null;\n  }\n\n  async initialize() {\n    this.zai = await ZAI.create();\n  }\n\n  getCacheKey(query, num) {\n    return `${query}_${num}`;\n  }\n\n  async search(query, num = 10) {\n    const cacheKey = this.getCacheKey(query, num);\n    const cached = this.cache.get(cacheKey);\n\n    \u002F\u002F Check if cached and not expired\n    if (cached && Date.now() - cached.timestamp \u003C this.cacheDuration) {\n      console.log('Returning cached results');\n      return {\n        ...cached.data,\n        cached: true\n      };\n    }\n\n    \u002F\u002F Perform fresh search\n    const results = await this.zai.functions.invoke('web_search', {\n      query: query,\n      num: num\n    });\n\n    \u002F\u002F Cache results\n    this.cache.set(cacheKey, {\n      data: results,\n      timestamp: Date.now()\n    });\n\n    return {\n      results: results,\n      cached: false\n    };\n  }\n\n  clearCache() {\n    this.cache.clear();\n  }\n\n  getCacheSize() {\n    return this.cache.size;\n  }\n}\n\n\u002F\u002F Usage\nconst search = new CachedSearch(1800000); \u002F\u002F 30 minutes cache\nawait search.initialize();\n\nconst result1 = await search.search('TypeScript tutorial');\nconsole.log('Cached:', result1.cached); \u002F\u002F false\n\nconst result2 = await search.search('TypeScript tutorial');\nconsole.log('Cached:', result2.cached); \u002F\u002F true\n```\n\n### 4. Rate Limiting\n\n```javascript\nclass RateLimitedSearch {\n  constructor(requestsPerMinute = 60) {\n    this.zai = null;\n    this.requestsPerMinute = requestsPerMinute;\n    this.requests = [];\n  }\n\n  async initialize() {\n    this.zai = await ZAI.create();\n  }\n\n  async search(query, num = 10) {\n    await this.checkRateLimit();\n\n    const results = await this.zai.functions.invoke('web_search', {\n      query: query,\n      num: num\n    });\n\n    this.requests.push(Date.now());\n    return results;\n  }\n\n  async checkRateLimit() {\n    const now = Date.now();\n    const oneMinuteAgo = now - 60000;\n\n    \u002F\u002F Remove requests older than 1 minute\n    this.requests = this.requests.filter(time => time > oneMinuteAgo);\n\n    if (this.requests.length >= this.requestsPerMinute) {\n      const oldestRequest = this.requests[0];\n      const waitTime = 60000 - (now - oldestRequest);\n      \n      console.log(`Rate limit reached. Waiting ${waitTime}ms`);\n      await new Promise(resolve => setTimeout(resolve, waitTime));\n      \n      \u002F\u002F Recheck after waiting\n      return this.checkRateLimit();\n    }\n  }\n}\n```\n\n## Common Use Cases\n\n1. **Real-time Information Retrieval**: Get current news, stock prices, weather\n2. **Research & Analysis**: Gather information on specific topics\n3. **Content Discovery**: Find articles, tutorials, documentation\n4. **Competitive Analysis**: Research competitors and market trends\n5. **Fact Checking**: Verify information against web sources\n6. **SEO & Content Research**: Analyze search results for content strategy\n7. **News Aggregation**: Collect news from various sources\n8. **Academic Research**: Find papers, studies, and academic content\n\n## Integration Examples\n\n### Express.js Search API\n\n```javascript\nimport express from 'express';\nimport ZAI from 'z-ai-web-dev-sdk';\n\nconst app = express();\napp.use(express.json());\n\nlet zaiInstance;\n\nasync function initZAI() {\n  zaiInstance = await ZAI.create();\n}\n\napp.get('\u002Fapi\u002Fsearch', async (req, res) => {\n  try {\n    const { q: query, num = 10 } = req.query;\n\n    if (!query) {\n      return res.status(400).json({ error: 'Query parameter \"q\" is required' });\n    }\n\n    const numResults = Math.min(parseInt(num) || 10, 20);\n\n    const results = await zaiInstance.functions.invoke('web_search', {\n      query: query,\n      num: numResults\n    });\n\n    res.json({\n      success: true,\n      query: query,\n      totalResults: results.length,\n      results: results\n    });\n  } catch (error) {\n    res.status(500).json({\n      success: false,\n      error: error.message\n    });\n  }\n});\n\napp.get('\u002Fapi\u002Fsearch\u002Fnews', async (req, res) => {\n  try {\n    const { topic, timeframe = 'recent' } = req.query;\n\n    if (!topic) {\n      return res.status(400).json({ error: 'Topic parameter is required' });\n    }\n\n    const timeKeywords = {\n      recent: 'latest news',\n      today: 'today news',\n      week: 'this week news'\n    };\n\n    const query = `${topic} ${timeKeywords[timeframe] || timeKeywords.recent}`;\n\n    const results = await zaiInstance.functions.invoke('web_search', {\n      query: query,\n      num: 15\n    });\n\n    \u002F\u002F Sort by date\n    const sortedResults = results.sort((a, b) => {\n      return new Date(b.date) - new Date(a.date);\n    });\n\n    res.json({\n      success: true,\n      topic: topic,\n      timeframe: timeframe,\n      results: sortedResults\n    });\n  } catch (error) {\n    res.status(500).json({\n      success: false,\n      error: error.message\n    });\n  }\n});\n\ninitZAI().then(() => {\n  app.listen(3000, () => {\n    console.log('Search API running on port 3000');\n  });\n});\n```\n\n### Search with AI Summary\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function searchAndSummarize(query) {\n  const zai = await ZAI.create();\n\n  \u002F\u002F Step 1: Search the web\n  const searchResults = await zai.functions.invoke('web_search', {\n    query: query,\n    num: 10\n  });\n\n  \u002F\u002F Step 2: Create summary using chat completions\n  const searchContext = searchResults\n    .slice(0, 5)\n    .map((r, i) => `${i + 1}. ${r.name}\\n${r.snippet}`)\n    .join('\\n\\n');\n\n  const completion = await zai.chat.completions.create({\n    messages: [\n      {\n        role: 'assistant',\n        content: 'You are a research assistant. Summarize search results clearly and concisely.'\n      },\n      {\n        role: 'user',\n        content: `Query: \"${query}\"\\n\\nSearch Results:\\n${searchContext}\\n\\nProvide a comprehensive summary of these results.`\n      }\n    ],\n    thinking: { type: 'disabled' }\n  });\n\n  const summary = completion.choices[0]?.message?.content;\n\n  return {\n    query: query,\n    summary: summary,\n    sources: searchResults.slice(0, 5).map(r => ({\n      title: r.name,\n      url: r.url\n    })),\n    totalResults: searchResults.length\n  };\n}\n\n\u002F\u002F Usage\nconst result = await searchAndSummarize('benefits of renewable energy');\nconsole.log('Summary:', result.summary);\nconsole.log('Sources:', result.sources);\n```\n\n## Troubleshooting\n\n**Issue**: \"SDK must be used in backend\"\n- **Solution**: Ensure z-ai-web-dev-sdk is only imported and used in server-side code\n\n**Issue**: Empty or no results returned\n- **Solution**: Try different query terms, check internet connectivity, verify API status\n\n**Issue**: Unexpected response format\n- **Solution**: Verify the response is an array, check for API changes, add type validation\n\n**Issue**: Rate limiting errors\n- **Solution**: Implement request throttling, add delays between searches, use caching\n\n**Issue**: Low quality search results\n- **Solution**: Refine query terms, filter results by domain or date, validate result quality\n\n## Performance Tips\n\n1. **Reuse SDK Instance**: Create ZAI instance once and reuse across searches\n2. **Implement Caching**: Cache search results to reduce API calls\n3. **Optimize Query Terms**: Use specific, targeted queries for better results\n4. **Limit Result Count**: Request only the number of results you need\n5. **Parallel Searches**: Use Promise.all for multiple independent searches\n6. **Result Filtering**: Filter results on client side when possible\n\n## Security Considerations\n\n1. **Input Validation**: Sanitize and validate user search queries\n2. **Rate Limiting**: Implement rate limits to prevent abuse\n3. **API Key Protection**: Never expose SDK credentials in client-side code\n4. **Result Filtering**: Filter potentially harmful or inappropriate content\n5. **URL Validation**: Validate URLs before redirecting users\n6. **Privacy**: Don't log sensitive user search queries\n\n## Remember\n\n- Always use z-ai-web-dev-sdk in backend code only\n- The SDK is already installed - import as shown in examples\n- Search results are returned as an array of SearchFunctionResultItem objects\n- Implement proper error handling and retries for production\n- Cache results when appropriate to reduce API calls\n- Use specific query terms for better search results\n- Validate and filter results before displaying to users\n- Check `scripts\u002Fweb_search.ts` for a quick start example\n","# Web Search Skill\n\nThis skill guides the implementation of web search functionality using the z-ai-web-dev-sdk package, enabling applications to search the web and retrieve current information.\n\n## Installation Path\n\n**Recommended Location**: `{project_path}\u002Fskills\u002Fweb-search`\n\nExtract this skill package to the above path in your project.\n\n**Reference Scripts**: Example test scripts are available in the `{project_path}\u002Fskills\u002Fweb-search\u002Fscripts\u002F` directory for quick testing and reference. See `{project_path}\u002Fskills\u002Fweb-search\u002Fscripts\u002Fweb_search.ts` for a working example.\n\n## Overview\n\nThe Web Search skill allows you to build applications that can search the internet, retrieve current information, and access real-time data from web sources.\n\n**IMPORTANT**: z-ai-web-dev-sdk MUST be used in backend code only. Never use it in client-side code.\n\n## Prerequisites\n\nThe z-ai-web-dev-sdk package is already installed. Import it as shown in the examples below.\n\n## CLI Usage (For Simple Tasks)\n\nFor simple web search queries, you can use the z-ai CLI instead of writing code. This is ideal for quick information retrieval, testing search functionality, or command-line automation.\n\n### Basic Web Search\n\n```bash\n# Simple search query\nz-ai function --name \"web_search\" --args '{\"query\": \"artificial intelligence\"}'\n\n# Using short options\nz-ai function -n web_search -a '{\"query\": \"latest tech news\"}'\n```\n\n### Search with Custom Parameters\n\n```bash\n# Limit number of results\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"machine learning\", \"num\": 5}'\n\n# Search with recency filter (results from last N days)\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"cryptocurrency news\", \"num\": 10, \"recency_days\": 7}'\n```\n\n### Save Search Results\n\n```bash\n# Save results to JSON file\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"climate change research\", \"num\": 5}' \\\n  -o search_results.json\n\n# Recent news with file output\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"AI breakthroughs\", \"num\": 3, \"recency_days\": 1}' \\\n  -o ai_news.json\n```\n\n### Advanced Search Examples\n\n```bash\n# Search for specific topics\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"quantum computing applications\", \"num\": 8}' \\\n  -o quantum.json\n\n# Find recent scientific papers\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"genomics research\", \"num\": 5, \"recency_days\": 30}' \\\n  -o genomics.json\n\n# Technology news from last 24 hours\nz-ai function \\\n  -n web_search \\\n  -a '{\"query\": \"tech industry updates\", \"recency_days\": 1}' \\\n  -o today_tech.json\n```\n\n### CLI Parameters\n\n- `--name, -n`: **Required** - Function name (use \"web_search\")\n- `--args, -a`: **Required** - JSON arguments object with:\n  - `query` (string, required): Search keywords\n  - `num` (number, optional): Number of results (default: 10)\n  - `recency_days` (number, optional): Filter results from last N days\n- `--output, -o \u003Cpath>`: Optional - Output file path (JSON format)\n\n### Search Result Structure\n\nEach result contains:\n- `url`: Full URL of the result\n- `name`: Title of the page\n- `snippet`: Preview text\u002Fdescription\n- `host_name`: Domain name\n- `rank`: Result ranking\n- `date`: Publication\u002Fupdate date\n- `favicon`: Favicon URL\n\n### When to Use CLI vs SDK\n\n**Use CLI for:**\n- Quick information lookups\n- Testing search queries\n- Simple automation scripts\n- One-off research tasks\n\n**Use SDK for:**\n- Dynamic search in applications\n- Multi-step search workflows\n- Custom result processing and filtering\n- Production applications with complex logic\n\n## Search Result Type\n\nEach search result is a `SearchFunctionResultItem` with the following structure:\n\n```typescript\ninterface SearchFunctionResultItem {\n  url: string;          \u002F\u002F Full URL of the result\n  name: string;         \u002F\u002F Title of the page\n  snippet: string;      \u002F\u002F Preview text\u002Fdescription\n  host_name: string;    \u002F\u002F Domain name\n  rank: number;         \u002F\u002F Result ranking\n  date: string;         \u002F\u002F Publication\u002Fupdate date\n  favicon: string;      \u002F\u002F Favicon URL\n}\n```\n\n## Basic Web Search\n\n### Simple Search Query\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function searchWeb(query) {\n  const zai = await ZAI.create();\n\n  const results = await zai.functions.invoke('web_search', {\n    query: query,\n    num: 10\n  });\n\n  return results;\n}\n\n\u002F\u002F Usage\nconst searchResults = await searchWeb('What is the capital of France?');\nconsole.log('Search Results:', searchResults);\n```\n\n### Search with Custom Result Count\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function searchWithLimit(query, numberOfResults) {\n  const zai = await ZAI.create();\n\n  const results = await zai.functions.invoke('web_search', {\n    query: query,\n    num: numberOfResults\n  });\n\n  return results;\n}\n\n\u002F\u002F Usage - Get top 5 results\nconst topResults = await searchWithLimit('artificial intelligence news', 5);\n\n\u002F\u002F Usage - Get top 20 results\nconst moreResults = await searchWithLimit('JavaScript frameworks', 20);\n```\n\n### Formatted Search Results\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function getFormattedResults(query) {\n  const zai = await ZAI.create();\n\n  const results = await zai.functions.invoke('web_search', {\n    query: query,\n    num: 10\n  });\n\n  \u002F\u002F Format results for display\n  const formatted = results.map((item, index) => ({\n    position: index + 1,\n    title: item.name,\n    url: item.url,\n    description: item.snippet,\n    domain: item.host_name,\n    publishDate: item.date\n  }));\n\n  return formatted;\n}\n\n\u002F\u002F Usage\nconst results = await getFormattedResults('climate change solutions');\nresults.forEach(result => {\n  console.log(`${result.position}. ${result.title}`);\n  console.log(`   ${result.url}`);\n  console.log(`   ${result.description}`);\n  console.log('');\n});\n```\n\n## Advanced Use Cases\n\n### Search with Result Processing\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nclass SearchProcessor {\n  constructor() {\n    this.zai = null;\n  }\n\n  async initialize() {\n    this.zai = await ZAI.create();\n  }\n\n  async search(query, options = {}) {\n    const {\n      num = 10,\n      filterDomain = null,\n      minSnippetLength = 0\n    } = options;\n\n    const results = await this.zai.functions.invoke('web_search', {\n      query: query,\n      num: num\n    });\n\n    \u002F\u002F Filter results\n    let filtered = results;\n\n    if (filterDomain) {\n      filtered = filtered.filter(item => \n        item.host_name.includes(filterDomain)\n      );\n    }\n\n    if (minSnippetLength > 0) {\n      filtered = filtered.filter(item => \n        item.snippet.length >= minSnippetLength\n      );\n    }\n\n    return filtered;\n  }\n\n  extractDomains(results) {\n    return [...new Set(results.map(item => item.host_name))];\n  }\n\n  groupByDomain(results) {\n    const grouped = {};\n    \n    results.forEach(item => {\n      if (!grouped[item.host_name]) {\n        grouped[item.host_name] = [];\n      }\n      grouped[item.host_name].push(item);\n    });\n\n    return grouped;\n  }\n\n  sortByDate(results, ascending = false) {\n    return results.sort((a, b) => {\n      const dateA = new Date(a.date);\n      const dateB = new Date(b.date);\n      return ascending ? dateA - dateB : dateB - dateA;\n    });\n  }\n}\n\n\u002F\u002F Usage\nconst processor = new SearchProcessor();\nawait processor.initialize();\n\nconst results = await processor.search('machine learning tutorials', {\n  num: 15,\n  minSnippetLength: 50\n});\n\nconsole.log('Domains found:', processor.extractDomains(results));\nconsole.log('Grouped by domain:', processor.groupByDomain(results));\nconsole.log('Sorted by date:', processor.sortByDate(results));\n```\n\n### News Search\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function searchNews(topic, timeframe = 'recent') {\n  const zai = await ZAI.create();\n\n  \u002F\u002F Add time-based keywords to query\n  const timeKeywords = {\n    recent: 'latest news',\n    today: 'today news',\n    week: 'this week news',\n    month: 'this month news'\n  };\n\n  const query = `${topic} ${timeKeywords[timeframe] || timeKeywords.recent}`;\n\n  const results = await zai.functions.invoke('web_search', {\n    query: query,\n    num: 10\n  });\n\n  \u002F\u002F Sort by date (most recent first)\n  const sortedResults = results.sort((a, b) => {\n    return new Date(b.date) - new Date(a.date);\n  });\n\n  return sortedResults;\n}\n\n\u002F\u002F Usage\nconst aiNews = await searchNews('artificial intelligence', 'today');\nconst techNews = await searchNews('technology', 'week');\n\nconsole.log('Latest AI News:');\naiNews.forEach(item => {\n  console.log(`${item.name} (${item.date})`);\n  console.log(`${item.snippet}\\n`);\n});\n```\n\n### Research Assistant\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nclass ResearchAssistant {\n  constructor() {\n    this.zai = null;\n  }\n\n  async initialize() {\n    this.zai = await ZAI.create();\n  }\n\n  async researchTopic(topic, depth = 'standard') {\n    const numResults = {\n      quick: 5,\n      standard: 10,\n      deep: 20\n    };\n\n    const results = await this.zai.functions.invoke('web_search', {\n      query: topic,\n      num: numResults[depth] || 10\n    });\n\n    \u002F\u002F Analyze results\n    const analysis = {\n      topic: topic,\n      totalResults: results.length,\n      sources: this.extractDomains(results),\n      topResults: results.slice(0, 5).map(r => ({\n        title: r.name,\n        url: r.url,\n        summary: r.snippet\n      })),\n      dateRange: this.getDateRange(results)\n    };\n\n    return analysis;\n  }\n\n  extractDomains(results) {\n    const domains = {};\n    results.forEach(item => {\n      domains[item.host_name] = (domains[item.host_name] || 0) + 1;\n    });\n    return domains;\n  }\n\n  getDateRange(results) {\n    const dates = results\n      .map(r => new Date(r.date))\n      .filter(d => !isNaN(d));\n\n    if (dates.length === 0) return null;\n\n    return {\n      earliest: new Date(Math.min(...dates)),\n      latest: new Date(Math.max(...dates))\n    };\n  }\n\n  async compareTopics(topic1, topic2) {\n    const [results1, results2] = await Promise.all([\n      this.zai.functions.invoke('web_search', { query: topic1, num: 10 }),\n      this.zai.functions.invoke('web_search', { query: topic2, num: 10 })\n    ]);\n\n    const domains1 = new Set(results1.map(r => r.host_name));\n    const domains2 = new Set(results2.map(r => r.host_name));\n\n    const commonDomains = [...domains1].filter(d => domains2.has(d));\n\n    return {\n      topic1: {\n        name: topic1,\n        results: results1.length,\n        uniqueDomains: domains1.size\n      },\n      topic2: {\n        name: topic2,\n        results: results2.length,\n        uniqueDomains: domains2.size\n      },\n      commonDomains: commonDomains\n    };\n  }\n}\n\n\u002F\u002F Usage\nconst assistant = new ResearchAssistant();\nawait assistant.initialize();\n\nconst research = await assistant.researchTopic('quantum computing', 'deep');\nconsole.log('Research Analysis:', research);\n\nconst comparison = await assistant.compareTopics(\n  'renewable energy',\n  'solar power'\n);\nconsole.log('Topic Comparison:', comparison);\n```\n\n### Search Result Validation\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function validateSearchResults(query) {\n  const zai = await ZAI.create();\n\n  const results = await zai.functions.invoke('web_search', {\n    query: query,\n    num: 10\n  });\n\n  \u002F\u002F Validate and score results\n  const validated = results.map(item => {\n    let score = 0;\n    let flags = [];\n\n    \u002F\u002F Check snippet quality\n    if (item.snippet && item.snippet.length > 50) {\n      score += 20;\n    } else {\n      flags.push('short_snippet');\n    }\n\n    \u002F\u002F Check date availability\n    if (item.date && item.date !== 'N\u002FA') {\n      score += 20;\n    } else {\n      flags.push('no_date');\n    }\n\n    \u002F\u002F Check URL validity\n    try {\n      new URL(item.url);\n      score += 20;\n    } catch (e) {\n      flags.push('invalid_url');\n    }\n\n    \u002F\u002F Check domain quality (not perfect, but basic check)\n    if (!item.host_name.includes('spam') && \n        !item.host_name.includes('ads')) {\n      score += 20;\n    } else {\n      flags.push('suspicious_domain');\n    }\n\n    \u002F\u002F Check title quality\n    if (item.name && item.name.length > 10) {\n      score += 20;\n    } else {\n      flags.push('short_title');\n    }\n\n    return {\n      ...item,\n      qualityScore: score,\n      validationFlags: flags,\n      isHighQuality: score >= 80\n    };\n  });\n\n  \u002F\u002F Sort by quality score\n  return validated.sort((a, b) => b.qualityScore - a.qualityScore);\n}\n\n\u002F\u002F Usage\nconst validated = await validateSearchResults('best programming practices');\nconsole.log('High quality results:', \n  validated.filter(r => r.isHighQuality).length\n);\n```\n\n## Best Practices\n\n### 1. Query Optimization\n\n```javascript\n\u002F\u002F Bad: Too vague\nconst bad = await searchWeb('information');\n\n\u002F\u002F Good: Specific and targeted\nconst good = await searchWeb('JavaScript async\u002Fawait best practices 2024');\n\n\u002F\u002F Good: Include context\nconst goodWithContext = await searchWeb('React hooks tutorial for beginners');\n```\n\n### 2. Error Handling\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function safeSearch(query, retries = 3) {\n  let lastError;\n\n  for (let attempt = 1; attempt \u003C= retries; attempt++) {\n    try {\n      const zai = await ZAI.create();\n\n      const results = await zai.functions.invoke('web_search', {\n        query: query,\n        num: 10\n      });\n\n      if (!Array.isArray(results) || results.length === 0) {\n        throw new Error('No results found or invalid response');\n      }\n\n      return {\n        success: true,\n        results: results,\n        attempts: attempt\n      };\n    } catch (error) {\n      lastError = error;\n      console.error(`Attempt ${attempt} failed:`, error.message);\n\n      if (attempt \u003C retries) {\n        \u002F\u002F Wait before retry (exponential backoff)\n        await new Promise(resolve => setTimeout(resolve, 1000 * attempt));\n      }\n    }\n  }\n\n  return {\n    success: false,\n    error: lastError.message,\n    attempts: retries\n  };\n}\n```\n\n### 3. Result Caching\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nclass CachedSearch {\n  constructor(cacheDuration = 3600000) { \u002F\u002F 1 hour default\n    this.cache = new Map();\n    this.cacheDuration = cacheDuration;\n    this.zai = null;\n  }\n\n  async initialize() {\n    this.zai = await ZAI.create();\n  }\n\n  getCacheKey(query, num) {\n    return `${query}_${num}`;\n  }\n\n  async search(query, num = 10) {\n    const cacheKey = this.getCacheKey(query, num);\n    const cached = this.cache.get(cacheKey);\n\n    \u002F\u002F Check if cached and not expired\n    if (cached && Date.now() - cached.timestamp \u003C this.cacheDuration) {\n      console.log('Returning cached results');\n      return {\n        ...cached.data,\n        cached: true\n      };\n    }\n\n    \u002F\u002F Perform fresh search\n    const results = await this.zai.functions.invoke('web_search', {\n      query: query,\n      num: num\n    });\n\n    \u002F\u002F Cache results\n    this.cache.set(cacheKey, {\n      data: results,\n      timestamp: Date.now()\n    });\n\n    return {\n      results: results,\n      cached: false\n    };\n  }\n\n  clearCache() {\n    this.cache.clear();\n  }\n\n  getCacheSize() {\n    return this.cache.size;\n  }\n}\n\n\u002F\u002F Usage\nconst search = new CachedSearch(1800000); \u002F\u002F 30 minutes cache\nawait search.initialize();\n\nconst result1 = await search.search('TypeScript tutorial');\nconsole.log('Cached:', result1.cached); \u002F\u002F false\n\nconst result2 = await search.search('TypeScript tutorial');\nconsole.log('Cached:', result2.cached); \u002F\u002F true\n```\n\n### 4. Rate Limiting\n\n```javascript\nclass RateLimitedSearch {\n  constructor(requestsPerMinute = 60) {\n    this.zai = null;\n    this.requestsPerMinute = requestsPerMinute;\n    this.requests = [];\n  }\n\n  async initialize() {\n    this.zai = await ZAI.create();\n  }\n\n  async search(query, num = 10) {\n    await this.checkRateLimit();\n\n    const results = await this.zai.functions.invoke('web_search', {\n      query: query,\n      num: num\n    });\n\n    this.requests.push(Date.now());\n    return results;\n  }\n\n  async checkRateLimit() {\n    const now = Date.now();\n    const oneMinuteAgo = now - 60000;\n\n    \u002F\u002F Remove requests older than 1 minute\n    this.requests = this.requests.filter(time => time > oneMinuteAgo);\n\n    if (this.requests.length >= this.requestsPerMinute) {\n      const oldestRequest = this.requests[0];\n      const waitTime = 60000 - (now - oldestRequest);\n      \n      console.log(`Rate limit reached. Waiting ${waitTime}ms`);\n      await new Promise(resolve => setTimeout(resolve, waitTime));\n      \n      \u002F\u002F Recheck after waiting\n      return this.checkRateLimit();\n    }\n  }\n}\n```\n\n## Common Use Cases\n\n1. **Real-time Information Retrieval**: Get current news, stock prices, weather\n2. **Research & Analysis**: Gather information on specific topics\n3. **Content Discovery**: Find articles, tutorials, documentation\n4. **Competitive Analysis**: Research competitors and market trends\n5. **Fact Checking**: Verify information against web sources\n6. **SEO & Content Research**: Analyze search results for content strategy\n7. **News Aggregation**: Collect news from various sources\n8. **Academic Research**: Find papers, studies, and academic content\n\n## Integration Examples\n\n### Express.js Search API\n\n```javascript\nimport express from 'express';\nimport ZAI from 'z-ai-web-dev-sdk';\n\nconst app = express();\napp.use(express.json());\n\nlet zaiInstance;\n\nasync function initZAI() {\n  zaiInstance = await ZAI.create();\n}\n\napp.get('\u002Fapi\u002Fsearch', async (req, res) => {\n  try {\n    const { q: query, num = 10 } = req.query;\n\n    if (!query) {\n      return res.status(400).json({ error: 'Query parameter \"q\" is required' });\n    }\n\n    const numResults = Math.min(parseInt(num) || 10, 20);\n\n    const results = await zaiInstance.functions.invoke('web_search', {\n      query: query,\n      num: numResults\n    });\n\n    res.json({\n      success: true,\n      query: query,\n      totalResults: results.length,\n      results: results\n    });\n  } catch (error) {\n    res.status(500).json({\n      success: false,\n      error: error.message\n    });\n  }\n});\n\napp.get('\u002Fapi\u002Fsearch\u002Fnews', async (req, res) => {\n  try {\n    const { topic, timeframe = 'recent' } = req.query;\n\n    if (!topic) {\n      return res.status(400).json({ error: 'Topic parameter is required' });\n    }\n\n    const timeKeywords = {\n      recent: 'latest news',\n      today: 'today news',\n      week: 'this week news'\n    };\n\n    const query = `${topic} ${timeKeywords[timeframe] || timeKeywords.recent}`;\n\n    const results = await zaiInstance.functions.invoke('web_search', {\n      query: query,\n      num: 15\n    });\n\n    \u002F\u002F Sort by date\n    const sortedResults = results.sort((a, b) => {\n      return new Date(b.date) - new Date(a.date);\n    });\n\n    res.json({\n      success: true,\n      topic: topic,\n      timeframe: timeframe,\n      results: sortedResults\n    });\n  } catch (error) {\n    res.status(500).json({\n      success: false,\n      error: error.message\n    });\n  }\n});\n\ninitZAI().then(() => {\n  app.listen(3000, () => {\n    console.log('Search API running on port 3000');\n  });\n});\n```\n\n### Search with AI Summary\n\n```javascript\nimport ZAI from 'z-ai-web-dev-sdk';\n\nasync function searchAndSummarize(query) {\n  const zai = await ZAI.create();\n\n  \u002F\u002F Step 1: Search the web\n  const searchResults = await zai.functions.invoke('web_search', {\n    query: query,\n    num: 10\n  });\n\n  \u002F\u002F Step 2: Create summary using chat completions\n  const searchContext = searchResults\n    .slice(0, 5)\n    .map((r, i) => `${i + 1}. ${r.name}\\n${r.snippet}`)\n    .join('\\n\\n');\n\n  const completion = await zai.chat.completions.create({\n    messages: [\n      {\n        role: 'assistant',\n        content: 'You are a research assistant. Summarize search results clearly and concisely.'\n      },\n      {\n        role: 'user',\n        content: `Query: \"${query}\"\\n\\nSearch Results:\\n${searchContext}\\n\\nProvide a comprehensive summary of these results.`\n      }\n    ],\n    thinking: { type: 'disabled' }\n  });\n\n  const summary = completion.choices[0]?.message?.content;\n\n  return {\n    query: query,\n    summary: summary,\n    sources: searchResults.slice(0, 5).map(r => ({\n      title: r.name,\n      url: r.url\n    })),\n    totalResults: searchResults.length\n  };\n}\n\n\u002F\u002F Usage\nconst result = await searchAndSummarize('benefits of renewable energy');\nconsole.log('Summary:', result.summary);\nconsole.log('Sources:', result.sources);\n```\n\n## Troubleshooting\n\n**Issue**: \"SDK must be used in backend\"\n- **Solution**: Ensure z-ai-web-dev-sdk is only imported and used in server-side code\n\n**Issue**: Empty or no results returned\n- **Solution**: Try different query terms, check internet connectivity, verify API status\n\n**Issue**: Unexpected response format\n- **Solution**: Verify the response is an array, check for API changes, add type validation\n\n**Issue**: Rate limiting errors\n- **Solution**: Implement request throttling, add delays between searches, use caching\n\n**Issue**: Low quality search results\n- **Solution**: Refine query terms, filter results by domain or date, validate result quality\n\n## Performance Tips\n\n1. **Reuse SDK Instance**: Create ZAI instance once and reuse across searches\n2. **Implement Caching**: Cache search results to reduce API calls\n3. **Optimize Query Terms**: Use specific, targeted queries for better results\n4. **Limit Result Count**: Request only the number of results you need\n5. **Parallel Searches**: Use Promise.all for multiple independent searches\n6. **Result Filtering**: Filter results on client side when possible\n\n## Security Considerations\n\n1. **Input Validation**: Sanitize and validate user search queries\n2. **Rate Limiting**: Implement rate limits to prevent abuse\n3. **API Key Protection**: Never expose SDK credentials in client-side code\n4. **Result Filtering**: Filter potentially harmful or inappropriate content\n5. **URL Validation**: Validate URLs before redirecting users\n6. **Privacy**: Don't log sensitive user search queries\n\n## Remember\n\n- Always use z-ai-web-dev-sdk in backend code only\n- The SDK is already installed - import as shown in examples\n- Search results are returned as an array of SearchFunctionResultItem objects\n- Implement proper error handling and retries for production\n- Cache results when appropriate to reduce API calls\n- Use specific query terms for better search results\n- Validate and filter results before displaying to users\n- Check `scripts\u002Fweb_search.ts` for a quick start example\n",{"name":5,"license":14,"description":7},"main","7d045d4d6ec778ab8575aad8f8a7e7e7d4321918","skills\u002Fweb-search","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video","https:\u002F\u002Fgithub.com\u002Fnordeim","A freelance IT engineer","2026-07-06 19:57:32",{"source":8,"skillName":5,"commands":32,"prompt":42,"zipAvailable":43},[33,36,39],{"tool":34,"command":35},"npx","npx skills add nordeim\u002Fstory-into-video --skill web-search",{"tool":37,"command":38},"bunx","bunx skills add nordeim\u002Fstory-into-video --skill web-search",{"tool":40,"command":41},"pnpm","pnpm dlx skills add nordeim\u002Fstory-into-video --skill web-search","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fweb-search\u002FSKILL.md",true,[45,50],{"path":46,"resourceType":47,"resourceTypeDesc":48,"sizeBytes":49,"sourceHtmlUrl":15},"LICENSE.txt","LICENSE","许可证",1080,{"path":51,"resourceType":52,"resourceTypeDesc":53,"sizeBytes":54,"sourceHtmlUrl":55},"scripts\u002Fweb_search.ts","SCRIPT","脚本",1166,"https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fweb-search\u002Fscripts\u002Fweb_search.ts",[57,66,74,81,89,97],{"skillNo":58,"name":59,"nameZh":6,"description":60,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":61,"licenseFileUrl":62,"sourceHtmlUrl":63,"categories":64,"keywords":65,"publishedAt":19},"01M77Q7YD61R8X6JKW9F3N07PN","webapp-testing","Web application testing principles. E2E, Playwright, deep audit strategies.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fwebapp-testing\u002FSKILL.md",[],[],{"skillNo":67,"name":68,"nameZh":6,"description":69,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":70,"sourceHtmlUrl":71,"categories":72,"keywords":73,"publishedAt":19},"01M77Q74VD9G7H0HYYDA39NS7G","web-reader","Implement web page content extraction capabilities using the z-ai-web-dev-sdk. Use this skill when the user needs to scrape web pages, extract article content, retrieve page metadata, or build applications that process web content. Supports automatic content extraction with title, HTML, and publication time retrieval.","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fweb-reader\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fweb-reader\u002FSKILL.md",[],[],{"skillNo":75,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":78,"categories":79,"keywords":80,"publishedAt":19},"01M77Q6WY2DJZV5DQTMYKN9PVF","web-frameworks","Build modern full-stack web applications with Next.js 16 + React 19 (App Router, Server Components, RSC, PPR, cacheComponents, async params, SSR, SSG, ISR, standalone output), Turborepo (monorepo, task pipelines, remote caching, parallel execution), and RemixIcon (3100+ SVG icons). Use when creating React applications, implementing server-side rendering, setting up monorepos, optimizing build performance and caching, or working with TypeScript full-stack projects.","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fweb-frameworks\u002FSKILL.md",[],[],{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":85,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":19},"01M77Q6DD51GTZG7N68PSSSZ49","video-understand","Implement specialized video understanding capabilities using the z-ai-web-dev-sdk. Use this skill when the user needs to analyze video content, understand motion and temporal sequences, extract information from video frames, describe video scenes, or perform video-based AI analysis. Optimized for MP4, AVI, MOV, and other common video formats.","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fvideo-understand\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fvideo-understand\u002FSKILL.md",[],[],{"skillNo":90,"name":91,"nameZh":6,"description":92,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":93,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":19},"01M77Q667DHYZWHXQGB2MJDRA4","video-generation","Implement AI-powered video generation capabilities using the z-ai-web-dev-sdk. Use this skill when the user needs to generate videos from text prompts or images, create video content programmatically, or build applications that produce video outputs. Supports asynchronous task management with status polling and result retrieval.","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fvideo-generation\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fvideo-generation\u002FSKILL.md",[],[],{"skillNo":98,"name":99,"nameZh":6,"description":100,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":101,"sourceHtmlUrl":102,"categories":103,"keywords":104,"publishedAt":19},"01M77Q52CRK063YZ8KVW4TTCNH","ui-styling","Create beautiful, accessible user interfaces with shadcn\u002Fui components (built on Radix UI + Tailwind), Tailwind CSS utility-first styling, and canvas-based visual designs. Use when building user interfaces, implementing design systems, creating responsive layouts, adding accessible components (dialogs, dropdowns, forms, tables), customizing themes and colors, implementing dark mode, generating visual designs and posters, or establishing consistent styling patterns across applications.","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fui-styling\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fnordeim\u002Fstory-into-video\u002Fblob\u002Fmain\u002Fskills\u002Fui-styling\u002FSKILL.md",[],[]]