feat: key management and scheduled task tools

This commit is contained in:
zhayujie
2026-02-01 19:21:12 +08:00
parent d337140577
commit 4c8712d683
21 changed files with 2170 additions and 68 deletions

View File

@@ -0,0 +1,91 @@
---
name: bocha-search
description: High-quality web search with AI-optimized results. Use when user needs to search the internet for current information, news, or research topics.
homepage: https://open.bocha.cn/
metadata:
emoji: 🔍
requires:
bins: ["curl"]
env: ["BOCHA_API_KEY"]
primaryEnv: "BOCHA_API_KEY"
---
# Bocha Search
High-quality web search powered by Bocha AI, optimized for AI consumption. Returns web pages, images, and detailed metadata.
## Setup
This skill requires a Bocha API key. If not configured:
1. Visit https://open.bocha.cn to get an API key
2. Set the key using: `env_config(action="set", key="BOCHA_API_KEY", value="your-key")`
3. Or manually add to `~/cow/.env`: `BOCHA_API_KEY=your-key`
## Usage
**Important**: Scripts are located relative to this skill's base directory.
When you see this skill in `<available_skills>`, note the `<base_dir>` path.
```bash
# General pattern:
bash "<base_dir>/scripts/search.sh" "<query>" [count] [freshness] [summary]
# Parameters:
# - query: Search query (required)
# - count: Number of results (1-50, default: 10)
# - freshness: Time range filter (default: noLimit)
# Options: noLimit, oneDay, oneWeek, oneMonth, oneYear, YYYY-MM-DD..YYYY-MM-DD
# - summary: Include text summary (true/false, default: false)
```
## Examples
### Basic search
```bash
bash "<base_dir>/scripts/search.sh" "latest AI news"
```
### Search with more results
```bash
bash "<base_dir>/scripts/search.sh" "Python tutorials" 20
```
### Search recent content with summary
```bash
bash "<base_dir>/scripts/search.sh" "阿里巴巴ESG报告" 10 oneWeek true
```
### Search specific date range
```bash
bash "<base_dir>/scripts/search.sh" "tech news" 15 "2025-01-01..2025-02-01"
```
## Response Format
The API returns structured data compatible with Bing Search API:
**Web Pages** (in `data.webPages.value`):
- `name`: Page title
- `url`: Page URL
- `snippet`: Short description
- `summary`: Full text summary (if requested)
- `siteName`: Website name
- `siteIcon`: Website icon URL
- `datePublished`: Publication date (UTC+8)
- `language`: Page language
**Images** (in `data.images.value`):
- `contentUrl`: Image URL
- `hostPageUrl`: Source page URL
- `width`, `height`: Image dimensions
- `thumbnailUrl`: Thumbnail URL
## Notes
- **Optimized for AI**: Results include summaries and structured metadata
- **Time range**: Use `noLimit` for best results (algorithm auto-optimizes time range)
- **Timeout**: 30 seconds
- **Rate limits**: Check your API plan at https://open.bocha.cn
- **Response format**: Compatible with Bing Search API for easy integration

View File

