chore: import upstream snapshot with attribution
Test Vector Database Adaptors / Test MCP Vector DB Tools (push) Has been cancelled
Tests / Code Quality (Ruff & Mypy) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (macos-latest, 3.11) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (macos-latest, 3.12) (push) Has been cancelled
Tests / Tests (push) Has been cancelled
Docker Publish / Build and Push Docker Images (map[description:Skill Seekers CLI - Convert documentation to AI skills dockerfile:Dockerfile name:skill-seekers]) (push) Has been cancelled
Docker Publish / Build and Push Docker Images (map[description:Skill Seekers MCP Server - 25 tools for AI assistants dockerfile:Dockerfile.mcp name:skill-seekers-mcp]) (push) Has been cancelled
Docker Publish / Test Docker Images (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (ubuntu-latest, 3.10) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (ubuntu-latest, 3.11) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (ubuntu-latest, 3.12) (push) Has been cancelled
Tests / Serial / Integration / E2E Tests (push) Has been cancelled
Tests / MCP Server Tests (push) Has been cancelled
Test Vector Database Adaptors / Test chroma Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test faiss Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test qdrant Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test weaviate Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test MCP Vector DB Tools (push) Has been cancelled
Tests / Code Quality (Ruff & Mypy) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (macos-latest, 3.11) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (macos-latest, 3.12) (push) Has been cancelled
Tests / Tests (push) Has been cancelled
Docker Publish / Build and Push Docker Images (map[description:Skill Seekers CLI - Convert documentation to AI skills dockerfile:Dockerfile name:skill-seekers]) (push) Has been cancelled
Docker Publish / Build and Push Docker Images (map[description:Skill Seekers MCP Server - 25 tools for AI assistants dockerfile:Dockerfile.mcp name:skill-seekers-mcp]) (push) Has been cancelled
Docker Publish / Test Docker Images (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (ubuntu-latest, 3.10) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (ubuntu-latest, 3.11) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (ubuntu-latest, 3.12) (push) Has been cancelled
Tests / Serial / Integration / E2E Tests (push) Has been cancelled
Tests / MCP Server Tests (push) Has been cancelled
Test Vector Database Adaptors / Test chroma Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test faiss Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test qdrant Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test weaviate Adaptor (push) Has been cancelled
This commit is contained in:
Executable
+113
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Bootstrap Skill Seekers into an Operational Skill for Claude Code
|
||||
#
|
||||
# Usage: ./scripts/bootstrap_skill.sh
|
||||
# Output: output/skill-seekers/ (skill directory)
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
SKILL_NAME="skill-seekers"
|
||||
OUTPUT_DIR="$PROJECT_ROOT/output/$SKILL_NAME"
|
||||
HEADER_FILE="$SCRIPT_DIR/skill_header.md"
|
||||
|
||||
echo "============================================"
|
||||
echo " Skill Seekers Bootstrap"
|
||||
echo "============================================"
|
||||
|
||||
# Step 1: Sync dependencies
|
||||
echo "Step 1: uv sync..."
|
||||
if ! command -v uv &> /dev/null; then
|
||||
echo "❌ Error: 'uv' is not installed"
|
||||
echo ""
|
||||
echo "Install uv:"
|
||||
echo " curl -LsSf https://astral.sh/uv/install.sh | sh"
|
||||
echo " # or"
|
||||
echo " pip install uv"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
cd "$PROJECT_ROOT"
|
||||
uv sync --quiet
|
||||
echo "✓ Done"
|
||||
|
||||
# Step 2: Run codebase analysis
|
||||
echo "Step 2: Analyzing codebase..."
|
||||
rm -rf "$OUTPUT_DIR" 2>/dev/null || true
|
||||
uv run skill-seekers create "$PROJECT_ROOT" \
|
||||
--name "$SKILL_NAME" \
|
||||
--output "$OUTPUT_DIR" 2>&1 | grep -E "^(INFO|✅)" || true
|
||||
echo "✓ Done"
|
||||
|
||||
# Step 3: Prepend header to SKILL.md
|
||||
echo "Step 3: Adding operational header..."
|
||||
if [[ -f "$HEADER_FILE" ]]; then
|
||||
# Detect end of frontmatter dynamically
|
||||
# Look for second occurrence of '---'
|
||||
FRONTMATTER_END=$(grep -n '^---$' "$OUTPUT_DIR/SKILL.md" | sed -n '2p' | cut -d: -f1)
|
||||
|
||||
if [[ -n "$FRONTMATTER_END" ]]; then
|
||||
# Skip frontmatter + blank line
|
||||
AUTO_CONTENT=$(tail -n +$((FRONTMATTER_END + 2)) "$OUTPUT_DIR/SKILL.md")
|
||||
else
|
||||
# Fallback to line 6 if no frontmatter found
|
||||
AUTO_CONTENT=$(tail -n +6 "$OUTPUT_DIR/SKILL.md")
|
||||
fi
|
||||
|
||||
# Combine: header + auto-generated
|
||||
cat "$HEADER_FILE" > "$OUTPUT_DIR/SKILL.md"
|
||||
echo "$AUTO_CONTENT" >> "$OUTPUT_DIR/SKILL.md"
|
||||
echo "✓ Done ($(wc -l < "$OUTPUT_DIR/SKILL.md") lines)"
|
||||
else
|
||||
echo "Warning: $HEADER_FILE not found, using auto-generated only"
|
||||
fi
|
||||
|
||||
# Step 4: Validate merged SKILL.md
|
||||
echo "Step 4: Validating SKILL.md..."
|
||||
if [[ -f "$OUTPUT_DIR/SKILL.md" ]]; then
|
||||
# Check file not empty
|
||||
if [[ ! -s "$OUTPUT_DIR/SKILL.md" ]]; then
|
||||
echo "❌ Error: SKILL.md is empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check frontmatter exists
|
||||
if ! head -1 "$OUTPUT_DIR/SKILL.md" | grep -q '^---$'; then
|
||||
echo "⚠️ Warning: SKILL.md missing frontmatter delimiter"
|
||||
fi
|
||||
|
||||
# Check required fields
|
||||
if ! grep -q '^name:' "$OUTPUT_DIR/SKILL.md"; then
|
||||
echo "❌ Error: SKILL.md missing 'name:' field"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -q '^description:' "$OUTPUT_DIR/SKILL.md"; then
|
||||
echo "❌ Error: SKILL.md missing 'description:' field"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ Validation passed"
|
||||
else
|
||||
echo "❌ Error: SKILL.md not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Bootstrap Complete!"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Output: $OUTPUT_DIR/"
|
||||
echo " - SKILL.md ($(wc -l < "$OUTPUT_DIR/SKILL.md") lines)"
|
||||
echo " - references/ (API docs, patterns, examples)"
|
||||
echo ""
|
||||
echo "Install to Claude Code:"
|
||||
echo " cp -r output/$SKILL_NAME ~/.claude/skills/"
|
||||
echo ""
|
||||
echo "Verify:"
|
||||
echo " ls ~/.claude/skills/$SKILL_NAME/SKILL.md"
|
||||
echo ""
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
# Check if Chinese translations are in sync with English originals
|
||||
# Usage: ./scripts/check_translation_sync.sh
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔍 Checking translation sync..."
|
||||
echo ""
|
||||
|
||||
MISSING=0
|
||||
OUT_OF_SYNC=0
|
||||
|
||||
# Find all English docs (excluding zh-CN and archive)
|
||||
find docs -name "*.md" -not -path "docs/zh-CN/*" -not -path "docs/archive/*" | while read -r en_file; do
|
||||
# Calculate corresponding Chinese file path
|
||||
rel_path="${en_file#docs/}"
|
||||
zh_file="docs/zh-CN/$rel_path"
|
||||
|
||||
# Check if Chinese version exists
|
||||
if [ ! -f "$zh_file" ]; then
|
||||
echo "❌ Missing: $zh_file (source: $en_file)"
|
||||
MISSING=$((MISSING + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
# Get last modification times
|
||||
en_mtime=$(git log -1 --format=%ct "$en_file" 2>/dev/null || stat -c %Y "$en_file" 2>/dev/null || echo 0)
|
||||
zh_mtime=$(git log -1 --format=%ct "$zh_file" 2>/dev/null || stat -c %Y "$zh_file" 2>/dev/null || echo 0)
|
||||
|
||||
# Check if English is newer
|
||||
if [ "$en_mtime" -gt "$zh_mtime" ]; then
|
||||
echo "⚠️ Out of sync: $zh_file (English updated more recently)"
|
||||
OUT_OF_SYNC=$((OUT_OF_SYNC + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
|
||||
# Summary
|
||||
TOTAL_EN=$(find docs -name "*.md" -not -path "docs/zh-CN/*" -not -path "docs/archive/*" | wc -l)
|
||||
TOTAL_ZH=$(find docs/zh-CN -name "*.md" 2>/dev/null | wc -l)
|
||||
|
||||
echo "📊 Summary:"
|
||||
echo " English docs: $TOTAL_EN"
|
||||
echo " Chinese docs: $TOTAL_ZH"
|
||||
|
||||
if [ "$MISSING" -gt 0 ]; then
|
||||
echo " ❌ Missing translations: $MISSING"
|
||||
fi
|
||||
|
||||
if [ "$OUT_OF_SYNC" -gt 0 ]; then
|
||||
echo " ⚠️ Out of sync: $OUT_OF_SYNC"
|
||||
fi
|
||||
|
||||
if [ "$MISSING" -eq 0 ] && [ "$OUT_OF_SYNC" -eq 0 ]; then
|
||||
echo ""
|
||||
echo "✅ All translations in sync!"
|
||||
exit 0
|
||||
else
|
||||
echo ""
|
||||
echo "❌ Translation sync issues found"
|
||||
exit 1
|
||||
fi
|
||||
Executable
+72
@@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
# Performance Benchmark Runner for Skill Seekers
|
||||
# Runs comprehensive benchmarks for all platform adaptors
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${CYAN}║ Skill Seekers Performance Benchmarks ║${NC}"
|
||||
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo ""
|
||||
|
||||
# Ensure we're in the project root
|
||||
if [ ! -f "pyproject.toml" ]; then
|
||||
echo -e "${RED}Error: Must run from project root${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if package is installed
|
||||
if ! python -c "import skill_seekers" 2>/dev/null; then
|
||||
echo -e "${YELLOW}Package not installed. Installing...${NC}"
|
||||
pip install -e . > /dev/null 2>&1
|
||||
echo -e "${GREEN}✓ Package installed${NC}"
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}Running benchmark suite...${NC}"
|
||||
echo ""
|
||||
|
||||
# Run benchmarks with pytest
|
||||
if pytest tests/test_adaptor_benchmarks.py -v -m benchmark --tb=short -s; then
|
||||
echo ""
|
||||
echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}║ All Benchmarks Passed ✓ ║${NC}"
|
||||
echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
# Summary
|
||||
echo -e "${CYAN}Benchmark Summary:${NC}"
|
||||
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo "✓ format_skill_md() benchmarked across 11 adaptors"
|
||||
echo "✓ Package operations benchmarked (time + size)"
|
||||
echo "✓ Scaling behavior analyzed (1-50 references)"
|
||||
echo "✓ JSON vs ZIP compression ratios measured"
|
||||
echo "✓ Metadata processing overhead quantified"
|
||||
echo "✓ Empty vs full skill performance compared"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}📊 Key Insights:${NC}"
|
||||
echo "• All adaptors complete formatting in < 500ms"
|
||||
echo "• Package operations complete in < 1 second"
|
||||
echo "• Linear scaling confirmed (not exponential)"
|
||||
echo "• Metadata overhead < 10%"
|
||||
echo "• ZIP compression ratio: ~80-90x"
|
||||
echo ""
|
||||
|
||||
exit 0
|
||||
else
|
||||
echo ""
|
||||
echo -e "${RED}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${RED}║ Some Benchmarks Failed ✗ ║${NC}"
|
||||
echo -e "${RED}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Check the output above for details${NC}"
|
||||
exit 1
|
||||
fi
|
||||
Executable
+248
@@ -0,0 +1,248 @@
|
||||
#!/bin/bash
|
||||
# Integration Test Runner with Docker Infrastructure
|
||||
# Manages vector database services and runs integration tests
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
COMPOSE_FILE="tests/docker-compose.test.yml"
|
||||
|
||||
function print_header() {
|
||||
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${CYAN}║ Skill Seekers Integration Test Runner ║${NC}"
|
||||
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
function check_docker() {
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo -e "${RED}Error: Docker not found${NC}"
|
||||
echo "Please install Docker: https://docs.docker.com/get-docker/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
|
||||
echo -e "${RED}Error: docker-compose not found${NC}"
|
||||
echo "Please install docker-compose: https://docs.docker.com/compose/install/"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function start_services() {
|
||||
echo -e "${BLUE}Starting test infrastructure...${NC}"
|
||||
echo ""
|
||||
|
||||
# Use either docker-compose or docker compose
|
||||
if command -v docker-compose &> /dev/null; then
|
||||
docker-compose -f "$COMPOSE_FILE" up -d
|
||||
else
|
||||
docker compose -f "$COMPOSE_FILE" up -d
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}Waiting for services to be ready...${NC}"
|
||||
sleep 5
|
||||
|
||||
# Check service health
|
||||
local all_healthy=true
|
||||
|
||||
echo -n "Weaviate... "
|
||||
if curl -s http://localhost:8080/v1/.well-known/ready > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✓${NC}"
|
||||
else
|
||||
echo -e "${RED}✗${NC}"
|
||||
all_healthy=false
|
||||
fi
|
||||
|
||||
echo -n "Qdrant... "
|
||||
if curl -s http://localhost:6333/ > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✓${NC}"
|
||||
else
|
||||
echo -e "${RED}✗${NC}"
|
||||
all_healthy=false
|
||||
fi
|
||||
|
||||
echo -n "ChromaDB... "
|
||||
if curl -s http://localhost:8000/api/v1/heartbeat > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✓${NC}"
|
||||
else
|
||||
echo -e "${RED}✗${NC}"
|
||||
all_healthy=false
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
if [ "$all_healthy" = false ]; then
|
||||
echo -e "${YELLOW}Warning: Some services may not be ready yet${NC}"
|
||||
echo -e "${YELLOW}Waiting an additional 10 seconds...${NC}"
|
||||
sleep 10
|
||||
fi
|
||||
}
|
||||
|
||||
function stop_services() {
|
||||
echo -e "${BLUE}Stopping test infrastructure...${NC}"
|
||||
|
||||
if command -v docker-compose &> /dev/null; then
|
||||
docker-compose -f "$COMPOSE_FILE" down -v
|
||||
else
|
||||
docker compose -f "$COMPOSE_FILE" down -v
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓ Services stopped${NC}"
|
||||
}
|
||||
|
||||
function run_tests() {
|
||||
echo -e "${BLUE}Running integration tests...${NC}"
|
||||
echo ""
|
||||
|
||||
# Install required packages if missing
|
||||
local missing_packages=()
|
||||
|
||||
if ! python -c "import weaviate" 2>/dev/null; then
|
||||
missing_packages+=("weaviate-client")
|
||||
fi
|
||||
|
||||
if ! python -c "import chromadb" 2>/dev/null; then
|
||||
missing_packages+=("chromadb")
|
||||
fi
|
||||
|
||||
if ! python -c "import qdrant_client" 2>/dev/null; then
|
||||
missing_packages+=("qdrant-client")
|
||||
fi
|
||||
|
||||
if [ ${#missing_packages[@]} -gt 0 ]; then
|
||||
echo -e "${YELLOW}Installing missing packages: ${missing_packages[*]}${NC}"
|
||||
pip install "${missing_packages[@]}" > /dev/null 2>&1
|
||||
echo -e "${GREEN}✓ Packages installed${NC}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Run tests
|
||||
if pytest tests/test_integration_adaptors.py -v -m integration --tb=short; then
|
||||
echo ""
|
||||
echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}║ All Integration Tests Passed ✓ ║${NC}"
|
||||
echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
return 0
|
||||
else
|
||||
echo ""
|
||||
echo -e "${RED}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${RED}║ Some Integration Tests Failed ✗ ║${NC}"
|
||||
echo -e "${RED}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function show_logs() {
|
||||
echo -e "${BLUE}Showing service logs...${NC}"
|
||||
echo ""
|
||||
|
||||
if command -v docker-compose &> /dev/null; then
|
||||
docker-compose -f "$COMPOSE_FILE" logs --tail=50
|
||||
else
|
||||
docker compose -f "$COMPOSE_FILE" logs --tail=50
|
||||
fi
|
||||
}
|
||||
|
||||
function show_status() {
|
||||
echo -e "${BLUE}Service status:${NC}"
|
||||
echo ""
|
||||
|
||||
if command -v docker-compose &> /dev/null; then
|
||||
docker-compose -f "$COMPOSE_FILE" ps
|
||||
else
|
||||
docker compose -f "$COMPOSE_FILE" ps
|
||||
fi
|
||||
}
|
||||
|
||||
function show_help() {
|
||||
echo "Integration Test Runner"
|
||||
echo ""
|
||||
echo "Usage: $0 [command]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " start Start vector database services"
|
||||
echo " stop Stop and clean up services"
|
||||
echo " test Run integration tests"
|
||||
echo " run Start services + run tests + stop services (default)"
|
||||
echo " logs Show service logs"
|
||||
echo " status Show service status"
|
||||
echo " help Show this help message"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 # Run complete workflow"
|
||||
echo " $0 start # Just start services"
|
||||
echo " $0 test # Run tests (services must be running)"
|
||||
echo " $0 stop # Stop all services"
|
||||
}
|
||||
|
||||
# Main script
|
||||
print_header
|
||||
check_docker
|
||||
|
||||
# Parse command
|
||||
COMMAND="${1:-run}"
|
||||
|
||||
case "$COMMAND" in
|
||||
start)
|
||||
start_services
|
||||
echo ""
|
||||
echo -e "${GREEN}Services started successfully!${NC}"
|
||||
echo "Run tests with: $0 test"
|
||||
;;
|
||||
|
||||
stop)
|
||||
stop_services
|
||||
;;
|
||||
|
||||
test)
|
||||
run_tests
|
||||
;;
|
||||
|
||||
run)
|
||||
echo -e "${CYAN}Running complete workflow:${NC}"
|
||||
echo "1. Start services"
|
||||
echo "2. Run tests"
|
||||
echo "3. Stop services"
|
||||
echo ""
|
||||
|
||||
start_services
|
||||
echo ""
|
||||
|
||||
if run_tests; then
|
||||
TEST_RESULT=0
|
||||
else
|
||||
TEST_RESULT=1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
stop_services
|
||||
exit $TEST_RESULT
|
||||
;;
|
||||
|
||||
logs)
|
||||
show_logs
|
||||
;;
|
||||
|
||||
status)
|
||||
show_status
|
||||
;;
|
||||
|
||||
help|--help|-h)
|
||||
show_help
|
||||
;;
|
||||
|
||||
*)
|
||||
echo -e "${RED}Unknown command: $COMMAND${NC}"
|
||||
echo ""
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
# Fast parallel test runner for local development.
|
||||
# Phase 1: Fast unit tests with xdist (~2-3 min)
|
||||
# Phase 2: Serial/Integration/E2E tests (~10-15 min)
|
||||
# Phase 3: MCP tests (if MCP installed)
|
||||
set -e
|
||||
|
||||
MCP_SKIP="--ignore=tests/test_mcp_server.py --ignore=tests/test_mcp_fastmcp.py --ignore=tests/test_install_skill_e2e.py --ignore=tests/test_unified_mcp_integration.py --ignore=tests/test_mcp_git_sources.py --ignore=tests/test_mcp_vector_dbs.py --ignore=tests/test_mcp_workflow_tools.py --ignore=tests/test_server_fastmcp_http.py"
|
||||
|
||||
INTEGRATION_SKIP="--ignore=tests/test_real_world_fastmcp.py --ignore=tests/test_issue_277_discord_e2e.py --ignore=tests/test_browser_renderer.py --ignore=tests/test_integration_adaptors.py --ignore=tests/test_bootstrap_skill_e2e.py --ignore=tests/test_git_sources_e2e.py --ignore=tests/test_marketplace_publisher.py --ignore=tests/test_sync_config_e2e.py --ignore=tests/test_estimate_pages.py"
|
||||
|
||||
echo "=== Phase 1: Fast Unit Tests (parallel) ==="
|
||||
pytest tests/ -n auto --dist=loadfile \
|
||||
${MCP_SKIP} ${INTEGRATION_SKIP} \
|
||||
-m "not slow and not integration and not e2e and not network and not serial" \
|
||||
-q --timeout=120 "$@"
|
||||
|
||||
echo ""
|
||||
echo "=== Phase 2: Serial/Integration/E2E Tests ==="
|
||||
pytest tests/ \
|
||||
-m "integration or e2e or slow or network or serial" \
|
||||
-v --timeout=300 "$@"
|
||||
|
||||
echo ""
|
||||
echo "=== Phase 3: MCP Tests ==="
|
||||
python -c "import mcp" 2>/dev/null && {
|
||||
pytest tests/test_mcp_server.py tests/test_mcp_fastmcp.py \
|
||||
tests/test_mcp_git_sources.py tests/test_mcp_vector_dbs.py \
|
||||
tests/test_mcp_workflow_tools.py tests/test_unified_mcp_integration.py \
|
||||
tests/test_server_fastmcp_http.py tests/test_install_skill.py \
|
||||
tests/test_install_skill_e2e.py \
|
||||
-v --timeout=180 "$@"
|
||||
} || echo "MCP not installed — skipping Phase 3"
|
||||
|
||||
echo ""
|
||||
echo "All phases complete."
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
name: skill-seekers
|
||||
description: Generate LLM skills from documentation, codebases, and GitHub repositories
|
||||
---
|
||||
|
||||
# Skill Seekers
|
||||
|
||||
## Prerequisites
|
||||
|
||||
```bash
|
||||
pip install skill-seekers
|
||||
# Or: uv pip install skill-seekers
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
| Source | Command |
|
||||
|--------|---------|
|
||||
| Local code | `skill-seekers create ./path` |
|
||||
| Docs URL | `skill-seekers create https://docs.example.com` |
|
||||
| GitHub | `skill-seekers create owner/repo` |
|
||||
| PDF | `skill-seekers create document.pdf` |
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Analyze local codebase
|
||||
skill-seekers create /path/to/project --name my-skill
|
||||
|
||||
# Package for Claude
|
||||
yes | skill-seekers package output/my-skill/ --no-open
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--preset quick/standard/comprehensive` | Analysis preset |
|
||||
| `--skip-patterns` | Skip pattern detection |
|
||||
| `--skip-test-examples` | Skip test extraction |
|
||||
|
||||
---
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Translate Skill Seekers documentation to Chinese.
|
||||
|
||||
Usage:
|
||||
python scripts/translate_doc.py <file> --target-lang zh-CN
|
||||
python scripts/translate_doc.py docs/getting-started/02-quick-start.md
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def get_version() -> str:
|
||||
"""Get current version from package."""
|
||||
try:
|
||||
from skill_seekers import __version__
|
||||
return __version__
|
||||
except ImportError:
|
||||
return "3.1.0"
|
||||
|
||||
|
||||
def translate_with_anthropic(content: str, api_key: str) -> str:
|
||||
"""Translate content using Anthropic Claude API."""
|
||||
try:
|
||||
import anthropic
|
||||
|
||||
client = anthropic.Anthropic(api_key=api_key)
|
||||
|
||||
system_prompt = """You are a professional technical translator translating Skill Seekers documentation from English to Simplified Chinese.
|
||||
|
||||
Translation rules:
|
||||
1. Keep technical terms in English: CLI, API, JSON, YAML, MCP, URL, HTTP, etc.
|
||||
2. Keep code examples, commands, and file paths in English
|
||||
3. Keep proper nouns (product names, company names) in English
|
||||
4. Use Simplified Chinese (简体中文)
|
||||
5. Maintain all Markdown formatting
|
||||
6. Translate link text but keep link targets (will be handled separately)
|
||||
7. Use professional, technical Chinese appropriate for developers
|
||||
8. Preserve all code blocks, they should remain exactly the same
|
||||
|
||||
Output ONLY the translated content, no explanations."""
|
||||
|
||||
message = client.messages.create(
|
||||
model="claude-3-5-sonnet-20241022",
|
||||
max_tokens=8000,
|
||||
temperature=0.1,
|
||||
system=system_prompt,
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": f"Translate this technical documentation to Simplified Chinese:\n\n{content}"
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
return message.content[0].text
|
||||
except Exception as e:
|
||||
print(f"Translation API error: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def add_translation_header(content: str, original_file: Path, target_lang: str) -> str:
|
||||
"""Add translation header to document."""
|
||||
version = get_version()
|
||||
date = datetime.now().strftime("%Y-%m-%d")
|
||||
original_name = original_file.name
|
||||
|
||||
# Calculate relative path from docs/
|
||||
try:
|
||||
relative_path = original_file.relative_to("docs")
|
||||
original_link = f"../{relative_path}"
|
||||
except ValueError:
|
||||
original_link = f"../{original_file.name}"
|
||||
|
||||
header = f"""> **注意:** 本文档是 [{original_name}]({original_link}) 的中文翻译。
|
||||
>
|
||||
> - **最后翻译日期:** {date}
|
||||
> - **英文原文版本:** {version}
|
||||
> - **翻译状态:** ⚠️ 待审阅
|
||||
>
|
||||
> 如果本文档与英文版本有冲突,请以英文版本为准。
|
||||
>
|
||||
> ---
|
||||
>
|
||||
> **Note:** This document is a Chinese translation of [{original_name}]({original_link}).
|
||||
>
|
||||
> - **Last translated:** {date}
|
||||
> - **Original version:** {version}
|
||||
> - **Translation status:** ⚠️ Pending review
|
||||
>
|
||||
> If there are conflicts, the English version takes precedence.
|
||||
|
||||
---
|
||||
|
||||
"""
|
||||
|
||||
return header + content
|
||||
|
||||
|
||||
def fix_links(content: str, original_file: Path) -> str:
|
||||
"""Fix internal links to point to Chinese versions."""
|
||||
# Pattern for markdown links: [text](path)
|
||||
# We need to convert links to other docs to point to zh-CN versions
|
||||
|
||||
def replace_link(match):
|
||||
text = match.group(1)
|
||||
path = match.group(2)
|
||||
|
||||
# Skip external links
|
||||
if path.startswith(('http://', 'https://', '#', 'mailto:')):
|
||||
return match.group(0)
|
||||
|
||||
# Skip anchor-only links
|
||||
if path.startswith('#'):
|
||||
return match.group(0)
|
||||
|
||||
# For relative links to other md files, adjust path
|
||||
if path.endswith('.md'):
|
||||
# If it's a relative link, it should point to zh-CN version
|
||||
if not path.startswith('/'):
|
||||
# Count directory levels
|
||||
depth = len(original_file.parent.parts) - 1 # -1 for 'docs'
|
||||
if depth > 0:
|
||||
# Going up to docs/, then into zh-CN/
|
||||
prefix = '../' * depth
|
||||
new_path = prefix + 'zh-CN/' + path.lstrip('./')
|
||||
else:
|
||||
new_path = 'zh-CN/' + path
|
||||
return f'[{text}]({new_path})'
|
||||
|
||||
return match.group(0)
|
||||
|
||||
# Replace markdown links
|
||||
content = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', replace_link, content)
|
||||
|
||||
return content
|
||||
|
||||
|
||||
def translate_file(input_path: str, target_lang: str = "zh-CN"):
|
||||
"""Translate a documentation file."""
|
||||
input_file = Path(input_path).resolve()
|
||||
|
||||
if not input_file.exists():
|
||||
print(f"❌ File not found: {input_file}")
|
||||
return False
|
||||
|
||||
# Read English content
|
||||
with open(input_file, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Remove existing translation header if present (for re-translation)
|
||||
if '> **注意:**' in content[:500]:
|
||||
# Find the separator and remove everything before it
|
||||
separator_pos = content.find('---\n\n')
|
||||
if separator_pos != -1:
|
||||
content = content[separator_pos + 5:]
|
||||
|
||||
# Translate content
|
||||
api_key = os.environ.get('ANTHROPIC_API_KEY')
|
||||
if api_key:
|
||||
print(f"🤖 Translating with Claude API: {input_file.name}")
|
||||
translated = translate_with_anthropic(content, api_key)
|
||||
if translated:
|
||||
content = translated
|
||||
else:
|
||||
print(f"⚠️ Translation failed, keeping original content for: {input_file.name}")
|
||||
else:
|
||||
print(f"⚠️ No ANTHROPIC_API_KEY, skipping translation for: {input_file.name}")
|
||||
return False
|
||||
|
||||
# Fix internal links
|
||||
content = fix_links(content, input_file)
|
||||
|
||||
# Add translation header
|
||||
content = add_translation_header(content, input_file, target_lang)
|
||||
|
||||
# Determine output path
|
||||
try:
|
||||
relative_path = input_file.relative_to(Path("docs").resolve())
|
||||
except ValueError:
|
||||
# If file is not in docs/, use just the filename
|
||||
relative_path = Path(input_file.name)
|
||||
|
||||
output_file = Path("docs") / target_lang / relative_path
|
||||
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Write translated content
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
|
||||
print(f"✅ Created: {output_file}")
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Translate Skill Seekers documentation to Chinese"
|
||||
)
|
||||
parser.add_argument(
|
||||
"file",
|
||||
nargs='?',
|
||||
help="Path to the documentation file to translate (not needed with --batch)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--target-lang",
|
||||
default="zh-CN",
|
||||
help="Target language code (default: zh-CN)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--batch",
|
||||
action="store_true",
|
||||
help="Translate all documentation files"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.batch:
|
||||
# Translate all docs
|
||||
docs_dir = Path("docs")
|
||||
files_to_translate = []
|
||||
|
||||
for pattern in ["**/*.md"]:
|
||||
files = list(docs_dir.glob(pattern))
|
||||
for f in files:
|
||||
# Skip already translated files and archive
|
||||
if "zh-CN" not in str(f) and "archive" not in str(f):
|
||||
files_to_translate.append(f)
|
||||
|
||||
print(f"🔄 Batch translating {len(files_to_translate)} files...")
|
||||
success_count = 0
|
||||
for f in files_to_translate:
|
||||
if translate_file(str(f), args.target_lang):
|
||||
success_count += 1
|
||||
|
||||
print(f"\n✅ Successfully translated {success_count}/{len(files_to_translate)} files")
|
||||
else:
|
||||
# Translate single file
|
||||
translate_file(args.file, args.target_lang)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user