Fix responses compact fallback handling (#426)
* fix route drag overlay alignment * fix(web): address route drag review comments * fix route card review follow-up * Fix responses compact fallback handling * Fix compact endpoint candidate typing * Tighten compact fallback matcher
This commit is contained in:
@@ -344,6 +344,7 @@ export type RuntimeSettingsPayload = {
|
||||
systemProxyUrl?: string;
|
||||
modelAvailabilityProbeEnabled?: boolean;
|
||||
codexUpstreamWebsocketEnabled?: boolean;
|
||||
responsesCompactFallbackToResponsesEnabled?: boolean;
|
||||
disableCrossProtocolFallback?: boolean;
|
||||
proxySessionChannelConcurrencyLimit?: number;
|
||||
proxySessionChannelQueueWaitMs?: number;
|
||||
|
||||
@@ -62,6 +62,7 @@ type RuntimeSettings = {
|
||||
logCleanupRetentionDays: number;
|
||||
modelAvailabilityProbeEnabled: boolean;
|
||||
codexUpstreamWebsocketEnabled: boolean;
|
||||
responsesCompactFallbackToResponsesEnabled: boolean;
|
||||
disableCrossProtocolFallback: boolean;
|
||||
proxySessionChannelConcurrencyLimit: number;
|
||||
proxySessionChannelQueueWaitMs: number;
|
||||
@@ -241,6 +242,7 @@ export default function Settings() {
|
||||
logCleanupRetentionDays: 30,
|
||||
modelAvailabilityProbeEnabled: false,
|
||||
codexUpstreamWebsocketEnabled: false,
|
||||
responsesCompactFallbackToResponsesEnabled: false,
|
||||
disableCrossProtocolFallback: false,
|
||||
proxySessionChannelConcurrencyLimit: 2,
|
||||
proxySessionChannelQueueWaitMs: 1500,
|
||||
@@ -488,6 +490,7 @@ export default function Settings() {
|
||||
: 30,
|
||||
modelAvailabilityProbeEnabled: !!runtimeInfo.modelAvailabilityProbeEnabled,
|
||||
codexUpstreamWebsocketEnabled: !!runtimeInfo.codexUpstreamWebsocketEnabled,
|
||||
responsesCompactFallbackToResponsesEnabled: !!runtimeInfo.responsesCompactFallbackToResponsesEnabled,
|
||||
disableCrossProtocolFallback: !!runtimeInfo.disableCrossProtocolFallback,
|
||||
proxySessionChannelConcurrencyLimit: Number(runtimeInfo.proxySessionChannelConcurrencyLimit) >= 0
|
||||
? Math.trunc(Number(runtimeInfo.proxySessionChannelConcurrencyLimit))
|
||||
@@ -709,6 +712,7 @@ export default function Settings() {
|
||||
try {
|
||||
const res = await api.updateRuntimeSettings({
|
||||
codexUpstreamWebsocketEnabled: runtime.codexUpstreamWebsocketEnabled,
|
||||
responsesCompactFallbackToResponsesEnabled: runtime.responsesCompactFallbackToResponsesEnabled,
|
||||
proxySessionChannelConcurrencyLimit: runtime.proxySessionChannelConcurrencyLimit,
|
||||
proxySessionChannelQueueWaitMs: runtime.proxySessionChannelQueueWaitMs,
|
||||
});
|
||||
@@ -717,6 +721,9 @@ export default function Settings() {
|
||||
codexUpstreamWebsocketEnabled: typeof res?.codexUpstreamWebsocketEnabled === 'boolean'
|
||||
? res.codexUpstreamWebsocketEnabled
|
||||
: prev.codexUpstreamWebsocketEnabled,
|
||||
responsesCompactFallbackToResponsesEnabled: typeof res?.responsesCompactFallbackToResponsesEnabled === 'boolean'
|
||||
? res.responsesCompactFallbackToResponsesEnabled
|
||||
: prev.responsesCompactFallbackToResponsesEnabled,
|
||||
proxySessionChannelConcurrencyLimit: Number(res?.proxySessionChannelConcurrencyLimit) >= 0
|
||||
? Math.trunc(Number(res.proxySessionChannelConcurrencyLimit))
|
||||
: prev.proxySessionChannelConcurrencyLimit,
|
||||
@@ -1439,6 +1446,14 @@ export default function Settings() {
|
||||
/>
|
||||
允许 metapi 到 Codex 上游使用 WebSocket
|
||||
</label>
|
||||
<label style={{ display: 'inline-flex', alignItems: 'center', gap: 8, fontSize: 13, color: 'var(--color-text-secondary)', marginBottom: 14 }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={runtime.responsesCompactFallbackToResponsesEnabled}
|
||||
onChange={(e) => setRuntime((prev) => ({ ...prev, responsesCompactFallbackToResponsesEnabled: e.target.checked }))}
|
||||
/>
|
||||
Compact 明确不支持时回退到普通 Responses
|
||||
</label>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1fr', gap: 12, marginBottom: 10 }}>
|
||||
<div>
|
||||
<div style={{ fontSize: 12, color: 'var(--color-text-muted)', marginBottom: 6 }}>会话通道并发上限</div>
|
||||
@@ -1481,6 +1496,9 @@ export default function Settings() {
|
||||
<div style={{ fontSize: 12, color: 'var(--color-text-muted)', marginBottom: 12, lineHeight: 1.7 }}>
|
||||
这组 lease 只作用于能识别稳定 `session_id` 的会话型请求;没有稳定会话标识的普通请求不会进入这个池。
|
||||
</div>
|
||||
<div style={{ fontSize: 12, color: 'var(--color-text-muted)', marginBottom: 12, lineHeight: 1.7 }}>
|
||||
默认只走原生 `/responses/compact`。开启回退后,只有当上游明确返回 compact 不支持或路径不存在时,才会退回普通 `/responses`。
|
||||
</div>
|
||||
<div>
|
||||
<button onClick={saveProxyTransportSettings} disabled={savingProxyTransport} className="btn btn-primary">
|
||||
{savingProxyTransport ? <><span className="spinner spinner-sm" style={{ borderTopColor: 'white', borderColor: 'rgba(255,255,255,0.3)' }} /> 保存中...</> : '保存传输与并发'}
|
||||
|
||||
@@ -56,6 +56,7 @@ describe('Settings proxy transport', () => {
|
||||
logCleanupProgramLogsEnabled: true,
|
||||
logCleanupRetentionDays: 14,
|
||||
codexUpstreamWebsocketEnabled: false,
|
||||
responsesCompactFallbackToResponsesEnabled: false,
|
||||
proxySessionChannelConcurrencyLimit: 4,
|
||||
proxySessionChannelQueueWaitMs: 3200,
|
||||
routingFallbackUnitCost: 1,
|
||||
@@ -74,6 +75,7 @@ describe('Settings proxy transport', () => {
|
||||
apiMock.updateRuntimeSettings.mockResolvedValue({
|
||||
success: true,
|
||||
codexUpstreamWebsocketEnabled: true,
|
||||
responsesCompactFallbackToResponsesEnabled: true,
|
||||
proxySessionChannelConcurrencyLimit: 6,
|
||||
proxySessionChannelQueueWaitMs: 4200,
|
||||
});
|
||||
@@ -104,6 +106,12 @@ describe('Settings proxy transport', () => {
|
||||
));
|
||||
const websocketToggle = websocketToggleLabel.findByType('input');
|
||||
expect(websocketToggle.props.checked).toBe(false);
|
||||
const compactFallbackToggleLabel = root.root.find((node) => (
|
||||
node.type === 'label'
|
||||
&& collectText(node).includes('Compact 明确不支持时回退到普通 Responses')
|
||||
));
|
||||
const compactFallbackToggle = compactFallbackToggleLabel.findByType('input');
|
||||
expect(compactFallbackToggle.props.checked).toBe(false);
|
||||
|
||||
const concurrencyInput = root.root.find((node) => (
|
||||
node.type === 'input'
|
||||
@@ -118,6 +126,7 @@ describe('Settings proxy transport', () => {
|
||||
|
||||
await act(async () => {
|
||||
websocketToggle.props.onChange({ target: { checked: true } });
|
||||
compactFallbackToggle.props.onChange({ target: { checked: true } });
|
||||
concurrencyInput.props.onChange({ target: { value: '6' } });
|
||||
queueWaitInput.props.onChange({ target: { value: '4200' } });
|
||||
});
|
||||
@@ -134,6 +143,7 @@ describe('Settings proxy transport', () => {
|
||||
|
||||
expect(apiMock.updateRuntimeSettings).toHaveBeenCalledWith({
|
||||
codexUpstreamWebsocketEnabled: true,
|
||||
responsesCompactFallbackToResponsesEnabled: true,
|
||||
proxySessionChannelConcurrencyLimit: 6,
|
||||
proxySessionChannelQueueWaitMs: 4200,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user