MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / interactiveAddProvider

Function interactiveAddProvider

src/setup/provider-add-interactive.ts:36–153  ·  view source on GitHub ↗
(preselectId?: string)

Source from the content-addressed store, hash-verified

34 * the Groq key while still using the friendly key-prompt + auto-wire path.
35 */
36export async function interactiveAddProvider(preselectId?: string): Promise<InteractiveAddResult | null> {
37 const opts: PromptOptions = { interactive: isInteractiveTTY() };
38 if (!opts.interactive) {
39 throw new Error('Interactive add needs a TTY. Use: qodex provider add <id> --base-url <url> --key-env <ENV> [--model <id>]');
40 }
41
42 // 1. Resolve the gateway — either preselected or chosen from the list.
43 let spec: GatewaySpec | undefined;
44 let customName = '';
45 let customBaseUrl = '';
46 let customKeyEnv = '';
47
48 if (preselectId && findGateway(preselectId)) {
49 spec = findGateway(preselectId);
50 } else if (preselectId) {
51 // A name we don't know — treat it as a custom provider. If the user passed a
52 // URL (`provider add https://api.x.com/v1`), use it as the base URL and derive
53 // a valid slug name from its host; otherwise slugify the given name.
54 if (/^[a-z][a-z0-9+.-]*:\/\//i.test(preselectId.trim())) {
55 customBaseUrl = preselectId.trim();
56 }
57 customName = slugifyProviderName(preselectId);
58 } else {
59 const ids = listGatewayIds();
60 const choices = [
61 ...ids.map(id => {
62 const g = KNOWN_GATEWAYS[id]!;
63 return { value: id, label: g.title, hint: g.baseUrl };
64 }),
65 { value: CUSTOM_SENTINEL, label: 'Something else (custom OpenAI-compatible endpoint)', hint: 'enter base URL yourself' },
66 ];
67 const picked = await choose('\nWhich provider do you want to add?', choices, ids[0]!, opts);
68 if (picked === CUSTOM_SENTINEL) {
69 customName = slugifyProviderName(await text(' Provider name (one word, e.g. "myhost")', '', opts));
70 if (!customName) { console.log(' ✗ Cancelled — no name given.'); return null; }
71 } else {
72 spec = findGateway(picked);
73 }
74 }
75
76 // 2. For a custom provider, gather base URL + derive the env var name.
77 if (!spec) {
78 if (!customBaseUrl) {
79 customBaseUrl = (await text(' OpenAI-compatible base URL (…/v1)', '', opts)).trim();
80 if (!customBaseUrl) { console.log(' ✗ Cancelled — no base URL given.'); return null; }
81 }
82 customKeyEnv = `${customName.toUpperCase().replace(/[^A-Z0-9]/g, '_')}_API_KEY`;
83 }
84
85 const name = spec ? spec.name : customName;
86 const apiKeyEnv = spec ? spec.apiKeyEnv : customKeyEnv;
87 const title = spec ? spec.title : name;
88
89 // If the provider came from the interactive menu (not a `provider add <id>` argument), confirm
90 // the pick before doing anything. This catches the case where a stray Enter — e.g. from pasting
91 // multiple lines into the terminal — lands on the default row and would otherwise silently
92 // configure the wrong provider.
93 if (!preselectId) {

Callers 1

index.tsFile · 0.85

Calls 10

isInteractiveTTYFunction · 0.85
findGatewayFunction · 0.85
slugifyProviderNameFunction · 0.85
listGatewayIdsFunction · 0.85
chooseFunction · 0.85
textFunction · 0.85
confirmFunction · 0.85
setEnvKeyFunction · 0.85
buildCustomEntryFunction · 0.85
addProviderToConfigFunction · 0.85

Tested by

no test coverage detected