Unify installers on tagged releases
This commit is contained in:
42
.github/workflows/publish.yml
vendored
42
.github/workflows/publish.yml
vendored
@@ -52,6 +52,7 @@ jobs:
|
|||||||
|
|
||||||
build-native-bundles:
|
build-native-bundles:
|
||||||
needs: version-check
|
needs: version-check
|
||||||
|
if: needs.version-check.outputs.should_publish == 'true'
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -97,47 +98,6 @@ jobs:
|
|||||||
name: native-${{ matrix.id }}
|
name: native-${{ matrix.id }}
|
||||||
path: dist/release/*
|
path: dist/release/*
|
||||||
|
|
||||||
release-edge:
|
|
||||||
needs:
|
|
||||||
- version-check
|
|
||||||
- build-native-bundles
|
|
||||||
if: needs.build-native-bundles.result == 'success'
|
|
||||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
path: release-assets
|
|
||||||
merge-multiple: true
|
|
||||||
- shell: bash
|
|
||||||
env:
|
|
||||||
GH_REPO: ${{ github.repository }}
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
VERSION: ${{ needs.version-check.outputs.version }}
|
|
||||||
run: |
|
|
||||||
NOTES="Rolling Feynman bundles from main for the curl/PowerShell installer."
|
|
||||||
if gh release view edge >/dev/null 2>&1; then
|
|
||||||
gh release view edge --json assets --jq '.assets[].name' | while IFS= read -r asset; do
|
|
||||||
[ -n "$asset" ] || continue
|
|
||||||
gh release delete-asset edge "$asset" --yes
|
|
||||||
done
|
|
||||||
gh release upload edge release-assets/*
|
|
||||||
gh release edit edge \
|
|
||||||
--title "edge" \
|
|
||||||
--notes "$NOTES" \
|
|
||||||
--prerelease \
|
|
||||||
--draft=false \
|
|
||||||
--target "$GITHUB_SHA"
|
|
||||||
else
|
|
||||||
gh release create edge release-assets/* \
|
|
||||||
--title "edge" \
|
|
||||||
--notes "$NOTES" \
|
|
||||||
--prerelease \
|
|
||||||
--latest=false \
|
|
||||||
--target "$GITHUB_SHA"
|
|
||||||
fi
|
|
||||||
|
|
||||||
release-github:
|
release-github:
|
||||||
needs:
|
needs:
|
||||||
- version-check
|
- version-check
|
||||||
|
|||||||
@@ -59,3 +59,12 @@ Use this file to track chronology, not release notes. Keep entries short, factua
|
|||||||
- Failed / learned: PowerShell installer behavior was not executed locally because PowerShell is not installed in this environment.
|
- Failed / learned: PowerShell installer behavior was not executed locally because PowerShell is not installed in this environment.
|
||||||
- Blockers: None for the Unix installer flow; Windows remains syntax-only by inspection.
|
- Blockers: None for the Unix installer flow; Windows remains syntax-only by inspection.
|
||||||
- Next: If users want this exposed more prominently, add a dedicated docs/reference page and a homepage-specific skills-only CTA instead of a text link.
|
- Next: If users want this exposed more prominently, add a dedicated docs/reference page and a homepage-specific skills-only CTA instead of a text link.
|
||||||
|
|
||||||
|
### 2026-03-26 18:08 PDT — installer-release-unification
|
||||||
|
|
||||||
|
- Objective: Remove the moving `edge` installer channel and unify installs on tagged releases only.
|
||||||
|
- Changed: Updated `scripts/install/install.sh`, `scripts/install/install.ps1`, `scripts/install/install-skills.sh`, and `scripts/install/install-skills.ps1` so the default target is the latest tagged release, latest-version resolution uses public GitHub release pages instead of `api.github.com`, and explicit `edge` requests now fail with a removal message; removed the `release-edge` job from `.github/workflows/publish.yml`; updated `README.md` and `website/src/content/docs/getting-started/installation.md`; re-synced `website/public/install*`.
|
||||||
|
- Verified: Ran `sh -n` on the Unix installer copies; confirmed `sh scripts/install/install.sh edge` and `sh scripts/install/install-skills.sh edge --dir <tmp>` fail with the intended removal message; executed `sh scripts/install/install.sh` into temp dirs and confirmed the installed binary reports `0.2.14`; executed `sh scripts/install/install-skills.sh --dir <tmp>` and confirmed extracted `SKILL.md` files; ran `cd website && npm run build`.
|
||||||
|
- Failed / learned: The install failure was caused by unauthenticated GitHub API rate limiting on the `edge` path, so renaming channels without removing the API dependency would not have fixed the root cause.
|
||||||
|
- Blockers: `npm run build` still emits a pre-existing duplicate-content warning for `getting-started/installation`; the build succeeds.
|
||||||
|
- Next: If desired, remove the now-unused `stable` alias too and clean up the duplicate docs-content warning separately.
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ curl -fsSL https://feynman.is/install | bash
|
|||||||
irm https://feynman.is/install.ps1 | iex
|
irm https://feynman.is/install.ps1 | iex
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The one-line installer fetches the latest tagged release. To pin a version, pass it explicitly, for example `curl -fsSL https://feynman.is/install | bash -s -- 0.2.14`.
|
||||||
|
|
||||||
If you install via `pnpm` or `bun` instead of the standalone bundle, Feynman requires Node.js `20.19.0` or newer.
|
If you install via `pnpm` or `bun` instead of the standalone bundle, Feynman requires Node.js `20.19.0` or newer.
|
||||||
|
|
||||||
### Skills Only
|
### Skills Only
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
param(
|
param(
|
||||||
[string]$Version = "edge",
|
[string]$Version = "latest",
|
||||||
[ValidateSet("User", "Repo")]
|
[ValidateSet("User", "Repo")]
|
||||||
[string]$Scope = "User",
|
[string]$Scope = "User",
|
||||||
[string]$TargetDir = ""
|
[string]$TargetDir = ""
|
||||||
@@ -11,37 +11,34 @@ function Normalize-Version {
|
|||||||
param([string]$RequestedVersion)
|
param([string]$RequestedVersion)
|
||||||
|
|
||||||
if (-not $RequestedVersion) {
|
if (-not $RequestedVersion) {
|
||||||
return "edge"
|
return "latest"
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($RequestedVersion.ToLowerInvariant()) {
|
switch ($RequestedVersion.ToLowerInvariant()) {
|
||||||
"edge" { return "edge" }
|
|
||||||
"latest" { return "latest" }
|
"latest" { return "latest" }
|
||||||
"stable" { return "latest" }
|
"stable" { return "latest" }
|
||||||
|
"edge" { throw "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." }
|
||||||
default { return $RequestedVersion.TrimStart("v") }
|
default { return $RequestedVersion.TrimStart("v") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Resolve-LatestReleaseVersion {
|
||||||
|
$page = Invoke-WebRequest -Uri "https://github.com/getcompanion-ai/feynman/releases/latest"
|
||||||
|
$match = [regex]::Match($page.Content, 'releases/tag/v([0-9][^"''<>\s]*)')
|
||||||
|
if (-not $match.Success) {
|
||||||
|
throw "Failed to resolve the latest Feynman release version."
|
||||||
|
}
|
||||||
|
|
||||||
|
return $match.Groups[1].Value
|
||||||
|
}
|
||||||
|
|
||||||
function Resolve-VersionMetadata {
|
function Resolve-VersionMetadata {
|
||||||
param([string]$RequestedVersion)
|
param([string]$RequestedVersion)
|
||||||
|
|
||||||
$normalizedVersion = Normalize-Version -RequestedVersion $RequestedVersion
|
$normalizedVersion = Normalize-Version -RequestedVersion $RequestedVersion
|
||||||
|
|
||||||
if ($normalizedVersion -eq "edge") {
|
|
||||||
return [PSCustomObject]@{
|
|
||||||
ResolvedVersion = "edge"
|
|
||||||
GitRef = "main"
|
|
||||||
DownloadUrl = "https://github.com/getcompanion-ai/feynman/archive/refs/heads/main.zip"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($normalizedVersion -eq "latest") {
|
if ($normalizedVersion -eq "latest") {
|
||||||
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest"
|
$resolvedVersion = Resolve-LatestReleaseVersion
|
||||||
if (-not $release.tag_name) {
|
|
||||||
throw "Failed to resolve the latest Feynman release version."
|
|
||||||
}
|
|
||||||
|
|
||||||
$resolvedVersion = $release.tag_name.TrimStart("v")
|
|
||||||
} else {
|
} else {
|
||||||
$resolvedVersion = $normalizedVersion
|
$resolvedVersion = $normalizedVersion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
VERSION="edge"
|
VERSION="latest"
|
||||||
SCOPE="${FEYNMAN_SKILLS_SCOPE:-user}"
|
SCOPE="${FEYNMAN_SKILLS_SCOPE:-user}"
|
||||||
TARGET_DIR="${FEYNMAN_SKILLS_DIR:-}"
|
TARGET_DIR="${FEYNMAN_SKILLS_DIR:-}"
|
||||||
|
|
||||||
@@ -12,12 +12,16 @@ step() {
|
|||||||
|
|
||||||
normalize_version() {
|
normalize_version() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
"" | edge)
|
"")
|
||||||
printf 'edge\n'
|
printf 'latest\n'
|
||||||
;;
|
;;
|
||||||
latest | stable)
|
latest | stable)
|
||||||
printf 'latest\n'
|
printf 'latest\n'
|
||||||
;;
|
;;
|
||||||
|
edge)
|
||||||
|
echo "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
v*)
|
v*)
|
||||||
printf '%s\n' "${1#v}"
|
printf '%s\n' "${1#v}"
|
||||||
;;
|
;;
|
||||||
@@ -73,14 +77,9 @@ download_text() {
|
|||||||
resolve_version() {
|
resolve_version() {
|
||||||
normalized_version="$(normalize_version "$VERSION")"
|
normalized_version="$(normalize_version "$VERSION")"
|
||||||
|
|
||||||
if [ "$normalized_version" = "edge" ]; then
|
|
||||||
printf 'edge\nmain\n'
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$normalized_version" = "latest" ]; then
|
if [ "$normalized_version" = "latest" ]; then
|
||||||
release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest")"
|
release_page="$(download_text "https://github.com/getcompanion-ai/feynman/releases/latest")"
|
||||||
resolved_version="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"v\([^"]*\)".*/\1/p' | head -n 1)"
|
resolved_version="$(printf '%s\n' "$release_page" | sed -n 's@.*releases/tag/v\([0-9][^"<>[:space:]]*\).*@\1@p' | head -n 1)"
|
||||||
|
|
||||||
if [ -z "$resolved_version" ]; then
|
if [ -z "$resolved_version" ]; then
|
||||||
echo "Failed to resolve the latest Feynman release version." >&2
|
echo "Failed to resolve the latest Feynman release version." >&2
|
||||||
@@ -125,7 +124,7 @@ while [ $# -gt 0 ]; do
|
|||||||
;;
|
;;
|
||||||
--dir)
|
--dir)
|
||||||
if [ $# -lt 2 ]; then
|
if [ $# -lt 2 ]; then
|
||||||
echo "Usage: install-skills.sh [edge|stable|latest|<version>] [--user|--repo] [--dir <path>]" >&2
|
echo "Usage: install-skills.sh [stable|latest|<version>] [--user|--repo] [--dir <path>]" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
TARGET_DIR="$2"
|
TARGET_DIR="$2"
|
||||||
@@ -136,7 +135,7 @@ while [ $# -gt 0 ]; do
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Unknown argument: $1" >&2
|
echo "Unknown argument: $1" >&2
|
||||||
echo "Usage: install-skills.sh [edge|stable|latest|<version>] [--user|--repo] [--dir <path>]" >&2
|
echo "Usage: install-skills.sh [stable|latest|<version>] [--user|--repo] [--dir <path>]" >&2
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
param(
|
param(
|
||||||
[string]$Version = "edge"
|
[string]$Version = "latest"
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
@@ -8,17 +8,27 @@ function Normalize-Version {
|
|||||||
param([string]$RequestedVersion)
|
param([string]$RequestedVersion)
|
||||||
|
|
||||||
if (-not $RequestedVersion) {
|
if (-not $RequestedVersion) {
|
||||||
return "edge"
|
return "latest"
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($RequestedVersion.ToLowerInvariant()) {
|
switch ($RequestedVersion.ToLowerInvariant()) {
|
||||||
"edge" { return "edge" }
|
|
||||||
"latest" { return "latest" }
|
"latest" { return "latest" }
|
||||||
"stable" { return "latest" }
|
"stable" { return "latest" }
|
||||||
|
"edge" { throw "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." }
|
||||||
default { return $RequestedVersion.TrimStart("v") }
|
default { return $RequestedVersion.TrimStart("v") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Resolve-LatestReleaseVersion {
|
||||||
|
$page = Invoke-WebRequest -Uri "https://github.com/getcompanion-ai/feynman/releases/latest"
|
||||||
|
$match = [regex]::Match($page.Content, 'releases/tag/v([0-9][^"''<>\s]*)')
|
||||||
|
if (-not $match.Success) {
|
||||||
|
throw "Failed to resolve the latest Feynman release version."
|
||||||
|
}
|
||||||
|
|
||||||
|
return $match.Groups[1].Value
|
||||||
|
}
|
||||||
|
|
||||||
function Resolve-ReleaseMetadata {
|
function Resolve-ReleaseMetadata {
|
||||||
param(
|
param(
|
||||||
[string]$RequestedVersion,
|
[string]$RequestedVersion,
|
||||||
@@ -28,34 +38,8 @@ function Resolve-ReleaseMetadata {
|
|||||||
|
|
||||||
$normalizedVersion = Normalize-Version -RequestedVersion $RequestedVersion
|
$normalizedVersion = Normalize-Version -RequestedVersion $RequestedVersion
|
||||||
|
|
||||||
if ($normalizedVersion -eq "edge") {
|
|
||||||
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/tags/edge"
|
|
||||||
$asset = $release.assets | Where-Object { $_.name -like "feynman-*-$AssetTarget.$BundleExtension" } | Select-Object -First 1
|
|
||||||
if (-not $asset) {
|
|
||||||
throw "Failed to resolve the latest Feynman edge bundle."
|
|
||||||
}
|
|
||||||
|
|
||||||
$archiveName = $asset.name
|
|
||||||
$suffix = ".$BundleExtension"
|
|
||||||
$bundleName = $archiveName.Substring(0, $archiveName.Length - $suffix.Length)
|
|
||||||
$resolvedVersion = $bundleName.Substring("feynman-".Length)
|
|
||||||
$resolvedVersion = $resolvedVersion.Substring(0, $resolvedVersion.Length - ("-$AssetTarget").Length)
|
|
||||||
|
|
||||||
return [PSCustomObject]@{
|
|
||||||
ResolvedVersion = $resolvedVersion
|
|
||||||
BundleName = $bundleName
|
|
||||||
ArchiveName = $archiveName
|
|
||||||
DownloadUrl = $asset.browser_download_url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($normalizedVersion -eq "latest") {
|
if ($normalizedVersion -eq "latest") {
|
||||||
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest"
|
$resolvedVersion = Resolve-LatestReleaseVersion
|
||||||
if (-not $release.tag_name) {
|
|
||||||
throw "Failed to resolve the latest Feynman release version."
|
|
||||||
}
|
|
||||||
|
|
||||||
$resolvedVersion = $release.tag_name.TrimStart("v")
|
|
||||||
} else {
|
} else {
|
||||||
$resolvedVersion = $normalizedVersion
|
$resolvedVersion = $normalizedVersion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
VERSION="${1:-edge}"
|
VERSION="${1:-latest}"
|
||||||
INSTALL_BIN_DIR="${FEYNMAN_INSTALL_BIN_DIR:-$HOME/.local/bin}"
|
INSTALL_BIN_DIR="${FEYNMAN_INSTALL_BIN_DIR:-$HOME/.local/bin}"
|
||||||
INSTALL_APP_DIR="${FEYNMAN_INSTALL_APP_DIR:-$HOME/.local/share/feynman}"
|
INSTALL_APP_DIR="${FEYNMAN_INSTALL_APP_DIR:-$HOME/.local/share/feynman}"
|
||||||
SKIP_PATH_UPDATE="${FEYNMAN_INSTALL_SKIP_PATH_UPDATE:-0}"
|
SKIP_PATH_UPDATE="${FEYNMAN_INSTALL_SKIP_PATH_UPDATE:-0}"
|
||||||
@@ -54,12 +54,16 @@ run_with_spinner() {
|
|||||||
|
|
||||||
normalize_version() {
|
normalize_version() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
"" | edge)
|
"")
|
||||||
printf 'edge\n'
|
printf 'latest\n'
|
||||||
;;
|
;;
|
||||||
latest | stable)
|
latest | stable)
|
||||||
printf 'latest\n'
|
printf 'latest\n'
|
||||||
;;
|
;;
|
||||||
|
edge)
|
||||||
|
echo "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
v*)
|
v*)
|
||||||
printf '%s\n' "${1#v}"
|
printf '%s\n' "${1#v}"
|
||||||
;;
|
;;
|
||||||
@@ -184,36 +188,9 @@ warn_command_conflict() {
|
|||||||
resolve_release_metadata() {
|
resolve_release_metadata() {
|
||||||
normalized_version="$(normalize_version "$VERSION")"
|
normalized_version="$(normalize_version "$VERSION")"
|
||||||
|
|
||||||
if [ "$normalized_version" = "edge" ]; then
|
|
||||||
release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/tags/edge")"
|
|
||||||
asset_url=""
|
|
||||||
|
|
||||||
for candidate in $(printf '%s\n' "$release_json" | sed -n 's/.*"browser_download_url":[[:space:]]*"\([^"]*\)".*/\1/p'); do
|
|
||||||
case "$candidate" in
|
|
||||||
*/feynman-*-${asset_target}.${archive_extension})
|
|
||||||
asset_url="$candidate"
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "$asset_url" ]; then
|
|
||||||
echo "Failed to resolve the latest Feynman edge bundle." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
archive_name="${asset_url##*/}"
|
|
||||||
bundle_name="${archive_name%.$archive_extension}"
|
|
||||||
resolved_version="${bundle_name#feynman-}"
|
|
||||||
resolved_version="${resolved_version%-${asset_target}}"
|
|
||||||
|
|
||||||
printf '%s\n%s\n%s\n%s\n' "$resolved_version" "$bundle_name" "$archive_name" "$asset_url"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$normalized_version" = "latest" ]; then
|
if [ "$normalized_version" = "latest" ]; then
|
||||||
release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest")"
|
release_page="$(download_text "https://github.com/getcompanion-ai/feynman/releases/latest")"
|
||||||
resolved_version="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"v\([^"]*\)".*/\1/p' | head -n 1)"
|
resolved_version="$(printf '%s\n' "$release_page" | sed -n 's@.*releases/tag/v\([0-9][^"<>[:space:]]*\).*@\1@p' | head -n 1)"
|
||||||
|
|
||||||
if [ -z "$resolved_version" ]; then
|
if [ -z "$resolved_version" ]; then
|
||||||
echo "Failed to resolve the latest Feynman release version." >&2
|
echo "Failed to resolve the latest Feynman release version." >&2
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
VERSION="${1:-edge}"
|
VERSION="${1:-latest}"
|
||||||
INSTALL_BIN_DIR="${FEYNMAN_INSTALL_BIN_DIR:-$HOME/.local/bin}"
|
INSTALL_BIN_DIR="${FEYNMAN_INSTALL_BIN_DIR:-$HOME/.local/bin}"
|
||||||
INSTALL_APP_DIR="${FEYNMAN_INSTALL_APP_DIR:-$HOME/.local/share/feynman}"
|
INSTALL_APP_DIR="${FEYNMAN_INSTALL_APP_DIR:-$HOME/.local/share/feynman}"
|
||||||
SKIP_PATH_UPDATE="${FEYNMAN_INSTALL_SKIP_PATH_UPDATE:-0}"
|
SKIP_PATH_UPDATE="${FEYNMAN_INSTALL_SKIP_PATH_UPDATE:-0}"
|
||||||
@@ -54,12 +54,16 @@ run_with_spinner() {
|
|||||||
|
|
||||||
normalize_version() {
|
normalize_version() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
"" | edge)
|
"")
|
||||||
printf 'edge\n'
|
printf 'latest\n'
|
||||||
;;
|
;;
|
||||||
latest | stable)
|
latest | stable)
|
||||||
printf 'latest\n'
|
printf 'latest\n'
|
||||||
;;
|
;;
|
||||||
|
edge)
|
||||||
|
echo "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
v*)
|
v*)
|
||||||
printf '%s\n' "${1#v}"
|
printf '%s\n' "${1#v}"
|
||||||
;;
|
;;
|
||||||
@@ -184,36 +188,9 @@ warn_command_conflict() {
|
|||||||
resolve_release_metadata() {
|
resolve_release_metadata() {
|
||||||
normalized_version="$(normalize_version "$VERSION")"
|
normalized_version="$(normalize_version "$VERSION")"
|
||||||
|
|
||||||
if [ "$normalized_version" = "edge" ]; then
|
|
||||||
release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/tags/edge")"
|
|
||||||
asset_url=""
|
|
||||||
|
|
||||||
for candidate in $(printf '%s\n' "$release_json" | sed -n 's/.*"browser_download_url":[[:space:]]*"\([^"]*\)".*/\1/p'); do
|
|
||||||
case "$candidate" in
|
|
||||||
*/feynman-*-${asset_target}.${archive_extension})
|
|
||||||
asset_url="$candidate"
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "$asset_url" ]; then
|
|
||||||
echo "Failed to resolve the latest Feynman edge bundle." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
archive_name="${asset_url##*/}"
|
|
||||||
bundle_name="${archive_name%.$archive_extension}"
|
|
||||||
resolved_version="${bundle_name#feynman-}"
|
|
||||||
resolved_version="${resolved_version%-${asset_target}}"
|
|
||||||
|
|
||||||
printf '%s\n%s\n%s\n%s\n' "$resolved_version" "$bundle_name" "$archive_name" "$asset_url"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$normalized_version" = "latest" ]; then
|
if [ "$normalized_version" = "latest" ]; then
|
||||||
release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest")"
|
release_page="$(download_text "https://github.com/getcompanion-ai/feynman/releases/latest")"
|
||||||
resolved_version="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"v\([^"]*\)".*/\1/p' | head -n 1)"
|
resolved_version="$(printf '%s\n' "$release_page" | sed -n 's@.*releases/tag/v\([0-9][^"<>[:space:]]*\).*@\1@p' | head -n 1)"
|
||||||
|
|
||||||
if [ -z "$resolved_version" ]; then
|
if [ -z "$resolved_version" ]; then
|
||||||
echo "Failed to resolve the latest Feynman release version." >&2
|
echo "Failed to resolve the latest Feynman release version." >&2
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
VERSION="edge"
|
VERSION="latest"
|
||||||
SCOPE="${FEYNMAN_SKILLS_SCOPE:-user}"
|
SCOPE="${FEYNMAN_SKILLS_SCOPE:-user}"
|
||||||
TARGET_DIR="${FEYNMAN_SKILLS_DIR:-}"
|
TARGET_DIR="${FEYNMAN_SKILLS_DIR:-}"
|
||||||
|
|
||||||
@@ -12,12 +12,16 @@ step() {
|
|||||||
|
|
||||||
normalize_version() {
|
normalize_version() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
"" | edge)
|
"")
|
||||||
printf 'edge\n'
|
printf 'latest\n'
|
||||||
;;
|
;;
|
||||||
latest | stable)
|
latest | stable)
|
||||||
printf 'latest\n'
|
printf 'latest\n'
|
||||||
;;
|
;;
|
||||||
|
edge)
|
||||||
|
echo "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
v*)
|
v*)
|
||||||
printf '%s\n' "${1#v}"
|
printf '%s\n' "${1#v}"
|
||||||
;;
|
;;
|
||||||
@@ -73,14 +77,9 @@ download_text() {
|
|||||||
resolve_version() {
|
resolve_version() {
|
||||||
normalized_version="$(normalize_version "$VERSION")"
|
normalized_version="$(normalize_version "$VERSION")"
|
||||||
|
|
||||||
if [ "$normalized_version" = "edge" ]; then
|
|
||||||
printf 'edge\nmain\n'
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$normalized_version" = "latest" ]; then
|
if [ "$normalized_version" = "latest" ]; then
|
||||||
release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest")"
|
release_page="$(download_text "https://github.com/getcompanion-ai/feynman/releases/latest")"
|
||||||
resolved_version="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"v\([^"]*\)".*/\1/p' | head -n 1)"
|
resolved_version="$(printf '%s\n' "$release_page" | sed -n 's@.*releases/tag/v\([0-9][^"<>[:space:]]*\).*@\1@p' | head -n 1)"
|
||||||
|
|
||||||
if [ -z "$resolved_version" ]; then
|
if [ -z "$resolved_version" ]; then
|
||||||
echo "Failed to resolve the latest Feynman release version." >&2
|
echo "Failed to resolve the latest Feynman release version." >&2
|
||||||
@@ -125,7 +124,7 @@ while [ $# -gt 0 ]; do
|
|||||||
;;
|
;;
|
||||||
--dir)
|
--dir)
|
||||||
if [ $# -lt 2 ]; then
|
if [ $# -lt 2 ]; then
|
||||||
echo "Usage: install-skills.sh [edge|stable|latest|<version>] [--user|--repo] [--dir <path>]" >&2
|
echo "Usage: install-skills.sh [stable|latest|<version>] [--user|--repo] [--dir <path>]" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
TARGET_DIR="$2"
|
TARGET_DIR="$2"
|
||||||
@@ -136,7 +135,7 @@ while [ $# -gt 0 ]; do
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Unknown argument: $1" >&2
|
echo "Unknown argument: $1" >&2
|
||||||
echo "Usage: install-skills.sh [edge|stable|latest|<version>] [--user|--repo] [--dir <path>]" >&2
|
echo "Usage: install-skills.sh [stable|latest|<version>] [--user|--repo] [--dir <path>]" >&2
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
param(
|
param(
|
||||||
[string]$Version = "edge",
|
[string]$Version = "latest",
|
||||||
[ValidateSet("User", "Repo")]
|
[ValidateSet("User", "Repo")]
|
||||||
[string]$Scope = "User",
|
[string]$Scope = "User",
|
||||||
[string]$TargetDir = ""
|
[string]$TargetDir = ""
|
||||||
@@ -11,37 +11,34 @@ function Normalize-Version {
|
|||||||
param([string]$RequestedVersion)
|
param([string]$RequestedVersion)
|
||||||
|
|
||||||
if (-not $RequestedVersion) {
|
if (-not $RequestedVersion) {
|
||||||
return "edge"
|
return "latest"
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($RequestedVersion.ToLowerInvariant()) {
|
switch ($RequestedVersion.ToLowerInvariant()) {
|
||||||
"edge" { return "edge" }
|
|
||||||
"latest" { return "latest" }
|
"latest" { return "latest" }
|
||||||
"stable" { return "latest" }
|
"stable" { return "latest" }
|
||||||
|
"edge" { throw "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." }
|
||||||
default { return $RequestedVersion.TrimStart("v") }
|
default { return $RequestedVersion.TrimStart("v") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Resolve-LatestReleaseVersion {
|
||||||
|
$page = Invoke-WebRequest -Uri "https://github.com/getcompanion-ai/feynman/releases/latest"
|
||||||
|
$match = [regex]::Match($page.Content, 'releases/tag/v([0-9][^"''<>\s]*)')
|
||||||
|
if (-not $match.Success) {
|
||||||
|
throw "Failed to resolve the latest Feynman release version."
|
||||||
|
}
|
||||||
|
|
||||||
|
return $match.Groups[1].Value
|
||||||
|
}
|
||||||
|
|
||||||
function Resolve-VersionMetadata {
|
function Resolve-VersionMetadata {
|
||||||
param([string]$RequestedVersion)
|
param([string]$RequestedVersion)
|
||||||
|
|
||||||
$normalizedVersion = Normalize-Version -RequestedVersion $RequestedVersion
|
$normalizedVersion = Normalize-Version -RequestedVersion $RequestedVersion
|
||||||
|
|
||||||
if ($normalizedVersion -eq "edge") {
|
|
||||||
return [PSCustomObject]@{
|
|
||||||
ResolvedVersion = "edge"
|
|
||||||
GitRef = "main"
|
|
||||||
DownloadUrl = "https://github.com/getcompanion-ai/feynman/archive/refs/heads/main.zip"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($normalizedVersion -eq "latest") {
|
if ($normalizedVersion -eq "latest") {
|
||||||
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest"
|
$resolvedVersion = Resolve-LatestReleaseVersion
|
||||||
if (-not $release.tag_name) {
|
|
||||||
throw "Failed to resolve the latest Feynman release version."
|
|
||||||
}
|
|
||||||
|
|
||||||
$resolvedVersion = $release.tag_name.TrimStart("v")
|
|
||||||
} else {
|
} else {
|
||||||
$resolvedVersion = $normalizedVersion
|
$resolvedVersion = $normalizedVersion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
param(
|
param(
|
||||||
[string]$Version = "edge"
|
[string]$Version = "latest"
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
@@ -8,17 +8,27 @@ function Normalize-Version {
|
|||||||
param([string]$RequestedVersion)
|
param([string]$RequestedVersion)
|
||||||
|
|
||||||
if (-not $RequestedVersion) {
|
if (-not $RequestedVersion) {
|
||||||
return "edge"
|
return "latest"
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($RequestedVersion.ToLowerInvariant()) {
|
switch ($RequestedVersion.ToLowerInvariant()) {
|
||||||
"edge" { return "edge" }
|
|
||||||
"latest" { return "latest" }
|
"latest" { return "latest" }
|
||||||
"stable" { return "latest" }
|
"stable" { return "latest" }
|
||||||
|
"edge" { throw "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." }
|
||||||
default { return $RequestedVersion.TrimStart("v") }
|
default { return $RequestedVersion.TrimStart("v") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Resolve-LatestReleaseVersion {
|
||||||
|
$page = Invoke-WebRequest -Uri "https://github.com/getcompanion-ai/feynman/releases/latest"
|
||||||
|
$match = [regex]::Match($page.Content, 'releases/tag/v([0-9][^"''<>\s]*)')
|
||||||
|
if (-not $match.Success) {
|
||||||
|
throw "Failed to resolve the latest Feynman release version."
|
||||||
|
}
|
||||||
|
|
||||||
|
return $match.Groups[1].Value
|
||||||
|
}
|
||||||
|
|
||||||
function Resolve-ReleaseMetadata {
|
function Resolve-ReleaseMetadata {
|
||||||
param(
|
param(
|
||||||
[string]$RequestedVersion,
|
[string]$RequestedVersion,
|
||||||
@@ -28,34 +38,8 @@ function Resolve-ReleaseMetadata {
|
|||||||
|
|
||||||
$normalizedVersion = Normalize-Version -RequestedVersion $RequestedVersion
|
$normalizedVersion = Normalize-Version -RequestedVersion $RequestedVersion
|
||||||
|
|
||||||
if ($normalizedVersion -eq "edge") {
|
|
||||||
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/tags/edge"
|
|
||||||
$asset = $release.assets | Where-Object { $_.name -like "feynman-*-$AssetTarget.$BundleExtension" } | Select-Object -First 1
|
|
||||||
if (-not $asset) {
|
|
||||||
throw "Failed to resolve the latest Feynman edge bundle."
|
|
||||||
}
|
|
||||||
|
|
||||||
$archiveName = $asset.name
|
|
||||||
$suffix = ".$BundleExtension"
|
|
||||||
$bundleName = $archiveName.Substring(0, $archiveName.Length - $suffix.Length)
|
|
||||||
$resolvedVersion = $bundleName.Substring("feynman-".Length)
|
|
||||||
$resolvedVersion = $resolvedVersion.Substring(0, $resolvedVersion.Length - ("-$AssetTarget").Length)
|
|
||||||
|
|
||||||
return [PSCustomObject]@{
|
|
||||||
ResolvedVersion = $resolvedVersion
|
|
||||||
BundleName = $bundleName
|
|
||||||
ArchiveName = $archiveName
|
|
||||||
DownloadUrl = $asset.browser_download_url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($normalizedVersion -eq "latest") {
|
if ($normalizedVersion -eq "latest") {
|
||||||
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest"
|
$resolvedVersion = Resolve-LatestReleaseVersion
|
||||||
if (-not $release.tag_name) {
|
|
||||||
throw "Failed to resolve the latest Feynman release version."
|
|
||||||
}
|
|
||||||
|
|
||||||
$resolvedVersion = $release.tag_name.TrimStart("v")
|
|
||||||
} else {
|
} else {
|
||||||
$resolvedVersion = $normalizedVersion
|
$resolvedVersion = $normalizedVersion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ The installer detects your OS and architecture automatically. On macOS it suppor
|
|||||||
|
|
||||||
If you previously installed Feynman via `npm`, `pnpm`, or `bun` and still see local Node.js errors after a curl install, your shell is probably still resolving the older global binary first. Run `which -a feynman`, then `hash -r`, or launch the standalone shim directly with `~/.local/bin/feynman`.
|
If you previously installed Feynman via `npm`, `pnpm`, or `bun` and still see local Node.js errors after a curl install, your shell is probably still resolving the older global binary first. Run `which -a feynman`, then `hash -r`, or launch the standalone shim directly with `~/.local/bin/feynman`.
|
||||||
|
|
||||||
By default, the one-line installer tracks the rolling `edge` channel from `main`.
|
|
||||||
|
|
||||||
On **Windows**, open PowerShell as Administrator and run:
|
On **Windows**, open PowerShell as Administrator and run:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
@@ -59,22 +57,20 @@ Or install them repo-locally:
|
|||||||
|
|
||||||
These installers download only the `skills/` tree from the Feynman repository. They do not install the Feynman terminal, bundled Node runtime, auth storage, or Pi packages.
|
These installers download only the `skills/` tree from the Feynman repository. They do not install the Feynman terminal, bundled Node runtime, auth storage, or Pi packages.
|
||||||
|
|
||||||
## Stable or pinned releases
|
## Pinned releases
|
||||||
|
|
||||||
If you want the latest tagged release instead of the rolling `edge` channel:
|
The one-line installer already targets the latest tagged release. To pin an exact version, pass it explicitly:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://feynman.is/install | bash -s -- stable
|
curl -fsSL https://feynman.is/install | bash -s -- 0.2.14
|
||||||
```
|
```
|
||||||
|
|
||||||
On Windows:
|
On Windows:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
& ([scriptblock]::Create((irm https://feynman.is/install.ps1))) -Version stable
|
& ([scriptblock]::Create((irm https://feynman.is/install.ps1))) -Version 0.2.14
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also pin an exact version by replacing `stable` with a version such as `0.2.14`.
|
|
||||||
|
|
||||||
## pnpm
|
## pnpm
|
||||||
|
|
||||||
If you already have Node.js `20.19.0` or newer installed, you can install Feynman globally via `pnpm`:
|
If you already have Node.js `20.19.0` or newer installed, you can install Feynman globally via `pnpm`:
|
||||||
|
|||||||
Reference in New Issue
Block a user