@gajae-code/coding-agent 0.15.2 → 0.15.4
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/CHANGELOG.md +43 -1
- package/dist/types/config/autorouting-tier-map.d.ts +0 -9
- package/dist/types/config/file-lock.d.ts +7 -1
- package/dist/types/config/keybindings.d.ts +13 -3
- package/dist/types/config/model-registry.d.ts +5 -0
- package/dist/types/config/model-resolver.d.ts +1 -0
- package/dist/types/config/settings-schema.d.ts +65 -1
- package/dist/types/coordinator/contract.d.ts +1 -1
- package/dist/types/coordinator-mcp/question-state.d.ts +42 -2
- package/dist/types/extensibility/extensions/types.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +12 -0
- package/dist/types/gjc-runtime/workflow-placeholder.d.ts +6 -0
- package/dist/types/main.d.ts +1 -1
- package/dist/types/modes/action-registry.d.ts +1 -0
- package/dist/types/modes/components/hook-selector.d.ts +1 -0
- package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +1 -1
- package/dist/types/modes/components/welcome.d.ts +2 -0
- package/dist/types/modes/controllers/input-controller.d.ts +16 -1
- package/dist/types/modes/controllers/runtime-mcp-command-controller.d.ts +42 -0
- package/dist/types/modes/interactive-mode.d.ts +7 -0
- package/dist/types/modes/shared/oauth-url-copy.d.ts +9 -0
- package/dist/types/modes/types.d.ts +3 -0
- package/dist/types/modes/ui-language.d.ts +2 -1
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +1 -0
- package/dist/types/sdk/broker/session-index.d.ts +18 -0
- package/dist/types/sdk/bus/index.d.ts +4 -1
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +4 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +2 -0
- package/dist/types/sdk/cli/session-cli.d.ts +1 -1
- package/dist/types/sdk/lifecycle/service.d.ts +32 -5
- package/dist/types/sdk/session.d.ts +5 -0
- package/dist/types/session/agent-session.d.ts +4 -0
- package/dist/types/session/fallback-chain-controller.d.ts +8 -0
- package/dist/types/slash-commands/helpers/aside.d.ts +54 -0
- package/dist/types/tools/ask.d.ts +9 -0
- package/dist/types/utils/clipboard.d.ts +9 -1
- package/package.json +7 -7
- package/scripts/generate-sdk-adapter-parity-manifest.ts +5 -2
- package/scripts/generate-sdk-operation-inventory.ts +3 -0
- package/src/commands/sdk.ts +2 -2
- package/src/config/autorouting-tier-map.ts +0 -9
- package/src/config/file-lock.ts +15 -1
- package/src/config/keybindings.ts +13 -3
- package/src/config/model-registry.ts +132 -21
- package/src/config/model-resolver.ts +2 -1
- package/src/config/models-config-schema.ts +2 -2
- package/src/config/settings-schema.ts +66 -1
- package/src/config/settings.ts +1 -1
- package/src/coordinator/contract.ts +1 -0
- package/src/coordinator-mcp/question-state.ts +235 -4
- package/src/coordinator-mcp/server.ts +402 -2
- package/src/dap/client.ts +19 -8
- package/src/deep-interview/render-middleware.ts +6 -2
- package/src/extensibility/extensions/types.ts +2 -0
- package/src/gjc-runtime/deep-interview-stage.ts +20 -1
- package/src/gjc-runtime/deep-interview-state.ts +3 -1
- package/src/gjc-runtime/ralplan-runtime.ts +6 -1
- package/src/gjc-runtime/session-state-lock.ts +11 -2
- package/src/gjc-runtime/ultragoal-runtime.ts +5 -0
- package/src/gjc-runtime/workflow-placeholder.ts +33 -0
- package/src/internal-urls/docs-index.generated.ts +11 -9
- package/src/lsp/client.ts +39 -4
- package/src/main.ts +42 -11
- package/src/modes/action-registry.ts +7 -0
- package/src/modes/components/hook-selector.ts +2 -1
- package/src/modes/components/iterm-pet-transport.ts +4 -2
- package/src/modes/components/runtime-mcp-add-wizard.ts +38 -1
- package/src/modes/components/settings-selector.ts +1 -0
- package/src/modes/components/tool-status-header.ts +149 -41
- package/src/modes/components/welcome.ts +8 -0
- package/src/modes/controllers/extension-ui-controller.ts +1 -0
- package/src/modes/controllers/goal-mode-controller.ts +7 -2
- package/src/modes/controllers/input-controller.ts +141 -7
- package/src/modes/controllers/plan-mode-controller.ts +12 -4
- package/src/modes/controllers/runtime-mcp-command-controller.ts +164 -20
- package/src/modes/controllers/selector-controller.ts +11 -2
- package/src/modes/interactive-mode.ts +88 -1
- package/src/modes/shared/oauth-url-copy.ts +33 -0
- package/src/modes/types.ts +3 -0
- package/src/modes/ui-language.ts +44 -3
- package/src/runtime-mcp/oauth-flow.ts +19 -8
- package/src/runtime-mcp/transports/stdio.ts +27 -13
- package/src/sdk/acp/adapter.ts +29 -2
- package/src/sdk/broker/broker.ts +26 -6
- package/src/sdk/broker/lifecycle-ledger.ts +28 -1
- package/src/sdk/broker/lifecycle.ts +664 -5
- package/src/sdk/broker/session-index.ts +246 -0
- package/src/sdk/broker/transport.ts +1 -0
- package/src/sdk/bus/index.ts +135 -38
- package/src/sdk/bus/natives-augment.d.ts +20 -1
- package/src/sdk/bus/telegram-daemon-contract.ts +4 -1
- package/src/sdk/bus/telegram-daemon.ts +3 -0
- package/src/sdk/cli/session-cli.ts +34 -7
- package/src/sdk/lifecycle/service.ts +166 -11
- package/src/sdk/mcp/server.ts +2 -1
- package/src/sdk/protocol/operation-inventory.generated.json +40 -0
- package/src/sdk/protocol/operation-registry.ts +2 -1
- package/src/sdk/session.ts +91 -7
- package/src/session/agent-session.ts +473 -66
- package/src/session/fallback-chain-controller.ts +17 -0
- package/src/setup/frictionless-onboarding.ts +4 -4
- package/src/slash-commands/aside-command.test.ts +366 -0
- package/src/slash-commands/builtin-registry.ts +19 -0
- package/src/slash-commands/helpers/aside.ts +299 -0
- package/src/tools/ask-contract.ts +54 -3
- package/src/tools/ask.ts +54 -6
- package/src/utils/clipboard.ts +37 -28
|
@@ -16,12 +16,14 @@ import {
|
|
|
16
16
|
enrichModelThinking,
|
|
17
17
|
getBundledModels,
|
|
18
18
|
getBundledProviders,
|
|
19
|
+
getEnvApiKey,
|
|
19
20
|
googleAntigravityModelManagerOptions,
|
|
20
21
|
googleGeminiCliModelManagerOptions,
|
|
21
22
|
isCodexGpt56Tier,
|
|
22
23
|
isKnownProvider,
|
|
23
24
|
type Model,
|
|
24
25
|
type ModelManagerOptions,
|
|
26
|
+
type ModelMaxTokensSource,
|
|
25
27
|
type ModelRefreshStrategy,
|
|
26
28
|
type ModelRequestTransform,
|
|
27
29
|
modelSupportsReasoningControl,
|
|
@@ -47,6 +49,10 @@ function isVllmNoAuthToken(provider: string, apiKey: string | undefined): boolea
|
|
|
47
49
|
return provider === "vllm" && apiKey === VLLM_DEFAULT_LOCAL_TOKEN;
|
|
48
50
|
}
|
|
49
51
|
|
|
52
|
+
function normalizeVllmApiKey(provider: string, apiKey: string | undefined): string | undefined {
|
|
53
|
+
return isVllmNoAuthToken(provider, apiKey) ? getEnvApiKey(provider) : apiKey;
|
|
54
|
+
}
|
|
55
|
+
|
|
50
56
|
import { registerOAuthProvider, unregisterOAuthProviders } from "@gajae-code/ai/utils/oauth";
|
|
51
57
|
import type { OAuthCredentials, OAuthLoginCallbacks } from "@gajae-code/ai/utils/oauth/types";
|
|
52
58
|
import { $pickCredentialEnv, $rotatingCredentialEnv, isRecord, logger } from "@gajae-code/utils";
|
|
@@ -996,7 +1002,10 @@ function applyModelOverride(model: Model<Api>, override: ModelOverride): Model<A
|
|
|
996
1002
|
override: override.contextWindow,
|
|
997
1003
|
});
|
|
998
1004
|
}
|
|
999
|
-
if (override.maxTokens !== undefined
|
|
1005
|
+
if (override.maxTokens !== undefined && Number.isSafeInteger(override.maxTokens) && override.maxTokens > 0) {
|
|
1006
|
+
result.maxTokens = override.maxTokens;
|
|
1007
|
+
result.maxTokensSource = "configured";
|
|
1008
|
+
}
|
|
1000
1009
|
if (override.contextPromotionTarget !== undefined) result.contextPromotionTarget = override.contextPromotionTarget;
|
|
1001
1010
|
if (override.wireModelId !== undefined) result.wireModelId = override.wireModelId;
|
|
1002
1011
|
result.requestTransform = mergeRequestTransform(model.requestTransform, override.requestTransform);
|
|
@@ -1074,6 +1083,7 @@ type CustomModelOverlay = {
|
|
|
1074
1083
|
cost?: { input: number; output: number; cacheRead: number; cacheWrite: number };
|
|
1075
1084
|
contextWindow?: number;
|
|
1076
1085
|
maxTokens?: number;
|
|
1086
|
+
maxTokensSource?: ModelMaxTokensSource;
|
|
1077
1087
|
headers?: Record<string, string>;
|
|
1078
1088
|
compat?: Model<Api>["compat"];
|
|
1079
1089
|
contextPromotionTarget?: string;
|
|
@@ -1150,6 +1160,10 @@ function buildCustomModelOverlay(
|
|
|
1150
1160
|
cost: modelDef.cost,
|
|
1151
1161
|
contextWindow: modelDef.contextWindow,
|
|
1152
1162
|
maxTokens: modelDef.maxTokens,
|
|
1163
|
+
maxTokensSource:
|
|
1164
|
+
modelDef.maxTokens !== undefined && Number.isSafeInteger(modelDef.maxTokens) && modelDef.maxTokens > 0
|
|
1165
|
+
? "configured"
|
|
1166
|
+
: undefined,
|
|
1153
1167
|
headers: mergeCustomModelHeaders(providerHeaders, modelDef.headers, authHeader, providerApiKey),
|
|
1154
1168
|
compat: mergeCompat(providerCompat, modelDef.compat),
|
|
1155
1169
|
requestTransform: mergeRequestTransform(providerRequestTransform, modelDef.requestTransform),
|
|
@@ -1284,6 +1298,8 @@ function finalizeCustomModel(model: CustomModelOverlay, options: CustomModelBuil
|
|
|
1284
1298
|
contextWindow:
|
|
1285
1299
|
resolvedModel.contextWindow ?? reference?.contextWindow ?? (options.useDefaults ? 128000 : undefined),
|
|
1286
1300
|
maxTokens: resolvedModel.maxTokens ?? reference?.maxTokens ?? (options.useDefaults ? 16384 : undefined),
|
|
1301
|
+
maxTokensSource:
|
|
1302
|
+
resolvedModel.maxTokensSource ?? (reference?.maxTokensSource === "configured" ? "configured" : undefined),
|
|
1287
1303
|
headers: resolvedModel.headers,
|
|
1288
1304
|
compat: mergeCompat(reference?.compat, resolvedModel.compat),
|
|
1289
1305
|
contextPromotionTarget: resolvedModel.contextPromotionTarget,
|
|
@@ -1507,6 +1523,68 @@ export class ModelRegistry {
|
|
|
1507
1523
|
}
|
|
1508
1524
|
}
|
|
1509
1525
|
|
|
1526
|
+
admitCachedProviderForStoredLiteralCredential(providerId: string, selector: AuthCredentialSelector): boolean {
|
|
1527
|
+
const cachedModels = this.#loadCachedProviderModelsForStoredLiteralCredential(providerId, selector);
|
|
1528
|
+
if (!cachedModels || cachedModels.length === 0) return false;
|
|
1529
|
+
|
|
1530
|
+
this.#suspendRebuild();
|
|
1531
|
+
try {
|
|
1532
|
+
this.#mergeDiscoveredModels(cachedModels);
|
|
1533
|
+
this.#rebuildProviderActivity();
|
|
1534
|
+
this.#modelBindingsApplier.apply();
|
|
1535
|
+
return true;
|
|
1536
|
+
} finally {
|
|
1537
|
+
this.#resumeRebuild();
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
/** @internal Validate an existing startup model without mutating a caller-supplied registry. */
|
|
1542
|
+
validateModelForStoredLiteralCredential(
|
|
1543
|
+
providerId: string,
|
|
1544
|
+
modelId: string,
|
|
1545
|
+
selector: AuthCredentialSelector,
|
|
1546
|
+
): boolean {
|
|
1547
|
+
if (!this.find(providerId, modelId)) return false;
|
|
1548
|
+
if (this.#resolveStaticModelReference(providerId, modelId)) return true;
|
|
1549
|
+
const cachedModels = this.#loadCachedProviderModelsForStoredLiteralCredential(providerId, selector, false);
|
|
1550
|
+
return cachedModels ? resolveProviderModelReference(providerId, modelId, cachedModels) !== undefined : false;
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
/** @internal Whether startup must establish credential-scoped cache provenance for this exact target. */
|
|
1554
|
+
requiresStoredLiteralCredentialCacheAdmission(providerId: string, modelId: string): boolean {
|
|
1555
|
+
return !this.find(providerId, modelId) || !this.#resolveStaticModelReference(providerId, modelId);
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
#loadCachedProviderModelsForStoredLiteralCredential(
|
|
1559
|
+
providerId: string,
|
|
1560
|
+
selector: AuthCredentialSelector,
|
|
1561
|
+
publishDiscoveryState = true,
|
|
1562
|
+
): Model<Api>[] | undefined {
|
|
1563
|
+
const supportsDiscovery =
|
|
1564
|
+
this.#discoveryManager.providerIds().has(providerId) ||
|
|
1565
|
+
PROVIDER_DESCRIPTORS.some(descriptor => descriptor.providerId === providerId);
|
|
1566
|
+
if (!supportsDiscovery) return undefined;
|
|
1567
|
+
const authEvidence = this.authStorage.getStoredLiteralApiKeyEvidenceGeneration(providerId, selector);
|
|
1568
|
+
if (!authEvidence) return undefined;
|
|
1569
|
+
return [
|
|
1570
|
+
...this.#loadCachedStandardProviderModels(providerId, authEvidence),
|
|
1571
|
+
...this.#loadCachedDiscoverableModels(providerId, authEvidence, publishDiscoveryState),
|
|
1572
|
+
];
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
#resolveStaticModelReference(providerId: string, modelId: string): Model<Api> | undefined {
|
|
1576
|
+
const normalizedProvider = providerId.toLowerCase();
|
|
1577
|
+
const matchingActivity = [...this.#providerActivity.entries()].filter(
|
|
1578
|
+
([candidateProvider]) => candidateProvider.toLowerCase() === normalizedProvider,
|
|
1579
|
+
);
|
|
1580
|
+
if (matchingActivity.length !== 1) return undefined;
|
|
1581
|
+
const [canonicalProvider, activity] = matchingActivity[0];
|
|
1582
|
+
const staticModels = this.#models.filter(
|
|
1583
|
+
model => model.provider === canonicalProvider && activity.staticModelIds.has(model.id),
|
|
1584
|
+
);
|
|
1585
|
+
return resolveProviderModelReference(providerId, modelId, staticModels);
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1510
1588
|
#getStaticLoadEnvironmentFingerprint(): string {
|
|
1511
1589
|
const providerBaseUrlEnvKeys = new Set(
|
|
1512
1590
|
[
|
|
@@ -1744,6 +1822,7 @@ export class ModelRegistry {
|
|
|
1744
1822
|
cost: customModel.cost ?? existingModel.cost,
|
|
1745
1823
|
contextWindow: customModel.contextWindow ?? existingModel.contextWindow,
|
|
1746
1824
|
maxTokens: customModel.maxTokens ?? existingModel.maxTokens,
|
|
1825
|
+
maxTokensSource: customModel.maxTokensSource ?? existingModel.maxTokensSource,
|
|
1747
1826
|
// Same-id custom definitions replace bundled transport behavior. Provider-level
|
|
1748
1827
|
// headers/compat were already folded into customModel during parsing; do not
|
|
1749
1828
|
// re-merge bundled transport metadata here.
|
|
@@ -1762,16 +1841,17 @@ export class ModelRegistry {
|
|
|
1762
1841
|
return merged;
|
|
1763
1842
|
}
|
|
1764
1843
|
|
|
1765
|
-
#loadCachedStandardProviderModels(): Model<Api>[] {
|
|
1844
|
+
#loadCachedStandardProviderModels(providerId?: string, authEvidence?: string): Model<Api>[] {
|
|
1766
1845
|
const configuredDiscoveryProviders = new Set(this.#discoveryManager.providers.map(provider => provider.provider));
|
|
1767
1846
|
const cachedModels: Model<Api>[] = [];
|
|
1768
1847
|
for (const descriptor of PROVIDER_DESCRIPTORS) {
|
|
1848
|
+
if (providerId && descriptor.providerId !== providerId) continue;
|
|
1769
1849
|
if (configuredDiscoveryProviders.has(descriptor.providerId)) {
|
|
1770
1850
|
continue;
|
|
1771
1851
|
}
|
|
1772
1852
|
const cache = readModelCache<Api>(descriptor.providerId, 24 * 60 * 60 * 1000, Date.now, this.#cacheDbPath);
|
|
1773
1853
|
const expectedProvenance = fingerprintDescriptorDiscoveryProvenance(
|
|
1774
|
-
this.#getProviderEvidenceGeneration(descriptor.providerId),
|
|
1854
|
+
authEvidence ?? this.#getProviderEvidenceGeneration(descriptor.providerId),
|
|
1775
1855
|
this.#normalizeDiscoveryEvidenceEndpoint(this.#getProviderBaseUrlForDiscovery(descriptor.providerId) ?? ""),
|
|
1776
1856
|
);
|
|
1777
1857
|
if (
|
|
@@ -1796,22 +1876,29 @@ export class ModelRegistry {
|
|
|
1796
1876
|
return cachedModels;
|
|
1797
1877
|
}
|
|
1798
1878
|
|
|
1799
|
-
#loadCachedDiscoverableModels(
|
|
1879
|
+
#loadCachedDiscoverableModels(
|
|
1880
|
+
providerId?: string,
|
|
1881
|
+
authEvidence?: string,
|
|
1882
|
+
publishDiscoveryState = true,
|
|
1883
|
+
): Model<Api>[] {
|
|
1800
1884
|
const cachedModels: Model<Api>[] = [];
|
|
1801
1885
|
for (const providerConfig of this.#discoveryManager.providers) {
|
|
1886
|
+
if (providerId && providerConfig.provider !== providerId) continue;
|
|
1802
1887
|
let expectedProvenance: string | undefined;
|
|
1803
1888
|
try {
|
|
1804
1889
|
const effectiveConfig = this.#effectiveDiscoveryProviderConfig(providerConfig);
|
|
1805
1890
|
expectedProvenance = fingerprintConfiguredDiscoveryRequestShape(
|
|
1806
1891
|
effectiveConfig,
|
|
1807
|
-
this.#getProviderEvidenceGeneration(effectiveConfig.provider),
|
|
1892
|
+
authEvidence ?? this.#getProviderEvidenceGeneration(effectiveConfig.provider),
|
|
1808
1893
|
this.#normalizeDiscoveryEvidenceEndpoint(effectiveConfig.baseUrl ?? ""),
|
|
1809
1894
|
);
|
|
1810
1895
|
} catch {
|
|
1811
1896
|
// A context that cannot be fully derived cannot vouch for a cache row.
|
|
1812
1897
|
expectedProvenance = undefined;
|
|
1813
1898
|
}
|
|
1814
|
-
const models =
|
|
1899
|
+
const models = publishDiscoveryState
|
|
1900
|
+
? this.#discoveryManager.loadCached(providerConfig, this.#cacheDbPath, expectedProvenance)
|
|
1901
|
+
: this.#readCachedDiscoverableModels(providerConfig, expectedProvenance);
|
|
1815
1902
|
// Cache rows persist sanitized transport metadata (no headers), so a
|
|
1816
1903
|
// rebooted registry re-derives the provider transport override from the
|
|
1817
1904
|
// same source the live publish path uses — mirroring the cached
|
|
@@ -1834,6 +1921,22 @@ export class ModelRegistry {
|
|
|
1834
1921
|
return cachedModels;
|
|
1835
1922
|
}
|
|
1836
1923
|
|
|
1924
|
+
#readCachedDiscoverableModels(
|
|
1925
|
+
providerConfig: DiscoveryProviderConfig,
|
|
1926
|
+
expectedProvenance: string | undefined,
|
|
1927
|
+
): Model<Api>[] {
|
|
1928
|
+
const cache = readModelCache<Api>(providerConfig.provider, 24 * 60 * 60 * 1000, Date.now, this.#cacheDbPath);
|
|
1929
|
+
if (
|
|
1930
|
+
cache === null ||
|
|
1931
|
+
cache.dynamicModelIds === undefined ||
|
|
1932
|
+
expectedProvenance === undefined ||
|
|
1933
|
+
cache.dynamicModelProvenance !== expectedProvenance
|
|
1934
|
+
) {
|
|
1935
|
+
return [];
|
|
1936
|
+
}
|
|
1937
|
+
return applyFinalCodexGpt56ContextCap(cache.models);
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1837
1940
|
#applyProviderCompat(compat: Model<Api>["compat"] | undefined, models: Model<Api>[]): Model<Api>[] {
|
|
1838
1941
|
if (!compat) return models;
|
|
1839
1942
|
return models.map(model => ({ ...model, compat: mergeCompat(model.compat, compat) }));
|
|
@@ -2452,6 +2555,10 @@ export class ModelRegistry {
|
|
|
2452
2555
|
}
|
|
2453
2556
|
return;
|
|
2454
2557
|
}
|
|
2558
|
+
this.#mergeDiscoveredModels(discovered);
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
#mergeDiscoveredModels(discovered: readonly Model<Api>[]): void {
|
|
2455
2562
|
const discoveredModels = this.#applyHardcodedModelPolicies(
|
|
2456
2563
|
discovered.map(model =>
|
|
2457
2564
|
mergeDiscoveredModel(
|
|
@@ -2495,11 +2602,14 @@ export class ModelRegistry {
|
|
|
2495
2602
|
if (optionalAuth && isCurrentPreflight()) this.#credentiallessAuthFallbackProviders.delete(provider);
|
|
2496
2603
|
let apiKey: string | undefined;
|
|
2497
2604
|
try {
|
|
2498
|
-
apiKey =
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2605
|
+
apiKey = normalizeVllmApiKey(
|
|
2606
|
+
provider,
|
|
2607
|
+
await this.#peekApiKeyForProvider(provider, {
|
|
2608
|
+
ignoreCredentiallessFallback: optionalAuth,
|
|
2609
|
+
refreshOAuth: true,
|
|
2610
|
+
baseUrl: providerConfig.baseUrl,
|
|
2611
|
+
}),
|
|
2612
|
+
);
|
|
2503
2613
|
const currentAuthConfigurationGeneration = this.authStorage.getProviderConfigurationGeneration(provider);
|
|
2504
2614
|
if (preflightAuthConfigurationGeneration !== currentAuthConfigurationGeneration) {
|
|
2505
2615
|
const currentOAuthRefreshGeneration = this.authStorage.getProviderOAuthRefreshGeneration(provider);
|
|
@@ -3287,6 +3397,11 @@ export class ModelRegistry {
|
|
|
3287
3397
|
if (!isRecord(item) || typeof item.id !== "string" || !item.id.trim()) continue;
|
|
3288
3398
|
const id = item.id;
|
|
3289
3399
|
const referenceModel = resolveCustomModelReference(id);
|
|
3400
|
+
const discoveredMaxTokens = firstPositiveDiscoveryNumber(
|
|
3401
|
+
item.max_completion_tokens,
|
|
3402
|
+
item.max_tokens,
|
|
3403
|
+
item.max_output_tokens,
|
|
3404
|
+
);
|
|
3290
3405
|
const api = this.#resolveDiscoveredModelApi(providerConfig, id);
|
|
3291
3406
|
discovered.push(
|
|
3292
3407
|
enrichModelThinking({
|
|
@@ -3309,14 +3424,8 @@ export class ModelRegistry {
|
|
|
3309
3424
|
referenceModel?.contextWindow,
|
|
3310
3425
|
UNK_CONTEXT_WINDOW,
|
|
3311
3426
|
) ?? UNK_CONTEXT_WINDOW,
|
|
3312
|
-
maxTokens:
|
|
3313
|
-
|
|
3314
|
-
item.max_completion_tokens,
|
|
3315
|
-
item.max_tokens,
|
|
3316
|
-
item.max_output_tokens,
|
|
3317
|
-
referenceModel?.maxTokens,
|
|
3318
|
-
UNK_MAX_TOKENS,
|
|
3319
|
-
) ?? UNK_MAX_TOKENS,
|
|
3427
|
+
maxTokens: discoveredMaxTokens ?? referenceModel?.maxTokens ?? UNK_MAX_TOKENS,
|
|
3428
|
+
maxTokensSource: discoveredMaxTokens === undefined ? referenceModel?.maxTokensSource : "discovered",
|
|
3320
3429
|
headers: providerConfig.headers,
|
|
3321
3430
|
compat: mergeCompat(
|
|
3322
3431
|
{
|
|
@@ -4367,9 +4476,11 @@ export class ModelRegistry {
|
|
|
4367
4476
|
}
|
|
4368
4477
|
|
|
4369
4478
|
async #getApiKeyOrNoAuth(provider: string, lookup: () => Promise<string | undefined>): Promise<string | undefined> {
|
|
4370
|
-
|
|
4371
|
-
if (!this.#optionalAuthProviders.has(provider)) return kNoAuth;
|
|
4479
|
+
const credentialless = this.#isCredentiallessProvider(provider);
|
|
4480
|
+
if (credentialless && !this.#optionalAuthProviders.has(provider)) return kNoAuth;
|
|
4372
4481
|
const apiKey = await lookup();
|
|
4482
|
+
if (isVllmNoAuthToken(provider, apiKey)) return normalizeVllmApiKey(provider, apiKey) ?? kNoAuth;
|
|
4483
|
+
if (!credentialless) return apiKey;
|
|
4373
4484
|
if (apiKey !== undefined) {
|
|
4374
4485
|
this.#credentiallessAuthFallbackProviders.delete(provider);
|
|
4375
4486
|
return apiKey;
|
|
@@ -1025,6 +1025,7 @@ export interface ModelChainResolutionOptions {
|
|
|
1025
1025
|
aliasIntent?: "preset-equivalent" | "reject";
|
|
1026
1026
|
canonicalSessionId?: string | null;
|
|
1027
1027
|
credentialSessionId?: string;
|
|
1028
|
+
signal?: AbortSignal;
|
|
1028
1029
|
}
|
|
1029
1030
|
|
|
1030
1031
|
export async function resolveModelChainWithAuth(
|
|
@@ -1080,7 +1081,7 @@ export async function resolveModelChainWithAuth(
|
|
|
1080
1081
|
break;
|
|
1081
1082
|
}
|
|
1082
1083
|
}
|
|
1083
|
-
const key = await modelRegistry.getApiKey(candidate.model, credentialSessionId);
|
|
1084
|
+
const key = await modelRegistry.getApiKey(candidate.model, credentialSessionId, { signal: options?.signal });
|
|
1084
1085
|
if (isAuthenticatedOrKeyless(key)) {
|
|
1085
1086
|
return { ...candidate, activeIndex, skips };
|
|
1086
1087
|
}
|
|
@@ -158,7 +158,7 @@ const ModelDefinitionSchema = z
|
|
|
158
158
|
.optional(),
|
|
159
159
|
premiumMultiplier: z.number().optional(),
|
|
160
160
|
contextWindow: z.number().optional(),
|
|
161
|
-
maxTokens: z.number().optional(),
|
|
161
|
+
maxTokens: z.number().int().finite().positive().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
162
162
|
headers: z.record(z.string(), z.string()).optional(),
|
|
163
163
|
compat: ModelCompatSchema.optional(),
|
|
164
164
|
contextPromotionTarget: z.string().min(1).optional(),
|
|
@@ -185,7 +185,7 @@ export const ModelOverrideSchema = z
|
|
|
185
185
|
.optional(),
|
|
186
186
|
premiumMultiplier: z.number().optional(),
|
|
187
187
|
contextWindow: z.number().optional(),
|
|
188
|
-
maxTokens: z.number().optional(),
|
|
188
|
+
maxTokens: z.number().int().finite().positive().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
189
189
|
headers: z.record(z.string(), z.string()).optional(),
|
|
190
190
|
compat: ModelCompatSchema.optional(),
|
|
191
191
|
contextPromotionTarget: z.string().min(1).optional(),
|
|
@@ -745,7 +745,7 @@ export const SETTINGS_SCHEMA = {
|
|
|
745
745
|
// ────────────────────────────────────────────────────────────────────────
|
|
746
746
|
"ui.language": {
|
|
747
747
|
type: "enum",
|
|
748
|
-
values: ["en", "ko"] as const,
|
|
748
|
+
values: ["en", "ko", "ja"] as const,
|
|
749
749
|
default: "en",
|
|
750
750
|
ui: {
|
|
751
751
|
tab: "appearance",
|
|
@@ -754,6 +754,7 @@ export const SETTINGS_SCHEMA = {
|
|
|
754
754
|
options: [
|
|
755
755
|
{ value: "en", label: "English" },
|
|
756
756
|
{ value: "ko", label: "Korean (한국어)" },
|
|
757
|
+
{ value: "ja", label: "Japanese (日本語)" },
|
|
757
758
|
],
|
|
758
759
|
},
|
|
759
760
|
},
|
|
@@ -1682,6 +1683,17 @@ export const SETTINGS_SCHEMA = {
|
|
|
1682
1683
|
},
|
|
1683
1684
|
},
|
|
1684
1685
|
|
|
1686
|
+
"startup.skipLogoAnimation": {
|
|
1687
|
+
type: "boolean",
|
|
1688
|
+
default: false,
|
|
1689
|
+
ui: {
|
|
1690
|
+
tab: "interaction",
|
|
1691
|
+
label: "Skip Startup Logo Animation",
|
|
1692
|
+
description:
|
|
1693
|
+
"Skip the animated startup logo sweep; the welcome surface, its resting logo, and all information rows still render. Applies at the next interactive start.",
|
|
1694
|
+
},
|
|
1695
|
+
},
|
|
1696
|
+
|
|
1685
1697
|
"startup.checkUpdate": {
|
|
1686
1698
|
type: "boolean",
|
|
1687
1699
|
default: true,
|
|
@@ -1928,6 +1940,52 @@ export const SETTINGS_SCHEMA = {
|
|
|
1928
1940
|
},
|
|
1929
1941
|
},
|
|
1930
1942
|
|
|
1943
|
+
"compaction.adaptive.enabled": {
|
|
1944
|
+
type: "boolean",
|
|
1945
|
+
default: false,
|
|
1946
|
+
ui: {
|
|
1947
|
+
tab: "context",
|
|
1948
|
+
label: "Adaptive Compaction",
|
|
1949
|
+
description: "Adjust compaction frequency by context size and call rate",
|
|
1950
|
+
},
|
|
1951
|
+
},
|
|
1952
|
+
"compaction.adaptive.baseThresholdPercent": {
|
|
1953
|
+
type: "number",
|
|
1954
|
+
default: 85,
|
|
1955
|
+
ui: {
|
|
1956
|
+
tab: "context",
|
|
1957
|
+
label: "Adaptive Base Threshold %",
|
|
1958
|
+
description: "Base context percentage used when adaptive compaction is enabled",
|
|
1959
|
+
},
|
|
1960
|
+
},
|
|
1961
|
+
"compaction.adaptive.aggression": {
|
|
1962
|
+
type: "number",
|
|
1963
|
+
default: 0.15,
|
|
1964
|
+
ui: {
|
|
1965
|
+
tab: "context",
|
|
1966
|
+
label: "Adaptive Aggression",
|
|
1967
|
+
description: "How strongly call rate lowers the compaction threshold; use 0 to 1",
|
|
1968
|
+
},
|
|
1969
|
+
},
|
|
1970
|
+
"compaction.adaptive.turnWindow": {
|
|
1971
|
+
type: "number",
|
|
1972
|
+
default: 15,
|
|
1973
|
+
ui: {
|
|
1974
|
+
tab: "context",
|
|
1975
|
+
label: "Call-Rate Window",
|
|
1976
|
+
description: "Minutes of recent calls considered by adaptive compaction",
|
|
1977
|
+
},
|
|
1978
|
+
},
|
|
1979
|
+
"compaction.adaptive.minThresholdPercent": {
|
|
1980
|
+
type: "number",
|
|
1981
|
+
default: 50,
|
|
1982
|
+
ui: {
|
|
1983
|
+
tab: "context",
|
|
1984
|
+
label: "Adaptive Floor %",
|
|
1985
|
+
description: "Lowest context percentage adaptive compaction may lower the threshold to",
|
|
1986
|
+
},
|
|
1987
|
+
},
|
|
1988
|
+
|
|
1931
1989
|
"compaction.handoffSaveToDisk": {
|
|
1932
1990
|
type: "boolean",
|
|
1933
1991
|
default: false,
|
|
@@ -4320,6 +4378,13 @@ export interface CompactionSettings {
|
|
|
4320
4378
|
strategy: "context-full" | "handoff" | "off";
|
|
4321
4379
|
thresholdPercent: number;
|
|
4322
4380
|
thresholdTokens: number;
|
|
4381
|
+
adaptive: {
|
|
4382
|
+
enabled: boolean;
|
|
4383
|
+
baseThresholdPercent: number;
|
|
4384
|
+
aggression: number;
|
|
4385
|
+
turnWindow: number;
|
|
4386
|
+
minThresholdPercent: number;
|
|
4387
|
+
};
|
|
4323
4388
|
reserveTokens: number;
|
|
4324
4389
|
keepRecentTokens: number;
|
|
4325
4390
|
handoffSaveToDisk: boolean;
|
package/src/config/settings.ts
CHANGED
|
@@ -1174,7 +1174,7 @@ export class Settings implements NotificationSettingsReader {
|
|
|
1174
1174
|
for (const key of Object.keys(SETTINGS_SCHEMA) as SettingPath[]) {
|
|
1175
1175
|
if (key.startsWith(`${prefix}.`)) {
|
|
1176
1176
|
const suffix = key.slice(prefix.length + 1);
|
|
1177
|
-
result
|
|
1177
|
+
setByPath(result, suffix.split("."), this.get(key));
|
|
1178
1178
|
}
|
|
1179
1179
|
}
|
|
1180
1180
|
return result as unknown as GroupTypeMap[G];
|
|
@@ -12,6 +12,7 @@ export const COORDINATOR_MCP_TOOL_NAMES = [
|
|
|
12
12
|
"gjc_coordinator_watch_events",
|
|
13
13
|
"gjc_coordinator_register_session",
|
|
14
14
|
"gjc_coordinator_start_session",
|
|
15
|
+
"gjc_coordinator_retire_start_session",
|
|
15
16
|
"gjc_coordinator_activate_session",
|
|
16
17
|
"gjc_coordinator_stop_session",
|
|
17
18
|
"gjc_coordinator_send_prompt",
|