feat: Ollama models command, with load/pull/delete and unload (#16)
This commit was merged in pull request #16.
This commit is contained in:
@@ -3,9 +3,10 @@ import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { readAttachment } from "../attachments";
|
||||
import { runAutoDelete } from "../cleanup";
|
||||
import { useChat, type ToolActivity } from "../hooks/useChat";
|
||||
import { usePreferences } from "../hooks/usePreferences";
|
||||
import { useVisionSupport } from "../hooks/useVision";
|
||||
import { buildThreadMarkdown, renderAttachments, type TranscriptOptions } from "../markdown";
|
||||
import { getLamPreferences } from "../preferences";
|
||||
import type { ResolvedPreferences } from "../preferences";
|
||||
import { deleteSession, listSessions, loadSession, summarizeSession } from "../sessions";
|
||||
import { resolveStartup } from "../startup";
|
||||
import { buildThread } from "../thread";
|
||||
@@ -94,17 +95,49 @@ interface SessionRow {
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
export function ChatView({
|
||||
/** Shown while the conversation and the preferences are still being read. */
|
||||
function LoadingChat() {
|
||||
return <List isLoading navigationTitle="Lam" searchBarPlaceholder="Loading conversations…" />;
|
||||
}
|
||||
|
||||
/**
|
||||
* The chat surface, once its preferences are known.
|
||||
*
|
||||
* Split in two so that {@link ChatView} can wait for the model before the state
|
||||
* machine starts. `useChat` is created with the preferences it will use, so
|
||||
* handing it preferences that are still loading would pin the conversation to
|
||||
* whatever the preference said before the selection arrived.
|
||||
*
|
||||
* The outer half does nothing but that wait, and the loading state costs one
|
||||
* LocalStorage read, which is a few milliseconds while the user is still moving
|
||||
* their hands towards the keyboard.
|
||||
*/
|
||||
export function ChatView(props: ChatViewProps) {
|
||||
const { preferences } = usePreferences();
|
||||
|
||||
if (!preferences) return <LoadingChat />;
|
||||
return <ChatSession {...props} preferences={preferences} />;
|
||||
}
|
||||
|
||||
interface ChatSessionProps extends ChatViewProps {
|
||||
preferences: ResolvedPreferences;
|
||||
}
|
||||
|
||||
function ChatSession({
|
||||
preferences,
|
||||
initialSession,
|
||||
initialPrompt,
|
||||
initialSessionId,
|
||||
initialAttachmentPath,
|
||||
launchNote,
|
||||
}: ChatViewProps) {
|
||||
const preferences = useMemo(() => getLamPreferences(), []);
|
||||
const chat = useChat({ preferences, initialSession });
|
||||
}: ChatSessionProps) {
|
||||
// The capability check is resolved before the chat exists, because its answer
|
||||
// is part of the system prompt: a model that knows it can read images describes
|
||||
// the one it is sent, and one that does not know reasons about itself instead.
|
||||
const vision = useVisionSupport(preferences);
|
||||
const chat = useChat({ preferences, initialSession, vision: vision.support });
|
||||
const { replaceSession } = chat;
|
||||
const { canSeeImages } = useVisionSupport(preferences);
|
||||
const { canSeeImages } = vision;
|
||||
const { activity } = chat;
|
||||
|
||||
const [input, setInput] = useState(initialPrompt ?? "");
|
||||
@@ -396,7 +429,7 @@ export function ChatView({
|
||||
};
|
||||
|
||||
if (startup === "loading" || summaries === undefined) {
|
||||
return <List isLoading navigationTitle="Lam" searchBarPlaceholder="Loading conversations…" />;
|
||||
return <LoadingChat />;
|
||||
}
|
||||
|
||||
const placeholder = chat.status ? `${chat.status}. Press ⏎ to stop` : "Lam is thinking. Press ⏎ to stop";
|
||||
|
||||
Reference in New Issue
Block a user