@theokit/sdk 2.10.0 → 2.11.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.11.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 6893812: Forward `ModelSelection.params` reasoning to OpenRouter / OpenAI-compat providers (issue #47). The `thinking` param was silently dropped (model resolution kept only `model.id`; the request body had no `reasoning` field), so `Agent.send` never requested or surfaced reasoning. Now a `thinking` param maps to the reasoning request the target provider accepts — OpenRouter (and OpenAI-compatible passthroughs) use the unified `reasoning: { effort }` object, while native OpenAI Chat Completions uses the top-level `reasoning_effort` string (so opting into reasoning never 400s on api.openai.com). The streamed reasoning (`delta.reasoning`, or `delta.reasoning_content` on DeepSeek-direct / vLLM / LMStudio compat endpoints) is surfaced as `thinking-delta` `InteractionUpdate`s (live via `onDelta`) plus a `thinking` `SDKMessage` (replayed by `Run.stream`), on a separate channel from the visible answer. Validated end-to-end against `deepseek/deepseek-r1` via OpenRouter.
8
+
9
+ ## 2.11.0
10
+
11
+ ### Minor Changes
12
+
13
+ - ac3f77d: @theokit/sdk: resolveModelCapabilities catalog gains cheap OpenRouter slugs (qwen3-coder, deepseek v4-flash/v3.2, glm-4.7-flash, gemini-2.5-flash-lite/pro) so they resolve real context windows instead of the 4096 default. @theokit/sdk-tools: new createGenericHttpSearchAdapter (env-keyed generic HTTP WebSearchCallback alongside Brave); buildEnvContext gains git-branch detection + an injectable clock. @theokit/sdk-cache: ships createLexicalEmbedder (zero-dependency token-hash lexical embedder built-in).
14
+
3
15
  ## 2.10.0
4
16
 
5
17
  ### Minor Changes
@@ -6889,6 +6889,14 @@ function buildAssistantEvent(inputs, text) {
6889
6889
  message: { role: "assistant", content: [{ type: "text", text }] }
6890
6890
  };
6891
6891
  }
