@gajae-code/coding-agent 0.16.1 → 0.16.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 +70 -0
- package/dist/types/cli/args.d.ts +2 -2
- package/dist/types/cli/root-flags.d.ts +4 -2
- package/dist/types/cli.d.ts +1 -1
- package/dist/types/commands/launch.d.ts +1 -1
- package/dist/types/config/autorouting-tier-map.d.ts +3 -0
- package/dist/types/config/model-registry.d.ts +4 -0
- package/dist/types/config/model-resolver.d.ts +9 -0
- package/dist/types/config/settings-schema.d.ts +29 -1
- package/dist/types/discovery/claude-plugins.d.ts +3 -1
- package/dist/types/discovery/helpers.d.ts +2 -0
- package/dist/types/extensibility/gjc-plugins/mcp-policy.d.ts +16 -0
- package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -0
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +1 -1
- package/dist/types/extensibility/shared-events.d.ts +1 -1
- package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
- package/dist/types/modes/components/assistant-message.d.ts +1 -2
- package/dist/types/modes/components/settings-selector.d.ts +6 -1
- package/dist/types/modes/components/status-line/command.d.ts +35 -0
- package/dist/types/modes/components/status-line/index.d.ts +1 -0
- package/dist/types/modes/components/status-line/types.d.ts +5 -0
- package/dist/types/modes/components/tool-status-header.d.ts +14 -0
- package/dist/types/modes/controllers/event-controller.d.ts +6 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/types.d.ts +1 -0
- package/dist/types/runtime-mcp/client.d.ts +9 -1
- package/dist/types/runtime-mcp/manager.d.ts +7 -1
- package/dist/types/runtime-mcp/pool.d.ts +22 -3
- package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -4
- package/dist/types/runtime-mcp/types.d.ts +22 -0
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +12 -0
- package/dist/types/sdk/bus/slack-live-provider.d.ts +6 -0
- package/dist/types/sdk/bus/slack-provider.d.ts +12 -0
- package/dist/types/sdk/cli/rows.d.ts +7 -0
- package/dist/types/sdk/host/events.d.ts +1 -0
- package/dist/types/sdk/host/host.d.ts +2 -0
- package/dist/types/sdk/host/session-runtime.d.ts +23 -0
- package/dist/types/sdk/session-api-key.d.ts +26 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +9 -0
- package/dist/types/setup/paseo/announce.d.ts +111 -0
- package/dist/types/setup/paseo/setup-deps.d.ts +2 -1
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +2 -1
- package/dist/types/tools/fetch.d.ts +7 -0
- package/dist/types/tools/index.d.ts +8 -2
- package/dist/types/tools/path-utils.d.ts +2 -0
- package/dist/types/tools/search.d.ts +6 -0
- package/dist/types/utils/external-editor.d.ts +5 -0
- package/package.json +7 -7
- package/scripts/capture-status-line-custom-editor-showcase.ts +151 -0
- package/scripts/generate-sdk-operation-inventory.ts +9 -0
- package/scripts/verify-status-line-custom-editor-showcase.ts +309 -0
- package/src/cli/args.ts +20 -9
- package/src/cli/root-flags.ts +5 -3
- package/src/config/autorouting-tier-map.ts +1 -0
- package/src/config/file-lock.ts +181 -17
- package/src/config/model-preset-registry.ts +5 -3
- package/src/config/model-profiles.ts +40 -0
- package/src/config/model-registry.ts +57 -11
- package/src/config/model-resolver.ts +48 -0
- package/src/config/settings-schema.ts +33 -1
- package/src/config/settings.ts +1 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +11 -11
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +13 -2
- package/src/discovery/builtin.ts +13 -4
- package/src/discovery/claude-plugins.ts +12 -4
- package/src/discovery/helpers.ts +10 -2
- package/src/extensibility/gjc-plugins/compiler.ts +208 -58
- package/src/extensibility/gjc-plugins/installer.ts +13 -12
- package/src/extensibility/gjc-plugins/mcp-policy.ts +81 -52
- package/src/extensibility/gjc-plugins/paths.ts +13 -0
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +758 -16
- package/src/extensibility/runtime-skill-discovery.ts +77 -151
- package/src/extensibility/shared-events.ts +1 -1
- package/src/extensibility/skills.ts +44 -16
- package/src/gjc-runtime/repository-binding.ts +1 -1
- package/src/gjc-runtime/session-state-lock.ts +94 -6
- package/src/internal-urls/docs-index.generated.ts +10 -10
- package/src/main.ts +72 -34
- package/src/modes/DESIGN.md +54 -0
- package/src/modes/acp/acp-agent.ts +29 -14
- package/src/modes/components/assistant-message.ts +22 -9
- package/src/modes/components/model-selector.ts +166 -33
- package/src/modes/components/settings-selector.ts +1075 -235
- package/src/modes/components/status-line/command.ts +190 -0
- package/src/modes/components/status-line/index.ts +1 -0
- package/src/modes/components/status-line/segments.ts +32 -5
- package/src/modes/components/status-line/types.ts +5 -0
- package/src/modes/components/tool-status-header.ts +393 -21
- package/src/modes/controllers/command-controller.ts +2 -0
- package/src/modes/controllers/event-controller.ts +148 -5
- package/src/modes/controllers/selector-controller.ts +21 -0
- package/src/modes/interactive-mode.ts +47 -1
- package/src/modes/types.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +1 -0
- package/src/prompts/system/system-prompt.md +8 -0
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/job.md +1 -1
- package/src/prompts/tools/search.md +2 -0
- package/src/runtime-mcp/client.ts +60 -17
- package/src/runtime-mcp/manager.ts +171 -14
- package/src/runtime-mcp/pool.test.ts +209 -0
- package/src/runtime-mcp/pool.ts +224 -23
- package/src/runtime-mcp/transports/stdio.ts +158 -24
- package/src/runtime-mcp/types.ts +24 -0
- package/src/sdk/acp/adapter.ts +1 -1
- package/src/sdk/broker/broker.ts +5 -4
- package/src/sdk/bus/chat-daemon-control.ts +1 -1
- package/src/sdk/bus/chat-daemon-runtime.ts +44 -1
- package/src/sdk/bus/slack-daemon.ts +92 -2
- package/src/sdk/bus/slack-live-provider.ts +12 -0
- package/src/sdk/bus/slack-provider.ts +5 -0
- package/src/sdk/cli/rows.ts +47 -2
- package/src/sdk/cli/session-cli.ts +47 -23
- package/src/sdk/host/events.ts +25 -2
- package/src/sdk/host/host.ts +4 -1
- package/src/sdk/host/session-runtime.test.ts +36 -25
- package/src/sdk/host/session-runtime.ts +279 -43
- package/src/sdk/protocol/operation-inventory.generated.json +66 -0
- package/src/sdk/router/session-router.ts +60 -37
- package/src/sdk/session-api-key.ts +94 -0
- package/src/sdk/session.ts +73 -30
- package/src/sdk/transport/serve-cli.ts +3 -3
- package/src/session/agent-session.ts +123 -38
- package/src/session/contribution-prep.ts +214 -21
- package/src/setup/paseo/announce.ts +450 -0
- package/src/setup/paseo/setup-deps.ts +15 -3
- package/src/slash-commands/builtin-registry.ts +1 -0
- package/src/system-prompt.ts +4 -0
- package/src/task/executor.ts +2 -1
- package/src/task/index.ts +17 -4
- package/src/tools/bash.ts +50 -21
- package/src/tools/cron.ts +1 -1
- package/src/tools/fetch.ts +29 -1
- package/src/tools/index.ts +8 -2
- package/src/tools/job.ts +8 -2
- package/src/tools/monitor.ts +8 -2
- package/src/tools/path-utils.ts +7 -0
- package/src/tools/search.ts +116 -58
- package/src/tools/skill.ts +22 -2
- package/src/tools/subagent.ts +3 -1
- package/src/tools/tool-catalog.generated.ts +9 -2
- package/src/utils/external-editor.ts +16 -2
- package/src/web/insane/bridge.ts +113 -23
- package/src/web/search/providers/perplexity.ts +102 -41
|
@@ -410,6 +410,10 @@ export class ModelSelectorComponent extends Container {
|
|
|
410
410
|
#unsubscribeProviderOrderChanged: () => void = () => {};
|
|
411
411
|
#unsubscribeAuthGeneration: () => void = () => {};
|
|
412
412
|
#disposed = false;
|
|
413
|
+
#catalogLoaded = false;
|
|
414
|
+
#catalogLoadPromise?: Promise<void>;
|
|
415
|
+
#presetCatalogRefreshPending = false;
|
|
416
|
+
#openSmartRoutingAfterPresetRefresh = false;
|
|
413
417
|
/** Standalone smart-routing entry: cancel closes the selector instead of falling back to the preset landing. */
|
|
414
418
|
#smartRoutingOnly = false;
|
|
415
419
|
|
|
@@ -422,6 +426,8 @@ export class ModelSelectorComponent extends Container {
|
|
|
422
426
|
#presetScopeIndex: number = 0;
|
|
423
427
|
#providerAuthById = new Map<string, boolean>();
|
|
424
428
|
#bareProfileAuthByName = new Map<string, boolean>();
|
|
429
|
+
// Rebuilt with the provider and bare-selector snapshots on every catalog or credential refresh.
|
|
430
|
+
#profileAuthByName = new Map<string, boolean>();
|
|
425
431
|
#providerAuthPending: boolean = false;
|
|
426
432
|
#providerAuthRefreshGeneration = 0;
|
|
427
433
|
#presetLoginHint?: string;
|
|
@@ -545,21 +551,39 @@ export class ModelSelectorComponent extends Container {
|
|
|
545
551
|
this.#unsubscribeCatalogChanged = this.#modelRegistry.onCatalogChanged(() => {
|
|
546
552
|
if (this.#disposed) return;
|
|
547
553
|
if (this.#viewMode === "presets") {
|
|
548
|
-
this.#
|
|
554
|
+
if (this.#presetCatalogRefreshPending) return;
|
|
555
|
+
this.#rebuildRoleModels();
|
|
549
556
|
this.#clampPresetCursor();
|
|
550
557
|
void this.#refreshProviderAuth();
|
|
551
558
|
this.#renderPresetLanding();
|
|
552
559
|
this.#tui.requestRender();
|
|
553
560
|
return;
|
|
554
561
|
}
|
|
562
|
+
if (this.#viewMode === "smart-routing" && this.#smartRoutingPanel) return;
|
|
563
|
+
// The in-flight load already consumes the latest registry snapshot. Avoid
|
|
564
|
+
// materializing the same catalog again from its own change notification.
|
|
565
|
+
if (this.#catalogLoadPromise) return;
|
|
566
|
+
if (!this.#catalogLoaded) {
|
|
567
|
+
void this.#initializeCatalogView();
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
555
570
|
if (this.#refreshCatalogView()) this.#tui.requestRender();
|
|
556
571
|
});
|
|
557
572
|
}
|
|
558
573
|
|
|
559
|
-
//
|
|
560
|
-
//
|
|
574
|
+
// Proxy and provider-policy changes invalidate preset availability. Provider-order changes are
|
|
575
|
+
// advisory only while smart routing is mounted and must not discard its draft.
|
|
561
576
|
this.#unsubscribeProviderOrderChanged = this.#settings.onChanged?.(path => {
|
|
562
|
-
if (this.#disposed
|
|
577
|
+
if (this.#disposed) return;
|
|
578
|
+
if (
|
|
579
|
+
path === "modelProfile.proxyProvider" ||
|
|
580
|
+
path === "modelProfile.proxyMode" ||
|
|
581
|
+
path === "disabledProviders"
|
|
582
|
+
) {
|
|
583
|
+
if (this.#viewMode === "presets") void this.#refreshProviderAuth();
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
if (path !== "modelProviderOrder") return;
|
|
563
587
|
if (this.#viewMode !== "smart-routing") return;
|
|
564
588
|
const panel = this.#smartRoutingPanel;
|
|
565
589
|
if (!panel) return;
|
|
@@ -572,34 +596,21 @@ export class ModelSelectorComponent extends Container {
|
|
|
572
596
|
void this.#refreshProviderAuth();
|
|
573
597
|
}) ?? (() => {});
|
|
574
598
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
if (this.#viewMode === "presets" && (this.#modelRegistry.getModelProfiles?.().size ?? 0) === 0) {
|
|
584
|
-
this.#viewMode = "models";
|
|
585
|
-
}
|
|
586
|
-
if (this.#viewMode === "presets") {
|
|
587
|
-
void this.#refreshProviderAuth();
|
|
599
|
+
if (this.#viewMode === "presets") {
|
|
600
|
+
// The landing only needs profile definitions and provider authentication.
|
|
601
|
+
// Refresh static configuration without enumerating and canonicalizing the
|
|
602
|
+
// full browser catalog, then resolve preset authentication once.
|
|
603
|
+
this.#presetCatalogRefreshPending = true;
|
|
604
|
+
if ((this.#modelRegistry.getModelProfiles?.().size ?? 0) > 0) {
|
|
588
605
|
this.#renderPresetLanding();
|
|
589
606
|
} else {
|
|
590
|
-
this.#
|
|
591
|
-
// Always apply the current search query — the user may have typed
|
|
592
|
-
// while models were loading asynchronously.
|
|
593
|
-
const currentQuery = this.#searchInput.getValue();
|
|
594
|
-
if (currentQuery) {
|
|
595
|
-
this.#filterModels(currentQuery);
|
|
596
|
-
} else {
|
|
597
|
-
this.#updateList();
|
|
598
|
-
}
|
|
607
|
+
this.#listContainer.addChild(new Text(theme.fg("muted", "Loading model presets..."), 0, 0));
|
|
599
608
|
}
|
|
600
|
-
// Request re-render after models are loaded
|
|
601
609
|
this.#tui.requestRender();
|
|
602
|
-
|
|
610
|
+
void this.#initializePresetLanding();
|
|
611
|
+
} else {
|
|
612
|
+
void this.#initializeCatalogView();
|
|
613
|
+
}
|
|
603
614
|
}
|
|
604
615
|
|
|
605
616
|
override dispose(): void {
|
|
@@ -1332,6 +1343,10 @@ export class ModelSelectorComponent extends Container {
|
|
|
1332
1343
|
return this.#modelRegistry.getModelProfile?.(name) ?? this.#modelRegistry.getModelProfiles?.().get(name);
|
|
1333
1344
|
}
|
|
1334
1345
|
|
|
1346
|
+
#isPresetAvailabilityPending(): boolean {
|
|
1347
|
+
return this.#presetCatalogRefreshPending || this.#providerAuthPending;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1335
1350
|
#isProviderAuthenticated(providerId: string): boolean | undefined {
|
|
1336
1351
|
return this.#providerAuthById.get(providerId);
|
|
1337
1352
|
}
|
|
@@ -1405,9 +1420,13 @@ export class ModelSelectorComponent extends Container {
|
|
|
1405
1420
|
return [...missing].sort((a, b) => a.localeCompare(b));
|
|
1406
1421
|
}
|
|
1407
1422
|
|
|
1408
|
-
#isPresetAuthenticated(
|
|
1423
|
+
#isPresetAuthenticated(
|
|
1424
|
+
profileOrProfiles: ModelProfileDefinition | ModelProfileDefinition[],
|
|
1425
|
+
computeCurrent = false,
|
|
1426
|
+
): boolean {
|
|
1409
1427
|
const profiles = Array.isArray(profileOrProfiles) ? profileOrProfiles : [profileOrProfiles];
|
|
1410
1428
|
return profiles.every(profile => {
|
|
1429
|
+
if (!computeCurrent) return this.#profileAuthByName.get(profile.name) === true;
|
|
1411
1430
|
if (profile.source !== "user") {
|
|
1412
1431
|
if (inspectProxyProviderId(this.#settings).status === "invalid") return false;
|
|
1413
1432
|
const proxyProvider = tryResolveProxyProviderId(this.#settings);
|
|
@@ -1503,6 +1522,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
1503
1522
|
const refreshGeneration = ++this.#providerAuthRefreshGeneration;
|
|
1504
1523
|
this.#providerAuthById = new Map();
|
|
1505
1524
|
this.#bareProfileAuthByName = new Map();
|
|
1525
|
+
this.#profileAuthByName = new Map();
|
|
1506
1526
|
const availableModels = this.#getProfileAvailableModels();
|
|
1507
1527
|
const resolutionRegistry = this.#createProfileResolutionRegistry(availableModels);
|
|
1508
1528
|
const providers = new Set<string>();
|
|
@@ -1612,6 +1632,11 @@ export class ModelSelectorComponent extends Container {
|
|
|
1612
1632
|
)
|
|
1613
1633
|
return;
|
|
1614
1634
|
this.#bareProfileAuthByName = new Map(profileAuthEntries);
|
|
1635
|
+
this.#profileAuthByName = new Map(
|
|
1636
|
+
[...this.#getPresetGroups().values()]
|
|
1637
|
+
.flat()
|
|
1638
|
+
.map(profile => [profile.name, this.#isPresetAuthenticated(profile, true)]),
|
|
1639
|
+
);
|
|
1615
1640
|
} finally {
|
|
1616
1641
|
if (
|
|
1617
1642
|
!this.#disposed &&
|
|
@@ -1684,6 +1709,39 @@ export class ModelSelectorComponent extends Container {
|
|
|
1684
1709
|
this.#searchInput.setValue(value);
|
|
1685
1710
|
}
|
|
1686
1711
|
|
|
1712
|
+
async #initializePresetLanding(): Promise<void> {
|
|
1713
|
+
this.#presetCatalogRefreshPending = true;
|
|
1714
|
+
let refreshFailed = false;
|
|
1715
|
+
try {
|
|
1716
|
+
const refreshStatic = this.#modelRegistry.refreshStatic;
|
|
1717
|
+
if (typeof refreshStatic === "function") await refreshStatic.call(this.#modelRegistry);
|
|
1718
|
+
this.#errorMessage = this.#modelRegistry.getError();
|
|
1719
|
+
} catch (error) {
|
|
1720
|
+
refreshFailed = true;
|
|
1721
|
+
this.#errorMessage = error instanceof Error ? error.message : String(error);
|
|
1722
|
+
} finally {
|
|
1723
|
+
this.#presetCatalogRefreshPending = false;
|
|
1724
|
+
}
|
|
1725
|
+
if (this.#disposed || this.#viewMode !== "presets") return;
|
|
1726
|
+
if ((this.#modelRegistry.getModelProfiles?.().size ?? 0) === 0) {
|
|
1727
|
+
this.#viewMode = "models";
|
|
1728
|
+
void this.#initializeCatalogView();
|
|
1729
|
+
return;
|
|
1730
|
+
}
|
|
1731
|
+
this.#rebuildRoleModels();
|
|
1732
|
+
this.#clampPresetCursor();
|
|
1733
|
+
if (this.#openSmartRoutingAfterPresetRefresh) {
|
|
1734
|
+
this.#openSmartRoutingAfterPresetRefresh = false;
|
|
1735
|
+
if (!refreshFailed) {
|
|
1736
|
+
this.#enterSmartRoutingMode();
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
void this.#refreshProviderAuth();
|
|
1741
|
+
this.#renderPresetLanding();
|
|
1742
|
+
this.#tui.requestRender();
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1687
1745
|
#switchToModelMode(seed?: string, options?: { imageRoleFilter?: boolean }): void {
|
|
1688
1746
|
this.#viewMode = "models";
|
|
1689
1747
|
this.#expandedPresetProviderId = undefined;
|
|
@@ -1695,8 +1753,52 @@ export class ModelSelectorComponent extends Container {
|
|
|
1695
1753
|
this.#selectedIndex = 0;
|
|
1696
1754
|
this.#imageRoleFilter = options?.imageRoleFilter ?? false;
|
|
1697
1755
|
this.#setSearchInputValue(seed ?? this.#searchInput.getValue());
|
|
1756
|
+
void this.#initializeCatalogView();
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
async #initializeCatalogView(): Promise<void> {
|
|
1760
|
+
if (this.#catalogLoaded) {
|
|
1761
|
+
this.#presentCatalogView();
|
|
1762
|
+
return;
|
|
1763
|
+
}
|
|
1764
|
+
if (this.#catalogLoadPromise) return this.#catalogLoadPromise;
|
|
1765
|
+
|
|
1766
|
+
this.#headerContainer.clear();
|
|
1767
|
+
this.#listContainer.clear();
|
|
1768
|
+
this.#listContainer.addChild(new Text(theme.fg("muted", "Loading models..."), 0, 0));
|
|
1769
|
+
this.#tui.requestRender();
|
|
1770
|
+
|
|
1771
|
+
const load = this.#loadModels().then(() => {
|
|
1772
|
+
this.#catalogLoaded = true;
|
|
1773
|
+
if (this.#disposed) return;
|
|
1774
|
+
if (this.#smartRoutingOnly) {
|
|
1775
|
+
this.#enterSmartRoutingMode();
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
if (this.#viewMode === "models") this.#presentCatalogView();
|
|
1779
|
+
});
|
|
1780
|
+
this.#catalogLoadPromise = load;
|
|
1781
|
+
try {
|
|
1782
|
+
await load;
|
|
1783
|
+
} catch (error) {
|
|
1784
|
+
if (!this.#disposed && (this.#viewMode === "models" || this.#viewMode === "smart-routing")) {
|
|
1785
|
+
this.#errorMessage = error instanceof Error ? error.message : String(error);
|
|
1786
|
+
this.#buildProviderTabs();
|
|
1787
|
+
this.#updateTabBar();
|
|
1788
|
+
this.#updateList();
|
|
1789
|
+
this.#tui.requestRender();
|
|
1790
|
+
}
|
|
1791
|
+
} finally {
|
|
1792
|
+
if (this.#catalogLoadPromise === load) this.#catalogLoadPromise = undefined;
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
#presentCatalogView(): void {
|
|
1797
|
+
this.#buildProviderTabs();
|
|
1698
1798
|
this.#updateTabBar();
|
|
1799
|
+
// Apply the latest query: input remains responsive while the catalog loads.
|
|
1699
1800
|
this.#filterModels(this.#searchInput.getValue());
|
|
1801
|
+
this.#tui.requestRender();
|
|
1700
1802
|
}
|
|
1701
1803
|
|
|
1702
1804
|
/**
|
|
@@ -1880,6 +1982,12 @@ export class ModelSelectorComponent extends Container {
|
|
|
1880
1982
|
for (const line of this.#formatCurrentSessionLines()) {
|
|
1881
1983
|
this.#headerContainer.addChild(new Text(line, 0, 0));
|
|
1882
1984
|
}
|
|
1985
|
+
if (this.#errorMessage) {
|
|
1986
|
+
for (const line of String(this.#errorMessage).split("\n")) {
|
|
1987
|
+
this.#listContainer.addChild(new Text(theme.fg("error", line), 0, 0));
|
|
1988
|
+
}
|
|
1989
|
+
this.#listContainer.addChild(new Spacer(1));
|
|
1990
|
+
}
|
|
1883
1991
|
const rows = this.#getPresetRows();
|
|
1884
1992
|
for (let i = 0; i < rows.length; i++) {
|
|
1885
1993
|
const row = rows[i];
|
|
@@ -1926,7 +2034,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
1926
2034
|
}
|
|
1927
2035
|
if (row.kind === "group") {
|
|
1928
2036
|
const authenticated = this.#isPresetGroupUsable(row.profiles);
|
|
1929
|
-
const mark = this.#
|
|
2037
|
+
const mark = this.#isPresetAvailabilityPending() ? "…" : authenticated ? "✓" : "✗";
|
|
1930
2038
|
const containsActive =
|
|
1931
2039
|
this.#activeModelProfile !== undefined &&
|
|
1932
2040
|
row.profiles.some(profile => profile.name === this.#activeModelProfile);
|
|
@@ -1938,7 +2046,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
1938
2046
|
}
|
|
1939
2047
|
const presentation = getModelProfilePresentation(row.profile);
|
|
1940
2048
|
const authenticated = this.#isPresetAuthenticated(row.profile);
|
|
1941
|
-
const mark = this.#
|
|
2049
|
+
const mark = this.#isPresetAvailabilityPending() ? "…" : authenticated ? "✓" : "✗";
|
|
1942
2050
|
const isActive = row.profile.name === this.#activeModelProfile;
|
|
1943
2051
|
const label = ` ${mark} ${presentation.displayName}`;
|
|
1944
2052
|
const renderedLabel = selected ? theme.fg("accent", label) : authenticated ? label : theme.fg("dim", label);
|
|
@@ -2305,7 +2413,11 @@ export class ModelSelectorComponent extends Container {
|
|
|
2305
2413
|
|
|
2306
2414
|
handleInput(keyData: string): void {
|
|
2307
2415
|
if (this.#viewMode === "smart-routing") {
|
|
2308
|
-
this.#smartRoutingPanel
|
|
2416
|
+
if (this.#smartRoutingPanel) {
|
|
2417
|
+
this.#smartRoutingPanel.handleInput(keyData);
|
|
2418
|
+
} else if (getKeybindings().matches(keyData, "tui.select.cancel")) {
|
|
2419
|
+
this.#onCancelCallback();
|
|
2420
|
+
}
|
|
2309
2421
|
return;
|
|
2310
2422
|
}
|
|
2311
2423
|
if (this.#assignmentState === "assigning") {
|
|
@@ -2477,6 +2589,11 @@ export class ModelSelectorComponent extends Container {
|
|
|
2477
2589
|
this.#onSelectCallback({ kind: "deleteProfile", profileName: this.#previewProfileName });
|
|
2478
2590
|
return;
|
|
2479
2591
|
}
|
|
2592
|
+
if (this.#isPresetAvailabilityPending()) {
|
|
2593
|
+
this.#presetLoginHint = "Refreshing preset availability...";
|
|
2594
|
+
this.#renderPresetLanding();
|
|
2595
|
+
return;
|
|
2596
|
+
}
|
|
2480
2597
|
const missing = this.#getMissingProviders(profile);
|
|
2481
2598
|
if (missing.length > 0) {
|
|
2482
2599
|
this.#presetLoginHint = `Run ${missing.map(provider => `/login ${provider}`).join(", ")}`;
|
|
@@ -2504,6 +2621,12 @@ export class ModelSelectorComponent extends Container {
|
|
|
2504
2621
|
const row = this.#getSelectedPresetRow();
|
|
2505
2622
|
if (!row) return;
|
|
2506
2623
|
if (row.kind === "smartRouting") {
|
|
2624
|
+
if (this.#presetCatalogRefreshPending) {
|
|
2625
|
+
this.#openSmartRoutingAfterPresetRefresh = true;
|
|
2626
|
+
this.#presetLoginHint = "Refreshing model configuration...";
|
|
2627
|
+
this.#renderPresetLanding();
|
|
2628
|
+
return;
|
|
2629
|
+
}
|
|
2507
2630
|
this.#enterSmartRoutingMode();
|
|
2508
2631
|
return;
|
|
2509
2632
|
}
|
|
@@ -2523,6 +2646,11 @@ export class ModelSelectorComponent extends Container {
|
|
|
2523
2646
|
return;
|
|
2524
2647
|
}
|
|
2525
2648
|
if (row.kind === "group") {
|
|
2649
|
+
if (this.#isPresetAvailabilityPending()) {
|
|
2650
|
+
this.#presetLoginHint = "Refreshing preset availability...";
|
|
2651
|
+
this.#renderPresetLanding();
|
|
2652
|
+
return;
|
|
2653
|
+
}
|
|
2526
2654
|
// A group is a list of alternative presets; only surface a login hint
|
|
2527
2655
|
// when none of its members are usable. A partially-usable group stays
|
|
2528
2656
|
// navigable so the user can drill in and pick a usable member.
|
|
@@ -2546,6 +2674,11 @@ export class ModelSelectorComponent extends Container {
|
|
|
2546
2674
|
this.#renderPresetLanding();
|
|
2547
2675
|
return;
|
|
2548
2676
|
}
|
|
2677
|
+
if (this.#isPresetAvailabilityPending() && !isCustomUserProfile(row.profile)) {
|
|
2678
|
+
this.#presetLoginHint = "Refreshing preset availability...";
|
|
2679
|
+
this.#renderPresetLanding();
|
|
2680
|
+
return;
|
|
2681
|
+
}
|
|
2549
2682
|
const missing = this.#getMissingProviders(row.profile);
|
|
2550
2683
|
if (missing.length > 0 && !isCustomUserProfile(row.profile)) {
|
|
2551
2684
|
this.#presetLoginHint = `Run ${missing.map(provider => `/login ${provider}`).join(", ")}`;
|
|
@@ -2583,7 +2716,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
2583
2716
|
this.#presetLoginHint = undefined;
|
|
2584
2717
|
this.#clampPresetCursor();
|
|
2585
2718
|
}
|
|
2586
|
-
this.#
|
|
2719
|
+
void this.#refreshProviderAuth();
|
|
2587
2720
|
this.#tui.requestRender();
|
|
2588
2721
|
}
|
|
2589
2722
|
|