maka-agent 0.2.1-dev.85.20261014 → 0.2.1-dev.86.20261014

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 (59) hide show
  1. package/dist/acp/session-configuration.js +1 -0
  2. package/dist/run-command-core.js +4 -7
  3. package/dist/runtime-host-session-driver.js +4 -4
  4. package/dist/tui-copy-catalog.js +3 -0
  5. package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
  6. package/node_modules/@maka/antigravity-acp-plugin/dist/plugin.mjs +2 -1
  7. package/node_modules/@maka/core/dist/model-metadata.js +8 -0
  8. package/node_modules/@maka/core/dist/model-thinking.js +10 -29
  9. package/node_modules/@maka/core/dist/recall.js +10 -2
  10. package/node_modules/@maka/core/dist/session.js +2 -0
  11. package/node_modules/@maka/core/dist/settings.js +2 -0
  12. package/node_modules/@maka/core/dist/subagent-settings.js +2 -1
  13. package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +23 -0
  14. package/node_modules/@maka/runtime/dist/model-adapter.js +3 -0
  15. package/node_modules/@maka/runtime/dist/model-factory.js +38 -98
  16. package/node_modules/@maka/runtime/dist/plugin-session-query-service.js +135 -0
  17. package/node_modules/@maka/runtime/dist/plugin-source-service.js +123 -0
  18. package/node_modules/@maka/runtime/dist/plugin-tool-service.js +3 -0
  19. package/node_modules/@maka/runtime/dist/plugin-turn-finish-service.js +63 -0
  20. package/node_modules/@maka/runtime/dist/tool-availability.js +3 -1
  21. package/node_modules/@maka/runtime/dist/tool-free-model-call.js +21 -3
  22. package/node_modules/@maka/runtime/package.json +2 -0
  23. package/node_modules/@maka/runtime-host/dist/assistant/background-sessions.js +32 -0
  24. package/node_modules/@maka/runtime-host/dist/assistant/execution-outcome.js +52 -0
  25. package/node_modules/@maka/runtime-host/dist/assistant/index-initiative/assistant.js +236 -0
  26. package/node_modules/@maka/runtime-host/dist/assistant/index-initiative/controller.js +192 -0
  27. package/node_modules/@maka/runtime-host/dist/assistant/index-initiative/host.js +71 -0
  28. package/node_modules/@maka/runtime-host/dist/assistant/index-initiative/prompt.js +26 -0
  29. package/node_modules/@maka/runtime-host/dist/assistant/index-initiative/store.js +228 -0
  30. package/node_modules/@maka/runtime-host/dist/assistant/memory-network/controller.js +1121 -0
  31. package/node_modules/@maka/runtime-host/dist/assistant/memory-network/corpus.js +431 -0
  32. package/node_modules/@maka/runtime-host/dist/assistant/memory-network/extractor.js +143 -0
  33. package/node_modules/@maka/runtime-host/dist/assistant/memory-network/host.js +402 -0
  34. package/node_modules/@maka/runtime-host/dist/assistant/memory-network/store.js +388 -0
  35. package/node_modules/@maka/runtime-host/dist/assistant/proactive-matters/controller.js +316 -0
  36. package/node_modules/@maka/runtime-host/dist/assistant/proactive-matters/delegation.js +232 -0
  37. package/node_modules/@maka/runtime-host/dist/assistant/proactive-matters/delivery.js +250 -0
  38. package/node_modules/@maka/runtime-host/dist/assistant/proactive-matters/files.js +103 -0
  39. package/node_modules/@maka/runtime-host/dist/assistant/proactive-matters/host-types.js +19 -0
  40. package/node_modules/@maka/runtime-host/dist/assistant/proactive-matters/host.js +135 -0
  41. package/node_modules/@maka/runtime-host/dist/assistant/proactive-matters/matter.js +22 -0
  42. package/node_modules/@maka/runtime-host/dist/assistant/proactive-matters/prompt.js +51 -0
  43. package/node_modules/@maka/runtime-host/dist/assistant/proactive-matters/review.js +132 -0
  44. package/node_modules/@maka/runtime-host/dist/assistant/proactive-matters/store.js +885 -0
  45. package/node_modules/@maka/runtime-host/dist/assistant/proactive-matters/tools.js +176 -0
  46. package/node_modules/@maka/runtime-host/dist/assistant/service.js +421 -0
  47. package/node_modules/@maka/runtime-host/dist/protocol/index.js +4 -1
  48. package/node_modules/@maka/runtime-host/dist/protocol/operations.js +3 -1
  49. package/node_modules/@maka/runtime-host/dist/protocol/personal-assistant.js +58 -0
  50. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +191 -13
  51. package/node_modules/@maka/runtime-host/dist/server/execution-model-authority.js +6 -0
  52. package/node_modules/@maka/runtime-host/dist/server/execution-model-composition.js +1 -0
  53. package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +12 -2
  54. package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +12 -0
  55. package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +30 -13
  56. package/node_modules/@maka/storage/dist/execution-stores.js +2 -0
  57. package/node_modules/@maka/storage/dist/runtime-event-persistence.js +1 -0
  58. package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +9 -0
  59. package/package.json +1 -1
