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:
|
||||
needs: version-check
|
||||
if: needs.version-check.outputs.should_publish == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -97,47 +98,6 @@ jobs:
|
||||
name: native-${{ matrix.id }}
|
||||
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:
|
||||
needs:
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
### 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
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
### Skills Only
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
param(
|
||||
[string]$Version = "edge",
|
||||
[string]$Version = "latest",
|
||||
[ValidateSet("User", "Repo")]
|
||||
[string]$Scope = "User",
|
||||
[string]$TargetDir = ""
|
||||
@@ -11,37 +11,34 @@ function Normalize-Version {
|
||||
param([string]$RequestedVersion)
|
||||
|
||||
if (-not $RequestedVersion) {
|
||||
return "edge"
|
||||
return "latest"
|
||||
}
|
||||
|
||||
switch ($RequestedVersion.ToLowerInvariant()) {
|
||||
"edge" { return "edge" }
|
||||
"latest" { 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") }
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
param([string]$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") {
|
||||
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest"
|
||||
if (-not $release.tag_name) {
|
||||
throw "Failed to resolve the latest Feynman release version."
|
||||
}
|
||||
|
||||
$resolvedVersion = $release.tag_name.TrimStart("v")
|
||||
$resolvedVersion = Resolve-LatestReleaseVersion
|
||||
} else {
|
||||
$resolvedVersion = $normalizedVersion
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
set -eu
|
||||
|
||||
VERSION="edge"
|
||||
VERSION="latest"
|
||||
SCOPE="${FEYNMAN_SKILLS_SCOPE:-user}"
|
||||
TARGET_DIR="${FEYNMAN_SKILLS_DIR:-}"
|
||||
|
||||
@@ -12,12 +12,16 @@ step() {
|
||||
|
||||
normalize_version() {
|
||||
case "$1" in
|
||||
"" | edge)
|
||||
printf 'edge\n'
|
||||
"")
|
||||
printf 'latest\n'
|
||||
;;
|
||||
latest | stable)
|
||||
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*)
|
||||
printf '%s\n' "${1#v}"
|
||||
;;
|
||||
@@ -73,14 +77,9 @@ download_text() {
|
||||
resolve_version() {
|
||||
normalized_version="$(normalize_version "$VERSION")"
|
||||
|
||||
if [ "$normalized_version" = "edge" ]; then
|
||||
printf 'edge\nmain\n'
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$normalized_version" = "latest" ]; then
|
||||
release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest")"
|
||||
resolved_version="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"v\([^"]*\)".*/\1/p' | head -n 1)"
|
||||
release_page="$(download_text "https://github.com/getcompanion-ai/feynman/releases/latest")"
|
||||
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
|
||||
echo "Failed to resolve the latest Feynman release version." >&2
|
||||
@@ -125,7 +124,7 @@ while [ $# -gt 0 ]; do
|
||||
;;
|
||||
--dir)
|
||||
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
|
||||
fi
|
||||
TARGET_DIR="$2"
|
||||
@@ -136,7 +135,7 @@ while [ $# -gt 0 ]; do
|
||||
;;
|
||||
*)
|
||||
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
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
param(
|
||||
[string]$Version = "edge"
|
||||
[string]$Version = "latest"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
@@ -8,17 +8,27 @@ function Normalize-Version {
|
||||
param([string]$RequestedVersion)
|
||||
|
||||
if (-not $RequestedVersion) {
|
||||
return "edge"
|
||||
return "latest"
|
||||
}
|
||||
|
||||
switch ($RequestedVersion.ToLowerInvariant()) {
|
||||
"edge" { return "edge" }
|
||||
"latest" { 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") }
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
param(
|
||||
[string]$RequestedVersion,
|
||||
@@ -28,34 +38,8 @@ function Resolve-ReleaseMetadata {
|
||||
|
||||
$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") {
|
||||
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest"
|
||||
if (-not $release.tag_name) {
|
||||
throw "Failed to resolve the latest Feynman release version."
|
||||
}
|
||||
|
||||
$resolvedVersion = $release.tag_name.TrimStart("v")
|
||||
$resolvedVersion = Resolve-LatestReleaseVersion
|
||||
} else {
|
||||
$resolvedVersion = $normalizedVersion
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
set -eu
|
||||
|
||||
VERSION="${1:-edge}"
|
||||
VERSION="${1:-latest}"
|
||||
INSTALL_BIN_DIR="${FEYNMAN_INSTALL_BIN_DIR:-$HOME/.local/bin}"
|
||||
INSTALL_APP_DIR="${FEYNMAN_INSTALL_APP_DIR:-$HOME/.local/share/feynman}"
|
||||
SKIP_PATH_UPDATE="${FEYNMAN_INSTALL_SKIP_PATH_UPDATE:-0}"
|
||||
@@ -54,12 +54,16 @@ run_with_spinner() {
|
||||
|
||||
normalize_version() {
|
||||
case "$1" in
|
||||
"" | edge)
|
||||
printf 'edge\n'
|
||||
"")
|
||||
printf 'latest\n'
|
||||
;;
|
||||
latest | stable)
|
||||
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*)
|
||||
printf '%s\n' "${1#v}"
|
||||
;;
|
||||
@@ -184,36 +188,9 @@ warn_command_conflict() {
|
||||
resolve_release_metadata() {
|
||||
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
|
||||
release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest")"
|
||||
resolved_version="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"v\([^"]*\)".*/\1/p' | head -n 1)"
|
||||
release_page="$(download_text "https://github.com/getcompanion-ai/feynman/releases/latest")"
|
||||
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
|
||||
echo "Failed to resolve the latest Feynman release version." >&2
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
set -eu
|
||||
|
||||
VERSION="${1:-edge}"
|
||||
VERSION="${1:-latest}"
|
||||
INSTALL_BIN_DIR="${FEYNMAN_INSTALL_BIN_DIR:-$HOME/.local/bin}"
|
||||
INSTALL_APP_DIR="${FEYNMAN_INSTALL_APP_DIR:-$HOME/.local/share/feynman}"
|
||||
SKIP_PATH_UPDATE="${FEYNMAN_INSTALL_SKIP_PATH_UPDATE:-0}"
|
||||
@@ -54,12 +54,16 @@ run_with_spinner() {
|
||||
|
||||
normalize_version() {
|
||||
case "$1" in
|
||||
"" | edge)
|
||||
printf 'edge\n'
|
||||
"")
|
||||
printf 'latest\n'
|
||||
;;
|
||||
latest | stable)
|
||||
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*)
|
||||
printf '%s\n' "${1#v}"
|
||||
;;
|
||||
@@ -184,36 +188,9 @@ warn_command_conflict() {
|
||||
resolve_release_metadata() {
|
||||
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
|
||||
release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest")"
|
||||
resolved_version="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"v\([^"]*\)".*/\1/p' | head -n 1)"
|
||||
release_page="$(download_text "https://github.com/getcompanion-ai/feynman/releases/latest")"
|
||||
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
|
||||
echo "Failed to resolve the latest Feynman release version." >&2
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
set -eu
|
||||
|
||||
VERSION="edge"
|
||||
VERSION="latest"
|
||||
SCOPE="${FEYNMAN_SKILLS_SCOPE:-user}"
|
||||
TARGET_DIR="${FEYNMAN_SKILLS_DIR:-}"
|
||||
|
||||
@@ -12,12 +12,16 @@ step() {
|
||||
|
||||
normalize_version() {
|
||||
case "$1" in
|
||||
"" | edge)
|
||||
printf 'edge\n'
|
||||
"")
|
||||
printf 'latest\n'
|
||||
;;
|
||||
latest | stable)
|
||||
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*)
|
||||
printf '%s\n' "${1#v}"
|
||||
;;
|
||||
@@ -73,14 +77,9 @@ download_text() {
|
||||
resolve_version() {
|
||||
normalized_version="$(normalize_version "$VERSION")"
|
||||
|
||||
if [ "$normalized_version" = "edge" ]; then
|
||||
printf 'edge\nmain\n'
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$normalized_version" = "latest" ]; then
|
||||
release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest")"
|
||||
resolved_version="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"v\([^"]*\)".*/\1/p' | head -n 1)"
|
||||
release_page="$(download_text "https://github.com/getcompanion-ai/feynman/releases/latest")"
|
||||
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
|
||||
echo "Failed to resolve the latest Feynman release version." >&2
|
||||
@@ -125,7 +124,7 @@ while [ $# -gt 0 ]; do
|
||||
;;
|
||||
--dir)
|
||||
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
|
||||
fi
|
||||
TARGET_DIR="$2"
|
||||
@@ -136,7 +135,7 @@ while [ $# -gt 0 ]; do
|
||||
;;
|
||||
*)
|
||||
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
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
param(
|
||||
[string]$Version = "edge",
|
||||
[string]$Version = "latest",
|
||||
[ValidateSet("User", "Repo")]
|
||||
[string]$Scope = "User",
|
||||
[string]$TargetDir = ""
|
||||
@@ -11,37 +11,34 @@ function Normalize-Version {
|
||||
param([string]$RequestedVersion)
|
||||
|
||||
if (-not $RequestedVersion) {
|
||||
return "edge"
|
||||
return "latest"
|
||||
}
|
||||
|
||||
switch ($RequestedVersion.ToLowerInvariant()) {
|
||||
"edge" { return "edge" }
|
||||
"latest" { 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") }
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
param([string]$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") {
|
||||
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest"
|
||||
if (-not $release.tag_name) {
|
||||
throw "Failed to resolve the latest Feynman release version."
|
||||
}
|
||||
|
||||
$resolvedVersion = $release.tag_name.TrimStart("v")
|
||||
$resolvedVersion = Resolve-LatestReleaseVersion
|
||||
} else {
|
||||
$resolvedVersion = $normalizedVersion
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
param(
|
||||
[string]$Version = "edge"
|
||||
[string]$Version = "latest"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
@@ -8,17 +8,27 @@ function Normalize-Version {
|
||||
param([string]$RequestedVersion)
|
||||
|
||||
if (-not $RequestedVersion) {
|
||||
return "edge"
|
||||
return "latest"
|
||||
}
|
||||
|
||||
switch ($RequestedVersion.ToLowerInvariant()) {
|
||||
"edge" { return "edge" }
|
||||
"latest" { 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") }
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
param(
|
||||
[string]$RequestedVersion,
|
||||
@@ -28,34 +38,8 @@ function Resolve-ReleaseMetadata {
|
||||
|
||||
$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") {
|
||||
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest"
|
||||
if (-not $release.tag_name) {
|
||||
throw "Failed to resolve the latest Feynman release version."
|
||||
}
|
||||
|
||||
$resolvedVersion = $release.tag_name.TrimStart("v")
|
||||
$resolvedVersion = Resolve-LatestReleaseVersion
|
||||
} else {
|
||||
$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`.
|
||||
|
||||
By default, the one-line installer tracks the rolling `edge` channel from `main`.
|
||||
|
||||
On **Windows**, open PowerShell as Administrator and run:
|
||||
|
||||
```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.
|
||||
|
||||
## 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
|
||||
curl -fsSL https://feynman.is/install | bash -s -- stable
|
||||
curl -fsSL https://feynman.is/install | bash -s -- 0.2.14
|
||||
```
|
||||
|
||||
On Windows:
|
||||
|
||||
```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
|
||||
|
||||
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