Add s2-storage skill with reusable upload script
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
eb8da9611e
commit
5dcfd0413d
3 changed files with 92 additions and 2 deletions
|
|
@ -232,10 +232,10 @@ description: Master index of all skills in your robot assistant system. Your ass
|
||||||
**Dependencies:** `yt-dlp` CLI, Python 3
|
**Dependencies:** `yt-dlp` CLI, Python 3
|
||||||
|
|
||||||
### S2 Storage
|
### S2 Storage
|
||||||
**Purpose:** Upload and manage files on S2, a self-hosted file storage service at s2.connorrhodes.com. Provides upload endpoint and auth details for persistent file storage.
|
**Purpose:** Upload and manage files on S2, a self-hosted file storage service at s2.connorrhodes.com. Use `skills/s2-storage/scripts/s2_upload.py` for all uploads — do not rewrite the curl command inline in other skills.
|
||||||
**Triggers:** "upload to s2," "s2," "s2 storage," "upload a file," "store this file"
|
**Triggers:** "upload to s2," "s2," "s2 storage," "upload a file," "store this file"
|
||||||
**File:** `skills/s2-storage/SKILL.md`
|
**File:** `skills/s2-storage/SKILL.md`
|
||||||
**Dependencies:** `curl` CLI
|
**Dependencies:** `uv`, Python `requests`
|
||||||
|
|
||||||
### SilverBullet Query
|
### SilverBullet Query
|
||||||
**Purpose:** Write Space Lua (SLIQ) queries and live filter widgets for SilverBullet notes. Covers filtering pages by folder or tag, listing tasks, showing recently modified notes, building dashboards, and embedding dynamic query expressions in any note.
|
**Purpose:** Write Space Lua (SLIQ) queries and live filter widgets for SilverBullet notes. Covers filtering pages by folder or tag, listing tasks, showing recently modified notes, building dashboards, and embedding dynamic query expressions in any note.
|
||||||
|
|
|
||||||
35
s2-storage/SKILL.md
Normal file
35
s2-storage/SKILL.md
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
name: s2-storage
|
||||||
|
description: Upload and manage files on S2, a self-hosted file storage service at s2.connorrhodes.com. Use when the user says "upload to s2", "store this file", "put this on s2", or when any other skill needs to upload a file and get a persistent URL back.
|
||||||
|
version: 1.0.0
|
||||||
|
---
|
||||||
|
|
||||||
|
# S2 Storage
|
||||||
|
|
||||||
|
Upload files to `s2.connorrhodes.com` via the API and get back a persistent URL.
|
||||||
|
|
||||||
|
## Endpoint
|
||||||
|
|
||||||
|
- **URL:** `POST https://api.connorrhodes.com/agent/s2_upload`
|
||||||
|
- **Auth:** `x-api-key: LT6CXiLT5cEApfqtThz17bENr6OLP804FepOMqa1tZkfTGXiiCcSFlupl6gaYeX`
|
||||||
|
- **Response:** JSON string — the public URL of the uploaded file
|
||||||
|
|
||||||
|
## Script
|
||||||
|
|
||||||
|
Use `scripts/s2_upload.py` for all uploads. Do not rewrite the curl command inline.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Upload and print the URL
|
||||||
|
uv run ~/notes/skills/s2-storage/scripts/s2_upload.py /path/to/file.pdf
|
||||||
|
|
||||||
|
# Upload and delete the local file afterwards
|
||||||
|
uv run ~/notes/skills/s2-storage/scripts/s2_upload.py /path/to/file.pdf --delete
|
||||||
|
```
|
||||||
|
|
||||||
|
The script prints the S2 URL to stdout on success and exits non-zero on failure.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
- Always delete the local file after upload unless the user explicitly wants to keep it. Pass `--delete` to the script.
|
||||||
|
- The returned URL is permanent and publicly accessible — treat it as the canonical reference going forward.
|
||||||
|
- When another skill needs to upload a file (e.g., log-work-expense, brag-sheet), use this script rather than reimplementing the curl call.
|
||||||
55
s2-storage/scripts/s2_upload.py
Normal file
55
s2-storage/scripts/s2_upload.py
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# /// script
|
||||||
|
# requires-python = ">=3.11"
|
||||||
|
# dependencies = ["requests"]
|
||||||
|
# ///
|
||||||
|
"""Upload a file to S2 storage at s2.connorrhodes.com.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
s2_upload.py <file_path> [--delete]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--delete Delete the local file after a successful upload.
|
||||||
|
|
||||||
|
Output:
|
||||||
|
Prints the S2 URL on stdout.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
|
||||||
|
API_KEY = "LT6CXiLT5cEApfqtThz17bENr6OLP804FepOMqa1tZkfTGXiiCcSFlupl6gaYeX"
|
||||||
|
ENDPOINT = "https://api.connorrhodes.com/agent/s2_upload"
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = sys.argv[1:]
|
||||||
|
if not args or args[0] in ("-h", "--help"):
|
||||||
|
print(__doc__)
|
||||||
|
sys.exit(0 if args else 1)
|
||||||
|
|
||||||
|
file_path = args[0]
|
||||||
|
delete_after = "--delete" in args
|
||||||
|
|
||||||
|
if not os.path.isfile(file_path):
|
||||||
|
print(f"Error: file not found: {file_path}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
with open(file_path, "rb") as f:
|
||||||
|
resp = requests.post(
|
||||||
|
ENDPOINT,
|
||||||
|
headers={"x-api-key": API_KEY},
|
||||||
|
files={"file": (os.path.basename(file_path), f)},
|
||||||
|
)
|
||||||
|
|
||||||
|
resp.raise_for_status()
|
||||||
|
url = resp.json() if isinstance(resp.json(), str) else resp.text.strip().strip('"')
|
||||||
|
print(url)
|
||||||
|
|
||||||
|
if delete_after:
|
||||||
|
os.remove(file_path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue