fss-link 1.6.1 → 1.6.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +63 -316
  3. package/bundle/fss-link.js +4038 -134262
  4. package/docs/CONFIGURATION.md +200 -0
  5. package/docs/README.md +192 -0
  6. package/docs/TOOLS.md +268 -0
  7. package/docs/assets/batch_0001_fss-link-terminal-interface.png +0 -0
  8. package/docs/assets/batch_0002_multiprovider-connection-hub-a.png +0 -0
  9. package/docs/assets/batch_0003_database-persistence-system-a.png +0 -0
  10. package/docs/assets/batch_0004_context-window-compression-a.png +0 -0
  11. package/docs/assets/batch_0005_file-operations-with-safety.png +0 -0
  12. package/docs/assets/batch_0006_semantic-search-rag-system.png +0 -0
  13. package/docs/assets/batch_0008_document-parsing-suite-a.png +0 -0
  14. package/docs/assets/batch_0009_web-research-tools-a.png +0 -0
  15. package/docs/assets/batch_0010_texttospeech-voice-output-a.png +0 -0
  16. package/docs/assets/batch_0011_shell-command-execution-a.png +0 -0
  17. package/docs/assets/batch_0012_mcp-extension-system-a.png +0 -0
  18. package/docs/assets/batch_0014_approval-mode-switches-a.png +0 -0
  19. package/docs/assets/batch_0015_folder-trust-system-a.png +0 -0
  20. package/package.json +53 -38
  21. package/scripts/check-publish.js +2 -1
  22. package/scripts/install-linux.sh +1 -2
  23. package/scripts/install-macos.sh +1 -2
  24. package/scripts/install-windows.ps1 +1 -2
  25. package/scripts/prebundle-sync-dist.js +51 -0
  26. package/README.pdf +0 -0
  27. package/scripts/analyze-session-logs.sh +0 -279
  28. package/scripts/emergency-kill-all-tests.sh +0 -95
  29. package/scripts/emergency-kill-vitest.sh +0 -95
  30. package/scripts/extract-session-logs.sh +0 -202
  31. package/scripts/get-previous-tag.js +0 -213
  32. package/scripts/get-release-version.js +0 -119
  33. package/scripts/index-session-logs.sh +0 -173
  34. package/scripts/local_telemetry.js +0 -219
  35. package/scripts/memory-monitor.sh +0 -165
  36. package/scripts/process-session-log.py +0 -302
  37. package/scripts/quick-install.sh +0 -195
  38. package/scripts/telemetry_gcp.js +0 -188
  39. package/scripts/telemetry_utils.js +0 -421
  40. package/scripts/test-windows-paths.js +0 -51
  41. package/scripts/tests/get-release-version.test.js +0 -110
  42. package/scripts/tests/test-setup.ts +0 -12
  43. package/scripts/tests/vitest.config.ts +0 -20
