This commit is contained in:
YeonGyu-Kim
2026-05-27 13:58:58 +09:00
parent 73e8988f31
commit db00bb3d42
18 changed files with 21606 additions and 431 deletions
+66 -35
View File
@@ -11,7 +11,7 @@ import {
} from "./config-manager"
import { detectedToInitialValues, formatConfigSummary, SYMBOLS } from "./install-validators"
import { getUnsupportedOpenCodeVersionMessage } from "./minimum-opencode-version"
import { promptInstallConfig } from "./tui-install-prompts"
import { promptInstallConfig, promptInstallPlatform } from "./tui-install-prompts"
import { runCodexInstaller } from "./install-codex"
export async function runTuiInstaller(args: InstallArgs, version: string): Promise<number> {
@@ -20,8 +20,28 @@ export async function runTuiInstaller(args: InstallArgs, version: string): Promi
return 1
}
const detected = detectCurrentConfig()
const isUpdate = detected.isInstalled
const selectedPlatform = await promptInstallPlatform(args.platform ?? "opencode")
if (!selectedPlatform) return 1
const hasOpenCode = selectedPlatform === "opencode" || selectedPlatform === "both"
const detected = hasOpenCode
? detectCurrentConfig()
: {
isInstalled: false,
installedVersion: null,
hasClaude: false,
isMax20: false,
hasOpenAI: false,
hasGemini: false,
hasCopilot: false,
hasCodex: false,
hasOpencodeZen: false,
hasZaiCodingPlan: false,
hasKimiForCoding: false,
hasOpencodeGo: false,
hasVercelAiGateway: false,
}
const isUpdate = hasOpenCode && detected.isInstalled
p.intro(color.bgMagenta(color.white(isUpdate ? " oMoMoMoMo... Update " : " oMoMoMoMo... ")))
@@ -31,45 +51,49 @@ export async function runTuiInstaller(args: InstallArgs, version: string): Promi
}
const spinner = p.spinner()
spinner.start("Checking OpenCode installation")
if (hasOpenCode) {
spinner.start("Checking OpenCode installation")
const installed = await isOpenCodeInstalled()
const openCodeVersion = await getOpenCodeVersion()
if (!installed) {
spinner.stop(`OpenCode binary not found ${color.yellow("[!]")}`)
p.log.warn("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.")
p.note("Visit https://opencode.ai/docs for installation instructions", "Installation Guide")
} else {
spinner.stop(`OpenCode ${openCodeVersion ?? "installed"} ${color.green("[OK]")}`)
const installed = await isOpenCodeInstalled()
const openCodeVersion = await getOpenCodeVersion()
if (!installed) {
spinner.stop(`OpenCode binary not found ${color.yellow("[!]")}`)
p.log.warn("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.")
p.note("Visit https://opencode.ai/docs for installation instructions", "Installation Guide")
} else {
spinner.stop(`OpenCode ${openCodeVersion ?? "installed"} ${color.green("[OK]")}`)
const unsupportedVersionMessage = getUnsupportedOpenCodeVersionMessage(openCodeVersion)
if (unsupportedVersionMessage) {
p.log.warn(unsupportedVersionMessage)
p.outro(color.red("Installation blocked."))
return 1
const unsupportedVersionMessage = getUnsupportedOpenCodeVersionMessage(openCodeVersion)
if (unsupportedVersionMessage) {
p.log.warn(unsupportedVersionMessage)
p.outro(color.red("Installation blocked."))
return 1
}
}
}
const config = await promptInstallConfig(detected)
const config = await promptInstallConfig(detected, selectedPlatform)
if (!config) return 1
spinner.start(`Adding ${PLUGIN_NAME} to OpenCode config`)
const pluginResult = await addPluginToOpenCodeConfig(version)
if (!pluginResult.success) {
spinner.stop(`Failed to add plugin: ${pluginResult.error}`)
p.outro(color.red("Installation failed."))
return 1
}
spinner.stop(`Plugin added to ${color.cyan(pluginResult.configPath)}`)
if (config.hasOpenCode) {
spinner.start(`Adding ${PLUGIN_NAME} to OpenCode config`)
const pluginResult = await addPluginToOpenCodeConfig(version)
if (!pluginResult.success) {
spinner.stop(`Failed to add plugin: ${pluginResult.error}`)
p.outro(color.red("Installation failed."))
return 1
}
spinner.stop(`Plugin added to ${color.cyan(pluginResult.configPath)}`)
spinner.start(`Writing ${PLUGIN_NAME} configuration`)
const omoResult = writeOmoConfig(config)
if (!omoResult.success) {
spinner.stop(`Failed to write config: ${omoResult.error}`)
p.outro(color.red("Installation failed."))
return 1
spinner.start(`Writing ${PLUGIN_NAME} configuration`)
const omoResult = writeOmoConfig(config)
if (!omoResult.success) {
spinner.stop(`Failed to write config: ${omoResult.error}`)
p.outro(color.red("Installation failed."))
return 1
}
spinner.stop(`Config written to ${color.cyan(omoResult.configPath)}`)
}
spinner.stop(`Config written to ${color.cyan(omoResult.configPath)}`)
if (!config.hasClaude) {
p.log.info(
@@ -92,12 +116,19 @@ export async function runTuiInstaller(args: InstallArgs, version: string): Promi
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
spinner.stop(`Codex install failed ${color.yellow("[!]")}`)
if (!config.hasOpenCode) {
p.log.error(`Codex install failed: ${message}`)
p.outro(color.red("Installation failed."))
return 1
}
p.log.warn(`Codex install failed (OpenCode install remains successful): ${message}`)
}
}
p.log.success(color.bold(isUpdate ? "Configuration updated!" : "Installation complete!"))
p.log.message(`Run ${color.cyan("opencode")} to start!`)
if (config.hasOpenCode) {
p.log.message(`Run ${color.cyan("opencode")} to start!`)
}
p.log.info("Anonymous telemetry is enabled by default. Disable it with OMO_SEND_ANONYMOUS_TELEMETRY=0 or OMO_DISABLE_POSTHOG=1.")
p.log.info("Docs: docs/legal/privacy-policy.md and docs/legal/terms-of-service.md")
@@ -115,7 +146,7 @@ export async function runTuiInstaller(args: InstallArgs, version: string): Promi
p.outro(color.green("oMoMoMoMo... Enjoy!"))
if ((config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
if (config.hasOpenCode && (config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
const providers: string[] = []
if (config.hasClaude) providers.push(`Anthropic ${color.gray("→ Claude Pro/Max")}`)
if (config.hasGemini) providers.push(`Google ${color.gray("→ Gemini")}`)