@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
- // Only include temperature when explicitly declared — newer
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
- ...(typeof temperature === 'number' ? { temperature } : {}),
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.0",
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",