loopengine 0.1.45 → 0.1.47
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.
|
@@ -8,6 +8,8 @@ export interface AgentEditableFields {
|
|
|
8
8
|
model?: {
|
|
9
9
|
provider: Provider;
|
|
10
10
|
model?: string;
|
|
11
|
+
maxTokens?: number;
|
|
12
|
+
reasoningEffort?: string;
|
|
11
13
|
};
|
|
12
14
|
maxTurns?: number;
|
|
13
15
|
contextBudgetTokens?: number;
|
|
@@ -18,6 +20,8 @@ export interface AgentEditResult {
|
|
|
18
20
|
model?: {
|
|
19
21
|
provider: Provider;
|
|
20
22
|
model: string;
|
|
23
|
+
maxTokens?: number;
|
|
24
|
+
reasoningEffort?: string;
|
|
21
25
|
};
|
|
22
26
|
maxTurns?: number;
|
|
23
27
|
contextBudgetTokens?: number;
|
|
@@ -162,12 +162,34 @@ export function editAgentFile(agentName, fields) {
|
|
|
162
162
|
if (provider !== 'anthropic' && !modelName) {
|
|
163
163
|
throw new AgentModelError(`A model name is required for provider '${provider}' — only anthropic has a default (claude-sonnet-5).`);
|
|
164
164
|
}
|
|
165
|
+
const maxTokens = fields.model.maxTokens;
|
|
166
|
+
if (maxTokens !== undefined && (!Number.isInteger(maxTokens) || maxTokens < 1)) {
|
|
167
|
+
throw new AgentEditNotSupportedError('model.maxTokens must be a positive integer.');
|
|
168
|
+
}
|
|
169
|
+
const reasoningEffort = fields.model.reasoningEffort;
|
|
170
|
+
// Only AgentModelConfig's 'openai' variant carries this (see its own
|
|
171
|
+
// doc comment) — refusing rather than silently dropping it for
|
|
172
|
+
// another provider, same "don't guess" posture the model-name check
|
|
173
|
+
// right above already follows.
|
|
174
|
+
if (reasoningEffort !== undefined && provider !== 'openai') {
|
|
175
|
+
throw new AgentModelError(`model.reasoningEffort only applies to provider 'openai' — '${provider}' doesn't support it.`);
|
|
176
|
+
}
|
|
177
|
+
// Every field the form actually round-trips (not just provider/model)
|
|
178
|
+
// — omitting maxTokens/reasoningEffort here, the way this used to
|
|
179
|
+
// unconditionally build `{ provider, model }` alone, would silently
|
|
180
|
+
// wipe out a value that was already set the moment an operator
|
|
181
|
+
// changed anything else about the model through this same form.
|
|
182
|
+
const objectFields = [`provider: '${provider}'`, `model: ${tsStringLiteral(modelName)}`];
|
|
183
|
+
if (maxTokens !== undefined)
|
|
184
|
+
objectFields.push(`maxTokens: ${maxTokens}`);
|
|
185
|
+
if (reasoningEffort !== undefined)
|
|
186
|
+
objectFields.push(`reasoningEffort: ${tsStringLiteral(reasoningEffort)}`);
|
|
165
187
|
edits.push({
|
|
166
188
|
start: prop.initializer.getStart(sourceFile),
|
|
167
189
|
end: prop.initializer.getEnd(),
|
|
168
|
-
text: `{
|
|
190
|
+
text: `{ ${objectFields.join(', ')} }`,
|
|
169
191
|
});
|
|
170
|
-
result.model = { provider, model: modelName };
|
|
192
|
+
result.model = { provider, model: modelName, maxTokens, reasoningEffort };
|
|
171
193
|
// The property's own value is now correct, but a stale
|
|
172
194
|
// "// reads ANTHROPIC_API_KEY" sitting right after it (from before a
|
|
173
195
|
// provider change) would be actively misleading, not just cosmetic —
|
|
@@ -658,6 +658,7 @@ export const agentsConfigPageHtml = `<!doctype html>
|
|
|
658
658
|
'<dt>Provider</dt><dd>' + escapeHtml(cfg.model.provider) + '</dd>' +
|
|
659
659
|
'<dt>Model</dt><dd>' + escapeHtml(cfg.model.model || '(provider default)') + '</dd>' +
|
|
660
660
|
'<dt>Max tokens</dt><dd>' + escapeHtml(cfg.model.maxTokens != null ? cfg.model.maxTokens : '(default)') + '</dd>' +
|
|
661
|
+
'<dt>Reasoning effort</dt><dd>' + escapeHtml(cfg.model.reasoningEffort || (cfg.model.provider === 'openai' ? '(provider default)' : 'n/a')) + '</dd>' +
|
|
661
662
|
'</dl>' +
|
|
662
663
|
'<form class="add-source" id="modelForm" style="display:none">' +
|
|
663
664
|
'<label>Provider' +
|
|
@@ -670,6 +671,16 @@ export const agentsConfigPageHtml = `<!doctype html>
|
|
|
670
671
|
'<label>Model name <span class="hint">(required for openai/deepseek; defaults to claude-sonnet-5 for anthropic)</span>' +
|
|
671
672
|
'<input type="text" name="modelName" value="' + escapeHtml(cfg.model.model || '') + '">' +
|
|
672
673
|
'</label>' +
|
|
674
|
+
'<label>Max tokens <span class="hint">(blank for provider default)</span>' +
|
|
675
|
+
'<input type="number" name="maxTokens" min="1" step="1" value="' + (cfg.model.maxTokens != null ? escapeHtml(cfg.model.maxTokens) : '') + '">' +
|
|
676
|
+
'</label>' +
|
|
677
|
+
'<label>Reasoning effort <span class="hint">(openai only — some reasoning models reject function tools unless this is \\\'none\\\'; leave unset otherwise)</span>' +
|
|
678
|
+
'<select name="reasoningEffort">' +
|
|
679
|
+
['', 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'].map(function (v) {
|
|
680
|
+
return '<option value="' + v + '"' + (v === (cfg.model.reasoningEffort || '') ? ' selected' : '') + '>' + (v || '(unset)') + '</option>';
|
|
681
|
+
}).join('') +
|
|
682
|
+
'</select>' +
|
|
683
|
+
'</label>' +
|
|
673
684
|
'<button type="submit">Save</button>' +
|
|
674
685
|
'<button type="button" id="cancelModelBtn">Cancel</button>' +
|
|
675
686
|
'<div class="error" id="modelError"></div>' +
|
|
@@ -793,6 +804,10 @@ export const agentsConfigPageHtml = `<!doctype html>
|
|
|
793
804
|
var body = { model: { provider: data.get('provider') } };
|
|
794
805
|
var modelName = data.get('modelName');
|
|
795
806
|
if (modelName && modelName.trim()) body.model.model = modelName;
|
|
807
|
+
var maxTokens = data.get('maxTokens');
|
|
808
|
+
if (maxTokens && String(maxTokens).trim()) body.model.maxTokens = parseInt(maxTokens, 10);
|
|
809
|
+
var reasoningEffort = data.get('reasoningEffort');
|
|
810
|
+
if (reasoningEffort) body.model.reasoningEffort = reasoningEffort;
|
|
796
811
|
fetch('/agents/' + encodeURIComponent(name), {
|
|
797
812
|
method: 'PUT',
|
|
798
813
|
headers: { 'content-type': 'application/json' },
|