@opencode/ai 0.0.0-dev-19594 → 0.0.0-dev-19596

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.
Files changed (56) hide show
  1. package/dist/cache-policy.js +10 -2
  2. package/dist/effort-updates.d.ts +12 -0
  3. package/dist/effort-updates.js +23 -0
  4. package/dist/protocols/alibaba-messages.d.ts +4 -1
  5. package/dist/protocols/anthropic-messages.d.ts +11 -2
  6. package/dist/protocols/anthropic-messages.js +48 -17
  7. package/dist/protocols/meta-messages.d.ts +4 -1
  8. package/dist/protocols/meta-responses.d.ts +2 -2
  9. package/dist/protocols/open-responses.d.ts +9 -2
  10. package/dist/protocols/open-responses.js +17 -2
  11. package/dist/protocols/openai-chat.d.ts +7 -7
  12. package/dist/protocols/openai-compatible-chat.d.ts +1 -1
  13. package/dist/protocols/openai-compatible-responses.d.ts +1 -1
  14. package/dist/protocols/openai-responses.d.ts +56 -25
  15. package/dist/protocols/openai-responses.js +23 -4
  16. package/dist/protocols/utils/open-responses-options.d.ts +2 -4
  17. package/dist/protocols/utils/open-responses-options.js +2 -2
  18. package/dist/protocols/utils/responses-compaction.js +3 -1
  19. package/dist/protocols/xai-responses.d.ts +1 -1
  20. package/dist/protocols/zai-chat.d.ts +1 -1
  21. package/dist/protocols/zai-messages.d.ts +4 -1
  22. package/dist/providers/alibaba.d.ts +12 -9
  23. package/dist/providers/amazon-bedrock-mantle.d.ts +2 -2
  24. package/dist/providers/anthropic-compatible.d.ts +4 -1
  25. package/dist/providers/anthropic.d.ts +4 -1
  26. package/dist/providers/azure.d.ts +13 -3
  27. package/dist/providers/baseten.d.ts +2 -2
  28. package/dist/providers/cerebras.d.ts +2 -2
  29. package/dist/providers/cloudflare-ai-gateway.d.ts +2 -2
  30. package/dist/providers/cloudflare-workers-ai.d.ts +2 -2
  31. package/dist/providers/deepinfra.d.ts +2 -2
  32. package/dist/providers/deepseek.d.ts +2 -2
  33. package/dist/providers/fireworks.d.ts +2 -2
  34. package/dist/providers/google-vertex-chat.d.ts +1 -1
  35. package/dist/providers/google-vertex-messages.d.ts +4 -1
  36. package/dist/providers/google-vertex-responses.d.ts +1 -1
  37. package/dist/providers/groq.d.ts +2 -2
  38. package/dist/providers/meta.d.ts +6 -3
  39. package/dist/providers/minimax.d.ts +6 -3
  40. package/dist/providers/moonshot.d.ts +6 -3
  41. package/dist/providers/openai-compatible-responses.d.ts +1 -1
  42. package/dist/providers/openai-compatible.d.ts +1 -1
  43. package/dist/providers/openai.d.ts +7 -2
  44. package/dist/providers/openrouter.d.ts +4 -4
  45. package/dist/providers/togetherai.d.ts +2 -2
  46. package/dist/providers/xai.d.ts +1 -1
  47. package/dist/providers/zai-coding-plan.d.ts +6 -3
  48. package/dist/providers/zai.d.ts +1 -1
  49. package/dist/route/client.d.ts +1 -0
  50. package/dist/route/client.js +3 -1
  51. package/dist/route/protocol.d.ts +2 -0
  52. package/dist/schema/messages.d.ts +22 -3
  53. package/dist/schema/messages.js +9 -1
  54. package/dist/schema/options.d.ts +5 -0
  55. package/dist/schema/options.js +4 -0
  56. package/package.json +3 -3
@@ -12,6 +12,7 @@
12
12
  // count against the four-breakpoint budget; auto only fills remaining slots.
13
13
  import { CacheHint } from "./schema/options.js";