@@ -0,0 +1,75 @@
#!/usr/bin/env bash
# Bocha Web Search API wrapper
# API Docs: https://open.bocha.cn/
set -euo pipefail
query="${1:-}"
count="${2:-10}"
freshness="${3:-noLimit}"
summary="${4:-false}"
if [ -z "$query" ]; then
echo '{"error": "Query is required", "usage": "bash search.sh <query> [count] [freshness] [summary]"}'
exit 1
fi
if [ -z "${BOCHA_API_KEY:-}" ]; then
echo '{"error": "BOCHA_API_KEY environment variable is not set", "help": "Visit https://open.bocha.cn to get an API key"}'
exit 1
fi
# Validate count (1-50)
if ! [[ "$count" =~ ^[0-9]+$ ]] || [ "$count" -lt 1 ] || [ "$count" -gt 50 ]; then
count=10
fi
# Build JSON request body
request_body=$(cat <<EOF
{
"query": "$query",
"count": $count,
"freshness": "$freshness",
"summary": $summary
}
EOF
)
# Call Bocha API
response=$(curl -sS --max-time 30 \
-X POST \
-H "Authorization: Bearer $BOCHA_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d "$request_body" \
"https://api.bocha.cn/v1/web-search" 2>&1)
curl_exit_code=$?
if [ $curl_exit_code -ne 0 ]; then
echo "{\"error\": \"Failed to call Bocha API\", \"details\": \"$response\"}"
exit 1
fi
# Simple JSON validation - check if response starts with { or [
if [[ ! "$response" =~ ^[[:space:]]*[\{\[] ]]; then
echo "{\"error\": \"Invalid JSON response from API\", \"response\": \"$response\"}"
exit 1
fi
# Extract API code using grep and sed (basic JSON parsing)
api_code=$(echo "$response" | grep -o '"code"[[:space:]]*:[[:space:]]*[0-9]*' | grep -o '[0-9]*' | head -1)
# If code extraction failed or code is not 200, check for error
if [ -n "$api_code" ] && [ "$api_code" != "200" ]; then
# Try to extract error message
api_msg=$(echo "$response" | grep -o '"msg"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/"msg"[[:space:]]*:[[:space:]]*"\(.*\)"/\1/' | head -1)
if [ -z "$api_msg" ]; then
api_msg="Unknown error"
fi
echo "{\"error\": \"API returned error\", \"code\": $api_code, \"message\": \"$api_msg\"}"
exit 1
fi
# Return the full response
echo "$response"

View File

@@ -243,20 +243,87 @@ If you used `--examples`, delete any placeholder files that are not needed for t
##### Frontmatter
Write the YAML frontmatter with `name` and `description`:
Write the YAML frontmatter with `name`, `description`, and optional `metadata`:
- `name`: The skill name
- `description`: This is the primary triggering mechanism for your skill, and helps the agent understand when to use the skill.
- Include both what the Skill does and specific triggers/contexts for when to use it.
- Include all "when to use" information here - Not in the body. The body is only loaded after triggering, so "When to Use This Skill" sections in the body are not helpful to the agent.
- Example description for a `docx` skill: "Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. Use when the agent needs to work with professional documents (.docx files) for: (1) Creating new documents, (2) Modifying or editing content, (3) Working with tracked changes, (4) Adding comments, or any other document tasks"
- `metadata`: (Optional) Specify requirements and configuration
- `requires.bins`: Required binaries (e.g., `["curl", "jq"]`)
- `requires.env`: Required environment variables (e.g., `["OPENAI_API_KEY"]`)
- `primaryEnv`: Primary environment variable name (for API keys)
- `always`: Set to `true` to always load regardless of requirements
- `emoji`: Skill icon (optional)
Do not include any other fields in YAML frontmatter.
**API Key Requirements**:
If your skill needs an API key, declare it in metadata:
```yaml
---
name: my-search
description: Search using MyAPI
metadata:
requires:
bins: ["curl"]
env: ["MYAPI_KEY"]
primaryEnv: "MYAPI_KEY"
---
```
**Auto-enable rule**: Skills are automatically enabled when required environment variables are set, and automatically disabled when missing. No manual configuration needed.
##### Body
Write instructions for using the skill and its bundled resources.
**If your skill requires an API key**, include setup instructions in the body:
```markdown
## Setup
This skill requires an API key from [Service Name].
1. Visit https://service.com to get an API key
2. Configure it using: `env_config(action="set", key="SERVICE_API_KEY", value="your-key")`
3. Or manually add to `~/cow/.env`: `SERVICE_API_KEY=your-key`
4. Restart the agent for changes to take effect
## Usage
...
```
The bash script should check for the key and provide helpful error messages:
```bash
#!/usr/bin/env bash
if [ -z "${SERVICE_API_KEY:-}" ]; then
echo "Error: SERVICE_API_KEY not set"
echo "Please configure your API key first (see SKILL.md)"
exit 1
fi
curl -H "Authorization: Bearer $SERVICE_API_KEY" ...
```
**Script Path Convention**:
When writing SKILL.md instructions, remember that:
- Skills are listed in `<available_skills>` with a `<base_dir>` path
- Scripts should be referenced as: `<base_dir>/scripts/script_name.sh`
- The AI will see the base_dir and can construct the full path
Example instruction in SKILL.md:
```markdown
## Usage
Scripts are in this skill's base directory (shown in skill listing).
bash "<base_dir>/scripts/my_script.sh" <args>
```
### Step 5: Validate (Optional)
Validate skill format:

View File

@@ -1,11 +1,12 @@
---
name: web-fetch
description: Fetch and extract readable content from web pages
description: Fetch and extract readable content from web pages. Use for lightweight page access without browser automation.
homepage: https://github.com/zhayujie/chatgpt-on-wechat
metadata:
emoji: 🌐
requires:
bins: ["curl"]
always: true
---
# Web Fetch
@@ -14,10 +15,16 @@ Fetch and extract readable content from web pages using curl and basic text proc
## Usage
Use the provided script to fetch a URL and extract its content:
**Important**: Scripts are located relative to this skill's base directory.
When you see this skill in `<available_skills>`, note the `<base_dir>` path.
```bash
bash scripts/fetch.sh <url> [output_file]
# General pattern:
bash "<base_dir>/scripts/fetch.sh" <url> [output_file]
# Example (replace <base_dir> with actual path from skill listing):
bash "~/chatgpt-on-wechat/skills/web-fetch/scripts/fetch.sh" "https://example.com"
```
**Parameters:**
@@ -31,18 +38,18 @@ bash scripts/fetch.sh <url> [output_file]
### Fetch a web page
```bash
bash scripts/fetch.sh "https://example.com"
bash "<base_dir>/scripts/fetch.sh" "https://example.com"
```
### Save to file
```bash
bash scripts/fetch.sh "https://example.com" output.txt
bash "<base_dir>/scripts/fetch.sh" "https://example.com" output.txt
cat output.txt
```
## Notes
- Uses curl for HTTP requests (timeout: 20s)
- Uses curl for HTTP requests (timeout: 10s)
- Extracts title and basic text content
- Removes HTML tags and scripts
- Works with any standard web page

View File

@@ -19,7 +19,7 @@ if [[ ! "$url" =~ ^https?:// ]]; then
fi
# Fetch the page with curl
html=$(curl -sS -L --max-time 20 \
html=$(curl -sS -L --max-time 10 \
-H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" \
-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" \
"$url" 2>&1) || {