@yeaft/webchat-agent 1.0.156 → 1.0.157
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 +1 -1
- package/yeaft/llm/openai-responses.js +13 -11
- package/yeaft/models.js +20 -5
package/package.json
CHANGED
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
} from './adapter.js';
|
|
42
42
|
import {
|
|
43
43
|
normalizeEffort,
|
|
44
|
+
getModelEffortOptions,
|
|
44
45
|
getThinkingCapability,
|
|
45
46
|
mapEffortToOpenAIReasoning,
|
|
46
47
|
} from '../models.js';
|
|
@@ -57,10 +58,9 @@ function thinkingV1Enabled() {
|
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
/**
|
|
60
|
-
* Translate a normalised effort
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* adaptive efforts must be dropped, not downgraded.
|
|
61
|
+
* Translate a normalised effort into the OpenAI Responses `reasoning.effort`
|
|
62
|
+
* field. Model capability filtering happens at the call site because `max` is
|
|
63
|
+
* supported by GPT-5.6 but not by older OpenAI reasoning models.
|
|
64
64
|
*/
|
|
65
65
|
function effortForResponses(effort) {
|
|
66
66
|
return mapEffortToOpenAIReasoning(effort);
|
|
@@ -248,7 +248,7 @@ export class OpenAIResponsesAdapter extends LLMAdapter {
|
|
|
248
248
|
// ─── Streaming ──────────────────────────────────────────
|
|
249
249
|
|
|
250
250
|
/**
|
|
251
|
-
* @param {{ model: string, system: string, messages: import('./adapter.js').UnifiedMessage[], tools?: import('./adapter.js').UnifiedToolDef[], maxTokens?: number, effort?: 'minimal'|'low'|'medium'|'high'|'xhigh'|'max', effortSource?: 'user'|'auto', extraBody?: object, signal?: AbortSignal, onRawExchange?: ({rawRequest, rawResponse}) => void }} params
|
|
251
|
+
* @param {{ model: string, system: string, messages: import('./adapter.js').UnifiedMessage[], tools?: import('./adapter.js').UnifiedToolDef[], maxTokens?: number, effort?: 'minimal'|'low'|'medium'|'high'|'xhigh'|'max', effortSource?: 'user'|'auto', effortContext?: object, extraBody?: object, signal?: AbortSignal, onRawExchange?: ({rawRequest, rawResponse}) => void, onRequestStart?: () => void }} params
|
|
252
252
|
*
|
|
253
253
|
* NOTE on `extraBody`: any keys you spread here are merged verbatim into
|
|
254
254
|
* the wire body and — because the verbatim debug feature is intentionally
|
|
@@ -257,7 +257,7 @@ export class OpenAIResponsesAdapter extends LLMAdapter {
|
|
|
257
257
|
* `api-key` headers are auto-redacted (see `redactRawRequest` in
|
|
258
258
|
* `adapter.js`); request-body fields are caller-controlled.
|
|
259
259
|
*/
|
|
260
|
-
async *stream({ model, system, messages, tools, maxTokens = 16384, effort, effortSource, extraBody, signal, onRawExchange, onRequestStart }) {
|
|
260
|
+
async *stream({ model, system, messages, tools, maxTokens = 16384, effort, effortSource, effortContext = {}, extraBody, signal, onRawExchange, onRequestStart }) {
|
|
261
261
|
if (signal?.aborted) throw new LLMAbortError();
|
|
262
262
|
|
|
263
263
|
const body = {
|
|
@@ -276,8 +276,9 @@ export class OpenAIResponsesAdapter extends LLMAdapter {
|
|
|
276
276
|
// Unknown / unsupported models silently drop the field.
|
|
277
277
|
const normEffort = normalizeEffort(effort);
|
|
278
278
|
if ((thinkingV1Enabled() || effortSource === 'user') && normEffort) {
|
|
279
|
-
const cap = getThinkingCapability(model);
|
|
280
|
-
|
|
279
|
+
const cap = getThinkingCapability(model, effortContext);
|
|
280
|
+
const supportedEfforts = getModelEffortOptions(model, effortContext);
|
|
281
|
+
if (cap.supportsThinking && cap.thinkingProtocol === 'openai-reasoning' && supportedEfforts.includes(normEffort)) {
|
|
281
282
|
const wireEffort = effortForResponses(normEffort);
|
|
282
283
|
if (wireEffort) body.reasoning = { effort: wireEffort };
|
|
283
284
|
}
|
|
@@ -517,7 +518,7 @@ export class OpenAIResponsesAdapter extends LLMAdapter {
|
|
|
517
518
|
* expose them, mirror the stream() instrumentation. Parity with
|
|
518
519
|
* anthropic.js's `call()`.
|
|
519
520
|
*/
|
|
520
|
-
async call({ model, system, messages, maxTokens = 4096, effort, effortSource, extraBody, signal, onRequestStart }) {
|
|
521
|
+
async call({ model, system, messages, maxTokens = 4096, effort, effortSource, effortContext = {}, extraBody, signal, onRequestStart }) {
|
|
521
522
|
if (signal?.aborted) throw new LLMAbortError();
|
|
522
523
|
|
|
523
524
|
const body = {
|
|
@@ -530,8 +531,9 @@ export class OpenAIResponsesAdapter extends LLMAdapter {
|
|
|
530
531
|
// Mirror stream()'s thinking injection for non-streaming side queries.
|
|
531
532
|
const normEffort = normalizeEffort(effort);
|
|
532
533
|
if ((thinkingV1Enabled() || effortSource === 'user') && normEffort) {
|
|
533
|
-
const cap = getThinkingCapability(model);
|
|
534
|
-
|
|
534
|
+
const cap = getThinkingCapability(model, effortContext);
|
|
535
|
+
const supportedEfforts = getModelEffortOptions(model, effortContext);
|
|
536
|
+
if (cap.supportsThinking && cap.thinkingProtocol === 'openai-reasoning' && supportedEfforts.includes(normEffort)) {
|
|
535
537
|
const wireEffort = effortForResponses(normEffort);
|
|
536
538
|
if (wireEffort) body.reasoning = { effort: wireEffort };
|
|
537
539
|
}
|
package/yeaft/models.js
CHANGED
|
@@ -34,7 +34,7 @@ import { lookupModelLimitSync } from './llm/models-dev.js';
|
|
|
34
34
|
* @property {'anthropic' | 'anthropic-adaptive' | 'openai-reasoning' | 'none'} [thinkingProtocol] — task-327a:
|
|
35
35
|
* 'anthropic' → thinking:{type:'enabled', budget_tokens:N}
|
|
36
36
|
* 'anthropic-adaptive' → thinking:{type:'adaptive'} + output_config:{effort}
|
|
37
|
-
* 'openai-reasoning' → reasoning:{effort:'minimal'|'low'|'medium'|'high'|'xhigh'}
|
|
37
|
+
* 'openai-reasoning' → reasoning:{effort:'minimal'|'low'|'medium'|'high'|'xhigh'|'max'}
|
|
38
38
|
* 'none' (default) → parameter silently dropped by router
|
|
39
39
|
* @property {'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null} [defaultEffort] — adapter-level default
|
|
40
40
|
* when caller doesn't specify effort (null = no default / decision-tree decides).
|
|
@@ -405,12 +405,12 @@ export const ANTHROPIC_THINKING_BUDGETS = {
|
|
|
405
405
|
};
|
|
406
406
|
|
|
407
407
|
/**
|
|
408
|
-
* Map a Yeaft effort level to the OpenAI reasoning.effort enum.
|
|
409
|
-
*
|
|
410
|
-
*
|
|
408
|
+
* Map a Yeaft effort level to the OpenAI reasoning.effort enum. Supported
|
|
409
|
+
* values are model-dependent; capability filtering happens before this wire
|
|
410
|
+
* translation. Unsupported values are dropped; the adapter MUST NOT error.
|
|
411
411
|
*
|
|
412
412
|
* @param {Effort} effort
|
|
413
|
-
* @returns {'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | null}
|
|
413
|
+
* @returns {'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null}
|
|
414
414
|
*/
|
|
415
415
|
export function mapEffortToOpenAIReasoning(effort) {
|
|
416
416
|
if (!effort) return null;
|
|
@@ -420,11 +420,13 @@ export function mapEffortToOpenAIReasoning(effort) {
|
|
|
420
420
|
case 'medium': return 'medium';
|
|
421
421
|
case 'high': return 'high';
|
|
422
422
|
case 'xhigh': return 'xhigh';
|
|
423
|
+
case 'max': return 'max';
|
|
423
424
|
default: return null;
|
|
424
425
|
}
|
|
425
426
|
}
|
|
426
427
|
|
|
427
428
|
export const OPENAI_REASONING_EFFORT_OPTIONS = ['minimal', 'low', 'medium', 'high', 'xhigh'];
|
|
429
|
+
export const OPENAI_MAX_REASONING_EFFORT_OPTIONS = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
428
430
|
export const ANTHROPIC_MANUAL_EFFORT_OPTIONS = ['low', 'medium', 'high'];
|
|
429
431
|
export const ANTHROPIC_ADAPTIVE_EFFORT_OPTIONS = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
430
432
|
export const ANTHROPIC_ADAPTIVE_MAX_EFFORT_OPTIONS = ['low', 'medium', 'high', 'max'];
|
|
@@ -454,6 +456,19 @@ function inferThinkingCapability(model) {
|
|
|
454
456
|
const id = parseModelRef(model).modelId.toLowerCase();
|
|
455
457
|
if (!id) return null;
|
|
456
458
|
|
|
459
|
+
// GPT-5.6 adds the model-specific `max` tier. Keep this ahead of the generic
|
|
460
|
+
// GPT inference so older OpenAI models do not advertise a value they reject.
|
|
461
|
+
// Provider suffixes such as gpt-5.6-sol are variants of the same model family.
|
|
462
|
+
if (/^gpt-5\.6($|[-.])/.test(id)) {
|
|
463
|
+
return {
|
|
464
|
+
supportsThinking: true,
|
|
465
|
+
thinkingProtocol: 'openai-reasoning',
|
|
466
|
+
defaultEffort: null,
|
|
467
|
+
maxBudgetTokens: null,
|
|
468
|
+
effortOptions: OPENAI_MAX_REASONING_EFFORT_OPTIONS,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
|
|
457
472
|
if (/^(gpt-5|o1|o3|o4|chatgpt-|codex-)/.test(id)) {
|
|
458
473
|
return { supportsThinking: true, thinkingProtocol: 'openai-reasoning', defaultEffort: null, maxBudgetTokens: null };
|
|
459
474
|
}
|