Files
finns0309 29920bea56 chore: standardize repo to vendor-skill conventions
Bring pexo-skills up to the structure used by mature vendor skill repos
(HeyGen, Higgsfield) so it reads as a professional, trustworthy source.

Repo-level config:
- LICENSE (MIT) — also fixes the broken license badge in README
- VERSION — single repo-wide version source (0.3.12)
- .codex-plugin/plugin.json + .cursor-plugin/plugin.json — installable in
  Codex and Cursor (was Claude Code only)
- .claude-plugin/marketplace.json — rewritten to the canonical Anthropic
  format; adds the previously-missing pexo-agent skill
- scripts/update-check.sh — opt-in local<->remote VERSION check with cache/snooze

Docs:
- CLAUDE.md — runtime contract (delivery-worker role, hard rules, structure)
- INSTALL_FOR_AGENTS.md + INSTALL.md — agent- and human-facing install
- CONTRIBUTING.md — quality bar + slug convention (name==dir, no brand in
  slug, Use-when/NOT-for descriptions)

GitHub:
- CODEOWNERS, PR template, issue templates (bug + new-skill-request)

Does not touch any SKILL.md content or slugs — that is the next change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 15:21:44 +08:00

125 lines
4.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# pexo-skills update-check — opt-in version check.
# Prints one of:
# JUST_UPGRADED <old> <new> — marker found from a recent upgrade
# UPGRADE_AVAILABLE <old> <new> — remote VERSION differs from local
# (nothing) — up to date, snoozed, disabled, or fetch failed
#
# The pexo-agent skill calls this opportunistically and relays UPGRADE_AVAILABLE
# to the user with the one-line update command. Failure is always silent.
#
# Usage:
# ./scripts/update-check.sh # quiet check
# ./scripts/update-check.sh --force # bust cache and snooze
#
# Env overrides (testing):
# SKILL_DIR — override repo root
# SKILLS_STATE — override ~/.pexo-skills state directory
# REMOTE_URL — override remote VERSION URL
set -euo pipefail
SKILL_DIR="${SKILL_DIR:-$(cd "$(dirname "$0")/.." && pwd)}"
STATE_DIR="${SKILLS_STATE:-$HOME/.pexo-skills}"
CACHE_FILE="$STATE_DIR/last-update-check"
MARKER_FILE="$STATE_DIR/just-upgraded-from"
SNOOZE_FILE="$STATE_DIR/update-snoozed"
VERSION_FILE="$SKILL_DIR/VERSION"
REMOTE_URL="${REMOTE_URL:-https://raw.githubusercontent.com/pexoai/pexo-skills/main/VERSION}"
# ─── Force flag ───────────────────────────────────────────
if [ "${1:-}" = "--force" ]; then
rm -f "$CACHE_FILE" "$SNOOZE_FILE"
fi
# ─── Disabled? ────────────────────────────────────────────
if [ -f "$STATE_DIR/update-check-disabled" ]; then
exit 0
fi
# ─── Snooze helper ────────────────────────────────────────
# Snooze file format: <version> <level> <epoch>
# Levels: 1=24h, 2=48h, 3+=7d. New version resets snooze.
check_snooze() {
local remote_ver="$1"
[ ! -f "$SNOOZE_FILE" ] && return 1
local v l e
v="$(awk '{print $1}' "$SNOOZE_FILE")"
l="$(awk '{print $2}' "$SNOOZE_FILE")"
e="$(awk '{print $3}' "$SNOOZE_FILE")"
[ -z "$v" ] || [ -z "$l" ] || [ -z "$e" ] && return 1
case "$l" in *[!0-9]*) return 1 ;; esac
case "$e" in *[!0-9]*) return 1 ;; esac
[ "$v" != "$remote_ver" ] && return 1 # new version → ignore stale snooze
local d
case "$l" in
1) d=86400 ;;
2) d=172800 ;;
*) d=604800 ;;
esac
local now expires
now="$(date +%s)"
expires=$(( e + d ))
[ "$now" -lt "$expires" ] && return 0
return 1
}
# ─── Step 1: local version ────────────────────────────────
[ ! -f "$VERSION_FILE" ] && exit 0
LOCAL="$(tr -d '[:space:]' < "$VERSION_FILE")"
[ -z "$LOCAL" ] && exit 0
# ─── Step 2: just-upgraded marker ─────────────────────────
if [ -f "$MARKER_FILE" ]; then
OLD="$(tr -d '[:space:]' < "$MARKER_FILE")"
rm -f "$MARKER_FILE" "$SNOOZE_FILE"
[ -n "$OLD" ] && echo "JUST_UPGRADED $OLD $LOCAL"
fi
# ─── Step 3: cache freshness ──────────────────────────────
# UP_TO_DATE: 60min TTL. UPGRADE_AVAILABLE: 720min TTL (nag less).
if [ -f "$CACHE_FILE" ]; then
CACHED="$(cat "$CACHE_FILE")"
case "$CACHED" in
UP_TO_DATE*) TTL=60 ;;
UPGRADE_AVAILABLE*) TTL=720 ;;
*) TTL=0 ;;
esac
STALE=$(find "$CACHE_FILE" -mmin +$TTL 2>/dev/null || true)
if [ -z "$STALE" ] && [ "$TTL" -gt 0 ]; then
case "$CACHED" in
UP_TO_DATE*)
CV="$(echo "$CACHED" | awk '{print $2}')"
[ "$CV" = "$LOCAL" ] && exit 0
;;
UPGRADE_AVAILABLE*)
CO="$(echo "$CACHED" | awk '{print $2}')"
if [ "$CO" = "$LOCAL" ]; then
CN="$(echo "$CACHED" | awk '{print $3}')"
check_snooze "$CN" && exit 0
echo "$CACHED"
exit 0
fi
;;
esac
fi
fi
# ─── Step 4: fetch remote ─────────────────────────────────
mkdir -p "$STATE_DIR"
REMOTE="$(curl -sf --max-time 5 "$REMOTE_URL" 2>/dev/null | tr -d '[:space:]' || true)"
# Validate: looks like a semver. Reject HTML error pages.
if ! echo "$REMOTE" | grep -qE '^[0-9]+\.[0-9.]+$'; then
echo "UP_TO_DATE $LOCAL" > "$CACHE_FILE"
exit 0
fi
if [ "$LOCAL" = "$REMOTE" ]; then
echo "UP_TO_DATE $LOCAL" > "$CACHE_FILE"
exit 0
fi
echo "UPGRADE_AVAILABLE $LOCAL $REMOTE" > "$CACHE_FILE"
check_snooze "$REMOTE" && exit 0
echo "UPGRADE_AVAILABLE $LOCAL $REMOTE"