refactor: rename the commands after what they do (#26)
This commit was merged in pull request #26.
This commit is contained in:
@@ -68,12 +68,12 @@ npm run build
|
|||||||
Setup is two prompts on first launch, then one command you can revisit any time.
|
Setup is two prompts on first launch, then one command you can revisit any time.
|
||||||
|
|
||||||
1. **The API key.** Vicinae prompts for required preferences before a command runs, so the very first launch asks for your Ollama API key.
|
1. **The API key.** Vicinae prompts for required preferences before a command runs, so the very first launch asks for your Ollama API key.
|
||||||
2. **The model.** The next prompt asks which model to use. Type it exactly, e.g. `deepseek-v4.1-flash:cloud` or `gpt-oss:120b`. Typing it by hand is the fragile part, so run **Ollama Models** afterwards and pick the real one from the list.
|
2. **The model.** The next prompt asks which model to use. Type it exactly, e.g. `deepseek-v4.1-flash:cloud` or `gpt-oss:120b`. Typing it by hand is the fragile part, so run **Manage Models** afterwards and pick the real one from the list.
|
||||||
3. **`Set Up Lam Agent`** verifies the connection, lists every model your key can actually reach, and reports which one is in use and where that came from.
|
3. **`Setup & Status`** verifies the connection, lists every model your key can actually reach, and reports which one is in use and where that came from.
|
||||||
|
|
||||||
To change the model later, run **Ollama Models** and pick one, or edit the **Model** preference directly.
|
To change the model later, run **Manage Models** and pick one, or edit the **Model** preference directly.
|
||||||
|
|
||||||
> An extension can read preferences but not write them, which is why a pick made in **Ollama Models** is stored by the extension and layered over the preference rather than saved into it. See [Models](#models) for how the two are reconciled, and for what a reset does.
|
> An extension can read preferences but not write them, which is why a pick made in **Manage Models** is stored by the extension and layered over the preference rather than saved into it. See [Models](#models) for how the two are reconciled, and for what a reset does.
|
||||||
|
|
||||||
## Keyboard shortcuts
|
## Keyboard shortcuts
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ To change the model later, run **Ollama Models** and pick one, or edit the **Mod
|
|||||||
| `↩` with an empty bar | Open the highlighted conversation |
|
| `↩` with an empty bar | Open the highlighted conversation |
|
||||||
| `⌘ N` | New chat |
|
| `⌘ N` | New chat |
|
||||||
| `⌘ ⇧ S` | Snip a region and attach it to this chat (only with a vision model) |
|
| `⌘ ⇧ S` | Snip a region and attach it to this chat (only with a vision model) |
|
||||||
| `⌘ ⇧ ⌫` | Delete the highlighted conversation (also in **Chat Sessions**) |
|
| `⌘ ⇧ ⌫` | Delete the highlighted conversation (also in **Chat History**) |
|
||||||
|
|
||||||
Prompts are single line. An earlier `⌘ ↩` multi-line composer was removed. See [Architecture](#architecture) for why a `Form.TextArea` cannot be laid out cleanly in a launcher. The `Tab` shortcut went with it: the left column *is* the conversation switcher now, so an accessory dropdown would only duplicate it.
|
Prompts are single line. An earlier `⌘ ↩` multi-line composer was removed. See [Architecture](#architecture) for why a `Form.TextArea` cannot be laid out cleanly in a launcher. The `Tab` shortcut went with it: the left column *is* the conversation switcher now, so an accessory dropdown would only duplicate it.
|
||||||
|
|
||||||
@@ -118,16 +118,16 @@ vicinae 'vicinae://launch/lam-agent/chat?fallbackText=summarise%20this'
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| **Chat with Lam** | The chat surface. Bind this to your global shortcut. |
|
| **Chat with Lam** | The chat surface. Bind this to your global shortcut. |
|
||||||
| **Snip to Lam** | Capture a region and start a new chat about it. A `no-view` command, so the launcher window closes before the selector appears. Bind this to a second shortcut for one-key "snip and ask". |
|
| **Snip to Lam** | Capture a region and start a new chat about it. A `no-view` command, so the launcher window closes before the selector appears. Bind this to a second shortcut for one-key "snip and ask". |
|
||||||
| **Chat Sessions** | Browse, reopen, and delete past conversations. |
|
| **Chat History** | Browse, reopen, and delete past conversations. |
|
||||||
| **Ollama Models** | Browse the models the configured host can reach, pick the one Lam uses, and pull or delete models on a server you run. See [Models](#models). |
|
| **Manage Models** | Browse the models the configured host can reach, pick the one Lam uses, and pull or delete models on a server you run. See [Models](#models). |
|
||||||
| **Set Up Lam Agent** | Verify the connection, list available models, check whether the selected model can see images, and clear out chats or unattached photos. |
|
| **Setup & Status** | Verify the connection, list available models, check whether the selected model can see images, and clear out chats or unattached photos. |
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
| Preference | Default | Notes |
|
| Preference | Default | Notes |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| **Ollama API Key** | None | Required. Stored by Vicinae as a password preference. |
|
| **Ollama API Key** | None | Required. Stored by Vicinae as a password preference. |
|
||||||
| **Model** | None | Required. Any model your key can reach. **Ollama Models** can pick one for you, and a pick takes precedence over this value until you reset it from the setup screen. |
|
| **Model** | None | Required. Any model your key can reach. **Manage Models** can pick one for you, and a pick takes precedence over this value until you reset it from the setup screen. |
|
||||||
| **Ollama Host** | `https://ollama.com` | Set to `http://localhost:11434` for a local server. |
|
| **Ollama Host** | `https://ollama.com` | Set to `http://localhost:11434` for a local server. |
|
||||||
| **Location** | None | The place Lam should treat as yours, for example `Cebu City, Philippines`. Optional. The only exact location available, and the only one that stops anything being inferred. |
|
| **Location** | None | The place Lam should treat as yours, for example `Cebu City, Philippines`. Optional. The only exact location available, and the only one that stops anything being inferred. |
|
||||||
| **IP Geolocation** | off | Off by default. When on, and only when **Location** is empty, your IP is sent to ipwho.is to resolve a rough area. |
|
| **IP Geolocation** | off | Off by default. When on, and only when **Location** is empty, your IP is sent to ipwho.is to resolve a rough area. |
|
||||||
@@ -145,7 +145,7 @@ vicinae 'vicinae://launch/lam-agent/chat?fallbackText=summarise%20this'
|
|||||||
|
|
||||||
## Models
|
## Models
|
||||||
|
|
||||||
**Ollama Models** lists everything the configured host can reach, filtered by the search bar. Each row shows the parameter count and how much disk it takes, with tags for the model in use and for anything that reports image input. Picking one writes it to LocalStorage and `loadPreferences` layers it over the `Model` preference, so it takes effect on the next question with no restart.
|
**Manage Models** lists everything the configured host can reach, filtered by the search bar. Each row shows the parameter count and how much disk it takes, with tags for the model in use and for anything that reports image input. Picking one writes it to LocalStorage and `loadPreferences` layers it over the `Model` preference, so it takes effect on the next question with no restart.
|
||||||
|
|
||||||
| Action | Notes |
|
| Action | Notes |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
@@ -211,7 +211,7 @@ If you turn on **IP Geolocation**, and only then, `get_location` resolves a roug
|
|||||||
|
|
||||||
**It is coarser than "city-level" suggests, and that is worth knowing before trusting it.** An IP address identifies the point where the traffic left the ISP, not the person. Measured from one machine on Globe Telecom, an IPv4 lookup resolved to Cebu City and an IPv6 lookup moments later resolved to Talisay in Calabarzon, roughly 500km apart. If you want a place you can rely on, set **Location** and turn this off.
|
**It is coarser than "city-level" suggests, and that is worth knowing before trusting it.** An IP address identifies the point where the traffic left the ISP, not the person. Measured from one machine on Globe Telecom, an IPv4 lookup resolved to Cebu City and an IPv6 lookup moments later resolved to Talisay in Calabarzon, roughly 500km apart. If you want a place you can rely on, set **Location** and turn this off.
|
||||||
|
|
||||||
The answer is cached for 6 hours rather than looked up per question, because an area does not change between questions and every lookup hands over another copy of your address. `Set Up Lam Agent` clears that cache, and the capability cache, when you re-test.
|
The answer is cached for 6 hours rather than looked up per question, because an area does not change between questions and every lookup hands over another copy of your address. `Setup & Status` clears that cache, and the capability cache, when you re-test.
|
||||||
|
|
||||||
This extension does not use GPS. That would mean CoreLocation on macOS, which has no command-line interface, or GeoClue on Linux, whose usual provider resolves nearby Wi-Fi networks through a Mozilla service anyway. Neither is worth it for "is it late where you are".
|
This extension does not use GPS. That would mean CoreLocation on macOS, which has no command-line interface, or GeoClue on Linux, whose usual provider resolves nearby Wi-Fi networks through a Mozilla service anyway. Neither is worth it for "is it late where you are".
|
||||||
|
|
||||||
@@ -287,7 +287,7 @@ The index entry for a conversation carries its image paths (`SessionSummary.atta
|
|||||||
|
|
||||||
### Doing it by hand
|
### Doing it by hand
|
||||||
|
|
||||||
**Set Up Lam Agent** has a Maintenance section with the same two jobs as explicit actions:
|
**Setup & Status** has a Maintenance section with the same two jobs as explicit actions:
|
||||||
|
|
||||||
| Action | What it deletes |
|
| Action | What it deletes |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
@@ -352,8 +352,8 @@ The list shows the sources the answer cited, falling back to everything the turn
|
|||||||
src/
|
src/
|
||||||
chat.tsx # "chat" command entrypoint, thin wrapper
|
chat.tsx # "chat" command entrypoint, thin wrapper
|
||||||
snip.tsx # "snip" command entrypoint, no-view: captures then hands over
|
snip.tsx # "snip" command entrypoint, no-view: captures then hands over
|
||||||
models.tsx # "models" command: browse, pick, pull, delete
|
manage-models.tsx # "manage-models" command: browse, pick, pull, delete
|
||||||
sessions.tsx # browse, reopen, delete conversations
|
chat-history.tsx # "chat-history" command: browse, reopen, delete conversations
|
||||||
setup.tsx # connection check + live model list
|
setup.tsx # connection check + live model list
|
||||||
lib/
|
lib/
|
||||||
ollama.ts # the only file that talks HTTP
|
ollama.ts # the only file that talks HTTP
|
||||||
@@ -423,7 +423,7 @@ The rendered height stays capped at 200px whatever is asked for (`Math.min(_rawH
|
|||||||
|
|
||||||
**The logic layer has no Vicinae imports.** `agent.ts`, `ollama.ts`, `tools.ts` and friends are plain TypeScript, which is why they unit test without a runtime. A test enforces this.
|
**The logic layer has no Vicinae imports.** `agent.ts`, `ollama.ts`, `tools.ts` and friends are plain TypeScript, which is why they unit test without a runtime. A test enforces this.
|
||||||
|
|
||||||
**Preferences have exactly one reader.** `loadPreferences` applies the model chosen in **Ollama Models** on top of what Vicinae holds, and it is asynchronous because that pick lives in LocalStorage. `getLamPreferences` is deliberately not exported, because a second, synchronous reader would look correct and silently ignore the pick. Views take preferences through `hooks/usePreferences`, and the chat view is split in two so that `useChat` is only ever created once the model is known, rather than being pinned to whatever the preference said a moment earlier.
|
**Preferences have exactly one reader.** `loadPreferences` applies the model chosen in **Manage Models** on top of what Vicinae holds, and it is asynchronous because that pick lives in LocalStorage. `getLamPreferences` is deliberately not exported, because a second, synchronous reader would look correct and silently ignore the pick. Views take preferences through `hooks/usePreferences`, and the chat view is split in two so that `useChat` is only ever created once the model is known, rather than being pinned to whatever the preference said a moment earlier.
|
||||||
|
|
||||||
**Sessions are capped twice over**, once per turn and once per session, because `LocalStorage` has no documented ceiling.
|
**Sessions are capped twice over**, once per turn and once per session, because `LocalStorage` has no documented ceiling.
|
||||||
|
|
||||||
@@ -441,7 +441,7 @@ The hand-off goes through `snip` specifically rather than straight to `chat` on
|
|||||||
|
|
||||||
**An attached image is sent once and never replayed.** It is the largest thing a request can carry, so `buildMessages` attaches it to the question it belongs to and drops it afterwards, exactly as it already drops tool output. The cost is that a follow-up about a screenshot needs the image attached again; the alternative is re-sending every screenshot in the conversation on every turn. Only the path and mime type go into storage: `MAX_STORED_CHARS_PER_TURN` exists so one turn cannot dominate `LocalStorage`, and base64 would blow past it on a single 1080p capture.
|
**An attached image is sent once and never replayed.** It is the largest thing a request can carry, so `buildMessages` attaches it to the question it belongs to and drops it afterwards, exactly as it already drops tool output. The cost is that a follow-up about a screenshot needs the image attached again; the alternative is re-sending every screenshot in the conversation on every turn. Only the path and mime type go into storage: `MAX_STORED_CHARS_PER_TURN` exists so one turn cannot dominate `LocalStorage`, and base64 would blow past it on a single 1080p capture.
|
||||||
|
|
||||||
**Whether the model can see is a tri-state, and the prompt gets the whole answer.** `canSeeImages` stays fail-closed, because offering the snip action to a model that cannot read would waste the selection gesture. But the system prompt needs `"unknown"` kept apart from `"no"`: telling a model it cannot see when the check merely failed is a false claim about the user's setup, and telling it nothing is what made it reason about its own capability instead of describing the image it had been sent. A model name that does not exist on the server is the common way to end up at `"unknown"`, which is one more reason the Models command picks names from the list rather than taking them typed.
|
**Whether the model can see is a tri-state, and the prompt gets the whole answer.** `canSeeImages` stays fail-closed, because offering the snip action to a model that cannot read would waste the selection gesture. But the system prompt needs `"unknown"` kept apart from `"no"`: telling a model it cannot see when the check merely failed is a false claim about the user's setup, and telling it nothing is what made it reason about its own capability instead of describing the image it had been sent. A model name that does not exist on the server is the common way to end up at `"unknown"`, which is one more reason the Manage Models command picks names from the list rather than taking them typed.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
|||||||
+7
-10
@@ -11,34 +11,31 @@
|
|||||||
{
|
{
|
||||||
"name": "chat",
|
"name": "chat",
|
||||||
"title": "Chat with Lam",
|
"title": "Chat with Lam",
|
||||||
"subtitle": "Lam Agent",
|
|
||||||
"description": "Ask Lam anything. Answers stream in as they are generated, your session history is kept, and Lam can search the web when it needs current information.",
|
"description": "Ask Lam anything. Answers stream in as they are generated, your session history is kept, and Lam can search the web when it needs current information.",
|
||||||
"mode": "view"
|
"mode": "view"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "snip",
|
"name": "snip",
|
||||||
"title": "Snip to Lam",
|
"title": "Snip to Lam",
|
||||||
"subtitle": "Lam Agent",
|
|
||||||
"description": "Capture a region of the screen and start a new chat about it. The launcher window closes first so it cannot end up in the shot. Offered only when the model in preferences supports image input.",
|
"description": "Capture a region of the screen and start a new chat about it. The launcher window closes first so it cannot end up in the shot. Offered only when the model in preferences supports image input.",
|
||||||
"mode": "no-view"
|
"mode": "no-view"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sessions",
|
"name": "chat-history",
|
||||||
"title": "Chat Sessions",
|
"title": "Chat History",
|
||||||
"description": "Browse, reopen, and clean up your past conversations with Lam.",
|
"description": "Browse, reopen, and clean up your past conversations with Lam.",
|
||||||
"mode": "view"
|
"mode": "view"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "models",
|
"name": "manage-models",
|
||||||
"title": "Ollama Models",
|
"title": "Manage Models",
|
||||||
"subtitle": "Lam Agent",
|
|
||||||
"description": "Browse the models your Ollama host can reach, pick the one Lam should use, unload one that is holding memory, and pull or delete models on a server you run. A pick takes effect immediately; a pull keeps downloading until it finishes, so leave the launcher open.",
|
"description": "Browse the models your Ollama host can reach, pick the one Lam should use, unload one that is holding memory, and pull or delete models on a server you run. A pick takes effect immediately; a pull keeps downloading until it finishes, so leave the launcher open.",
|
||||||
"mode": "view"
|
"mode": "view"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "setup",
|
"name": "setup",
|
||||||
"title": "Set Up Lam Agent",
|
"title": "Setup & Status",
|
||||||
"description": "Check your Ollama connection, pick the model Lam should use, and tune how Lam answers.",
|
"description": "Check your Ollama connection, pick the model Lam should use, tune how Lam answers, and clear out old chats or screenshots you never sent.",
|
||||||
"mode": "view"
|
"mode": "view"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -53,7 +50,7 @@
|
|||||||
{
|
{
|
||||||
"name": "model",
|
"name": "model",
|
||||||
"title": "Model",
|
"title": "Model",
|
||||||
"description": "The model Lam should use, for example deepseek-v4.1-flash:cloud or gpt-oss:120b. Run \"Set Up Lam Agent\" to pick from the models your key can access.",
|
"description": "The model Lam should use, for example deepseek-v4.1-flash:cloud or gpt-oss:120b. Run \"Setup & Status\" to pick from the models your key can access.",
|
||||||
"type": "textfield",
|
"type": "textfield",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ describe("resolveStartup", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("does not resume when a session was pushed in by hand", async () => {
|
it("does not resume when a session was pushed in by hand", async () => {
|
||||||
// The sessions command already knows which conversation to show.
|
// The Chat History command already knows which conversation to show.
|
||||||
const p = ports();
|
const p = ports();
|
||||||
|
|
||||||
await resolveStartup(input({ hasInitialSession: true }), p);
|
await resolveStartup(input({ hasInitialSession: true }), p);
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export default function SessionsCommand() {
|
|||||||
return (
|
return (
|
||||||
<List
|
<List
|
||||||
isLoading={!loaded}
|
isLoading={!loaded}
|
||||||
navigationTitle="Chat Sessions"
|
navigationTitle="Chat History"
|
||||||
searchBarPlaceholder="Search conversations…"
|
searchBarPlaceholder="Search conversations…"
|
||||||
>
|
>
|
||||||
{loaded && items.length === 0 ? (
|
{loaded && items.length === 0 ? (
|
||||||
+1
-1
@@ -6,7 +6,7 @@ import { readSnipContext } from "./lib/snip";
|
|||||||
* Entrypoint for the "chat" command.
|
* Entrypoint for the "chat" command.
|
||||||
*
|
*
|
||||||
* Deliberately thin: everything lives in {@link ChatView} so the same view can
|
* Deliberately thin: everything lives in {@link ChatView} so the same view can
|
||||||
* also be pushed onto the navigation stack from the sessions command.
|
* also be pushed onto the navigation stack from the Chat History command.
|
||||||
*
|
*
|
||||||
* Assign this command a global shortcut in Vicinae's settings to get the
|
* Assign this command a global shortcut in Vicinae's settings to get the
|
||||||
* launcher-and-start-typing behaviour. `fallbackText` is populated when the
|
* launcher-and-start-typing behaviour. `fallbackText` is populated when the
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const STORAGE_INDEX_KEY = "lam.sessions.index";
|
|||||||
export const STORAGE_SESSION_PREFIX = "lam.session.";
|
export const STORAGE_SESSION_PREFIX = "lam.session.";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The model picked in the Models command.
|
* The model picked in the Manage Models command.
|
||||||
*
|
*
|
||||||
* Separate from the `model` preference because an extension cannot write its own
|
* Separate from the `model` preference because an extension cannot write its own
|
||||||
* preferences: Vicinae reads them once at startup and holds them in memory, so
|
* preferences: Vicinae reads them once at startup and holds them in memory, so
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const FLUSH_INTERVAL_MS = 60;
|
|||||||
|
|
||||||
export interface UseChatOptions {
|
export interface UseChatOptions {
|
||||||
preferences: ResolvedPreferences;
|
preferences: ResolvedPreferences;
|
||||||
/** Restores an existing conversation, e.g. when reopening from the sessions command. */
|
/** Restores an existing conversation, e.g. when reopening from the Chat History command. */
|
||||||
initialSession?: Session;
|
initialSession?: Session;
|
||||||
/**
|
/**
|
||||||
* Whether the model can read images, for the system prompt.
|
* Whether the model can read images, for the system prompt.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { loadPreferences, type ResolvedPreferences } from "../preferences";
|
|||||||
* The preferences a view should use, or `undefined` until they have loaded.
|
* The preferences a view should use, or `undefined` until they have loaded.
|
||||||
*
|
*
|
||||||
* Every reader goes through `loadPreferences`, which layers the model chosen in
|
* Every reader goes through `loadPreferences`, which layers the model chosen in
|
||||||
* the Models command on top of what Vicinae holds, and that read is asynchronous
|
* the Manage Models command on top of what Vicinae holds, and that read is asynchronous
|
||||||
* because the selection lives in LocalStorage. A hook rather than a synchronous
|
* because the selection lives in LocalStorage. A hook rather than a synchronous
|
||||||
* call so that the one reader is also the only way to get preferences into a
|
* call so that the one reader is also the only way to get preferences into a
|
||||||
* component, and a view that forgets to handle the loading case fails to compile
|
* component, and a view that forgets to handle the loading case fails to compile
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export interface ResolvedPreferences {
|
|||||||
model: string;
|
model: string;
|
||||||
/**
|
/**
|
||||||
* Whether {@link ResolvedPreferences.model} came from the preference or from a
|
* Whether {@link ResolvedPreferences.model} came from the preference or from a
|
||||||
* pick in the Models command.
|
* pick in the Manage Models command.
|
||||||
*
|
*
|
||||||
* Carried rather than inferred, because the two disagree silently otherwise:
|
* Carried rather than inferred, because the two disagree silently otherwise:
|
||||||
* the setup screen would show one model while the chat used another, and the
|
* the setup screen would show one model while the chat used another, and the
|
||||||
@@ -244,14 +244,14 @@ export function resolvePreferences(raw: LamPreferences): ResolvedPreferences {
|
|||||||
/**
|
/**
|
||||||
* Vicinae's own preferences, resolved and normalised. Not exported: everything
|
* Vicinae's own preferences, resolved and normalised. Not exported: everything
|
||||||
* outside this module should go through {@link loadPreferences}, which also
|
* outside this module should go through {@link loadPreferences}, which also
|
||||||
* applies the model chosen in the Models command.
|
* applies the model chosen in the Manage Models command.
|
||||||
*/
|
*/
|
||||||
function getLamPreferences(): ResolvedPreferences {
|
function getLamPreferences(): ResolvedPreferences {
|
||||||
return resolvePreferences(getPreferenceValues<LamPreferences>());
|
return resolvePreferences(getPreferenceValues<LamPreferences>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The model chosen in the Models command, if there is one.
|
* The model chosen in the Manage Models command, if there is one.
|
||||||
*
|
*
|
||||||
* Never throws. Storage that cannot be read means no selection rather than a
|
* Never throws. Storage that cannot be read means no selection rather than a
|
||||||
* broken command, because the fallback (the preference) is always a valid
|
* broken command, because the fallback (the preference) is always a valid
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ import { errorMessage } from "./utils";
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export interface StartupInput {
|
export interface StartupInput {
|
||||||
/** A conversation already in hand, which is how the sessions command pushes this view. */
|
/** A conversation already in hand, which is how the Chat History command pushes this view. */
|
||||||
hasInitialSession: boolean;
|
hasInitialSession: boolean;
|
||||||
/** A conversation to reopen by id, handed over by the snip command. */
|
/** A conversation to reopen by id, handed over by the snip command. */
|
||||||
initialSessionId?: string;
|
initialSessionId?: string;
|
||||||
|
|||||||
+1
-1
@@ -66,7 +66,7 @@ export async function visionSupport(check: VisionCheck): Promise<VisionSupport>
|
|||||||
* Drops every cached answer.
|
* Drops every cached answer.
|
||||||
*
|
*
|
||||||
* A model can gain vision without its name changing (a re-pull, a different
|
* A model can gain vision without its name changing (a re-pull, a different
|
||||||
* tag on the same account), so `Set Up Lam Agent` calls this rather than
|
* tag on the same account), so `Setup & Status` calls this rather than
|
||||||
* leaving the user pinned to a stale "no".
|
* leaving the user pinned to a stale "no".
|
||||||
*/
|
*/
|
||||||
export async function forgetVisionSupport(): Promise<void> {
|
export async function forgetVisionSupport(): Promise<void> {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export default function ModelsCommand() {
|
|||||||
// marked up relative to it: which row is current, and whether picking one
|
// marked up relative to it: which row is current, and whether picking one
|
||||||
// would change anything.
|
// would change anything.
|
||||||
if (!preferences) {
|
if (!preferences) {
|
||||||
return <List isLoading navigationTitle="Ollama Models" searchBarPlaceholder="Loading models…" />;
|
return <List isLoading navigationTitle="Manage Models" searchBarPlaceholder="Loading models…" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <ModelsScreen preferences={preferences} reloadPreferences={reload} />;
|
return <ModelsScreen preferences={preferences} reloadPreferences={reload} />;
|
||||||
@@ -256,7 +256,7 @@ function ModelsScreen({ preferences, reloadPreferences }: ModelsScreenProps) {
|
|||||||
return (
|
return (
|
||||||
<List
|
<List
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
navigationTitle="Ollama Models"
|
navigationTitle="Manage Models"
|
||||||
searchBarPlaceholder="Search models…"
|
searchBarPlaceholder="Search models…"
|
||||||
actions={listActions}
|
actions={listActions}
|
||||||
>
|
>
|
||||||
+3
-3
@@ -56,11 +56,11 @@ export default function SetupCommand() {
|
|||||||
|
|
||||||
// The screen does nothing until the model is known, because half of what it
|
// 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
|
// 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
|
// one from preferences or from the Manage Models command. Rendering it with the
|
||||||
// preference value and correcting it a moment later would flash a wrong answer
|
// preference value and correcting it a moment later would flash a wrong answer
|
||||||
// at the user.
|
// at the user.
|
||||||
if (!preferences) {
|
if (!preferences) {
|
||||||
return <List isLoading navigationTitle="Lam Agent Setup" searchBarPlaceholder="Loading preferences…" />;
|
return <List isLoading navigationTitle="Setup & Status" searchBarPlaceholder="Loading preferences…" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <SetupScreen preferences={preferences} reloadPreferences={reload} />;
|
return <SetupScreen preferences={preferences} reloadPreferences={reload} />;
|
||||||
@@ -207,7 +207,7 @@ function SetupScreen({ preferences, reloadPreferences }: SetupScreenProps) {
|
|||||||
return (
|
return (
|
||||||
<List
|
<List
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
navigationTitle="Lam Agent Setup"
|
navigationTitle="Setup & Status"
|
||||||
searchBarPlaceholder="Search models…"
|
searchBarPlaceholder="Search models…"
|
||||||
actions={settingsActions}
|
actions={settingsActions}
|
||||||
>
|
>
|
||||||
|
|||||||
+2
-2
@@ -34,7 +34,7 @@ function settleWindow(): Promise<void> {
|
|||||||
* Bind it to a global shortcut for one-key "snip and ask".
|
* Bind it to a global shortcut for one-key "snip and ask".
|
||||||
*/
|
*/
|
||||||
export default async function SnipCommand(props: LaunchProps) {
|
export default async function SnipCommand(props: LaunchProps) {
|
||||||
// Awaited because the model can come from a pick in the Models command, which
|
// Awaited because the model can come from a pick in the Manage Models command, which
|
||||||
// lives in storage. The vision check below is about whichever model is in use,
|
// lives in storage. The vision check below is about whichever model is in use,
|
||||||
// so it has to be the resolved one.
|
// so it has to be the resolved one.
|
||||||
const preferences = await loadPreferences();
|
const preferences = await loadPreferences();
|
||||||
@@ -59,7 +59,7 @@ export default async function SnipCommand(props: LaunchProps) {
|
|||||||
await showHUD(
|
await showHUD(
|
||||||
vision === "no"
|
vision === "no"
|
||||||
? `${preferences.model} cannot see images. Pick a vision model in preferences.`
|
? `${preferences.model} cannot see images. Pick a vision model in preferences.`
|
||||||
: `Could not check whether ${preferences.model} can see images. Run Set Up Lam Agent.`,
|
: `Could not check whether ${preferences.model} can see images. Run Setup & Status.`,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user