[codex] rename site API request wording (#423)
* rename site api request wording * replace real site example domains
This commit is contained in:
@@ -62,14 +62,14 @@ describe('accounts api endpoint host selection', { timeout: 15_000 }, () => {
|
||||
|
||||
const site = await db.insert(schema.sites).values({
|
||||
name: 'Nihao Panel',
|
||||
url: 'https://nih.cc',
|
||||
url: 'https://console.example.com',
|
||||
platform: 'new-api',
|
||||
status: 'active',
|
||||
}).returning().get();
|
||||
|
||||
await db.insert(schema.siteApiEndpoints).values({
|
||||
siteId: site.id,
|
||||
url: 'https://api.nih.cc',
|
||||
url: 'https://api.example.com',
|
||||
enabled: true,
|
||||
sortOrder: 0,
|
||||
}).run();
|
||||
@@ -90,7 +90,7 @@ describe('accounts api endpoint host selection', { timeout: 15_000 }, () => {
|
||||
tokenType: 'apikey',
|
||||
modelCount: 1,
|
||||
});
|
||||
expect(getModelsMock).toHaveBeenCalledWith('https://api.nih.cc', 'sk-nihao', undefined);
|
||||
expect(getModelsMock).toHaveBeenCalledWith('https://api.example.com', 'sk-nihao', undefined);
|
||||
expect(verifyTokenMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -101,7 +101,7 @@ describe('accounts api endpoint host selection', { timeout: 15_000 }, () => {
|
||||
|
||||
const site = await db.insert(schema.sites).values({
|
||||
name: 'Nihao Pool',
|
||||
url: 'https://nih.cc',
|
||||
url: 'https://console.example.com',
|
||||
platform: 'new-api',
|
||||
status: 'active',
|
||||
}).returning().get();
|
||||
@@ -109,13 +109,13 @@ describe('accounts api endpoint host selection', { timeout: 15_000 }, () => {
|
||||
await db.insert(schema.siteApiEndpoints).values([
|
||||
{
|
||||
siteId: site.id,
|
||||
url: 'https://api-a.nih.cc',
|
||||
url: 'https://api-a.example.com',
|
||||
enabled: true,
|
||||
sortOrder: 0,
|
||||
},
|
||||
{
|
||||
siteId: site.id,
|
||||
url: 'https://api-b.nih.cc',
|
||||
url: 'https://api-b.example.com',
|
||||
enabled: true,
|
||||
sortOrder: 1,
|
||||
},
|
||||
@@ -137,12 +137,12 @@ describe('accounts api endpoint host selection', { timeout: 15_000 }, () => {
|
||||
tokenType: 'apikey',
|
||||
modelCount: 1,
|
||||
});
|
||||
expect(getModelsMock).toHaveBeenNthCalledWith(1, 'https://api-a.nih.cc', 'sk-rotate', undefined);
|
||||
expect(getModelsMock).toHaveBeenNthCalledWith(2, 'https://api-b.nih.cc', 'sk-rotate', undefined);
|
||||
expect(getModelsMock).toHaveBeenNthCalledWith(1, 'https://api-a.example.com', 'sk-rotate', undefined);
|
||||
expect(getModelsMock).toHaveBeenNthCalledWith(2, 'https://api-b.example.com', 'sk-rotate', undefined);
|
||||
|
||||
const endpoints = await db.select().from(schema.siteApiEndpoints).all();
|
||||
const firstEndpoint = endpoints.find((item) => item.url === 'https://api-a.nih.cc');
|
||||
const secondEndpoint = endpoints.find((item) => item.url === 'https://api-b.nih.cc');
|
||||
const firstEndpoint = endpoints.find((item) => item.url === 'https://api-a.example.com');
|
||||
const secondEndpoint = endpoints.find((item) => item.url === 'https://api-b.example.com');
|
||||
expect(firstEndpoint?.cooldownUntil).toBeTruthy();
|
||||
expect(firstEndpoint?.lastFailureReason).toContain('HTTP 502');
|
||||
expect(secondEndpoint?.lastSelectedAt).toBeTruthy();
|
||||
@@ -158,14 +158,14 @@ describe('accounts api endpoint host selection', { timeout: 15_000 }, () => {
|
||||
|
||||
const site = await db.insert(schema.sites).values({
|
||||
name: 'Nihao Panel',
|
||||
url: 'https://nih.cc',
|
||||
url: 'https://console.example.com',
|
||||
platform: 'new-api',
|
||||
status: 'active',
|
||||
}).returning().get();
|
||||
|
||||
await db.insert(schema.siteApiEndpoints).values({
|
||||
siteId: site.id,
|
||||
url: 'https://api.nih.cc',
|
||||
url: 'https://api.example.com',
|
||||
enabled: true,
|
||||
sortOrder: 0,
|
||||
}).run();
|
||||
@@ -186,7 +186,7 @@ describe('accounts api endpoint host selection', { timeout: 15_000 }, () => {
|
||||
tokenType: 'session',
|
||||
apiToken: 'sk-derived',
|
||||
});
|
||||
expect(verifyTokenMock).toHaveBeenCalledWith('https://nih.cc', 'session-token', undefined);
|
||||
expect(verifyTokenMock).toHaveBeenCalledWith('https://console.example.com', 'session-token', undefined);
|
||||
expect(getModelsMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -195,14 +195,14 @@ describe('accounts api endpoint host selection', { timeout: 15_000 }, () => {
|
||||
|
||||
const site = await db.insert(schema.sites).values({
|
||||
name: 'Nihao Panel',
|
||||
url: 'https://nih.cc',
|
||||
url: 'https://console.example.com',
|
||||
platform: 'new-api',
|
||||
status: 'active',
|
||||
}).returning().get();
|
||||
|
||||
await db.insert(schema.siteApiEndpoints).values({
|
||||
siteId: site.id,
|
||||
url: 'https://api.nih.cc',
|
||||
url: 'https://api.example.com',
|
||||
enabled: true,
|
||||
sortOrder: 0,
|
||||
}).run();
|
||||
@@ -221,7 +221,7 @@ describe('accounts api endpoint host selection', { timeout: 15_000 }, () => {
|
||||
expect(response.json()).toMatchObject({
|
||||
tokenType: 'apikey',
|
||||
});
|
||||
expect(getModelsMock).toHaveBeenCalledWith('https://api.nih.cc', 'sk-nihao-create', undefined);
|
||||
expect(getModelsMock).toHaveBeenCalledWith('https://api.example.com', 'sk-nihao-create', undefined);
|
||||
});
|
||||
|
||||
it('rotates API key account creation across configured ai endpoints after a retryable failure', async () => {
|
||||
@@ -231,7 +231,7 @@ describe('accounts api endpoint host selection', { timeout: 15_000 }, () => {
|
||||
|
||||
const site = await db.insert(schema.sites).values({
|
||||
name: 'Nihao Create Pool',
|
||||
url: 'https://nih.cc',
|
||||
url: 'https://console.example.com',
|
||||
platform: 'new-api',
|
||||
status: 'active',
|
||||
}).returning().get();
|
||||
@@ -239,13 +239,13 @@ describe('accounts api endpoint host selection', { timeout: 15_000 }, () => {
|
||||
await db.insert(schema.siteApiEndpoints).values([
|
||||
{
|
||||
siteId: site.id,
|
||||
url: 'https://api-create-a.nih.cc',
|
||||
url: 'https://api-create-a.example.com',
|
||||
enabled: true,
|
||||
sortOrder: 0,
|
||||
},
|
||||
{
|
||||
siteId: site.id,
|
||||
url: 'https://api-create-b.nih.cc',
|
||||
url: 'https://api-create-b.example.com',
|
||||
enabled: true,
|
||||
sortOrder: 1,
|
||||
},
|
||||
@@ -265,7 +265,7 @@ describe('accounts api endpoint host selection', { timeout: 15_000 }, () => {
|
||||
expect(response.json()).toMatchObject({
|
||||
tokenType: 'apikey',
|
||||
});
|
||||
expect(getModelsMock).toHaveBeenNthCalledWith(1, 'https://api-create-a.nih.cc', 'sk-nihao-create-rotate', undefined);
|
||||
expect(getModelsMock).toHaveBeenNthCalledWith(2, 'https://api-create-b.nih.cc', 'sk-nihao-create-rotate', undefined);
|
||||
expect(getModelsMock).toHaveBeenNthCalledWith(1, 'https://api-create-a.example.com', 'sk-nihao-create-rotate', undefined);
|
||||
expect(getModelsMock).toHaveBeenNthCalledWith(2, 'https://api-create-b.example.com', 'sk-nihao-create-rotate', undefined);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -150,7 +150,7 @@ describe('chat proxy site api endpoint rotation', () => {
|
||||
it('rotates to the next configured ai endpoint for retryable /v1/chat/completions failures', async () => {
|
||||
const site = await db.insert(schema.sites).values({
|
||||
name: 'nihao-panel',
|
||||
url: 'https://nih.cc',
|
||||
url: 'https://console.example.com',
|
||||
platform: 'openai',
|
||||
status: 'active',
|
||||
}).returning().get();
|
||||
@@ -168,13 +168,13 @@ describe('chat proxy site api endpoint rotation', () => {
|
||||
await db.insert(schema.siteApiEndpoints).values([
|
||||
{
|
||||
siteId: site.id,
|
||||
url: 'https://api-a.nih.cc',
|
||||
url: 'https://api-a.example.com',
|
||||
enabled: true,
|
||||
sortOrder: 0,
|
||||
},
|
||||
{
|
||||
siteId: site.id,
|
||||
url: 'https://api-b.nih.cc',
|
||||
url: 'https://api-b.example.com',
|
||||
enabled: true,
|
||||
sortOrder: 1,
|
||||
},
|
||||
@@ -222,10 +222,10 @@ describe('chat proxy site api endpoint rotation', () => {
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json()?.choices?.[0]?.message?.content).toBe('ok via api-b');
|
||||
expect(fetchMock).toHaveBeenCalledTimes(4);
|
||||
expect(String(fetchMock.mock.calls[0]?.[0] || '')).toBe('https://api-a.nih.cc/v1/chat/completions');
|
||||
expect(String(fetchMock.mock.calls[1]?.[0] || '')).toBe('https://api-a.nih.cc/v1/responses');
|
||||
expect(String(fetchMock.mock.calls[2]?.[0] || '')).toBe('https://api-a.nih.cc/v1/messages');
|
||||
expect(String(fetchMock.mock.calls[3]?.[0] || '')).toBe('https://api-b.nih.cc/v1/chat/completions');
|
||||
expect(String(fetchMock.mock.calls[0]?.[0] || '')).toBe('https://api-a.example.com/v1/chat/completions');
|
||||
expect(String(fetchMock.mock.calls[1]?.[0] || '')).toBe('https://api-a.example.com/v1/responses');
|
||||
expect(String(fetchMock.mock.calls[2]?.[0] || '')).toBe('https://api-a.example.com/v1/messages');
|
||||
expect(String(fetchMock.mock.calls[3]?.[0] || '')).toBe('https://api-b.example.com/v1/chat/completions');
|
||||
expect(selectNextChannelMock).not.toHaveBeenCalled();
|
||||
expect(recordFailureMock).not.toHaveBeenCalled();
|
||||
expect(recordSuccessMock).toHaveBeenCalledTimes(1);
|
||||
@@ -235,7 +235,7 @@ describe('chat proxy site api endpoint rotation', () => {
|
||||
.orderBy(asc(schema.siteApiEndpoints.sortOrder), asc(schema.siteApiEndpoints.id))
|
||||
.all();
|
||||
expect(storedEndpoints[0]).toMatchObject({
|
||||
url: 'https://api-a.nih.cc',
|
||||
url: 'https://api-a.example.com',
|
||||
lastFailureReason: 'HTTP 502: [upstream:/v1/messages] Upstream returned HTTP 502: bad gateway via messages',
|
||||
});
|
||||
expect(storedEndpoints[0]?.cooldownUntil).toBeTruthy();
|
||||
|
||||
@@ -120,7 +120,7 @@ describe('/v1/completions site api endpoint rotation', () => {
|
||||
it('cools down a retryable failed endpoint and retries the next endpoint within the same site', async () => {
|
||||
const site = await db.insert(schema.sites).values({
|
||||
name: 'nihao-panel',
|
||||
url: 'https://nih.cc',
|
||||
url: 'https://console.example.com',
|
||||
platform: 'new-api',
|
||||
status: 'active',
|
||||
}).returning().get();
|
||||
@@ -138,13 +138,13 @@ describe('/v1/completions site api endpoint rotation', () => {
|
||||
await db.insert(schema.siteApiEndpoints).values([
|
||||
{
|
||||
siteId: site.id,
|
||||
url: 'https://api-a.nih.cc',
|
||||
url: 'https://api-a.example.com',
|
||||
enabled: true,
|
||||
sortOrder: 0,
|
||||
},
|
||||
{
|
||||
siteId: site.id,
|
||||
url: 'https://api-b.nih.cc',
|
||||
url: 'https://api-b.example.com',
|
||||
enabled: true,
|
||||
sortOrder: 1,
|
||||
},
|
||||
@@ -194,8 +194,8 @@ describe('/v1/completions site api endpoint rotation', () => {
|
||||
object: 'text_completion',
|
||||
});
|
||||
expect(fetchMock).toHaveBeenCalledTimes(2);
|
||||
expect(String(fetchMock.mock.calls[0]?.[0] || '')).toBe('https://api-a.nih.cc/v1/completions');
|
||||
expect(String(fetchMock.mock.calls[1]?.[0] || '')).toBe('https://api-b.nih.cc/v1/completions');
|
||||
expect(String(fetchMock.mock.calls[0]?.[0] || '')).toBe('https://api-a.example.com/v1/completions');
|
||||
expect(String(fetchMock.mock.calls[1]?.[0] || '')).toBe('https://api-b.example.com/v1/completions');
|
||||
expect(selectNextChannelMock).not.toHaveBeenCalled();
|
||||
expect(recordFailureMock).not.toHaveBeenCalled();
|
||||
expect(recordSuccessMock).toHaveBeenCalledTimes(1);
|
||||
@@ -205,12 +205,12 @@ describe('/v1/completions site api endpoint rotation', () => {
|
||||
.orderBy(asc(schema.siteApiEndpoints.sortOrder), asc(schema.siteApiEndpoints.id))
|
||||
.all();
|
||||
expect(storedEndpoints[0]).toMatchObject({
|
||||
url: 'https://api-a.nih.cc',
|
||||
url: 'https://api-a.example.com',
|
||||
lastFailureReason: 'HTTP 502: bad gateway',
|
||||
});
|
||||
expect(storedEndpoints[0]?.cooldownUntil).toBeTruthy();
|
||||
expect(storedEndpoints[1]).toMatchObject({
|
||||
url: 'https://api-b.nih.cc',
|
||||
url: 'https://api-b.example.com',
|
||||
});
|
||||
expect(storedEndpoints[1]?.lastSelectedAt).toBeTruthy();
|
||||
});
|
||||
|
||||
@@ -617,7 +617,7 @@ describe('responses websocket transport', () => {
|
||||
type: 'error',
|
||||
status: 408,
|
||||
error: {
|
||||
message: '当前站点的 AI 请求地址均不可用',
|
||||
message: '当前站点的 API 请求地址均不可用',
|
||||
},
|
||||
});
|
||||
expect(fetchMock).toHaveBeenCalledTimes(0);
|
||||
|
||||
@@ -138,21 +138,21 @@ describe('refreshModelsForAccount credential discovery', () => {
|
||||
it('uses the configured ai endpoint for direct model discovery credentials', async () => {
|
||||
getApiTokenMock.mockResolvedValue(null);
|
||||
getModelsMock.mockImplementation(async (baseUrl: string, token: string) => (
|
||||
baseUrl === 'https://api.nih.cc' && token === 'session-token'
|
||||
baseUrl === 'https://api.example.com' && token === 'session-token'
|
||||
? ['gpt-4.1']
|
||||
: []
|
||||
));
|
||||
|
||||
const site = await db.insert(schema.sites).values({
|
||||
name: 'nihao-panel',
|
||||
url: 'https://nih.cc',
|
||||
url: 'https://console.example.com',
|
||||
platform: 'new-api',
|
||||
status: 'active',
|
||||
}).returning().get();
|
||||
|
||||
await db.insert(schema.siteApiEndpoints).values({
|
||||
siteId: site.id,
|
||||
url: 'https://api.nih.cc',
|
||||
url: 'https://api.example.com',
|
||||
enabled: true,
|
||||
sortOrder: 0,
|
||||
}).run();
|
||||
@@ -175,7 +175,7 @@ describe('refreshModelsForAccount credential discovery', () => {
|
||||
modelCount: 1,
|
||||
modelsPreview: ['gpt-4.1'],
|
||||
});
|
||||
expect(getModelsMock).toHaveBeenCalledWith('https://api.nih.cc', 'session-token', undefined);
|
||||
expect(getModelsMock).toHaveBeenCalledWith('https://api.example.com', 'session-token', undefined);
|
||||
});
|
||||
|
||||
it('deduplicates discovered model names before writing availability rows', async () => {
|
||||
|
||||
@@ -207,7 +207,7 @@ export async function requireSiteApiBaseUrl(
|
||||
): Promise<string> {
|
||||
const baseUrl = await resolveSiteApiBaseUrl(site, now);
|
||||
if (baseUrl) return baseUrl;
|
||||
throw new Error('当前站点的 AI 请求地址均不可用');
|
||||
throw new Error('当前站点的 API 请求地址均不可用');
|
||||
}
|
||||
|
||||
export async function recordSiteApiEndpointFailure(
|
||||
@@ -258,11 +258,11 @@ export async function runWithSiteApiEndpointPool<T>(
|
||||
const target = await selectSiteApiEndpointTarget(site);
|
||||
if (!target) {
|
||||
if (lastError) throw lastError;
|
||||
throw new Error('当前站点的 AI 请求地址均不可用');
|
||||
throw new Error('当前站点的 API 请求地址均不可用');
|
||||
}
|
||||
if (target.endpointId && attemptedEndpointIds.has(target.endpointId)) {
|
||||
if (lastError) throw lastError;
|
||||
throw new Error('当前站点的 AI 请求地址均不可用');
|
||||
throw new Error('当前站点的 API 请求地址均不可用');
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user