373d10595b
Captures roughly forty version bumps (v0.2.6 → v0.2.47) of work that
accumulated without commits.
- Pluggable provider system under server/providers/: gemini, anthropic,
openai, openai-compatible, ollama, whisper-compatible, relay. Mix and
match transcription + analysis per request via the picker UI.
- Relay backend integration. Hardcoded relay URL in server/relay-default.js
(operator-controlled at build time, not user-configurable). New
/api/relay/{status,policy} endpoints proxy to the relay; balance pings
populate a cached credit display.
- Per-install identity in server/install-id.js for relay credit accounting.
Sent to the relay as X-Recap-Install-Id; persists across upgrades, lost
on a full uninstall + reinstall. Not surfaced in the UI.
- Admin login gate (server/admin-auth.js + setAdminPassword action). Scrypt
password hash + HMAC-signed session cookie.
- Entitlement scheme rename: pro / max (each paired with subscriptions and
relay_pro / relay_max), replacing the misleading "core" entitlement
that conflicted with the user-facing "Core" tier name.
- Activation screen: dynamic credit count pulled from /api/relay/policy,
"Skip — use free mode" button, accurate paid-feature list.
- Top toolbar: inline credit-balance pill (or "BYO configured" fallback),
Upgrade + "I have a key" buttons.
- Picker UI: per-provider sections with Save/Test/Delete buttons, sections
collapsible by chevron, default-collapsed unless currently selected,
"Use comped credits (reset to relay)" link when the user has strayed,
green hint under inputs whose values are server-configured.
- Activity log: chevron-collapsible groups per video, refresh-survival via
localStorage + a 500-entry server-side buffer, explicit Clear button.
- YouTube captions fast-path with user toggle (skips audio download + AI
transcription when captions are available — uncheck for speaker labels).
- Cancel button: AbortController plumbed through every provider SDK call;
retryAPI short-circuits on AbortError; cancellation events surface in
the activity log instead of silent retries.
- Long-video analysis: auto-coalesce transcript entries before building the
analysis prompt so local-model context windows (32k-ish) don't overflow.
Original entries preserved for transcript display via an index map; the
analyzer sees a coarser view but click-to-seek timestamps stay precise.
- StartOS action grouping (Setup / AI Providers) so the actions list is
navigable.
- Manifest description rewritten to reflect multi-provider support and
free-tier relay credits.
- Smaller fixes: summarize-button enablement no longer requires a Gemini
key when other providers are configured; analysis fallback chain handles
context-length and 503 capacity errors; single-segment expansion for
providers that don't return per-segment timestamps (Parakeet et al.);
many other UX polish items.
176 lines
5.8 KiB
Bash
Executable File
176 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Interactive version bump.
|
|
#
|
|
# Shows the current version, asks for the new version (with a sensible default:
|
|
# patch-level bump), and asks for release notes. Then:
|
|
# 1. Creates startos/versions/v<new>.ts
|
|
# 2. Updates startos/versions/index.ts (adds import, updates `current:`,
|
|
# pushes old current into `other:`)
|
|
#
|
|
# If the file .release-notes-pending.txt exists in the project root, its
|
|
# contents are shown as the default release notes (just press Enter to accept).
|
|
# Drop a note in that file before running this script to pre-fill the
|
|
# prompt. The file is deleted on a successful bump.
|
|
#
|
|
# Flags:
|
|
# --from-deploy Treat the absence of .release-notes-pending.txt as the
|
|
# signal that no new work needs to ship — exit 0 without
|
|
# bumping. Lets `make deploy` always include this step
|
|
# without forcing a redundant bump when the user (or a
|
|
# prior run) already bumped.
|
|
#
|
|
# Run standalone with `make bump`, or as the first step of `make deploy`.
|
|
|
|
set -euo pipefail
|
|
|
|
FROM_DEPLOY=0
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--from-deploy) FROM_DEPLOY=1 ;;
|
|
esac
|
|
done
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
VERSIONS_DIR="$PROJECT_ROOT/startos/versions"
|
|
INDEX_FILE="$VERSIONS_DIR/index.ts"
|
|
PENDING_NOTES_FILE="$PROJECT_ROOT/.release-notes-pending.txt"
|
|
|
|
# When invoked from `make deploy`, treat a missing pending-notes file as
|
|
# "nothing new to ship — current version is already fresh, skip the bump."
|
|
# Standalone `make bump` always prompts.
|
|
if [ "$FROM_DEPLOY" = "1" ] && [ ! -f "$PENDING_NOTES_FILE" ]; then
|
|
echo ""
|
|
echo " (No .release-notes-pending.txt — current version is already bumped. Skipping.)"
|
|
echo ""
|
|
exit 0
|
|
fi
|
|
|
|
# --- Discover current version ---
|
|
CURRENT_VAR="$(sed -nE "s/.*current:[[:space:]]*(v_[0-9_]+).*/\1/p" "$INDEX_FILE" | head -1)"
|
|
if [ -z "$CURRENT_VAR" ]; then
|
|
echo "X Could not find current version in $INDEX_FILE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
CURRENT_DOT="$(echo "$CURRENT_VAR" | sed 's/^v_//; s/_/./g')"
|
|
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_DOT"
|
|
SUGGESTED="$MAJOR.$MINOR.$((PATCH + 1))"
|
|
|
|
echo ""
|
|
echo "═══════════════════════════════════════════"
|
|
echo " Bumping version"
|
|
echo "═══════════════════════════════════════════"
|
|
echo ""
|
|
echo " Current: $CURRENT_DOT"
|
|
echo ""
|
|
|
|
# --- Prompt for new version ---
|
|
read -r -p " New version [$SUGGESTED]: " NEW_VERSION
|
|
NEW_VERSION="${NEW_VERSION:-$SUGGESTED}"
|
|
|
|
if ! [[ "$NEW_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
echo "X Invalid version: '$NEW_VERSION' (expected format: x.y.z, e.g. 0.1.10)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
NEW_FILE="$VERSIONS_DIR/v${NEW_VERSION}.ts"
|
|
if [ -f "$NEW_FILE" ]; then
|
|
echo "X Version file already exists: $NEW_FILE" >&2
|
|
echo " (If you want to re-run, delete that file first.)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
NEW_VAR="v_$(echo "$NEW_VERSION" | tr '.' '_')"
|
|
|
|
# --- Prompt for release notes ---
|
|
# If suggested notes are sitting in .release-notes-pending.txt, show them
|
|
# as the default. Press Enter to accept, or type something different.
|
|
SUGGESTED_NOTES=""
|
|
if [ -f "$PENDING_NOTES_FILE" ]; then
|
|
# Read the file, trim leading/trailing whitespace, collapse interior newlines
|
|
# into spaces so it fits the one-line release-notes format.
|
|
SUGGESTED_NOTES="$(tr '\n' ' ' < "$PENDING_NOTES_FILE" | sed -e 's/[[:space:]]\{1,\}/ /g' -e 's/^ //' -e 's/ $//')"
|
|
fi
|
|
|
|
echo ""
|
|
if [ -n "$SUGGESTED_NOTES" ]; then
|
|
echo " Suggested release notes (from .release-notes-pending.txt):"
|
|
echo " $SUGGESTED_NOTES"
|
|
echo ""
|
|
read -r -p " Release notes (Enter to accept, or type new): " RELEASE_NOTES
|
|
RELEASE_NOTES="${RELEASE_NOTES:-$SUGGESTED_NOTES}"
|
|
else
|
|
read -r -p " Release notes (one-liner, what changed in $NEW_VERSION?): " RELEASE_NOTES
|
|
fi
|
|
|
|
if [ -z "$RELEASE_NOTES" ]; then
|
|
echo "X Release notes are required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Escape for TypeScript single-quoted string: backslash first, then single quote
|
|
ESCAPED_NOTES="$(printf '%s' "$RELEASE_NOTES" | sed -e 's/\\/\\\\/g' -e "s/'/\\\\'/g")"
|
|
|
|
# Clean up partial state if anything below fails
|
|
cleanup_on_error() {
|
|
[ -f "$NEW_FILE" ] && rm -f "$NEW_FILE"
|
|
[ -f "$INDEX_FILE.tmp" ] && rm -f "$INDEX_FILE.tmp"
|
|
[ -f "$INDEX_FILE.bak" ] && rm -f "$INDEX_FILE.bak"
|
|
}
|
|
trap cleanup_on_error ERR
|
|
|
|
# --- 1. Create new version file ---
|
|
cat > "$NEW_FILE" <<EOF
|
|
import { VersionInfo } from '@start9labs/start-sdk'
|
|
|
|
export const $NEW_VAR = VersionInfo.of({
|
|
version: '$NEW_VERSION:0',
|
|
releaseNotes: {
|
|
en_US: '$ESCAPED_NOTES',
|
|
},
|
|
migrations: {
|
|
up: async ({ effects }) => {},
|
|
down: async ({ effects }) => {},
|
|
},
|
|
})
|
|
EOF
|
|
|
|
# --- 2. Update index.ts ---
|
|
# Insert `import { v_NEW } from './vNEW'` right after the last existing version
|
|
# import, so the imports stay contiguous.
|
|
NEW_IMPORT="import { $NEW_VAR } from './v$NEW_VERSION'"
|
|
|
|
awk -v new_import="$NEW_IMPORT" '
|
|
/^import \{ v_[0-9_]+ \} from/ { last_imp = NR }
|
|
{ lines[NR] = $0 }
|
|
END {
|
|
for (i = 1; i <= NR; i++) {
|
|
print lines[i]
|
|
if (i == last_imp) print new_import
|
|
}
|
|
}
|
|
' "$INDEX_FILE" > "$INDEX_FILE.tmp"
|
|
mv "$INDEX_FILE.tmp" "$INDEX_FILE"
|
|
|
|
# Point `current:` at the new version, and prepend the old current into `other:`.
|
|
# Use -i.bak for macOS/BSD + Linux/GNU sed compatibility.
|
|
sed -i.bak \
|
|
-e "s/current: $CURRENT_VAR/current: $NEW_VAR/" \
|
|
-e "s/other: \[/other: [$CURRENT_VAR, /" \
|
|
"$INDEX_FILE"
|
|
rm -f "$INDEX_FILE.bak"
|
|
|
|
trap - ERR
|
|
|
|
# --- Clean up the pending-notes scratch file now that we've consumed it ---
|
|
if [ -f "$PENDING_NOTES_FILE" ]; then
|
|
rm -f "$PENDING_NOTES_FILE"
|
|
fi
|
|
|
|
echo ""
|
|
echo " ✓ Created startos/versions/v${NEW_VERSION}.ts"
|
|
echo " ✓ Wired up in startos/versions/index.ts"
|
|
echo " ✓ Version: $CURRENT_DOT → $NEW_VERSION"
|
|
echo ""
|