@agentforge-io/core 2.1.0 → 2.1.1
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.
|
@@ -11,6 +11,38 @@ const model_strategy_1 = require("../types/model-strategy");
|
|
|
11
11
|
const noopLogger = {
|
|
12
12
|
log: () => { }, warn: () => { }, debug: () => { }, error: () => { },
|
|
13
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* Anthropic's newer model families deprecated the `temperature` parameter
|
|
16
|
+
* entirely — they auto-tune sampling internally and return 400
|
|
17
|
+
* `invalid_request_error: \`temperature\` is deprecated for this model` if
|
|
18
|
+
* the caller still sends one. Older families (3.x, the original 4.0
|
|
19
|
+
* releases) accept it fine.
|
|
20
|
+
*
|
|
21
|
+
* Detection by string match on the model id rather than a hard-coded
|
|
22
|
+
* allowlist: new model ids land between SDK releases, and we don't want
|
|
23
|
+
* to break temperature on legacy agents the day a new family ships.
|
|
24
|
+
* Pattern: anything that contains `-4-5`, `-4-6`, `-4-7`, …, `-5-*`,
|
|
25
|
+
* `-6-*`, etc. counts as "newer." Old 4-0 / 4-1 / 3-x ids are unaffected.
|
|
26
|
+
*
|
|
27
|
+
* Heuristic, not exhaustive — if a future family lands with a different
|
|
28
|
+
* naming convention we'll have to extend this. The cost of being wrong
|
|
29
|
+
* is a single 400 the operator can fix by clearing the temperature in
|
|
30
|
+
* the editor; the cost of NOT filtering is the same 400 today.
|
|
31
|
+
*/
|
|
32
|
+
function modelRejectsTemperature(model) {
|
|
33
|
+
if (!model)
|
|
34
|
+
return false;
|
|
35
|
+
// Normalize: ignore vendor prefixes like "anthropic/claude-..." and
|
|
36
|
+
// bracket suffixes like "claude-opus-4-7[1m]" (long-context variant).
|
|
37
|
+
const m = model.toLowerCase().replace(/\[[^\]]*\]/g, '');
|
|
38
|
+
// claude-*-4-5, 4-6, 4-7, 4-8 …
|
|
39
|
+
if (/claude-[a-z]+-4-([5-9])\b/.test(m))
|
|
40
|
+
return true;
|
|
41
|
+
// claude-*-5-x, claude-*-6-x, … (future major bumps)
|
|
42
|
+
if (/claude-[a-z]+-([5-9])-/.test(m))
|
|
43
|
+
return true;
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
14
46
|
/**
|
|
15
47
|
* Framework-free runner for Claude. Handles the agentic loop (tool calls) for
|
|
16
48
|
* sync runs and exposes streaming as an `AsyncGenerator<StreamChunk>` so any
|
|
@@ -74,12 +106,17 @@ class AgentRunnerService {
|
|
|
74
106
|
if (this.logger && selection.reason !== 'default' && selection.reason !== 'forced') {
|
|
75
107
|
this.logger.debug(`[modelRouter] agent=${agent.id} ${selection.reason}=${selection.trigger} → ${model}`);
|
|
76
108
|
}
|
|
109
|
+
// Per-turn temperature gating. The PER-MODEL filter runs INSIDE
|
|
110
|
+
// the loop because `model` can change between turns (model
|
|
111
|
+
// strategy can route a long-context turn to a different family
|
|
112
|
+
// than the short turns above it). Computing once outside would
|
|
113
|
+
// either over-strip (drop temperature for a legacy follow-up
|
|
114
|
+
// model) or under-strip (forward it to a new-family upgrade).
|
|
115
|
+
const includeTemperature = typeof temperature === 'number' && !modelRejectsTemperature(model);
|
|
77
116
|
const response = await this.client.messages.create({
|
|
78
117
|
model,
|
|
79
118
|
max_tokens: maxTokens,
|
|
80
|
-
|
|
81
|
-
// models 400 on `temperature` when tools are present.
|
|
82
|
-
...(typeof temperature === 'number' ? { temperature } : {}),
|
|
119
|
+
...(includeTemperature ? { temperature } : {}),
|
|
83
120
|
system: systemPrompt,
|
|
84
121
|
messages: currentMessages,
|
|
85
122
|
tools: tools,
|
|
@@ -193,10 +230,12 @@ class AgentRunnerService {
|
|
|
193
230
|
if (this.logger && selection.reason !== 'default' && selection.reason !== 'forced') {
|
|
194
231
|
this.logger.debug(`[modelRouter] agent=${agent.id} ${selection.reason}=${selection.trigger} → ${model}`);
|
|
195
232
|
}
|
|
233
|
+
// Per-turn temperature gating — see `run()` above for rationale.
|
|
234
|
+
const includeTemperature = typeof temperature === 'number' && !modelRejectsTemperature(model);
|
|
196
235
|
const stream = this.client.messages.stream({
|
|
197
236
|
model,
|
|
198
237
|
max_tokens: maxTokens,
|
|
199
|
-
...(
|
|
238
|
+
...(includeTemperature ? { temperature } : {}),
|
|
200
239
|
system: systemPrompt,
|
|
201
240
|
messages: currentMessages,
|
|
202
241
|
tools: tools,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentforge-io/core",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Framework-free AI runtime SDK. Owns: agent loop (Anthropic), conversations, tools, streaming, agent-job queue, SdkHooks. Identity, billing, infra (email/uploads/secrets) live in the host's modules — not here.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|