14
14
  import { LLMRequest, Message, ToolDefinition } from "./schema/messages.js";
15
+ import { effortUpdate } from "./effort-updates.js";
15
16
  const AUTO = {
16
17
  tools: true,
17
18
  system: true,
@@ -100,10 +101,17 @@ const markMessages = (messages, strategy, hint, budget) => {
100
101
  return markMessageAt(messages, lastIndexOfRole(messages, "user"), hint, budget);
101
102
  if (strategy === "latest-assistant")
102
103
  return markMessageAt(messages, lastIndexOfRole(messages, "assistant"), hint, budget);
103
- const start = Math.max(0, messages.length - strategy.tail);
104
+ let start = messages.length;
105
+ let remaining = strategy.tail;
106
+ while (remaining > 0 && start > 0) {
107
+ start -= 1;
108
+ if (effortUpdate(messages[start]) === undefined)
109
+ remaining -= 1;
110
+ }
104
111
  let next = messages;
105
112
  for (let i = start; i < messages.length; i++)
106
- next = markMessageAt(next, i, hint, budget);
113
+ if (effortUpdate(messages[i]) === undefined)
114
+ next = markMessageAt(next, i, hint, budget);
107
115
  return next;
108
116
  };
109
117
  const countHints = (request) => countToolHints(request.tools) +
@@ -0,0 +1,12 @@
1
+ import { LLMRequest, type EffortPart, type Message } from "./schema/messages.js";
2
+ export declare const effortUpdate: (message: Message) => EffortPart | undefined;
3
+ export declare const stripEffortUpdates: (request: LLMRequest) => LLMRequest<import("./index.js").LanguageModel<{
4
+ readonly [x: string]: unknown;
5
+ }, import("./route.js").CompactionOperations | undefined>>;
6
+ export declare const applyEffortUpdates: (request: LLMRequest) => LLMRequest;
7
+ export declare const resolveEffortUpdates: (request: LLMRequest, current: string | undefined) => {
8
+ request: LLMRequest<import("./index.js").LanguageModel<{
9
+ readonly [x: string]: unknown;
10
+ }, import("./route.js").CompactionOperations | undefined>>;
11
+ effort: string | undefined;
12
+ };
@@ -0,0 +1,23 @@
1
+ // Changing the top-level reasoning effort invalidates the provider prompt cache. Protocols with a native
2
+ // per-message update keep it frozen and lower `Message.effort(...)` markers instead; other routes strip them.
3
+ import { LLMRequest } from "./schema/messages.js";
4
+ export const effortUpdate = (message) => {
5
+ if (message.role !== "system" || message.content.length !== 1)
6
+ return undefined;
7
+ const part = message.content[0];
8
+ return part.type === "effort" ? part : undefined;
9
+ };
10
+ export const stripEffortUpdates = (request) => {
11
+ const messages = request.messages.filter((message) => effortUpdate(message) === undefined);
12
+ return messages.length === request.messages.length ? request : LLMRequest.update(request, { messages });
13
+ };
14
+ export const applyEffortUpdates = (request) => request.model.route.supportsEffortUpdates?.(request) ? request : stripEffortUpdates(request);
15
+ // Reverted or forked history can leave the last marker disagreeing with the requested effort.
16
+ export const resolveEffortUpdates = (request, current) => {
17
+ const updates = request.messages.flatMap((message) => effortUpdate(message) ?? []);
18
+ if (updates.length === 0)
19
+ return { request, effort: current };
20
+ if (updates.at(-1)?.effort !== current)
21
+ return { request: stripEffortUpdates(request), effort: current };
22
+ return { request, effort: updates[0]?.previous };
23
+ };
@@ -187,7 +187,6 @@ export declare const protocol: Protocol<{
187
187
  readonly content: string | null;
188
188
  })[];
