fix(electrobun): PathBrowser uses unguarded files.browse RPC (dirs only)

- files.browse: new RPC handler — unguarded directory listing, returns
  only directories (no file content access). Used by PathBrowser wizard.
- PathBrowser: uses files.browse instead of files.list (was blocked by
  guardPath "access denied: path outside allowed project directories")
- Home dir resolved via files.homeDir RPC (not process.env.HOME)

Note: GTK native dialog title/theme/sort controlled by Electrobun's
native wrapper — canChooseFiles:false should set SELECT_FOLDER action
but may need upstream fix for correct title.
This commit is contained in:
Hibryda 2026-03-22 12:11:39 +01:00
parent 46b4893d2d
commit 41d5cc3c12
3 changed files with 22 additions and 1 deletions

View file

@ -43,6 +43,22 @@ export function createFilesHandlers() {
}
},
// Unguarded directory listing for the PathBrowser (wizard).
// Only returns dir names — no file content access.
"files.browse": async ({ path: dirPath }: { path: string }) => {
try {
const resolved = path.resolve(dirPath.replace(/^~/, process.env.HOME || "/home"));
const dirents = fs.readdirSync(resolved, { withFileTypes: true });
const entries = dirents
.filter((d) => !d.name.startsWith(".") && d.isDirectory())
.map((d) => ({ name: d.name, type: "dir" as const, size: 0 }))
.sort((a, b) => a.name.localeCompare(b.name));
return { entries };
} catch (err) {
return { entries: [], error: err instanceof Error ? err.message : String(err) };
}
},
"files.read": async ({ path: filePath }: { path: string }) => {
const guard = guardPath(filePath);
if (!guard.valid) {

View file

@ -56,7 +56,7 @@
try {
const home = await resolveHome();
const expandedPath = dirPath.replace(/^~/, home);
const result = await appRpc.request['files.list']({ path: expandedPath });
const result = await appRpc.request['files.browse']({ path: expandedPath });
if (result?.error) {
error = result.error;
entries = [];

View file

@ -146,6 +146,11 @@ export type PtyRPCRequests = {
error?: string;
};
};
/** Unguarded directory listing for PathBrowser (dirs only, no file content) */
"files.browse": {
params: { path: string };
response: { entries: { name: string; type: 'dir'; size: number }[]; error?: string };
};
/** Native folder picker dialog */
"files.pickDirectory": {
params: { startingFolder?: string };