@yeaft/webchat-agent 1.0.551 → 1.0.552

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "1.0.551",
3
+ "version": "1.0.552",
4
4
  "description": "Remote worker agent for Yeaft Web Code Agent — connects the native Yeaft engine, CLI providers, and workbench tools",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -162,17 +162,21 @@ function availableModel(config, ref) {
162
162
  if (models.length === 0) return null;
163
163
  const parsed = parseModelRef(ref);
164
164
  return models.find(model => model.ref === ref)
165
- || models.find(model => !parsed.providerName && model.id === parsed.modelId)
165
+ || models.find(model => model.id === parsed.modelId
166
+ && (!parsed.providerName || model.provider === parsed.providerName))
166
167
  || null;
167
168
  }
168
169
 
169
- export function resolveWorkItemModel(config, vp, rawPolicy) {
170
+ export function resolveWorkItemModel(config, vp, rawPolicy, modelTags = {}) {
170
171
  const policy = normalizeModelPolicy(rawPolicy);
171
172
  let model;
172
173
  let source;
173
174
  if (policy.mode === 'specific') {
174
175
  model = policy.model;
175
176
  source = 'stage-specific';
177
+ } else if (policy.mode === 'tag') {
178
+ model = modelTags[policy.tag] || null;
179
+ source = `tag:${policy.tag}`;
176
180
  } else if (policy.mode === 'primary') {
177
181
  model = config.primaryModel || config.model || null;
178
182
  source = 'agent-primary';
@@ -191,8 +195,9 @@ export function resolveWorkItemModel(config, vp, rawPolicy) {
191
195
  if (Array.isArray(config.availableModels) && config.availableModels.length > 0 && !available) {
192
196
  throw policyError(`Configured Work Center model is unavailable: ${model}`);
193
197
  }
198
+ if (policy.mode === 'tag' && available?.ref) model = available.ref;
194
199
  const effortOptions = Array.isArray(available?.effortOptions) ? available.effortOptions : [];
195
- const effortOrder = ['minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'ultra'];
200
+ const effortOrder = ['medium', 'high', 'xhigh'];
196
201
  const requestedIndex = effortOrder.indexOf(policy.effort);
197
202
  const effort = !policy.effort || effortOptions.length === 0
198
203
  ? null
@@ -20,7 +20,10 @@ import { isDynamicWorkItem } from './execution-mode.js';
20
20
  import { applyCoordinatorReplan } from './plan-mutation.js';
21
21
  import { buildWorkItemAttachmentContext } from './attachments.js';
22
22
  import { sanitizeDiagnosticText } from './debug-projection.js';
23
- import { generatedActionGraphRules } from './workflow.js';
23
+ import {
24
+ DEFAULT_WORK_CENTER_MODEL_TAGS,
25
+ generatedActionGraphRules,
26
+ } from './workflow.js';
24
27
  import { workItemCapabilityContext } from './capabilities.js';
25
28
 
26
29
  const COORDINATOR_MAX_REPLY_CHARS = 8_000;
@@ -900,7 +903,12 @@ export class WorkItemCoordinator {
900
903
  ...(settings?.modelPolicy || {}),
901
904
  effort: settings?.actionModelPolicies?.triage?.effort || settings?.modelPolicy?.effort || 'high',
902
905
  };
903
- resolved = resolveWorkItemModel(runtime.config, assignment.vp, coordinatorPolicy);
906
+ resolved = resolveWorkItemModel(
907
+ runtime.config,
908
+ assignment.vp,
909
+ coordinatorPolicy,
910
+ settings?.modelTags || DEFAULT_WORK_CENTER_MODEL_TAGS,
911
+ );
904
912
  } catch (error) {
905
913
  throw coordinatorExecutionError(error, 'selection', language);
906
914
  }
@@ -1,5 +1,5 @@
1
1
  import { resolveWorkItemModel, selectWorkItemVp } from './assignment.js';
2
- import { resolveWorkflowSnapshot } from './workflow.js';
2
+ import { normalizeWorkCenterSettings, resolveWorkflowSnapshot } from './workflow.js';
3
3
 
4
4
  function publicVp(vp) {
5
5
  return vp ? {
@@ -17,6 +17,7 @@ function publicVp(vp) {
17
17
  }
18
18
 
19
19
  export function previewWorkCenterPlan({ settings, workflowId, stageOverrides, registry, config }) {
20
+ const normalizedSettings = normalizeWorkCenterSettings(settings);
20
21
  const workflow = resolveWorkflowSnapshot(settings, workflowId, stageOverrides);
21
22
  const vps = registry.listVps();
22
23
  const syntheticRuns = [];
@@ -28,7 +29,12 @@ export function previewWorkCenterPlan({ settings, workflowId, stageOverrides, re
28
29
  vps,
29
30
  priorRuns: syntheticRuns,
30
31
  });
31
- const model = resolveWorkItemModel(config, assignment.vp, stage.modelPolicy);
32
+ const model = resolveWorkItemModel(
33
+ config,
34
+ assignment.vp,
35
+ stage.modelPolicy,
36
+ normalizedSettings.modelTags,
37
+ );
32
38
  syntheticRuns.push({
33
39
  actionType: stage.type,
34
40
  roleSnapshot: { actionType: stage.type },
@@ -37,7 +37,11 @@ import { loadMCPConfig } from '../config.js';
37
37
  import { MCPManager } from '../mcp.js';
38
38
  import { buildMcpFlattenedTools } from '../tools/mcp-tools.js';
39
39
  import { recallWorkspaceSessionContext } from './workspace-context.js';
40
- import { applyGeneratedPlan, BUILT_IN_ACTION_TYPES } from './workflow.js';
40
+ import {
41
+ applyGeneratedPlan,
42
+ BUILT_IN_ACTION_TYPES,
43
+ DEFAULT_WORK_CENTER_MODEL_TAGS,
44
+ } from './workflow.js';
41
45
  import { isDynamicWorkItem, usesMainlineContext } from './execution-mode.js';
42
46
  import {
43
47
  applyAdditivePlanProposal,
@@ -1081,8 +1085,10 @@ export class WorkItemRunner {
1081
1085
  async run({ workItem, action, run, signal, ownerBootId, onProgress, registerProgressReader, registerInputWake, onEngineEvent = null }) {
1082
1086
  assertCreateVpActionAuthority(workItem, action, this.registry);
1083
1087
  const runtime = await this.runtimeProvider();
1088
+ const settings = this.policyProvider ? await this.policyProvider() : null;
1084
1089
  const currentSettings = ['ai', 'coordinator'].includes(workItem?.workflowSnapshot?.planningMode)
1085
- && this.policyProvider ? await this.policyProvider() : null;
1090
+ ? settings
1091
+ : null;
1086
1092
  const currentModelPolicy = currentSettings?.actionModelPolicies?.[action.type]
1087
1093
  || currentSettings?.actionModelPolicies?.custom
1088
1094
  || currentSettings?.modelPolicy
@@ -1125,7 +1131,16 @@ export class WorkItemRunner {
1125
1131
  error.retryable = false;
1126
1132
  throw error;
1127
1133
  }
1128
- const resolvedModel = resolveWorkItemModel(runtime.config, vp, executionAction.modelPolicy);
1134
+ const fallbackModel = runtime.config.primaryModel || runtime.config.model || null;
1135
+ const modelTags = settings?.modelTags || Object.fromEntries(
1136
+ Object.keys(DEFAULT_WORK_CENTER_MODEL_TAGS).map(tag => [tag, fallbackModel]),
1137
+ );
1138
+ const resolvedModel = resolveWorkItemModel(
1139
+ runtime.config,
1140
+ vp,
1141
+ executionAction.modelPolicy,
1142
+ modelTags,
1143
+ );
1129
1144
  const memoryBlock = recallWorkItemMemory(
1130
1145
  { ...runtime, yeaftDir: runtime.yeaftDir || this.yeaftDir },
1131
1146
  workItem,
@@ -21,12 +21,35 @@ export const BUILT_IN_ACTION_TYPES = Object.freeze([
21
21
  ]);
22
22
  const STAGE_TYPES = new Set(BUILT_IN_ACTION_TYPES);
23
23
  const ASSIGNMENT_MODES = new Set(['auto', 'pool', 'fixed', 'planned']);
24
- const MODEL_MODES = new Set(['inherit', 'primary', 'fast', 'specific']);
25
- const MODEL_EFFORTS = new Set(['minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'ultra']);
24
+ const MODEL_MODES = new Set(['inherit', 'primary', 'fast', 'specific', 'tag']);
25
+ const MODEL_EFFORTS = new Set(['medium', 'high', 'xhigh']);
26
26
  const WORKSPACE_MODES = new Set(['shared', 'read', 'isolated-write', 'integrate']);
27
- const HIGH_EFFORT_ACTION_TYPES = new Set(['triage', 'research', 'design', 'diagnose', 'review']);
28
27
  const ACTION_CONTEXT_QUOTE_MAX_BYTES = 8 * 1024;
29
28
 
29
+ export const DEFAULT_WORK_CENTER_MODEL_TAGS = Object.freeze({
30
+ fast: 'gpt-5.6-luna',
31
+ balanced: 'gpt-5.6-sol',
32
+ ultimate: 'gpt-6-astra',
33
+ });
34
+
35
+ const ULTIMATE_ACTION_TYPES = new Set(['triage', 'research', 'design', 'diagnose', 'review']);
36
+ const FAST_ACTION_TYPES = new Set(['document', 'deliver', 'write']);
37
+
38
+ function normalizeModelTags(value) {
39
+ const source = value && typeof value === 'object' && !Array.isArray(value)
40
+ ? value
41
+ : DEFAULT_WORK_CENTER_MODEL_TAGS;
42
+ return Object.fromEntries(Object.entries(source)
43
+ .map(([tag, model]) => [canonicalActionId(tag), typeof model === 'string' ? model.trim() : ''])
44
+ .filter(([tag, model]) => tag && model));
45
+ }
46
+
47
+ function defaultActionModelTag(type) {
48
+ if (ULTIMATE_ACTION_TYPES.has(type)) return { tag: 'ultimate', effort: 'xhigh' };
49
+ if (FAST_ACTION_TYPES.has(type)) return { tag: 'fast', effort: 'medium' };
50
+ return { tag: 'balanced', effort: 'high' };
51
+ }
52
+
30
53
  const DEFAULT_STAGE_INSTRUCTIONS = Object.freeze({
31
54
  triage: 'Turn the request into an executable contract. Inspect relevant repository facts before deciding the flow. Classify the WorkItem, identify constraints, risks, dependencies, and missing acceptance criteria, then plan only the Actions needed for this task. Do not implement. If the goal or acceptance criteria must change, submit a contractPatch and explain why.',
32
55
  research: 'Answer the Action objective with verifiable evidence. Search the repository and, when needed, authoritative external sources. Separate observed facts from inference, record unresolved uncertainty, and produce a concise conclusion that a later Action can use.',
@@ -97,26 +120,26 @@ const DEFAULT_SOFTWARE_CHANGE_STAGES = Object.freeze([
97
120
  {
98
121
  id: 'triage', name: 'Triage', type: 'triage',
99
122
  assignmentPolicy: { mode: 'auto', capability: 'triage', candidateVpIds: [], fixedVpId: null, separateFromStageTypes: [] },
100
- modelPolicy: { mode: 'inherit', model: null, effort: null },
123
+ modelPolicy: { mode: 'tag', tag: 'ultimate', effort: 'xhigh' },
101
124
  maxAttempts: 2,
102
125
  },
103
126
  {
104
127
  id: 'implement', name: 'Implement', type: 'implement',
105
128
  assignmentPolicy: { mode: 'auto', capability: 'implement', candidateVpIds: [], fixedVpId: null, separateFromStageTypes: [] },
106
- modelPolicy: { mode: 'inherit', model: null, effort: null },
129
+ modelPolicy: { mode: 'tag', tag: 'balanced', effort: 'high' },
107
130
  maxAttempts: 2,
108
131
  },
109
132
  {
110
133
  id: 'review', name: 'Review', type: 'review',
111
134
  assignmentPolicy: { mode: 'auto', capability: 'review', candidateVpIds: [], fixedVpId: null, separateFromStageTypes: ['implement'] },
112
- modelPolicy: { mode: 'inherit', model: null, effort: null },
135
+ modelPolicy: { mode: 'tag', tag: 'ultimate', effort: 'xhigh' },
113
136
  maxAttempts: 2,
114
137
  changesRequestedStageId: 'implement',
115
138
  },
116
139
  {
117
140
  id: 'deliver', name: 'Deliver', type: 'deliver',
118
141
  assignmentPolicy: { mode: 'auto', capability: 'deliver', candidateVpIds: [], fixedVpId: null, separateFromStageTypes: [] },
119
- modelPolicy: { mode: 'inherit', model: null, effort: null },
142
+ modelPolicy: { mode: 'tag', tag: 'fast', effort: 'medium' },
120
143
  maxAttempts: 2,
121
144
  },
122
145
  ]);
@@ -183,14 +206,18 @@ export function normalizeModelPolicy(value) {
183
206
  const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};
184
207
  const mode = MODEL_MODES.has(source.mode) ? source.mode : 'inherit';
185
208
  const model = typeof source.model === 'string' && source.model.trim() ? source.model.trim() : null;
209
+ const tag = typeof source.tag === 'string' && source.tag.trim()
210
+ ? canonicalActionId(source.tag)
211
+ : null;
186
212
  const effort = MODEL_EFFORTS.has(source.effort) ? source.effort : null;
187
213
  if (mode === 'specific' && !model) throw new Error('Specific Work Center model policy requires a model');
188
- return { mode, model, effort };
214
+ if (mode === 'tag' && !tag) throw new Error('Tagged Work Center model policy requires a tag');
215
+ return { mode, model, tag, effort };
189
216
  }
190
217
 
191
218
  export function defaultActionModelPolicy(type, fallback = null) {
192
- const base = normalizeModelPolicy(fallback);
193
- return { ...base, effort: HIGH_EFFORT_ACTION_TYPES.has(type) ? 'high' : 'medium' };
219
+ if (fallback) return normalizeModelPolicy(fallback);
220
+ return normalizeModelPolicy({ mode: 'tag', ...defaultActionModelTag(type) });
194
221
  }
195
222
 
196
223
  export function normalizeActionModelPolicies(value, fallback = null) {
@@ -308,8 +335,9 @@ export function defaultWorkCenterSettings() {
308
335
  maxConcurrentActions: 3,
309
336
  defaultWorkDir: '',
310
337
  globalInstructions: '',
311
- modelPolicy: { mode: 'inherit', model: null, effort: null },
312
- coordinatorModelPolicy: { mode: 'inherit', model: null, effort: 'high' },
338
+ modelTags: { ...DEFAULT_WORK_CENTER_MODEL_TAGS },
339
+ modelPolicy: normalizeModelPolicy({ mode: 'tag', tag: 'balanced', effort: 'high' }),
340
+ coordinatorModelPolicy: normalizeModelPolicy({ mode: 'tag', tag: 'ultimate', effort: 'xhigh' }),
313
341
  actionModelPolicies: normalizeActionModelPolicies(),
314
342
  actionInstructions: normalizeActionInstructions(),
315
343
  workflows: [normalizeWorkflowDefinition({
@@ -347,6 +375,7 @@ export function normalizeWorkCenterSettings(value) {
347
375
  maxConcurrentActions: Math.min(Math.max(Number(source.maxConcurrentActions) || 3, 1), 12),
348
376
  defaultWorkDir: typeof source.defaultWorkDir === 'string' ? source.defaultWorkDir.trim() : '',
349
377
  globalInstructions: normalizeGlobalInstructions(source.globalInstructions),
378
+ modelTags: normalizeModelTags(source.modelTags),
350
379
  modelPolicy: normalizeModelPolicy(source.modelPolicy || migratedModelPolicy),
351
380
  coordinatorModelPolicy: normalizeModelPolicy(
352
381
  source.coordinatorModelPolicy || { ...(source.modelPolicy || migratedModelPolicy), effort: 'high' },