converse-mcp-server 3.7.1 → 4.0.0
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/.env.example +17 -3
- package/README.md +67 -49
- package/docs/API.md +55 -18
- package/docs/EXAMPLES.md +38 -0
- package/docs/PROVIDERS.md +92 -52
- package/package.json +1 -1
- package/src/config.js +29 -5
- package/src/prompts/helpPrompt.js +27 -2
- package/src/providers/anthropic.js +5 -1
- package/src/providers/claude.js +39 -88
- package/src/providers/codex.js +73 -144
- package/src/providers/copilot.js +42 -149
- package/src/providers/deepseek.js +1 -0
- package/src/providers/gemini-cli.js +64 -97
- package/src/providers/google.js +5 -1
- package/src/providers/mistral.js +5 -1
- package/src/providers/openai-compatible.js +4 -1
- package/src/providers/openai.js +5 -1
- package/src/providers/openrouter.js +1 -0
- package/src/providers/xai.js +5 -1
- package/src/services/summarizationService.js +45 -49
- package/src/tools/chat.js +56 -52
- package/src/tools/modes/roundtable.js +60 -49
- package/src/utils/localProviderAuth.js +63 -0
- package/src/utils/modelCatalog.js +38 -0
- package/src/utils/modelRouting.js +580 -343
package/src/providers/copilot.js
CHANGED
|
@@ -18,29 +18,19 @@ import { fileURLToPath } from 'node:url';
|
|
|
18
18
|
import { debugLog, debugError } from '../utils/console.js';
|
|
19
19
|
import { ProviderError, ErrorCodes, StopReasons } from './interface.js';
|
|
20
20
|
import { clampReasoningEffort } from '../utils/reasoningEffort.js';
|
|
21
|
+
import { findCatalogEntry, findCatalogId } from '../utils/modelCatalog.js';
|
|
22
|
+
import { isPackageResolvable } from '../utils/localProviderAuth.js';
|
|
21
23
|
|
|
22
|
-
const
|
|
23
|
-
copilot: {
|
|
24
|
-
modelName: 'copilot',
|
|
25
|
-
friendlyName: 'GitHub Copilot (via CLI SDK)',
|
|
26
|
-
contextWindow: 128000,
|
|
27
|
-
maxOutputTokens: 16384,
|
|
28
|
-
supportsStreaming: true,
|
|
29
|
-
supportsImages: false,
|
|
30
|
-
supportsWebSearch: false,
|
|
31
|
-
timeout: 1800000,
|
|
32
|
-
description:
|
|
33
|
-
'GitHub Copilot via CLI SDK - uses default or env-configured model',
|
|
34
|
-
aliases: ['copilot-sdk', 'github-copilot'],
|
|
35
|
-
},
|
|
24
|
+
const DEFAULT_MODEL = 'gpt-6-sol';
|
|
36
25
|
|
|
26
|
+
// Keyed by the SDK model ID, which is also the canonical ID the router
|
|
27
|
+
// resolves to. Every name here is reached only through the `copilot:`
|
|
28
|
+
// namespace — Copilot never serves bare model names.
|
|
29
|
+
const SUPPORTED_MODELS = {
|
|
37
30
|
// OpenAI models
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
// latest GPT tier (reachable only via the `copilot:` namespace — bare
|
|
42
|
-
// `codex` routes to the Codex provider and bare `gpt*` keyword-routes to
|
|
43
|
-
// OpenAI before Copilot's catalog is consulted).
|
|
31
|
+
// `gpt-6` / `gpt-5.6` point at that generation's Sol, matching Copilot's own
|
|
32
|
+
// bare-alias behavior; `sol`/`luna` and the legacy `gpt-5` shortcut follow
|
|
33
|
+
// the current generation. `codex` and `gpt` point at the latest GPT tier.
|
|
44
34
|
'gpt-6-sol': {
|
|
45
35
|
modelName: 'gpt-6-sol',
|
|
46
36
|
friendlyName: 'GPT-6 Sol (via Copilot)',
|
|
@@ -205,22 +195,6 @@ class CopilotProviderError extends ProviderError {
|
|
|
205
195
|
}
|
|
206
196
|
}
|
|
207
197
|
|
|
208
|
-
/**
|
|
209
|
-
* Check if Copilot SDK is available (installed as dependency)
|
|
210
|
-
*/
|
|
211
|
-
let _sdkAvailable = null;
|
|
212
|
-
function isCopilotSDKAvailable() {
|
|
213
|
-
if (_sdkAvailable !== null) return _sdkAvailable;
|
|
214
|
-
try {
|
|
215
|
-
// Use synchronous resolve to check if the package exists
|
|
216
|
-
import.meta.resolve('@github/copilot-sdk');
|
|
217
|
-
_sdkAvailable = true;
|
|
218
|
-
} catch {
|
|
219
|
-
_sdkAvailable = false;
|
|
220
|
-
}
|
|
221
|
-
return _sdkAvailable;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
198
|
/**
|
|
225
199
|
* Dynamically import Copilot SDK (lazy loading)
|
|
226
200
|
*/
|
|
@@ -443,106 +417,24 @@ function createPermissionHandler(accessLevel) {
|
|
|
443
417
|
}
|
|
444
418
|
|
|
445
419
|
/**
|
|
446
|
-
* Resolve a
|
|
447
|
-
*
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
const lower = name.toLowerCase().trim();
|
|
452
|
-
if (!lower) return null;
|
|
453
|
-
|
|
454
|
-
// Direct key match
|
|
455
|
-
if (SUPPORTED_MODELS[lower] && lower !== 'copilot') {
|
|
456
|
-
return SUPPORTED_MODELS[lower].modelName;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// Alias match
|
|
460
|
-
for (const config of Object.values(SUPPORTED_MODELS)) {
|
|
461
|
-
if (config.modelName === 'copilot') continue;
|
|
462
|
-
if (
|
|
463
|
-
config.aliases &&
|
|
464
|
-
config.aliases.some((alias) => alias.toLowerCase() === lower)
|
|
465
|
-
) {
|
|
466
|
-
return config.modelName;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
return null;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* Look up model config from SUPPORTED_MODELS by name or alias.
|
|
475
|
-
* Strips copilot: prefix and falls back to the base copilot config.
|
|
476
|
-
*/
|
|
477
|
-
function findModelConfig(modelName) {
|
|
478
|
-
if (typeof modelName !== 'string') return null;
|
|
479
|
-
|
|
480
|
-
let name = modelName;
|
|
481
|
-
if (name.toLowerCase().startsWith('copilot:')) {
|
|
482
|
-
name = name.slice('copilot:'.length).trim();
|
|
483
|
-
}
|
|
484
|
-
if (!name) return SUPPORTED_MODELS.copilot;
|
|
485
|
-
|
|
486
|
-
const nameLower = name.toLowerCase();
|
|
487
|
-
|
|
488
|
-
if (SUPPORTED_MODELS[nameLower]) {
|
|
489
|
-
return SUPPORTED_MODELS[nameLower];
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
for (const config of Object.values(SUPPORTED_MODELS)) {
|
|
493
|
-
if (
|
|
494
|
-
config.aliases &&
|
|
495
|
-
config.aliases.some((alias) => alias.toLowerCase() === nameLower)
|
|
496
|
-
) {
|
|
497
|
-
return config;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
return null;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* Resolve model to pass to SDK session
|
|
506
|
-
* Precedence: explicit model param > config COPILOT_MODEL > omit (SDK default)
|
|
507
|
-
*
|
|
508
|
-
* Handles copilot: prefix stripping, alias resolution, and env var fallback.
|
|
509
|
-
* Note: "copilot" is a Converse routing alias, not a valid SDK model ID.
|
|
420
|
+
* Resolve a model name to the SDK model ID for the session. The router hands
|
|
421
|
+
* over canonical catalog IDs; aliases are accepted for direct callers.
|
|
422
|
+
* @param {string} [model] - Catalog ID or alias; defaults to DEFAULT_MODEL
|
|
423
|
+
* @returns {string}
|
|
424
|
+
* @throws {CopilotProviderError} When the name is not in the catalog
|
|
510
425
|
*/
|
|
511
|
-
function resolveSessionModel(
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
// Guard non-string inputs
|
|
515
|
-
if (typeof requestModel !== 'string') {
|
|
516
|
-
requestModel = '';
|
|
426
|
+
function resolveSessionModel(model) {
|
|
427
|
+
if (typeof model !== 'string' || !model.trim()) {
|
|
428
|
+
return DEFAULT_MODEL;
|
|
517
429
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
// Empty suffix or converse alias → use env/default
|
|
526
|
-
if (
|
|
527
|
-
!effectiveModel ||
|
|
528
|
-
converseAliases.includes(effectiveModel.toLowerCase())
|
|
529
|
-
) {
|
|
530
|
-
const envModel = config?.providers?.copilotmodel;
|
|
531
|
-
if (envModel) {
|
|
532
|
-
let resolved = typeof envModel === 'string' ? envModel : '';
|
|
533
|
-
if (resolved.toLowerCase().startsWith('copilot:')) {
|
|
534
|
-
resolved = resolved.slice('copilot:'.length).trim();
|
|
535
|
-
}
|
|
536
|
-
if (!resolved || converseAliases.includes(resolved.toLowerCase())) {
|
|
537
|
-
return undefined;
|
|
538
|
-
}
|
|
539
|
-
return resolveModelAlias(resolved) || resolved;
|
|
540
|
-
}
|
|
541
|
-
return undefined;
|
|
430
|
+
const id = findCatalogId(SUPPORTED_MODELS, model);
|
|
431
|
+
if (!id) {
|
|
432
|
+
throw new CopilotProviderError(
|
|
433
|
+
`Unknown Copilot model "${model}"`,
|
|
434
|
+
ErrorCodes.MODEL_NOT_FOUND,
|
|
435
|
+
);
|
|
542
436
|
}
|
|
543
|
-
|
|
544
|
-
// Resolve alias or passthrough unknown models to SDK
|
|
545
|
-
return resolveModelAlias(effectiveModel) || effectiveModel;
|
|
437
|
+
return SUPPORTED_MODELS[id].modelName;
|
|
546
438
|
}
|
|
547
439
|
|
|
548
440
|
/**
|
|
@@ -590,23 +482,20 @@ async function checkReasoningSupport(client, modelId) {
|
|
|
590
482
|
async function* createStreamingGenerator(client, prompt, options, signal, config) {
|
|
591
483
|
const { model, timeout = 1800000, reasoning_effort } = options;
|
|
592
484
|
|
|
593
|
-
const sessionModel = resolveSessionModel(model
|
|
485
|
+
const sessionModel = resolveSessionModel(model);
|
|
594
486
|
const accessLevel = getToolAccessLevel(config);
|
|
595
487
|
|
|
596
488
|
const sessionConfig = {
|
|
597
489
|
streaming: true,
|
|
598
490
|
onPermissionRequest: createPermissionHandler(accessLevel),
|
|
491
|
+
model: sessionModel,
|
|
599
492
|
};
|
|
600
493
|
|
|
601
|
-
if (sessionModel) {
|
|
602
|
-
sessionConfig.model = sessionModel;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
494
|
if (reasoning_effort) {
|
|
606
495
|
const mapped = mapReasoningEffort(reasoning_effort);
|
|
607
496
|
if (mapped) {
|
|
608
|
-
const effectiveModel = sessionModel
|
|
609
|
-
const modelDef =
|
|
497
|
+
const effectiveModel = sessionModel;
|
|
498
|
+
const modelDef = SUPPORTED_MODELS[sessionModel];
|
|
610
499
|
|
|
611
500
|
let supported;
|
|
612
501
|
if (modelDef && modelDef.supportsReasoningEffort !== undefined) {
|
|
@@ -650,7 +539,7 @@ async function* createStreamingGenerator(client, prompt, options, signal, config
|
|
|
650
539
|
yield {
|
|
651
540
|
type: 'start',
|
|
652
541
|
provider: 'copilot',
|
|
653
|
-
model: sessionModel
|
|
542
|
+
model: sessionModel,
|
|
654
543
|
};
|
|
655
544
|
|
|
656
545
|
// Bridge push-based SDK events to pull-based generator using queue + promise
|
|
@@ -775,7 +664,7 @@ async function* createStreamingGenerator(client, prompt, options, signal, config
|
|
|
775
664
|
}
|
|
776
665
|
}
|
|
777
666
|
|
|
778
|
-
export {
|
|
667
|
+
export { resolveSessionModel, resolveCopilotCliPath };
|
|
779
668
|
|
|
780
669
|
/**
|
|
781
670
|
* Copilot SDK Provider Implementation
|
|
@@ -783,7 +672,7 @@ export { resolveModelAlias, resolveSessionModel, resolveCopilotCliPath };
|
|
|
783
672
|
export const copilotProvider = {
|
|
784
673
|
async invoke(messages, options = {}) {
|
|
785
674
|
const {
|
|
786
|
-
model =
|
|
675
|
+
model = DEFAULT_MODEL,
|
|
787
676
|
config,
|
|
788
677
|
stream = false,
|
|
789
678
|
signal,
|
|
@@ -797,15 +686,17 @@ export const copilotProvider = {
|
|
|
797
686
|
);
|
|
798
687
|
}
|
|
799
688
|
|
|
689
|
+
// Validated before the client spawns the Copilot CLI.
|
|
690
|
+
const sessionModel = resolveSessionModel(model);
|
|
691
|
+
|
|
800
692
|
try {
|
|
801
693
|
const cwd = config.server?.client_cwd || process.cwd();
|
|
802
694
|
const client = await getCopilotClient(cwd, config);
|
|
803
695
|
const prompt = convertMessagesToPrompt(messages);
|
|
804
696
|
|
|
805
|
-
const
|
|
806
|
-
const modelConfig = findModelConfig(sessionModel || model) || SUPPORTED_MODELS.copilot;
|
|
697
|
+
const modelConfig = SUPPORTED_MODELS[sessionModel];
|
|
807
698
|
const invokeOptions = {
|
|
808
|
-
model,
|
|
699
|
+
model: sessionModel,
|
|
809
700
|
timeout: modelConfig.timeout,
|
|
810
701
|
reasoning_effort,
|
|
811
702
|
};
|
|
@@ -843,7 +734,7 @@ export const copilotProvider = {
|
|
|
843
734
|
rawResponse: { content, usage },
|
|
844
735
|
metadata: {
|
|
845
736
|
provider: 'copilot',
|
|
846
|
-
model: sessionModel
|
|
737
|
+
model: sessionModel,
|
|
847
738
|
usage: usage
|
|
848
739
|
? {
|
|
849
740
|
input_tokens: usage.input_tokens || 0,
|
|
@@ -901,12 +792,14 @@ export const copilotProvider = {
|
|
|
901
792
|
}
|
|
902
793
|
},
|
|
903
794
|
|
|
795
|
+
defaultModel: DEFAULT_MODEL,
|
|
796
|
+
|
|
904
797
|
/**
|
|
905
798
|
* Validate Copilot SDK configuration
|
|
906
799
|
* Returns true optimistically — auth errors surface at runtime
|
|
907
800
|
*/
|
|
908
801
|
validateConfig(_config) {
|
|
909
|
-
return
|
|
802
|
+
return isPackageResolvable('@github/copilot-sdk');
|
|
910
803
|
},
|
|
911
804
|
|
|
912
805
|
isAvailable(config) {
|
|
@@ -918,6 +811,6 @@ export const copilotProvider = {
|
|
|
918
811
|
},
|
|
919
812
|
|
|
920
813
|
getModelConfig(modelName) {
|
|
921
|
-
return
|
|
814
|
+
return findCatalogEntry(SUPPORTED_MODELS, modelName);
|
|
922
815
|
},
|
|
923
816
|
};
|
|
@@ -140,6 +140,7 @@ export const deepseekProvider = createOpenAICompatibleProvider({
|
|
|
140
140
|
baseURL: 'https://api.deepseek.com',
|
|
141
141
|
providerName: 'DeepSeek',
|
|
142
142
|
supportedModels: SUPPORTED_MODELS,
|
|
143
|
+
defaultModel: 'deepseek-v4-pro',
|
|
143
144
|
validateApiKey,
|
|
144
145
|
transformRequest,
|
|
145
146
|
transformResponse,
|
|
@@ -18,11 +18,10 @@
|
|
|
18
18
|
* interactively (`agy`) via Google OAuth. The first interactive login also
|
|
19
19
|
* establishes workspace trust for the user's home directory.
|
|
20
20
|
*
|
|
21
|
-
* The provider registry key remains 'gemini-cli'
|
|
22
|
-
*
|
|
23
|
-
* model
|
|
24
|
-
*
|
|
25
|
-
* lists first, while 3.1 Pro remains the only Pro tier Antigravity offers.
|
|
21
|
+
* The provider registry key remains 'gemini-cli'; its namespaces are `gemini:`
|
|
22
|
+
* and `agy:`. Flash is the default: Gemini 3.8 Flash is the current-generation
|
|
23
|
+
* model agy lists first, while 3.1 Pro remains the only Pro tier Antigravity
|
|
24
|
+
* offers.
|
|
26
25
|
*/
|
|
27
26
|
|
|
28
27
|
import { existsSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
|
@@ -32,6 +31,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
32
31
|
import { debugLog, debugError } from '../utils/console.js';
|
|
33
32
|
import { ProviderError, ErrorCodes, StopReasons } from './interface.js';
|
|
34
33
|
import { clampReasoningEffort } from '../utils/reasoningEffort.js';
|
|
34
|
+
import { findCatalogEntry } from '../utils/modelCatalog.js';
|
|
35
35
|
|
|
36
36
|
// Prompts at or below this length pass directly as the -p argv value (fast
|
|
37
37
|
// path). Larger prompts are written to a file and -p carries a bootstrap
|
|
@@ -53,13 +53,15 @@ const POST_KILL_GRACE_MS = 5000;
|
|
|
53
53
|
const PTY_COLS = 1000;
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
* Supported Gemini models
|
|
57
|
-
*
|
|
58
|
-
*
|
|
56
|
+
* Supported Gemini models, keyed by the same model IDs the Google API provider
|
|
57
|
+
* uses so a bare name resolves to one model whichever provider serves it. Each
|
|
58
|
+
* maps to an agy display-name base that gets a reasoning-effort suffix
|
|
59
|
+
* appended at spawn time. All are text-only (print mode has no image input
|
|
60
|
+
* channel).
|
|
59
61
|
*/
|
|
60
62
|
const SUPPORTED_MODELS = {
|
|
61
|
-
gemini: {
|
|
62
|
-
modelName: 'gemini',
|
|
63
|
+
'gemini-3.8-flash': {
|
|
64
|
+
modelName: 'gemini-3.8-flash',
|
|
63
65
|
friendlyName: 'Gemini 3.8 Flash (via Antigravity CLI)',
|
|
64
66
|
contextWindow: 1048576,
|
|
65
67
|
maxOutputTokens: 65536,
|
|
@@ -69,28 +71,23 @@ const SUPPORTED_MODELS = {
|
|
|
69
71
|
supportsThinking: true,
|
|
70
72
|
timeout: DEFAULT_TIMEOUT_MS,
|
|
71
73
|
description:
|
|
72
|
-
'Gemini 3.8 Flash via Antigravity CLI (agy) - requires Antigravity Google OAuth login',
|
|
73
|
-
aliases: [
|
|
74
|
+
'Gemini 3.8 Flash via Antigravity CLI (agy, default) - requires Antigravity Google OAuth login',
|
|
75
|
+
aliases: [
|
|
76
|
+
'flash',
|
|
77
|
+
'gemini-3.8',
|
|
78
|
+
'gemini3.8',
|
|
79
|
+
'gemini-3.8-flash-latest',
|
|
80
|
+
'flash-3.8',
|
|
81
|
+
'flash3.8',
|
|
82
|
+
'gemini-flash-3.8',
|
|
83
|
+
'gemini flash 3.8',
|
|
84
|
+
'3.8-flash',
|
|
85
|
+
],
|
|
74
86
|
// agy display-name base; reasoning_effort selects the parenthesized variant
|
|
75
87
|
agyModelBase: 'Gemini 3.8 Flash',
|
|
76
88
|
},
|
|
77
|
-
'gemini
|
|
78
|
-
modelName: 'gemini
|
|
79
|
-
friendlyName: 'Gemini 3.8 Flash (via Antigravity CLI)',
|
|
80
|
-
contextWindow: 1048576,
|
|
81
|
-
maxOutputTokens: 65536,
|
|
82
|
-
supportsStreaming: true,
|
|
83
|
-
supportsImages: false,
|
|
84
|
-
supportsWebSearch: false,
|
|
85
|
-
supportsThinking: true,
|
|
86
|
-
timeout: DEFAULT_TIMEOUT_MS,
|
|
87
|
-
description:
|
|
88
|
-
'Gemini 3.8 Flash via Antigravity CLI (agy) - explicit alias of `gemini`',
|
|
89
|
-
aliases: ['flash'],
|
|
90
|
-
agyModelBase: 'Gemini 3.8 Flash',
|
|
91
|
-
},
|
|
92
|
-
'gemini:pro': {
|
|
93
|
-
modelName: 'gemini:pro',
|
|
89
|
+
'gemini-3.1-pro-preview': {
|
|
90
|
+
modelName: 'gemini-3.1-pro-preview',
|
|
94
91
|
friendlyName: 'Gemini 3.1 Pro (via Antigravity CLI)',
|
|
95
92
|
contextWindow: 1048576,
|
|
96
93
|
maxOutputTokens: 65536,
|
|
@@ -101,11 +98,26 @@ const SUPPORTED_MODELS = {
|
|
|
101
98
|
timeout: DEFAULT_TIMEOUT_MS,
|
|
102
99
|
description:
|
|
103
100
|
'Gemini 3.1 Pro via Antigravity CLI (agy) - requires Antigravity Google OAuth login',
|
|
104
|
-
aliases: [
|
|
101
|
+
aliases: [
|
|
102
|
+
'pro',
|
|
103
|
+
'gemini-pro',
|
|
104
|
+
'gemini pro',
|
|
105
|
+
'gemini-3.1-pro',
|
|
106
|
+
'gemini-3.1',
|
|
107
|
+
'gemini3.1',
|
|
108
|
+
'3.1-pro',
|
|
109
|
+
'gemini-3',
|
|
110
|
+
'gemini3',
|
|
111
|
+
'gemini-3-pro',
|
|
112
|
+
'gemini-3-pro-preview',
|
|
113
|
+
'3-pro',
|
|
114
|
+
],
|
|
105
115
|
agyModelBase: 'Gemini 3.1 Pro',
|
|
106
116
|
},
|
|
107
117
|
};
|
|
108
118
|
|
|
119
|
+
const DEFAULT_MODEL = 'gemini-3.8-flash';
|
|
120
|
+
|
|
109
121
|
/**
|
|
110
122
|
* Custom error class for Gemini CLI (agy) provider errors
|
|
111
123
|
*/
|
|
@@ -197,45 +209,24 @@ function effortSuffix(base, reasoningEffort) {
|
|
|
197
209
|
}
|
|
198
210
|
|
|
199
211
|
/**
|
|
200
|
-
* Resolve a
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
* @param {string} model - e.g. 'gemini', 'gemini:flash', or a full agy name
|
|
212
|
+
* Resolve a model name + reasoning_effort to the agy display name passed via
|
|
213
|
+
* --model. The router hands over canonical catalog IDs; aliases are accepted
|
|
214
|
+
* for direct callers.
|
|
215
|
+
* @param {string} [model] - Catalog ID or alias; defaults to DEFAULT_MODEL
|
|
205
216
|
* @param {string} [reasoningEffort]
|
|
206
217
|
* @returns {string} agy --model value, e.g. 'Gemini 3.8 Flash (High)'
|
|
218
|
+
* @throws {GeminiCliProviderError} When the name is not in the catalog
|
|
207
219
|
*/
|
|
208
220
|
export function resolveAgyModel(model, reasoningEffort) {
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
let name = raw;
|
|
217
|
-
if (name.toLowerCase().startsWith('gemini:')) {
|
|
218
|
-
name = name.slice('gemini:'.length).trim();
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const nameLower = name.toLowerCase();
|
|
222
|
-
|
|
223
|
-
// Determine the agy base
|
|
224
|
-
let base;
|
|
225
|
-
if (
|
|
226
|
-
!nameLower ||
|
|
227
|
-
nameLower === 'gemini' ||
|
|
228
|
-
nameLower === 'gemini-cli' ||
|
|
229
|
-
nameLower === 'flash'
|
|
230
|
-
) {
|
|
231
|
-
base = SUPPORTED_MODELS.gemini.agyModelBase;
|
|
232
|
-
} else if (nameLower === 'pro') {
|
|
233
|
-
base = SUPPORTED_MODELS['gemini:pro'].agyModelBase;
|
|
234
|
-
} else {
|
|
235
|
-
// Unknown suffix: pass through verbatim (power-user agy display name)
|
|
236
|
-
return raw;
|
|
221
|
+
const name = typeof model === 'string' && model.trim() ? model : DEFAULT_MODEL;
|
|
222
|
+
const entry = findCatalogEntry(SUPPORTED_MODELS, name);
|
|
223
|
+
if (!entry) {
|
|
224
|
+
throw new GeminiCliProviderError(
|
|
225
|
+
`Unknown Antigravity model "${model}"`,
|
|
226
|
+
ErrorCodes.MODEL_NOT_FOUND,
|
|
227
|
+
);
|
|
237
228
|
}
|
|
238
|
-
|
|
229
|
+
const base = entry.agyModelBase;
|
|
239
230
|
return `${base} ${effortSuffix(base, reasoningEffort)}`;
|
|
240
231
|
}
|
|
241
232
|
|
|
@@ -654,7 +645,7 @@ async function* createStreamingGenerator(fullText, userFacingModel) {
|
|
|
654
645
|
* provider errors.
|
|
655
646
|
*/
|
|
656
647
|
async function executeAgy(messages, options) {
|
|
657
|
-
const { model =
|
|
648
|
+
const { model = DEFAULT_MODEL, reasoning_effort, signal, timeout } = options;
|
|
658
649
|
|
|
659
650
|
const prompt = buildPrompt(messages);
|
|
660
651
|
const agyModel = resolveAgyModel(model, reasoning_effort);
|
|
@@ -699,7 +690,7 @@ export const geminiCliProvider = {
|
|
|
699
690
|
* @returns {Promise<Object>|AsyncGenerator} Response or stream generator
|
|
700
691
|
*/
|
|
701
692
|
async invoke(messages, options = {}) {
|
|
702
|
-
const { model =
|
|
693
|
+
const { model = DEFAULT_MODEL, stream = false, signal } = options;
|
|
703
694
|
|
|
704
695
|
if (signal?.aborted) {
|
|
705
696
|
throw new GeminiCliProviderError('Request cancelled', 'CANCELLED');
|
|
@@ -729,9 +720,13 @@ export const geminiCliProvider = {
|
|
|
729
720
|
};
|
|
730
721
|
},
|
|
731
722
|
|
|
723
|
+
defaultModel: DEFAULT_MODEL,
|
|
724
|
+
|
|
732
725
|
/**
|
|
733
726
|
* Validate configuration. agy uses OAuth (no env keys); always true.
|
|
734
|
-
* Availability is determined by isAvailable (binary presence).
|
|
727
|
+
* Availability is determined by isAvailable (binary presence). agy keeps
|
|
728
|
+
* its login outside any file converse can check, so a logged-out agy
|
|
729
|
+
* surfaces at invoke time and bare-name/auto routing fails over.
|
|
735
730
|
*/
|
|
736
731
|
validateConfig(_config) {
|
|
737
732
|
return true;
|
|
@@ -752,37 +747,9 @@ export const geminiCliProvider = {
|
|
|
752
747
|
},
|
|
753
748
|
|
|
754
749
|
/**
|
|
755
|
-
* Get model configuration for a specific model (alias-aware
|
|
750
|
+
* Get model configuration for a specific model (alias-aware).
|
|
756
751
|
*/
|
|
757
752
|
getModelConfig(modelName) {
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
const name = modelName.toLowerCase().trim();
|
|
761
|
-
|
|
762
|
-
// Full agy display-name passthrough → matching tier config. Any 3.x Flash
|
|
763
|
-
// (agy also lists 3.6/3.7) shares the Flash config; any 3.x Pro the Pro one.
|
|
764
|
-
if (/gemini 3\.\d+ flash/i.test(modelName)) {
|
|
765
|
-
return SUPPORTED_MODELS['gemini:flash'];
|
|
766
|
-
}
|
|
767
|
-
if (/gemini 3\.\d+ pro/i.test(modelName)) {
|
|
768
|
-
return SUPPORTED_MODELS['gemini:pro'];
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
// Exact key match (gemini, gemini:flash, gemini:pro)
|
|
772
|
-
if (SUPPORTED_MODELS[name]) {
|
|
773
|
-
return SUPPORTED_MODELS[name];
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
// Alias match
|
|
777
|
-
for (const config of Object.values(SUPPORTED_MODELS)) {
|
|
778
|
-
if (
|
|
779
|
-
config.aliases &&
|
|
780
|
-
config.aliases.some((alias) => alias.toLowerCase() === name)
|
|
781
|
-
) {
|
|
782
|
-
return config;
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
return null;
|
|
753
|
+
return findCatalogEntry(SUPPORTED_MODELS, modelName);
|
|
787
754
|
},
|
|
788
755
|
};
|
package/src/providers/google.js
CHANGED
|
@@ -434,7 +434,11 @@ async function retryWithBackoff(fn, maxRetries = 4) {
|
|
|
434
434
|
/**
|
|
435
435
|
* Main Google provider implementation
|
|
436
436
|
*/
|
|
437
|
+
const DEFAULT_MODEL = 'gemini-3.1-pro-preview';
|
|
438
|
+
|
|
437
439
|
export const googleProvider = {
|
|
440
|
+
defaultModel: DEFAULT_MODEL,
|
|
441
|
+
|
|
438
442
|
/**
|
|
439
443
|
* Unified provider interface: invoke messages with options
|
|
440
444
|
* @param {Array} messages - Array of message objects with role and content
|
|
@@ -443,7 +447,7 @@ export const googleProvider = {
|
|
|
443
447
|
*/
|
|
444
448
|
async invoke(messages, options = {}) {
|
|
445
449
|
const {
|
|
446
|
-
model =
|
|
450
|
+
model = DEFAULT_MODEL,
|
|
447
451
|
maxTokens = null,
|
|
448
452
|
stream = false,
|
|
449
453
|
reasoning_effort = 'medium',
|
package/src/providers/mistral.js
CHANGED
|
@@ -319,7 +319,11 @@ function extractRateLimitInfo(headers) {
|
|
|
319
319
|
/**
|
|
320
320
|
* Main Mistral provider implementation
|
|
321
321
|
*/
|
|
322
|
+
const DEFAULT_MODEL = 'mistral-medium-3-5';
|
|
323
|
+
|
|
322
324
|
export const mistralProvider = {
|
|
325
|
+
defaultModel: DEFAULT_MODEL,
|
|
326
|
+
|
|
323
327
|
/**
|
|
324
328
|
* Unified provider interface: invoke messages with options
|
|
325
329
|
* @param {Array} messages - Array of message objects with role and content
|
|
@@ -328,7 +332,7 @@ export const mistralProvider = {
|
|
|
328
332
|
*/
|
|
329
333
|
async invoke(messages, options = {}) {
|
|
330
334
|
const {
|
|
331
|
-
model =
|
|
335
|
+
model = DEFAULT_MODEL,
|
|
332
336
|
maxTokens = null,
|
|
333
337
|
stream = false,
|
|
334
338
|
reasoning_effort = 'medium',
|
|
@@ -273,6 +273,7 @@ export function createOpenAICompatibleProvider(providerConfig) {
|
|
|
273
273
|
transformStreamChunk,
|
|
274
274
|
resolveModelConfig,
|
|
275
275
|
defaultParams = {},
|
|
276
|
+
defaultModel = Object.keys(supportedModels)[0],
|
|
276
277
|
} = providerConfig;
|
|
277
278
|
|
|
278
279
|
// Create custom error class for this provider
|
|
@@ -284,12 +285,14 @@ export function createOpenAICompatibleProvider(providerConfig) {
|
|
|
284
285
|
}
|
|
285
286
|
|
|
286
287
|
return {
|
|
288
|
+
defaultModel,
|
|
289
|
+
|
|
287
290
|
/**
|
|
288
291
|
* Unified provider interface: invoke messages with options
|
|
289
292
|
*/
|
|
290
293
|
async invoke(messages, options = {}) {
|
|
291
294
|
const {
|
|
292
|
-
model =
|
|
295
|
+
model = defaultModel,
|
|
293
296
|
maxTokens = null,
|
|
294
297
|
stream = false,
|
|
295
298
|
reasoning_effort = 'medium',
|
package/src/providers/openai.js
CHANGED
|
@@ -547,7 +547,11 @@ function convertMessages(messages, useResponsesAPI = false) {
|
|
|
547
547
|
/**
|
|
548
548
|
* Main OpenAI provider implementation
|
|
549
549
|
*/
|
|
550
|
+
const DEFAULT_MODEL = 'gpt-6-sol';
|
|
551
|
+
|
|
550
552
|
export const openaiProvider = {
|
|
553
|
+
defaultModel: DEFAULT_MODEL,
|
|
554
|
+
|
|
551
555
|
/**
|
|
552
556
|
* Unified provider interface: invoke messages with options
|
|
553
557
|
* @param {Array} messages - Array of message objects with role and content
|
|
@@ -556,7 +560,7 @@ export const openaiProvider = {
|
|
|
556
560
|
*/
|
|
557
561
|
async invoke(messages, options = {}) {
|
|
558
562
|
const {
|
|
559
|
-
model =
|
|
563
|
+
model = DEFAULT_MODEL,
|
|
560
564
|
maxTokens = null,
|
|
561
565
|
stream = false,
|
|
562
566
|
reasoning_effort = 'medium',
|
|
@@ -550,6 +550,7 @@ export const openrouterProvider = createOpenAICompatibleProvider({
|
|
|
550
550
|
baseURL: 'https://openrouter.ai/api/v1',
|
|
551
551
|
providerName: 'OpenRouter',
|
|
552
552
|
supportedModels: SUPPORTED_MODELS,
|
|
553
|
+
defaultModel: 'z-ai/glm-5.2',
|
|
553
554
|
validateApiKey,
|
|
554
555
|
transformRequest,
|
|
555
556
|
transformResponse,
|
package/src/providers/xai.js
CHANGED
|
@@ -212,7 +212,11 @@ function extractCitations(response) {
|
|
|
212
212
|
/**
|
|
213
213
|
* Main XAI provider implementation
|
|
214
214
|
*/
|
|
215
|
+
const DEFAULT_MODEL = 'grok-4.5';
|
|
216
|
+
|
|
215
217
|
export const xaiProvider = {
|
|
218
|
+
defaultModel: DEFAULT_MODEL,
|
|
219
|
+
|
|
216
220
|
/**
|
|
217
221
|
* Unified provider interface: invoke messages with options
|
|
218
222
|
* @param {Array} messages - Array of message objects with role and content
|
|
@@ -221,7 +225,7 @@ export const xaiProvider = {
|
|
|
221
225
|
*/
|
|
222
226
|
async invoke(messages, options = {}) {
|
|
223
227
|
const {
|
|
224
|
-
model =
|
|
228
|
+
model = DEFAULT_MODEL,
|
|
225
229
|
maxTokens = null,
|
|
226
230
|
stream = false,
|
|
227
231
|
reasoning_effort = 'medium',
|