Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions packages/cli/src/__tests__/pi-tui-runner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,33 @@ describe('Maka Pi TUI runner', () => {
]);
});

test('shows the default thinking status for Ollama Cloud GLM-5.2', async () => {
const terminal = new FakeTerminal();
const driver = new SlashCommandDriver();
const run = runMakaPiTui({
title: 'Maka',
driver,
cwd: '/repo',
model: 'glm-5.2',
connectionSlug: 'ollama-cloud',
providerType: 'ollama-cloud',
permissionMode: 'ask',
terminal,
});

await waitFor(() => plainTerminalOutput(terminal.output()).includes(
'Maka · ask · glm-5.2 · thinking:default · ollama-cloud · /repo',
));

exitMaka(terminal);
await Promise.race([
run,
delay(50).then(() => {
throw new Error('TUI did not close during test cleanup');
}),
]);
});

test('handles /thinking off when the current model exposes a real off wire', async () => {
const terminal = new FakeTerminal();
const driver = new SlashCommandDriver();
Expand Down
21 changes: 18 additions & 3 deletions packages/core/src/__tests__/model-thinking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,30 @@ describe('thinkingOptionsForModel', () => {
);
});

test('Ollama Cloud exposes the documented OpenAI-compatible reasoning effort values', () => {
test('Ollama Cloud reasoning models expose off/low/medium/high/max; GPT-OSS low/medium/high only; deprecated excluded', () => {
assert.deepEqual(
thinkingOptionsForModel('ollama-cloud', 'qwen3.5:397b'),
{ efforts: ['none', 'low', 'medium', 'high'], toggle: true },
{ efforts: ['none', 'low', 'medium', 'high', 'max'], toggle: true },
);
assert.deepEqual(
[...thinkingVariantsForModel('ollama-cloud', 'qwen3.5:397b')],
['off', 'low', 'medium', 'high'],
['off', 'low', 'medium', 'high', 'max'],
);
assert.deepEqual(
[...thinkingVariantsForModel('ollama-cloud', 'glm-5.2')],
['off', 'low', 'medium', 'high', 'max'],
);
assert.deepEqual(
thinkingOptionsForModel('ollama-cloud', 'gpt-oss:120b'),
{ efforts: ['low', 'medium', 'high'] },
);
assert.deepEqual(
[...thinkingVariantsForModel('ollama-cloud', 'gpt-oss:120b')],
['low', 'medium', 'high'],
);
assert.deepEqual([...thinkingVariantsForModel('ollama-cloud', 'devstral-2:123b')], []);
assert.deepEqual([...thinkingVariantsForModel('ollama-cloud', 'cogito-2.1:671b')], []);
assert.deepEqual([...thinkingVariantsForModel('ollama-cloud', 'kimi-k2-thinking')], []);
});

test('claude-subscription inherits anthropic thinking options (displayMetadataOnly preserves them)', () => {
Expand Down
27 changes: 22 additions & 5 deletions packages/core/src/model-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,27 @@ const VOLCENGINE_CODING_PLAN_MODEL_METADATA: Record<string, ModelMetadata> = {
'kimi-k2.7-code': planModel('Kimi-K2.7-Code', true, 256_000, 32_000),
};

// Ollama Cloud accepts reasoning_effort for every active reasoning model in its
// generated catalog. GPT-OSS is the narrower exception and cannot be disabled.
const OLLAMA_CLOUD_STANDARD_THINKING_OPTIONS: ThinkingOptions = {
efforts: ['none', 'low', 'medium', 'high', 'max'],
toggle: true,
};

const OLLAMA_CLOUD_GPT_OSS_THINKING_OPTIONS: ThinkingOptions = {
efforts: ['low', 'medium', 'high'],
};

const ollamaCloudThinkingModels: Record<string, ModelMetadata> = Object.fromEntries(
Object.entries(GENERATED_MODELS_DEV_METADATA['ollama-cloud'])
.filter(([, metadata]) => metadata.capabilities?.reasoning && metadata.lifecycle !== 'deprecated')
.map(([id]) => [id, {
thinkingOptions: id.startsWith('gpt-oss')
? OLLAMA_CLOUD_GPT_OSS_THINKING_OPTIONS
: OLLAMA_CLOUD_STANDARD_THINKING_OPTIONS,
}]),
);

// Facts that models.dev cannot express: provider wire controls and
// access-path-specific aliases/limits. Standard model facts stay generated.
const STATIC_MODEL_METADATA: Partial<Record<ProviderType, Record<string, ModelMetadata>>> = {
Expand Down Expand Up @@ -225,11 +246,7 @@ const STATIC_MODEL_METADATA: Partial<Record<ProviderType, Record<string, ModelMe
},
},
},
'ollama-cloud': {
'qwen3.5:397b': {
thinkingOptions: { efforts: ['none', 'low', 'medium', 'high'], toggle: true },
},
},
'ollama-cloud': ollamaCloudThinkingModels,
deepseek: {
'deepseek-v4-flash': { thinkingOptions: { efforts: ['high', 'max'], toggle: true } },
},
Expand Down
17 changes: 17 additions & 0 deletions packages/runtime/src/__tests__/model-factory-thinking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,21 @@ describe('buildProviderOptions: thinking level', () => {
assert.deepEqual(buildProviderOptions(conn('vercel'), 'grok-4.3', 'high'), {});
});

test('Ollama Cloud sends reasoning effort under its namespace; standard models expose off, GPT-OSS does not', () => {
assert.deepEqual([...thinkingVariantsForModel('ollama-cloud', 'glm-5.2')], ['off', 'low', 'medium', 'high', 'max']);
assert.deepEqual(buildProviderOptions(conn('ollama-cloud'), 'glm-5.2', 'high'), {
'ollama-cloud': { reasoningEffort: 'high' },
});
assert.deepEqual(buildProviderOptions(conn('ollama-cloud'), 'glm-5.2', 'off'), {
'ollama-cloud': { reasoningEffort: 'none' },
});
assert.deepEqual([...thinkingVariantsForModel('ollama-cloud', 'gpt-oss:120b')], ['low', 'medium', 'high']);
assert.deepEqual(buildProviderOptions(conn('ollama-cloud'), 'gpt-oss:120b', 'high'), {
'ollama-cloud': { reasoningEffort: 'high' },
});
assert.deepEqual(buildProviderOptions(conn('ollama-cloud'), 'gpt-oss:120b', 'off'), {});
});

test('a level the model does not support is dropped (defensive)', () => {
assert.deepEqual(buildProviderOptions(conn('openai'), 'gpt-4o', 'high'), { openai: { store: false } });
assert.deepEqual(buildProviderOptions(conn('anthropic'), 'claude-haiku-4-5', 'max'), { anthropic: {} });
Expand Down Expand Up @@ -258,6 +273,8 @@ describe('buildProviderOptions: resolver/options drift guard', () => {
{ providerType: 'groq', model: 'openai/gpt-oss-120b' },
{ providerType: 'openrouter', model: 'openai/gpt-5.6-sol' },
{ providerType: 'vercel', model: 'xai/grok-4.3' },
{ providerType: 'ollama-cloud', model: 'glm-5.2' },
{ providerType: 'ollama-cloud', model: 'gpt-oss:120b' },
{ providerType: 'cloudflare-workers-ai', model: '@cf/moonshotai/kimi-k2.6' },
{ providerType: 'zai-coding-plan', model: 'glm-5.2', slug: 'zai-coding-plan' },
{ providerType: 'volcengine-ark', model: 'doubao-seed-2-0-pro-260215' },
Expand Down
Loading