Skip to content

feat: add temperature and other common settings to model-level configuration - #388

Merged
robert-j-y merged 1 commit into
mainfrom
devin/1769809800-issue-387-temperature-settings
Apr 15, 2026
Merged

feat: add temperature and other common settings to model-level configuration#388
robert-j-y merged 1 commit into
mainfrom
devin/1769809800-issue-387-temperature-settings

Conversation

@robert-j-y

Copy link
Copy Markdown
Contributor

Description

Fixes #387

Adds support for setting default values for common model parameters at model creation time. Previously, settings like temperature could only be passed at call time via generateText/streamText. Now users can set defaults when creating the model:

// Before: TypeScript error - temperature not allowed
const model = openrouter('google/gemini-3-flash-preview', {
  temperature: 0 // ❌ Error
});

// After: Works correctly
const model = openrouter('google/gemini-3-flash-preview', {
  temperature: 0,
  topP: 0.9,
  maxTokens: 100,
});

Call-level options still override model-level settings when provided.

New settings added to OpenRouterSharedSettings:

  • temperature - Controls randomness (0-2)
  • topP - Nucleus sampling (0-1)
  • topK - Top-k sampling
  • frequencyPenalty - Penalize repeated tokens (-2 to 2)
  • presencePenalty - Penalize tokens based on presence (-2 to 2)
  • maxTokens - Maximum tokens to generate

Key areas for review:

Checklist

  • I have run pnpm stylecheck and pnpm typecheck
  • I have run pnpm test and all tests pass
  • I have added tests for my changes (if applicable)
  • I have updated documentation (if applicable)

Changeset

  • I have run pnpm changeset to create a changeset file

Link to Devin run: https://app.devin.ai/sessions/ad14476ac9334b8a962f771f56e48975
Requested by: Robert Yeakel (@robert-j-y)

@seannetlife

Copy link
Copy Markdown

ah, this is gonna be awesome to have. ty!

@louisgv louisgv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

…uration

Fixes #387

This change adds support for setting default values for common model parameters
at the model creation level:
- temperature
- topP
- topK
- frequencyPenalty
- presencePenalty
- maxTokens

These settings can be overridden at call time via generateText/streamText options.

Example:
```typescript
const model = openrouter('google/gemini-3-flash-preview', {
  temperature: 0,
  topP: 0.9,
  maxTokens: 100,
});
```

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>
@robert-j-y
robert-j-y force-pushed the devin/1769809800-issue-387-temperature-settings branch from 0eb69f3 to 89d7000 Compare April 15, 2026 21:18
@robert-j-y
robert-j-y merged commit 916c4c1 into main Apr 15, 2026
2 checks passed
@robert-j-y
robert-j-y deleted the devin/1769809800-issue-387-temperature-settings branch April 15, 2026 21:45
@github-actions github-actions Bot mentioned this pull request Apr 15, 2026
robert-j-y added a commit that referenced this pull request Apr 26, 2026
…eaming, and #413 reasoning-delta metadata fix

Restores four pieces of behavior that were inadvertently removed when the
empty reasoning_details fix was applied:

- #419: Defensive usage fallback in stream finish handler that copies
  openrouterUsage promptTokens/completionTokens into usage.inputTokens.total
  /outputTokens.total when the standard fields are still undefined after
  computeTokenUsage().
- #388: Model-level settings fallbacks (?? this.settings.X) for max_tokens,
  temperature, top_p, frequency_penalty, presence_penalty, top_k.
- #443: eager_input_streaming forwarding from tool providerOptions to the
  function tool request body.
- #413: Stop attaching accumulated reasoning_details snapshots to
  reasoning-start/reasoning-delta events to avoid payload bloat. The
  always-include behavior remains on reasoning-end and the stream finish
  event, which is the only place opencode-style consumers read it from.

Keeps the legitimate empty reasoning_details fix in place so DeepSeek V4
and similar providers continue to receive the empty array on follow-up
turns.

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>
robert-j-y added a commit that referenced this pull request Apr 26, 2026
…ons (#487)

* fix: preserve empty reasoning_details arrays in multi-turn conversations

Always include reasoning_details in finish event metadata and reasoning-end
providerMetadata, even when the accumulated array is empty. DeepSeek V4 and
similar providers require the field to be sent back in subsequent turns to
maintain conversation state.

* fix: treat empty reasoning_details array as explicit metadata signal

Replace length>0 checks with Array.isArray checks so that an explicit []
from message-level providerOptions is treated as 'metadata present but empty'
rather than 'metadata absent'. Preserve [] through dedup/signature-filter path.

* test(perry): update assertions for empty reasoning_details preservation

* test(perry): update signature-roundtrip assertions for empty reasoning_details

* test(perry): update stream usage accounting assertion for reasoning_details

* test(perry): update doStream finish event snapshots for reasoning_details

* chore(perry): add patch changeset for empty reasoning_details fix

* fix: restore #419 usage fallback, settings fallbacks, eager_input_streaming, and #413 reasoning-delta metadata fix

Restores four pieces of behavior that were inadvertently removed when the
empty reasoning_details fix was applied:

- #419: Defensive usage fallback in stream finish handler that copies
  openrouterUsage promptTokens/completionTokens into usage.inputTokens.total
  /outputTokens.total when the standard fields are still undefined after
  computeTokenUsage().
- #388: Model-level settings fallbacks (?? this.settings.X) for max_tokens,
  temperature, top_p, frequency_penalty, presence_penalty, top_k.
- #443: eager_input_streaming forwarding from tool providerOptions to the
  function tool request body.
- #413: Stop attaching accumulated reasoning_details snapshots to
  reasoning-start/reasoning-delta events to avoid payload bloat. The
  always-include behavior remains on reasoning-end and the stream finish
  event, which is the only place opencode-style consumers read it from.

Keeps the legitimate empty reasoning_details fix in place so DeepSeek V4
and similar providers continue to receive the empty array on follow-up
turns.

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>

* test: restore deleted #419/eager_input_streaming/#413 test coverage

Restores the seven tests that were inadvertently deleted along with the
empty reasoning_details fix and flips the reasoning-start/reasoning-delta
providerMetadata assertions back to toBeUndefined() to lock in the
restored #413 behavior.

- 3 tests for eager_input_streaming forwarding from tool providerOptions.
- 4 tests for the #419 defensive usage fallback in the stream finish handler.
- Adjusts the two streaming reasoning_details tests to assert that
  reasoning-start and reasoning-delta events do NOT carry providerMetadata
  (the snapshot is exposed only on reasoning-end and the finish event).

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Robert Yeakel <robert.yeakel@openrouter.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support temperature settings in OpenRouterChatSettings. (Missing)

3 participants