Dashboard › cli › Distillation
fba3564e-8f67-4711-8d21-cb5eacc12b26["lore_tm_v1_qgz11SxvUTpGWruhQGem-GC21Deab1ReoxgOLX_KvQU","lore_tm_v1_6e-Y4TRm2b7YGmm_4MsXON0w21IVBdQT64-KrtDnfM0","lore_tm_v1_Pty2k1FxgWy_XICRTOPm42c6TiVgPQ-qQG5H8W0qK7g","lore_tm_v1_3LBYRhISdCgkFgbSr2bqBJWIs38atvG6Pde3Cig0J0k","lore_tm_v1_2Op5baR97rxfH5TfSUlovs-obXhF193x-EsPI2Stx2Y"]
SourceStrategy.resolveChain(currentVersion, targetVersion, signal?, report?): Promise<PatchChain | null>; a null result always falls back to a full download, and report classifications are telemetry-only and never change control flow.DeltaUnavailableReason has exactly 5 values: "no_patches" for no tags/assets in range, "malformed_chain" for a published but invalid chain, "too_long" for exceeding maximum depth, "over_budget" for exceeding the size-ratio gate, and "network" for transient resolution failure.DeltaSource is "cache" | "network" | "offline_miss". DeltaTelemetry exposes onResolved(info), onOfflineMiss(), and onUnavailable(reason); onUnavailable reports why no chain was usable but always leaves full-download fallback behavior unchanged.ResolveAndApplyOpts injects source, currentVersion, targetVersion, oldPath, destPath, optional cache, offline, onProgress, telemetry, and signal. When offline is true, resolution must never touch the networkβcache hit or bust.onProgress are never rendered by the library; the library only emits them through safeProgress(onProgress).resolveAndApply() is cache-first: it calls tryLoadCachedChain(cache, currentVersion, targetVersion), reports a hit via telemetry.onResolved({ source: "cache", chain }), and applies it immediately. Any cache-load exception is converted to a cache miss by returning null.resolveAndApply() invokes telemetry.onOfflineMiss() and returns null without source/network resolution.{ type: "phase", phase: "resolve" }, defaults the unavailable classification to "no_patches", lets the source replace it through UnavailableReporter, invokes telemetry.onUnavailable(unavailableReason) on a null chain, and returns null for full-download fallback.chain.steps is persisted using fire-and-forget cache.save(chain, chain.steps).catch(() => {}); cache-save failures are intentionally swallowed. The chain is then reported through telemetry.onResolved({ source: "network", chain }).applyChain() computes apply progress total as the sum of parsePatchHeader(patch.data).newSize across every hop, because byte callbacks include in-memory intermediate outputs and the final disk write. Using only the final hop size would make a multi-hop bar reach 100% after the first hop and then freeze.applyChain() sets total = null; this is only a best-effort progress fallback, while corrupt data is rejected later during actual patch application.applyChain() calls applyPatchChainInMemory(oldPath, chain.patches.map((p) => p.data), destPath, onBytes), accumulates written, and emits ordered apply events: phase, cumulative bytes with total, then done.chain.expectedSha256, and throws SHA-256 mismatch after patching: got ${sha256}, expected ${chain.expectedSha256} on mismatch; success emits verify done and returns { sha256, patchBytes: chain.totalSize, chainLength: chain.patches.length }.packages/cli/src/lib/binary.ts defines UpgradeSource with readonly githubRepo, ghcrRepo, and tagPrefix.UPGRADE_SOURCES is ordered as: 1. { githubRepo: "getsentry/toolkit", ghcrRepo: "getsentry/toolkit", tagPrefix: "cli@" }; 2. { githubRepo: "getsentry/cli", ghcrRepo: "getsentry/cli", tagPrefix: "" }. Source resolution falls through only on HTTP 404.PRIMARY_UPGRADE_SOURCE is UPGRADE_SOURCES[0], making getsentry/toolkit with release tag prefix cli@ the default for direct helpers that do not first resolve a source.getBinaryDownloadUrl(version, source) constructs https://github.com/${source.githubRepo}/releases/download/${source.tagPrefix}${version}/${getPlatformBinaryName()}.packages/cli/src/lib/binary.ts are getGitHubReleasesUrl(), getGitHubReleaseByTagUrl(), getGitHubLatestReleaseUrl(), and getGitHubRepositoryUrl(). Prefixed sources discover latest releases with ?per_page=100; unprefixed sources use /latest.ResolveUpgradeSourceOptions takes getProbeUrl, optional injected fetch, optional shared signal, and optional ordered sources; its fetch defaults to the CLI CA-aware customFetch.fetchUpgradeProbe() sends getGitHubHeaders() and the supplied signal. It rethrows AbortError, converts TLS certificate errors to UpgradeError("network_error", buildTlsErrorDetail(error)), and converts other connection failures to UpgradeError("network_error", "Failed to connect to GitHub: ...").resolveUpgradeSource() returns both the selected source and its successful probe response, so the caller never repeats the successful request. Only HTTP 404 advances to the next source; every other HTTP response or network failure aborts immediately.fetchLatestFromGitHubWithSource(signal?, sources = UPGRADE_SOURCES) resolves a source using getGitHubLatestReleaseUrl, parses either one release object or an array of releases, calls extractReleaseVersions(data, source), strips VERSION_PREFIX_REGEX from the first tag, and returns { version, source }; no parsed version throws UpgradeError("network_error", "No version found in GitHub release").fetchLatestFromGitHub(signal?, source?) delegates to fetchLatestFromGitHubWithSource, restricting resolution to [source] when explicitly supplied, and returns only .version.fetchLatestFromNpm() requests ${NPM_REGISTRY_URL}/latest with Accept: application/json; non-OK responses throw UpgradeError("network_error", "Failed to fetch from npm: ${response.status}"), and a response without version throws UpgradeError("network_error", "No version found in npm registry").fetchLatestNightlyVersionWithSource() rejects an already-aborted signal with new AbortError(), resolves the "nightly" manifest, extracts the version with getNightlyVersion(resolved.manifest), and returns that version with the selected source.resolveNightlyManifest(tag, signal, sources) processes sources in order. For each source it first probes getGitHubRepositoryUrl; a source-not-found 404 advances to the next source, while other errors propagate. It then calls getAnonymousToken(source, signal) and fetchManifest(token, tag, signal, source); a tag-specific HTTP 404 advances, while other errors propagate.resolveNightlyManifest() throws UpgradeError("network_error", "No CLI upgrade source was found: every source returned HTTP 404").resolveNightlyManifest() implementation additionally performs a GitHub repository availability probe for each attempted source.fetchLatestVersion(method, channel = "stable") uses GHCR nightly resolution for "nightly", GitHub for stable "curl"/"brew" installs, and npm for other stable package-manager installs.resolveLatestUpgradeVersion(channel, signal?) preserves the selected source by dispatching to fetchLatestNightlyVersionWithSource(signal) or fetchLatestFromGitHubWithSource(signal).resolveExistingUpgradeVersion(version) validates pinned nightly versions through resolveNightlyManifest(\nightly-${version}`, undefined, UPGRADE_SOURCES)and pinned stable versions throughresolveUpgradeSource({ getProbeUrl: (source) => getGitHubReleaseByTagUrl(version, source) }); it returns { version, source }, returns null` only when all sources are not found, and rethrows other failures.nightlyVersionExists(version, source) performs getAnonymousToken(source) and fetchManifest(token, \nightly-${version}`, undefined, source); it returns falseonly for anUpgradeErrorcontaining"HTTP 404"` and propagates all other errors.standaloneVersionExists(version, source?) uses the supplied source directly when present: nightly versions call nightlyVersionExists, while stable versions fetch getGitHubReleaseByTagUrl(version, source) with getGitHubHeaders() and return .ok. Without a source, it calls resolveExistingUpgradeVersion(version).versionExists(method, version, source?) uses standalone source resolution for nightly versions and for "curl"/"brew" methods; other package-manager versions send HEAD to ${NPM_REGISTRY_URL}/${version}.DownloadResult contains tempBinaryPath, lockPath, and optional patchBytes, where patchBytes records the delta patch size only when a delta upgrade replaced the full download.writeChunkSync(fd, chunk) loops around writeSync() to handle short writes and throws writeSync returned ${n} for chunk of ${chunk.byteLength - written} bytes if the kernel returns 0 or less, preventing an infinite loop on an unwritable file descriptor.drainBodyToFd(body, fd, onBytes) drains a decompressed ReadableStream<Uint8Array> while separately retaining terminal stream errors and synchronous write-loop errors; it never closes the caller-owned file descriptor.downloadBinaryToTemp flow acquires a download lock before attempting tryDeltaUpgrade, tracks optional patchBytes, distinguishes offline === "explicit", fsyncs/validates the downloaded file because Bun.file(path).writer() may return before the file is durably surfaced, and returns { tempBinaryPath: tempPath, lockPath, patchBytes } while leaving lock release to the caller after the child process exits.