125 lines
4.2 KiB
TypeScript
125 lines
4.2 KiB
TypeScript
import * as p from "@clack/prompts"
|
|
import type { Option } from "@clack/prompts"
|
|
import type {
|
|
ClaudeSubscription,
|
|
DetectedConfig,
|
|
InstallConfig,
|
|
} from "./types"
|
|
import { detectedToInitialValues } from "./install-validators"
|
|
|
|
async function selectOrCancel<TValue extends Readonly<string | boolean | number>>(params: {
|
|
message: string
|
|
options: Option<TValue>[]
|
|
initialValue: TValue
|
|
}): Promise<TValue | null> {
|
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return null
|
|
|
|
const value = await p.select<TValue>({
|
|
message: params.message,
|
|
options: params.options,
|
|
initialValue: params.initialValue,
|
|
})
|
|
if (p.isCancel(value)) {
|
|
p.cancel("Installation cancelled.")
|
|
return null
|
|
}
|
|
return value as TValue
|
|
}
|
|
|
|
export async function promptInstallConfig(detected: DetectedConfig): Promise<InstallConfig | null> {
|
|
const initial = detectedToInitialValues(detected)
|
|
|
|
const claude = await selectOrCancel<ClaudeSubscription>({
|
|
message: "Do you have a Claude Pro/Max subscription?",
|
|
options: [
|
|
{ value: "no", label: "No", hint: "Will use opencode/big-pickle as fallback" },
|
|
{ value: "yes", label: "Yes (standard)", hint: "Claude Opus 4.5 for orchestration" },
|
|
{ value: "max20", label: "Yes (max20 mode)", hint: "Full power with Claude Sonnet 4.6 for Librarian" },
|
|
],
|
|
initialValue: initial.claude,
|
|
})
|
|
if (!claude) return null
|
|
|
|
const openai = await selectOrCancel({
|
|
message: "Do you have an OpenAI/ChatGPT Plus subscription?",
|
|
options: [
|
|
{ value: "no", label: "No", hint: "Oracle will use fallback models" },
|
|
{ value: "yes", label: "Yes", hint: "GPT-5.4 for Oracle (high-IQ debugging)" },
|
|
],
|
|
initialValue: initial.openai,
|
|
})
|
|
if (!openai) return null
|
|
|
|
const gemini = await selectOrCancel({
|
|
message: "Will you integrate Google Gemini?",
|
|
options: [
|
|
{ value: "no", label: "No", hint: "Frontend/docs agents will use fallback" },
|
|
{ value: "yes", label: "Yes", hint: "Beautiful UI generation with Gemini 3 Pro" },
|
|
],
|
|
initialValue: initial.gemini,
|
|
})
|
|
if (!gemini) return null
|
|
|
|
const copilot = await selectOrCancel({
|
|
message: "Do you have a GitHub Copilot subscription?",
|
|
options: [
|
|
{ value: "no", label: "No", hint: "Only native providers will be used" },
|
|
{ value: "yes", label: "Yes", hint: "Fallback option when native providers unavailable" },
|
|
],
|
|
initialValue: initial.copilot,
|
|
})
|
|
if (!copilot) return null
|
|
|
|
const opencodeZen = await selectOrCancel({
|
|
message: "Do you have access to OpenCode Zen (opencode/ models)?",
|
|
options: [
|
|
{ value: "no", label: "No", hint: "Will use other configured providers" },
|
|
{ value: "yes", label: "Yes", hint: "opencode/claude-opus-4-6, opencode/gpt-5.4, etc." },
|
|
],
|
|
initialValue: initial.opencodeZen,
|
|
})
|
|
if (!opencodeZen) return null
|
|
|
|
const zaiCodingPlan = await selectOrCancel({
|
|
message: "Do you have a Z.ai Coding Plan subscription?",
|
|
options: [
|
|
{ value: "no", label: "No", hint: "Will use other configured providers" },
|
|
{ value: "yes", label: "Yes", hint: "Fallback for Librarian and Multimodal Looker" },
|
|
],
|
|
initialValue: initial.zaiCodingPlan,
|
|
})
|
|
if (!zaiCodingPlan) return null
|
|
|
|
const kimiForCoding = await selectOrCancel({
|
|
message: "Do you have a Kimi For Coding subscription?",
|
|
options: [
|
|
{ value: "no", label: "No", hint: "Will use other configured providers" },
|
|
{ value: "yes", label: "Yes", hint: "Kimi K2.5 for Sisyphus/Prometheus fallback" },
|
|
],
|
|
initialValue: initial.kimiForCoding,
|
|
})
|
|
if (!kimiForCoding) return null
|
|
|
|
const opencodeGo = await selectOrCancel({
|
|
message: "Do you have an OpenCode Go subscription?",
|
|
options: [
|
|
{ value: "no", label: "No", hint: "Will use other configured providers" },
|
|
{ value: "yes", label: "Yes", hint: "OpenCode Go for quick tasks" },
|
|
],
|
|
initialValue: initial.opencodeGo,
|
|
})
|
|
if (!opencodeGo) return null
|
|
|
|
return {
|
|
hasClaude: claude !== "no",
|
|
isMax20: claude === "max20",
|
|
hasOpenAI: openai === "yes",
|
|
hasGemini: gemini === "yes",
|
|
hasCopilot: copilot === "yes",
|
|
hasOpencodeZen: opencodeZen === "yes",
|
|
hasZaiCodingPlan: zaiCodingPlan === "yes",
|
|
hasKimiForCoding: kimiForCoding === "yes",
|
|
hasOpencodeGo: opencodeGo === "yes",
|
|
}
|
|
}
|