189
189
  } | {
190
- readonly role: "system";
191
190
  readonly content: readonly {
192
191
  readonly type: "text";
193
192
  readonly text: string;
@@ -196,6 +195,10 @@ export declare const protocol: Protocol<{
196
195
  readonly ttl?: "1h" | "5m" | undefined;
197
196
  } | undefined;
198
197
  }[];
198
+ readonly role: "system";
199
+ readonly output_config?: {
200
+ readonly effort: string;
201
+ } | undefined;
199
202
  })[];
200
203
  readonly stream: true;
201
204
  readonly metadata?: {
@@ -286,6 +286,9 @@ export declare const AnthropicMessagesBody: Schema.Struct<{
286
286
  readonly ttl: Schema.optional<Schema.Literals<readonly ["5m", "1h"]>>;
287
287
  }>>;
288
288
  }>>;
289
+ readonly output_config: Schema.optional<Schema.Struct<{
290
+ readonly effort: Schema.String;
291
+ }>>;
289
292
  }>]>>;
290
293
  tools: Schema.optional<Schema.$Array<Schema.Struct<{
291
294
  readonly name: Schema.String;
@@ -529,7 +532,6 @@ export declare const protocol: Protocol<{
529
532
  readonly content: string | null;
530
533
  })[];
531
534
  } | {
532
- readonly role: "system";
533
535
  readonly content: readonly {
534
536
  readonly type: "text";
535
537
  readonly text: string;
@@ -538,6 +540,10 @@ export declare const protocol: Protocol<{
538
540
  readonly ttl?: "1h" | "5m" | undefined;
539
541
  } | undefined;
540
542
  }[];
543
+ readonly role: "system";
544
+ readonly output_config?: {
545
+ readonly effort: string;
546
+ } | undefined;
541
547
  })[];
542
548
  readonly stream: true;
543
549
  readonly metadata?: {
@@ -883,7 +889,6 @@ export declare const route: Route<{
883
889
  readonly content: string | null;
884
890
  })[];
885
891
  } | {
886
- readonly role: "system";
887
892
  readonly content: readonly {
888
893
  readonly type: "text";
889
894
  readonly text: string;
@@ -892,6 +897,10 @@ export declare const route: Route<{
892
897
  readonly ttl?: "1h" | "5m" | undefined;
893
898
  } | undefined;
894
899
  }[];
900
+ readonly role: "system";
901
+ readonly output_config?: {
902
+ readonly effort: string;
903
+ } | undefined;
895
904
  })[];
896
905
  readonly stream: true;
