desktop-pet-app 0.2.9 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/out/main/index.js +49 -5
  2. package/package.json +1 -1
package/out/main/index.js CHANGED
@@ -1717,6 +1717,12 @@ async function checkForUpdates(currentVersion = electron.app.getVersion()) {
1717
1717
  status = { kind: "up-to-date", checkedAt: Date.now() };
1718
1718
  return status;
1719
1719
  }
1720
+ const cachedArtifactPath = await verifiedCachedArtifact(update);
1721
+ if (cachedArtifactPath) {
1722
+ status = { kind: "downloaded", update, artifactPath: cachedArtifactPath, downloadedAt: Date.now() };
1723
+ logger.info("using cached verified update", { version: update.version });
1724
+ return status;
1725
+ }
1720
1726
  status = { kind: "available", update, checkedAt: Date.now() };
1721
1727
  logger.info("update available", { currentVersion, version: update.version });
1722
1728
  return status;
@@ -1743,7 +1749,7 @@ async function downloadAvailableUpdate() {
1743
1749
  if (!available) return status;
1744
1750
  status = { kind: "downloading", update: available, downloadedBytes: 0 };
1745
1751
  const updateDirectory = node_path.join(electron.app.getPath("userData"), "updates");
1746
- const artifactPath = node_path.join(updateDirectory, `desktop-pet-${available.version}${installerExtension(available.releaseUrl)}`);
1752
+ const artifactPath = updateArtifactPath(available);
1747
1753
  const temporaryPath = `${artifactPath}.${node_crypto.randomUUID()}.download`;
1748
1754
  try {
1749
1755
  await promises.mkdir(updateDirectory, { recursive: true });
@@ -1793,6 +1799,7 @@ async function installDownloadedUpdate() {
1793
1799
  downloaded.artifactPath,
1794
1800
  downloaded.update.sha256,
1795
1801
  process.platform,
1802
+ downloaded.update.version,
1796
1803
  process.execPath,
1797
1804
  JSON.stringify(restartArgumentsAfterUpdate())
1798
1805
  ], {
@@ -1812,6 +1819,29 @@ function supportsInAppInstall() {
1812
1819
  function restartArgumentsAfterUpdate() {
1813
1820
  return !electron.app.isPackaged && process.argv[1] ? [process.argv[1]] : [];
1814
1821
  }
1822
+ function updateArtifactPath(update) {
1823
+ return node_path.join(electron.app.getPath("userData"), "updates", `desktop-pet-${update.version}${installerExtension(update.releaseUrl)}`);
1824
+ }
1825
+ async function verifiedCachedArtifact(update) {
1826
+ const artifactPath = updateArtifactPath(update);
1827
+ try {
1828
+ return await sha256File(artifactPath) === update.sha256 ? artifactPath : void 0;
1829
+ } catch (error) {
1830
+ if (error.code !== "ENOENT") {
1831
+ logger.warn("could not verify cached update", { version: update.version, error: String(error) });
1832
+ }
1833
+ return void 0;
1834
+ }
1835
+ }
1836
+ function sha256File(path2) {
1837
+ return new Promise((resolve, reject) => {
1838
+ const hash = node_crypto.createHash("sha256");
1839
+ const input = node_fs.createReadStream(path2);
1840
+ input.on("data", (chunk) => hash.update(chunk));
1841
+ input.on("error", reject);
1842
+ input.on("end", () => resolve(hash.digest("hex")));
1843
+ });
1844
+ }
1815
1845
  async function saveAndHash(body, destination, onChunk) {
1816
1846
  const hash = node_crypto.createHash("sha256");
1817
1847
  const meter = new node_stream.Transform({
@@ -1861,7 +1891,7 @@ const { dirname, join } = require('node:path')
1861
1891
  const { execFile, spawn } = require('node:child_process')
1862
1892
  const { promisify } = require('node:util')
1863
1893
 
1864
- const [, , parentPidText, sourcePath, expectedSHA256, platform, fallbackExecutable, fallbackArgsJSON] = process.argv
1894
+ const [, , parentPidText, sourcePath, expectedSHA256, platform, targetVersion, fallbackExecutable, fallbackArgsJSON] = process.argv
1865
1895
  const parentPid = Number(parentPidText)
1866
1896
  const fallbackArgs = JSON.parse(fallbackArgsJSON || '[]')
1867
1897
  const run = promisify(execFile)
@@ -1884,11 +1914,25 @@ const restartFallback = () => {
1884
1914
  child.on('error', () => undefined)
1885
1915
  child.unref()
1886
1916
  }
1917
+ const findInstalledMacApp = async () => {
1918
+ const query = 'kMDItemCFBundleIdentifier == "${MAC_BUNDLE_ID}"'
1919
+ const { stdout } = await run('/usr/bin/mdfind', [query])
1920
+ const candidates = stdout.split('\n').map((value) => value.trim()).filter((value) => value.endsWith('.app'))
1921
+ for (const candidate of candidates) {
1922
+ try {
1923
+ const plist = join(candidate, 'Contents', 'Info.plist')
1924
+ const result = await run('/usr/libexec/PlistBuddy', ['-c', 'Print :CFBundleShortVersionString', plist])
1925
+ if (result.stdout.trim() === targetVersion) return candidate
1926
+ } catch {}
1927
+ }
1928
+ throw new Error('installed app for target version was not found')
1929
+ }
1887
1930
  const restartInstalledApp = async () => {
1888
- // 安装器可能会保留已有应用的位置(开发构建尤其如此),不能假设它在 /Applications。
1889
- // 让 LaunchServices 按 bundle ID 查找刚安装的实际应用位置。
1890
1931
  if (platform === 'darwin') {
1891
- await run('/usr/bin/open', ['-b', '${MAC_BUNDLE_ID}'])
1932
+ // 安装器可能把包重定位到已有开发构建,且机器上可能存在多个同 bundle ID 的应用。
1933
+ // 找到版本完全匹配的具体路径再启动,避免按 bundle ID 命中旧副本后静默失败。
1934
+ const installedApp = await findInstalledMacApp()
1935
+ await run('/usr/bin/open', ['-n', installedApp])
1892
1936
  return
1893
1937
  }
1894
1938
  restartFallback()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "desktop-pet-app",
3
- "version": "0.2.9",
3
+ "version": "0.3.1",
4
4
  "description": "AI desktop pet with MCP support and a self-hosted relay server",
5
5
  "license": "MIT",
6
6
  "keywords": [