synabun 2026.4.26-beta.13 → 2026.4.26-beta.15
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.
- package/neural-interface/server.js +45 -18
- package/package.json +1 -1
|
@@ -10604,7 +10604,10 @@ async function checkSynabunUpdate() {
|
|
|
10604
10604
|
} catch { /* keep prior current if package.json read fails */ }
|
|
10605
10605
|
|
|
10606
10606
|
const curParsed = parseSemver(current);
|
|
10607
|
-
|
|
10607
|
+
// Numeric-only suffix (`2026.4.26-1`) is a post-release iteration, not a
|
|
10608
|
+
// prerelease — keep those on the stable channel. Only true alpha/beta/rc
|
|
10609
|
+
// suffixes flip the channel.
|
|
10610
|
+
const installedChannel = (curParsed?.pre && curParsed.iter == null) ? 'prerelease' : 'stable';
|
|
10608
10611
|
|
|
10609
10612
|
const fetchJsonWithTimeout = async (url, ms = 5000) => {
|
|
10610
10613
|
const controller = new AbortController();
|
|
@@ -10799,25 +10802,36 @@ function parseVersion(raw) {
|
|
|
10799
10802
|
}
|
|
10800
10803
|
|
|
10801
10804
|
// Structured semver parse — handles calver bumps and prerelease tags:
|
|
10802
|
-
// "2026.4.26" -> { major:2026, minor:4, patch:26, pre:null }
|
|
10803
|
-
// "2026.4.20-2" -> { major:2026, minor:4, patch:20, pre:"2"
|
|
10804
|
-
// "2026.4.26-beta.3" -> { major:2026, minor:4, patch:26, pre:"beta.3" }
|
|
10805
|
-
// "v1.2.3-rc.1" -> { major:1, minor:2, patch:3, pre:"rc.1" }
|
|
10805
|
+
// "2026.4.26" -> { major:2026, minor:4, patch:26, pre:null, iter:null }
|
|
10806
|
+
// "2026.4.20-2" -> { major:2026, minor:4, patch:20, pre:"2", iter:2 }
|
|
10807
|
+
// "2026.4.26-beta.3" -> { major:2026, minor:4, patch:26, pre:"beta.3", iter:null }
|
|
10808
|
+
// "v1.2.3-rc.1" -> { major:1, minor:2, patch:3, pre:"rc.1", iter:null }
|
|
10809
|
+
//
|
|
10810
|
+
// `iter` is set when the suffix is purely numeric (SynaBun's calver iteration
|
|
10811
|
+
// scheme: `2026.4.26-1` is the FIRST patch published after `2026.4.26`).
|
|
10812
|
+
// Strict semver §9 treats any prerelease suffix as PRE-release (lower than no
|
|
10813
|
+
// suffix). SynaBun publishes calver iterations as `latest` on npm, so we need
|
|
10814
|
+
// to treat numeric-only suffixes as POST-release iterations instead.
|
|
10806
10815
|
function parseSemver(raw) {
|
|
10807
10816
|
if (raw == null) return null;
|
|
10808
10817
|
const s = String(raw).trim().replace(/^v\.?/, '');
|
|
10809
10818
|
const m = s.match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/);
|
|
10810
10819
|
if (!m) return null;
|
|
10820
|
+
const pre = m[4] || null;
|
|
10821
|
+
const iter = pre && /^\d+$/.test(pre) ? Number(pre) : null;
|
|
10811
10822
|
return {
|
|
10812
10823
|
major: +m[1],
|
|
10813
10824
|
minor: +m[2],
|
|
10814
10825
|
patch: +m[3],
|
|
10815
|
-
pre
|
|
10826
|
+
pre,
|
|
10827
|
+
iter,
|
|
10816
10828
|
};
|
|
10817
10829
|
}
|
|
10818
10830
|
|
|
10819
|
-
//
|
|
10820
|
-
// 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0
|
|
10831
|
+
// Precedence (mix of semver §11 + SynaBun calver-iteration convention):
|
|
10832
|
+
// 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0 < 1.0.0-1 < 1.0.0-2
|
|
10833
|
+
// Numeric-only suffix = post-release iteration (NEWER than no-suffix release).
|
|
10834
|
+
// Mixed/alpha suffix = prerelease (OLDER than no-suffix release, per semver).
|
|
10821
10835
|
// Returns negative if a<b, positive if a>b, 0 if equal. Accepts strings or
|
|
10822
10836
|
// parsed objects.
|
|
10823
10837
|
function compareSemver(a, b) {
|
|
@@ -10829,11 +10843,19 @@ function compareSemver(a, b) {
|
|
|
10829
10843
|
if (pa.major !== pb.major) return pa.major - pb.major;
|
|
10830
10844
|
if (pa.minor !== pb.minor) return pa.minor - pb.minor;
|
|
10831
10845
|
if (pa.patch !== pb.patch) return pa.patch - pb.patch;
|
|
10832
|
-
// Equal x.y.z.
|
|
10846
|
+
// Equal x.y.z. Order from oldest → newest:
|
|
10847
|
+
// alpha-prerelease < no-suffix release < numeric iteration
|
|
10833
10848
|
if (!pa.pre && !pb.pre) return 0;
|
|
10849
|
+
// Numeric iterations are POST-release: always newer than no-suffix and
|
|
10850
|
+
// newer than alpha prereleases.
|
|
10851
|
+
if (pa.iter != null && pb.iter == null) return 1;
|
|
10852
|
+
if (pa.iter == null && pb.iter != null) return -1;
|
|
10853
|
+
if (pa.iter != null && pb.iter != null) return pa.iter - pb.iter;
|
|
10854
|
+
// Neither side is a numeric iteration. Standard semver §11: no-suffix is
|
|
10855
|
+
// greater than alpha prerelease.
|
|
10834
10856
|
if (!pa.pre && pb.pre) return 1;
|
|
10835
10857
|
if ( pa.pre && !pb.pre) return -1;
|
|
10836
|
-
// Both have prerelease — compare identifiers per semver §11.4.
|
|
10858
|
+
// Both have alpha-flavoured prerelease — compare identifiers per semver §11.4.
|
|
10837
10859
|
const ia = pa.pre.split('.');
|
|
10838
10860
|
const ib = pb.pre.split('.');
|
|
10839
10861
|
const len = Math.max(ia.length, ib.length);
|
|
@@ -10886,6 +10908,7 @@ function detectInstallSource(binPath) {
|
|
|
10886
10908
|
if (/\/node_modules\//.test(p) || /\/npm\/node_modules\//.test(p)) return 'npm';
|
|
10887
10909
|
if (p.includes('/opt/homebrew/') || p.includes('/usr/local/cellar/') || /\/homebrew\//.test(p)) return 'brew';
|
|
10888
10910
|
if (p.includes('/.claude/local/') || p.includes('/anthropicclaude/')) return 'native';
|
|
10911
|
+
if (/\/\.local\/bin\//.test(p)) return 'native';
|
|
10889
10912
|
if (/\/program files( \(x86\))?\//.test(p) || /\/localappdata\/.*anthropicclaude/.test(p)) return 'native';
|
|
10890
10913
|
if (p.includes('/winget/') || p.includes('/microsoft/winget/')) return 'winget';
|
|
10891
10914
|
if (/\/usr\/local\/lib\/node_modules\//.test(p)) return 'npm';
|
|
@@ -11014,15 +11037,19 @@ async function checkToolVersions() {
|
|
|
11014
11037
|
}
|
|
11015
11038
|
|
|
11016
11039
|
// Nuclear safety net for the recurring claude phantom-version bug:
|
|
11017
|
-
//
|
|
11018
|
-
//
|
|
11019
|
-
//
|
|
11020
|
-
//
|
|
11021
|
-
if (
|
|
11040
|
+
// only reject when binary path detection failed (truly phantom). If we
|
|
11041
|
+
// resolved a path AND it's outside SynaBun's own dirs, trust the version
|
|
11042
|
+
// — Anthropic ships these versions in the native installer too, so a
|
|
11043
|
+
// version-only blacklist hits legit installs at ~/.local/bin/claude.exe.
|
|
11044
|
+
if (
|
|
11045
|
+
tool.key === 'claude-code' &&
|
|
11046
|
+
installed &&
|
|
11047
|
+
KNOWN_STALE_CLAUDE_VERSIONS.has(installed) &&
|
|
11048
|
+
!probedBinPath
|
|
11049
|
+
) {
|
|
11022
11050
|
console.warn(
|
|
11023
|
-
` [version-guard] Rejected claude v${installed} from
|
|
11024
|
-
` — matches known-stale SynaBun bundle
|
|
11025
|
-
`If you actually have this version installed, remove it from KNOWN_STALE_CLAUDE_VERSIONS.`
|
|
11051
|
+
` [version-guard] Rejected claude v${installed} from (unknown path)` +
|
|
11052
|
+
` — matches known-stale SynaBun bundle and no binary path could be resolved.`
|
|
11026
11053
|
);
|
|
11027
11054
|
installed = null;
|
|
11028
11055
|
}
|