From a1f5ca33f3fe08394224733a1679d2af183c3742 Mon Sep 17 00:00:00 2001 From: Kushagra Singh Gaur Date: Thu, 4 Jun 2026 17:33:25 +0530 Subject: [PATCH 1/4] fix(init): normalize custom base URL --- src/commands/init.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/commands/init.ts b/src/commands/init.ts index 9c5fc46..efbec11 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -8,6 +8,10 @@ import { installPrepareCommitMsgHook } from '../git/hook.js'; const CUSTOM_KEY = '__custom__'; +export function normalizeBaseUrl(value: string): string { + return value.replace(/\/+$/, ''); +} + export function buildApiKeyPrompt(existingKey: string, apiKeyEnv: string) { return { message: `Enter your API key (will be stored in config), or leave blank to use ${pc.cyan(`$${apiKeyEnv}`)} env var:`, @@ -78,7 +82,7 @@ export async function initCommand(options: { installHook?: boolean } = {}): Prom outro('Setup cancelled.'); return; } - baseUrl = urlResult; + baseUrl = normalizeBaseUrl(urlResult); apiKeyEnv = 'CUSTOM_API_KEY'; needsApiKey = true; } else { From d3ae4d957ab49cdfe9a65389bebbc2d0815d09aa Mon Sep 17 00:00:00 2001 From: Kushagra Singh Gaur Date: Thu, 4 Jun 2026 17:34:10 +0530 Subject: [PATCH 2/4] test(init): cover custom base URL normalization --- tests/init-base-url.test.mjs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/init-base-url.test.mjs diff --git a/tests/init-base-url.test.mjs b/tests/init-base-url.test.mjs new file mode 100644 index 0000000..76c550b --- /dev/null +++ b/tests/init-base-url.test.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; + +import { normalizeBaseUrl } from '../dist/commands/init.js'; + +test('trims trailing slashes from custom base URLs', () => { + assert.equal(normalizeBaseUrl('https://api.example.com/v1/'), 'https://api.example.com/v1'); + assert.equal(normalizeBaseUrl('https://api.example.com/v1///'), 'https://api.example.com/v1'); +}); + +test('preserves custom base URLs without trailing slashes', () => { + assert.equal(normalizeBaseUrl('https://api.example.com/v1'), 'https://api.example.com/v1'); +}); From 66b2c2b99eaa316642716a97061f965893e6548f Mon Sep 17 00:00:00 2001 From: Kushagra963-lab <147275307+Kushagra963-lab@users.noreply.github.com> Date: Fri, 26 Jun 2026 06:43:40 +0530 Subject: [PATCH 3/4] test: cover single trailing slash base URL --- tests/init-base-url.test.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/init-base-url.test.mjs b/tests/init-base-url.test.mjs index 76c550b..8f27c47 100644 --- a/tests/init-base-url.test.mjs +++ b/tests/init-base-url.test.mjs @@ -3,8 +3,11 @@ import test from 'node:test'; import { normalizeBaseUrl } from '../dist/commands/init.js'; -test('trims trailing slashes from custom base URLs', () => { +test('handles single trailing slash', () => { assert.equal(normalizeBaseUrl('https://api.example.com/v1/'), 'https://api.example.com/v1'); +}); + +test('trims multiple trailing slashes from custom base URLs', () => { assert.equal(normalizeBaseUrl('https://api.example.com/v1///'), 'https://api.example.com/v1'); }); From 7d0a8625f199b3b761ffadc914b53fef48589e5f Mon Sep 17 00:00:00 2001 From: Kushagra Singh Gaur Date: Fri, 26 Jun 2026 11:19:52 +0530 Subject: [PATCH 4/4] Add test for initCommand saving normalized base URL Added a test for initCommand to verify it saves the normalized custom provider base URL correctly. --- tests/init-base-url.test.mjs | 42 +++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/tests/init-base-url.test.mjs b/tests/init-base-url.test.mjs index 8f27c47..1c2f4f2 100644 --- a/tests/init-base-url.test.mjs +++ b/tests/init-base-url.test.mjs @@ -1,7 +1,7 @@ import assert from 'node:assert/strict'; import test from 'node:test'; -import { normalizeBaseUrl } from '../dist/commands/init.js'; +import { initCommand, normalizeBaseUrl } from '../dist/commands/init.js'; test('handles single trailing slash', () => { assert.equal(normalizeBaseUrl('https://api.example.com/v1/'), 'https://api.example.com/v1'); @@ -14,3 +14,43 @@ test('trims multiple trailing slashes from custom base URLs', () => { test('preserves custom base URLs without trailing slashes', () => { assert.equal(normalizeBaseUrl('https://api.example.com/v1'), 'https://api.example.com/v1'); }); + +test('initCommand saves normalized custom provider base URL', async () => { + const savedConfigs = []; + const selectedValues = ['__custom__', 'custom-model']; + const textValues = ['https://api.example.com/v1/', 'test-api-key', '50']; + const spinnerStub = { + start() {}, + stop() {}, + }; + + await initCommand( + {}, + { + intro() {}, + outro() {}, + select: async () => selectedValues.shift(), + text: async () => textValues.shift(), + confirm: async () => false, + spinner: () => spinnerStub, + isCancel: () => false, + configExists: () => false, + fetchModels: async (provider, baseUrl) => { + assert.equal(provider, '__custom__'); + assert.equal(baseUrl, 'https://api.example.com/v1'); + return ['custom-model']; + }, + saveConfig: async (config) => { + savedConfigs.push(config); + }, + testConnection: async (config) => { + assert.equal(config.baseUrl, 'https://api.example.com/v1'); + return config.model; + }, + }, + ); + + assert.equal(savedConfigs.length, 1); + assert.equal(savedConfigs[0].provider, '__custom__'); + assert.equal(savedConfigs[0].baseUrl, 'https://api.example.com/v1'); +});