Skill: geri4/gcore-fastedge (version 1.0.1)

--- name: fastedge description: Build and deploy WebAssembly applications to Gcore FastEdge edge computing platform. Use when creating, building, or deploying FastEdge HTTP apps with Rust SDK. Triggers on phrases like "deploy to FastEdge", "build FastEdge app", "create FastEdge application", "Wasm on FastEdge", or when working with Gcore edge computing. metadata: '{"openclaw":{"requires":{"bins":["rustup","cargo","python3"],"env":["GCORE_API_KEY"]},"primaryEnv":"GCORE_API_KEY","install":[{"id":"requests","kind":"uv","packages":["requests"],"label":"Install Python requests package (uv)"}]}}' --- # FastEdge Skill Build and deploy WebAssembly HTTP applications to Gcore FastEdge. ## Quick Start ### 1. Create a new FastEdge app Initialize a Rust project with the FastEdge SDK: ```bash mkdir myapp && cd myapp ``` Create `.cargo/config.toml`: ```toml [build] target = "wasm32-wasip1" ``` Create `Cargo.toml`: ```toml [package] name = "myapp" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] fastedge = "0.2" ``` Create `src/lib.rs`: ```rust use fastedge::{ body::Body, http::{Request, Response, StatusCode, Error}, }; #[fastedge::http] fn main(_req: Request<Body>) -> Result<Response<Body>, Error> { Response::builder() .status(StatusCode::OK) .header("content-type", "text/plain") .body(Body::from("Hello from FastEdge!")) } ``` ### 2. Build the Wasm binary Requires Rust and wasm32-wasip1 target: ```bash rustup target add wasm32-wasip1 cargo build --release ``` Binary location: `target/wasm32-wasip1/release/myapp.wasm` ### 3. Deploy via CLI Set your API key (get from https://accounts.gcore.com/account-settings/api-tokens): ```bash export GCORE_API_KEY="your_api_token" ``` Upload binary: ```bash curl -X POST \ 'https://api.gcore.com/fastedge/v1/binaries/raw' \ -H 'accept: application/json' \ -H "Authorization: APIKey $GCORE_API_KEY" \ -H 'Content-Type: application/octet-stream' \ --data-binary '@./target/wasm32-wasip1/release/myapp.wasm' ``` Save the `id` from response (binary_id). Create app: ```bash curl -X POST \ 'https://api.gcore.com/fastedge/v1/apps' \ -H 'accept: application/json' \ -H 'client_id: 0' \ -H "Authorization: APIKey $GCORE_API_KEY" \ -H 'Content-Type: application/json' \ -d '{ "name": "my-app-name", "binary": BINARY_ID, "status": 1 }' ``` Your app will be at: `https://my-app-name-XXXX.fastedge.app` ## Useful Patterns ### HTML Response ```rust Response::builder() .status(StatusCode::OK) .header("content-type", "text/html; charset=utf-8") .body(Body::from(html_string)) ``` ### Access Request Headers ```rust let ip = req.headers() .get("x-real-ip") .and_then(|v| v.to_str().ok()) .unwrap_or("unknown"); ``` Common headers provided by FastEdge: - `x-real-ip` - Client IP address - `x-forwarded-for` - Proxied client IP - `geoip-country-code` - Country code - `geoip-city` - City name - `host` - Request host ### Update Existing App ```bash curl -X PUT \ 'https://api.gcore.com/fastedge/v1/apps/APP_ID' \ -H 'accept: application/json' \ -H "Authorization: APIKey $GCORE_API_KEY" \ -H 'Content-Type: application/json' \ -d '{ "binary": NEW_BINARY_ID, "status": 1, "name": "app-name" }' ``` ## Resources - **Template project**: See `assets/rust-template/` for a starter template - **Build script**: See `scripts/build_rust.py` for automated build/upload - **API Docs**: https://gcore.com/docs/fastedge

path: README.md
content: # FastEdge Skill

FastEdge skill for building and deploying WebAssembly apps to Gcore FastEdge.

## Installation

```bash
openclaw skill install fastedge
```

## Usage

After installation, Codex will automatically use this skill when you ask about FastEdge, edge computing, or Wasm deployment.

Example prompts:
- "Deploy this to FastEdge"
- "Create a new FastEdge app"
- "Build a Wasm app for edge computing"

## Structure

```
fastedge-skill/
├── SKILL.md                 # Main skill documentation
├── assets/
│   └── rust-template/       # Starter Rust project template
├── scripts/
│   └── build_rust.py        # Build helper script
```