@@ -1,95 +0,0 @@
1
- #!/bin/bash
2
-
3
- # 🚨 EMERGENCY VITEST KILLER - System Recovery Script
4
- # Purpose: Kill all vitest processes when they consume excessive memory
5
- # Usage: ./scripts/emergency-kill-vitest.sh [--force]
6
-
7
- set -e
8
-
9
- # Colors for output
10
- RED='\033[0;31m'
11
- YELLOW='\033[1;33m'
12
- GREEN='\033[0;32m'
13
- NC='\033[0m' # No Color
14
-
15
- echo -e "${RED}🚨 EMERGENCY VITEST KILLER ACTIVATED${NC}"
16
- echo "Scanning for vitest processes..."
17
-
18
- # Find all vitest-related processes
19
- VITEST_PIDS=$(pgrep -f "vitest\|node.*test" 2>/dev/null || true)
20
- NODE_TEST_PIDS=$(pgrep -f "node.*\.test\." 2>/dev/null || true)
21
- ALL_PIDS="${VITEST_PIDS} ${NODE_TEST_PIDS}"
22
-
23
- if [ -z "$ALL_PIDS" ]; then
24
- echo -e "${GREEN}✅ No vitest processes found running${NC}"
25
- exit 0
26
- fi
27
-
28
- echo -e "${YELLOW}Found processes to kill:${NC}"
29
- echo "$ALL_PIDS" | tr ' ' '\n' | while read -r pid; do
30
- if [ -n "$pid" ]; then
31
- ps -p "$pid" -o pid,ppid,%cpu,%mem,cmd 2>/dev/null || true
32
- fi
33
- done
34
-
35
- # Check for --force flag
36
- if [ "$1" = "--force" ]; then
37
- echo -e "${RED}🔥 FORCE MODE: Killing immediately...${NC}"
38
- else
39
- echo ""
40
- echo -e "${YELLOW}⚠️ WARNING: This will kill ALL vitest and node test processes${NC}"
41
- echo "Press ENTER to continue, or Ctrl+C to cancel..."
42
- read -r
43
- fi
44
-
45
- # Kill processes gracefully first (SIGTERM)
46
- echo -e "${YELLOW}🔄 Attempting graceful shutdown (SIGTERM)...${NC}"
47
- for pid in $ALL_PIDS; do
48
- if [ -n "$pid" ]; then
49
- kill -TERM "$pid" 2>/dev/null || true
50
- echo "Sent SIGTERM to PID $pid"
51
- fi
52
- done
53
-
54
- # Wait 3 seconds for graceful shutdown
55
- echo "Waiting 3 seconds for graceful shutdown..."
56
- sleep 3
57
-
58
- # Check what's still running
59
- REMAINING_PIDS=$(pgrep -f "vitest\|node.*test" 2>/dev/null || true)
60
- if [ -n "$REMAINING_PIDS" ]; then
61
- echo -e "${RED}💀 Force killing remaining processes (SIGKILL)...${NC}"
62
- for pid in $REMAINING_PIDS; do
63
- if [ -n "$pid" ]; then
64
- kill -KILL "$pid" 2>/dev/null || true
65
- echo "Sent SIGKILL to PID $pid"
66
- fi
67
- done
68
- else
69
- echo -e "${GREEN}✅ All processes terminated gracefully${NC}"
70
- fi
71
-
72
- # Final verification
73
- sleep 1
74
- FINAL_CHECK=$(pgrep -f "vitest\|node.*test" 2>/dev/null || true)
75
- if [ -n "$FINAL_CHECK" ]; then
76
- echo -e "${RED}❌ Some processes still running:${NC}"
77
- echo "$FINAL_CHECK" | tr ' ' '\n' | while read -r pid; do
78
- if [ -n "$pid" ]; then
79
- ps -p "$pid" -o pid,ppid,%cpu,%mem,cmd 2>/dev/null || true
80
- fi
81
- done
82
- echo ""
83
- echo -e "${YELLOW}💡 You may need to run: sudo kill -9 <PID>${NC}"
84
- else
85
- echo -e "${GREEN}🎉 SUCCESS: All vitest processes killed${NC}"
86
- fi
87
-
88
- # Memory recovery suggestions
89
- echo ""
90
- echo -e "${YELLOW}🔧 Memory Recovery Suggestions:${NC}"
91
- echo "1. Run: sync && echo 3 | sudo tee /proc/sys/vm/drop_caches"
92
- echo "2. Check memory: free -h"
93
- echo "3. Check for zombie processes: ps aux | grep defunct"
94
- echo ""
95
- echo -e "${GREEN}Emergency kill complete!${NC}"
@@ -1,202 +0,0 @@
1
- #!/bin/bash
2
- # FSS Link Session Log Extractor
3
- # Extracts and organizes session logs from FSS Link checkpoint files
4
-
5
- set -euo pipefail
6
-
7
- # Configuration
8
- FSS_LINK_TMP_DIR="${HOME}/.fss-link/tmp"
9
- OUTPUT_DIR="/MASTERFOLDER/Projects/fss-link/fss-live-testing/session-logs"
10
- RAW_DIR="${OUTPUT_DIR}/raw"
11
- PROCESSED_DIR="${OUTPUT_DIR}/processed"
12
-
13
- # Colors for output
14
- RED='\033[0;31m'
15
- GREEN='\033[0;32m'
16
- YELLOW='\033[1;33m'
17
- BLUE='\033[0;34m'
18
- NC='\033[0m' # No Color
19
-
20
- # Usage information
21
- usage() {
22
- cat << EOF
23
- Usage: $0 [OPTIONS]
24
-
25
- Extract FSS Link session logs and prepare them for RAG indexing.
26
-
27
- OPTIONS:
28
- -d, --days DAYS Extract logs from last N days (default: 7)
29
- -a, --all Extract all available logs
30
- -t, --tool TOOL Filter by tool name (e.g., grep, read, write)
31
- -s, --session ID Extract specific session by ID
32
- -l, --list List available sessions
33
- -h, --help Show this help message
34
-
35
- EXAMPLES:
36
- $0 --days 1 # Extract logs from last 24 hours
37
- $0 --tool grep # Extract only grep-related sessions
38
- $0 --session 05e09634... # Extract specific session
39
- $0 --list # List all available sessions
40
-
41
- OUTPUT:
42
- Raw logs: ${RAW_DIR}/
43
- Processed logs: ${PROCESSED_DIR}/
44
- Analysis: ${OUTPUT_DIR}/analysis/
45
- EOF
46
- exit 1
47
- }
48
-
49
- # Parse arguments
50
- DAYS=7
51
- EXTRACT_ALL=false
52
- TOOL_FILTER=""
53
- SESSION_ID=""
54
- LIST_ONLY=false
55
-
56
- while [[ $# -gt 0 ]]; do
57
- case $1 in
58
- -d|--days)
59
- DAYS="$2"
60
- shift 2
61
- ;;
62
- -a|--all)
63
- EXTRACT_ALL=true
64
- shift
65
- ;;
66
- -t|--tool)
67
- TOOL_FILTER="$2"
68
- shift 2
69
- ;;
70
- -s|--session)
71
- SESSION_ID="$2"
72
- shift 2
73
- ;;
74
- -l|--list)
75
- LIST_ONLY=true
76
- shift
77
- ;;
78
- -h|--help)
79
- usage
80
- ;;
81
- *)
82
- echo -e "${RED}Unknown option: $1${NC}"
83
- usage
84
- ;;
85
- esac
86
- done
87
-
88
- # Ensure output directories exist
89
- mkdir -p "${RAW_DIR}" "${PROCESSED_DIR}" "${OUTPUT_DIR}/analysis"
90
-
91
- # List available sessions
92
- list_sessions() {
93
- echo -e "${BLUE}=== Available FSS Link Sessions ===${NC}\n"
94
-
95
- if [[ ! -d "${FSS_LINK_TMP_DIR}" ]]; then
96
- echo -e "${RED}FSS Link tmp directory not found: ${FSS_LINK_TMP_DIR}${NC}"
97
- exit 1
98
- fi
99
-
100
- find "${FSS_LINK_TMP_DIR}" -name "checkpoint*.json" -type f | while read -r checkpoint; do
101
- session_dir=$(dirname "${checkpoint}")
102
- session_id=$(basename "${session_dir}")
103
- file_size=$(du -h "${checkpoint}" | cut -f1)
104
- mod_time=$(stat -c '%y' "${checkpoint}" 2>/dev/null || stat -f '%Sm' "${checkpoint}")
105
-
106
- # Try to extract some context from the file
107
- context=$(jq -r '.messages[2].parts[0].text // "Unknown"' "${checkpoint}" 2>/dev/null | head -c 100)
108
-
109
- echo -e "${GREEN}Session:${NC} ${session_id}"
110
- echo -e " ${YELLOW}File:${NC} ${checkpoint}"
111
- echo -e " ${YELLOW}Size:${NC} ${file_size}"
112
- echo -e " ${YELLOW}Modified:${NC} ${mod_time}"
113
- echo -e " ${YELLOW}Context:${NC} ${context}..."
114
- echo ""
115
- done
116
- }
117
-
118
- # Extract specific session
119
- extract_session() {
120
- local session_path="$1"
121
- local session_id="$2"
122
- local output_name="$3"
123
-
124
- echo -e "${BLUE}Extracting session: ${session_id}${NC}"
125
-
126
- # Copy raw log
127
- cp "${session_path}" "${RAW_DIR}/${output_name}.json"
128
- echo -e "${GREEN}✓${NC} Raw log saved: ${RAW_DIR}/${output_name}.json"
129
-
130
- # Process log with Python script
131
- python3 /MASTERFOLDER/Projects/fss-link/scripts/process-session-log.py \
132
- "${session_path}" \
133
- "${PROCESSED_DIR}/${output_name}.md"
134
-
135
- if [[ $? -eq 0 ]]; then
136
- echo -e "${GREEN}✓${NC} Processed log saved: ${PROCESSED_DIR}/${output_name}.md"
137
- else
138
- echo -e "${RED}✗${NC} Failed to process session log"
139
- return 1
140
- fi
141
- }
142
-
143
- # Main execution
144
- main() {
145
- if [[ "${LIST_ONLY}" == "true" ]]; then
146
- list_sessions
147
- exit 0
148
- fi
149
-
150
- echo -e "${BLUE}=== FSS Link Session Log Extractor ===${NC}\n"
151
-
152
- # Specific session extraction
153
- if [[ -n "${SESSION_ID}" ]]; then
154
- session_path="${FSS_LINK_TMP_DIR}/${SESSION_ID}/checkpoint-fileRead.json"
155
- if [[ ! -f "${session_path}" ]]; then
156
- echo -e "${RED}Session not found: ${SESSION_ID}${NC}"
157
- exit 1
158
- fi
159
-
160
- timestamp=$(date +%Y%m%d-%H%M%S)
161
- extract_session "${session_path}" "${SESSION_ID}" "session-${timestamp}"
162
- exit 0
163
- fi
164
-
165
- # Extract sessions based on filters
166
- local count=0
167
- find "${FSS_LINK_TMP_DIR}" -name "checkpoint*.json" -type f | while read -r checkpoint; do
168
- session_dir=$(dirname "${checkpoint}")
169
- session_id=$(basename "${session_dir}")
170
-
171
- # Apply time filter
172
- if [[ "${EXTRACT_ALL}" == "false" ]]; then
173
- # Check if file was modified in last N days
174
- if [[ $(find "${checkpoint}" -mtime "-${DAYS}" | wc -l) -eq 0 ]]; then
175
- continue
176
- fi
177
- fi
178
-
179
- # Apply tool filter
180
- if [[ -n "${TOOL_FILTER}" ]]; then
181
- if ! grep -qi "${TOOL_FILTER}" "${checkpoint}" 2>/dev/null; then
182
- continue
183
- fi
184
- fi
185
-
186
- # Extract this session
187
- mod_date=$(stat -c '%Y' "${checkpoint}" 2>/dev/null || stat -f '%m' "${checkpoint}")
188
- formatted_date=$(date -d "@${mod_date}" +%Y%m%d-%H%M%S 2>/dev/null || date -r "${mod_date}" +%Y%m%d-%H%M%S)
189
- output_name="session-${formatted_date}-${session_id:0:8}"
190
-
191
- extract_session "${checkpoint}" "${session_id}" "${output_name}"
192
- ((count++))
193
- done
194
-
195
- echo -e "\n${GREEN}Extraction complete: ${count} sessions processed${NC}"
196
- echo -e "${YELLOW}Next steps:${NC}"
197
- echo -e " 1. Review processed logs in: ${PROCESSED_DIR}/"
198
- echo -e " 2. Index with RAG: cd ${OUTPUT_DIR} && rag-index create processed/"
199
- echo -e " 3. Search logs: rag fss-link-sessions 'your query'"
200
- }
201
-
202
- main
@@ -1,213 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- import { execSync } from 'child_process';
8
-
9
- /**
10
- * Determines the correct previous tag for release notes generation.
11
- * This function handles the complexity of mixed tag types (regular releases vs nightly releases).
12
- *
13
- * @param {string} currentTag - The current release tag (e.g., "v0.1.23")
14
- * @returns {string|null} - The previous tag to compare against, or null if no suitable tag found
15
- */
16
- export function getPreviousTag(currentTag) {
17
- try {
18
- // Parse the current tag to understand its type
19
- const currentTagInfo = parseTag(currentTag);
20
- if (!currentTagInfo) {
21
- console.error(`Invalid current tag format: ${currentTag}`);
22
- return null;
23
- }
24
-
25
- // Find the appropriate previous tag based on the current tag type
26
- let previousTag = null;
27
-
28
- if (currentTagInfo.isNightly) {
29
- // For nightly releases, find the last stable release
30
- previousTag = findLastStableTag(currentTagInfo);
31
- } else {
32
- // For stable releases, find the previous stable release
33
- previousTag = findPreviousStableTag(currentTagInfo);
34
- }
35
-
36
- return previousTag;
37
- } catch (error) {
38
- console.error('Error getting previous tag:', error.message);
39
- return null;
40
- }
41
- }
42
-
43
- /**
44
- * Parses a tag string to extract version information and type
45
- */
46
- function parseTag(tag) {
47
- // Remove 'v' prefix if present
48
- const cleanTag = tag.startsWith('v') ? tag.substring(1) : tag;
49
-
50
- // Match pattern: X.Y.Z or X.Y.Z-prerelease
51
- const match = cleanTag.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
52
- if (!match) {
53
- return null;
54
- }
55
-
56
- const [, major, minor, patch, prerelease] = match;
57
-
58
- return {
59
- original: tag,
60
- major: parseInt(major),
61
- minor: parseInt(minor),
62
- patch: parseInt(patch),
63
- prerelease: prerelease || null,
64
- isNightly: prerelease && prerelease.startsWith('nightly'),
65
- isPreview: prerelease && prerelease.startsWith('preview'),
66
- version: `${major}.${minor}.${patch}`,
67
- };
68
- }
69
-
70
- /**
71
- * Finds the last stable tag for a nightly release
72
- * Assumes version numbers are incremental and checks backwards from current version
73
- */
74
- function findLastStableTag(currentTagInfo) {
75
- // For nightly releases, find the stable version of the same version number first
76
- const baseVersion = `v${currentTagInfo.version}`;
77
-
78
- // Check if the stable version of the current version exists
79
- if (tagExists(baseVersion)) {
80
- return baseVersion;
81
- }
82
-
83
- // If not, look for the previous stable versions by decrementing version numbers
84
- let { major, minor, patch } = currentTagInfo;
85
-
86
- // Try decrementing patch version first
87
- while (patch > 0) {
88
- patch--;
89
- const candidateTag = `v${major}.${minor}.${patch}`;
90
- if (tagExists(candidateTag)) {
91
- return candidateTag;
92
- }
93
- }
94
-
95
- // Try decrementing minor version
96
- while (minor > 0) {
97
- minor--;
98
- patch = 999; // Start from a high patch number and work backwards
99
- while (patch >= 0) {
100
- const candidateTag = `v${major}.${minor}.${patch}`;
101
- if (tagExists(candidateTag)) {
102
- return candidateTag;
103
- }
104
- patch--;
105
- // Don't check too many patch versions to avoid infinite loops
106
- if (patch < 0) break;
107
- }
108
- }
109
-
110
- // Try decrementing major version
111
- while (major > 0) {
112
- major--;
113
- minor = 999; // Start from a high minor number and work backwards
114
- while (minor >= 0) {
115
- patch = 999;
116
- while (patch >= 0) {
117
- const candidateTag = `v${major}.${minor}.${patch}`;
118
- if (tagExists(candidateTag)) {
119
- return candidateTag;
120
- }
121
- patch--;
122
- if (patch < 0) break;
123
- }
124
- minor--;
125
- if (minor < 0) break;
126
- }
127
- }
128
-
129
- return null;
130
- }
131
-
132
- /**
133
- * Finds the previous stable tag for a stable release
134
- * Assumes version numbers are incremental and checks backwards from current version
135
- */
136
- function findPreviousStableTag(currentTagInfo) {
137
- let { major, minor, patch } = currentTagInfo;
138
-
139
- // Try decrementing patch version first
140
- while (patch > 0) {
141
- patch--;
142
- const candidateTag = `v${major}.${minor}.${patch}`;
143
- if (tagExists(candidateTag)) {
144
- return candidateTag;
145
- }
146
- }
147
-
148
- // Try decrementing minor version
149
- while (minor > 0) {
150
- minor--;
151
- patch = 999; // Start from a high patch number and work backwards
152
- while (patch >= 0) {
153
- const candidateTag = `v${major}.${minor}.${patch}`;
154
- if (tagExists(candidateTag)) {
155
- return candidateTag;
156
- }
157
- patch--;
158
- // Don't check too many patch versions to avoid infinite loops
159
- if (patch < 0) break;
160
- }
161
- }
162
-
163
- // Try decrementing major version
164
- while (major > 0) {
165
- major--;
166
- minor = 999; // Start from a high minor number and work backwards
167
- while (minor >= 0) {
168
- patch = 999;
169
- while (patch >= 0) {
170
- const candidateTag = `v${major}.${minor}.${patch}`;
171
- if (tagExists(candidateTag)) {
172
- return candidateTag;
173
- }
174
- patch--;
175
- if (patch < 0) break;
176
- }
177
- minor--;
178
- if (minor < 0) break;
179
- }
180
- }
181
-
182
- return null;
183
- }
184
-
185
- /**
186
- * Checks if a git tag exists
187
- */
188
- function tagExists(tag) {
189
- try {
190
- execSync(`git rev-parse --verify ${tag}`, { stdio: 'ignore' });
191
- return true;
192
- } catch {
193
- return false;
194
- }
195
- }
196
-
197
- // CLI usage
198
- if (process.argv[1] === new URL(import.meta.url).pathname) {
199
- const currentTag = process.argv[2];
200
-
201
- if (!currentTag) {
202
- console.error('Usage: node get-previous-tag.js <current-tag>');
203
- process.exit(1);
204
- }
205
-
206
- const previousTag = getPreviousTag(currentTag);
207
- if (previousTag) {
208
- console.log(previousTag);
209
- } else {
210
- console.error('No suitable previous tag found');
211
- process.exit(1);
212
- }
213
- }
@@ -1,119 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- import { execSync } from 'child_process';
8
- import fs from 'fs';
9
- import path from 'path';
10
-
11
- function getPackageVersion() {
12
- const packageJsonPath = path.resolve(process.cwd(), 'package.json');
13
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
14
- return packageJson.version;
15
- }
16
-
17
- function incrementPatchVersion(version) {
18
- const parts = version.split('.');
19
- const major = parseInt(parts[0]);
20
- const minor = parseInt(parts[1]);
21
- const patch = parseInt(parts[2].split('-')[0]); // Handle pre-release versions
22
- return `${major}.${minor}.${patch + 1}`;
23
- }
24
-
25
- function getLatestNightlyCount() {
26
- try {
27
- // Try to get the latest nightly tag from git to determine the counter
28
- const currentVersion = getPackageVersion();
29
- const nextVersion = incrementPatchVersion(currentVersion);
30
- const tags = execSync(`git tag -l "v${nextVersion}-nightly.*"`)
31
- .toString()
32
- .trim();
33
-
34
- if (!tags) return 0;
35
-
36
- const nightlyTags = tags.split('\n').filter(Boolean);
37
- const counts = nightlyTags.map((tag) => {
38
- const match = tag.match(/nightly\.(\d+)$/);
39
- return match ? parseInt(match[1]) : 0;
40
- });
41
-
42
- return Math.max(...counts, -1) + 1;
43
- } catch (_error) {
44
- // If we can't get tags, start from 0
45
- return 0;
46
- }
47
- }
48
-
49
- export function getNightlyTagName() {
50
- const version = getPackageVersion();
51
- const nextVersion = incrementPatchVersion(version);
52
- const nightlyCount = getLatestNightlyCount();
53
-
54
- return `v${nextVersion}-nightly.${nightlyCount}`;
55
- }
56
-
57
- export function getReleaseVersion() {
58
- const isNightly = process.env.IS_NIGHTLY === 'true';
59
- const manualVersion = process.env.MANUAL_VERSION;
60
-
61
- let releaseTag;
62
-
63
- if (isNightly) {
64
- console.error('Calculating next nightly version...');
65
- releaseTag = getNightlyTagName();
66
- } else if (manualVersion) {
67
- console.error(`Using manual version: ${manualVersion}`);
68
- releaseTag = manualVersion;
69
- } else {
70
- throw new Error(
71
- 'Error: No version specified and this is not a nightly release.',
72
- );
73
- }
74
-
75
- if (!releaseTag) {
76
- throw new Error('Error: Version could not be determined.');
77
- }
78
-
79
- if (!releaseTag.startsWith('v')) {
80
- console.error("Version is missing 'v' prefix. Prepending it.");
81
- releaseTag = `v${releaseTag}`;
82
- }
83
-
84
- if (releaseTag.includes('+')) {
85
- throw new Error(
86
- 'Error: Versions with build metadata (+) are not supported for releases. Please use a pre-release version (e.g., v1.2.3-alpha.4) instead.',
87
- );
88
- }
89
-
90
- if (!releaseTag.match(/^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$/)) {
91
- throw new Error(
92
- 'Error: Version must be in the format vX.Y.Z or vX.Y.Z-prerelease',
93
- );
94
- }
95
-
96
- const releaseVersion = releaseTag.substring(1);
97
- let npmTag = 'latest';
98
- if (releaseVersion.includes('-')) {
99
- const prereleasePart = releaseVersion.split('-')[1];
100
- npmTag = prereleasePart.split('.')[0];
101
-
102
- // Ensure nightly releases use 'nightly' tag, not 'latest'
103
- if (npmTag === 'nightly') {
104
- npmTag = 'nightly';
105
- }
106
- }
107
-
108
- return { releaseTag, releaseVersion, npmTag };
109
- }
110
-
111
- if (process.argv[1] === new URL(import.meta.url).pathname) {
112
- try {
113
- const versions = getReleaseVersion();
114
- console.log(JSON.stringify(versions));
115
- } catch (error) {
116
- console.error(error.message);
117
- process.exit(1);
118
- }
119
- }