@@ -28,6 +28,7 @@ const PERMISSION_NAMES = {
28
28
  const THINKING_NAMES = {
29
29
  default: 'Default',
30
30
  off: 'Off',
31
+ on: 'On',
31
32
  minimal: 'Minimal',
32
33
  low: 'Low',
33
34
  medium: 'Medium',
@@ -117,14 +117,13 @@ export function parseMakaRunArgs(argv) {
117
117
  ...(flags.get('cwd') !== undefined ? { cwd: flags.get('cwd') } : {}),
118
118
  ...(flags.get('connection') !== undefined ? { connection: flags.get('connection') } : {}),
119
119
  ...(flags.get('model') !== undefined ? { model: flags.get('model') } : {}),
120
- ...(thinking !== undefined && thinking !== 'default' ? { thinking } : {}),
120
+ ...(thinking !== undefined ? { thinking: thinking === 'default' ? null : thinking } : {}),
121
121
  ...(timeoutSeconds !== undefined ? { timeoutMs: Math.ceil(timeoutSeconds * 1_000) } : {}),
122
122
  ...(parsedMaxSteps !== undefined ? { maxSteps: parsedMaxSteps } : {}),
123
123
  ...(booleanFlags.has('yolo') ? { yolo: true } : {}),
124
124
  ...(resumeId !== undefined ? { resumeId } : {}),
125
125
  ...(continueLatest ? { continueLatest: true } : {}),
126
126
  ...(graph ? { graph: true } : {}),
127
- ...(thinking === 'default' ? { thinkingDefaultExplicit: true } : {}),
128
127
  ...(flags.get('host') !== undefined ? { hostProfileId: flags.get('host') } : {}),
129
128
  ...(flags.get('project') !== undefined ? { projectId: flags.get('project') } : {}),
130
129
  },
@@ -159,10 +158,8 @@ export async function runMakaTextCliCore(argv, adapter, overrides = {}) {
159
158
  ? { explicitConnection: parsed.options.connection }
160
159
  : {}),
161
160
  ...(parsed.options.model !== undefined ? { explicitModel: parsed.options.model } : {}),
162
- thinkingSpecified: parsed.options.thinking !== undefined || parsed.options.thinkingDefaultExplicit === true,
163
- ...(parsed.options.thinking !== undefined
164
- ? { explicitThinking: parsed.options.thinking }
165
- : {}),
161
+ thinkingSpecified: parsed.options.thinking !== undefined,
162
+ ...(parsed.options.thinking != null ? { explicitThinking: parsed.options.thinking } : {}),
166
163
  }, {
167
164
  canonicalizeDirectory: canonicalDirectory,
168
165
  ...(parsed.options.hostProfileId && parsed.options.hostProfileId !== 'local'
@@ -381,7 +378,7 @@ function makaRunHelpText(cliCommand) {
381
378
  ' --host <profile-id> Connect through a saved Runtime Host profile',
382
379
  ' --project <project-id> Select an existing Project on a remote Host',
383
380
  ' --model <id> Model to use',
384
- ' --thinking <level> off|minimal|low|medium|high|xhigh|max|default',
381
+ ' --thinking <level> off|on|minimal|low|medium|high|xhigh|max|default',
385
382
  ' --timeout <seconds> Invocation timeout',
386
383
  ' --max-steps <count> Tool-step cap',
387
384
  ' --yolo Give this task full access to your files and network',
@@ -159,12 +159,12 @@ class RuntimeHostMakaSessionDriverImpl {
159
159
  this.#llmConnectionId = input.llmConnectionId;
160
160
  this.#llmConnectionSlug = input.llmConnectionSlug;
161
161
  this.#model = input.model;
162
- this.#thinkingLevel = input.thinkingLevel;
162
+ this.#thinkingLevel = input.thinkingLevel ?? undefined;
163
163
  // An omitted mode stays omitted: the Host applies its configured default.
164
164
  // Substituting a literal `ask` here would make the CLI a second authority
165
165
  // over the starting boundary and silently override that default.
166
166
  this.#permissionMode = input.permissionMode;
167
- const session = await this.#createSession(input.name ?? DEFAULT_SESSION_NAME);
167
+ const session = await this.#createSession(input.name ?? DEFAULT_SESSION_NAME, input.thinkingLevel);
168
168
  return projectSessionCatalogSummary(session);
169
169
  }
170
170
  async listSessions(options = {}) {
@@ -1139,7 +1139,7 @@ class RuntimeHostMakaSessionDriverImpl {
1139
1139
  this.#sessionCreation = undefined;
1140
1140
  }
1141
1141
  }
1142
- async #createSession(name) {
1142
+ async #createSession(name, thinkingLevel = this.#thinkingLevel) {
1143
1143
  const workspace = this.#workspace.target;
1144
1144
  if (!workspace) {
1145
1145
  throw new Error('A remote Runtime Host Session requires an explicit Project');
@@ -1163,7 +1163,7 @@ class RuntimeHostMakaSessionDriverImpl {
1163
1163
  ...(this.#orchestrationMode === 'default'
1164
1164
  ? {}
1165
1165
  : { orchestrationMode: this.#orchestrationMode }),
1166
- ...(this.#thinkingLevel === undefined ? {} : { thinkingLevel: this.#thinkingLevel }),
1166
+ ...(thinkingLevel === undefined ? {} : { thinkingLevel }),
1167
1167
  }));
1168
1168
  this.#sessionGeneration += 1;
1169
1169
  this.#sessionId = sessionId;
@@ -178,6 +178,7 @@ const TUI_COPY_RESOURCES_PICKERS_EN = {
178
178
  addAccount: 'add account',
179
179
  thinkingLevels: {
180
180
  off: 'Off',
181
+ on: 'On',
181
182
  minimal: 'Minimal',
182
183
  low: 'Low',
183
184
  medium: 'Medium',
@@ -921,6 +922,7 @@ export const TUI_COPY_RESOURCES = {
921
922
  addAccount: '添加账号',
922
923
  thinkingLevels: {
923
924
  off: '关',
925
+ on: '开',
924
926
  minimal: '最小',
925
927
  low: '低',
926
928
  medium: '中',
@@ -1045,6 +1047,7 @@ export const TUI_COPY_RESOURCES = {
1045
1047
  addAccount: '新增帳號',
1046
1048
  thinkingLevels: {
1047
1049
  off: '關',
1050
+ on: '開',
1048
1051
  minimal: '最小',
1049
1052
  low: '低',
1050
1053
  medium: '中',
@@ -1,6 +1,7 @@
1
1
  // ../core/dist/model-thinking.js
2
2
  var THINKING_LEVELS = [
3
3
  "off",
4
+ "on",
4
5
  "minimal",
5
6
  "low",
6
7
  "medium",
@@ -8,7 +9,7 @@ var THINKING_LEVELS = [
8
9
  "xhigh",
9
10
  "max"
10
11
  ];
11
- var DECLARABLE_RELAY_THINKING_LEVELS = THINKING_LEVELS.filter((level) => level !== "off");
12
+ var DECLARABLE_RELAY_THINKING_LEVELS = THINKING_LEVELS.filter((level) => level !== "off" && level !== "on");
12
13
 
13
14
  // src/model-presentation.ts
14
15
  function describeAntigravityModels(models) {
@@ -439,6 +439,14 @@ const COMMAND_CODE_MODEL_METADATA = {
439
439
  function buildStaticModelMetadata(active) {
440
440
  return {
441
441
  anthropic: ANTHROPIC_MODEL_OVERRIDES,
442
+ opencode: {
443
+ 'claude-sonnet-4-5': {
444
+ thinkingOptions: ANTHROPIC_MODEL_OVERRIDES['claude-sonnet-4-5'].thinkingOptions,
445
+ },
446
+ 'claude-haiku-4-5': {
447
+ thinkingOptions: ANTHROPIC_MODEL_OVERRIDES['claude-haiku-4-5'].thinkingOptions,
448
+ },
449
+ },
442
450
  openai: OPENAI_GPT6_MODEL_OVERRIDES,
443
451
  'claude-subscription': claudeSubscriptionModelMetadata(active),
444
452
  // The Command Code Provider-API plan rides the same effort table.
@@ -20,6 +20,7 @@ import { lookupModelMetadata } from './model-metadata.js';
20
20
  import { isModelApiProtocol } from './provider-registry.js';
21
21
  export const THINKING_LEVELS = [
22
22
  'off',
23
+ 'on',
23
24
  'minimal',
24
25
  'low',
25
26
  'medium',
@@ -27,29 +28,12 @@ export const THINKING_LEVELS = [
27
28
  'xhigh',
28
29
  'max',
29
30
  ];
30
- /**
31
- * The levels a generic-relay declaration may hold — the vocabulary the
32
- * settings surfaces offer and the one the data layer admits. `off` is the
33
- * sole exclusion: it is not an intensity tier but a *disable* wire
34
- * (`reasoning_effort: 'none'`), and no generic relay is presumed to honor
35
- * that encoding; built-in providers that support it get `off` from their own
36
- * metadata instead. `minimal` and every effort tier above are pure
37
- * intensity values — the user declaring them is the authority on what the
38
- * relay accepts.
39
- */
40
- export const DECLARABLE_RELAY_THINKING_LEVELS = THINKING_LEVELS.filter((level) => level !== 'off');
31
+ /** Relay declarations contain effort tiers; switches require a provider-specific wire. */
32
+ export const DECLARABLE_RELAY_THINKING_LEVELS = THINKING_LEVELS.filter((level) => level !== 'off' && level !== 'on');
41
33
  export function isThinkingLevel(value) {
42
34
  return typeof value === 'string' && THINKING_LEVELS.includes(value);
43
35
  }
44
- /**
45
- * Derive the user-facing thinking-level choices from a model's declared
46
- * `ThinkingOptions`. `none` (OpenAI's off effort) and declared `offBehavior`
47
- * surface as `'off'`; other effort values map to the same-named
48
- * `ThinkingLevel`. Raw `toggle` alone is intentionally not enough because some
49
- * adapters have no real disabled wire. Unknown effort values (not in
50
- * `ThinkingLevel`) are dropped. Returns `[]` for models with no declared
51
- * options (miss → no thinking menu, fallback default).
52
- */
36
+ /** Only expose controls the adapter can encode; unknown effort values are ignored. */
53
37
  function deriveThinkingChoices(options) {
54
38
  if (!options)
55
39
  return [];
@@ -59,10 +43,13 @@ function deriveThinkingChoices(options) {
59
43
  for (const effort of options.efforts ?? []) {
60
44
  if (effort === 'none')
61
45
  choices.add('off');
62
- else if (isThinkingLevel(effort))
46
+ else if (DECLARABLE_RELAY_THINKING_LEVELS.includes(effort)) {
63
47
  choices.add(effort);
64
- // Unknown effort values (not in ThinkingLevel) are dropped — add the
65
- // level to THINKING_LEVELS if a provider introduces a new effort tier.
48
+ }
49
+ }
50
+ // Legacy Claude models need an explicit enabled request and have no effort knob.
51
+ if (options.offBehavior === 'anthropic-thinking-disabled' && choices.size === 1) {
52
+ choices.add('on');
66
53
  }
67
54
  return THINKING_LEVELS.filter((level) => choices.has(level));
68
55
  }
@@ -108,12 +95,6 @@ function normalizeModelOverride(entry) {
108
95
  return undefined;
109
96
  const declared = {};
110
97
  if (Array.isArray(entry.thinkingLevels)) {
111
- // Declared levels are filtered to the declarable vocabulary, not merely
112
- // the level vocabulary: `off` is a disable-wire encoding no generic
113
- // relay is presumed to speak, and a declaration table has no business
114
- // carrying it. The codec rejects it in persisted documents for the same
115
- // reason; normalize silently drops it because it also sanitizes input
116
- // that never passed a validator (settings drafts, hand-edited tables).
117
98
  const declaredSet = new Set(entry.thinkingLevels.filter((level) => isThinkingLevel(level) &&
118
99
  DECLARABLE_RELAY_THINKING_LEVELS.includes(level)));
119
100
  if (declaredSet.size > 0) {
@@ -635,7 +635,15 @@ function optionalTimestamp(value) {
635
635
  return null;
636
636
  return value;
637
637
  }
638
- function eligibleSessions(sessions, filter) {
638
+ /** Complete read-only history corpus for plugin organizers; same privacy and
639
+ * revision rules as Recall, without the search query's scan-count cap. */
640
+ export async function listRecallHistorySessions(deps, activeSessionId) {
641
+ const privacy = validateWorkspacePrivacyContext(await deps.getPrivacyContext());
642
+ if (!privacy.ok || privacy.value.incognitoActive)
643
+ throw new Error('History is unavailable while workspace privacy cannot be verified or incognito is active');
644
+ return eligibleSessions(collapseSessionRevisions(await deps.listSessions(), activeSessionId), { includeArchived: false }, Number.POSITIVE_INFINITY);
645
+ }
646
+ function eligibleSessions(sessions, filter, limit = MAX_SESSIONS_SCANNED) {
639
647
  return sessions
640
648
  .filter((session) =>
641
649
  // Retired simulator transcripts are task records, not real history;
@@ -647,7 +655,7 @@ function eligibleSessions(sessions, filter) {
647
655
  const byTime = (right.lastMessageAt ?? 0) - (left.lastMessageAt ?? 0);
648
656
  return byTime !== 0 ? byTime : left.id.localeCompare(right.id);
649
657
  })
650
- .slice(0, MAX_SESSIONS_SCANNED);
658
+ .slice(0, limit);
651
659
  }
652
660
  async function readFacts(deps, terms, options) {
653
661
  if (!deps.searchFacts)
@@ -965,3 +965,5 @@ function inferLegacyTurnStatus(messages) {
965
965
  return 'failed';
966
966
  return 'completed';
967
967
  }
968
+ /** Durable provenance for assistant-created workers; visibility is a client preference. */
969
+ export const ASSISTANT_BACKGROUND_SESSION_LABEL = 'personal-assistant-background';
@@ -340,6 +340,7 @@ export function createDefaultSettings() {
340
340
  activeTab: 'requests',
341
341
  },
342
342
  appearance: {
343
+ showAssistantBackgroundSessions: false,
343
344
  workbarTogglePosition: 'titlebar',
344
345
  theme: 'auto',
345
346
  palette: 'default',
@@ -517,6 +518,7 @@ export function normalizeSettings(input) {
517
518
  // position; UI density is no longer a product setting.
518
519
  appearance: {
519
520
  ...appearanceWithoutLegacyFields,
521
+ showAssistantBackgroundSessions: base.appearance.showAssistantBackgroundSessions === true,
520
522
  workbarTogglePosition: base.appearance.workbarTogglePosition === 'edge' ? 'edge' : 'titlebar',
521
523
  palette: isThemePalette(base.appearance.palette) ? base.appearance.palette : 'default',
522
524
  // Same fail-closed rule as `palette` above, for the same reason: an
@@ -81,5 +81,6 @@ export function normalizeSubagentSettings(input) {
81
81
  enabled: value.enabled,
82
82
  });
83
83
  }
84
- return { presets };
84
+ const enabled = input.enabled;
85
+ return { ...(typeof enabled === 'boolean' ? { enabled } : {}), presets };
85
86
  }
@@ -1121,6 +1121,7 @@ export class AiSdkTurn {
1121
1121
  const requestProjection = shapedProjection;
1122
1122
  const completedProviderSteps = [];
1123
1123
  let requestMessages = messages;
1124
+ let finishFeedback;
1124
1125
  let result;
1125
1126
  let providerOutcome;
1126
1127
  let finishReason = 'stop';
@@ -1161,10 +1162,12 @@ export class AiSdkTurn {
1161
1162
  }
1162
1163
  const requestSystemPromptBase = joinPromptFragments([
1163
1164
  systemPrompt,
1165
+ finishFeedback,
1164
1166
  finalChildSummaryStep ? CHILD_STEP_BUDGET_FINALIZATION_PROMPT : undefined,
1165
1167
  toolRuntime.hasSandboxBoundaryDenial() ? SANDBOX_BOUNDARY_DENIED_FOR_TURN : undefined,
1166
1168
  sandboxBoundaryFinalizationStep ? SANDBOX_BOUNDARY_FINALIZATION_PROMPT : undefined,
1167
1169
  ]);
1170
+ finishFeedback = undefined;
1168
1171
  const codeModeCatalogPrompt = toolMode === 'code_mode'
1169
1172
  ? renderCodeModeCatalogPrompt(toolRuntime.hasSandboxBoundaryDenial()
1170
1173
  ? new Map([...nestedTools].filter(([name]) => name !== REQUEST_SANDBOX_BOUNDARY_TOOL_NAME))
@@ -1929,6 +1932,26 @@ export class AiSdkTurn {
1929
1932
  continue agentLoop;
1930
1933
  }
1931
1934
  }
1935
+ if (mayTakeAnotherStep &&
1936
+ returnedToolCalls.length === 0 &&
1937
+ this.deps.backend.beforeTurnFinish &&
1938
+ this.deps.backend.loadTurnRuntimeEvents &&
1939
+ this.deps.modelAdapter.mapFinishReason(finishReason) === 'end_turn') {
1940
+ const decision = await this.deps.backend.beforeTurnFinish({
1941
+ sessionId: this.deps.backend.sessionId,
1942
+ turnId,
1943
+ signal: turnAbortController.signal,
1944
+ });
1945
+ if (!decision.allow && !this.aborted && !this.loopStopRequested) {
1946
+ if ((await input.handoffBoundary?.(turnAbortController.signal, maxSteps === undefined ? null : maxSteps - runtimeSteps)) === 'pause') {
1947
+ this.handoffPaused = true;
1948
+ break agentLoop;
1949
+ }
1950
+ finishFeedback = decision.feedback;
1951
+ currentStepMessageId = this.deps.newId();
1952
+ continue agentLoop;
1953
+ }
1954
+ }
1932
1955
  break agentLoop;
1933
1956
  }
1934
1957
  // Refine Tool Availability against the final active set. Deferred
@@ -1091,6 +1091,9 @@ export function lowerModelTools(tools) {
1091
1091
  ? { description: definition.description }
1092
1092
  : {}),
1093
1093
  inputSchema: definition.inputSchema,
1094
+ // Responses otherwise promotes optional properties to required filters.
1095
+ // Maka validates the original tool schema at dispatch.
1096
+ strict: false,
1094
1097
  },
1095
1098
  ]));
1096
1099
  }
@@ -26,7 +26,6 @@ import { createOpenResponses } from '@ai-sdk/open-responses';
26
26
  import { createOpenAI } from '@ai-sdk/openai';
27
27
  import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
28
28
  import { isJSONArray, } from '@ai-sdk/provider';
29
- import { lookupModelMetadata } from '@maka/core/model-metadata';
30
29
  import { modelOverride, resolveThinkingLevel, THINKING_LEVELS, supportsCustomFastServiceTier, thinkingOptionsForModel, thinkingVariantsForConnection, } from '@maka/core/model-thinking';
31
30
  import { createOpenAiChatReasoningTransport, createOpenAiChatReasoningTransportState, } from './openai-chat-reasoning-transport.js';
32
31
  import { openResponsesUrl } from './provider-urls.js';
@@ -304,54 +303,29 @@ function modelFamilyId(modelId) {
304
303
  function claudeFamilyId(modelId) {
305
304
  return modelFamilyId(modelId).replace(/^(claude-(?:haiku|opus|sonnet)-\d+)\.(\d+)(?=$|-)/, '$1-$2');
306
305
  }
307
- function defaultOpenAiReasoningEffort(modelId) {
308
- const familyModelId = modelFamilyId(modelId);
309
- return thinkingOptionsForModel('openai', familyModelId)?.efforts?.includes('medium')
310
- ? 'medium'
311
- : undefined;
312
- }
313
306
  function openAiResponsesSummary(modelId, reasoningEffort) {
314
- return reasoningEffort !== 'none' && defaultOpenAiReasoningEffort(modelId) !== undefined
307
+ return reasoningEffort !== 'none' &&
308
+ (thinkingOptionsForModel('openai', modelFamilyId(modelId))?.efforts?.length ?? 0) > 0
315
309
  ? { reasoningSummary: 'auto' }
316
310
  : {};
317
311
  }
318
- function visibleClaudeThinking(providerType, modelId, thinkingOptions, effort) {
319
- const mode = claudeThinkingMode(providerType, modelId, thinkingOptions);
320
- if (!mode)
312
+ function claudeThinkingOptions(modelId, level) {
313
+ if (level === undefined || level === 'off')
321
314
  return undefined;
322
- const thinking = mode === 'adaptive'
323
- ? { type: 'adaptive', display: 'summarized' }
324
- : { type: 'enabled', budgetTokens: 1_024 };
325
- return {
326
- thinking,
327
- ...(effort ? { effort } : {}),
328
- };
329
- }
330
- function claudeThinkingMode(providerType, modelId, thinkingOptions) {
331
315
  const familyModelId = claudeFamilyId(modelId);
332
316
  if (!familyModelId.startsWith('claude-'))
333
317
  return undefined;
334
- const providerMetadata = lookupModelMetadata(providerType, modelId);
335
- const anthropicMetadata = lookupModelMetadata('anthropic', familyModelId);
336
318
  const isKnownBareLegacyClaude4 = /^claude-(?:opus|sonnet)-4$/.test(familyModelId);
337
- const effectiveOptions = thinkingOptions ??
338
- providerMetadata.thinkingOptions ??
339
- anthropicMetadata.thinkingOptions ??
340
- thinkingOptionsForModel('anthropic', familyModelId);
341
- const supportsThinking = effectiveOptions?.toggle === true ||
342
- (effectiveOptions?.efforts?.length ?? 0) > 0 ||
343
- providerMetadata.capabilities?.reasoning === true ||
344
- anthropicMetadata.capabilities?.reasoning === true ||
345
- isKnownBareLegacyClaude4;
346
- if (!supportsThinking)
347
- return undefined;
348
319
  // The SDK's capability table only recognizes dated Claude 4 aliases. The
349
320
  // active bare aliases are the same legacy budget-thinking families.
350
- if (isKnownBareLegacyClaude4)
351
- return 'legacy';
352
- return getAnthropicModelCapabilities(familyModelId).supportsAdaptiveThinking
353
- ? 'adaptive'
354
- : 'legacy';
321
+ const adaptive = !isKnownBareLegacyClaude4 &&
322
+ getAnthropicModelCapabilities(familyModelId).supportsAdaptiveThinking;
323
+ return {
324
+ thinking: adaptive
325
+ ? { type: 'adaptive', display: 'summarized' }
326
+ : { type: 'enabled', budgetTokens: 1_024 },
327
+ ...(level === 'on' ? {} : { effort: level }),
328
+ };
355
329
  }
356
330
  /**
357
331
  * The level that asks this model for the least reasoning it accepts, for
@@ -400,33 +374,23 @@ function buildThinkingProviderOptions(connection, modelId, thinkingLevel, runtim
400
374
  }
401
375
  : {};
402
376
  }
403
- return buildFamilyWire(connection, modelId, level, thinkingOptions, thinkingLevel, runtime);
377
+ return buildFamilyWire(connection, modelId, level, thinkingOptions, runtime);
404
378
  case 'kimi-coding-plan': {
405
- // Kimi's coding route has no off wire. Check the raw argument, not the
406
- // normalized level: the entry gate above drops unsupported levels to
407
- // undefined (default max), but an explicit off must be rejected, never
408
- // silently upgraded to max. Today off cannot reach this branch through
409
- // the UI (variants exclude it), but a direct runtime caller or a future
410
- // models.dev `none` declaration must fail loudly, and the wire-contract
411
- // sweep keeps that tripwire armed.
412
- if (thinkingLevel === 'off')
379
+ if (!level || level === 'off' || level === 'on')
413
380
  return {};
414
- const effort = level ?? 'max';
415
381
  if (runtime.wire === 'openai-chat') {
416
382
  // The kimiCodingPlan provider-options namespace is the
417
383
  // openai-compatible adapter name; ai-sdk resolves its camelCase
418
384
  // alias to the kimi-coding-plan schema key (reasoning_effort).
419
385
  return {
420
- kimiCodingPlan: { reasoningEffort: effort },
386
+ kimiCodingPlan: { reasoningEffort: level },
421
387
  };
422
388
  }
423
389
  return {
424
390
  anthropic: modelId === 'k3' || modelId === 'k3-256k'
425
391
  ? {
426
- // K3 (and its 256k-context variant) supports adaptive thinking
427
- // only; effort defaults to max when unset.
428
392
  thinking: { type: 'adaptive' },
429
- effort,
393
+ effort: level,
430
394
  }
431
395
  : modelId === 'kimi-for-coding'
432
396
  ? {
@@ -434,7 +398,7 @@ function buildThinkingProviderOptions(connection, modelId, thinkingLevel, runtim
434
398
  // Anthropic AI SDK also requires a compatibility budget and
435
399
  // otherwise injects the same value with a warning.
436
400
  thinking: { type: 'enabled', budgetTokens: 1_024 },
437
- effort,
401
+ effort: level,
438
402
  }
439
403
  : {
440
404
  // kimi-for-coding-highspeed has no declared effort and no
@@ -450,17 +414,14 @@ function buildThinkingProviderOptions(connection, modelId, thinkingLevel, runtim
450
414
  case 'MiniMax':
451
415
  case 'MiniMax-cn': {
452
416
  let reasoning = {};
453
- const summarizedThinking = connection.providerType === 'anthropic' &&
454
- (thinkingLevel === undefined || level !== undefined)
455
- ? visibleClaudeThinking(connection.providerType, modelId, thinkingOptions, level)
456
- : undefined;
417
+ const summarizedThinking = connection.providerType === 'anthropic' ? claudeThinkingOptions(modelId, level) : undefined;
457
418
  if (level === 'off' && thinkingOptions?.offBehavior === 'anthropic-thinking-disabled') {
458
419
  reasoning = { thinking: { type: 'disabled' } };
459
420
  }
460
421
  else if (summarizedThinking) {
461
422
  reasoning = summarizedThinking;
462
423
  }
463
- else if (level && level !== 'off') {
424
+ else if (level && level !== 'off' && level !== 'on') {
464
425
  reasoning = { effort: level };
465
426
  }
466
427
  return {
@@ -472,30 +433,17 @@ function buildThinkingProviderOptions(connection, modelId, thinkingLevel, runtim
472
433
  },
473
434
  };
474
435
  }
475
- case 'openai-codex': {
476
- const reasoningEffort = level === 'off'
477
- ? 'none'
478
- : (level ??
479
- (thinkingLevel === undefined ? defaultOpenAiReasoningEffort(modelId) : undefined));
480
- return {
481
- openai: {
482
- store: false,
483
- textVerbosity: 'medium',
484
- ...openAiResponsesSummary(modelId, reasoningEffort),
485
- ...(reasoningEffort ? { reasoningEffort } : {}),
486
- },
487
- };
488
- }
436
+ case 'openai-codex':
489
437
  case 'openai': {
490
- const usesResponses = runtime.wire === 'openai-responses';
491
- const reasoningEffort = level === 'off'
492
- ? 'none'
493
- : (level ??
494
- (thinkingLevel === undefined ? defaultOpenAiReasoningEffort(modelId) : undefined));
438
+ const isCodex = connection.providerType === 'openai-codex';
439
+ const reasoningEffort = level === 'off' ? 'none' : level;
495
440
  return {
496
441
  openai: {
497
442
  store: false,
498
- ...(usesResponses ? openAiResponsesSummary(modelId, reasoningEffort) : {}),
443
+ ...(isCodex ? { textVerbosity: 'medium' } : {}),
444
+ ...(runtime.wire === 'openai-responses'
445
+ ? openAiResponsesSummary(modelId, reasoningEffort)
446
+ : {}),
499
447
  ...(reasoningEffort ? { reasoningEffort } : {}),
500
448
  },
501
449
  };
@@ -520,11 +468,11 @@ function buildThinkingProviderOptions(connection, modelId, thinkingLevel, runtim
520
468
  },
521
469
  };
522
470
  }
523
- return buildFamilyWire(connection, modelId, level, thinkingOptions, thinkingLevel, runtime);
471
+ return buildFamilyWire(connection, modelId, level, thinkingOptions, runtime);
524
472
  case 'volcengine-ark':
525
473
  return {
526
474
  [toCamelCase(connection.providerType)]: {
527
- thinking: { type: level === 'off' ? 'disabled' : 'enabled' },
475
+ ...(level ? { thinking: { type: level === 'off' ? 'disabled' : 'enabled' } } : {}),
528
476
  ...(level && level !== 'off' ? { reasoningEffort: level } : {}),
529
477
  },
530
478
  };
@@ -564,7 +512,7 @@ function buildThinkingProviderOptions(connection, modelId, thinkingLevel, runtim
564
512
  // above (level is defined only when metadata declares it) is what makes
565
513
  // this safe to generalize: undeclared models never reach the wire.
566
514
  default:
567
- return buildFamilyWire(connection, modelId, level, thinkingOptions, thinkingLevel, runtime);
515
+ return buildFamilyWire(connection, modelId, level, thinkingOptions, runtime);
568
516
  }
569
517
  }
570
518
  function withParallelToolCallOptions(connection, modelId, options, runtime) {
@@ -601,9 +549,9 @@ function withParallelToolCallOptions(connection, modelId, options, runtime) {
601
549
  },
602
550
  };
603
551
  }
604
- function buildFamilyWire(connection, modelId, level, thinkingOptions, requestedLevel, runtime) {
552
+ function buildFamilyWire(connection, modelId, level, thinkingOptions, runtime) {
605
553
  const { adapter, wire, reasoningReplay } = runtime;
606
- const explicitReasoningEffort = level ? (level === 'off' ? 'none' : level) : undefined;
554
+ const explicitReasoningEffort = level && level !== 'on' ? (level === 'off' ? 'none' : level) : undefined;
607
555
  // Provider selection and reasoning continuation are independent. The OpenAI
608
556
  // provider reads its provider-options namespace; the Open Responses provider
609
557
  // consumes a provider-native reasoningEffort through the same namespace,
@@ -625,34 +573,26 @@ function buildFamilyWire(connection, modelId, level, thinkingOptions, requestedL
625
573
  const serviceTier = supportsCustomFastServiceTier(connection, modelId)
626
574
  ? modelOverride(connection, modelId)?.serviceTier
627
575
  : undefined;
628
- const reasoningEffort = explicitReasoningEffort ??
629
- (requestedLevel === undefined ? defaultOpenAiReasoningEffort(modelId) : undefined);
630
576
  return {
631
577
  openai: {
632
578
  store: false,
633
579
  ...(reasons || reasoningReplay.contract.reasoningReplay === 'encrypted-content'
634
580
  ? { forceReasoning: true }
635
581
  : {}),
636
- ...openAiResponsesSummary(modelId, reasoningEffort),
637
- ...(reasoningEffort ? { reasoningEffort } : {}),
582
+ ...openAiResponsesSummary(modelId, explicitReasoningEffort),
583
+ ...(explicitReasoningEffort ? { reasoningEffort: explicitReasoningEffort } : {}),
638
584
  ...(serviceTier ? { serviceTier } : {}),
639
585
  },
640
586
  };
641
587
  }
642
- if (wire === 'anthropic-messages' && (requestedLevel === undefined || level !== undefined)) {
643
- const reasoning = visibleClaudeThinking(connection.providerType, modelId, thinkingOptions, explicitReasoningEffort);
588
+ if (wire === 'anthropic-messages') {
589
+ if (level === 'off' && thinkingOptions?.offBehavior === 'anthropic-thinking-disabled') {
590
+ return { anthropic: { thinking: { type: 'disabled' } } };
591
+ }
592
+ const reasoning = claudeThinkingOptions(modelId, level);
644
593
  if (reasoning)
645
594
  return { anthropic: reasoning };
646
595
  }
647
- if (wire === 'openai-chat' && adapter.kind === 'openai-compatible') {
648
- const reasoningEffort = explicitReasoningEffort ??
649
- (requestedLevel === undefined ? defaultOpenAiReasoningEffort(modelId) : undefined);
650
- if (reasoningEffort) {
651
- return {
652
- [openAiCompatibleProviderOptionsKey(connection)]: { reasoningEffort },
653
- };
654
- }
655
- }
656
596
  if (!explicitReasoningEffort)
657
597
  return {};
658
598
  switch (adapter.kind) {