[codex] add coding plan site initialization flow (#351)

* add coding plan site initialization flow

* fix ci for coding plan site init flow

* address coding plan review comments
This commit is contained in:
Cita
2026-03-31 21:55:25 +08:00
committed by GitHub
parent e74e11375c
commit 0de9c5e3f1
20 changed files with 1272 additions and 67 deletions
+2 -1
View File
@@ -9,9 +9,10 @@ import {
type SiteAnnouncement,
UserInfo,
} from './base.js';
import { stripTrailingSlashes } from '../urlNormalization.js';
function normalizeBaseUrl(baseUrl: string): string {
return (baseUrl || '').replace(/\/+$/, '');
return stripTrailingSlashes(baseUrl || '');
}
/**
+3 -1
View File
@@ -1,3 +1,5 @@
import { stripTrailingSlashes } from '../urlNormalization.js';
export type TitleHintPlatform =
| 'anyrouter'
| 'done-hub'
@@ -34,7 +36,7 @@ function normalizeBaseUrl(url: string): string {
const parsed = new URL(trimmed);
return `${parsed.protocol}//${parsed.host}`;
} catch {
return trimmed.replace(/\/+$/, '');
return stripTrailingSlashes(trimmed);
}
}
+11 -1
View File
@@ -1,7 +1,17 @@
import { detectPlatform } from './platforms/index.js';
import { detectSiteInitializationPreset } from '../../shared/siteInitializationPresets.js';
import { stripTrailingSlashes } from './urlNormalization.js';
export async function detectSite(url: string) {
const normalizedUrl = url.replace(/\/+$/, '');
const normalizedUrl = stripTrailingSlashes(url);
const preset = detectSiteInitializationPreset(normalizedUrl);
if (preset) {
return {
url: normalizedUrl,
platform: preset.platform,
initializationPresetId: preset.id,
};
}
const adapter = await detectPlatform(normalizedUrl);
if (!adapter) return null;
return { url: normalizedUrl, platform: adapter.platformName };
+3 -3
View File
@@ -10,6 +10,7 @@ import type { Dispatcher, RequestInit as UndiciRequestInit } from 'undici';
import { Agent as UndiciAgent, ProxyAgent } from 'undici';
import { mergeHeadersWithSiteCustomHeaders } from './siteCustomHeaders.js';
import { getProxyUrlFromExtraConfig } from './accountExtraConfig.js';
import { stripTrailingSlashes } from './urlNormalization.js';
const SITE_PROXY_CACHE_TTL_MS = 3_000;
const SUPPORTED_PROXY_PROTOCOLS = new Set([
@@ -100,11 +101,10 @@ function normalizeSiteUrl(value: string): string {
try {
const parsed = new URL(trimmed);
const pathname = parsed.pathname.replace(/\/+$/, '');
const normalizedPath = pathname === '/' ? '' : pathname;
const normalizedPath = stripTrailingSlashes(parsed.pathname);
return `${parsed.origin}${normalizedPath}`;
} catch {
return trimmed.replace(/\/+$/, '');
return stripTrailingSlashes(trimmed);
}
}
@@ -0,0 +1,13 @@
import { describe, expect, it } from 'vitest';
import { stripTrailingSlashes } from './urlNormalization.js';
describe('stripTrailingSlashes', () => {
it('removes trailing slashes without using regex behavior', () => {
expect(stripTrailingSlashes('')).toBe('');
expect(stripTrailingSlashes('https://api.example.com')).toBe('https://api.example.com');
expect(stripTrailingSlashes('https://api.example.com///')).toBe('https://api.example.com');
expect(stripTrailingSlashes('/api/v1///')).toBe('/api/v1');
expect(stripTrailingSlashes('////')).toBe('');
});
});
+7
View File
@@ -0,0 +1,7 @@
export function stripTrailingSlashes(value: string): string {
let end = value.length;
while (end > 0 && value.charCodeAt(end - 1) === 47) {
end -= 1;
}
return end === value.length ? value : value.slice(0, end);
}