## License

MIT


path: assets/rust-template/Cargo.toml
content: [package]
name = "fastedge-app"
version = "1.0.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
fastedge = "0.2"

[profile.release]
opt-level = "z"
lto = true
strip = true


path: assets/rust-template/src/lib.rs
content: use fastedge::{
    body::Body,
    http::{Request, Response, StatusCode, Error},
};

#[fastedge::http]
fn main(_req: Request<Body>) -> Result<Response<Body>, Error> {
    Response::builder()
        .status(StatusCode::OK)
        .header("content-type", "text/html; charset=utf-8")
        .body(Body::from(r#"<!DOCTYPE html>
<html><head><title>FastEdge App</title></head>
<body><h1>Hello from FastEdge!</h1></body>
</html>
"#))
}


path: assets/rust-template/.cargo/config.toml
content: [build]
target = "wasm32-wasip1"


path: scripts/build_rust.py
content: #!/usr/bin/env python3
"""Build FastEdge Rust app and optionally deploy."""
import subprocess
import sys
import os
import requests

def build():
    """Build the Wasm binary."""
    # Check for wasm32-wasip1 target
    result = subprocess.run(
        ["rustup", "target", "add", "wasm32-wasip1"],
        capture_output=True,
        text=True
    )
    
    # Build
    result = subprocess.run(
        ["cargo", "build", "--release"],
        capture_output=True,
        text=True
    )
    
    if result.returncode != 0:
        print(f"Build failed:\n{result.stderr}")
        sys.exit(1)
    
    # Find the wasm file
    name = os.path.basename(os.getcwd())
    wasm_path = f"target/wasm32-wasip1/release/{name.replace('-', '_')}.wasm"
    
    if not os.path.exists(wasm_path):
        # Try with original name
        import glob
        wasm_files = glob.glob("target/wasm32-wasip1/release/*.wasm")
        if wasm_files:
            wasm_path = wasm_files[0]
        else:
            print("No wasm file found in target/wasm32-wasip1/release/")
            sys.exit(1)
    
    size = os.path.getsize(wasm_path)
    print(f"✓ Built: {wasm_path} ({size:,} bytes)")
    return wasm_path

def deploy(binary_id: int = None, app_name: str = None, app_id: int = None):
    """Deploy or update a FastEdge app."""
    [REDACTED_SECRET]"GCORE_API_KEY")
    if not [REDACTED_SECRET]"Error: GCORE_API_KEY environment variable not set")
        sys.exit(1)
    
    headers = {
        "Authorization": f"APIKey {api_key}",
        "Content-Type": "application/json",
        "accept": "application/json"
    }
    
    if app_id:
        # Update existing app
        url = f"https://api.gcore.com/fastedge/v1/apps/{app_id}"
        resp = requests.put(
            url,
            headers=headers,
            json={"binary": binary_id, "status": 1, "name": app_name}
        )
    else:
        # Create new app
        url = "https://api.gcore.com/fastedge/v1/apps"
        resp = requests.post(
            url,
            headers=headers,
            json={
                "name": app_name,
                "binary": binary_id,
                "status": 1
            }
        )
    
    if resp.status_code in (200, 201):
        data = resp.json()
        print(f"✓ Deployed: {data.get('url')}")
        print(f"  App ID: {data.get('id')}")
    else:
        print(f"Error: {resp.status_code} - {resp.text}")
        sys.exit(1)

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: build_rust.py build|deploy [OPTIONS]")
        print("  build                    - Build the Wasm binary")
        print("  deploy --app-name NAME   - Create new app")
        print("  deploy --app-id ID --binary-id ID - Update existing app")
        sys.exit(1)
    
    cmd = sys.argv[1]
    
    if cmd == "build":
        build()
    elif cmd == "deploy":
        # Parse simple args
        app_name = None
        app_id = None
        binary_id = None
        
        i = 2
        while i < len(sys.argv):
            if sys.argv[i] == "--app-name":
                app_name = sys.argv[i+1]
                i += 2
            elif sys.argv[i] == "--app-id":
                app_id = int(sys.argv[i+1])
                i += 2
            elif sys.argv[i] == "--binary-id":
                binary_id = int(sys.argv[i+1])
                i += 2
            else:
                i += 1
        
        if not binary_id:
            print("Error: --binary-id required for deploy")
            sys.exit(1)
        
        deploy(binary_id, app_name, app_id)
    else:
        print(f"Unknown command: {cmd}")
        sys.exit(1)


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