| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- import { spawn } from "bun"
- import z from "zod/v4"
- import { NamedError } from "../util/error"
- import { Log } from "../util/log"
- import { Bus } from "../bus"
- const SUPPORTED_IDES = [
- { name: "Windsurf" as const, cmd: "windsurf" },
- { name: "Visual Studio Code" as const, cmd: "code" },
- { name: "Cursor" as const, cmd: "cursor" },
- { name: "VSCodium" as const, cmd: "codium" },
- ]
- export namespace Ide {
- const log = Log.create({ service: "ide" })
- export const Event = {
- Installed: Bus.event(
- "ide.installed",
- z.object({
- ide: z.string(),
- }),
- ),
- }
- export const AlreadyInstalledError = NamedError.create("AlreadyInstalledError", z.object({}))
- export const InstallFailedError = NamedError.create(
- "InstallFailedError",
- z.object({
- stderr: z.string(),
- }),
- )
- export function ide() {
- if (process.env["TERM_PROGRAM"] === "vscode") {
- const v = process.env["GIT_ASKPASS"]
- for (const ide of SUPPORTED_IDES) {
- if (v?.includes(ide.name)) return ide.name
- }
- }
- return "unknown"
- }
- export function alreadyInstalled() {
- return process.env["OPENCODE_CALLER"] === "vscode"
- }
- export async function install(ide: (typeof SUPPORTED_IDES)[number]["name"]) {
- const cmd = SUPPORTED_IDES.find((i) => i.name === ide)?.cmd
- if (!cmd) throw new Error(`Unknown IDE: ${ide}`)
- const p = spawn([cmd, "--install-extension", "sst-dev.opencode"], {
- stdout: "pipe",
- stderr: "pipe",
- })
- await p.exited
- const stdout = await new Response(p.stdout).text()
- const stderr = await new Response(p.stderr).text()
- log.info("installed", {
- ide,
- stdout,
- stderr,
- })
- if (p.exitCode !== 0) {
- throw new InstallFailedError({ stderr })
- }
- if (stdout.includes("already installed")) {
- throw new AlreadyInstalledError({})
- }
- }
- }
|