Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
82 lines
2.5 KiB
TypeScript
82 lines
2.5 KiB
TypeScript
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
import {
|
|
fetchProviderModelCatalog,
|
|
providerModelCacheKey,
|
|
readCachedProviderModelCatalog,
|
|
seedProviderModelCatalog,
|
|
} from '../../infrastructure/ai/cattyProviderModels';
|
|
import type { ComposerPickerModel } from '../../infrastructure/ai/composerPicker';
|
|
import type { ProviderConfig } from '../../infrastructure/ai/types';
|
|
import { getFetchBridge } from '../settings/tabs/ai/types';
|
|
|
|
export interface ProviderModelCatalog {
|
|
models: ComposerPickerModel[];
|
|
fetched: boolean;
|
|
loading: boolean;
|
|
error?: string;
|
|
}
|
|
|
|
export function useProviderModelCatalog(
|
|
provider: ProviderConfig | undefined,
|
|
enabled: boolean,
|
|
): ProviderModelCatalog {
|
|
const cacheKey = provider && enabled ? providerModelCacheKey(provider) : '';
|
|
const providerRef = useRef(provider);
|
|
providerRef.current = provider;
|
|
const seed = useMemo(
|
|
() => {
|
|
if (!cacheKey) return { models: [], fetched: false };
|
|
const current = providerRef.current;
|
|
return current ? seedProviderModelCatalog(current) : { models: [], fetched: false };
|
|
},
|
|
[cacheKey],
|
|
);
|
|
const [catalog, setCatalog] = useState<Omit<ProviderModelCatalog, 'loading'>>(() => {
|
|
const current = providerRef.current;
|
|
const hit = current && enabled ? readCachedProviderModelCatalog(current) : null;
|
|
return hit ? { models: hit, fetched: true } : seed;
|
|
});
|
|
const [loading, setLoading] = useState(() => {
|
|
const current = providerRef.current;
|
|
return Boolean(enabled && current && !readCachedProviderModelCatalog(current));
|
|
});
|
|
|
|
useEffect(() => {
|
|
const current = providerRef.current;
|
|
if (!enabled || !current) {
|
|
setCatalog({ models: [], fetched: false });
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
|
|
const hit = readCachedProviderModelCatalog(current);
|
|
if (hit) {
|
|
setCatalog((prev) => (
|
|
prev.fetched && prev.models === hit ? prev : { models: hit, fetched: true }
|
|
));
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
|
|
let cancelled = false;
|
|
setCatalog(seedProviderModelCatalog(current));
|
|
setLoading(true);
|
|
void fetchProviderModelCatalog(current, getFetchBridge()).then((next) => {
|
|
if (cancelled) return;
|
|
setCatalog(next);
|
|
setLoading(false);
|
|
});
|
|
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [cacheKey, enabled]);
|
|
|
|
return {
|
|
models: catalog.models.length > 0 ? catalog.models : seed.models,
|
|
fetched: catalog.fetched,
|
|
loading,
|
|
error: catalog.error,
|
|
};
|
|
}
|