[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
243
infrastructure/ai/types.test.ts
Normal file
243
infrastructure/ai/types.test.ts
Normal file
@@ -0,0 +1,243 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
import {
|
||||
CLAUDE_MODEL_PRESETS,
|
||||
CODEBUDDY_MODEL_PRESETS,
|
||||
CODEX_GPT_5_6_MIN_CLI_VERSION,
|
||||
CODEX_MODEL_PRESETS,
|
||||
CURSOR_MODEL_PRESETS,
|
||||
GROK_MODEL_PRESETS,
|
||||
extractCliSemver,
|
||||
filterAgentModelPresetsForCliVersion,
|
||||
getAgentModelPresets,
|
||||
resolveAgentCliVersion,
|
||||
resolveAgentModelSelection,
|
||||
resolveDiscoveredAgentCliVersion,
|
||||
} from './types';
|
||||
|
||||
test('Claude presets advertise effort levels separately from the model id', () => {
|
||||
for (const preset of CLAUDE_MODEL_PRESETS) {
|
||||
assert.deepEqual(preset.thinkingLevels, ['low', 'medium', 'high', 'max']);
|
||||
assert.ok(preset.defaultThinkingLevel);
|
||||
}
|
||||
assert.equal(resolveAgentModelSelection(CLAUDE_MODEL_PRESETS[0]!), 'default/medium');
|
||||
});
|
||||
|
||||
test('getAgentModelPresets returns CodeBuddy fallback models for command paths', () => {
|
||||
assert.deepEqual(
|
||||
getAgentModelPresets('/opt/homebrew/bin/codebuddy'),
|
||||
CODEBUDDY_MODEL_PRESETS,
|
||||
);
|
||||
assert.ok(CODEBUDDY_MODEL_PRESETS.some((model) => model.id === 'deepseek-v4-pro'));
|
||||
});
|
||||
|
||||
test('getAgentModelPresets returns Cursor presets for cursor-agent paths and sdkBackend', () => {
|
||||
assert.deepEqual(getAgentModelPresets('/Users/me/.local/bin/cursor-agent', 'cursor'), CURSOR_MODEL_PRESETS);
|
||||
assert.deepEqual(getAgentModelPresets('/usr/bin/cursor-agent'), CURSOR_MODEL_PRESETS);
|
||||
// Bare `agent` is no longer treated as Cursor without an explicit sdkBackend.
|
||||
assert.deepEqual(getAgentModelPresets('/Users/me/.local/bin/agent'), []);
|
||||
assert.equal(getAgentModelPresets('/Users/me/.local/bin/agent', 'cursor')[0]?.id, 'auto');
|
||||
assert.deepEqual(
|
||||
getAgentModelPresets(undefined, 'cursor').find((model) => model.id === 'gpt-5.5')?.thinkingLevels,
|
||||
['low', 'medium', 'high'],
|
||||
);
|
||||
assert.deepEqual(
|
||||
getAgentModelPresets(undefined, 'codebuddy')[0]?.thinkingLevels,
|
||||
['low', 'medium', 'high', 'xhigh'],
|
||||
);
|
||||
});
|
||||
|
||||
test('getAgentModelPresets keeps Codex presets separate from CodeBuddy presets', () => {
|
||||
assert.deepEqual(getAgentModelPresets('codex'), CODEX_MODEL_PRESETS);
|
||||
assert.notDeepEqual(CODEBUDDY_MODEL_PRESETS, CODEX_MODEL_PRESETS);
|
||||
});
|
||||
|
||||
test('getAgentModelPresets returns curated Grok fallback when runtime catalog is empty', () => {
|
||||
assert.ok(GROK_MODEL_PRESETS.length > 0);
|
||||
assert.deepEqual(getAgentModelPresets(undefined, 'grok'), GROK_MODEL_PRESETS);
|
||||
assert.deepEqual(getAgentModelPresets('/usr/local/bin/grok'), GROK_MODEL_PRESETS);
|
||||
assert.deepEqual(getAgentModelPresets('C:\\\\Tools\\\\grok.exe', 'grok'), GROK_MODEL_PRESETS);
|
||||
assert.equal(getAgentModelPresets(undefined, 'grok')[0]?.id, 'grok-4.5');
|
||||
assert.deepEqual(getAgentModelPresets(undefined, 'grok')[0]?.thinkingLevels, [
|
||||
'high',
|
||||
'medium',
|
||||
'low',
|
||||
]);
|
||||
assert.equal(getAgentModelPresets(undefined, 'grok')[0]?.defaultThinkingLevel, 'high');
|
||||
assert.deepEqual(getAgentModelPresets(undefined, 'grok')[1], {
|
||||
id: 'grok-4.6',
|
||||
name: 'Grok 4.6',
|
||||
thinkingLevels: ['xhigh', 'high', 'medium', 'low'],
|
||||
defaultThinkingLevel: 'high',
|
||||
});
|
||||
// Empty/failed runtime catalog path: shared resolver still yields a non-empty list.
|
||||
const runtimeCatalog: Array<{ id: string; name: string }> = [];
|
||||
const resolved = runtimeCatalog.length > 0
|
||||
? runtimeCatalog
|
||||
: getAgentModelPresets('grok', 'grok');
|
||||
assert.ok(resolved.length > 0);
|
||||
assert.deepEqual(resolved, GROK_MODEL_PRESETS);
|
||||
});
|
||||
|
||||
test('CODEX_MODEL_PRESETS lists GPT-5.6 Sol/Terra/Luna with official reasoning levels', () => {
|
||||
const byId = Object.fromEntries(CODEX_MODEL_PRESETS.map((model) => [model.id, model]));
|
||||
assert.deepEqual(
|
||||
CODEX_MODEL_PRESETS.map((model) => model.id),
|
||||
[
|
||||
'gpt-5.6-sol',
|
||||
'gpt-5.6-terra',
|
||||
'gpt-5.6-luna',
|
||||
'gpt-5.5',
|
||||
'gpt-5.4',
|
||||
'gpt-5.4-mini',
|
||||
'gpt-5.2',
|
||||
],
|
||||
);
|
||||
assert.equal(byId['gpt-5.6-sol']?.description, 'Latest');
|
||||
assert.equal(byId['gpt-5.6-sol']?.defaultThinkingLevel, 'low');
|
||||
assert.equal(byId['gpt-5.6-terra']?.defaultThinkingLevel, 'medium');
|
||||
assert.equal(byId['gpt-5.6-luna']?.defaultThinkingLevel, 'medium');
|
||||
assert.deepEqual(byId['gpt-5.6-sol']?.thinkingLevels, [
|
||||
'low',
|
||||
'medium',
|
||||
'high',
|
||||
'xhigh',
|
||||
'max',
|
||||
'ultra',
|
||||
]);
|
||||
assert.deepEqual(byId['gpt-5.6-terra']?.thinkingLevels, [
|
||||
'low',
|
||||
'medium',
|
||||
'high',
|
||||
'xhigh',
|
||||
'max',
|
||||
'ultra',
|
||||
]);
|
||||
// Luna omits ultra per openai/codex models-manager catalog (+ lobehub).
|
||||
assert.deepEqual(byId['gpt-5.6-luna']?.thinkingLevels, [
|
||||
'low',
|
||||
'medium',
|
||||
'high',
|
||||
'xhigh',
|
||||
'max',
|
||||
]);
|
||||
assert.deepEqual(byId['gpt-5.5']?.thinkingLevels, ['low', 'medium', 'high', 'xhigh']);
|
||||
assert.deepEqual(byId['gpt-5.4']?.thinkingLevels, ['low', 'medium', 'high', 'xhigh']);
|
||||
assert.deepEqual(byId['gpt-5.4-mini']?.thinkingLevels, ['low', 'medium', 'high', 'xhigh']);
|
||||
assert.deepEqual(byId['gpt-5.2']?.thinkingLevels, ['low', 'medium', 'high', 'xhigh']);
|
||||
});
|
||||
|
||||
test('resolveAgentModelSelection uses catalog default effort, not last array entry', () => {
|
||||
assert.equal(resolveAgentModelSelection(CODEX_MODEL_PRESETS[0]!), 'gpt-5.6-sol/low');
|
||||
assert.equal(
|
||||
resolveAgentModelSelection(CODEX_MODEL_PRESETS.find((m) => m.id === 'gpt-5.6-terra')!),
|
||||
'gpt-5.6-terra/medium',
|
||||
);
|
||||
assert.equal(
|
||||
resolveAgentModelSelection({
|
||||
id: 'custom',
|
||||
name: 'Custom',
|
||||
thinkingLevels: ['low', 'high'],
|
||||
}),
|
||||
'custom/low',
|
||||
);
|
||||
assert.equal(
|
||||
resolveAgentModelSelection({ id: 'plain', name: 'Plain' }),
|
||||
'plain',
|
||||
);
|
||||
assert.equal(
|
||||
resolveAgentModelSelection({
|
||||
id: 'glm-5.1',
|
||||
name: 'GLM 5.1',
|
||||
thinkingLevels: ['low', 'medium', 'high'],
|
||||
defaultThinkingLevel: 'medium',
|
||||
encodeDefaultThinking: false,
|
||||
}),
|
||||
'glm-5.1',
|
||||
);
|
||||
});
|
||||
|
||||
test('filterAgentModelPresetsForCliVersion gates GPT-5.6 on CLI < 0.144.0', () => {
|
||||
assert.equal(extractCliSemver('codex-cli 0.136.0'), '0.136.0');
|
||||
assert.equal(CODEX_GPT_5_6_MIN_CLI_VERSION, '0.144.0');
|
||||
|
||||
const oldCli = filterAgentModelPresetsForCliVersion(CODEX_MODEL_PRESETS, '0.136.0');
|
||||
assert.deepEqual(
|
||||
oldCli.map((model) => model.id),
|
||||
['gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.2'],
|
||||
);
|
||||
assert.equal(resolveAgentModelSelection(oldCli[0]!), 'gpt-5.5/medium');
|
||||
|
||||
const newCli = filterAgentModelPresetsForCliVersion(CODEX_MODEL_PRESETS, 'codex-cli 0.144.1');
|
||||
assert.equal(newCli[0]?.id, 'gpt-5.6-sol');
|
||||
|
||||
// Unknown version: hide version-gated models so pre-discovery cannot
|
||||
// auto-default old installs onto Sol. Ungated presets keep the picker usable.
|
||||
assert.deepEqual(
|
||||
filterAgentModelPresetsForCliVersion(CODEX_MODEL_PRESETS, undefined).map((m) => m.id),
|
||||
['gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.2'],
|
||||
);
|
||||
});
|
||||
|
||||
test('resolveDiscoveredAgentCliVersion matches command path or sdk backend', () => {
|
||||
assert.equal(
|
||||
resolveDiscoveredAgentCliVersion(
|
||||
{ command: '/usr/local/bin/codex', sdkBackend: 'codex' },
|
||||
[{ command: 'codex', path: '/usr/local/bin/codex', binPath: '/usr/local/bin/codex', sdkBackend: 'codex', version: '0.144.1' }],
|
||||
),
|
||||
'0.144.1',
|
||||
);
|
||||
// Manual path must not inherit PATH discovery version for a different binary.
|
||||
assert.equal(
|
||||
resolveDiscoveredAgentCliVersion(
|
||||
{ command: '/opt/old/codex', sdkBackend: 'codex' },
|
||||
[{ command: 'codex', path: '/usr/local/bin/codex', binPath: '/usr/local/bin/codex', sdkBackend: 'codex', version: '0.144.1' }],
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
assert.equal(
|
||||
resolveDiscoveredAgentCliVersion(
|
||||
{ command: 'codex', sdkBackend: 'codex' },
|
||||
[{ command: 'claude', path: '/bin/claude', binPath: '/bin/claude', sdkBackend: 'claude', version: '1.0.0' }],
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
assert.equal(
|
||||
resolveDiscoveredAgentCliVersion(
|
||||
{ command: 'codex', sdkBackend: 'codex' },
|
||||
[{ command: 'codex', path: '/usr/local/bin/codex', binPath: '/usr/local/bin/codex', sdkBackend: 'codex', version: '0.144.1' }],
|
||||
),
|
||||
'0.144.1',
|
||||
);
|
||||
});
|
||||
|
||||
test('resolveAgentCliVersion prefers stored cliVersion over discovery', () => {
|
||||
assert.equal(
|
||||
resolveAgentCliVersion(
|
||||
{ command: '/opt/custom/codex', sdkBackend: 'codex', cliVersion: 'codex-cli 0.144.3' },
|
||||
[{ command: 'codex', path: '/usr/local/bin/codex', binPath: '/usr/local/bin/codex', sdkBackend: 'codex', version: '0.136.0' }],
|
||||
),
|
||||
'codex-cli 0.144.3',
|
||||
);
|
||||
// Custom path with stored probe unlocks GPT-5.6 even when not on PATH.
|
||||
const gated = filterAgentModelPresetsForCliVersion(
|
||||
CODEX_MODEL_PRESETS,
|
||||
resolveAgentCliVersion(
|
||||
{ command: '/opt/custom/codex', sdkBackend: 'codex', cliVersion: '0.144.0' },
|
||||
[],
|
||||
),
|
||||
);
|
||||
assert.equal(gated[0]?.id, 'gpt-5.6-sol');
|
||||
});
|
||||
|
||||
test('getAgentModelPresets resolves Windows command paths with backslashes', () => {
|
||||
assert.deepEqual(
|
||||
getAgentModelPresets('C\\Users\\foo\\AppData\\Roaming\\npm\\codex.cmd'),
|
||||
CODEX_MODEL_PRESETS,
|
||||
);
|
||||
assert.deepEqual(
|
||||
getAgentModelPresets('C\\Program Files\\nodejs\\claude.exe'),
|
||||
CLAUDE_MODEL_PRESETS,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user