feat: Ollama models command, with load/pull/delete and unload (#16)
This commit was merged in pull request #16.
This commit is contained in:
+77
-6
@@ -1,12 +1,14 @@
|
||||
import { Action, ActionPanel, Alert, Icon, List, confirmAlert, openExtensionPreferences } from "@vicinae/api";
|
||||
import { useCallback, useEffect, useMemo, useState, type ReactNode } from "react";
|
||||
import { Action, ActionPanel, Alert, Icon, List, Toast, confirmAlert, openExtensionPreferences, showToast } from "@vicinae/api";
|
||||
import { useCallback, useEffect, useState, type ReactNode } from "react";
|
||||
import { clearAllChats, clearOrphanedSnips, runAutoDelete } from "./lib/cleanup";
|
||||
import { usePreferences } from "./lib/hooks/usePreferences";
|
||||
import {
|
||||
clearModelSelection,
|
||||
describeAutoDelete,
|
||||
describeMaxToolRounds,
|
||||
describeResumeTimeout,
|
||||
getLamPreferences,
|
||||
needsSetup,
|
||||
type ResolvedPreferences,
|
||||
} from "./lib/preferences";
|
||||
import { listModels } from "./lib/ollama";
|
||||
import { forgetGeoPlace } from "./lib/geo";
|
||||
@@ -40,7 +42,29 @@ function maskKey(apiKey: string): string {
|
||||
}
|
||||
|
||||
export default function SetupCommand() {
|
||||
const preferences = useMemo(() => getLamPreferences(), []);
|
||||
const { preferences, reload } = usePreferences();
|
||||
|
||||
// The screen does nothing until the model is known, because half of what it
|
||||
// reports is about that model: whether it can see images, and whether it is the
|
||||
// one from preferences or from the Models command. Rendering it with the
|
||||
// preference value and correcting it a moment later would flash a wrong answer
|
||||
// at the user.
|
||||
if (!preferences) {
|
||||
return (
|
||||
<List isLoading navigationTitle="Lam Agent Setup" searchBarPlaceholder="Loading preferences…" />
|
||||
);
|
||||
}
|
||||
|
||||
return <SetupScreen preferences={preferences} reloadPreferences={reload} />;
|
||||
}
|
||||
|
||||
interface SetupScreenProps {
|
||||
preferences: ResolvedPreferences;
|
||||
/** Re-reads preferences after this screen changes the model selection. */
|
||||
reloadPreferences: () => void;
|
||||
}
|
||||
|
||||
function SetupScreen({ preferences, reloadPreferences }: SetupScreenProps) {
|
||||
const [models, setModels] = useState<ModelInfo[]>([]);
|
||||
const [error, setError] = useState<string | undefined>(undefined);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@@ -98,6 +122,25 @@ export default function SetupCommand() {
|
||||
void openExtensionPreferences();
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Hands the model back to the `Model` preference.
|
||||
*
|
||||
* The escape hatch for the one cost of keeping a selection: while one is set,
|
||||
* editing the preference has no effect, and the only way to notice is this
|
||||
* screen. Confirmed rather than immediate because it is a change the user
|
||||
* cannot see the result of until the next question they ask.
|
||||
*/
|
||||
const resetModel = useCallback(async () => {
|
||||
await clearModelSelection();
|
||||
reloadPreferences();
|
||||
|
||||
await showToast({
|
||||
style: Toast.Style.Success,
|
||||
title: "Model reset to the preference",
|
||||
message: preferences.preferenceModel,
|
||||
});
|
||||
}, [reloadPreferences, preferences.preferenceModel]);
|
||||
|
||||
/**
|
||||
* Confirms, then runs a destructive tidy-up.
|
||||
*
|
||||
@@ -191,8 +234,36 @@ export default function SetupCommand() {
|
||||
<List.Item
|
||||
icon={Icon.Stars}
|
||||
title="Model"
|
||||
subtitle={preferences.model}
|
||||
actions={settingsActions}
|
||||
subtitle={
|
||||
preferences.modelSource === "selection"
|
||||
? `${preferences.model} (chosen in Models; the preference says ${preferences.preferenceModel})`
|
||||
: preferences.model
|
||||
}
|
||||
actions={
|
||||
preferences.modelSource === "selection" ? (
|
||||
<ActionPanel>
|
||||
<Action
|
||||
title="Reset to the Preference"
|
||||
icon={Icon.ArrowCounterClockwise}
|
||||
onAction={() => void resetModel()}
|
||||
/>
|
||||
<ActionPanel.Section>
|
||||
<Action
|
||||
title="Open Extension Preferences"
|
||||
icon={Icon.BulletPoints}
|
||||
onAction={openPreferences}
|
||||
/>
|
||||
<Action
|
||||
title="Test Connection"
|
||||
icon={Icon.ArrowClockwise}
|
||||
onAction={() => void testConnection()}
|
||||
/>
|
||||
</ActionPanel.Section>
|
||||
</ActionPanel>
|
||||
) : (
|
||||
settingsActions
|
||||
)
|
||||
}
|
||||
/>
|
||||
<List.Item
|
||||
icon={Icon.BulletPoints}
|
||||
|
||||
Reference in New Issue
Block a user