6892
+ function buildThinkingEvent(inputs, text) {
6893
+ return {
6894
+ type: "thinking",
6895
+ agent_id: inputs.agentId,
6896
+ run_id: inputs.runId,
6897
+ text
6898
+ };
6899
+ }
6892
6900
  function buildAssistantTurn(text, toolCalls) {
6893
6901
  const content = [];
6894
6902
  if (text.length > 0) content.push({ type: "text", text });
@@ -7074,6 +7082,10 @@ ${additions}`;
7074
7082
  function toLlmTool(tool) {
7075
7083
  return { name: tool.name, description: tool.description, inputSchema: tool.inputSchema };
7076
7084
  }
7085
+ function reasoningEffortFromParams(params) {
7086
+ const thinking = params?.find((p) => p.id === "thinking");
7087
+ return thinking !== void 0 && thinking.value.length > 0 ? thinking.value : void 0;
7088
+ }
7077
7089
  async function streamLlmTurn(inputs, ctx) {
7078
7090
  const llmSpan = inputs.telemetry?.startSpan("llm.call", {
7079
7091
  "model.id": inputs.model.id ?? "auto",
@@ -7090,6 +7102,12 @@ async function streamLlmTurn(inputs, ctx) {
7090
7102
  );
7091
7103
  return effective !== void 0 ? { system: effective } : {};
7092
7104
  })(),
7105
+ // issue #47: forward the reasoning effort from ModelSelection.params (the `thinking` param)
7106
+ // so the provider produces reasoning. Absent param ⇒ no `reasoning` field (bare request).
7107
+ ...(() => {
7108
+ const effort = reasoningEffortFromParams(inputs.model.params);
7109
+ return effort !== void 0 ? { reasoning: { effort } } : {};
7110
+ })(),
7093
7111
  messages: ctx.messages,
7094
7112
  tools: ctx.tools.map(toLlmTool)
7095
7113
  },
@@ -7158,6 +7176,7 @@ function registerLoopError(ctx, cause) {
7158
7176
  }
7159
7177
  async function runCollectorLoop(generator, inputs, ctx) {
7160
7178
  let accumulatedText = "";
7179
+ let reasoningText = "";
7161
7180
  let errored = false;
7162
7181
  let finishValue;
7163
7182
  while (true) {
@@ -7170,6 +7189,10 @@ async function runCollectorLoop(generator, inputs, ctx) {
7170
7189
  accumulatedText += next.value.text;
7171
7190
  await emitTextDeltaCallback(inputs, next.value.text);
7172
7191
  }
7192
+ if (next.value.type === "reasoning_delta") {
7193
+ reasoningText += next.value.text;
7194
+ await emitReasoningDeltaCallback(inputs, next.value.text);
7195
+ }
7173
7196
  if (next.value.type === "error") {
7174
7197
  registerLoopError(ctx, next.value);
7175
7198
  ctx.finalText = "";
@@ -7177,6 +7200,9 @@ async function runCollectorLoop(generator, inputs, ctx) {
7177
7200
  break;
7178
7201
  }
7179
7202
  }
7203
+ if (reasoningText.length > 0) {
7204
+ ctx.events.push(buildThinkingEvent(inputs, reasoningText));
7205
+ }
7180
7206
  return { accumulatedText, errored, finishValue };
7181
7207
  }
7182
7208
  async function emitTextDeltaCallback(inputs, text) {
@@ -7188,6 +7214,15 @@ async function emitTextDeltaCallback(inputs, text) {
7188
7214
  "SendOptions.onDelta"
7189
7215
  );
7190
7216
  }
7217
+ async function emitReasoningDeltaCallback(inputs, text) {
7218
+ if (inputs.onDelta === void 0) return;
7219
+ const cb = inputs.onDelta;
7220
+ await safeCall(
7221
+ () => cb({ update: { type: "thinking-delta", text } }),
7222
+ void 0,
7223
+ "SendOptions.onDelta"
7224
+ );
7225
+ }
7191
7226
  var init_loop_llm_stream = __esm({
7192
7227
  "src/internal/agent-loop/loop-llm-stream.ts"() {
7193
7228
  init_safe_call();
@@ -10072,7 +10107,14 @@ function mapOpenAIFinish(reason) {
10072
10107
  return "end_turn";
10073
10108
  }
10074
10109
  }
10075
- function buildOpenAIBody(request) {
10110
+ function applyReasoningRequest(body, effort, providerName) {
10111
+ if (providerName === "openai") {
10112
+ body.reasoning_effort = effort;
10113
+ return;
10114
+ }
10115
+ body.reasoning = { effort };
10116
+ }
10117
+ function buildOpenAIBody(request, providerName) {
10076
10118
  const messages = [];
10077
10119
  const systemText = openAISystemText(request.system);
10078
10120
  if (systemText.length > 0) {
@@ -10091,6 +10133,8 @@ function buildOpenAIBody(request) {
10091
10133
  };
10092
10134
  if (request.maxTokens !== void 0) body.max_tokens = request.maxTokens;
10093
10135
  if (request.temperature !== void 0) body.temperature = request.temperature;
10136
+ if (request.reasoning?.effort !== void 0)
10137
+ applyReasoningRequest(body, request.reasoning.effort, providerName);
10094
10138
  if (request.tools !== void 0 && request.tools.length > 0) {
10095
10139
  body.tools = request.tools.map((tool) => ({
10096
10140
  type: "function",
@@ -10186,7 +10230,7 @@ var init_openai2 = __esm({
10186
10230
  method: "POST",
10187
10231
  signal,
10188
10232
  headers,
10189
- body: JSON.stringify(buildOpenAIBody(request))
10233
+ body: JSON.stringify(buildOpenAIBody(request, providerId))
10190
10234
  });
10191
10235
  } catch (fetchErr) {
10192
10236
  const mapped = mapOllamaTransportError({
@@ -10248,6 +10292,10 @@ var init_openai2 = __esm({
10248
10292
  const events = [];
10249
10293
  this.applyUsage(chunk.usage);
10250
10294
  for (const choice of chunk.choices ?? []) {
10295
+ const reasoningEvent = this.applyReasoningDelta(
10296
+ choice.delta?.reasoning ?? choice.delta?.reasoning_content
10297
+ );
10298
+ if (reasoningEvent !== void 0) events.push(reasoningEvent);
10251
10299
  const textEvent = this.applyContentDelta(choice.delta?.content);
10252
10300
  if (textEvent !== void 0) events.push(textEvent);
10253
10301
  this.mergeToolCallDeltas(choice.delta?.tool_calls);
@@ -10255,6 +10303,10 @@ var init_openai2 = __esm({
10255
10303
  }
10256
10304
  return events;
10257
10305
  }
10306
+ applyReasoningDelta(reasoning) {
10307
+ if (typeof reasoning !== "string" || reasoning.length === 0) return void 0;
10308
+ return { type: "reasoning_delta", text: reasoning };
10309
+ }
10258
10310
  applyUsage(usage) {
10259
10311
  if (usage?.prompt_tokens !== void 0) this.inputTokens = usage.prompt_tokens;
10260
10312
  if (usage?.completion_tokens !== void 0) this.outputTokens = usage.completion_tokens;
@@ -11144,7 +11196,12 @@ function buildLoopInputs(options, runId, userText) {
11144
11196
  return {
11145
11197
  agentId: options.agentId,
11146
11198
  runId,
11147
- model: { id: effectiveModelId },
11199
+ // issue #47: carry ModelSelection.params (the reasoning `thinking` param) into the loop so the
11200
+ // request can forward reasoning. The id is stripped/normalized above; params pass through as-is.
11201
+ model: {
11202
+ id: effectiveModelId,
11203
+ ...options.model?.params !== void 0 ? { params: options.model.params } : {}
11204
+ },
11148
11205
  userMessage: userText,
11149
11206
  llm,
11150
11207
  mcp: buildMcpMap(options),