@zergai/ztc 0.4.0-beta.1 → 0.4.1-dev.36919234045
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/README.md +8 -1
- package/THIRD_PARTY_NOTICES.md +4 -0
- package/dist/App.js +2 -2
- package/dist/agent/agent.js +41 -5
- package/dist/agent/backends/anthropic.js +5 -10
- package/dist/agent/backends/gemini.js +2 -0
- package/dist/agent/backends/index.d.ts +1 -0
- package/dist/agent/backends/index.js +10 -1
- package/dist/agent/backends/openai.d.ts +0 -6
- package/dist/agent/backends/openai.js +5 -2
- package/dist/agent/backends/openai_compatible.d.ts +2 -0
- package/dist/agent/backends/openai_compatible.js +18 -8
- package/dist/agent/backends/provider_ids.d.ts +1 -0
- package/dist/agent/backends/provider_ids.js +4 -0
- package/dist/agent/backends/types.d.ts +1 -0
- package/dist/agent/backends/zrouter_stream.d.ts +5 -1
- package/dist/agent/backends/zrouter_stream.js +141 -37
- package/dist/agent/commands/compact.js +6 -5
- package/dist/agent/commands/config.js +4 -1
- package/dist/agent/commands/context.js +6 -1
- package/dist/agent/commands/effort.js +14 -6
- package/dist/agent/commands/model.js +12 -2
- package/dist/agent/commands/profile.js +21 -2
- package/dist/agent/commands/provider_selection.js +14 -1
- package/dist/agent/commands/settings.js +45 -7
- package/dist/agent/commands/types.d.ts +19 -0
- package/dist/agent/factory.js +14 -68
- package/dist/agent/subagent.d.ts +0 -10
- package/dist/agent/subagent.js +22 -0
- package/dist/agent/tool_response_store.d.ts +1 -1
- package/dist/agent/tool_response_store.js +4 -2
- package/dist/agent/tools/pane.d.ts +0 -7
- package/dist/agent/tools/pane.js +5 -4
- package/dist/app/command_context.js +33 -10
- package/dist/app/model_catalog_cache.d.ts +5 -0
- package/dist/app/model_catalog_cache.js +138 -0
- package/dist/app/restart.d.ts +1 -1
- package/dist/app/restart.js +16 -5
- package/dist/app/selection_completion.d.ts +17 -2
- package/dist/app/selection_completion.js +74 -6
- package/dist/app/session_manager.js +13 -8
- package/dist/cli_args.js +2 -16
- package/dist/cli_main.js +25 -6
- package/dist/cli_ratatui.js +70 -33
- package/dist/config/defaults.d.ts +2 -1
- package/dist/config/defaults.js +9 -2
- package/dist/config/resolved.d.ts +2 -2
- package/dist/config.d.ts +35 -3
- package/dist/config.js +227 -29
- package/dist/headless.js +2 -0
- package/dist/onboarding/first_run.js +5 -1
- package/dist/panes/model_catalog.d.ts +3 -3
- package/dist/panes/model_catalog.js +28 -4
- package/dist/panes/pane_registry.js +6 -2
- package/dist/panes/types.d.ts +2 -0
- package/dist/panes/ztc_launch.js +12 -0
- package/dist/session.d.ts +6 -2
- package/dist/session.js +65 -10
- package/dist/ui/views/completion_menu.js +10 -5
- package/dist/ui/views/status_bar.js +9 -5
- package/dist/ui/widgets/resume_panel.d.ts +2 -0
- package/dist/ui/widgets/resume_panel.js +17 -15
- package/dist/utils/compaction.d.ts +1 -1
- package/dist/utils/compaction.js +2 -2
- package/dist/utils/context.d.ts +4 -4
- package/dist/utils/context.js +14 -12
- package/dist/utils/deepseek.d.ts +2 -2
- package/dist/utils/deepseek.js +13 -5
- package/dist/utils/model_cache.d.ts +15 -0
- package/dist/utils/model_cache.js +143 -0
- package/dist/utils/models.d.ts +4 -2
- package/dist/utils/models.js +12 -16
- package/dist/utils/reasoning.d.ts +8 -1
- package/dist/utils/reasoning.js +31 -11
- package/dist/utils/router_catalog.d.ts +47 -0
- package/dist/utils/router_catalog.js +222 -0
- package/dist/zlm-embed.mjs +1180 -514
- package/node_modules/@zerg/model-contracts/LICENSE.md +375 -0
- package/node_modules/@zerg/model-contracts/README.md +78 -0
- package/node_modules/@zerg/model-contracts/index.d.ts +18 -0
- package/node_modules/@zerg/model-contracts/index.js +220 -0
- package/node_modules/@zerg/model-contracts/package.json +8 -0
- package/node_modules/glob/node_modules/brace-expansion/index.js +78 -22
- package/node_modules/glob/node_modules/brace-expansion/package.json +1 -1
- package/node_modules/readdir-glob/node_modules/brace-expansion/index.js +78 -22
- package/node_modules/readdir-glob/node_modules/brace-expansion/package.json +1 -1
- package/package.json +9 -6
- package/packages/model-contracts/LICENSE.md +375 -0
- package/packages/model-contracts/README.md +78 -0
- package/packages/model-contracts/index.d.ts +18 -0
- package/packages/model-contracts/index.js +220 -0
- package/packages/model-contracts/package.json +8 -0
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { type ReasoningWireSurface } from '@zerg/model-contracts';
|
|
2
|
+
import { type RouterCatalog, type RouterCatalogConnection } from './utils/router_catalog.js';
|
|
3
|
+
import type { ReasoningContract } from './utils/reasoning.js';
|
|
1
4
|
import { ZTCConfig, ZTCAuthCredentials, ApiEnvironment, ZTCAuthMode, ZTCConfigScope, CompactionTriggerMode, OpenAICompatibleSettings, ZTCPermissionProfile, IntentLayerSettings, ContextProgressBarSettings, CodexReasoningEffort, WorkflowSettings, Account, AccountRotation } from './config/types.js';
|
|
2
5
|
import type { AuthContext, ResolvedLLMConfig } from './config/resolved.js';
|
|
3
6
|
/** Validate and normalize an OpenAI-compatible inference destination. */
|
|
@@ -14,6 +17,12 @@ export declare class ConfigStore {
|
|
|
14
17
|
private config;
|
|
15
18
|
private profileEmulation;
|
|
16
19
|
private legacyApiKeyFromEnvironment;
|
|
20
|
+
/**
|
|
21
|
+
* Whether the routing in `this.config` came from a saved file or an explicit
|
|
22
|
+
* choice, rather than the built-in default. A config-less process that never
|
|
23
|
+
* picked a route must not hard-fail on the preset Router route it inherited.
|
|
24
|
+
*/
|
|
25
|
+
private routingIsConfigured;
|
|
17
26
|
private routerCredentials;
|
|
18
27
|
private routerCredentialsError;
|
|
19
28
|
private routerFallbackWarning;
|
|
@@ -21,6 +30,7 @@ export declare class ConfigStore {
|
|
|
21
30
|
private configScope;
|
|
22
31
|
/** Session-local overrides. Never persisted to config.json. */
|
|
23
32
|
private sessionOverrides;
|
|
33
|
+
private restoredSessionSelection;
|
|
24
34
|
/** CLI-only overrides. Never persisted to config.json. */
|
|
25
35
|
private cliOverrides;
|
|
26
36
|
/**
|
|
@@ -35,6 +45,10 @@ export declare class ConfigStore {
|
|
|
35
45
|
private applyEnvOverrides;
|
|
36
46
|
load(force?: boolean): Promise<ZTCConfig>;
|
|
37
47
|
refresh(): Promise<void>;
|
|
48
|
+
/** Copy saved settings and Router credentials, then activate them transactionally.
|
|
49
|
+
* Account registrations retain their credential paths; account homes are not cloned.
|
|
50
|
+
*/
|
|
51
|
+
duplicateProfile(requestedName: string, source?: string, activate?: () => void | Promise<void>): Promise<string>;
|
|
38
52
|
/** Load a profile in this process; restore the old view if runtime activation fails. */
|
|
39
53
|
switchProfile(name: string, activate: () => void | Promise<void>): Promise<void>;
|
|
40
54
|
save(): Promise<void>;
|
|
@@ -54,6 +68,7 @@ export declare class ConfigStore {
|
|
|
54
68
|
setConfigScope(scope: ZTCConfigScope): void;
|
|
55
69
|
clearSessionOverrides(): void;
|
|
56
70
|
withConfigScope<T>(scope: ZTCConfigScope, fn: () => T | Promise<T>): Promise<T>;
|
|
71
|
+
private releaseRestoredSelection;
|
|
57
72
|
set<K extends keyof ZTCConfig>(key: K, value: ZTCConfig[K]): void;
|
|
58
73
|
setGlobal<K extends keyof ZTCConfig>(key: K, value: ZTCConfig[K]): void;
|
|
59
74
|
setAll(next: Partial<ZTCConfig>): void;
|
|
@@ -68,7 +83,7 @@ export declare class ConfigStore {
|
|
|
68
83
|
* `undefined` removes the override instead of shadowing the saved value with
|
|
69
84
|
* an explicit undefined, so the configured setting applies again.
|
|
70
85
|
*/
|
|
71
|
-
setCliOverride<K extends keyof Pick<ZTCConfig, 'provider' | 'model' | 'codexEffort'>>(key: K, value: Pick<ZTCConfig, 'provider' | 'model' | 'codexEffort'>[K]): void;
|
|
86
|
+
setCliOverride<K extends keyof Pick<ZTCConfig, 'provider' | 'model' | 'codexEffort' | 'authMode' | 'zergProxyUrl'>>(key: K, value: Pick<ZTCConfig, 'provider' | 'model' | 'codexEffort' | 'authMode' | 'zergProxyUrl'>[K]): void;
|
|
72
87
|
getProvider(): string;
|
|
73
88
|
setProvider(provider: string): void;
|
|
74
89
|
/** All registered accounts (empty when no pool is configured). */
|
|
@@ -110,7 +125,10 @@ export declare class ConfigStore {
|
|
|
110
125
|
* Effective Codex effort for the active (or given) provider/model. Priority:
|
|
111
126
|
* per-model > per-provider > global. Defaults to the current provider/model.
|
|
112
127
|
*/
|
|
128
|
+
getReasoningWireSurface(provider?: string, model?: string): ReasoningWireSurface;
|
|
113
129
|
getCodexEffort(provider?: string, model?: string): CodexReasoningEffort | undefined;
|
|
130
|
+
/** The active transport owns the model's choices, aliases and advertised default. */
|
|
131
|
+
getReasoningContract(provider?: string, model?: string): ReasoningContract;
|
|
114
132
|
/** Saved effort the active (or given) model rejects; undefined when it applies. */
|
|
115
133
|
getUnsupportedCodexEffort(provider?: string, model?: string): CodexReasoningEffort | undefined;
|
|
116
134
|
/** Effort chosen by a startup `--effort` flag for this process (= none when unset). */
|
|
@@ -165,6 +183,21 @@ export declare class ConfigStore {
|
|
|
165
183
|
* getters stay — they are still used widely.
|
|
166
184
|
*/
|
|
167
185
|
getAuthContext(): AuthContext;
|
|
186
|
+
restoreSessionSelection(metadata: {
|
|
187
|
+
provider: string;
|
|
188
|
+
model: string;
|
|
189
|
+
authMode?: ZTCAuthMode;
|
|
190
|
+
routerOrigin?: string;
|
|
191
|
+
configProfile?: string;
|
|
192
|
+
}): void;
|
|
193
|
+
getRouterCatalogConnection(destination?: string | undefined): RouterCatalogConnection | undefined;
|
|
194
|
+
/** New children use configured routing, not a parent's restored inference route. */
|
|
195
|
+
getChildAuthMode(): ZTCAuthMode;
|
|
196
|
+
adoptRouterCatalog(catalog: RouterCatalog): Promise<void>;
|
|
197
|
+
getRouterCatalog(): RouterCatalog | undefined;
|
|
198
|
+
getResolvedAuthMode(): ZTCAuthMode;
|
|
199
|
+
getRoutedModelCatalog(): RouterCatalog | undefined;
|
|
200
|
+
getModelContextWindow(model?: string, provider?: string): number | null | undefined;
|
|
168
201
|
/**
|
|
169
202
|
* Resolve everything a backend factory needs into one struct. Folds in the
|
|
170
203
|
* provider/model override precedence, the direct-key precedence
|
|
@@ -179,8 +212,7 @@ export declare class ConfigStore {
|
|
|
179
212
|
*
|
|
180
213
|
* Reads through `get()` and the env-aware getters (never raw `this.config`)
|
|
181
214
|
* so cli/session overrides stay honored. `apiKey` is the DIRECT provider key;
|
|
182
|
-
* `authToken`/`useProxy` describe the proxy route separately
|
|
183
|
-
* still prefer a direct key (e.g. Gemini) over the proxy.
|
|
215
|
+
* `authToken`/`useProxy` describe the selected proxy route separately.
|
|
184
216
|
*/
|
|
185
217
|
resolveLLMBackendConfig(opts?: {
|
|
186
218
|
provider?: string;
|
package/dist/config.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { modelContract } from '@zerg/model-contracts';
|
|
2
|
+
import { isLocalSubscriptionProvider } from './agent/backends/provider_ids.js';
|
|
3
|
+
import { resolveRouterModel, readRouterCatalog } from './utils/router_catalog.js';
|
|
4
|
+
import { dirname, join } from 'path';
|
|
5
|
+
import { stat, readFile, writeFile, mkdir, chmod, rm, unlink, rename, realpath } from 'fs/promises';
|
|
3
6
|
import { randomUUID } from 'crypto';
|
|
4
|
-
import { activeProfile, builtinProfileEmulation, profileConfigDir, validateProfileName } from './config/profiles.js';
|
|
7
|
+
import { activeProfile, builtinProfileEmulation, listConfigProfiles, profileConfigDir, validateProfileName } from './config/profiles.js';
|
|
5
8
|
import { accountSourceToBackendOptions, canonicalAccountProvider, probeAccountIsolated, resolveActiveAccount, resolveRotation, } from './agent/backends/account_pool.js';
|
|
6
9
|
import { notifyAccountsChanged } from './agent/backends/account_events.js';
|
|
7
10
|
import { inferDefaultProvider, getDefaultApiKeyForProvider, getDefaultModelForProvider, resolveCodexEffort, unsupportedCodexEffort } from './config/defaults.js';
|
|
@@ -290,6 +293,20 @@ const ROUTING_SETTING_KEYS = [
|
|
|
290
293
|
function normalizedOrigin(value) {
|
|
291
294
|
return value?.trim().replace(/\/+$/, '') || undefined;
|
|
292
295
|
}
|
|
296
|
+
/** Explicit deployment routing takes precedence over a saved session origin. */
|
|
297
|
+
function routerOriginFromEnvironment() {
|
|
298
|
+
if (process.env.ZERG_PROXY_URL)
|
|
299
|
+
return process.env.ZERG_PROXY_URL;
|
|
300
|
+
if (process.env.ZERG_ROUTER_BASE_URL)
|
|
301
|
+
return normalizedOrigin(process.env.ZERG_ROUTER_BASE_URL);
|
|
302
|
+
const tiers = {
|
|
303
|
+
local: 'http://host.docker.internal:8000/api/zrouter',
|
|
304
|
+
dev: 'https://api-dev.zergai.com/api/zrouter', development: 'https://api-dev.zergai.com/api/zrouter',
|
|
305
|
+
prod: 'https://api.zergai.com/api/zrouter', production: 'https://api.zergai.com/api/zrouter', main: 'https://api.zergai.com/api/zrouter',
|
|
306
|
+
};
|
|
307
|
+
const tier = process.env.ZERG_DEPLOY_TIER || '';
|
|
308
|
+
return Object.hasOwn(tiers, tier) ? tiers[tier] : undefined;
|
|
309
|
+
}
|
|
293
310
|
/**
|
|
294
311
|
* True when the saved provider route can already reach a model: a direct or
|
|
295
312
|
* platform credential, a subscription or account login, a configured
|
|
@@ -402,6 +419,12 @@ export class ConfigStore {
|
|
|
402
419
|
// The legacy slot also carries runtime defaults. Only a configured key may
|
|
403
420
|
// be migrated into apiKeys or written to disk.
|
|
404
421
|
legacyApiKeyFromEnvironment = true;
|
|
422
|
+
/**
|
|
423
|
+
* Whether the routing in `this.config` came from a saved file or an explicit
|
|
424
|
+
* choice, rather than the built-in default. A config-less process that never
|
|
425
|
+
* picked a route must not hard-fail on the preset Router route it inherited.
|
|
426
|
+
*/
|
|
427
|
+
routingIsConfigured = false;
|
|
405
428
|
routerCredentials = null;
|
|
406
429
|
routerCredentialsError = null;
|
|
407
430
|
routerFallbackWarning = null;
|
|
@@ -409,6 +432,7 @@ export class ConfigStore {
|
|
|
409
432
|
configScope = 'global';
|
|
410
433
|
/** Session-local overrides. Never persisted to config.json. */
|
|
411
434
|
sessionOverrides = {};
|
|
435
|
+
restoredSessionSelection = false;
|
|
412
436
|
/** CLI-only overrides. Never persisted to config.json. */
|
|
413
437
|
cliOverrides = {};
|
|
414
438
|
/**
|
|
@@ -475,23 +499,10 @@ export class ConfigStore {
|
|
|
475
499
|
else if (tier === 'prod' || tier === 'production' || tier === 'main')
|
|
476
500
|
this.config.apiEnvironment = 'production';
|
|
477
501
|
}
|
|
478
|
-
//
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
else if (process.env.ZERG_ROUTER_BASE_URL) {
|
|
483
|
-
// Standalone ZergRouter (https://zergrouter.com) serves /v1/* at
|
|
484
|
-
// its root, no /api/zrouter suffix. Lower precedence than ZERG_PROXY_URL.
|
|
485
|
-
this.config.zergProxyUrl = process.env.ZERG_ROUTER_BASE_URL.replace(/\/+$/, '');
|
|
486
|
-
}
|
|
487
|
-
else if (process.env.ZERG_DEPLOY_TIER) {
|
|
488
|
-
const tier = process.env.ZERG_DEPLOY_TIER;
|
|
489
|
-
if (tier === 'local')
|
|
490
|
-
this.config.zergProxyUrl = 'http://host.docker.internal:8000/api/zrouter';
|
|
491
|
-
else if (tier === 'dev' || tier === 'development')
|
|
492
|
-
this.config.zergProxyUrl = 'https://api-dev.zergai.com/api/zrouter';
|
|
493
|
-
else if (tier === 'prod' || tier === 'production' || tier === 'main')
|
|
494
|
-
this.config.zergProxyUrl = 'https://api.zergai.com/api/zrouter';
|
|
502
|
+
// Resolve all explicit origin environment variables through one policy.
|
|
503
|
+
const originOverride = routerOriginFromEnvironment();
|
|
504
|
+
if (originOverride) {
|
|
505
|
+
this.config.zergProxyUrl = originOverride;
|
|
495
506
|
}
|
|
496
507
|
else if (!this.config.zergProxyUrl) {
|
|
497
508
|
// Local default: infer ZRouter from the selected API environment.
|
|
@@ -599,6 +610,59 @@ export class ConfigStore {
|
|
|
599
610
|
this.sessionOverrides = sessionOverrides;
|
|
600
611
|
this.configScope = scope;
|
|
601
612
|
}
|
|
613
|
+
/** Copy saved settings and Router credentials, then activate them transactionally.
|
|
614
|
+
* Account registrations retain their credential paths; account homes are not cloned.
|
|
615
|
+
*/
|
|
616
|
+
async duplicateProfile(requestedName, source = activeProfile(), activate = () => { }) {
|
|
617
|
+
const name = validateProfileName(requestedName.trim());
|
|
618
|
+
const from = validateProfileName(source);
|
|
619
|
+
if (name === 'default' || builtinProfileEmulation(name)) {
|
|
620
|
+
throw new Error(`Cannot duplicate onto "${name}": it is a built-in profile sharing the default settings. Pick another name.`);
|
|
621
|
+
}
|
|
622
|
+
if (name === from || (await listConfigProfiles()).includes(name)) {
|
|
623
|
+
throw new Error(`Config profile "${name}" already exists. Pick another name.`);
|
|
624
|
+
}
|
|
625
|
+
const sourceDir = profileConfigDir(from);
|
|
626
|
+
const emulation = builtinProfileEmulation(from);
|
|
627
|
+
if (from !== 'default' && !emulation && !(await stat(sourceDir)).isDirectory()) {
|
|
628
|
+
throw new Error(`Config profile "${from}" does not exist.`);
|
|
629
|
+
}
|
|
630
|
+
let saved = {};
|
|
631
|
+
try {
|
|
632
|
+
const parsed = JSON.parse(await readFile(join(sourceDir, 'config.json'), 'utf8'));
|
|
633
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
634
|
+
throw new Error(`Invalid config profile "${from}": expected an object.`);
|
|
635
|
+
}
|
|
636
|
+
saved = parsed;
|
|
637
|
+
}
|
|
638
|
+
catch (error) {
|
|
639
|
+
if (error.code !== 'ENOENT')
|
|
640
|
+
throw error;
|
|
641
|
+
}
|
|
642
|
+
if (emulation)
|
|
643
|
+
saved.emulationId = emulation;
|
|
644
|
+
const destination = profileConfigDir(name);
|
|
645
|
+
await mkdir(dirname(destination), { recursive: true, mode: 0o700 });
|
|
646
|
+
// An existing destination, including one created concurrently, is never ours to modify.
|
|
647
|
+
await mkdir(destination, { mode: 0o700 });
|
|
648
|
+
try {
|
|
649
|
+
await writeFile(join(destination, 'config.json'), JSON.stringify(saved, null, 2), { flag: 'wx', mode: 0o600 });
|
|
650
|
+
try {
|
|
651
|
+
const auth = await readFile(join(sourceDir, 'router-auth.json'));
|
|
652
|
+
await writeFile(join(destination, 'router-auth.json'), auth, { flag: 'wx', mode: 0o600 });
|
|
653
|
+
}
|
|
654
|
+
catch (error) {
|
|
655
|
+
if (error.code !== 'ENOENT')
|
|
656
|
+
throw error;
|
|
657
|
+
}
|
|
658
|
+
await this.switchProfile(name, activate);
|
|
659
|
+
}
|
|
660
|
+
catch (error) {
|
|
661
|
+
await rm(destination, { recursive: true, force: true });
|
|
662
|
+
throw error;
|
|
663
|
+
}
|
|
664
|
+
return name;
|
|
665
|
+
}
|
|
602
666
|
/** Load a profile in this process; restore the old view if runtime activation fails. */
|
|
603
667
|
async switchProfile(name, activate) {
|
|
604
668
|
const next = validateProfileName(name);
|
|
@@ -627,6 +691,7 @@ export class ConfigStore {
|
|
|
627
691
|
routerCredentialsError: this.routerCredentialsError,
|
|
628
692
|
routerFallbackWarning: this.routerFallbackWarning,
|
|
629
693
|
sessionOverrides: this.sessionOverrides,
|
|
694
|
+
restoredSessionSelection: this.restoredSessionSelection,
|
|
630
695
|
cliOverrides: this.cliOverrides,
|
|
631
696
|
runtimeActivePerProvider: this.runtimeActivePerProvider,
|
|
632
697
|
configScope: this.configScope,
|
|
@@ -640,6 +705,7 @@ export class ConfigStore {
|
|
|
640
705
|
}
|
|
641
706
|
else {
|
|
642
707
|
this.sessionOverrides = {};
|
|
708
|
+
this.restoredSessionSelection = false;
|
|
643
709
|
this.cliOverrides = {};
|
|
644
710
|
this.runtimeActivePerProvider = {};
|
|
645
711
|
this.configScope = 'global';
|
|
@@ -732,6 +798,8 @@ export class ConfigStore {
|
|
|
732
798
|
return {
|
|
733
799
|
...(this.cliOverrides.provider !== undefined ? { provider: this.cliOverrides.provider } : {}),
|
|
734
800
|
...(this.cliOverrides.model !== undefined ? { model: this.cliOverrides.model } : {}),
|
|
801
|
+
...(this.cliOverrides.authMode !== undefined ? { authMode: this.cliOverrides.authMode } : {}),
|
|
802
|
+
...(this.cliOverrides.zergProxyUrl !== undefined ? { zergProxyUrl: this.cliOverrides.zergProxyUrl } : {}),
|
|
735
803
|
};
|
|
736
804
|
}
|
|
737
805
|
getMaxTokensSource() {
|
|
@@ -747,6 +815,7 @@ export class ConfigStore {
|
|
|
747
815
|
}
|
|
748
816
|
clearSessionOverrides() {
|
|
749
817
|
this.sessionOverrides = {};
|
|
818
|
+
this.restoredSessionSelection = false;
|
|
750
819
|
}
|
|
751
820
|
async withConfigScope(scope, fn) {
|
|
752
821
|
const previous = this.configScope;
|
|
@@ -758,7 +827,15 @@ export class ConfigStore {
|
|
|
758
827
|
this.configScope = previous;
|
|
759
828
|
}
|
|
760
829
|
}
|
|
830
|
+
releaseRestoredSelection(key) {
|
|
831
|
+
if (!this.restoredSessionSelection || !['provider', 'model', 'authMode', 'zergProxyUrl'].includes(key))
|
|
832
|
+
return;
|
|
833
|
+
for (const route of ['provider', 'model', 'authMode', 'zergProxyUrl'])
|
|
834
|
+
delete this.sessionOverrides[route];
|
|
835
|
+
this.restoredSessionSelection = false;
|
|
836
|
+
}
|
|
761
837
|
set(key, value) {
|
|
838
|
+
this.releaseRestoredSelection(key);
|
|
762
839
|
if (this.configScope === 'session' || (key === 'emulationId' && this.profileEmulation)) {
|
|
763
840
|
this.sessionOverrides[key] = value;
|
|
764
841
|
return;
|
|
@@ -768,11 +845,14 @@ export class ConfigStore {
|
|
|
768
845
|
this.legacyApiKeyFromEnvironment = false;
|
|
769
846
|
}
|
|
770
847
|
setGlobal(key, value) {
|
|
848
|
+
this.releaseRestoredSelection(key);
|
|
771
849
|
this.config[key] = value;
|
|
772
850
|
if (key === 'apiKey')
|
|
773
851
|
this.legacyApiKeyFromEnvironment = false;
|
|
774
852
|
}
|
|
775
853
|
setAll(next) {
|
|
854
|
+
for (const key of Object.keys(next))
|
|
855
|
+
this.releaseRestoredSelection(key);
|
|
776
856
|
this.config = { ...build_default_config(), ...this.config, ...next };
|
|
777
857
|
if (Object.hasOwn(next, 'apiKey'))
|
|
778
858
|
this.legacyApiKeyFromEnvironment = false;
|
|
@@ -1021,8 +1101,34 @@ export class ConfigStore {
|
|
|
1021
1101
|
* Effective Codex effort for the active (or given) provider/model. Priority:
|
|
1022
1102
|
* per-model > per-provider > global. Defaults to the current provider/model.
|
|
1023
1103
|
*/
|
|
1104
|
+
getReasoningWireSurface(provider = this.getProvider(), model = this.getModel()) {
|
|
1105
|
+
if (provider === 'openai_compatible')
|
|
1106
|
+
return 'chat_tools';
|
|
1107
|
+
if (modelContract(provider, model)?.chatToolReasoningEfforts === undefined)
|
|
1108
|
+
return 'native_api';
|
|
1109
|
+
try {
|
|
1110
|
+
return this.resolveLLMBackendConfig({ provider, model }).useProxy ? 'chat_tools' : 'native_api';
|
|
1111
|
+
}
|
|
1112
|
+
catch (error) {
|
|
1113
|
+
if (error instanceof RouterConfigurationError)
|
|
1114
|
+
return 'chat_tools';
|
|
1115
|
+
throw error;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1024
1118
|
getCodexEffort(provider, model) {
|
|
1025
|
-
|
|
1119
|
+
const selectedProvider = provider ?? this.getProvider();
|
|
1120
|
+
const selectedModel = model ?? this.getModel();
|
|
1121
|
+
const catalog = this.getRoutedModelCatalog();
|
|
1122
|
+
const capabilities = catalog ? resolveRouterModel(catalog, selectedProvider, selectedModel)?.capabilities : undefined;
|
|
1123
|
+
return resolveCodexEffort(this.get(), selectedProvider, selectedModel, capabilities
|
|
1124
|
+
?? this.getReasoningWireSurface(selectedProvider, selectedModel));
|
|
1125
|
+
}
|
|
1126
|
+
/** The active transport owns the model's choices, aliases and advertised default. */
|
|
1127
|
+
getReasoningContract(provider = this.getProvider(), model = this.getModel()) {
|
|
1128
|
+
const catalog = this.getRoutedModelCatalog();
|
|
1129
|
+
if (catalog?.version === 1)
|
|
1130
|
+
return resolveRouterModel(catalog, provider, model)?.capabilities?.reasoning ?? [];
|
|
1131
|
+
return this.getReasoningWireSurface(provider, model);
|
|
1026
1132
|
}
|
|
1027
1133
|
/** Saved effort the active (or given) model rejects; undefined when it applies. */
|
|
1028
1134
|
getUnsupportedCodexEffort(provider, model) {
|
|
@@ -1201,6 +1307,84 @@ export class ConfigStore {
|
|
|
1201
1307
|
authMode: this.getAuthMode(),
|
|
1202
1308
|
};
|
|
1203
1309
|
}
|
|
1310
|
+
restoreSessionSelection(metadata) {
|
|
1311
|
+
// Legacy sessions did not persist routes. Explicit launch overrides retain priority.
|
|
1312
|
+
if (!metadata.authMode || this.cliOverrides.provider || this.cliOverrides.model
|
|
1313
|
+
|| (metadata.configProfile && metadata.configProfile !== activeProfile()))
|
|
1314
|
+
return;
|
|
1315
|
+
this.restoredSessionSelection = true;
|
|
1316
|
+
this.sessionOverrides.provider = metadata.provider;
|
|
1317
|
+
this.sessionOverrides.model = metadata.model;
|
|
1318
|
+
this.sessionOverrides.authMode = metadata.authMode;
|
|
1319
|
+
if (metadata.authMode !== 'direct' && metadata.routerOrigin && !routerOriginFromEnvironment())
|
|
1320
|
+
this.sessionOverrides.zergProxyUrl = metadata.routerOrigin;
|
|
1321
|
+
}
|
|
1322
|
+
getRouterCatalogConnection(destination = this.get().zergProxyUrl) {
|
|
1323
|
+
const origin = normalizedOrigin(destination);
|
|
1324
|
+
if (!origin)
|
|
1325
|
+
return undefined;
|
|
1326
|
+
const credentials = this.routerCredentials;
|
|
1327
|
+
if (credentials && !this.routerCredentialsError && credentials.origin === origin) {
|
|
1328
|
+
return { origin, token: credentials.token, workspaceId: credentials.workspaceId };
|
|
1329
|
+
}
|
|
1330
|
+
// Platform sessions are scoped to the platform's proxy, never another Router.
|
|
1331
|
+
const token = origin === this.deriveZRouterUrl(this.getApiBaseUrl()) ? this.getAuthToken() : undefined;
|
|
1332
|
+
return token ? { origin, token, workspaceId: this.getActiveWorkspace()?.id.toString() } : undefined;
|
|
1333
|
+
}
|
|
1334
|
+
/** New children use configured routing, not a parent's restored inference route. */
|
|
1335
|
+
getChildAuthMode() {
|
|
1336
|
+
if (!this.restoredSessionSelection)
|
|
1337
|
+
return this.getAuthMode();
|
|
1338
|
+
const { authMode: _restored, ...session } = this.sessionOverrides;
|
|
1339
|
+
return resolveAuthMode({ ...this.config, ...session, ...this.cliOverrides });
|
|
1340
|
+
}
|
|
1341
|
+
async adoptRouterCatalog(catalog) {
|
|
1342
|
+
if (catalog.version !== 1 || catalog.authRequired || this.getResolvedAuthMode() !== 'zrouter')
|
|
1343
|
+
return;
|
|
1344
|
+
const provider = this.getProvider(), model = this.getModel();
|
|
1345
|
+
const row = resolveRouterModel(catalog, provider, model);
|
|
1346
|
+
if (!row || (row.id === model && row.owned_by === provider))
|
|
1347
|
+
return;
|
|
1348
|
+
if (this.cliOverrides.provider || this.cliOverrides.model) {
|
|
1349
|
+
this.cliOverrides.provider = row.owned_by;
|
|
1350
|
+
this.cliOverrides.model = row.id;
|
|
1351
|
+
}
|
|
1352
|
+
else if (this.sessionOverrides.provider || this.sessionOverrides.model) {
|
|
1353
|
+
this.sessionOverrides.provider = row.owned_by;
|
|
1354
|
+
this.sessionOverrides.model = row.id;
|
|
1355
|
+
}
|
|
1356
|
+
else {
|
|
1357
|
+
this.config.provider = row.owned_by;
|
|
1358
|
+
this.config.model = row.id;
|
|
1359
|
+
await this.save();
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
getRouterCatalog() {
|
|
1363
|
+
const connection = this.getRouterCatalogConnection();
|
|
1364
|
+
return connection ? readRouterCatalog(connection) : undefined;
|
|
1365
|
+
}
|
|
1366
|
+
getResolvedAuthMode() {
|
|
1367
|
+
const mode = this.getAuthMode();
|
|
1368
|
+
if (mode !== 'auto')
|
|
1369
|
+
return mode;
|
|
1370
|
+
try {
|
|
1371
|
+
return this.resolveLLMBackendConfig().useProxy ? 'zrouter' : 'direct';
|
|
1372
|
+
}
|
|
1373
|
+
catch {
|
|
1374
|
+
return mode;
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
getRoutedModelCatalog() {
|
|
1378
|
+
if (isLocalSubscriptionProvider(this.getProvider()))
|
|
1379
|
+
return undefined;
|
|
1380
|
+
return this.getResolvedAuthMode() === 'zrouter' ? this.getRouterCatalog() : undefined;
|
|
1381
|
+
}
|
|
1382
|
+
getModelContextWindow(model = this.getModel(), provider = this.getProvider()) {
|
|
1383
|
+
const catalog = this.getRoutedModelCatalog();
|
|
1384
|
+
if (catalog?.version !== 1)
|
|
1385
|
+
return undefined;
|
|
1386
|
+
return resolveRouterModel(catalog, provider, model)?.capabilities?.context_window ?? null;
|
|
1387
|
+
}
|
|
1204
1388
|
/**
|
|
1205
1389
|
* Resolve everything a backend factory needs into one struct. Folds in the
|
|
1206
1390
|
* provider/model override precedence, the direct-key precedence
|
|
@@ -1215,8 +1399,7 @@ export class ConfigStore {
|
|
|
1215
1399
|
*
|
|
1216
1400
|
* Reads through `get()` and the env-aware getters (never raw `this.config`)
|
|
1217
1401
|
* so cli/session overrides stay honored. `apiKey` is the DIRECT provider key;
|
|
1218
|
-
* `authToken`/`useProxy` describe the proxy route separately
|
|
1219
|
-
* still prefer a direct key (e.g. Gemini) over the proxy.
|
|
1402
|
+
* `authToken`/`useProxy` describe the selected proxy route separately.
|
|
1220
1403
|
*/
|
|
1221
1404
|
resolveLLMBackendConfig(opts = {}) {
|
|
1222
1405
|
// `opts.config` resolves the config reads below (provider, model, authMode,
|
|
@@ -1233,15 +1416,15 @@ export class ConfigStore {
|
|
|
1233
1416
|
const repoOverride = !opts.provider && !opts.model && !this.hasExplicitModelOverride() && opts.cwd
|
|
1234
1417
|
? resolveRepoModelOverride(opts.cwd)
|
|
1235
1418
|
: null;
|
|
1236
|
-
|
|
1419
|
+
let provider = repoOverride?.provider
|
|
1237
1420
|
?? normalizeProviderId(opts.provider || cfg.provider || this.getProvider());
|
|
1238
1421
|
const configProvider = cfg.provider ? normalizeProviderId(cfg.provider) : undefined;
|
|
1239
|
-
|
|
1422
|
+
let model = repoOverride?.model
|
|
1240
1423
|
?? opts.model
|
|
1241
1424
|
?? (configProvider === provider ? cfg.model : undefined)
|
|
1242
1425
|
?? getDefaultModelForProvider(provider);
|
|
1243
|
-
const authMode = resolveAuthMode(cfg);
|
|
1244
|
-
const proxyUrl = cfg.zergProxyUrl;
|
|
1426
|
+
const authMode = isLocalSubscriptionProvider(provider) ? 'direct' : resolveAuthMode(cfg);
|
|
1427
|
+
const proxyUrl = normalizedOrigin(cfg.zergProxyUrl);
|
|
1245
1428
|
// Legacy platform tokens belong only to its /api/zrouter endpoint. A
|
|
1246
1429
|
// standalone Router requires its own device login, including after logout.
|
|
1247
1430
|
// Modal shared endpoints are unavailable through the legacy platform proxy.
|
|
@@ -1293,7 +1476,19 @@ export class ConfigStore {
|
|
|
1293
1476
|
|| this.getOpenAICompatibleSettings(cfg).baseUrl
|
|
1294
1477
|
|| cfg.openaiCompatibleBaseUrl;
|
|
1295
1478
|
const proxyAvailable = Boolean(proxyUrl && authToken);
|
|
1296
|
-
|
|
1479
|
+
// Resolve the route here so discovery and backend construction agree. Auto
|
|
1480
|
+
// retains the existing local-subscription and direct-Gemini preferences.
|
|
1481
|
+
const localSubscription = isLocalSubscriptionProvider(provider);
|
|
1482
|
+
const useProxy = authMode === 'direct' ? false : proxyAvailable
|
|
1483
|
+
&& !localSubscription && !(authMode === 'auto' && provider === 'gemini' && Boolean(apiKey));
|
|
1484
|
+
if (useProxy) {
|
|
1485
|
+
const catalog = readRouterCatalog({ origin: proxyUrl, token: authToken, workspaceId: this.getRouterCatalogConnection(proxyUrl)?.workspaceId });
|
|
1486
|
+
const descriptor = catalog?.version === 1 ? resolveRouterModel(catalog, provider, model) : undefined;
|
|
1487
|
+
if (descriptor) {
|
|
1488
|
+
provider = descriptor.owned_by;
|
|
1489
|
+
model = descriptor.id;
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1297
1492
|
const compatBaseUrl = provider === 'openai_compatible' && rawCompatBaseUrl
|
|
1298
1493
|
? compatEndpoint(rawCompatBaseUrl, { apiKey })
|
|
1299
1494
|
: rawCompatBaseUrl;
|
|
@@ -1314,7 +1509,9 @@ export class ConfigStore {
|
|
|
1314
1509
|
codexHome: accountOptions.codexHome,
|
|
1315
1510
|
codexAuthFilePath: accountOptions.codexAuthFilePath,
|
|
1316
1511
|
kimiCredsFilePath: accountOptions.kimiCredsFilePath,
|
|
1317
|
-
codexEffort:
|
|
1512
|
+
codexEffort: resolveCodexEffort(cfg, provider, model, (useProxy
|
|
1513
|
+
? this.getRouterCatalog()?.models.find(row => row.id === model && row.owned_by === provider)?.capabilities : undefined)
|
|
1514
|
+
?? (useProxy || provider === 'openai_compatible' ? 'chat_tools' : 'native_api')),
|
|
1318
1515
|
};
|
|
1319
1516
|
}
|
|
1320
1517
|
getEnvKey(provider) {
|
|
@@ -1335,6 +1532,7 @@ export class ConfigStore {
|
|
|
1335
1532
|
: undefined;
|
|
1336
1533
|
case 'openai': return process.env.OPENAI_API_KEY;
|
|
1337
1534
|
case 'deepseek': return process.env.DEEPSEEK_API_KEY;
|
|
1535
|
+
case 'fireworks': return process.env.FIREWORKS_API_KEY;
|
|
1338
1536
|
case 'gemini': return process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY;
|
|
1339
1537
|
case 'inception': return process.env.INCEPTION_API_KEY;
|
|
1340
1538
|
case 'openai_compatible': return process.env.OPENAI_COMPAT_API_KEY;
|
package/dist/headless.js
CHANGED
|
@@ -2736,6 +2736,8 @@ export class HeadlessApp {
|
|
|
2736
2736
|
* auto-starts; the user runs /goal resume. Shared by both load branches.
|
|
2737
2737
|
*/
|
|
2738
2738
|
applyResumedSession(session, restoreRuntimeMode = true) {
|
|
2739
|
+
if (!session.hosted_settings)
|
|
2740
|
+
configStore.restoreSessionSelection(session.metadata);
|
|
2739
2741
|
this.sessionId = session.metadata.id;
|
|
2740
2742
|
this.sessionManager.setSessionId(this.sessionId);
|
|
2741
2743
|
this.sessionName = session.metadata.name;
|
|
@@ -125,8 +125,12 @@ function formatProjectLine(options) {
|
|
|
125
125
|
return parts.join(' · ');
|
|
126
126
|
}
|
|
127
127
|
function formatRuntimeLine(options) {
|
|
128
|
+
const providerId = singleLine(options.provider);
|
|
129
|
+
const modelId = singleLine(options.model);
|
|
130
|
+
const displayModel = providerId && modelId.startsWith(`${providerId}/`)
|
|
131
|
+
? modelId.slice(providerId.length + 1) : modelId;
|
|
128
132
|
const provider = compact(options.provider, 12) || 'not configured';
|
|
129
|
-
const model = compact(
|
|
133
|
+
const model = compact(displayModel, 24) || 'default';
|
|
130
134
|
const version = compact(options.version, 12);
|
|
131
135
|
return `Runtime: ${provider}/${model}${version ? ` · ZTC v${version}` : ''}`;
|
|
132
136
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const PANE_PROVIDERS: readonly ["anthropic", "claude_code", "openai", "codex_app_server", "codex_legacy", "gemini", "deepseek", "fireworks", "modal", "kimi", "kimi_code"];
|
|
2
|
-
export type PaneProvider =
|
|
2
|
+
export type PaneProvider = string;
|
|
3
3
|
export interface CatalogModel {
|
|
4
4
|
id: string;
|
|
5
5
|
name: string;
|
|
@@ -14,13 +14,13 @@ export interface CatalogProviderGroup {
|
|
|
14
14
|
models: CatalogModel[];
|
|
15
15
|
}
|
|
16
16
|
export declare const MODEL_CATALOG: CatalogProviderGroup[];
|
|
17
|
-
export declare function isPaneProvider(value: string | undefined): value is PaneProvider;
|
|
17
|
+
export declare function isPaneProvider(value: string | undefined, route?: 'auto' | 'direct' | 'zrouter'): value is PaneProvider;
|
|
18
18
|
export declare function getModelDisplayName(modelId: string): string;
|
|
19
19
|
export declare function getProviderForModel(modelId: string): PaneProvider | undefined;
|
|
20
20
|
/** Provider-aware membership for duplicate model IDs such as the Codex catalogs. */
|
|
21
21
|
export declare function isModelAvailableForProvider(provider: string, modelId: string): boolean;
|
|
22
22
|
export declare function isCatalogModelForProvider(provider: PaneProvider, modelId: string): boolean;
|
|
23
|
-
export declare function resolveModelAndProvider(rawModel: string, rawProvider?: string): {
|
|
23
|
+
export declare function resolveModelAndProvider(rawModel: string, rawProvider?: string, route?: 'auto' | 'direct' | 'zrouter'): {
|
|
24
24
|
model: string;
|
|
25
25
|
provider?: PaneProvider | string;
|
|
26
26
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { configStore } from '../config.js';
|
|
1
2
|
import { GPT_6_API_EFFORTS, getKimiModelInfo, getSupportedCodexReasoningEfforts, KIMI_CODE_MODEL_IDS, KIMI_MODEL_IDS, KIMI_MODEL_INFO, OFFICIAL_CODEX_MODEL_IDS, OFFICIAL_CODEX_MODEL_INFO, } from '../utils/models.js';
|
|
2
3
|
import { DEEPSEEK_FLASH_EFFORTS, DEEPSEEK_FLASH_MODEL, MODAL_DEEPSEEK_FLASH_EFFORTS, MODAL_DEEPSEEK_FLASH_MODEL } from '../utils/deepseek.js';
|
|
3
4
|
import { FIREWORKS_CHAT_MODELS, FIREWORKS_FUNDED_MODEL } from '../utils/fireworks.js';
|
|
@@ -183,8 +184,8 @@ function getCodexModelAliases(id) {
|
|
|
183
184
|
return [];
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
|
-
export function isPaneProvider(value) {
|
|
187
|
-
return !!value && PROVIDER_SET.has(value);
|
|
187
|
+
export function isPaneProvider(value, route) {
|
|
188
|
+
return !!value && (PROVIDER_SET.has(value) || ((route === 'zrouter' || route === 'auto') && /^[a-z][a-z0-9_-]{0,127}$/.test(value)));
|
|
188
189
|
}
|
|
189
190
|
export function getModelDisplayName(modelId) {
|
|
190
191
|
return MODEL_BY_ID.get(modelId)?.name
|
|
@@ -203,8 +204,17 @@ export function isModelAvailableForProvider(provider, modelId) {
|
|
|
203
204
|
export function isCatalogModelForProvider(provider, modelId) {
|
|
204
205
|
return MODEL_CATALOG.some((group) => group.provider === provider && group.models.some((model) => model.id === modelId));
|
|
205
206
|
}
|
|
206
|
-
export function resolveModelAndProvider(rawModel, rawProvider) {
|
|
207
|
+
export function resolveModelAndProvider(rawModel, rawProvider, route) {
|
|
207
208
|
const trimmed = rawModel.trim();
|
|
209
|
+
if (route === 'zrouter' && rawProvider)
|
|
210
|
+
return { model: trimmed, provider: rawProvider };
|
|
211
|
+
if (route === 'zrouter') {
|
|
212
|
+
const matches = configStore.getRouterCatalog()?.models.filter(row => row.id === trimmed && row.capabilities?.chat);
|
|
213
|
+
if (matches?.length === 1)
|
|
214
|
+
return { model: trimmed, provider: matches[0].owned_by };
|
|
215
|
+
if (matches && matches.length > 1)
|
|
216
|
+
throw new Error('Ambiguous Router model. Specify --provider.');
|
|
217
|
+
}
|
|
208
218
|
const normalized = normalizeLookupValue(trimmed);
|
|
209
219
|
const providerNormalized = (rawProvider || '').toLowerCase();
|
|
210
220
|
// A custom OpenAI-compatible endpoint names its own models, so the id is a
|
|
@@ -289,5 +299,19 @@ function getCodexLegacyModelAliases(id) {
|
|
|
289
299
|
}
|
|
290
300
|
}
|
|
291
301
|
export function getModelCatalogPayload() {
|
|
292
|
-
|
|
302
|
+
const catalog = configStore.getRoutedModelCatalog();
|
|
303
|
+
if (catalog?.version !== 1)
|
|
304
|
+
return { providers: MODEL_CATALOG };
|
|
305
|
+
const groups = new Map();
|
|
306
|
+
for (const row of catalog.models) {
|
|
307
|
+
if (!row.capabilities?.chat)
|
|
308
|
+
continue;
|
|
309
|
+
const group = groups.get(row.owned_by) ?? { provider: row.owned_by, label: row.provider_display_name || row.owned_by, models: [] };
|
|
310
|
+
group.models.push({ id: row.id, name: row.display_name || row.id,
|
|
311
|
+
description: [row.capabilities.tools === false ? 'Chat only' : '', row.available === false ? 'Access unavailable' : ''].filter(Boolean).join(' · '),
|
|
312
|
+
supportedReasoningEfforts: row.capabilities.reasoning?.choices,
|
|
313
|
+
defaultReasoningEffort: row.capabilities.reasoning?.default });
|
|
314
|
+
groups.set(row.owned_by, group);
|
|
315
|
+
}
|
|
316
|
+
return { providers: [...groups.values()] };
|
|
293
317
|
}
|
|
@@ -26,15 +26,19 @@ function inferZtcLaunchSpec(pane) {
|
|
|
26
26
|
}
|
|
27
27
|
if (!sessionId)
|
|
28
28
|
return undefined;
|
|
29
|
+
const route = parseFlagValue(args, '--auth-mode');
|
|
30
|
+
const authMode = route === 'zrouter' || route === 'direct' || route === 'auto' ? route : undefined;
|
|
29
31
|
const explicitProvider = parseFlagValue(args, '--provider');
|
|
30
32
|
const explicitModel = parseFlagValue(args, '--model');
|
|
31
|
-
const resolved = explicitModel ? resolveModelAndProvider(explicitModel, explicitProvider) : { model: undefined, provider: explicitProvider };
|
|
33
|
+
const resolved = explicitModel ? resolveModelAndProvider(explicitModel, explicitProvider, authMode) : { model: undefined, provider: explicitProvider };
|
|
32
34
|
return {
|
|
33
35
|
kind: 'ztc',
|
|
36
|
+
authMode,
|
|
37
|
+
routerOrigin: parseFlagValue(args, '--router-url'),
|
|
34
38
|
session: { mode: sessionMode, id: sessionId },
|
|
35
39
|
cwd: pane.cwd,
|
|
36
40
|
title: pane.title,
|
|
37
|
-
providerOverride: isPaneProvider(resolved.provider) ? resolved.provider : undefined,
|
|
41
|
+
providerOverride: isPaneProvider(resolved.provider, authMode) ? resolved.provider : undefined,
|
|
38
42
|
modelOverride: resolved.model,
|
|
39
43
|
};
|
|
40
44
|
}
|
package/dist/panes/types.d.ts
CHANGED