@dsh-sup/dsh-core-linux-x64 0.1.6-BETA.7 → 0.1.6-BETA.9

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/core.cjs CHANGED
@@ -947,7 +947,7 @@ var require_version = __commonJS({
947
947
  var fs2 = require("node:fs");
948
948
  var path2 = require("node:path");
949
949
  function guardVersion() {
950
- if (true) return String("0.1.6-BETA.7");
950
+ if (true) return String("0.1.6-BETA.9");
951
951
  try {
952
952
  return JSON.parse(fs2.readFileSync(path2.join(__dirname, "..", "..", "package.json"), "utf8")).version || "unknown";
953
953
  } catch {
@@ -6509,44 +6509,195 @@ var require_ip = __commonJS({
6509
6509
  }
6510
6510
  });
6511
6511
 
6512
- // src/platform/distribution/policies.js
6513
- var require_policies = __commonJS({
6514
- "src/platform/distribution/policies.js"(exports2, module2) {
6512
+ // src/platform/distribution/registry-ref.js
6513
+ var require_registry_ref = __commonJS({
6514
+ "src/platform/distribution/registry-ref.js"(exports2, module2) {
6515
6515
  "use strict";
6516
6516
  var { isPrivateHostLiteral } = require_ip();
6517
- var FALLBACK_REGISTRIES = [
6518
- "https://registry.npmjs.org",
6519
- "https://registry.npmmirror.com"
6520
- ];
6521
- function normalizeOrigin(origin) {
6522
- return String(origin || "").trim().replace(/\/+$/, "");
6517
+ var REDIRECT_MAX_HOPS = 3;
6518
+ var MAX_BODY_BYTES = 32 * 1024 * 1024;
6519
+ var DEFAULT_TIMEOUT_MS = 1e4;
6520
+ function normalizeBase(raw) {
6521
+ return String(raw == null ? "" : raw).trim().replace(/\/+$/, "");
6523
6522
  }
6524
- function isValidOrigin(origin) {
6525
- const s = normalizeOrigin(origin);
6526
- if (!/^https?:\/\/(\[[0-9A-Fa-f:]+\]|[A-Za-z0-9.\-_]+)(:\d+)?$/.test(s)) return false;
6523
+ function hostViolation(host2) {
6524
+ const h = String(host2 || "").toLowerCase().replace(/^\[|\]$/g, "");
6525
+ if (!h) return "\u955C\u50CF\u6E90\u7F3A\u5C11\u4E3B\u673A\u540D";
6526
+ if (isPrivateHostLiteral(h)) return "\u955C\u50CF\u6E90\u4E3B\u673A\u4E0D\u5F97\u4E3A\u56DE\u73AF/\u79C1\u7F51/\u94FE\u8DEF\u672C\u5730/\u4FDD\u7559\u6BB5\u5B57\u9762\u91CF: " + h;
6527
+ return null;
6528
+ }
6529
+ function parseRegistryBase(raw) {
6530
+ const base = normalizeBase(raw);
6531
+ const bad = (violation) => ({ ok: false, base, protocol: "", host: "", violation });
6532
+ if (!base) return bad("\u955C\u50CF\u6E90\u4E3A\u7A7A");
6533
+ if (/[\s]/.test(base)) return bad("\u955C\u50CF\u6E90\u4E0D\u5F97\u542B\u7A7A\u767D\u5B57\u7B26");
6527
6534
  let u;
6528
6535
  try {
6529
- u = new URL(s);
6536
+ u = new URL(base);
6530
6537
  } catch {
6531
- return false;
6538
+ return bad("\u955C\u50CF\u6E90\u65E0\u6CD5\u89E3\u6790: " + base);
6532
6539
  }
6533
- if (u.protocol !== "http:" && u.protocol !== "https:") return false;
6534
- if (u.username || u.password) return false;
6535
- if (u.hash) return false;
6536
- if (!u.hostname) return false;
6537
- return u.pathname === "" || u.pathname === "/" || u.pathname === "//";
6540
+ if (u.protocol !== "http:" && u.protocol !== "https:") return bad("\u955C\u50CF\u6E90\u5FC5\u987B\u662F http(s) \u534F\u8BAE: " + base);
6541
+ if (u.username || u.password) return bad("\u955C\u50CF\u6E90\u4E0D\u5F97\u643A\u5E26\u7528\u6237\u540D\u6216\u5BC6\u7801: " + base);
6542
+ if (u.search) return bad("\u955C\u50CF\u6E90\u4E0D\u5F97\u643A\u5E26\u67E5\u8BE2\u4E32: " + base);
6543
+ if (u.hash) return bad("\u955C\u50CF\u6E90\u4E0D\u5F97\u643A\u5E26\u7247\u6BB5: " + base);
6544
+ if (!u.hostname) return bad("\u955C\u50CF\u6E90\u7F3A\u5C11\u4E3B\u673A\u540D: " + base);
6545
+ return { ok: true, base, protocol: u.protocol.replace(/:$/, ""), host: u.hostname, violation: null };
6538
6546
  }
6539
- function registryOriginViolation(origin) {
6540
- const o = normalizeOrigin(origin);
6541
- if (!isValidOrigin(o)) return "\u955C\u50CF\u6E90\u5FC5\u987B\u662F http(s) \u7EAF origin\uFF08\u65E0\u8DEF\u5F84/\u67E5\u8BE2/\u51ED\u8BC1\uFF09: " + o;
6547
+ function targetHostViolation(rawUrl, fromUrl) {
6542
6548
  let u;
6543
6549
  try {
6544
- u = new URL(o);
6550
+ u = new URL(String(rawUrl || ""));
6545
6551
  } catch {
6546
- return "\u955C\u50CF\u6E90\u65E0\u6CD5\u89E3\u6790: " + o;
6552
+ return "\u8DF3\u8F6C\u76EE\u6807\u65E0\u6CD5\u89E3\u6790";
6547
6553
  }
6548
- if (isPrivateHostLiteral(u.hostname)) return "\u955C\u50CF\u6E90\u4E3B\u673A\u4E0D\u5F97\u4E3A\u56DE\u73AF/\u79C1\u7F51/\u94FE\u8DEF\u672C\u5730/\u4FDD\u7559\u6BB5\u5B57\u9762\u91CF: " + o;
6549
- return null;
6554
+ if (u.protocol !== "http:" && u.protocol !== "https:") return "\u8DF3\u8F6C\u76EE\u6807\u534F\u8BAE\u975E\u6CD5: " + u.protocol;
6555
+ if (u.username || u.password) return "\u8DF3\u8F6C\u76EE\u6807\u4E0D\u5F97\u643A\u5E26\u51ED\u8BC1";
6556
+ let from;
6557
+ try {
6558
+ from = new URL(String(fromUrl || ""));
6559
+ } catch {
6560
+ from = null;
6561
+ }
6562
+ if (from && from.hostname.toLowerCase() === u.hostname.toLowerCase()) return null;
6563
+ return hostViolation(u.hostname);
6564
+ }
6565
+ function registryPackagePath(pkg) {
6566
+ return encodeURIComponent(String(pkg || ""));
6567
+ }
6568
+ function registryUrl(base, ...segments) {
6569
+ const parsed = parseRegistryBase(base);
6570
+ if (!parsed.ok) return null;
6571
+ const tail = segments.filter((s) => s !== "" && s != null).map((s) => String(s).replace(/^\/+/, "").replace(/\/+$/, "")).filter(Boolean).join("/");
6572
+ return tail ? parsed.base + "/" + tail : parsed.base;
6573
+ }
6574
+ function registryEnvPair(base) {
6575
+ const parsed = parseRegistryBase(base);
6576
+ if (!parsed.ok) return { ok: false, violation: parsed.violation, base: null, env: null };
6577
+ return {
6578
+ ok: true,
6579
+ violation: null,
6580
+ base: parsed.base,
6581
+ env: { npm_config_registry: parsed.base, NPM_CONFIG_REGISTRY: parsed.base }
6582
+ };
6583
+ }
6584
+ async function readCapped(res, maxBytes) {
6585
+ const cl = Number(res.headers && res.headers.get("content-length")) || 0;
6586
+ if (cl > maxBytes) return null;
6587
+ const reader = res.body && typeof res.body.getReader === "function" ? res.body.getReader() : null;
6588
+ if (!reader) {
6589
+ const text = await res.text();
6590
+ return text.length > maxBytes ? null : text;
6591
+ }
6592
+ const chunks = [];
6593
+ let total = 0;
6594
+ for (; ; ) {
6595
+ const { done, value } = await reader.read();
6596
+ if (done) break;
6597
+ if (!value) continue;
6598
+ total += value.byteLength || value.length || 0;
6599
+ if (total > maxBytes) {
6600
+ try {
6601
+ await reader.cancel();
6602
+ } catch {
6603
+ }
6604
+ return null;
6605
+ }
6606
+ chunks.push(value);
6607
+ }
6608
+ const buf = Buffer.concat(chunks.map((c) => Buffer.from(c.buffer, c.byteOffset, c.byteLength)));
6609
+ return buf.toString("utf8");
6610
+ }
6611
+ async function fetchRegistry(startUrl, opts) {
6612
+ const o = opts || {};
6613
+ const timeoutMs = Number.isFinite(o.timeoutMs) && o.timeoutMs > 0 ? o.timeoutMs : DEFAULT_TIMEOUT_MS;
6614
+ const maxBytes = Number.isFinite(o.maxBytes) && o.maxBytes > 0 ? o.maxBytes : MAX_BODY_BYTES;
6615
+ const maxHops = Number.isFinite(o.maxHops) ? o.maxHops : REDIRECT_MAX_HOPS;
6616
+ let url = String(startUrl || "");
6617
+ const hops = [];
6618
+ const fail = (status, error) => ({ ok: false, status, json: null, error, url, hops });
6619
+ for (let hop = 0; ; hop++) {
6620
+ let res;
6621
+ try {
6622
+ res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs), redirect: "manual" });
6623
+ } catch (e) {
6624
+ return fail(null, e && (e.name === "TimeoutError" ? "\u8D85\u65F6" : e.message) || String(e));
6625
+ }
6626
+ hops.push({ url, status: res.status });
6627
+ if (res.status >= 300 && res.status < 400) {
6628
+ try {
6629
+ if (res.body) await res.body.cancel();
6630
+ } catch {
6631
+ }
6632
+ if (hop >= maxHops) return fail(res.status, "\u8DF3\u8F6C\u6B21\u6570\u8D85\u8FC7\u4E0A\u9650");
6633
+ const loc = res.headers.get("location");
6634
+ if (!loc) return fail(res.status, "\u8DF3\u8F6C\u7F3A\u5C11 Location");
6635
+ let next;
6636
+ try {
6637
+ next = new URL(loc, url).toString();
6638
+ } catch {
6639
+ return fail(res.status, "\u8DF3\u8F6C\u76EE\u6807\u65E0\u6CD5\u89E3\u6790");
6640
+ }
6641
+ const tv = targetHostViolation(next, url);
6642
+ url = next;
6643
+ if (tv) return fail(res.status, tv);
6644
+ continue;
6645
+ }
6646
+ if (res.status < 200 || res.status >= 300) {
6647
+ try {
6648
+ if (res.body) await res.body.cancel();
6649
+ } catch {
6650
+ }
6651
+ return fail(res.status, "HTTP " + res.status);
6652
+ }
6653
+ if (o.expect === "none") {
6654
+ try {
6655
+ if (res.body) await res.body.cancel();
6656
+ } catch {
6657
+ }
6658
+ return { ok: true, status: res.status, json: null, error: null, url, hops };
6659
+ }
6660
+ let text;
6661
+ try {
6662
+ text = await readCapped(res, maxBytes);
6663
+ } catch (e) {
6664
+ return fail(res.status, "\u8BFB\u53D6\u54CD\u5E94\u4F53\u4E2D\u65AD\uFF1A" + (e && e.message || String(e)));
6665
+ }
6666
+ if (text === null) return fail(res.status, "\u54CD\u5E94\u4F53\u8D85\u8FC7\u4E0A\u9650");
6667
+ if (o.expect !== "json") return { ok: true, status: res.status, json: null, text, error: null, url, hops };
6668
+ try {
6669
+ return { ok: true, status: res.status, json: JSON.parse(text), error: null, url, hops };
6670
+ } catch {
6671
+ return fail(res.status, "\u54CD\u5E94\u4E0D\u662F\u5408\u6CD5 JSON");
6672
+ }
6673
+ }
6674
+ }
6675
+ module2.exports = {
6676
+ normalizeBase,
6677
+ hostViolation,
6678
+ parseRegistryBase,
6679
+ registryEnvPair,
6680
+ registryPackagePath,
6681
+ registryUrl,
6682
+ fetchRegistry
6683
+ };
6684
+ }
6685
+ });
6686
+
6687
+ // src/platform/distribution/policies.js
6688
+ var require_policies = __commonJS({
6689
+ "src/platform/distribution/policies.js"(exports2, module2) {
6690
+ "use strict";
6691
+ var registryRef = require_registry_ref();
6692
+ var NPM_TIMEOUT_MS = { install: 6e5, uninstall: 9e5 };
6693
+ var FALLBACK_REGISTRIES = [
6694
+ "https://registry.npmjs.org",
6695
+ "https://registry.npmmirror.com"
6696
+ ];
6697
+ function registryOriginViolation(origin) {
6698
+ const parsed = registryRef.parseRegistryBase(origin);
6699
+ if (!parsed.ok) return parsed.violation;
6700
+ return registryRef.hostViolation(parsed.host);
6550
6701
  }
6551
6702
  function effectiveOrigins(registryConfig, defaultRegistries) {
6552
6703
  const o = registryConfig && registryConfig.origins || [];
@@ -6564,32 +6715,28 @@ var require_policies = __commonJS({
6564
6715
  };
6565
6716
  }
6566
6717
  function resolveProbe(origin, spec, platformTag) {
6567
- const base = normalizeOrigin(origin);
6718
+ const timeoutMs = spec && Number.isFinite(spec.timeoutMs) && spec.timeoutMs > 0 ? spec.timeoutMs : 4e3;
6719
+ const parsed = registryRef.parseRegistryBase(origin);
6720
+ if (!parsed.ok) return { url: null, kind: "invalid", timeoutMs, violation: parsed.violation };
6568
6721
  if (spec && spec.kind === "package-metadata" && spec.pathTemplate && platformTag) {
6569
6722
  return {
6570
- url: base + "/" + spec.pathTemplate.replace("{platform}", platformTag),
6723
+ url: registryRef.registryUrl(parsed.base, spec.pathTemplate.replace("{platform}", platformTag)),
6571
6724
  kind: spec.kind,
6572
- timeoutMs: spec.timeoutMs || 4e3
6725
+ timeoutMs
6573
6726
  };
6574
6727
  }
6575
- return { url: base + "/-/ping", kind: "ping", timeoutMs: spec && spec.timeoutMs || 4e3 };
6576
- }
6577
- function pickFastestReachable(results) {
6578
- const reachable = results.filter((r) => r.ok).sort((a, b) => a.latencyMs - b.latencyMs);
6579
- return reachable.length ? reachable[0] : null;
6728
+ return { url: registryRef.registryUrl(parsed.base, "/-/ping"), kind: "ping", timeoutMs };
6580
6729
  }
6581
6730
  function isInCanaryList(state) {
6582
6731
  return state.canary === true;
6583
6732
  }
6584
6733
  module2.exports = {
6585
6734
  FALLBACK_REGISTRIES,
6586
- normalizeOrigin,
6587
- isValidOrigin,
6735
+ NPM_TIMEOUT_MS,
6588
6736
  registryOriginViolation,
6589
6737
  effectiveOrigins,
6590
6738
  rebuildRegistryConfig,
6591
6739
  resolveProbe,
6592
- pickFastestReachable,
6593
6740
  isInCanaryList
6594
6741
  };
6595
6742
  }
@@ -6705,64 +6852,6 @@ var require_release = __commonJS({
6705
6852
  }
6706
6853
  });
6707
6854
 
6708
- // src/platform/contract/matrix.js
6709
- var require_matrix = __commonJS({
6710
- "src/platform/contract/matrix.js"(exports2, module2) {
6711
- "use strict";
6712
- var SUPPORTED = [
6713
- { platform: "linux", arch: "x64", osTag: "linux", npmTag: "linux-x64" },
6714
- { platform: "darwin", arch: "arm64", osTag: "darwin", npmTag: "darwin-arm64" },
6715
- { platform: "darwin", arch: "x64", osTag: "darwin", npmTag: "darwin-x64" },
6716
- { platform: "win32", arch: "x64", osTag: "win", npmTag: "win-x64" }
6717
- ];
6718
- var OS_TAG = { linux: "linux", darwin: "darwin", win32: "win" };
6719
- var FRP_OS = { linux: "linux", darwin: "darwin", win32: "windows" };
6720
- var FRP_ARCH = { x64: "amd64", arm64: "arm64" };
6721
- function osTag(platform) {
6722
- return OS_TAG[platform || process.platform] || null;
6723
- }
6724
- function current(platform, arch) {
6725
- const p = platform || process.platform;
6726
- const a = arch || process.arch;
6727
- return { platform: p, arch: a, osTag: OS_TAG[p] || null, npmTag: npmTag(p, a) };
6728
- }
6729
- function npmTag(platform, arch) {
6730
- const p = platform || process.platform;
6731
- const a = arch || process.arch;
6732
- const os2 = OS_TAG[p];
6733
- if (!os2 || a !== "x64" && a !== "arm64") {
6734
- throw new Error("\u4E0D\u652F\u6301\u7684\u5E73\u53F0\u7EC4\u5408: " + p + "/" + a + "\uFF08\u4EC5 linux/darwin/win32 \xD7 x64/arm64\uFF09");
6735
- }
6736
- return os2 + "-" + a;
6737
- }
6738
- function isSupported(platform, arch) {
6739
- const p = platform || process.platform;
6740
- const a = arch || process.arch;
6741
- return SUPPORTED.some((x) => x.platform === p && x.arch === a);
6742
- }
6743
- function frpTag(platform, arch) {
6744
- const p = platform || process.platform;
6745
- const a = arch || process.arch;
6746
- const os2 = FRP_OS[p];
6747
- const am = FRP_ARCH[a];
6748
- if (!os2 || !am) return null;
6749
- return { os: os2, arch: am, tag: os2 + "_" + am, exe: p === "win32" };
6750
- }
6751
- function supportsProcessGroup(platform) {
6752
- return (platform || process.platform) !== "win32";
6753
- }
6754
- module2.exports = {
6755
- SUPPORTED,
6756
- osTag,
6757
- current,
6758
- npmTag,
6759
- isSupported,
6760
- frpTag,
6761
- supportsProcessGroup
6762
- };
6763
- }
6764
- });
6765
-
6766
6855
  // src/platform/contract/registry.js
6767
6856
  var require_registry = __commonJS({
6768
6857
  "src/platform/contract/registry.js"(exports2, module2) {
@@ -6864,26 +6953,16 @@ var require_registry = __commonJS({
6864
6953
  }
6865
6954
  });
6866
6955
 
6867
- // src/platform/distribution/registry.js
6868
- var require_registry2 = __commonJS({
6869
- "src/platform/distribution/registry.js"(exports2, module2) {
6956
+ // src/platform/distribution/registry-config.js
6957
+ var require_registry_config = __commonJS({
6958
+ "src/platform/distribution/registry-config.js"(exports2, module2) {
6870
6959
  "use strict";
6871
6960
  var fs2 = require("node:fs");
6872
6961
  var path2 = require("node:path");
6873
- var matrix = require_matrix();
6874
6962
  var registryContract = require_registry();
6875
6963
  var { writeAtomic } = require_fs();
6876
6964
  var policies = require_policies();
6877
6965
  var CONTRACT_TTL_MS = 60 * 1e3;
6878
- function platformTag() {
6879
- return matrix.npmTag();
6880
- }
6881
- function reloadContractIfStale(state) {
6882
- const now = Date.now();
6883
- if (state._contractLoadedAt && now - state._contractLoadedAt < CONTRACT_TTL_MS) return;
6884
- loadRegistryConfig(state);
6885
- state._contractLoadedAt = now;
6886
- }
6887
6966
  function loadRegistryConfig(state) {
6888
6967
  state.contract = registryContract.read(state.registryFile);
6889
6968
  if (!state.contract.ok) {
@@ -6910,6 +6989,12 @@ var require_registry2 = __commonJS({
6910
6989
  state.logger.warn && state.logger.warn("dist: registry config load failed: " + e.message);
6911
6990
  }
6912
6991
  }
6992
+ function reloadContractIfStale(state) {
6993
+ const now = Date.now();
6994
+ if (state._contractLoadedAt && now - state._contractLoadedAt < CONTRACT_TTL_MS) return;
6995
+ loadRegistryConfig(state);
6996
+ state._contractLoadedAt = now;
6997
+ }
6913
6998
  function saveRegistryConfig(state) {
6914
6999
  if (!state.registryFile) return;
6915
7000
  try {
@@ -6940,6 +7025,85 @@ var require_registry2 = __commonJS({
6940
7025
  doc.manualOrigin = rc.manualOrigin;
6941
7026
  writeAtomic(f, JSON.stringify(doc, null, 2) + "\n", { mode: 384 });
6942
7027
  }
7028
+ module2.exports = {
7029
+ CONTRACT_TTL_MS,
7030
+ loadRegistryConfig,
7031
+ reloadContractIfStale,
7032
+ saveRegistryConfig
7033
+ };
7034
+ }
7035
+ });
7036
+
7037
+ // src/platform/contract/matrix.js
7038
+ var require_matrix = __commonJS({
7039
+ "src/platform/contract/matrix.js"(exports2, module2) {
7040
+ "use strict";
7041
+ var SUPPORTED = [
7042
+ { platform: "linux", arch: "x64", osTag: "linux", npmTag: "linux-x64" },
7043
+ { platform: "darwin", arch: "arm64", osTag: "darwin", npmTag: "darwin-arm64" },
7044
+ { platform: "darwin", arch: "x64", osTag: "darwin", npmTag: "darwin-x64" },
7045
+ { platform: "win32", arch: "x64", osTag: "win", npmTag: "win-x64" }
7046
+ ];
7047
+ var OS_TAG = { linux: "linux", darwin: "darwin", win32: "win" };
7048
+ var FRP_OS = { linux: "linux", darwin: "darwin", win32: "windows" };
7049
+ var FRP_ARCH = { x64: "amd64", arm64: "arm64" };
7050
+ function osTag(platform) {
7051
+ return OS_TAG[platform || process.platform] || null;
7052
+ }
7053
+ function current(platform, arch) {
7054
+ const p = platform || process.platform;
7055
+ const a = arch || process.arch;
7056
+ return { platform: p, arch: a, osTag: OS_TAG[p] || null, npmTag: npmTag(p, a) };
7057
+ }
7058
+ function npmTag(platform, arch) {
7059
+ const p = platform || process.platform;
7060
+ const a = arch || process.arch;
7061
+ const os2 = OS_TAG[p];
7062
+ if (!os2 || a !== "x64" && a !== "arm64") {
7063
+ throw new Error("\u4E0D\u652F\u6301\u7684\u5E73\u53F0\u7EC4\u5408: " + p + "/" + a + "\uFF08\u4EC5 linux/darwin/win32 \xD7 x64/arm64\uFF09");
7064
+ }
7065
+ return os2 + "-" + a;
7066
+ }
7067
+ function isSupported(platform, arch) {
7068
+ const p = platform || process.platform;
7069
+ const a = arch || process.arch;
7070
+ return SUPPORTED.some((x) => x.platform === p && x.arch === a);
7071
+ }
7072
+ function frpTag(platform, arch) {
7073
+ const p = platform || process.platform;
7074
+ const a = arch || process.arch;
7075
+ const os2 = FRP_OS[p];
7076
+ const am = FRP_ARCH[a];
7077
+ if (!os2 || !am) return null;
7078
+ return { os: os2, arch: am, tag: os2 + "_" + am, exe: p === "win32" };
7079
+ }
7080
+ function supportsProcessGroup(platform) {
7081
+ return (platform || process.platform) !== "win32";
7082
+ }
7083
+ module2.exports = {
7084
+ SUPPORTED,
7085
+ osTag,
7086
+ current,
7087
+ npmTag,
7088
+ isSupported,
7089
+ frpTag,
7090
+ supportsProcessGroup
7091
+ };
7092
+ }
7093
+ });
7094
+
7095
+ // src/platform/distribution/registry.js
7096
+ var require_registry2 = __commonJS({
7097
+ "src/platform/distribution/registry.js"(exports2, module2) {
7098
+ "use strict";
7099
+ var matrix = require_matrix();
7100
+ var policies = require_policies();
7101
+ var ref = require_registry_ref();
7102
+ var config = require_registry_config();
7103
+ var PROBE_MAX_BODY_BYTES = 8 * 1024 * 1024;
7104
+ function platformTag() {
7105
+ return matrix.npmTag();
7106
+ }
6943
7107
  async function probeRegistry(state, origin) {
6944
7108
  const spec = state.contract && state.contract.ok && state.contract.probe || null;
6945
7109
  let tag = null;
@@ -6949,106 +7113,154 @@ var require_registry2 = __commonJS({
6949
7113
  tag = null;
6950
7114
  }
6951
7115
  const target = policies.resolveProbe(origin, spec, tag);
6952
- const start = Date.now();
6953
- try {
6954
- const res = await fetch(target.url, { signal: AbortSignal.timeout(target.timeoutMs), redirect: "manual" });
6955
- const ok = res.status >= 200 && res.status < 300;
6956
- return { ok, latencyMs: Date.now() - start, probe: target.kind };
6957
- } catch (e) {
6958
- return { ok: false, latencyMs: Date.now() - start, probe: target.kind };
7116
+ if (!target.url) {
7117
+ return { ok: false, latencyMs: 0, probe: target.kind, error: target.violation || "\u955C\u50CF\u57FA\u5740\u975E\u6CD5" };
6959
7118
  }
7119
+ const start = Date.now();
7120
+ const r = await ref.fetchRegistry(target.url, {
7121
+ timeoutMs: target.timeoutMs,
7122
+ expect: "text",
7123
+ maxBytes: PROBE_MAX_BODY_BYTES
7124
+ });
7125
+ return { ok: !!r.ok, latencyMs: Date.now() - start, probe: target.kind, error: r.error || null };
6960
7126
  }
6961
7127
  async function probeOrigin(state, origin) {
6962
- const o = policies.normalizeOrigin(origin);
6963
- if (!policies.isValidOrigin(o)) return { origin: o, ok: false, latencyMs: null, error: "\u975E\u6CD5 origin" };
6964
- const p = await probeRegistry(state, o);
6965
- return { origin: o, ok: !!p.ok, latencyMs: p.latencyMs, probe: p.probe };
7128
+ const parsed = ref.parseRegistryBase(origin);
7129
+ if (!parsed.ok) return { origin: ref.normalizeBase(origin), ok: false, latencyMs: null, error: parsed.violation };
7130
+ const p = await probeRegistry(state, parsed.base);
7131
+ return { origin: parsed.base, ok: !!p.ok, latencyMs: p.latencyMs, probe: p.probe, error: p.error || null };
6966
7132
  }
6967
7133
  function registryOrigins(state) {
6968
- return policies.effectiveOrigins(state.registryConfig, state.defaultRegistries);
7134
+ const seen = /* @__PURE__ */ new Set();
7135
+ const out = [];
7136
+ for (const raw of policies.effectiveOrigins(state.registryConfig, state.defaultRegistries)) {
7137
+ const parsed = ref.parseRegistryBase(raw);
7138
+ const base = parsed.ok ? parsed.base : ref.normalizeBase(raw);
7139
+ if (seen.has(base)) continue;
7140
+ seen.add(base);
7141
+ out.push(base);
7142
+ }
7143
+ return out;
7144
+ }
7145
+ async function probeAllOrigins(state, origins) {
7146
+ const results = await Promise.all(origins.map(async (origin) => {
7147
+ const p = await probeRegistry(state, origin);
7148
+ return { origin, ok: !!p.ok, latencyMs: p.latencyMs, error: p.error || null };
7149
+ }));
7150
+ results.sort((a, b) => a.ok === b.ok ? a.latencyMs - b.latencyMs : a.ok ? -1 : 1);
7151
+ return results;
7152
+ }
7153
+ function orderFor(primary, origins, results) {
7154
+ const usable = (o) => ref.parseRegistryBase(o).ok;
7155
+ const ranked = (results || []).filter((r) => r.ok).map((r) => r.origin);
7156
+ const ordered = [];
7157
+ for (const o of [primary, ...ranked, ...origins]) {
7158
+ if (!o || !usable(o)) continue;
7159
+ if (!ordered.includes(o)) ordered.push(o);
7160
+ }
7161
+ return ordered;
6969
7162
  }
6970
7163
  async function selectRegistry(state, force) {
6971
- reloadContractIfStale(state);
7164
+ config.reloadContractIfStale(state);
6972
7165
  const rc = state.registryConfig || {};
6973
- if (rc.mode === "manual" && rc.manualOrigin) {
6974
- const origin = policies.normalizeOrigin(rc.manualOrigin);
6975
- state.selectedRegistry = { origin, latencyMs: null, checkedAt: Date.now(), manual: true, probes: [] };
6976
- return origin;
6977
- }
7166
+ const origins = registryOrigins(state);
7167
+ const manualParsed = ref.parseRegistryBase(rc.manualOrigin);
7168
+ const manualBase = manualParsed.ok ? manualParsed.base : "";
7169
+ const manual = rc.mode === "manual" && !!manualBase;
6978
7170
  const now = Date.now();
6979
- if (!force && state.selectedRegistry && !state.selectedRegistry.manual && state.selectedRegistry.checkedAt && now - state.selectedRegistry.checkedAt < 30 * 60 * 1e3) {
6980
- return state.selectedRegistry.origin;
7171
+ const cached = state.selectedRegistry;
7172
+ if (!force && cached && cached.checkedAt && now - cached.checkedAt < 30 * 60 * 1e3) {
7173
+ return cached;
6981
7174
  }
6982
7175
  const c = state.contract;
6983
- if (!force && c && c.ok && c.selected) {
7176
+ if (!force && !manual && c && c.ok && c.selected) {
6984
7177
  const age = Math.floor(Date.now() / 1e3) - c.selected.checkedAt;
6985
- if (age >= 0 && age < 30 * 60) {
7178
+ const adopted = ref.parseRegistryBase(c.selected.origin);
7179
+ if (age >= 0 && age < 30 * 60 && adopted.ok) {
7180
+ const origin = adopted.base;
6986
7181
  state.selectedRegistry = {
6987
- origin: c.selected.origin,
6988
- latencyMs: c.selected.latencyMs,
6989
- checkedAt: Date.now(),
6990
- manual: false,
7182
+ origin,
7183
+ ordered: orderFor(origin, origins, null),
6991
7184
  source: "shell",
6992
- probes: []
7185
+ manual: false,
7186
+ checkedAt: now,
7187
+ latencyMs: Number.isFinite(c.selected.latencyMs) ? c.selected.latencyMs : null,
7188
+ probes: [{ origin, ok: true, latencyMs: c.selected.latencyMs, error: null, from: "shell-contract" }]
6993
7189
  };
6994
7190
  if (state.events) {
6995
7191
  try {
6996
- state.events.append("dist_registry_selected", { origin: c.selected.origin, source: "shell-contract" });
7192
+ state.events.append("dist_registry_selected", { origin, source: "shell-contract" });
6997
7193
  } catch {
6998
7194
  }
6999
7195
  }
7000
- return c.selected.origin;
7196
+ return state.selectedRegistry;
7001
7197
  }
7002
- }
7003
- const origins = registryOrigins(state);
7004
- const results = await Promise.all(origins.map(async (origin) => {
7005
- const p = await probeRegistry(state, origin);
7006
- return { origin, ok: p.ok, latencyMs: p.latencyMs };
7007
- }));
7008
- const picked = policies.pickFastestReachable(results);
7009
- if (!picked) {
7010
- state.selectedRegistry = { origin: null, latencyMs: null, checkedAt: null, manual: false, probes: results };
7011
- if (state.events) {
7012
- state.events.append("dist_registry_unreachable", {
7013
- candidates: results.map((r) => r.origin + ":" + r.latencyMs + "ms")
7014
- });
7198
+ if (!adopted.ok && state.logger && state.logger.warn) {
7199
+ state.logger.warn("dist: \u5951\u7EA6 selected \u57FA\u5740\u975E\u6CD5\uFF0C\u6539\u4E3A\u81EA\u884C\u6D4B\u901F\uFF08" + adopted.violation + "\uFF09");
7015
7200
  }
7016
- return null;
7017
7201
  }
7018
- state.selectedRegistry = {
7019
- origin: picked.origin,
7020
- latencyMs: picked.latencyMs,
7021
- checkedAt: Date.now(),
7022
- manual: false,
7202
+ const results = await probeAllOrigins(state, origins);
7203
+ const firstReachable = results.find((r) => r.ok);
7204
+ const primary = manual ? manualBase : firstReachable && firstReachable.origin || null;
7205
+ const selected = {
7206
+ origin: primary,
7207
+ ordered: orderFor(primary, origins, results),
7208
+ source: manual ? "manual" : firstReachable ? "probe" : "unreachable",
7209
+ manual,
7210
+ checkedAt: firstReachable || manual ? now : null,
7211
+ // 全不可达不缓存坏选择:下次调用仍会重测
7212
+ latencyMs: firstReachable && firstReachable.origin === primary ? firstReachable.latencyMs : null,
7023
7213
  probes: results
7024
7214
  };
7215
+ state.selectedRegistry = selected;
7025
7216
  if (state.events) {
7026
- state.events.append("dist_registry_selected", {
7027
- origin: picked.origin,
7028
- latencyMs: picked.latencyMs,
7029
- candidates: results.map((r) => r.origin + ":" + r.latencyMs + "ms")
7030
- });
7217
+ try {
7218
+ state.events.append(firstReachable || manual ? "dist_registry_selected" : "dist_registry_unreachable", {
7219
+ origin: primary,
7220
+ source: selected.source,
7221
+ candidates: results.map((r) => r.origin + ":" + (r.ok ? r.latencyMs + "ms" : r.error || "\u4E0D\u53EF\u8FBE"))
7222
+ });
7223
+ } catch {
7224
+ }
7031
7225
  }
7032
- return picked.origin;
7226
+ return selected;
7227
+ }
7228
+ async function registryOrigin(state, force) {
7229
+ const sel = await selectRegistry(state, force);
7230
+ return sel && sel.origin || null;
7033
7231
  }
7034
7232
  async function registryInfo(state) {
7035
- reloadContractIfStale(state);
7036
- const origin = await selectRegistry(state, false);
7233
+ config.reloadContractIfStale(state);
7234
+ const sel = await selectRegistry(state, false) || {};
7037
7235
  const rc = state.registryConfig || {};
7038
7236
  const c = state.contract;
7039
- const sel = state.selectedRegistry;
7237
+ const verdictOf = (origin) => (sel.probes || []).find((p) => p.origin === origin) || null;
7040
7238
  return {
7041
- origin,
7239
+ origin: sel.origin || null,
7240
+ ordered: sel.ordered || [],
7241
+ source: sel.source || null,
7042
7242
  mode: rc.mode || "auto",
7043
7243
  manualOrigin: rc.manualOrigin || "",
7044
7244
  candidates: registryOrigins(state).map((o) => ({ origin: o })),
7245
+ registries: registryOrigins(state).map((o) => {
7246
+ const parsed = ref.parseRegistryBase(o);
7247
+ const v = verdictOf(o);
7248
+ return {
7249
+ base: parsed.base,
7250
+ usable: parsed.ok,
7251
+ violation: parsed.violation,
7252
+ reachable: v ? v.ok : null,
7253
+ latencyMs: v ? v.latencyMs : null,
7254
+ error: v ? v.error || null : null
7255
+ };
7256
+ }),
7045
7257
  // 预设 = 壳投放的目录;契约不可用时为空数组,UI 应展示 candidates。
7046
7258
  presets: c && c.ok ? c.catalog : [],
7047
7259
  catalogSource: c && c.ok ? c.writtenBy || "shell" : "fallback",
7048
- latencyMs: sel && sel.latencyMs || null,
7049
- checkedAt: sel && sel.checkedAt || null,
7050
- manual: !!(sel && sel.manual),
7051
- probes: sel && sel.probes || []
7260
+ latencyMs: sel.latencyMs || null,
7261
+ checkedAt: sel.checkedAt || null,
7262
+ manual: !!sel.manual,
7263
+ probes: sel.probes || []
7052
7264
  };
7053
7265
  }
7054
7266
  async function setRegistryConfig(state, cfg) {
@@ -7085,7 +7297,7 @@ var require_registry2 = __commonJS({
7085
7297
  }
7086
7298
  }
7087
7299
  state.registryConfig = rc;
7088
- saveRegistryConfig(state);
7300
+ config.saveRegistryConfig(state);
7089
7301
  state.selectedRegistry = null;
7090
7302
  const info = await registryInfo(state);
7091
7303
  if (rejected.length) {
@@ -7097,21 +7309,127 @@ var require_registry2 = __commonJS({
7097
7309
  return info;
7098
7310
  }
7099
7311
  module2.exports = {
7100
- CONTRACT_TTL_MS,
7101
7312
  platformTag,
7102
- reloadContractIfStale,
7103
- loadRegistryConfig,
7104
- saveRegistryConfig,
7105
7313
  probeRegistry,
7106
7314
  probeOrigin,
7315
+ probeAllOrigins,
7107
7316
  registryOrigins,
7317
+ orderFor,
7108
7318
  selectRegistry,
7319
+ registryOrigin,
7109
7320
  registryInfo,
7110
7321
  setRegistryConfig
7111
7322
  };
7112
7323
  }
7113
7324
  });
7114
7325
 
7326
+ // src/platform/distribution/version-check.js
7327
+ var require_version_check = __commonJS({
7328
+ "src/platform/distribution/version-check.js"(exports2, module2) {
7329
+ "use strict";
7330
+ var { VERSION_RE } = require_version2();
7331
+ var input = require_input();
7332
+ var policies = require_policies();
7333
+ var registry = require_registry2();
7334
+ var ref = require_registry_ref();
7335
+ var release = require_release();
7336
+ var PKG_NAME_RE = input.PKG_NAME_RE;
7337
+ var METADATA_TIMEOUT_MS = 8e3;
7338
+ var FETCH_BUDGET_MS = 25e3;
7339
+ async function versionFromOrigin(state, base, pkg) {
7340
+ const url = ref.registryUrl(base, ref.registryPackagePath(pkg));
7341
+ const res = await ref.fetchRegistry(url, { timeoutMs: METADATA_TIMEOUT_MS, expect: "json" });
7342
+ if (!res.ok) return { version: null, error: res.error || "HTTP " + res.status };
7343
+ const picked = release.pickReleaseVersion(res.json, {
7344
+ isOurs: release.isOurReleasePackage(pkg),
7345
+ canary: policies.isInCanaryList(state),
7346
+ // 仅 isOurs 分支消费
7347
+ isValid: (v2) => typeof v2 === "string" && VERSION_RE.test(v2)
7348
+ });
7349
+ if (picked) return { version: picked, error: null };
7350
+ const lr = await ref.fetchRegistry(
7351
+ ref.registryUrl(base, ref.registryPackagePath(pkg), "latest"),
7352
+ { timeoutMs: METADATA_TIMEOUT_MS, expect: "json" }
7353
+ );
7354
+ if (!lr.ok) return { version: null, error: lr.error || "HTTP " + lr.status };
7355
+ const v = lr.json && typeof lr.json.version === "string" && VERSION_RE.test(lr.json.version) ? lr.json.version : null;
7356
+ return { version: v, error: v ? null : "\u5143\u6570\u636E\u65E0\u53EF\u7528\u7248\u672C" };
7357
+ }
7358
+ async function fetchNpmLatest(state, pkg, opts) {
7359
+ const o = opts || {};
7360
+ const fail = (error, attempts2) => ({ ok: false, version: null, origin: null, attempts: attempts2 || [], error });
7361
+ if (!pkg) return fail("\u7F3A\u5C11\u5305\u540D");
7362
+ if (!PKG_NAME_RE.test(pkg)) return fail("\u975E\u6CD5\u5305\u540D\uFF08\u5B57\u7B26\u96C6\u767D\u540D\u5355\u4E0D\u901A\u8FC7\uFF09: " + String(pkg).slice(0, 80));
7363
+ let candidates = [];
7364
+ if (o.authoritative) {
7365
+ const list = registry.registryOrigins(state).filter((x) => ref.parseRegistryBase(x).ok);
7366
+ candidates = list.filter((x) => /registry\.npmjs\.org/.test(x));
7367
+ if (!candidates.length && list.length) candidates = [list[0]];
7368
+ } else {
7369
+ const sel = await registry.selectRegistry(state, false);
7370
+ candidates = sel && sel.ordered || [];
7371
+ }
7372
+ if (!candidates.length) return fail("\u65E0\u53EF\u7528\u7684\u955C\u50CF\u6E90\u5019\u9009\uFF08\u5168\u90E8\u57FA\u5740\u975E\u6CD5\u6216\u5217\u8868\u4E3A\u7A7A\uFF09");
7373
+ const attempts = [];
7374
+ const deadline = Date.now() + FETCH_BUDGET_MS;
7375
+ for (let i = 0; i < candidates.length; i++) {
7376
+ if (i && Date.now() >= deadline) {
7377
+ attempts.push({ origin: candidates.slice(i).join(","), error: "\u672A\u5C1D\u8BD5\uFF08\u8D85\u51FA " + Math.round(FETCH_BUDGET_MS / 1e3) + "s \u603B\u9884\u7B97\uFF09" });
7378
+ break;
7379
+ }
7380
+ const base = candidates[i];
7381
+ const r = await versionFromOrigin(state, base, pkg);
7382
+ if (r.version) return { ok: true, version: r.version, origin: base, attempts, error: null };
7383
+ attempts.push({ origin: base, error: r.error || "\u672A\u53D6\u5230\u7248\u672C" });
7384
+ }
7385
+ return fail("\u5168\u90E8\u955C\u50CF\u672A\u53D6\u5230 " + pkg + " \u7684\u7248\u672C\uFF1A" + attempts.map((a) => a.origin + "=" + a.error).join("; "), attempts);
7386
+ }
7387
+ async function fetchGithubLatest(owner, repo) {
7388
+ if (!owner || !repo) return null;
7389
+ try {
7390
+ const res = await fetch(
7391
+ "https://api.github.com/repos/" + encodeURIComponent(owner) + "/" + encodeURIComponent(repo) + "/releases/latest",
7392
+ { signal: AbortSignal.timeout(1e4), headers: { "User-Agent": "dsh-supervisor" } }
7393
+ );
7394
+ if (!res.ok) return null;
7395
+ const j = await res.json();
7396
+ const tag = j && typeof j.tag_name === "string" ? j.tag_name : j && typeof j.name === "string" ? j.name : null;
7397
+ if (!tag) return null;
7398
+ return String(tag).replace(/^v/, "");
7399
+ } catch (e) {
7400
+ return null;
7401
+ }
7402
+ }
7403
+ async function fetchVersionInfo(state, pkg, channel, opts) {
7404
+ const ch = channel || "npm";
7405
+ const o = opts || {};
7406
+ if (ch === "github") {
7407
+ const slash = String(pkg).split("/");
7408
+ const version = slash.length >= 2 ? await fetchGithubLatest(slash[0], slash.slice(1).join("/")) : null;
7409
+ return {
7410
+ ok: !!version,
7411
+ version: version || null,
7412
+ origin: null,
7413
+ attempts: [],
7414
+ error: version ? null : "GitHub Releases \u672A\u67E5\u8BE2\u5230 " + pkg + " \u7684\u6700\u65B0\u7248"
7415
+ };
7416
+ }
7417
+ return fetchNpmLatest(state, pkg, { authoritative: o.authoritative === true });
7418
+ }
7419
+ async function fetchLatestVersion(state, pkg, channel, opts) {
7420
+ const r = await fetchVersionInfo(state, pkg, channel, opts);
7421
+ return r.ok ? r.version : null;
7422
+ }
7423
+ module2.exports = {
7424
+ METADATA_TIMEOUT_MS,
7425
+ FETCH_BUDGET_MS,
7426
+ fetchNpmLatest,
7427
+ fetchVersionInfo,
7428
+ fetchLatestVersion
7429
+ };
7430
+ }
7431
+ });
7432
+
7115
7433
  // src/platform/contract/runtime.js
7116
7434
  var require_runtime = __commonJS({
7117
7435
  "src/platform/contract/runtime.js"(exports2, module2) {
@@ -7189,72 +7507,12 @@ var require_install = __commonJS({
7189
7507
  var runtimeContract = require_runtime();
7190
7508
  var service = require_service().current();
7191
7509
  var { VERSION_RE } = require_version2();
7192
- var release = require_release();
7193
- var registry = require_registry2();
7510
+ var ref = require_registry_ref();
7194
7511
  var policies = require_policies();
7195
7512
  var input = require_input();
7196
7513
  var PKG_NAME_RE = input.PKG_NAME_RE;
7197
7514
  var BAD_ARGV_CHAR_RE = input.ARGV_UNSAFE_RE;
7198
7515
  var WIN_DRIVE_ABS_RE = input.WIN_ABS_PATH_RE;
7199
- async function fetchNpmLatest(state, pkg, opts) {
7200
- if (!pkg) return null;
7201
- const o = opts || {};
7202
- let origin = null;
7203
- if (o.authoritative) {
7204
- const list = registry.registryOrigins(state);
7205
- origin = list.find((x) => /registry\.npmjs\.org/.test(x)) || list[0] || "https://registry.npmjs.org";
7206
- } else {
7207
- origin = await registry.selectRegistry(state, false);
7208
- }
7209
- if (!origin) return null;
7210
- const base = policies.normalizeOrigin(origin);
7211
- if (!policies.isValidOrigin(base)) return null;
7212
- if (!PKG_NAME_RE.test(pkg)) return null;
7213
- try {
7214
- const res = await fetch(base + "/" + encodeURIComponent(pkg), { signal: AbortSignal.timeout(1e4) });
7215
- if (!res.ok) return null;
7216
- const j = await res.json();
7217
- const picked = release.pickReleaseVersion(j, {
7218
- isOurs: release.isOurReleasePackage(pkg),
7219
- canary: policies.isInCanaryList(state),
7220
- // 仅 isOurs 分支消费
7221
- isValid: (v) => typeof v === "string" && VERSION_RE.test(v)
7222
- });
7223
- if (picked) return picked;
7224
- const lr = await fetch(base + "/" + encodeURIComponent(pkg) + "/latest", { signal: AbortSignal.timeout(8e3) });
7225
- if (!lr.ok) return null;
7226
- const lj = await lr.json();
7227
- return lj && typeof lj.version === "string" && VERSION_RE.test(lj.version) ? lj.version : null;
7228
- } catch (e) {
7229
- return null;
7230
- }
7231
- }
7232
- async function fetchGithubLatest(owner, repo) {
7233
- if (!owner || !repo) return null;
7234
- try {
7235
- const res = await fetch(
7236
- "https://api.github.com/repos/" + encodeURIComponent(owner) + "/" + encodeURIComponent(repo) + "/releases/latest",
7237
- { signal: AbortSignal.timeout(1e4), headers: { "User-Agent": "dsh-supervisor" } }
7238
- );
7239
- if (!res.ok) return null;
7240
- const j = await res.json();
7241
- const tag = j && typeof j.tag_name === "string" ? j.tag_name : j && typeof j.name === "string" ? j.name : null;
7242
- if (!tag) return null;
7243
- return String(tag).replace(/^v/, "");
7244
- } catch (e) {
7245
- return null;
7246
- }
7247
- }
7248
- async function fetchLatestVersion(state, pkg, channel, opts) {
7249
- const ch = channel || "npm";
7250
- const o = opts || {};
7251
- if (ch === "github") {
7252
- const slash = String(pkg).split("/");
7253
- if (slash.length >= 2) return fetchGithubLatest(slash[0], slash.slice(1).join("/"));
7254
- return null;
7255
- }
7256
- return fetchNpmLatest(state, pkg, { authoritative: o.authoritative === true });
7257
- }
7258
7516
  var INFLIGHT_NPM = /* @__PURE__ */ new Set();
7259
7517
  function inflightNpmCount() {
7260
7518
  return INFLIGHT_NPM.size;
@@ -7271,50 +7529,55 @@ var require_install = __commonJS({
7271
7529
  }
7272
7530
  function runNpmInstall(opts) {
7273
7531
  const o = opts || {};
7532
+ const action = o.action === void 0 || o.action === null ? "install" : String(o.action);
7533
+ const bad = (r) => ({ ok: false, error: null, output: [], exitCode: null, timedOut: false, aborted: false, ...r });
7534
+ const fail = (error) => Promise.resolve(bad({ error }));
7535
+ if (action !== "install" && action !== "uninstall") return fail("runNpmInstall: \u672A\u77E5 action\uFF08\u53EA\u63A5\u53D7 install/uninstall\uFF09: " + action.slice(0, 40));
7274
7536
  const pkg = o.pkg || "@deepseek-ai/dsh";
7275
- if (!o.version) return Promise.resolve({ ok: false, error: "runNpmInstall: \u7F3A\u5C11 version\uFF08\u5FC5\u987B\u663E\u5F0F\u643A\u5E26\uFF09", output: [] });
7276
- if (!PKG_NAME_RE.test(pkg)) return Promise.resolve({ ok: false, error: "runNpmInstall: \u975E\u6CD5\u5305\u540D\uFF08\u5B57\u7B26\u96C6\u767D\u540D\u5355\u4E0D\u901A\u8FC7\uFF09: " + String(pkg).slice(0, 80), output: [] });
7277
- if (!VERSION_RE.test(String(o.version))) return Promise.resolve({ ok: false, error: "runNpmInstall: \u975E\u6CD5\u7248\u672C\u53F7\uFF08\u987B\u4E3A\u4E25\u683C semver\uFF09: " + String(o.version).slice(0, 80), output: [] });
7537
+ if (action === "install" && !o.version) return fail("runNpmInstall: \u7F3A\u5C11 version\uFF08\u5FC5\u987B\u663E\u5F0F\u643A\u5E26\uFF09");
7538
+ if (!PKG_NAME_RE.test(pkg)) return fail("runNpmInstall: \u975E\u6CD5\u5305\u540D\uFF08\u5B57\u7B26\u96C6\u767D\u540D\u5355\u4E0D\u901A\u8FC7\uFF09: " + String(pkg).slice(0, 80));
7539
+ if (action === "install" && !VERSION_RE.test(String(o.version))) return fail("runNpmInstall: \u975E\u6CD5\u7248\u672C\u53F7\uFF08\u987B\u4E3A\u4E25\u683C semver\uFF09: " + String(o.version).slice(0, 80));
7278
7540
  let argv;
7279
- const launcher = runtimeContract.npmLauncher();
7541
+ const contractLauncher = runtimeContract.npmLauncher();
7542
+ const launcher = o.launcher && o.launcher.program ? { program: String(o.launcher.program), args: Array.isArray(o.launcher.args) ? o.launcher.args.map(String) : [] } : contractLauncher;
7280
7543
  let bin = launcher.program;
7281
7544
  if (Array.isArray(o.commandTemplate) && o.commandTemplate.length) {
7282
- argv = o.commandTemplate.map((s) => String(s).replace(/{pkg}/g, pkg).replace(/{version}/g, o.version).replace(/{prefix}/g, o.prefix || ""));
7545
+ argv = o.commandTemplate.map((s) => String(s).replace(/{pkg}/g, pkg).replace(/{version}/g, o.version || "").replace(/{prefix}/g, o.prefix || ""));
7283
7546
  const fromTemplate = argv[0] !== "npm";
7284
7547
  bin = fromTemplate ? argv[0] : launcher.program;
7285
7548
  argv = (fromTemplate ? [] : launcher.args).concat(argv.slice(1));
7286
7549
  if (!fromTemplate && launcher.source === "path" && bin === "npm" && !execPath.resolveExecutable("npm")) {
7287
- return Promise.resolve({ ok: false, error: 'runNpmInstall: \u672A\u627E\u5230\u53EF\u6267\u884C\u7684 npm\uFF08commandTemplate[0]="npm" \u89E3\u6790\u5931\u8D25\uFF09', output: [] });
7550
+ return fail('runNpmInstall: \u672A\u627E\u5230\u53EF\u6267\u884C\u7684 npm\uFF08commandTemplate[0]="npm" \u89E3\u6790\u5931\u8D25\uFF09');
7288
7551
  }
7289
7552
  for (const a of argv) {
7290
7553
  if (BAD_ARGV_CHAR_RE.test(String(a)) && !WIN_DRIVE_ABS_RE.test(String(a))) {
7291
- return Promise.resolve({ ok: false, error: "runNpmInstall: commandTemplate \u66FF\u6362\u540E\u542B\u7981\u7528\u5B57\u7B26\uFF08\u7A7A\u767D/shell \u5143\u5B57\u7B26\uFF09: " + String(a).slice(0, 80), output: [] });
7554
+ return fail("runNpmInstall: commandTemplate \u66FF\u6362\u540E\u542B\u7981\u7528\u5B57\u7B26\uFF08\u7A7A\u767D/shell \u5143\u5B57\u7B26\uFF09: " + String(a).slice(0, 80));
7292
7555
  }
7293
7556
  }
7294
7557
  } else {
7295
- argv = [...launcher.args, "install", "-g", "--no-audit", "--no-fund"];
7558
+ argv = [...launcher.args, action, "-g"];
7559
+ if (action === "install") argv.push("--no-audit", "--no-fund");
7296
7560
  argv.push("--ignore-scripts");
7297
7561
  if (o.prefix) {
7298
7562
  const pv = input.prefixViolation(o.prefix);
7299
- if (pv) return Promise.resolve({ ok: false, error: "runNpmInstall: " + pv, output: [] });
7563
+ if (pv) return fail("runNpmInstall: " + pv);
7300
7564
  argv.push("--prefix", String(o.prefix));
7301
7565
  }
7302
- argv.push(pkg + "@" + o.version);
7566
+ argv.push(action === "install" ? pkg + "@" + o.version : pkg);
7303
7567
  }
7304
7568
  const envVars = runtimeContract.withPath(process.env);
7305
- if (o.registry) {
7306
- if (!policies.isValidOrigin(o.registry)) {
7307
- return Promise.resolve({ ok: false, error: "runNpmInstall: \u975E\u6CD5 registry origin\uFF08\u987B\u4E3A\u7EAF http(s) origin\uFF09: " + String(o.registry).slice(0, 80), output: [] });
7308
- }
7309
- envVars.npm_config_registry = o.registry;
7310
- envVars.NPM_CONFIG_REGISTRY = o.registry;
7569
+ if (o.registry && action === "install") {
7570
+ const rp = ref.registryEnvPair(o.registry);
7571
+ if (!rp.ok) return fail("runNpmInstall: \u975E\u6CD5 registry \u57FA\u5740\uFF08" + rp.violation + "\uFF09: " + String(o.registry).slice(0, 80));
7572
+ Object.assign(envVars, rp.env);
7311
7573
  }
7574
+ const timeoutMs = Number(o.timeoutMs) > 0 ? Number(o.timeoutMs) : policies.NPM_TIMEOUT_MS[action];
7312
7575
  return new Promise((resolve) => {
7313
7576
  let child;
7314
7577
  try {
7315
7578
  child = spawnOS.piped(bin, argv, { env: envVars, detached: o.detached !== false });
7316
7579
  } catch (e) {
7317
- return resolve({ ok: false, error: e.message, output: [] });
7580
+ return resolve(bad({ error: e.message }));
7318
7581
  }
7319
7582
  const out = [];
7320
7583
  let settled = false;
@@ -7341,13 +7604,13 @@ var require_install = __commonJS({
7341
7604
  pid: child.pid,
7342
7605
  abort: (reason) => {
7343
7606
  killTree();
7344
- finish({ ok: false, aborted: true, error: "\u5B89\u88C5\u88AB\u4E2D\u6B62: " + (reason || "guard-exit"), output: out });
7607
+ finish(bad({ aborted: true, error: "npm " + action + " \u88AB\u4E2D\u6B62: " + (reason || "guard-exit"), output: out }));
7345
7608
  }
7346
7609
  };
7347
7610
  const timer = setTimeout(() => {
7348
7611
  killTree();
7349
- finish({ ok: false, error: "\u5B89\u88C5\u8D85\u65F6", output: out });
7350
- }, o.timeoutMs || 6e5);
7612
+ finish(bad({ timedOut: true, error: "npm " + action + " \u8D85\u65F6\uFF08" + Math.round(timeoutMs / 1e3) + "s\uFF09\u5DF2\u7EC8\u6B62", output: out }));
7613
+ }, timeoutMs);
7351
7614
  INFLIGHT_NPM.add(handle);
7352
7615
  const onLine = (buf) => {
7353
7616
  for (const l of String(buf).split(/\r?\n/)) {
@@ -7365,10 +7628,11 @@ var require_install = __commonJS({
7365
7628
  child.stdout.on("data", onLine);
7366
7629
  child.stderr.on("data", onLine);
7367
7630
  child.on("error", (e) => {
7368
- finish({ ok: false, error: e.message, output: out });
7631
+ finish(bad({ error: e.message, output: out }));
7369
7632
  });
7370
7633
  child.on("exit", (code) => {
7371
- finish({ ok: code === 0, error: code === 0 ? null : "npm install \u9000\u51FA\u7801 " + code, output: out });
7634
+ const c = code === null ? -1 : code;
7635
+ finish({ ok: c === 0, error: c === 0 ? null : "npm " + action + " \u9000\u51FA\u7801 " + c, output: out, exitCode: c, timedOut: false, aborted: false });
7372
7636
  });
7373
7637
  });
7374
7638
  }
@@ -7417,9 +7681,6 @@ var require_install = __commonJS({
7417
7681
  PKG_NAME_RE,
7418
7682
  BAD_ARGV_CHAR_RE,
7419
7683
  WIN_DRIVE_ABS_RE,
7420
- fetchNpmLatest,
7421
- fetchGithubLatest,
7422
- fetchLatestVersion,
7423
7684
  runNpmInstall,
7424
7685
  waitPortHealthy,
7425
7686
  // 在途 npm 的记账/中止出口(关停路径经 platform/distribution 门面 re-export)
@@ -7435,7 +7696,9 @@ var require_distribution = __commonJS({
7435
7696
  "use strict";
7436
7697
  var policies = require_policies();
7437
7698
  var release = require_release();
7699
+ var registryConfig = require_registry_config();
7438
7700
  var registry = require_registry2();
7701
+ var versionCheck = require_version_check();
7439
7702
  var install = require_install();
7440
7703
  var { semverCompare, VERSION_RE } = require_version2();
7441
7704
  var DistributionManager = class {
@@ -7449,18 +7712,18 @@ var require_distribution = __commonJS({
7449
7712
  this.registryConfig = { mode: "auto", origins: [...this.defaultRegistries], manualOrigin: this.defaultRegistries[0] || "" };
7450
7713
  this.canary = opts.canary === true;
7451
7714
  this.selectedRegistry = null;
7452
- registry.loadRegistryConfig(this);
7715
+ registryConfig.loadRegistryConfig(this);
7453
7716
  this._contractLoadedAt = Date.now();
7454
7717
  }
7455
- // ---- 镜像源(registry.js)----
7718
+ // ---- 镜像源(registry-config.js 载入/落盘,registry.js 探测/选源)----
7456
7719
  _reloadContractIfStale() {
7457
- registry.reloadContractIfStale(this);
7720
+ registryConfig.reloadContractIfStale(this);
7458
7721
  }
7459
7722
  _loadRegistryConfig() {
7460
- registry.loadRegistryConfig(this);
7723
+ registryConfig.loadRegistryConfig(this);
7461
7724
  }
7462
7725
  _saveRegistryConfig() {
7463
- registry.saveRegistryConfig(this);
7726
+ registryConfig.saveRegistryConfig(this);
7464
7727
  }
7465
7728
  _platformTag() {
7466
7729
  return registry.platformTag();
@@ -7477,6 +7740,9 @@ var require_distribution = __commonJS({
7477
7740
  selectRegistry(force) {
7478
7741
  return registry.selectRegistry(this, force);
7479
7742
  }
7743
+ registryOrigin(force) {
7744
+ return registry.registryOrigin(this, force);
7745
+ }
7480
7746
  registryInfo() {
7481
7747
  return registry.registryInfo(this);
7482
7748
  }
@@ -7486,15 +7752,18 @@ var require_distribution = __commonJS({
7486
7752
  _inCanaryList() {
7487
7753
  return policies.isInCanaryList(this);
7488
7754
  }
7489
- // ---- 版本检查 / 安装 / 健康(install.js)----
7755
+ // ---- 版本检查 / 安装 / 健康(version-check.js + install.js)----
7756
+ // fetchNpmLatest 回 npm 通道的结构化结果(含给出该版本的 origin 与逐源原因)。
7757
+ // fetchVersionInfo 是**跨通道**的结构化口(npm|github,github 的 origin 恒 null);
7758
+ // fetchLatestVersion 只回版本字符串,只要版本号的调用方走它。
7490
7759
  fetchNpmLatest(pkg, opts) {
7491
- return install.fetchNpmLatest(this, pkg, opts);
7760
+ return versionCheck.fetchNpmLatest(this, pkg, opts);
7492
7761
  }
7493
- fetchGithubLatest(owner, repo) {
7494
- return install.fetchGithubLatest(owner, repo);
7762
+ fetchVersionInfo(pkg, channel, opts) {
7763
+ return versionCheck.fetchVersionInfo(this, pkg, channel, opts);
7495
7764
  }
7496
7765
  fetchLatestVersion(pkg, channel, opts) {
7497
- return install.fetchLatestVersion(this, pkg, channel, opts);
7766
+ return versionCheck.fetchLatestVersion(this, pkg, channel, opts);
7498
7767
  }
7499
7768
  runNpmInstall(opts) {
7500
7769
  return install.runNpmInstall(opts);
@@ -15194,6 +15463,7 @@ var require_pkg_cache = __commonJS({
15194
15463
  var fs2 = require("node:fs");
15195
15464
  var ex2 = require_exec();
15196
15465
  var { npxCacheDir, npxLauncher } = require_npx_forms();
15466
+ var registryRef = require_registry_ref();
15197
15467
  var HASH_DIR_RE = /^[0-9a-f]{8,}$/i;
15198
15468
  function pkgCacheDirs(pkg) {
15199
15469
  if (!pkg) return [];
@@ -15258,12 +15528,10 @@ var require_pkg_cache = __commonJS({
15258
15528
  if (!app || !app.pkg) return { ok: true };
15259
15529
  if (cachedPkgBin(app.pkg)) return { ok: true, cached: true };
15260
15530
  try {
15261
- const regOrigin = provider.dist ? await provider.dist.selectRegistry(false).catch(() => null) : null;
15531
+ const regOrigin = provider.dist ? await provider.dist.registryOrigin(false).catch(() => null) : null;
15262
15532
  const env = Object.assign({}, process.env);
15263
- if (regOrigin) {
15264
- env.npm_config_registry = regOrigin;
15265
- env.NPM_CONFIG_REGISTRY = regOrigin;
15266
- }
15533
+ const rp = registryRef.registryEnvPair(regOrigin);
15534
+ if (rp.ok) Object.assign(env, rp.env);
15267
15535
  const launcher = npxLauncher();
15268
15536
  await ex2.runOutAsync(launcher.program, [...launcher.args, "--yes", app.pkg, "--help"], { env, timeoutMs: 12e4 });
15269
15537
  return { ok: !!cachedPkgBin(app.pkg) };
@@ -15291,6 +15559,7 @@ var require_probe5 = __commonJS({
15291
15559
  var { cachedPkgBin, ensurePkgCached } = require_pkg_cache();
15292
15560
  var stateRoot2 = require_state_root();
15293
15561
  var { Rotator } = require_log();
15562
+ var registryRef = require_registry_ref();
15294
15563
  var INSTANCE_LOG_MAX_BYTES = 2 * 1024 * 1024;
15295
15564
  async function spawnInstance(provider, inst) {
15296
15565
  const app = provider.app;
@@ -15360,10 +15629,9 @@ var require_probe5 = __commonJS({
15360
15629
  envVars[k] = String(v).replace("{{key}}", inst.key).replace("{{port}}", String(port));
15361
15630
  }
15362
15631
  }
15363
- if (launch.registry) {
15364
- envVars.npm_config_registry = launch.registry;
15365
- envVars.NPM_CONFIG_REGISTRY = launch.registry;
15366
- }
15632
+ const rpReg = registryRef.registryEnvPair(launch.registry);
15633
+ if (rpReg.ok) Object.assign(envVars, rpReg.env);
15634
+ else if (launch.registry && provider.logger) provider.logger.warn("[proxy-instance] \u5951\u7EA6 registry \u975E\u6CD5\uFF08" + rpReg.violation + "\uFF09\uFF0C\u6539\u7528 npx \u9ED8\u8BA4\u6E90");
15367
15635
  const logFilter = /error|streaming|idle|timeout|ECONN|abort|socket|finish|truncat/i;
15368
15636
  const baseDir = provider.stateDir || stateRoot2.supervisorDir();
15369
15637
  let logWriter = null;
@@ -15955,7 +16223,7 @@ var require_proxy = __commonJS({
15955
16223
  }
15956
16224
  /** 解析启动命令(缓存优先 + fallback npx):拼装委托 command.js;凭证剔除留在本层(纪律)。 */
15957
16225
  async _resolveLaunchCommand(app, port, key) {
15958
- const registry = this.dist ? await this.dist.selectRegistry(false).catch(() => null) : null;
16226
+ const registry = this.dist ? await this.dist.registryOrigin(false).catch(() => null) : null;
15959
16227
  const cachedBin = this._cachedPkgBin(app.pkg);
15960
16228
  const launch = buildCommand({ app, port, cachedBin, registry, launcher: npxLauncher(), execPath: process.execPath });
15961
16229
  if (!launch || !launch.ok) return launch || { ok: false, error: "\u547D\u4EE4\u62FC\u88C5\u5931\u8D25" };
@@ -17590,12 +17858,18 @@ var require_apps_registry = __commonJS({
17590
17858
  continue;
17591
17859
  }
17592
17860
  let ver = null;
17861
+ let why = "\u5206\u53D1\u670D\u52A1\u4E0D\u53EF\u7528";
17593
17862
  try {
17594
- if (dist) ver = await dist.fetchNpmLatest(a.registry);
17595
- } catch {
17863
+ if (dist) {
17864
+ const r = await dist.fetchNpmLatest(a.registry);
17865
+ ver = r && r.ok ? r.version : null;
17866
+ why = r && r.ok ? null : r && r.error || "\u672A\u53D6\u5230\u7248\u672C";
17867
+ }
17868
+ } catch (e) {
17869
+ why = e && e.message || String(e);
17596
17870
  }
17597
17871
  const prev = c.latest || null;
17598
- cache[a.id] = { pkg: a.registry, latest: ver, checkedAt: Date.now(), error: ver ? null : "query failed" };
17872
+ cache[a.id] = { pkg: a.registry, latest: ver, checkedAt: Date.now(), error: ver ? null : why || "query failed" };
17599
17873
  if (ver && prev && ver !== prev && events) events.append("proxy_update_available", { appId: a.id, pkg: a.registry, from: prev, to: ver });
17600
17874
  results[a.id] = ver;
17601
17875
  }
@@ -19970,8 +20244,7 @@ var require_dsh_install = __commonJS({
19970
20244
  function createDshInstall(deps) {
19971
20245
  const { store, dist, tasks, logger, instancesRoot } = deps;
19972
20246
  const save = () => store.save();
19973
- let _latestDshVer = null;
19974
- let _latestDshVerAt = 0;
20247
+ let _latestDsh = null;
19975
20248
  function installTimeoutWatchdog(inst, task) {
19976
20249
  try {
19977
20250
  if (inst.state && inst.state.phase === "INSTALLING") {
@@ -20036,49 +20309,38 @@ var require_dsh_install = __commonJS({
20036
20309
  } catch {
20037
20310
  }
20038
20311
  }
20039
- const env = Object.assign({}, process.env);
20040
- let reg = null;
20041
- if (dist) {
20042
- try {
20043
- reg = await dist.selectRegistry(false);
20044
- if (reg) {
20045
- env.npm_config_registry = reg;
20046
- env.NPM_CONFIG_REGISTRY = reg;
20047
- }
20048
- } catch (e) {
20049
- logger.warn && logger.warn("sandbox registry select failed: " + e.message);
20050
- }
20051
- }
20052
- const latestVer = await latestDshVersion();
20053
- pushLog("\u5B89\u88C5\u76EE\u6807\u7248\u672C\uFF1A" + (latestVer || "latest tag"));
20054
- if (!latestVer) {
20312
+ if (!dist) {
20055
20313
  inst.state.installOk = false;
20056
- inst.state.installError = "\u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C";
20314
+ inst.state.installError = "dist \u5206\u53D1\u670D\u52A1\u4E0D\u53EF\u7528";
20057
20315
  save();
20058
20316
  if (task) {
20059
20317
  try {
20060
- tasks.fail(task.id, "\u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C");
20318
+ tasks.fail(task.id, "dist \u5206\u53D1\u670D\u52A1\u4E0D\u53EF\u7528");
20061
20319
  } catch {
20062
20320
  }
20063
20321
  }
20064
- return { ok: false, error: "\u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C" };
20322
+ return { ok: false, error: "dist \u5206\u53D1\u670D\u52A1\u4E0D\u53EF\u7528" };
20065
20323
  }
20066
- if (!dist) {
20324
+ const pick = await latestDsh();
20325
+ pushLog("\u5B89\u88C5\u76EE\u6807\u7248\u672C\uFF1A" + (pick.version || "\u672A\u77E5") + (pick.origin ? "\uFF08\u6E90 " + pick.origin + "\uFF09" : ""));
20326
+ if (!pick.version) {
20327
+ const why = "\u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C\uFF1A" + (pick.error || "\u672A\u77E5\u539F\u56E0");
20067
20328
  inst.state.installOk = false;
20068
- inst.state.installError = "dist \u5206\u53D1\u670D\u52A1\u4E0D\u53EF\u7528";
20329
+ inst.state.installError = why;
20069
20330
  save();
20070
20331
  if (task) {
20071
20332
  try {
20072
- tasks.fail(task.id, "dist \u5206\u53D1\u670D\u52A1\u4E0D\u53EF\u7528");
20333
+ tasks.fail(task.id, why);
20073
20334
  } catch {
20074
20335
  }
20075
20336
  }
20076
- return { ok: false, error: "dist \u5206\u53D1\u670D\u52A1\u4E0D\u53EF\u7528" };
20337
+ return { ok: false, error: why };
20077
20338
  }
20339
+ const latestVer = pick.version;
20078
20340
  const watchdog = setTimeout(() => installTimeoutWatchdog(inst, task), 10 * 60 * 1e3);
20079
20341
  let res;
20080
20342
  try {
20081
- res = await dist.runNpmInstall({ pkg: "@deepseek-ai/dsh", version: latestVer, prefix: installDir, registry: reg, onLine: pushLog });
20343
+ res = await dist.runNpmInstall({ pkg: "@deepseek-ai/dsh", version: latestVer, prefix: installDir, registry: pick.origin, onLine: pushLog });
20082
20344
  } finally {
20083
20345
  clearTimeout(watchdog);
20084
20346
  }
@@ -20124,18 +20386,24 @@ var require_dsh_install = __commonJS({
20124
20386
  return null;
20125
20387
  }
20126
20388
  }
20127
- async function latestDshVersion() {
20128
- if (_latestDshVer && Date.now() - _latestDshVerAt < 3e4) return _latestDshVer;
20129
- let v = null;
20130
- try {
20131
- if (dist) v = await dist.fetchNpmLatest("@deepseek-ai/dsh");
20132
- } catch {
20389
+ async function latestDsh() {
20390
+ if (_latestDsh && Date.now() - _latestDsh.at < 3e4) return _latestDsh;
20391
+ let r = { ok: false, version: null, origin: null, attempts: [], error: "dist \u5206\u53D1\u670D\u52A1\u4E0D\u53EF\u7528" };
20392
+ if (dist) {
20393
+ try {
20394
+ r = await dist.fetchNpmLatest("@deepseek-ai/dsh");
20395
+ } catch (e) {
20396
+ r = { ok: false, version: null, origin: null, attempts: [], error: e && e.message || String(e) };
20397
+ }
20133
20398
  }
20134
- _latestDshVer = v;
20135
- _latestDshVerAt = Date.now();
20136
- return v;
20399
+ if (r.ok && r.version) _latestDsh = Object.assign({ at: Date.now() }, r);
20400
+ return r;
20137
20401
  }
20138
- return { installSandbox, readInstalledVersion, latestDshVersion };
20402
+ async function latestDshVersion() {
20403
+ const r = await latestDsh();
20404
+ return r.version;
20405
+ }
20406
+ return { installSandbox, readInstalledVersion, latestDsh, latestDshVersion };
20139
20407
  }
20140
20408
  module2.exports = { createDshInstall };
20141
20409
  }
@@ -20183,6 +20451,9 @@ var require_upgrade = __commonJS({
20183
20451
  function readInstalledVersion(inst) {
20184
20452
  return install.readInstalledVersion(inst);
20185
20453
  }
20454
+ async function latestDsh() {
20455
+ return install.latestDsh();
20456
+ }
20186
20457
  async function latestDshVersion() {
20187
20458
  return install.latestDshVersion();
20188
20459
  }
@@ -20213,8 +20484,9 @@ var require_upgrade = __commonJS({
20213
20484
  let latest = cached && cached.latest || null;
20214
20485
  if (!latest || !cached || Date.now() - cached.checkedAt > _updTTL) {
20215
20486
  try {
20216
- latest = await dist.fetchNpmLatest("@deepseek-ai/dsh");
20217
- _updCache[id] = { latest, checkedAt: Date.now(), error: latest ? null : "\u67E5\u8BE2\u5931\u8D25" };
20487
+ const pick = await dist.fetchNpmLatest("@deepseek-ai/dsh");
20488
+ latest = pick.ok ? pick.version : null;
20489
+ _updCache[id] = { latest, checkedAt: Date.now(), error: pick.ok ? null : pick.error || "\u67E5\u8BE2\u5931\u8D25" };
20218
20490
  } catch (e) {
20219
20491
  latest = null;
20220
20492
  _updCache[id] = { latest: null, checkedAt: Date.now(), error: e.message };
@@ -20241,16 +20513,6 @@ var require_upgrade = __commonJS({
20241
20513
  _updJobs[id] = nj;
20242
20514
  (async () => {
20243
20515
  const installDir = sandbox.installDir(instancesRoot, inst);
20244
- const env = Object.assign({}, process.env);
20245
- let reg = null;
20246
- try {
20247
- reg = await dist.selectRegistry(false);
20248
- if (reg) {
20249
- env.npm_config_registry = reg;
20250
- env.NPM_CONFIG_REGISTRY = reg;
20251
- }
20252
- } catch {
20253
- }
20254
20516
  let wasRunning = false;
20255
20517
  try {
20256
20518
  wasRunning = lifecycle.probe(inst).running;
@@ -20277,12 +20539,15 @@ var require_upgrade = __commonJS({
20277
20539
  const s = tasks.step(task.id, "\u5B89\u88C5\u6700\u65B0\u7248");
20278
20540
  tasks.stepState(task.id, tasks.get(task.id).steps.indexOf(s), "running");
20279
20541
  }
20280
- const targetVer = await latestDshVersion();
20281
- if (task) tasks.log(task.id, "\u76EE\u6807\u7248\u672C\uFF1A" + (targetVer || "latest tag"));
20542
+ const pick = await latestDsh();
20543
+ const targetVer = pick.version;
20544
+ const reg = pick.origin;
20545
+ if (task) tasks.log(task.id, "\u76EE\u6807\u7248\u672C\uFF1A" + (targetVer || "\u672A\u77E5") + (reg ? "\uFF08\u6E90 " + reg + "\uFF09" : ""));
20282
20546
  if (!targetVer) {
20547
+ const why = "\u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C\uFF1A" + (pick.error || "\u672A\u77E5\u539F\u56E0");
20283
20548
  nj.errors++;
20284
- nj.error = "\u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C";
20285
- if (task) tasks.log(task.id, "\u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C");
20549
+ nj.error = why;
20550
+ if (task) tasks.log(task.id, why);
20286
20551
  } else {
20287
20552
  if (!dist) {
20288
20553
  nj.errors++;
@@ -21048,6 +21313,7 @@ var require_market_sources = __commonJS({
21048
21313
  "src/domains/plugin/market-sources.js"(exports2, module2) {
21049
21314
  "use strict";
21050
21315
  var { getJson, getText } = require_market_net();
21316
+ var ref = require_registry_ref();
21051
21317
  var RAW_MIRRORS = ["https://gh-proxy.com/", "https://ghproxy.net/"];
21052
21318
  async function rawGet(pathPart, isJson, timeoutMs = 15e3) {
21053
21319
  const direct = "https://raw.githubusercontent.com/" + pathPart;
@@ -21061,12 +21327,10 @@ var require_market_sources = __commonJS({
21061
21327
  throw new Error("raw fetch failed for " + pathPart);
21062
21328
  }
21063
21329
  async function fetchLatest(origin, name) {
21064
- try {
21065
- const base = String(origin || "").replace(/\/+$/, "");
21066
- return await getJson(base + "/" + encodeURIComponent(name) + "/latest", 8e3);
21067
- } catch {
21068
- return null;
21069
- }
21330
+ const url = ref.registryUrl(origin, ref.registryPackagePath(name), "latest");
21331
+ if (!url) return null;
21332
+ const r = await ref.fetchRegistry(url, { timeoutMs: 8e3, expect: "json" });
21333
+ return r.ok ? r.json : null;
21070
21334
  }
21071
21335
  async function repoPkg(fullName) {
21072
21336
  for (const branch of ["master", "main"]) {
@@ -21381,16 +21645,16 @@ var require_market = __commonJS({
21381
21645
  }
21382
21646
  return out;
21383
21647
  }
21384
- /** npm 镜像源 origin(经 dist 统一选择;dist 不可达降级官方源)。 */
21648
+ /** npm 镜像源基址(经 dist 统一选择;dist 不可达降级官方源)。尾斜杠归一交给 registry-ref。 */
21385
21649
  async _npmOrigin() {
21386
21650
  let origin = null;
21387
21651
  if (this.dist) {
21388
21652
  try {
21389
- origin = await this.dist.selectRegistry(false);
21653
+ origin = await this.dist.registryOrigin(false);
21390
21654
  } catch {
21391
21655
  }
21392
21656
  }
21393
- return (origin || REGISTRY).replace(/\/+$/, "");
21657
+ return origin || REGISTRY;
21394
21658
  }
21395
21659
  /** npm 最新版元数据查询(镜像源选择见 _npmOrigin)。 */
21396
21660
  async safeFetchLatest(name) {
@@ -21840,13 +22104,14 @@ var require_cli = __commonJS({
21840
22104
  "use strict";
21841
22105
  var spawn = require_spawn();
21842
22106
  var procOS = require_process();
22107
+ var registryRef = require_registry_ref();
21843
22108
  var { assertSafeCliArgs, cliArgv } = require_policies2();
21844
22109
  var CLI_TIMEOUT_MS = 18e4;
21845
22110
  var DEFAULT_REGISTRY = "https://registry.npmjs.org";
21846
22111
  async function registryOrigin(dist) {
21847
22112
  if (dist) {
21848
22113
  try {
21849
- return dist.selectRegistry(false);
22114
+ return await dist.registryOrigin(false);
21850
22115
  } catch {
21851
22116
  }
21852
22117
  }
@@ -21868,12 +22133,10 @@ var require_cli = __commonJS({
21868
22133
  }
21869
22134
  };
21870
22135
  Promise.resolve().then(() => registryOrigin2()).then((regRaw) => {
21871
- const reg = regRaw || null;
22136
+ const rp = registryRef.registryEnvPair(regRaw);
21872
22137
  const envBase = Object.assign({}, process.env, target.env);
21873
- if (reg) {
21874
- envBase.npm_config_registry = reg;
21875
- envBase.NPM_CONFIG_REGISTRY = reg;
21876
- } else if (logger && logger.warn) logger.warn("plugin CLI: \u65E0\u53EF\u7528\u7684 registry \u955C\u50CF\uFF0C\u56DE\u9000 pnpm \u9ED8\u8BA4\uFF08npmjs.org\uFF09");
22138
+ if (rp.ok) Object.assign(envBase, rp.env);
22139
+ else if (logger && logger.warn) logger.warn("plugin CLI: \u65E0\u53EF\u7528\u7684 registry \u955C\u50CF\uFF08" + rp.violation + "\uFF09\uFF0C\u56DE\u9000 pnpm \u9ED8\u8BA4\uFF08npmjs.org\uFF09");
21877
22140
  const env = envBase;
21878
22141
  let child;
21879
22142
  try {
@@ -22417,6 +22680,23 @@ var require_updater = __commonJS({
22417
22680
  "src/domains/plugin/updater.js"(exports2, module2) {
22418
22681
  "use strict";
22419
22682
  var { specType, isUpdateAvailable } = require_policies2();
22683
+ async function latestCached(ctx, name, force) {
22684
+ const c = ctx._updCache[name];
22685
+ if (c && !force && Date.now() - c.at < ctx._updTTL) return { latest: c.latest, error: null };
22686
+ let latest = null;
22687
+ let error = "\u5206\u53D1\u670D\u52A1\u4E0D\u53EF\u7528";
22688
+ if (ctx.dist) {
22689
+ try {
22690
+ const r = await ctx.dist.fetchNpmLatest(name);
22691
+ latest = r && r.ok ? r.version : null;
22692
+ error = r && r.ok ? null : r && r.error || "\u672A\u53D6\u5230\u7248\u672C";
22693
+ } catch (e) {
22694
+ error = e && e.message || String(e);
22695
+ }
22696
+ }
22697
+ if (latest !== null) ctx._updCache[name] = { latest, at: Date.now() };
22698
+ return { latest, error };
22699
+ }
22420
22700
  async function checkUpdates(ctx, force) {
22421
22701
  const targets = [ctx._nativeTarget(), ...ctx._allSandboxTargets()];
22422
22702
  const meta = /* @__PURE__ */ new Map();
@@ -22425,17 +22705,7 @@ var require_updater = __commonJS({
22425
22705
  if (meta.has(p.name)) continue;
22426
22706
  const st = specType(p.source);
22427
22707
  let latest = null;
22428
- const c = ctx._updCache[p.name];
22429
- if (c && !force && Date.now() - c.at < ctx._updTTL) latest = c.latest;
22430
- else {
22431
- if (st === "npm" && ctx.dist) {
22432
- try {
22433
- latest = await ctx.dist.fetchNpmLatest(p.name);
22434
- } catch {
22435
- }
22436
- }
22437
- if (latest !== null) ctx._updCache[p.name] = { latest, at: Date.now() };
22438
- }
22708
+ if (st === "npm" && ctx.dist) latest = (await latestCached(ctx, p.name, force)).latest;
22439
22709
  meta.set(p.name, { specType: st, latest });
22440
22710
  }
22441
22711
  }
@@ -22468,19 +22738,9 @@ var require_updater = __commonJS({
22468
22738
  const desc = targetStr === "all" ? "\u4EFB\u4F55\u76EE\u6807" : "\u76EE\u6807\u300C" + (targetStr || "native") + "\u300D";
22469
22739
  return { ok: false, error: desc + " \u672A\u5B89\u88C5\u63D2\u4EF6 " + name };
22470
22740
  }
22471
- let latest = null;
22472
- const c = ctx._updCache[name];
22473
- if (c && Date.now() - c.at < ctx._updTTL) latest = c.latest;
22474
- else {
22475
- if (ctx.dist) {
22476
- try {
22477
- latest = await ctx.dist.fetchNpmLatest(name);
22478
- } catch {
22479
- }
22480
- }
22481
- if (latest !== null) ctx._updCache[name] = { latest, at: Date.now() };
22482
- }
22483
- if (!latest) return { ok: false, error: "\u65E0\u6CD5\u83B7\u53D6 " + name + " \u7684\u6700\u65B0\u7248\u672C\uFF08registry \u4E0D\u53EF\u8FBE\uFF09\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5" };
22741
+ const pick = await latestCached(ctx, name, false);
22742
+ const latest = pick.latest;
22743
+ if (!latest) return { ok: false, error: "\u65E0\u6CD5\u83B7\u53D6 " + name + " \u7684\u6700\u65B0\u7248\u672C\uFF08" + (pick.error || "registry \u4E0D\u53EF\u8FBE") + "\uFF09\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5" };
22484
22744
  const job = ctx.jobs.createJob("update", name, targetStr || "native", targets);
22485
22745
  if (ctx.events) ctx.events.append("plugin_update_started", { name, jobId: job.id, target: job.target, targets: targets.map((t) => t.name) });
22486
22746
  let idx = 0;
@@ -23407,33 +23667,39 @@ var require_npm = __commonJS({
23407
23667
  async function latestVersion(host2) {
23408
23668
  if (!host2.dist || !host2.config.packageName) throw new Error("\u5206\u53D1\u670D\u52A1\u672A\u521D\u59CB\u5316\uFF0C\u65E0\u6CD5\u67E5\u8BE2\u6700\u65B0\u7248\u672C");
23409
23669
  const channel = host2.config.releaseChannel || "npm";
23410
- return host2.dist.fetchLatestVersion(host2.config.packageName, channel);
23670
+ return host2.dist.fetchVersionInfo(host2.config.packageName, channel);
23411
23671
  }
23412
23672
  async function selectRegistry(host2) {
23413
23673
  if (!host2.dist) return null;
23414
23674
  try {
23415
- return await host2.dist.selectRegistry(true);
23675
+ return await host2.dist.registryOrigin(true);
23416
23676
  } catch {
23417
23677
  return null;
23418
23678
  }
23419
23679
  }
23420
- function runInstall(host2, version, registry) {
23421
- if (!host2.dist) return Promise.resolve({ ok: false, error: "dist \u5206\u53D1\u670D\u52A1\u4E0D\u53EF\u7528\uFF0C\u65E0\u6CD5\u5B89\u88C5", output: [] });
23422
- const pkg = host2.config.packageName || "@deepseek-ai/dsh";
23423
- const tpl = host2.config.installCommandTemplate;
23680
+ function runNpm(host2, opts) {
23681
+ const a = opts && opts.action || "install";
23682
+ const verb = a === "uninstall" ? "\u5378\u8F7D" : "\u5B89\u88C5";
23683
+ if (!host2.dist) return Promise.resolve({ ok: false, error: "dist \u5206\u53D1\u670D\u52A1\u4E0D\u53EF\u7528\uFF0C\u65E0\u6CD5" + verb, output: [] });
23684
+ const tpl = a === "install" ? host2.config.installCommandTemplate : null;
23424
23685
  return host2.dist.runNpmInstall({
23425
- pkg,
23426
- version,
23427
- registry,
23686
+ action: a,
23687
+ pkg: host2.config.packageName || "@deepseek-ai/dsh",
23688
+ version: opts && opts.version,
23689
+ // 前缀单源:装与卸必须落在同一个全局前缀,否则「卸载成功」而包还在原地。
23690
+ prefix: host2.npmRoot || null,
23691
+ registry: opts && opts.registry,
23692
+ // 只在显式注入过 npm 形态时接管启动形态;生产留空,由执行器按运行期契约解析一次。
23693
+ launcher: host2._npmBin ? npmLaunch(host2) : null,
23428
23694
  commandTemplate: Array.isArray(tpl) && tpl.length ? tpl : null,
23429
- timeoutMs: host2.config.upgradeTimeoutMs || 6e5,
23695
+ timeoutMs: a === "uninstall" ? host2.config.uninstallTimeoutMs : host2.config.upgradeTimeoutMs,
23430
23696
  onLine: (l) => {
23431
23697
  host2._appendUpgradeLog(l);
23432
23698
  if (host2.installing) host2._appendInstallLog(l);
23433
23699
  }
23434
23700
  });
23435
23701
  }
23436
- module2.exports = { npmLaunch, resolveNpmRoot, checkEnvironment, latestVersion, selectRegistry, runInstall };
23702
+ module2.exports = { npmLaunch, resolveNpmRoot, checkEnvironment, latestVersion, selectRegistry, runNpm };
23437
23703
  }
23438
23704
  });
23439
23705
 
@@ -23442,9 +23708,6 @@ var require_ops4 = __commonJS({
23442
23708
  "src/app/native/ops.js"(exports2, module2) {
23443
23709
  "use strict";
23444
23710
  var fs2 = require("node:fs");
23445
- var spawnOS = require_spawn();
23446
- var { killTree } = require_process();
23447
- var { npmLaunch } = require_npm();
23448
23711
  var policies = require_policies3();
23449
23712
  var PKG_DEFAULT = "@deepseek-ai/dsh";
23450
23713
  function status(host2) {
@@ -23476,13 +23739,15 @@ var require_ops4 = __commonJS({
23476
23739
  host2.lastCheck = { at: (/* @__PURE__ */ new Date()).toISOString(), installed: null, latest: null, updateAvailable: false, note: "not-installed" };
23477
23740
  return policies.versionInfo(host2, installed);
23478
23741
  }
23479
- const latest = await host2._latestVersion();
23742
+ const info = await host2._latestVersion();
23743
+ const latest = info.ok ? info.version : null;
23480
23744
  host2.lastCheck = {
23481
23745
  at: (/* @__PURE__ */ new Date()).toISOString(),
23482
23746
  installed,
23483
23747
  latest,
23484
23748
  updateAvailable: latest ? policies.isNewer(latest, installed) : false,
23485
- error: latest ? null : "\u955C\u50CF\u6E90\u4E0D\u53EF\u8FBE\u6216\u672A\u67E5\u8BE2\u5230\u7248\u672C"
23749
+ // 拒因指名到源:「镜像源全挂」与「确实没有更新」显示成两句话是这块的全部意义。
23750
+ error: latest ? null : info.error || "\u955C\u50CF\u6E90\u4E0D\u53EF\u8FBE\u6216\u672A\u67E5\u8BE2\u5230\u7248\u672C"
23486
23751
  };
23487
23752
  if (host2.events) host2.events.append("version_checked", { installed, latest, updateAvailable: host2.lastCheck.updateAvailable });
23488
23753
  } catch (e) {
@@ -23509,20 +23774,24 @@ var require_ops4 = __commonJS({
23509
23774
  if (!env.ok) return { ok: false, error: "\u73AF\u5883\u68C0\u67E5\u5931\u8D25: " + env.errors.join("; ") };
23510
23775
  task = beginTask(host2, "install", { to: version || null, createdBy: "user" });
23511
23776
  let target = version;
23777
+ let registry = null;
23512
23778
  if (!target) {
23513
- target = await host2._latestVersion().catch(() => null);
23514
- if (!target) {
23779
+ const info = await host2._latestVersion().catch(() => null);
23780
+ if (!info || !info.ok || !info.version) {
23515
23781
  host2.installing = null;
23516
- if (task) host2.tasks.fail(task.id, "\u65E0\u6CD5\u4ECE\u955C\u50CF\u6E90\u83B7\u53D6\u6700\u65B0\u7248\u672C");
23517
- return { ok: false, error: "\u65E0\u6CD5\u4ECE\u955C\u50CF\u6E90\u83B7\u53D6\u6700\u65B0\u7248\u672C" };
23782
+ const why = info && info.error || "\u65E0\u6CD5\u4ECE\u955C\u50CF\u6E90\u83B7\u53D6\u6700\u65B0\u7248\u672C";
23783
+ if (task) host2.tasks.fail(task.id, why);
23784
+ return { ok: false, error: why };
23518
23785
  }
23786
+ target = info.version;
23787
+ registry = info.origin;
23519
23788
  }
23520
- const registry = await host2._selectRegistry();
23789
+ if (!registry) registry = await host2._selectRegistry();
23521
23790
  const pkg = host2.config.packageName || PKG_DEFAULT;
23522
23791
  if (task) host2.tasks.log(task.id, "\u5B89\u88C5 " + pkg + "@" + target + (registry ? " via " + registry : ""));
23523
23792
  if (host2.events) host2.events.append("native_install_started", { version: target, registry });
23524
23793
  if (host2.logger.info) host2.logger.info("native install: " + pkg + "@" + target + (registry ? " via " + registry : ""));
23525
- const res = await host2._runInstall(target, registry);
23794
+ const res = await host2._runNpm({ action: "install", version: target, registry });
23526
23795
  if (!res.ok) {
23527
23796
  host2.installing = null;
23528
23797
  host2.lastInstall = { ok: false, version: null, error: res.error, at: (/* @__PURE__ */ new Date()).toISOString(), log: host2.installLog.slice(-8) };
@@ -23614,46 +23883,9 @@ var require_ops4 = __commonJS({
23614
23883
  host2.tasks.start(task.id);
23615
23884
  host2.tasks.log(task.id, "\u5378\u8F7D " + (host2.config.packageName || PKG_DEFAULT));
23616
23885
  }
23617
- const pkg = host2.config.packageName || PKG_DEFAULT;
23618
- const uninstallArgs = ["uninstall", "-g"];
23619
- if (host2.npmRoot) uninstallArgs.push("--prefix", host2.npmRoot);
23620
- uninstallArgs.push(pkg);
23621
- const UNINSTALL_TIMEOUT_MS = typeof host2.config.uninstallTimeoutMs === "number" && host2.config.uninstallTimeoutMs > 0 ? host2.config.uninstallTimeoutMs : 15 * 60 * 1e3;
23622
- let uninstallTimedOut = false;
23623
- const exitCode = await new Promise((resolve) => {
23624
- let child;
23625
- try {
23626
- const np = npmLaunch(host2);
23627
- child = spawnOS.piped(np.program, np.args.concat(uninstallArgs));
23628
- } catch (e) {
23629
- return resolve(-1);
23630
- }
23631
- child.stdout.resume();
23632
- child.stderr.resume();
23633
- let done = false;
23634
- const finish = (code) => {
23635
- if (done) return;
23636
- done = true;
23637
- clearTimeout(timer);
23638
- resolve(code);
23639
- };
23640
- const timer = setTimeout(() => {
23641
- uninstallTimedOut = true;
23642
- host2.logger.warn && host2.logger.warn("npm uninstall \u8D85\u65F6\uFF08" + Math.round(UNINSTALL_TIMEOUT_MS / 1e3) + "s\uFF09\uFF0C\u7EC8\u6B62\u8FDB\u7A0B\u6811");
23643
- try {
23644
- killTree(child.pid, "SIGKILL", () => finish(-1));
23645
- } catch (e) {
23646
- try {
23647
- child.kill("SIGKILL");
23648
- } catch (e2) {
23649
- }
23650
- finish(-1);
23651
- }
23652
- }, UNINSTALL_TIMEOUT_MS);
23653
- if (timer.unref) timer.unref();
23654
- child.on("error", () => finish(-1));
23655
- child.on("exit", (code) => finish(code == null ? -1 : code));
23656
- });
23886
+ const res = await host2._runNpm({ action: "uninstall" });
23887
+ const exitCode = res.ok === true ? 0 : Number.isFinite(res.exitCode) ? res.exitCode : -1;
23888
+ const timedOut = res.timedOut === true || res.aborted === true;
23657
23889
  if (exitCode === 0 && m) {
23658
23890
  if (m.packageDir) rm(m.packageDir);
23659
23891
  if (m.binPath) rm(m.binPath);
@@ -23664,17 +23896,17 @@ var require_ops4 = __commonJS({
23664
23896
  } else {
23665
23897
  host2.logger.warn && host2.logger.warn("npm uninstall exit " + exitCode + "\uFF0C\u4FDD\u7559 manifest \u4EE5\u4FBF\u91CD\u8BD5\uFF08\u6570\u636E\u8DEF\u5F84\u672A\u5220\uFF09");
23666
23898
  }
23667
- const uninstallError = exitCode === 0 ? null : uninstallTimedOut ? "npm uninstall \u8D85\u65F6\uFF08" + Math.round(UNINSTALL_TIMEOUT_MS / 1e3) + "s\uFF09\u5DF2\u7EC8\u6B62\uFF0C\u5305\u53EF\u80FD\u4ECD\u5728\uFF0C\u53EF\u91CD\u8BD5" : "npm uninstall \u9000\u51FA\u7801 " + exitCode;
23668
- host2.lastUninstall = { ok: exitCode === 0, removed, error: uninstallError, timedOut: uninstallTimedOut, at: (/* @__PURE__ */ new Date()).toISOString() };
23899
+ const uninstallError = exitCode === 0 ? null : timedOut ? (res.error || "npm uninstall \u8D85\u65F6\u5DF2\u7EC8\u6B62") + "\uFF0C\u5305\u53EF\u80FD\u4ECD\u5728\uFF0C\u53EF\u91CD\u8BD5" : "npm uninstall \u9000\u51FA\u7801 " + exitCode;
23900
+ host2.lastUninstall = { ok: exitCode === 0, removed, error: uninstallError, timedOut, at: (/* @__PURE__ */ new Date()).toISOString() };
23669
23901
  if (host2.events) host2.events.append("native_uninstalled", { removed });
23670
23902
  if (host2.logger.info) host2.logger.info("native uninstalled, removed " + removed.length + " paths");
23671
23903
  if (task) {
23672
23904
  if (exitCode === 0) {
23673
23905
  host2.tasks.log(task.id, "\u5378\u8F7D\u5B8C\u6210\uFF0C\u6E05\u7406 " + removed.length + " \u4E2A\u8DEF\u5F84");
23674
23906
  host2.tasks.succeed(task.id);
23675
- } else host2.tasks.fail(task.id, "npm uninstall \u9000\u51FA\u7801 " + exitCode);
23907
+ } else host2.tasks.fail(task.id, uninstallError || "npm uninstall \u9000\u51FA\u7801 " + exitCode);
23676
23908
  }
23677
- return { ok: exitCode === 0, removed, timedOut: uninstallTimedOut, error: uninstallError };
23909
+ return { ok: exitCode === 0, removed, timedOut, error: uninstallError };
23678
23910
  } finally {
23679
23911
  host2.uninstalling = null;
23680
23912
  }
@@ -23723,12 +23955,12 @@ var require_upgrade2 = __commonJS({
23723
23955
  return task;
23724
23956
  }
23725
23957
  async function resolveTarget(host2, requestedVersion, task) {
23726
- if (requestedVersion) return requestedVersion;
23958
+ if (requestedVersion) return { version: requestedVersion, origin: null };
23727
23959
  taskLog(host2, task, "\u67E5\u8BE2\u6700\u65B0\u7248\u672C\u2026");
23728
23960
  log(host2, "\u67E5\u8BE2\u6700\u65B0\u7248\u672C\u2026");
23729
- const target = await host2._latestVersion();
23730
- if (!target) throw new Error("\u65E0\u6CD5\u4ECE\u4EFB\u4F55 registry \u83B7\u53D6\u6700\u65B0\u7248\u672C");
23731
- return target;
23961
+ const info = await host2._latestVersion();
23962
+ if (!info || !info.ok || !info.version) throw new Error(info && info.error || "\u65E0\u6CD5\u4ECE\u4EFB\u4F55 registry \u83B7\u53D6\u6700\u65B0\u7248\u672C");
23963
+ return { version: info.version, origin: info.origin };
23732
23964
  }
23733
23965
  async function stopForUpgrade(host2, task) {
23734
23966
  if (!(host2.hooks.isDshActive && host2.hooks.isDshActive())) return;
@@ -23741,10 +23973,10 @@ var require_upgrade2 = __commonJS({
23741
23973
  }
23742
23974
  if (host2.hooks.stopForUpgrade) await host2.hooks.stopForUpgrade();
23743
23975
  }
23744
- async function installTarget(host2, oldV, target, task) {
23745
- const registry = await host2._selectRegistry();
23976
+ async function installTarget(host2, oldV, target, origin, task) {
23977
+ const registry = origin || await host2._selectRegistry();
23746
23978
  markStep(host2, task, "\u5B89\u88C5 " + target);
23747
- const res = await host2._runInstall(target, registry);
23979
+ const res = await host2._runNpm({ action: "install", version: target, registry });
23748
23980
  if (!res.ok) throw new Error(res.error || "install failed");
23749
23981
  const newV = host2.installedVersion();
23750
23982
  if (newV !== target) throw new Error("\u5B89\u88C5\u540E\u7248\u672C\u6821\u9A8C\u5931\u8D25\uFF1A\u671F\u671B " + target + "\uFF0C\u5B9E\u9645 " + newV);
@@ -23840,7 +24072,7 @@ var require_upgrade2 = __commonJS({
23840
24072
  }
23841
24073
  tlog("\u81EA\u52A8\u56DE\u6EDA\u5230 " + oldVersion + "\u2026");
23842
24074
  const registry = await host2._selectRegistry();
23843
- const res = await host2._runInstall(oldVersion, registry);
24075
+ const res = await host2._runNpm({ action: "install", version: oldVersion, registry });
23844
24076
  let okVer = false;
23845
24077
  try {
23846
24078
  okVer = host2.installedVersion() === oldVersion;
@@ -23870,7 +24102,7 @@ var require_upgrade2 = __commonJS({
23870
24102
  if (host2.events) host2.events.append("upgrade_rollback_started", { to: host2.oldVersion });
23871
24103
  log(host2, "\u56DE\u6EDA\u5230 " + host2.oldVersion + "\u2026");
23872
24104
  const registry = await host2._selectRegistry();
23873
- const res = await host2._runInstall(host2.oldVersion, registry);
24105
+ const res = await host2._runNpm({ action: "install", version: host2.oldVersion, registry });
23874
24106
  let okVer = false;
23875
24107
  try {
23876
24108
  okVer = host2.installedVersion() === host2.oldVersion;
@@ -23934,7 +24166,8 @@ var require_upgrade2 = __commonJS({
23934
24166
  try {
23935
24167
  const oldV = host2.installedVersion();
23936
24168
  host2.oldVersion = oldV;
23937
- const target = await resolveTarget(host2, requestedVersion, task);
24169
+ const pick = await resolveTarget(host2, requestedVersion, task);
24170
+ const target = pick.version;
23938
24171
  host2.targetVersion = target;
23939
24172
  taskLog(host2, task, "\u76EE\u6807\u7248\u672C " + target);
23940
24173
  if (!oldV) {
@@ -23948,7 +24181,7 @@ var require_upgrade2 = __commonJS({
23948
24181
  log(host2, "\u5347\u7EA7 " + oldV + " \u2192 " + target);
23949
24182
  taskLog(host2, task, "\u5347\u7EA7 " + oldV + " \u2192 " + target);
23950
24183
  await stopForUpgrade(host2, task);
23951
- await installTarget(host2, oldV, target, task);
24184
+ await installTarget(host2, oldV, target, pick.origin, task);
23952
24185
  if (!(host2.hooks.desiredRunning && host2.hooks.desiredRunning())) return finishStopped(host2, oldV, target, task);
23953
24186
  return await verifyAndFinalize(host2, oldV, target, task);
23954
24187
  } catch (err) {
@@ -24002,7 +24235,7 @@ var require_installer = __commonJS({
24002
24235
  this.lastInstall = null;
24003
24236
  this.lastUninstall = null;
24004
24237
  }
24005
- /** 追加安装输出(有界,仅任务进行中由 _runInstall 写入)。 */
24238
+ /** 追加安装输出(有界,仅任务进行中由 _runNpm 的行日志写入)。 */
24006
24239
  _appendInstallLog(line) {
24007
24240
  this.installLog.push(line);
24008
24241
  if (this.installLog.length > 60) this.installLog.splice(0, this.installLog.length - 60);
@@ -24045,12 +24278,15 @@ var require_installer = __commonJS({
24045
24278
  _claimDataPaths() {
24046
24279
  return manifest.claimDataPaths(this);
24047
24280
  }
24048
- _runInstall(version, registry) {
24049
- return npm.runInstall(this, version, registry);
24281
+ /** npm 动作的唯一出口(装/升/回滚/卸载同源),入参见 npm.runNpm。 */
24282
+ _runNpm(opts) {
24283
+ return npm.runNpm(this, opts);
24050
24284
  }
24285
+ /** 最新版本 + 给出它的那个镜像源(结构化,回 {ok,version,origin,error})。 */
24051
24286
  _latestVersion() {
24052
24287
  return npm.latestVersion(this);
24053
24288
  }
24289
+ /** 只选源(钉死版本的安装与回滚用);查询过版本的安装路径走 _latestVersion 的 origin。 */
24054
24290
  _selectRegistry() {
24055
24291
  return npm.selectRegistry(this);
24056
24292
  }