@portel/photon 1.34.0 → 1.34.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.
- package/README.md +20 -6
- package/dist/auto-ui/beam.d.ts.map +1 -1
- package/dist/auto-ui/beam.js +8 -2
- package/dist/auto-ui/beam.js.map +1 -1
- package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
- package/dist/auto-ui/streamable-http-transport.js +52 -0
- package/dist/auto-ui/streamable-http-transport.js.map +1 -1
- package/dist/beam.bundle.js +47 -0
- package/dist/beam.bundle.js.map +2 -2
- package/dist/daemon/server.js +53 -11
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/session-manager.d.ts +2 -1
- package/dist/daemon/session-manager.d.ts.map +1 -1
- package/dist/daemon/session-manager.js +33 -2
- package/dist/daemon/session-manager.js.map +1 -1
- package/package.json +4 -3
package/dist/daemon/server.js
CHANGED
|
@@ -1734,7 +1734,9 @@ function watchBaseForProactiveMetadata(basePath, _isDefaultBase) {
|
|
|
1734
1734
|
watchDebounce.set(debounceKey, timer);
|
|
1735
1735
|
};
|
|
1736
1736
|
try {
|
|
1737
|
-
const watcher = safeWatchDir(basePath, (_eventType, filename) => onChange(filename)
|
|
1737
|
+
const watcher = safeWatchDir(basePath, (_eventType, filename) => onChange(filename), {
|
|
1738
|
+
bunPollMaxEntries: BUN_DIR_POLL_MAX_ENTRIES,
|
|
1739
|
+
});
|
|
1738
1740
|
baseDirWatchers.set(basePath, watcher);
|
|
1739
1741
|
}
|
|
1740
1742
|
catch (err) {
|
|
@@ -2968,7 +2970,7 @@ async function handleRequest(request, socket) {
|
|
|
2968
2970
|
const key = compositeKey(photonName, request.workingDir);
|
|
2969
2971
|
const sessionManager = sessionManagers.get(key);
|
|
2970
2972
|
if (sessionManager) {
|
|
2971
|
-
await sessionManager.clearInstances();
|
|
2973
|
+
await sessionManager.clearInstances('clear-instances');
|
|
2972
2974
|
}
|
|
2973
2975
|
return { type: 'result', id: request.id, success: true, data: { cleared: !!sessionManager } };
|
|
2974
2976
|
}
|
|
@@ -4638,6 +4640,7 @@ async function applyPatchToInstance(instance, photonName, ops, workingDir) {
|
|
|
4638
4640
|
*/
|
|
4639
4641
|
const IS_BUN = !!process.versions.bun;
|
|
4640
4642
|
const POLL_INTERVAL_MS = 2000; // 2s — good balance between latency and CPU
|
|
4643
|
+
const BUN_DIR_POLL_MAX_ENTRIES = parseNonNegativeEnvInt('PHOTON_BUN_DIR_POLL_MAX_ENTRIES', 512);
|
|
4641
4644
|
/** Track active poll timers so they can be cleaned up on shutdown */
|
|
4642
4645
|
const pollTimers = new Set();
|
|
4643
4646
|
function safeWatchFile(filePath, callback) {
|
|
@@ -4686,12 +4689,37 @@ function safeWatchFile(filePath, callback) {
|
|
|
4686
4689
|
},
|
|
4687
4690
|
};
|
|
4688
4691
|
}
|
|
4689
|
-
function
|
|
4692
|
+
function countDirEntries(dirPath) {
|
|
4693
|
+
try {
|
|
4694
|
+
return fs.readdirSync(dirPath).length;
|
|
4695
|
+
}
|
|
4696
|
+
catch {
|
|
4697
|
+
return null;
|
|
4698
|
+
}
|
|
4699
|
+
}
|
|
4700
|
+
function shouldSkipBunDirPoll(dirPath, maxEntries) {
|
|
4701
|
+
if (!IS_BUN || maxEntries === 0)
|
|
4702
|
+
return false;
|
|
4703
|
+
const count = countDirEntries(dirPath);
|
|
4704
|
+
if (count === null || count <= maxEntries)
|
|
4705
|
+
return false;
|
|
4706
|
+
logger.warn('Skipping Bun directory polling watcher for oversized directory', {
|
|
4707
|
+
dir: dirPath,
|
|
4708
|
+
entries: count,
|
|
4709
|
+
maxEntries,
|
|
4710
|
+
});
|
|
4711
|
+
return true;
|
|
4712
|
+
}
|
|
4713
|
+
function safeWatchDir(dirPath, callback, options = {}) {
|
|
4690
4714
|
if (!IS_BUN) {
|
|
4691
4715
|
const w = fs.watch(dirPath, (eventType, filename) => callback(eventType, filename));
|
|
4692
4716
|
return w;
|
|
4693
4717
|
}
|
|
4694
4718
|
// Bun fallback: readdir snapshot diffing
|
|
4719
|
+
if (options.bunPollMaxEntries !== undefined &&
|
|
4720
|
+
shouldSkipBunDirPoll(dirPath, options.bunPollMaxEntries)) {
|
|
4721
|
+
return { close() { } };
|
|
4722
|
+
}
|
|
4695
4723
|
let prevEntries = new Map(); // name -> mtimeMs
|
|
4696
4724
|
try {
|
|
4697
4725
|
for (const entry of fs.readdirSync(dirPath)) {
|
|
@@ -4836,7 +4864,7 @@ function watchPhotonFile(photonName, photonPath) {
|
|
|
4836
4864
|
for (const key of keysToDelete) {
|
|
4837
4865
|
const manager = sessionManagers.get(key);
|
|
4838
4866
|
if (manager)
|
|
4839
|
-
await manager.clearInstances();
|
|
4867
|
+
await manager.clearInstances('photon-deleted');
|
|
4840
4868
|
sessionManagers.delete(key);
|
|
4841
4869
|
photonPaths.delete(key);
|
|
4842
4870
|
workingDirs.delete(key);
|
|
@@ -4914,6 +4942,22 @@ function unwatchPhotonFile(watchPath) {
|
|
|
4914
4942
|
watchDebounce.delete(watchPath);
|
|
4915
4943
|
}
|
|
4916
4944
|
}
|
|
4945
|
+
function unwatchPhotonPath(photonPath) {
|
|
4946
|
+
let watchPath = photonPath;
|
|
4947
|
+
try {
|
|
4948
|
+
watchPath = fs.realpathSync(photonPath);
|
|
4949
|
+
}
|
|
4950
|
+
catch {
|
|
4951
|
+
// Symlink target may already be gone; fall back to caller path.
|
|
4952
|
+
}
|
|
4953
|
+
unwatchPhotonFile(watchPath);
|
|
4954
|
+
const debounceKey = path.resolve(photonPath);
|
|
4955
|
+
const timer = watchDebounce.get(debounceKey);
|
|
4956
|
+
if (timer) {
|
|
4957
|
+
clearTimeout(timer);
|
|
4958
|
+
watchDebounce.delete(debounceKey);
|
|
4959
|
+
}
|
|
4960
|
+
}
|
|
4917
4961
|
/**
|
|
4918
4962
|
* Detect whether a missing workingDir was renamed (moved) or deleted.
|
|
4919
4963
|
*
|
|
@@ -5041,7 +5085,7 @@ function watchWorkingDir(workingDir) {
|
|
|
5041
5085
|
for (const key of deletedDirKeys) {
|
|
5042
5086
|
const manager = sessionManagers.get(key);
|
|
5043
5087
|
if (manager)
|
|
5044
|
-
await manager.clearInstances();
|
|
5088
|
+
await manager.clearInstances('working-dir-deleted');
|
|
5045
5089
|
sessionManagers.delete(key);
|
|
5046
5090
|
photonPaths.delete(key);
|
|
5047
5091
|
workingDirs.delete(key);
|
|
@@ -5108,7 +5152,7 @@ function watchStateDir(workingDir) {
|
|
|
5108
5152
|
const key = compositeKey(filename, workingDir);
|
|
5109
5153
|
const manager = sessionManagers.get(key);
|
|
5110
5154
|
if (manager) {
|
|
5111
|
-
await manager.clearInstances();
|
|
5155
|
+
await manager.clearInstances('state-dir-deleted');
|
|
5112
5156
|
}
|
|
5113
5157
|
})();
|
|
5114
5158
|
}, 150);
|
|
@@ -5602,13 +5646,11 @@ function startupWatchPhotonDir(photonDir, defaultBase) {
|
|
|
5602
5646
|
if (photonPaths.has(photonKey) && !fs.existsSync(filePath)) {
|
|
5603
5647
|
photonPaths.delete(photonKey);
|
|
5604
5648
|
// fileWatchers is keyed by file path, not composite key
|
|
5605
|
-
|
|
5606
|
-
if (watcher) {
|
|
5607
|
-
watcher.close();
|
|
5608
|
-
fileWatchers.delete(filePath);
|
|
5609
|
-
}
|
|
5649
|
+
unwatchPhotonPath(filePath);
|
|
5610
5650
|
logger.info('Photon file removed', { photonName, path: filePath });
|
|
5611
5651
|
}
|
|
5652
|
+
}, {
|
|
5653
|
+
bunPollMaxEntries: BUN_DIR_POLL_MAX_ENTRIES,
|
|
5612
5654
|
});
|
|
5613
5655
|
if (typeof dirWatcher.on === 'function') {
|
|
5614
5656
|
dirWatcher.on('error', () => { }); // Non-fatal
|