897
906
  readonly metadata?: {
@@ -11,6 +11,7 @@ import { HttpTransport } from "../route/transport/index.js";
11
11
  import { AIError, HttpOptions, LLMRequest, LLMEvent, mergeJsonRecords, Usage, } from "../schema/index.js";
12
12
  import { JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js";
13
13
  import { classifyProviderFailure } from "../provider-error.js";
14
+ import { effortUpdate, resolveEffortUpdates } from "../effort-updates.js";
14
15
  import * as Cache from "./utils/cache.js";
15
16
  import { Lifecycle } from "./utils/lifecycle.js";
16
17
  import { ToolSchemaProjection } from "./utils/tool-schema.js";
@@ -19,6 +20,7 @@ const ADAPTER = "anthropic-messages";
19
20
  export const DEFAULT_BASE_URL = "https://api.anthropic.com/v1";
20
21
  export const PATH = "/messages";
21
22
  export const DEFAULT_MAX_TOKENS = 32_000;
23
+ const DEFAULT_EFFORT = "high";
22
24
  const SSE_EVENTS = new Set([
23
25
  "message",
24
26
  "message_start",
@@ -183,7 +185,11 @@ const AnthropicAssistantBlock = Schema.Union([
183
185
  const AnthropicMessage = Schema.Union([
184
186
  Schema.Struct({ role: Schema.Literal("user"), content: Schema.Array(AnthropicUserBlock) }),
185
187
  Schema.Struct({ role: Schema.Literal("assistant"), content: Schema.Array(AnthropicAssistantBlock) }),
186
- Schema.Struct({ role: Schema.Literal("system"), content: Schema.Array(AnthropicTextBlock) }),
188
+ Schema.Struct({
189
+ role: Schema.Literal("system"),
190
+ content: Schema.Array(AnthropicTextBlock),
191
+ output_config: Schema.optional(Schema.Struct({ effort: Schema.String })),
192
+ }),
187
193
  ]).pipe(Schema.toTaggedUnion("role"));
188
194
  const AnthropicTool = Schema.Struct({
189
195
  name: Schema.String,
@@ -697,6 +703,12 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* (re
697
703
  const providerMetadataKey = request.model.route.providerMetadataKey ?? String(request.model.provider);
698
704
  for (const [index, message] of request.messages.entries()) {
699
705
  if (message.role === "system") {
706
+ const update = effortUpdate(message);
707
+ if (update) {
708
+ // Accepted at any position, so the text-update placement rules do not apply.
709
+ messages.push({ role: "system", content: [], output_config: { effort: update.effort ?? DEFAULT_EFFORT } });
710
+ continue;
711
+ }
700
712
  if (splitsLocalToolResults(request.messages, index))
701
713
  return yield* invalid("Anthropic Messages system updates cannot split a local tool call from its tool result");
702
714
  if (supportsNativeSystemUpdates(request) && canUseNativeSystemUpdate(request, index)) {
@@ -842,17 +854,11 @@ const resolveOptions = Effect.fn("AnthropicMessages.resolveOptions")(function* (
842
854
  const outputConfigFormat = ProviderShared.isRecord(rawOutputConfig) && ProviderShared.isRecord(rawOutputConfig.format)
843
855
  ? rawOutputConfig.format
844
856
  : undefined;
845
- const output_config = outputConfigEffort === undefined && outputConfigFormat === undefined
846
- ? undefined
847
- : {
848
- ...(outputConfigEffort === undefined ? {} : { effort: outputConfigEffort }),
849
- ...(outputConfigFormat === undefined ? {} : { format: outputConfigFormat }),
850
- };
851
857
  const thinking = yield* resolveThinking(input?.thinking);
852
858
  return {
853
859
  thinking: applyThinkingBindingDefault(request.model, thinking),
854
860
  effort: outputConfigEffort,
855
- output_config,
861
+ format: outputConfigFormat,
856
862
  service_tier,
857
863
  metadata,
858
864
  container,
@@ -860,17 +866,32 @@ const resolveOptions = Effect.fn("AnthropicMessages.resolveOptions")(function* (
860
866
  cache_control,
861
867
  };
862
868
  });
869
+ // Accept gateway namespaces and Vertex suffixes without treating a snapshot date as a minor version.
870
+ const claudeVersion = (id) => {
871
+ const match = /(?:^|[./])claude-(?<family>[a-z]+)-(?<major>\d+)(?:[.-](?<minor>\d{1,2}))?(?:$|[-:@])/.exec(id.toLowerCase())?.groups;
872
+ if (!match)
873
+ return undefined;
874
+ return { family: match.family, major: Number(match.major), minor: Number(match.minor ?? 0) };
875
+ };
863
876
  const supportsThinkingBlockBinding = (model) => {
864
877
  const override = model.compatibility?.supportsThinkingBlockBinding;
865
878
  if (override !== undefined)
866
879
  return override;
867
- // Accept gateway namespaces and Vertex suffixes without treating a snapshot date as a minor version.
868
- const version = /(?:^|[./])claude-[a-z]+-(?<major>\d+)(?:[.-](?<minor>\d{1,2}))?(?:$|[-:@])/i.exec(model.id)?.groups;
869
- if (!version)
880
+ const version = claudeVersion(model.id);
881
+ return version !== undefined && (version.major > 5 || (version.major === 5 && version.minor >= 1));
882
+ };
883
+ const supportsEffortUpdates = (model) => {
884
+ const override = model.compatibility?.supportsEffortUpdates;
885
+ if (override !== undefined)
886
+ return override;
887
+ const version = claudeVersion(model.id);
888
+ if (version === undefined)
870
889
  return false;
871
- const major = Number(version.major);
872
- const minor = Number(version.minor ?? 0);
873
- return major > 5 || (major === 5 && minor >= 1);
890
+ if (version.family === "opus")
891
+ return version.major >= 5;
892
+ if (version.family !== "fable" && version.family !== "mythos")
893
+ return false;
894
+ return version.major > 5 || (version.major === 5 && version.minor >= 1);
874
895
  };
875
896
  const applyThinkingBindingDefault = (model, thinking) => {
876
897
  if (thinking?.type === "disabled")
@@ -909,13 +930,15 @@ const resolveThinking = Effect.fn("AnthropicMessages.resolveThinking")(function*
909
930
  });
910
931
  const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (request) {
911
932
  const management = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Schema.UndefinedOr(ContextManagement)))(request.providerOptions?.contextManagement);
933
+ const options = yield* resolveOptions(request);
934
+ const updates = resolveEffortUpdates(request, options.effort);
912
935
  const generation = request.generation;
913
936
  const toolSchemaCompatibility = request.model.compatibility?.toolSchema;
914
937
  // Allocate the 4-breakpoint budget in invalidation order: tools → system →
915
938
  // messages. Tools live highest in the cache hierarchy, so when callers
916
939
  // over-mark we keep their tool hints and shed the message-tail ones first.
917
940
  const breakpoints = Cache.newBreakpoints(ANTHROPIC_BREAKPOINT_CAP);
918
- const flattened = ProviderShared.flattenToolRequest(request);
941
+ const flattened = ProviderShared.flattenToolRequest(updates.request);
919
942
  const tools = flattened.tools.length === 0
920
943
  ? undefined
921
944
  : flattened.tools.map((tool) => lowerTool(breakpoints, tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, toolSchemaCompatibility)));
@@ -933,7 +956,12 @@ const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (reques
933
956
  if (breakpoints.dropped > 0) {
934
957
  yield* Effect.logWarning(`Anthropic Messages: dropped ${breakpoints.dropped} cache breakpoint(s); the API allows at most ${ANTHROPIC_BREAKPOINT_CAP} per request.`);
935
958
  }
936
- const options = yield* resolveOptions(request);
959
+ const output_config = updates.effort === undefined && options.format === undefined
960
+ ? undefined
961
+ : {
962
+ ...(updates.effort === undefined ? {} : { effort: updates.effort }),
963
+ ...(options.format === undefined ? {} : { format: options.format }),
964
+ };
937
965
  const body = {
938
966
  model: request.model.id,
939
967
  system,
@@ -947,7 +975,7 @@ const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (reques
947
975
  top_k: generation?.topK,
948
976
  stop_sequences: generation?.stop,
949
977
  thinking: options.thinking,
950
- output_config: options.output_config,
978
+ output_config,
951
979
  // top-level passthrough per SDK MessageCreateParamsBase:4638,4643,4649,4654,4670
952
980
  cache_control: options.cache_control,
953
981
  container: options.container,
@@ -1404,6 +1432,7 @@ export const protocol = Protocol.make({
1404
1432
  }),
1405
1433
  step,
1406
1434
  },
1435
+ supportsEffortUpdates: (request) => supportsEffortUpdates(request.model),
1407
1436
  });
1408
1437
  export const transport = () => {
1409
1438
  const http = HttpTransport.httpJson({ framing });
@@ -1440,6 +1469,8 @@ function requiredBetaHeaders(body) {
1440
1469
  const replaysCompaction = body.messages.some((message) => message.content.some((block) => block.type === "compaction"));
1441
1470
  if (requestsCompaction || replaysCompaction)
1442
1471
  betas.push("compact-2026-01-12");
1472
+ if (body.messages.some((message) => message.role === "system" && message.output_config !== undefined))
1473
+ betas.push("mid-conversation-output-config-2026-07-01");
1443
1474
  const thinking = body.thinking;
1444
1475
  if (thinking && thinking.type !== "disabled" && thinking.block_binding)
1445
1476
  betas.push("thinking-binding-controls-2026-08-01");
@@ -175,7 +175,6 @@ export declare const protocol: Protocol<{
175
175
  readonly content: string | null;
176
176
  })[];
177
177
  } | {
178
- readonly role: "system";
179
178
  readonly content: readonly {
180
179
  readonly type: "text";
181
180
  readonly text: string;
@@ -184,6 +183,10 @@ export declare const protocol: Protocol<{
184
183
  readonly ttl?: "1h" | "5m" | undefined;
185
184
  } | undefined;
186
185
  }[];
186
+ readonly role: "system";
187
+ readonly output_config?: {
188
+ readonly effort: string;
189
+ } | undefined;
187
190
  })[];
188
191
  readonly stream: true;
189
192
  readonly metadata?: {
@@ -153,7 +153,7 @@ export declare const protocol: Protocol<{
153
153
  readonly instructions?: string | undefined;
154
154
  readonly reasoning?: {
155
155
  readonly summary?: "auto" | "concise" | "detailed" | undefined;
156
- readonly effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
156
+ readonly effort?: import("../schema/options.js").ReasoningEffort | undefined;
157
157
  } | undefined;
158
158
  readonly tools?: readonly ({
159
159
  readonly type: "function";
@@ -409,7 +409,7 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
409
409
  readonly instructions?: string | undefined;
410
410
  readonly reasoning?: {
411
411
  readonly summary?: "auto" | "concise" | "detailed" | undefined;
412
- readonly effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
412
+ readonly effort?: import("../schema/options.js").ReasoningEffort | undefined;
413
413
  } | undefined;
414
414
  readonly tools?: readonly ({
415
415
  readonly type: "function";
@@ -90,6 +90,13 @@ export declare const CompactionItem: Schema.Struct<{
90
90
  readonly id: Schema.optional<Schema.NullOr<Schema.String>>;
91
91
  readonly encrypted_content: Schema.String;
92
92
  }>;
93
+ export declare const ConfigurationUpdate: Schema.Struct<{
94
+ readonly type: Schema.Literal<"configuration_update">;
95
+ readonly reasoning: Schema.Struct<{
96
+ readonly effort: Schema.declare<OpenResponsesOptions.ReasoningEffort, OpenResponsesOptions.ReasoningEffort>;
97
+ }>;
98
+ }>;
99
+ type ConfigurationUpdate = Schema.Schema.Type<typeof ConfigurationUpdate>;
93
100
  export declare const InputItem: Schema.Union<readonly [Schema.Struct<{
94
101
  readonly type: Schema.Literal<"compaction">;
95
102
  readonly id: Schema.optional<Schema.NullOr<Schema.String>>;
@@ -198,7 +205,7 @@ export type HostedToolReplayItem = {
198
205
  readonly id: string;
199
206
  readonly [key: string]: unknown;
200
207
  };
201
- type LoweredInputItem = OpenResponsesInputItem | HostedToolReplayItem | {
208
+ type LoweredInputItem = OpenResponsesInputItem | HostedToolReplayItem | ConfigurationUpdate | {
202
209
  readonly type: "message";
203
210
  readonly id?: string;
204
211
  readonly role: "assistant";
@@ -845,7 +852,7 @@ export declare const lowerConversation: (request: LLMRequest<import("../schema/o
845
852
  model: string & import("effect/Brand").Brand<"AI.ModelID">;
846
853
  input: LoweredInputItem[];
847
854
  }, AIError, never>;
848
- export declare const lowerGeneration: (request: LLMRequest) => {
855
+ export declare const lowerGeneration: (request: LLMRequest, options?: OpenResponsesOptions.Resolved) => {
849
856
  truncation?: "auto" | "disabled" | undefined;
850
857
  parallel_tool_calls?: boolean | undefined;
851
858
  max_tool_calls?: number | undefined;
@@ -4,6 +4,7 @@ import { Protocol } from "../route/protocol.js";
4
4
  import { AIError, LLMEvent, ProviderInternalError, Usage, } from "../schema/index.js";
5
5
  import { JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js";
6
6
  import { classifyProviderFailure } from "../provider-error.js";
7
+ import { effortUpdate } from "../effort-updates.js";
7
8
  import { OpenResponsesOptions } from "./utils/open-responses-options.js";
8
9
  import { Lifecycle } from "./utils/lifecycle.js";
9
10
  import { ToolSchemaProjection } from "./utils/tool-schema.js";
@@ -117,6 +118,11 @@ export const CompactionItem = Schema.Struct({
117
118
  id: optionalNull(Schema.String),
118
119
  encrypted_content: Schema.String,
119
120
  });
121
+ // Kept out of the baseline `InputItem` union: only the OpenAI extension accepts it.
122
+ export const ConfigurationUpdate = Schema.Struct({
123
+ type: Schema.Literal("configuration_update"),
124
+ reasoning: Schema.Struct({ effort: OpenResponsesOptions.ReasoningEffort }),
125
+ });
120
126
  export const InputItem = Schema.Union([
121
127
  CompactionItem,
122
128
  Schema.Struct({ role: Schema.tag("system"), content: Schema.String }),
@@ -423,12 +429,22 @@ const lowerToolResultOutput = Effect.fnUntraced(function* (part, request, adapte
423
429
  const content = part.result.value;
424
430
  return yield* Effect.forEach(content, (item) => lowerToolResultContentItem(item, request, adapter));
425
431
  });
432
+ const DEFAULT_EFFORT = "medium";
426
433
  const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (request, adapter) {
427
434
  const input = [];
428
435
  const providerMetadataKey = metadataKey(request.model);
429
436
  for (const message of request.messages) {
430
437
  const metadata = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Schema.UndefinedOr(MessageMetadata)))(message.providerMetadata?.[providerMetadataKey]);
431
438
  if (message.role === "system") {
439
+ const update = effortUpdate(message);
440
+ if (update) {
441
+ // Consecutive updates are rejected, so a newer one replaces its predecessor.
442
+ const last = input.at(-1);
443
+ if (last !== undefined && "type" in last && last.type === "configuration_update")
444
+ input.pop();
445
+ input.push({ type: "configuration_update", reasoning: { effort: update.effort ?? DEFAULT_EFFORT } });
446
+ continue;
447
+ }
432
448
  input.push({
433
449
  role: "developer",
434
450
  content: ProviderShared.joinText(yield* ProviderShared.systemUpdateText(adapter.name, message)),
@@ -561,8 +577,7 @@ export const lowerConversation = Effect.fn("OpenResponses.lowerConversation")(fu
561
577
  ...(instructions ? { instructions } : {}),
562
578
  };
563
579
  });
564
- export const lowerGeneration = (request) => {
565
- const options = OpenResponsesOptions.resolve(request);
580
+ export const lowerGeneration = (request, options = OpenResponsesOptions.resolve(request)) => {
566
581
  const generation = request.generation;
567
582
  const cacheKey = ProviderShared.promptCacheKey(request);
568
583
  const parallelToolCalls = resolveParallelToolCalls(request);
@@ -97,7 +97,7 @@ export declare const bodyFields: {
97
97
  }>>;
98
98
  store: Schema.optional<Schema.Boolean>;
99
99
  prompt_cache_key: Schema.optional<Schema.String>;
100
- reasoning_effort: Schema.optional<Schema.declare<import("./utils/open-responses-options.js").ReasoningEffort, import("./utils/open-responses-options.js").ReasoningEffort>>;
100
+ reasoning_effort: Schema.optional<Schema.declare<import("../schema/options.js").ReasoningEffort, import("../schema/options.js").ReasoningEffort>>;
101
101
  tool_stream: Schema.optional<Schema.Boolean>;
102
102
  max_completion_tokens: Schema.optional<Schema.Number>;
103
103
  max_tokens: Schema.optional<Schema.Number>;
@@ -193,7 +193,7 @@ declare const OpenAIChatBody: Schema.Struct<{
193
193
  }>>;
194
194
  store: Schema.optional<Schema.Boolean>;
195
195
  prompt_cache_key: Schema.optional<Schema.String>;
196
- reasoning_effort: Schema.optional<Schema.declare<import("./utils/open-responses-options.js").ReasoningEffort, import("./utils/open-responses-options.js").ReasoningEffort>>;
196
+ reasoning_effort: Schema.optional<Schema.declare<import("../schema/options.js").ReasoningEffort, import("../schema/options.js").ReasoningEffort>>;
197
197
  tool_stream: Schema.optional<Schema.Boolean>;
198
198
  max_completion_tokens: Schema.optional<Schema.Number>;
199
199
  max_tokens: Schema.optional<Schema.Number>;
@@ -292,7 +292,7 @@ interface LoweringOptions {
292
292
  export declare const fromRequest: (request: LLMRequest<import("../schema/options.js").LanguageModel<{
293
293
  readonly [x: string]: unknown;
294
294
  }, import("../route/client.js").CompactionOperations | undefined>>, options?: LoweringOptions | undefined) => Effect.Effect<{
295
- reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
295
+ reasoning_effort?: import("../schema/options.js").ReasoningEffort | undefined;
296
296
  prompt_cache_key?: string | undefined;
297
297
  store?: boolean | undefined;
298
298
  temperature: number | undefined;
@@ -389,7 +389,7 @@ export declare const fromRequest: (request: LLMRequest<import("../schema/options
389
389
  } | undefined;
390
390
  stream: true;
391
391
  } | {
392
- reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
392
+ reasoning_effort?: import("../schema/options.js").ReasoningEffort | undefined;
393
393
  prompt_cache_key?: string | undefined;
394
394
  store?: boolean | undefined;
395
395
  temperature: number | undefined;
@@ -584,7 +584,7 @@ export declare const protocol: Protocol<{
584
584
  readonly frequency_penalty?: number | undefined;
585
585
  readonly presence_penalty?: number | undefined;
586
586
  readonly prompt_cache_key?: string | undefined;
587
- readonly reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
587
+ readonly reasoning_effort?: import("../schema/options.js").ReasoningEffort | undefined;
588
588
  readonly store?: boolean | undefined;
589
589
  readonly stream_options?: {
590
590
  readonly include_usage: boolean;
@@ -751,7 +751,7 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
751
751
  readonly frequency_penalty?: number | undefined;
752
752
  readonly presence_penalty?: number | undefined;
753
753
  readonly prompt_cache_key?: string | undefined;
754
- readonly reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
754
+ readonly reasoning_effort?: import("../schema/options.js").ReasoningEffort | undefined;
755
755
  readonly store?: boolean | undefined;
756
756
  readonly stream_options?: {
757
757
  readonly include_usage: boolean;
@@ -850,7 +850,7 @@ export declare const route: Route<{
850
850
  readonly frequency_penalty?: number | undefined;
851
851
  readonly presence_penalty?: number | undefined;
852
852
  readonly prompt_cache_key?: string | undefined;
853
- readonly reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
853
+ readonly reasoning_effort?: import("../schema/options.js").ReasoningEffort | undefined;
854
854
  readonly store?: boolean | undefined;
855
855
  readonly stream_options?: {
856
856
  readonly include_usage: boolean;
@@ -99,7 +99,7 @@ export declare const route: Route<{
99
99
  readonly frequency_penalty?: number | undefined;
100
100
  readonly presence_penalty?: number | undefined;
101
101
  readonly prompt_cache_key?: string | undefined;
102
- readonly reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
102
+ readonly reasoning_effort?: import("../index.js").ReasoningEffort | undefined;
103
103
  readonly store?: boolean | undefined;
104
104
  readonly stream_options?: {
105
105
  readonly include_usage: boolean;
@@ -126,7 +126,7 @@ export declare const route: Route<{
126
126
  readonly instructions?: string | undefined;
127
127
  readonly reasoning?: {
128
128
  readonly summary?: "auto" | "concise" | "detailed" | undefined;
129
- readonly effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
129
+ readonly effort?: import("../index.js").ReasoningEffort | undefined;
130
130
  } | undefined;
131
131
  readonly tools?: readonly {
132
132
  readonly type: "function";