feat: refine usage views and add Codex system prompt editing
- Brighten usage subpages with consistent surfaces and text contrast - Show reasoning effort by default and migrate saved column settings - Hide HTTP method prefixes and tighten request table spacing - Support custom Codex system prompts and synchronize instruction templates - Add a clear button to plugin search - Update localization, mocks, and regression tests
This commit is contained in:
1 parent
dfba9b019f
commit
2b49fe6a25
19 files changed
+233
-23
No files matched your search
@@ -12,6 +12,7 @@ import {
|
||||
const configuration = (): CodexModelConfiguration => ({
|
||||
display_name: 'Third Party',
|
||||
description: null,
|
||||
base_instructions: 'You are a helpful coding assistant.',
|
||||
context_window: 128_000,
|
||||
max_context_window: 128_000,
|
||||
effective_context_window_percent: 95,
|
||||
@@ -28,6 +29,14 @@ const configuration = (): CodexModelConfiguration => ({
|
||||
});
|
||||
|
||||
describe('Codex 模型列表编辑', () => {
|
||||
test('识别系统提示词修改并拒绝空提示词', () => {
|
||||
const original = configuration();
|
||||
const edited = { ...original, base_instructions: '请用中文回答。\n保留换行。' };
|
||||
expect(sameCodexModelConfiguration(original, edited)).toBeFalse();
|
||||
expect(validateCodexModelConfiguration(edited)).toBeNull();
|
||||
expect(validateCodexModelConfiguration({ ...original, base_instructions: ' \n ' }))
|
||||
.toBe('agents.catalog.invalidPrompt');
|
||||
});
|
||||
test("区分 Codex 客户端 API、模板后备与自定义上下文", () => {
|
||||
const model: CodexCatalogEditorModel = {
|
||||
slug: "model-a", hasOfficialTemplate: true, customized: false,
|
||||
|
||||
+4
-2
@@ -9,11 +9,13 @@ const params = new URLSearchParams(location.search);
|
||||
localStorage.setItem('easy-cli-proxy-api.locale', params.get('locale') || 'zh-CN');
|
||||
// Keep the model column visible even if a previous fixture changed the user's layout.
|
||||
localStorage.setItem('cpa-gui.usage-events-visible-cols.v3', JSON.stringify([
|
||||
'time', 'key', 'source', 'model', 'effort', 'result', 'request', 'latency', 'speed', 'total', 'cache', 'provider',
|
||||
'time', 'key', 'source', 'model', 'result', 'request', 'latency', 'speed', 'total', 'cache', 'provider',
|
||||
]));
|
||||
localStorage.removeItem('cpa-gui.usage-events-visible-cols.v2');
|
||||
localStorage.removeItem('cpa-gui.usage-events-visible-cols.v4');
|
||||
localStorage.removeItem('cpa-gui.usage-events-visible-cols.v5');
|
||||
localStorage.removeItem('cpa-gui.usage-events-col-widths.v2');
|
||||
localStorage.removeItem('cpa-gui.usage-events-col-widths.v3');
|
||||
document.documentElement.dataset.theme = params.get('theme') || 'light';
|
||||
|
||||
const tokens = {
|
||||
@@ -44,7 +46,7 @@ const record = (id: string, model: string, alias: string, response_model?: strin
|
||||
alias,
|
||||
...(response_model === undefined ? {} : { response_model }),
|
||||
reasoning_effort: 'high',
|
||||
endpoint: '/v1/responses',
|
||||
endpoint: 'POST /v1/responses',
|
||||
api_key_hash: 'ui-key',
|
||||
api_key_display: 'sk-ui',
|
||||
api_key_remark: 'UI fixture',
|
||||
|
||||
@@ -49,6 +49,23 @@ const fs = require('node:fs');
|
||||
assert.equal(await page.evaluate(() => window.pluginsFixture.commands.some(call => call.command === 'open_core_logs_directory')), true);
|
||||
await noOverflow();
|
||||
|
||||
const searchInput = page.getByRole('searchbox');
|
||||
await searchInput.fill('qoder');
|
||||
const focusedSearch = await searchInput.evaluate(input => ({
|
||||
outline: getComputedStyle(input).outlineStyle,
|
||||
shadow: getComputedStyle(input).boxShadow,
|
||||
containerShadow: getComputedStyle(input.parentElement).boxShadow,
|
||||
}));
|
||||
assert.equal(focusedSearch.outline, 'none', 'the input must not draw a second focus ring inside the search field');
|
||||
assert.equal(focusedSearch.shadow, 'none');
|
||||
assert.notEqual(focusedSearch.containerShadow, 'none', 'the outer search field retains a visible focus indicator');
|
||||
await page.keyboard.press('Tab');
|
||||
assert.equal(await page.locator('.plugin-search-clear').evaluate(button => button === document.activeElement), true);
|
||||
await page.keyboard.press('Enter');
|
||||
assert.equal(await searchInput.inputValue(), '');
|
||||
assert.equal(await searchInput.evaluate(input => input === document.activeElement), true, 'clearing returns focus to search');
|
||||
assert.equal(await page.locator('.plugin-card').count(), 4, 'clearing restores the unfiltered list');
|
||||
|
||||
await card('kiro').getByRole('button', { name: 'Find in store', exact: true }).click();
|
||||
await card('Kiro').getByRole('button', { name: 'Install', exact: true }).waitFor();
|
||||
assert.equal(await tab('Plugin store').getAttribute('aria-current'), 'page');
|
||||
@@ -177,6 +194,9 @@ const fs = require('node:fs');
|
||||
if (process.env.PLUGIN_SCREENSHOT_DIR) {
|
||||
fs.mkdirSync(process.env.PLUGIN_SCREENSHOT_DIR, { recursive: true });
|
||||
await page.screenshot({ path: path.join(process.env.PLUGIN_SCREENSHOT_DIR, `plugins-${locale}-${width}.png`), fullPage: true });
|
||||
await page.getByRole('searchbox').fill('qoder');
|
||||
await page.screenshot({ path: path.join(process.env.PLUGIN_SCREENSHOT_DIR, `plugins-search-${locale}-${width}.png`), fullPage: true });
|
||||
await page.locator('.plugin-search-clear').click();
|
||||
}
|
||||
await card('Community analytics').getByRole('button', { name: locale === 'en' ? 'Install' : '安装', exact: true }).click();
|
||||
await dialog().waitFor();
|
||||
|
||||
@@ -89,6 +89,9 @@ function parseCsv(text) {
|
||||
await open('zh-CN');
|
||||
assert.equal(await modelCells().count(), 9, 'Every fixture record renders a model cell');
|
||||
const zhDetails = await modelDetails();
|
||||
assert.equal(await page.locator('.usage-th-effort').count(), 1, 'Migration enables reasoning effort for existing layouts');
|
||||
assert.equal(await page.locator('.usage-td-request').first().textContent(), '/v1/responses');
|
||||
assert.equal(await page.locator('.usage-td-request').first().getAttribute('title'), '/v1/responses');
|
||||
assert.match(await modelCells().first().getAttribute('title'), /response_model.*上游声明/);
|
||||
assert.deepEqual(await page.locator('.usage-events-table th').evaluateAll(cells => cells.slice(0, 2).map(cell => cell.className.split(' ')[0])), ['usage-th-time', 'usage-th-provider']);
|
||||
assert.equal(await page.locator('.usage-td-provider strong').first().textContent(), 'Codex');
|
||||
|
||||
Reference in new issue
Block a user