diff --git a/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts b/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts index 7f388cc48..790c37737 100644 --- a/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +++ b/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts @@ -132,9 +132,14 @@ export class LoginDialogComponent extends Container implements Focusable { this.contentContainer.addChild(new Text(theme.fg("warning", instructions), 1, 0)); } - // Try to open browser + // Try to open browser — on Windows, `start` needs an empty title arg + // so it treats the URL as a target, not a window title const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open"; - exec(`${openCmd} "${url}"`); + if (process.platform === "win32") { + exec(`start "" "${url}"`); + } else { + exec(`${openCmd} "${url}"`); + } this.tui.requestRender(); } diff --git a/src/resources/extensions/gsd/commands.ts b/src/resources/extensions/gsd/commands.ts index eaf5ebd94..05a048b41 100644 --- a/src/resources/extensions/gsd/commands.ts +++ b/src/resources/extensions/gsd/commands.ts @@ -1095,7 +1095,7 @@ async function configureNotifications(ctx: ExtensionCommandContext, prefs: Recor for (const field of notifFields) { const current = notif[field.key]; - const currentStr = current !== undefined ? String(current) : ""; + const currentStr = current !== undefined && typeof current === "boolean" ? String(current) : ""; const choice = await ctx.ui.select( `${field.label}${currentStr ? ` (current: ${currentStr})` : ` (default: ${field.defaultVal})`}:`, ["true", "false", "(keep current)"], diff --git a/src/resources/extensions/mcporter/index.ts b/src/resources/extensions/mcporter/index.ts index abd8d82e9..7cb041b46 100644 --- a/src/resources/extensions/mcporter/index.ts +++ b/src/resources/extensions/mcporter/index.ts @@ -418,12 +418,24 @@ export default function (pi: ExtensionAPI) { pi.on("session_start", async (_event, ctx) => { try { const ver = (await runMcporter(["--version"], undefined, 5000)).trim(); - ctx.ui.notify(`MCPorter ${ver} ready`, "info"); + ctx.ui.notify(`MCPorter ${ver} ready`, "info"); } catch { - ctx.ui.notify( - "MCPorter not found. Install with: npm i -g mcporter", - "error", - ); + ctx.ui.notify("MCPorter not found — attempting auto-install…", "warning"); + try { + await new Promise((resolve, reject) => { + exec("npm install -g mcporter", { timeout: 60000 }, (err) => { + if (err) reject(err); + else resolve(); + }); + }); + const ver = (await runMcporter(["--version"], undefined, 5000)).trim(); + ctx.ui.notify(`MCPorter ${ver} auto-installed ✓`, "info"); + } catch { + ctx.ui.notify( + "MCPorter auto-install failed. Install manually: npm i -g mcporter", + "error", + ); + } } }); } diff --git a/src/resources/extensions/search-the-web/native-search.ts b/src/resources/extensions/search-the-web/native-search.ts index 8221afce7..dd0181145 100644 --- a/src/resources/extensions/search-the-web/native-search.ts +++ b/src/resources/extensions/search-the-web/native-search.ts @@ -157,11 +157,13 @@ export function registerNativeSearchHooks(pi: NativeSearchPI): { getIsAnthropic: const hasBrave = !!process.env.BRAVE_API_KEY; const hasJina = !!process.env.JINA_API_KEY; const hasAnswers = !!process.env.BRAVE_ANSWERS_KEY; + const hasTavily = !!process.env.TAVILY_API_KEY; const parts: string[] = ["Web search v4 loaded"]; if (hasBrave) parts.push("Brave ✓"); if (hasAnswers) parts.push("Answers ✓"); if (hasJina) parts.push("Jina ✓"); + if (hasTavily) parts.push("Tavily ✓"); ctx.ui.notify(parts.join(" · "), "info"); });