onbuzz 6.3.1 → 6.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -252,11 +252,37 @@ describe('param-quirk ladder (backend path)', () => {
|
|
|
252
252
|
expect.stringContaining('MODEL QUIRK'), expect.anything());
|
|
253
253
|
});
|
|
254
254
|
|
|
255
|
-
test('
|
|
255
|
+
test('the SAME rejection after the strip → exactly two attempts, then throw (never an infinite ladder)', async () => {
|
|
256
256
|
const svc = makeService();
|
|
257
|
-
const calls = mockBackendRejecting(GPT56, () => true); // always rejects
|
|
257
|
+
const calls = mockBackendRejecting(GPT56, () => true); // always rejects on temperature
|
|
258
258
|
await expect(svc.sendMessage('gpt-5.6-sol', [{ role: 'user', content: 'hi' }], { ...KEYED }))
|
|
259
259
|
.rejects.toThrow();
|
|
260
|
-
expect(calls).toHaveLength(2); //
|
|
260
|
+
expect(calls).toHaveLength(2); // temperature stripped once; a second identical rejection learns nothing → throw
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test('gpt-6-astra fixture: two DIFFERENT rejections in one request (forced reasoning_effort, then temperature) → third attempt succeeds', async () => {
|
|
264
|
+
const svc = makeService();
|
|
265
|
+
const ASTRA = "400 Function tools with reasoning_effort are not supported for gpt-6-astra in /v1/chat/completions. To use function tools, use /v1/responses or set reasoning_effort to 'none'.";
|
|
266
|
+
const calls = [];
|
|
267
|
+
global.fetch = jest.fn(async (url, init) => {
|
|
268
|
+
const body = JSON.parse(init.body);
|
|
269
|
+
calls.push(body);
|
|
270
|
+
const reject = (message, param) => ({
|
|
271
|
+
ok: false, status: 400,
|
|
272
|
+
json: async () => ({ error: { message, param, code: 'unsupported_value' } }),
|
|
273
|
+
text: async () => JSON.stringify({ error: { message, param, code: 'unsupported_value' } }),
|
|
274
|
+
headers: { get: () => 'application/json' },
|
|
275
|
+
});
|
|
276
|
+
if (body.options?.reasoning_effort !== 'none') return reject(ASTRA, null);
|
|
277
|
+
if (body.options?.temperature !== undefined) return reject(GPT56, 'temperature');
|
|
278
|
+
return { ok: true, status: 200, json: async () => ({ content: 'ok' }), text: async () => 'ok', headers: { get: () => 'application/json' } };
|
|
279
|
+
});
|
|
280
|
+
const r = await svc.sendMessage('gpt-6-astra', [{ role: 'user', content: 'hi' }], { ...KEYED, temperature: 0.7 });
|
|
281
|
+
expect(r.content).toBe('ok');
|
|
282
|
+
expect(calls).toHaveLength(3);
|
|
283
|
+
expect(calls[2].options.reasoning_effort).toBe('none');
|
|
284
|
+
expect(calls[2].options.temperature).toBeUndefined();
|
|
285
|
+
const { getModelQuirkStore } = await import('../modelQuirks.js');
|
|
286
|
+
expect([...getModelQuirkStore().get('gpt-6-astra')].sort()).toEqual(['reasoning_effort=none', 'temperature']);
|
|
261
287
|
});
|
|
262
288
|
});
|
|
@@ -17,6 +17,9 @@ import {
|
|
|
17
17
|
COMPACTION_CONFIG
|
|
18
18
|
} from '../utilities/constants.js';
|
|
19
19
|
import { getModelQuirkStore, classifyParamError, classifyForcedValue, STRIPPABLE_PARAMS } from './modelQuirks.js';
|
|
20
|
+
|
|
21
|
+
/** Distinct parameter rejections a single request may learn from before giving up. */
|
|
22
|
+
const MAX_QUIRK_LEARNS_PER_REQUEST = 4;
|
|
20
23
|
import { getOllamaService, OLLAMA_MODEL_PREFIX } from './ollamaService.js';
|
|
21
24
|
import { getDaniService, DANI_MODEL_PREFIX } from './daniService.js';
|
|
22
25
|
import { SHARED_MEMORY_SCOPE } from './memoryService.js';
|
|
@@ -613,7 +616,11 @@ class AIService {
|
|
|
613
616
|
});
|
|
614
617
|
break;
|
|
615
618
|
} catch (err) {
|
|
616
|
-
|
|
619
|
+
// Each learned quirk changes the payload, so several distinct rejections
|
|
620
|
+
// may be resolved within ONE request (gpt-6-astra on the Responses API
|
|
621
|
+
// rejected `temperature`, then `reasoning_effort`: one learn per request
|
|
622
|
+
// cost two failed turns before the third succeeded).
|
|
623
|
+
if (quirkAttempt < MAX_QUIRK_LEARNS_PER_REQUEST && this._learnParamQuirk(model, err, payload.options)) continue;
|
|
617
624
|
throw err;
|
|
618
625
|
}
|
|
619
626
|
}
|
|
@@ -776,7 +783,11 @@ class AIService {
|
|
|
776
783
|
});
|
|
777
784
|
break;
|
|
778
785
|
} catch (err) {
|
|
779
|
-
|
|
786
|
+
// Each learned quirk changes the payload, so several distinct rejections
|
|
787
|
+
// may be resolved within ONE request (gpt-6-astra on the Responses API
|
|
788
|
+
// rejected `temperature`, then `reasoning_effort`: one learn per request
|
|
789
|
+
// cost two failed turns before the third succeeded).
|
|
790
|
+
if (quirkAttempt < MAX_QUIRK_LEARNS_PER_REQUEST && this._learnParamQuirk(model, err, payload.options)) continue;
|
|
780
791
|
throw err;
|
|
781
792
|
}
|
|
782
793
|
}
|