@yeaft/webchat-agent 1.0.424 → 1.0.425
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/local-runtime/version.json +1 -1
- package/local-runtime/web/app.bundle.js +4 -4
- package/local-runtime/web/app.bundle.js.gz +0 -0
- package/local-runtime/web/index.html +1 -1
- package/package.json +1 -1
- package/yeaft/effort.js +5 -5
- package/yeaft/engine.js +7 -6
- package/yeaft/llm/openai-responses.js +1 -1
- package/yeaft/models.js +39 -19
- package/yeaft/sessions/session-config.js +2 -2
- package/yeaft/web-bridge.js +1 -1
- package/yeaft/work-center/assignment.js +1 -1
- package/yeaft/work-center/workflow.js +1 -1
|
Binary file
|
package/package.json
CHANGED
package/yeaft/effort.js
CHANGED
|
@@ -61,7 +61,7 @@ export const SCENARIO_EFFORT = Object.freeze({
|
|
|
61
61
|
* Pick the effort level for a given query context.
|
|
62
62
|
*
|
|
63
63
|
* Decision order:
|
|
64
|
-
* 1. If userEffort is a valid Effort ('minimal'|'low'|'medium'|'high'|'xhigh'|'max'),
|
|
64
|
+
* 1. If userEffort is a valid Effort ('minimal'|'low'|'medium'|'high'|'xhigh'|'max'|'ultra'),
|
|
65
65
|
* return it unchanged. This is the explicit override path —
|
|
66
66
|
* `/max` prefix, Settings slider, or API caller.
|
|
67
67
|
* 2. If toolLoopTurns >= LONG_LOOP_TURN_THRESHOLD, upgrade the
|
|
@@ -74,7 +74,7 @@ export const SCENARIO_EFFORT = Object.freeze({
|
|
|
74
74
|
* already consumed in the current `query()` call.
|
|
75
75
|
* @param {unknown} [ctx.userEffort=null] — User-supplied override.
|
|
76
76
|
* Invalid values are ignored (fall through to scenario path).
|
|
77
|
-
* @returns {'minimal'|'low'|'medium'|'high'|'xhigh'|'max'} Resolved effort. Never null —
|
|
77
|
+
* @returns {'minimal'|'low'|'medium'|'high'|'xhigh'|'max'|'ultra'} Resolved effort. Never null —
|
|
78
78
|
* the adapter/router is responsible for dropping it when the
|
|
79
79
|
* feature flag is off or the model doesn't support thinking.
|
|
80
80
|
*/
|
|
@@ -97,7 +97,7 @@ export function pickEffort({ scenario = 'chat', toolLoopTurns = 0, userEffort =
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
|
-
* Parse a user prompt for `/max`, `/xhigh`, `/high`, `/medium`, `/low` prefix
|
|
100
|
+
* Parse a user prompt for `/ultra`, `/max`, `/xhigh`, `/high`, `/medium`, `/low` prefix
|
|
101
101
|
* commands. Returns `{ effort, cleanedPrompt }` where cleanedPrompt has
|
|
102
102
|
* the prefix (plus one trailing space) stripped.
|
|
103
103
|
*
|
|
@@ -108,11 +108,11 @@ export function pickEffort({ scenario = 'chat', toolLoopTurns = 0, userEffort =
|
|
|
108
108
|
* via `!` or `/skill:` instead to avoid collision.
|
|
109
109
|
*
|
|
110
110
|
* @param {string} prompt
|
|
111
|
-
* @returns {{ effort: 'low'|'medium'|'high'|'xhigh'|'max'|null, cleanedPrompt: string }}
|
|
111
|
+
* @returns {{ effort: 'low'|'medium'|'high'|'xhigh'|'max'|'ultra'|null, cleanedPrompt: string }}
|
|
112
112
|
*/
|
|
113
113
|
export function parseEffortPrefix(prompt) {
|
|
114
114
|
if (typeof prompt !== 'string') return { effort: null, cleanedPrompt: prompt };
|
|
115
|
-
const m = prompt.match(/^\/(max|xhigh|high|medium|low)(\s+|$)/);
|
|
115
|
+
const m = prompt.match(/^\/(ultra|max|xhigh|high|medium|low)(\s+|$)/);
|
|
116
116
|
if (!m) return { effort: null, cleanedPrompt: prompt };
|
|
117
117
|
const effort = m[1];
|
|
118
118
|
const cleanedPrompt = prompt.slice(m[0].length);
|
package/yeaft/engine.js
CHANGED
|
@@ -2046,9 +2046,9 @@ export class Engine {
|
|
|
2046
2046
|
* @param {string} params.prompt - The user prompt (required, non-empty).
|
|
2047
2047
|
* @param {Array} [params.messages] - Prior conversation messages.
|
|
2048
2048
|
* @param {AbortSignal} [params.signal] - Abort signal.
|
|
2049
|
-
* @param {'low'|'medium'|'high'|'max'|null} [params.userEffort] -
|
|
2049
|
+
* @param {'low'|'medium'|'high'|'xhigh'|'max'|'ultra'|null} [params.userEffort] -
|
|
2050
2050
|
* task-327b: explicit per-query effort override (from Settings or
|
|
2051
|
-
* API caller). `/max`/`/high`/`/medium`/`/low` prefixes in prompt
|
|
2051
|
+
* API caller). `/ultra`/`/max`/`/high`/`/medium`/`/low` prefixes in prompt
|
|
2052
2052
|
* also set this. Null/invalid → scenario decision tree decides.
|
|
2053
2053
|
* @param {string} [params.scenario='chat'] - task-327b: scenario tag
|
|
2054
2054
|
* forwarded to the effort decision tree. See effort.js
|
|
@@ -3031,10 +3031,11 @@ export class Engine {
|
|
|
3031
3031
|
allowRouterEscalate: thinkingCfg.allowRouterEscalate !== false,
|
|
3032
3032
|
});
|
|
3033
3033
|
// Only adopt the chain's choice when it strengthens the
|
|
3034
|
-
// baseline. We never weaken below pickEffort (e.g.
|
|
3035
|
-
// =
|
|
3036
|
-
// default
|
|
3037
|
-
if (
|
|
3034
|
+
// baseline. We never weaken below pickEffort (e.g. explicit
|
|
3035
|
+
// 'ultra' or consolidate='max' must not be downgraded by a VP
|
|
3036
|
+
// default or router plan).
|
|
3037
|
+
if (resolvedEffort !== 'ultra'
|
|
3038
|
+
&& (resolved.value === 'max' || (resolved.value === 'high' && resolvedEffort === 'low'))) {
|
|
3038
3039
|
resolvedEffort = resolved.value;
|
|
3039
3040
|
}
|
|
3040
3041
|
}
|
|
@@ -254,7 +254,7 @@ export class OpenAIResponsesAdapter extends LLMAdapter {
|
|
|
254
254
|
// ─── Streaming ──────────────────────────────────────────
|
|
255
255
|
|
|
256
256
|
/**
|
|
257
|
-
* @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
|
|
257
|
+
* @param {{ model: string, system: string, messages: import('./adapter.js').UnifiedMessage[], tools?: import('./adapter.js').UnifiedToolDef[], maxTokens?: number, effort?: 'minimal'|'low'|'medium'|'high'|'xhigh'|'max'|'ultra', effortSource?: 'user'|'auto', effortContext?: object, extraBody?: object, signal?: AbortSignal, onRawExchange?: ({rawRequest, rawResponse}) => void, onRequestStart?: () => void }} params
|
|
258
258
|
*
|
|
259
259
|
* NOTE on `extraBody`: any keys you spread here are merged verbatim into
|
|
260
260
|
* the wire body and — because the verbatim debug feature is intentionally
|
package/yeaft/models.js
CHANGED
|
@@ -34,9 +34,9 @@ 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'|'max'}
|
|
37
|
+
* 'openai-reasoning' → reasoning:{effort:'minimal'|'low'|'medium'|'high'|'xhigh'|'max'|'ultra'}
|
|
38
38
|
* 'none' (default) → parameter silently dropped by router
|
|
39
|
-
* @property {'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null} [defaultEffort] — adapter-level default
|
|
39
|
+
* @property {'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'ultra' | null} [defaultEffort] — adapter-level default
|
|
40
40
|
* when caller doesn't specify effort (null = no default / decision-tree decides).
|
|
41
41
|
* @property {number} [maxBudgetTokens] — task-327a: for anthropic protocol, the cap used when
|
|
42
42
|
* effort='max' (e.g. Opus 4 = 64K, Sonnet 4 = 32K). For openai-reasoning this field is unused
|
|
@@ -146,6 +146,7 @@ export const MODEL_REGISTRY = new Map([
|
|
|
146
146
|
supportsThinking: true,
|
|
147
147
|
thinkingProtocol: 'openai-reasoning',
|
|
148
148
|
defaultEffort: null,
|
|
149
|
+
effortOptions: ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],
|
|
149
150
|
}],
|
|
150
151
|
['gpt-4.1', {
|
|
151
152
|
provider: 'openai',
|
|
@@ -386,7 +387,7 @@ export function parseModelRef(ref) {
|
|
|
386
387
|
|
|
387
388
|
/**
|
|
388
389
|
* Valid effort levels accepted by Yeaft adapters.
|
|
389
|
-
* @typedef {'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'} Effort
|
|
390
|
+
* @typedef {'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'ultra'} Effort
|
|
390
391
|
*/
|
|
391
392
|
|
|
392
393
|
/**
|
|
@@ -410,7 +411,7 @@ export const ANTHROPIC_THINKING_BUDGETS = {
|
|
|
410
411
|
* translation. Unsupported values are dropped; the adapter MUST NOT error.
|
|
411
412
|
*
|
|
412
413
|
* @param {Effort} effort
|
|
413
|
-
* @returns {'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null}
|
|
414
|
+
* @returns {'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'ultra' | null}
|
|
414
415
|
*/
|
|
415
416
|
export function mapEffortToOpenAIReasoning(effort) {
|
|
416
417
|
if (!effort) return null;
|
|
@@ -421,12 +422,14 @@ export function mapEffortToOpenAIReasoning(effort) {
|
|
|
421
422
|
case 'high': return 'high';
|
|
422
423
|
case 'xhigh': return 'xhigh';
|
|
423
424
|
case 'max': return 'max';
|
|
425
|
+
case 'ultra': return 'ultra';
|
|
424
426
|
default: return null;
|
|
425
427
|
}
|
|
426
428
|
}
|
|
427
429
|
|
|
428
430
|
export const OPENAI_REASONING_EFFORT_OPTIONS = ['minimal', 'low', 'medium', 'high', 'xhigh'];
|
|
429
431
|
export const OPENAI_MAX_REASONING_EFFORT_OPTIONS = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
432
|
+
export const OPENAI_ULTRA_REASONING_EFFORT_OPTIONS = ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'];
|
|
430
433
|
export const ANTHROPIC_MANUAL_EFFORT_OPTIONS = ['low', 'medium', 'high'];
|
|
431
434
|
export const ANTHROPIC_ADAPTIVE_EFFORT_OPTIONS = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
432
435
|
export const ANTHROPIC_ADAPTIVE_MAX_EFFORT_OPTIONS = ['low', 'medium', 'high', 'max'];
|
|
@@ -442,7 +445,25 @@ export const ANTHROPIC_ADAPTIVE_MAX_EFFORT_OPTIONS = ['low', 'medium', 'high', '
|
|
|
442
445
|
// compatibility table explicitly supports `output_config` effort).
|
|
443
446
|
export const DEEPSEEK_REASONING_EFFORT_OPTIONS = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
444
447
|
|
|
445
|
-
const VALID_EFFORT_OPTIONS = new Set(['minimal', 'low', 'medium', 'high', 'xhigh', 'max']);
|
|
448
|
+
const VALID_EFFORT_OPTIONS = new Set(['minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'ultra']);
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* GPT models expose the provider-specific `ultra` tier starting at 5.5.
|
|
452
|
+
* Numeric comparison matters here: 5.10 is newer than 5.5.
|
|
453
|
+
*/
|
|
454
|
+
export function modelSupportsUltraEffort(model) {
|
|
455
|
+
const id = parseModelRef(model).modelId.toLowerCase();
|
|
456
|
+
const match = id.match(/^gpt-(\d+)(?:\.(\d+))?(?=$|[-.]|\[)/);
|
|
457
|
+
if (!match) return false;
|
|
458
|
+
const major = Number(match[1]);
|
|
459
|
+
const minor = Number(match[2] || 0);
|
|
460
|
+
return major > 5 || (major === 5 && minor >= 5);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function fenceUltraEffortOptions(model, options) {
|
|
464
|
+
if (!Array.isArray(options) || modelSupportsUltraEffort(model)) return options;
|
|
465
|
+
return options.filter(effort => effort !== 'ultra');
|
|
466
|
+
}
|
|
446
467
|
|
|
447
468
|
export function normalizeEffortOptions(options) {
|
|
448
469
|
if (!Array.isArray(options)) return null;
|
|
@@ -460,16 +481,14 @@ function inferThinkingCapability(model) {
|
|
|
460
481
|
const id = parseModelRef(model).modelId.toLowerCase();
|
|
461
482
|
if (!id) return null;
|
|
462
483
|
|
|
463
|
-
//
|
|
464
|
-
|
|
465
|
-
// Provider suffixes such as gpt-5.6-sol are variants of the same model family.
|
|
466
|
-
if (/^gpt-5\.6($|[-.])/.test(id)) {
|
|
484
|
+
// Provider suffixes are variants of the same GPT model family.
|
|
485
|
+
if (modelSupportsUltraEffort(model)) {
|
|
467
486
|
return {
|
|
468
487
|
supportsThinking: true,
|
|
469
488
|
thinkingProtocol: 'openai-reasoning',
|
|
470
489
|
defaultEffort: null,
|
|
471
490
|
maxBudgetTokens: null,
|
|
472
|
-
effortOptions:
|
|
491
|
+
effortOptions: OPENAI_ULTRA_REASONING_EFFORT_OPTIONS,
|
|
473
492
|
};
|
|
474
493
|
}
|
|
475
494
|
|
|
@@ -557,23 +576,24 @@ export function thinkingBudgetForEffort(model, effort) {
|
|
|
557
576
|
export function getThinkingCapability(model, context = {}) {
|
|
558
577
|
const info = MODEL_REGISTRY.get(model);
|
|
559
578
|
const modelId = parseModelRef(model).modelId;
|
|
560
|
-
const overrideOptions = normalizeEffortOptions(context.effortOptions);
|
|
579
|
+
const overrideOptions = fenceUltraEffortOptions(model, normalizeEffortOptions(context.effortOptions));
|
|
561
580
|
const overrideProtocol = context.thinkingProtocol || (
|
|
562
581
|
context.protocol === 'anthropic'
|
|
563
582
|
? (/^deepseek/i.test(modelId) ? 'anthropic-adaptive' : 'anthropic')
|
|
564
583
|
: context.protocol === 'openai-responses' ? 'openai-reasoning' : null
|
|
565
584
|
);
|
|
585
|
+
const hasExplicitThinking = info && Object.prototype.hasOwnProperty.call(info, 'supportsThinking');
|
|
586
|
+
const familyInferred = inferThinkingCapability(model);
|
|
566
587
|
if (context.supportsEffort === true || overrideOptions) {
|
|
567
588
|
return {
|
|
568
589
|
supportsThinking: true,
|
|
569
|
-
thinkingProtocol: overrideProtocol || 'openai-reasoning',
|
|
570
|
-
defaultEffort: context.defaultEffort ?? null,
|
|
571
|
-
maxBudgetTokens: context.maxBudgetTokens ?? null,
|
|
572
|
-
effortOptions: overrideOptions,
|
|
590
|
+
thinkingProtocol: overrideProtocol || info?.thinkingProtocol || familyInferred?.thinkingProtocol || 'openai-reasoning',
|
|
591
|
+
defaultEffort: context.defaultEffort ?? info?.defaultEffort ?? familyInferred?.defaultEffort ?? null,
|
|
592
|
+
maxBudgetTokens: context.maxBudgetTokens ?? info?.maxBudgetTokens ?? familyInferred?.maxBudgetTokens ?? null,
|
|
593
|
+
effortOptions: overrideOptions || info?.effortOptions || familyInferred?.effortOptions || null,
|
|
573
594
|
};
|
|
574
595
|
}
|
|
575
|
-
|
|
576
|
-
let inferred = hasExplicitThinking ? null : inferThinkingCapability(model);
|
|
596
|
+
let inferred = hasExplicitThinking ? null : familyInferred;
|
|
577
597
|
if (context.protocol === 'openai-responses' && !inferred && /^deepseek/i.test(parseModelRef(model).modelId)) {
|
|
578
598
|
inferred = {
|
|
579
599
|
supportsThinking: true,
|
|
@@ -608,7 +628,7 @@ export function getThinkingCapability(model, context = {}) {
|
|
|
608
628
|
thinkingProtocol: info?.thinkingProtocol || inferred?.thinkingProtocol || 'none',
|
|
609
629
|
defaultEffort: info?.defaultEffort ?? inferred?.defaultEffort ?? null,
|
|
610
630
|
maxBudgetTokens: info?.maxBudgetTokens ?? inferred?.maxBudgetTokens ?? null,
|
|
611
|
-
effortOptions: (info?.effortOptions || inferred?.effortOptions || null),
|
|
631
|
+
effortOptions: fenceUltraEffortOptions(model, info?.effortOptions || inferred?.effortOptions || null),
|
|
612
632
|
};
|
|
613
633
|
}
|
|
614
634
|
|
|
@@ -633,7 +653,7 @@ export function modelSupportsEffort(model, context = {}) {
|
|
|
633
653
|
* @returns {Effort | null}
|
|
634
654
|
*/
|
|
635
655
|
export function normalizeEffort(effort) {
|
|
636
|
-
if (effort === 'minimal' || effort === 'low' || effort === 'medium' || effort === 'high' || effort === 'xhigh' || effort === 'max') {
|
|
656
|
+
if (effort === 'minimal' || effort === 'low' || effort === 'medium' || effort === 'high' || effort === 'xhigh' || effort === 'max' || effort === 'ultra') {
|
|
637
657
|
return effort;
|
|
638
658
|
}
|
|
639
659
|
return null;
|
|
@@ -28,7 +28,7 @@ const CONFIG_FILE = 'config.json';
|
|
|
28
28
|
const MODEL_SOURCE_EXPLICIT = 'explicit';
|
|
29
29
|
const WRITABLE_KEYS = new Set(['model', 'modelEffort']);
|
|
30
30
|
const STORED_KEYS = new Set([...WRITABLE_KEYS, 'modelSource']);
|
|
31
|
-
const ALLOWED_EFFORTS = new Set(['minimal', 'low', 'medium', 'high', 'xhigh', 'max']);
|
|
31
|
+
const ALLOWED_EFFORTS = new Set(['minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'ultra']);
|
|
32
32
|
|
|
33
33
|
export class SessionConfigError extends Error {
|
|
34
34
|
constructor(code, message) {
|
|
@@ -99,7 +99,7 @@ export function validateSessionConfig(cfg) {
|
|
|
99
99
|
}
|
|
100
100
|
if ('modelEffort' in cfg && cfg.modelEffort !== null && cfg.modelEffort !== undefined && cfg.modelEffort !== '') {
|
|
101
101
|
if (typeof cfg.modelEffort !== 'string' || !ALLOWED_EFFORTS.has(cfg.modelEffort.trim())) {
|
|
102
|
-
throw new SessionConfigError('invalid_model_effort', 'modelEffort must be minimal, low, medium, high, xhigh, or
|
|
102
|
+
throw new SessionConfigError('invalid_model_effort', 'modelEffort must be minimal, low, medium, high, xhigh, max, or ultra');
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
}
|
package/yeaft/web-bridge.js
CHANGED
|
@@ -1163,7 +1163,7 @@ const ASK_USER_TIMEOUT_MS = 10 * 60_000;
|
|
|
1163
1163
|
|
|
1164
1164
|
function isHighReasoningEffort(effort) {
|
|
1165
1165
|
const value = typeof effort === 'string' ? effort.trim().toLowerCase() : '';
|
|
1166
|
-
return value === 'high' || value === 'xhigh' || value === 'max';
|
|
1166
|
+
return value === 'high' || value === 'xhigh' || value === 'max' || value === 'ultra';
|
|
1167
1167
|
}
|
|
1168
1168
|
|
|
1169
1169
|
function queryTimeoutMsForSessionConfig(config = null) {
|
|
@@ -143,7 +143,7 @@ export function resolveWorkItemModel(config, vp, rawPolicy) {
|
|
|
143
143
|
throw policyError(`Configured Work Center model is unavailable: ${model}`);
|
|
144
144
|
}
|
|
145
145
|
const effortOptions = Array.isArray(available?.effortOptions) ? available.effortOptions : [];
|
|
146
|
-
const effortOrder = ['minimal', 'low', 'medium', 'high', 'xhigh', 'max'];
|
|
146
|
+
const effortOrder = ['minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'ultra'];
|
|
147
147
|
const requestedIndex = effortOrder.indexOf(policy.effort);
|
|
148
148
|
const effort = !policy.effort || effortOptions.length === 0
|
|
149
149
|
? null
|
|
@@ -21,7 +21,7 @@ export const BUILT_IN_ACTION_TYPES = Object.freeze([
|
|
|
21
21
|
const STAGE_TYPES = new Set(BUILT_IN_ACTION_TYPES);
|
|
22
22
|
const ASSIGNMENT_MODES = new Set(['auto', 'pool', 'fixed', 'planned']);
|
|
23
23
|
const MODEL_MODES = new Set(['inherit', 'primary', 'fast', 'specific']);
|
|
24
|
-
const MODEL_EFFORTS = new Set(['minimal', 'low', 'medium', 'high', 'xhigh', 'max']);
|
|
24
|
+
const MODEL_EFFORTS = new Set(['minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'ultra']);
|
|
25
25
|
const WORKSPACE_MODES = new Set(['shared', 'read', 'isolated-write', 'integrate']);
|
|
26
26
|
const HIGH_EFFORT_ACTION_TYPES = new Set(['triage', 'research', 'design', 'diagnose', 'review']);
|
|
27
27
|
const ACTION_CONTEXT_QUOTE_MAX_BYTES = 8 * 1024;
|