fix(electrobun): wizard fixes — native dialog, models, PathBrowser, ensureDir

- Native dialog: resolve to nearest existing parent dir, detect user cancel
  (exit code 1) vs actual error, add createIfMissing option
- Claude models: fallback to KNOWN_CLAUDE_MODELS (6 models) when API key
  unavailable. Adds Opus 4.6, Sonnet 4.6, Opus 4.5, Sonnet 4, Haiku 4.5,
  Sonnet 3.7. Live API paginated to limit=100.
- PathBrowser: Select button moved to sticky header (always visible).
  Current path shown compact in header with RTL ellipsis.
- files.ensureDir RPC: creates directory recursively before project creation
- files.ensureDir added to RPC schema
This commit is contained in:
Hibryda 2026-03-25 01:05:15 +01:00
parent 162b5417e4
commit a4d180d382
6 changed files with 77 additions and 12 deletions

View file

@ -163,6 +163,16 @@ export function createFilesHandlers() {
}
},
"files.ensureDir": async ({ path: dirPath }: { path: string }) => {
try {
const resolved = path.resolve(dirPath.replace(/^~/, process.env.HOME ?? ""));
fs.mkdirSync(resolved, { recursive: true });
return { ok: true, path: resolved };
} catch (err) {
return { ok: false, error: err instanceof Error ? err.message : String(err) };
}
},
"files.write": async ({ path: filePath, content }: { path: string; content: string }) => {
const guard = guardPath(filePath);
if (!guard.valid) {

View file

@ -56,16 +56,30 @@ export function createMiscHandlers(deps: MiscDeps) {
return {
// ── Files: picker + homeDir ─────────────────────────────────────────
"files.pickDirectory": async ({ startingFolder }: { startingFolder?: string }) => {
"files.pickDirectory": async ({ startingFolder, createIfMissing }: { startingFolder?: string; createIfMissing?: boolean }) => {
try {
const { execSync } = await import("child_process");
const start = startingFolder?.replace(/^~/, process.env.HOME || "/home") || process.env.HOME || "/home";
const fs = await import("fs");
const home = process.env.HOME || "/home";
let start = (startingFolder || "~/").replace(/^~/, home);
// Resolve to nearest existing parent
while (start && start !== "/" && !fs.existsSync(start)) {
start = start.replace(/\/[^/]+\/?$/, "") || home;
}
if (!start || !fs.existsSync(start)) start = home;
const result = execSync(
`zenity --file-selection --directory --title="Select Project Folder" --filename="${start}/"`,
{ encoding: "utf-8", timeout: 120_000 },
).trim();
if (result && createIfMissing) {
fs.mkdirSync(result, { recursive: true });
}
return { path: result || null };
} catch {
} catch (err: unknown) {
// Exit code 1 = user cancelled — not an error
if (err && typeof err === "object" && "status" in err && (err as {status:number}).status === 1) {
return { path: null };
}
return { path: null };
}
},