@portel/photon 1.8.4 → 1.9.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"beam.d.ts","sourceRoot":"","sources":["../../src/auto-ui/beam.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiyBH,wBAAsB,SAAS,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAinFlF;AAiYD;;;GAGG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAsB9C"}
1
+ {"version":3,"file":"beam.d.ts","sourceRoot":"","sources":["../../src/auto-ui/beam.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiyBH,wBAAsB,SAAS,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAysFlF;AAiYD;;;GAGG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAsB9C"}
@@ -1837,9 +1837,30 @@ export async function startBeam(rawWorkingDir, port) {
1837
1837
  if (url.pathname === '/api/marketplace/list') {
1838
1838
  res.setHeader('Content-Type', 'application/json');
1839
1839
  try {
1840
+ // Auto-refresh caches older than 5 minutes so updates are detected without manual Sync
1841
+ await marketplace.autoUpdateStaleCaches(5 * 60 * 1000);
1842
+ const { readLocalMetadata } = await import('../marketplace-manager.js');
1840
1843
  const allPhotons = await marketplace.getAllPhotons();
1844
+ const localMetadata = await readLocalMetadata();
1841
1845
  const photonList = [];
1842
1846
  for (const [name, { metadata, marketplace: mp }] of allPhotons) {
1847
+ const installed = photonMCPs.has(name);
1848
+ let hasUpdate = false;
1849
+ let latestVersion = '';
1850
+ if (installed) {
1851
+ const installMeta = localMetadata.photons[`${name}.photon.ts`];
1852
+ if (installMeta && metadata.hash) {
1853
+ // Primary: hash comparison (catches code changes without version bump)
1854
+ hasUpdate = installMeta.originalHash !== metadata.hash;
1855
+ }
1856
+ else if (installMeta && metadata.version) {
1857
+ // Fallback: version comparison
1858
+ hasUpdate = installMeta.version !== metadata.version;
1859
+ }
1860
+ if (hasUpdate) {
1861
+ latestVersion = metadata.version || '';
1862
+ }
1863
+ }
1843
1864
  photonList.push({
1844
1865
  name,
1845
1866
  description: metadata.description || '',
@@ -1849,7 +1870,9 @@ export async function startBeam(rawWorkingDir, port) {
1849
1870
  marketplace: mp.name,
1850
1871
  icon: metadata.icon,
1851
1872
  internal: metadata.internal,
1852
- installed: photonMCPs.has(name),
1873
+ installed,
1874
+ hasUpdate,
1875
+ latestVersion,
1853
1876
  });
1854
1877
  }
1855
1878
  res.writeHead(200);
@@ -1891,6 +1914,9 @@ export async function startBeam(rawWorkingDir, port) {
1891
1914
  const hash = (await import('../marketplace-manager.js')).calculateHash(result.content);
1892
1915
  await marketplace.savePhotonMetadata(`${name}.photon.ts`, result.marketplace, result.metadata, hash);
1893
1916
  }
1917
+ // Trigger immediate load so the photon appears in the sidebar right away
1918
+ // (don't wait for the file watcher which has debounce delay)
1919
+ handleFileChange(name);
1894
1920
  res.writeHead(200);
1895
1921
  res.end(JSON.stringify({
1896
1922
  success: true,
@@ -1898,8 +1924,6 @@ export async function startBeam(rawWorkingDir, port) {
1898
1924
  path: targetPath,
1899
1925
  version: result.metadata?.version,
1900
1926
  }));
1901
- // Broadcast to connected clients to reload photon list
1902
- broadcastPhotonChange();
1903
1927
  }
1904
1928
  catch {
1905
1929
  res.writeHead(500);
@@ -1908,6 +1932,55 @@ export async function startBeam(rawWorkingDir, port) {
1908
1932
  });
1909
1933
  return;
1910
1934
  }
1935
+ // Marketplace API: Remove/uninstall a photon
1936
+ if (url.pathname === '/api/marketplace/remove' && req.method === 'POST') {
1937
+ res.setHeader('Content-Type', 'application/json');
1938
+ const body = await readBody(req);
1939
+ try {
1940
+ const { name } = JSON.parse(body);
1941
+ if (!name) {
1942
+ res.writeHead(400);
1943
+ res.end(JSON.stringify({ error: 'Missing photon name' }));
1944
+ return;
1945
+ }
1946
+ const filePath = path.join(workingDir, `${name}.photon.ts`);
1947
+ if (!existsSync(filePath)) {
1948
+ res.writeHead(404);
1949
+ res.end(JSON.stringify({ error: `Photon '${name}' not found` }));
1950
+ return;
1951
+ }
1952
+ // Remove the .photon.ts file
1953
+ await fs.unlink(filePath);
1954
+ // Remove UI assets directory if it exists
1955
+ const assetsDir = path.join(workingDir, name);
1956
+ if (existsSync(assetsDir) && lstatSync(assetsDir).isDirectory()) {
1957
+ await fs.rm(assetsDir, { recursive: true });
1958
+ }
1959
+ // Clear compiled cache
1960
+ const cacheDir = path.join(os.homedir(), '.cache', 'photon-mcp', 'compiled');
1961
+ for (const ext of ['.js', '.js.map']) {
1962
+ try {
1963
+ await fs.unlink(path.join(cacheDir, `${name}${ext}`));
1964
+ }
1965
+ catch {
1966
+ /* ignore */
1967
+ }
1968
+ }
1969
+ // Remove from loaded photons
1970
+ const idx = photons.findIndex((p) => p.name === name);
1971
+ if (idx !== -1)
1972
+ photons.splice(idx, 1);
1973
+ photonMCPs.delete(name);
1974
+ res.writeHead(200);
1975
+ res.end(JSON.stringify({ success: true, name }));
1976
+ broadcastPhotonChange();
1977
+ }
1978
+ catch {
1979
+ res.writeHead(500);
1980
+ res.end(JSON.stringify({ error: 'Failed to remove photon' }));
1981
+ }
1982
+ return;
1983
+ }
1911
1984
  // Marketplace API: Get all marketplace sources
1912
1985
  if (url.pathname === '/api/marketplace/sources') {
1913
1986
  res.setHeader('Content-Type', 'application/json');
@@ -2071,18 +2144,24 @@ export async function startBeam(rawWorkingDir, port) {
2071
2144
  const { readLocalMetadata } = await import('../marketplace-manager.js');
2072
2145
  const localMetadata = await readLocalMetadata();
2073
2146
  const updates = [];
2074
- // Check each installed photon for updates
2147
+ // Check each installed photon for updates (hash-based primary, version fallback)
2075
2148
  for (const [fileName, installMeta] of Object.entries(localMetadata.photons)) {
2076
2149
  const photonName = fileName.replace(/\.photon\.ts$/, '');
2077
2150
  const latestInfo = await marketplace.getPhotonMetadata(photonName);
2078
- if (latestInfo && latestInfo.metadata.version !== installMeta.version) {
2079
- updates.push({
2080
- name: photonName,
2081
- fileName,
2082
- currentVersion: installMeta.version,
2083
- latestVersion: latestInfo.metadata.version,
2084
- marketplace: latestInfo.marketplace.name,
2085
- });
2151
+ if (latestInfo) {
2152
+ const hashChanged = latestInfo.metadata.hash
2153
+ ? installMeta.originalHash !== latestInfo.metadata.hash
2154
+ : false;
2155
+ const versionChanged = latestInfo.metadata.version !== installMeta.version;
2156
+ if (hashChanged || versionChanged) {
2157
+ updates.push({
2158
+ name: photonName,
2159
+ fileName,
2160
+ currentVersion: installMeta.version,
2161
+ latestVersion: latestInfo.metadata.version,
2162
+ marketplace: latestInfo.marketplace.name,
2163
+ });
2164
+ }
2086
2165
  }
2087
2166
  }
2088
2167
  res.writeHead(200);