feat: persist last-used model in LocalStorage instead of preference
Drop the summaryModel preference (and the awkward textfield holding a raw model ID nobody could discover without poking the SDK types). Each AI view now controls its model dropdown, loads the shared velum.ai.last-model on mount, and writes it back on submit — so picking Claude 4.7 Opus in the summarize command becomes the prefilled default in briefing, action-items, structured-data, and reply next time around. Also drops 'model' from ReplyDefaults; the shared key supersedes it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,8 +17,9 @@ Alle Werte sind in den Raycast-Einstellungen pro Extension einstellbar.
|
|||||||
**Verhalten:**
|
**Verhalten:**
|
||||||
- `Standard-Sitzungsmodus` — `Aktive Sitzung wiederverwenden` (Default), `Neue Sitzung pro Anfrage`, `Tagessitzung`
|
- `Standard-Sitzungsmodus` — `Aktive Sitzung wiederverwenden` (Default), `Neue Sitzung pro Anfrage`, `Tagessitzung`
|
||||||
- `Ausgabe der Schnellbefehle` — `In die Zwischenablage kopieren` (Default) oder `Am Cursor einfügen`
|
- `Ausgabe der Schnellbefehle` — `In die Zwischenablage kopieren` (Default) oder `Am Cursor einfügen`
|
||||||
- `Standard-Modell für AI-Befehle` — Modell-ID, die in den AI-Views vorausgewählt ist (Default `anthropic-claude-sonnet-4-6`, benötigt Raycast Pro). Die View-Dropdowns listen aktuelle Modelle aus `src/ai.ts`; neue Modelle dort eintragen, wenn Raycast sie ausrollt.
|
|
||||||
- `Eigener Name` — Default-Signatur für AI-generierte Email-Antworten, im Antwort-Befehl pro Aufruf überschreibbar
|
- `Eigener Name` — Default-Signatur für AI-generierte Email-Antworten, im Antwort-Befehl pro Aufruf überschreibbar
|
||||||
|
|
||||||
|
Das KI-Modell ist keine Preference: jeder AI-Befehl zeigt ein `KI-Modell`-Dropdown mit dem aktuellen Modell-Katalog aus `src/ai.ts`. Die Auswahl wird in `LocalStorage` (`velum.ai.last-model`) persistiert und ist beim nächsten Aufruf in jedem AI-Befehl vorausgewählt.
|
||||||
- `Maximale Anzahl gespeicherter Sitzungen` — älteste werden geprunt (Default 20)
|
- `Maximale Anzahl gespeicherter Sitzungen` — älteste werden geprunt (Default 20)
|
||||||
- `Raycast nach Kopieren/Einfügen schließen` — Auto-Close und Pop-To-Root nach AI-Workflow-Abschluss (Default an)
|
- `Raycast nach Kopieren/Einfügen schließen` — Auto-Close und Pop-To-Root nach AI-Workflow-Abschluss (Default an)
|
||||||
|
|
||||||
|
|||||||
@@ -178,15 +178,6 @@
|
|||||||
"required": true,
|
"required": true,
|
||||||
"placeholder": "Raphael"
|
"placeholder": "Raphael"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "summaryModel",
|
|
||||||
"title": "Standard-Modell für AI-Befehle",
|
|
||||||
"description": "Raycast-KI-Modell-ID, vorausgewählt in den AI-Views. Die volle Modellliste ist dort als Dropdown verfügbar. Benötigt Raycast Pro.",
|
|
||||||
"type": "textfield",
|
|
||||||
"required": true,
|
|
||||||
"default": "anthropic-claude-sonnet-4-6",
|
|
||||||
"placeholder": "anthropic-claude-sonnet-4-6"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "maxSessions",
|
"name": "maxSessions",
|
||||||
"title": "Maximale Anzahl gespeicherter Sitzungen",
|
"title": "Maximale Anzahl gespeicherter Sitzungen",
|
||||||
|
|||||||
18
src/ai.ts
18
src/ai.ts
@@ -1,3 +1,5 @@
|
|||||||
|
import { LocalStorage } from "@raycast/api";
|
||||||
|
|
||||||
export type Creativity = "none" | "low" | "medium" | "high";
|
export type Creativity = "none" | "low" | "medium" | "high";
|
||||||
|
|
||||||
export const CREATIVITY_OPTIONS: Creativity[] = [
|
export const CREATIVITY_OPTIONS: Creativity[] = [
|
||||||
@@ -77,6 +79,22 @@ export const MODEL_OPTIONS: ModelOption[] = [
|
|||||||
{ value: "together-moonshotai/Kimi-K2.5", title: "Kimi K2.5" },
|
{ value: "together-moonshotai/Kimi-K2.5", title: "Kimi K2.5" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const LAST_MODEL_STORAGE_KEY = "velum.ai.last-model";
|
||||||
|
|
||||||
|
export const DEFAULT_MODEL: string = MODEL_OPTIONS[0].value;
|
||||||
|
|
||||||
|
export async function getLastUsedModel(): Promise<string> {
|
||||||
|
const stored = await LocalStorage.getItem<string>(LAST_MODEL_STORAGE_KEY);
|
||||||
|
if (stored && MODEL_OPTIONS.some((option) => option.value === stored)) {
|
||||||
|
return stored;
|
||||||
|
}
|
||||||
|
return DEFAULT_MODEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setLastUsedModel(model: string): Promise<void> {
|
||||||
|
await LocalStorage.setItem(LAST_MODEL_STORAGE_KEY, model);
|
||||||
|
}
|
||||||
|
|
||||||
export const STRICT_PLACEHOLDER_RULE = [
|
export const STRICT_PLACEHOLDER_RULE = [
|
||||||
"STRENGE REGEL: Gib jeden Platzhalter zeichengetreu (inklusive spitzer Klammern, Großbuchstaben und Unterstrich + Nummer) zurück.",
|
"STRENGE REGEL: Gib jeden Platzhalter zeichengetreu (inklusive spitzer Klammern, Großbuchstaben und Unterstrich + Nummer) zurück.",
|
||||||
"Du darfst Platzhalter NIEMALS auflösen, raten, übersetzen oder mit erfundenen Namen ersetzen. Schreibe sie exakt so, wie sie in der Eingabe stehen.",
|
"Du darfst Platzhalter NIEMALS auflösen, raten, übersetzen oder mit erfundenen Namen ersetzen. Schreibe sie exakt so, wie sie in der Eingabe stehen.",
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ import { useEffect, useMemo, useState } from "react";
|
|||||||
import {
|
import {
|
||||||
type Creativity,
|
type Creativity,
|
||||||
CREATIVITY_OPTIONS,
|
CREATIVITY_OPTIONS,
|
||||||
|
DEFAULT_MODEL,
|
||||||
|
getLastUsedModel,
|
||||||
MODEL_OPTIONS,
|
MODEL_OPTIONS,
|
||||||
|
setLastUsedModel,
|
||||||
STRICT_PLACEHOLDER_RULE,
|
STRICT_PLACEHOLDER_RULE,
|
||||||
} from "./ai";
|
} from "./ai";
|
||||||
import { PseudonymizationConfirm } from "./ai-views";
|
import { PseudonymizationConfirm } from "./ai-views";
|
||||||
import { getPreferences } from "./preferences";
|
|
||||||
import { getSelectedTextSafely } from "./selection";
|
import { getSelectedTextSafely } from "./selection";
|
||||||
import {
|
import {
|
||||||
createSession,
|
createSession,
|
||||||
@@ -75,23 +77,25 @@ type FormValues = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function Command() {
|
export default function Command() {
|
||||||
const preferences = getPreferences();
|
|
||||||
const [text, setText] = useState("");
|
const [text, setText] = useState("");
|
||||||
const [sessions, setSessions] = useState<VelumSession[]>([]);
|
const [sessions, setSessions] = useState<VelumSession[]>([]);
|
||||||
const [activeSessionId, setActiveSessionId] = useState<string>();
|
const [activeSessionId, setActiveSessionId] = useState<string>();
|
||||||
const [entityTypes, setEntityTypes] = useState<EntityType[]>([]);
|
const [entityTypes, setEntityTypes] = useState<EntityType[]>([]);
|
||||||
const [selectedEntityTypes, setSelectedEntityTypes] = useState<string[]>([]);
|
const [selectedEntityTypes, setSelectedEntityTypes] = useState<string[]>([]);
|
||||||
|
const [model, setModel] = useState<string>(DEFAULT_MODEL);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const { push } = useNavigation();
|
const { push } = useNavigation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function load() {
|
async function load() {
|
||||||
const [loadedSessions, activeId] = await Promise.all([
|
const [loadedSessions, activeId, lastModel] = await Promise.all([
|
||||||
listSessions(),
|
listSessions(),
|
||||||
getActiveSessionId(),
|
getActiveSessionId(),
|
||||||
|
getLastUsedModel(),
|
||||||
]);
|
]);
|
||||||
setSessions(loadedSessions);
|
setSessions(loadedSessions);
|
||||||
setActiveSessionId(activeId);
|
setActiveSessionId(activeId);
|
||||||
|
setModel(lastModel);
|
||||||
|
|
||||||
const selection = await getSelectedTextSafely();
|
const selection = await getSelectedTextSafely();
|
||||||
if (selection && selection.trim()) {
|
if (selection && selection.trim()) {
|
||||||
@@ -150,6 +154,8 @@ export default function Command() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setLastUsedModel(values.model);
|
||||||
|
|
||||||
const toast = await showToast({
|
const toast = await showToast({
|
||||||
style: Toast.Style.Animated,
|
style: Toast.Style.Animated,
|
||||||
title: "Pseudonymisiere…",
|
title: "Pseudonymisiere…",
|
||||||
@@ -272,7 +278,8 @@ export default function Command() {
|
|||||||
<Form.Dropdown
|
<Form.Dropdown
|
||||||
id="model"
|
id="model"
|
||||||
title="KI-Modell"
|
title="KI-Modell"
|
||||||
defaultValue={preferences.summaryModel}
|
value={model}
|
||||||
|
onChange={setModel}
|
||||||
>
|
>
|
||||||
{MODEL_OPTIONS.map((option) => (
|
{MODEL_OPTIONS.map((option) => (
|
||||||
<Form.Dropdown.Item
|
<Form.Dropdown.Item
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ import { useEffect, useMemo, useState } from "react";
|
|||||||
import {
|
import {
|
||||||
type Creativity,
|
type Creativity,
|
||||||
CREATIVITY_OPTIONS,
|
CREATIVITY_OPTIONS,
|
||||||
|
DEFAULT_MODEL,
|
||||||
|
getLastUsedModel,
|
||||||
MODEL_OPTIONS,
|
MODEL_OPTIONS,
|
||||||
|
setLastUsedModel,
|
||||||
STRICT_PLACEHOLDER_RULE,
|
STRICT_PLACEHOLDER_RULE,
|
||||||
} from "./ai";
|
} from "./ai";
|
||||||
import { PseudonymizationConfirm } from "./ai-views";
|
import { PseudonymizationConfirm } from "./ai-views";
|
||||||
import { getPreferences } from "./preferences";
|
|
||||||
import { getSelectedTextSafely } from "./selection";
|
import { getSelectedTextSafely } from "./selection";
|
||||||
import {
|
import {
|
||||||
createSession,
|
createSession,
|
||||||
@@ -80,23 +82,25 @@ type FormValues = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function Command() {
|
export default function Command() {
|
||||||
const preferences = getPreferences();
|
|
||||||
const [text, setText] = useState("");
|
const [text, setText] = useState("");
|
||||||
const [sessions, setSessions] = useState<VelumSession[]>([]);
|
const [sessions, setSessions] = useState<VelumSession[]>([]);
|
||||||
const [activeSessionId, setActiveSessionId] = useState<string>();
|
const [activeSessionId, setActiveSessionId] = useState<string>();
|
||||||
const [entityTypes, setEntityTypes] = useState<EntityType[]>([]);
|
const [entityTypes, setEntityTypes] = useState<EntityType[]>([]);
|
||||||
const [selectedEntityTypes, setSelectedEntityTypes] = useState<string[]>([]);
|
const [selectedEntityTypes, setSelectedEntityTypes] = useState<string[]>([]);
|
||||||
|
const [model, setModel] = useState<string>(DEFAULT_MODEL);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const { push } = useNavigation();
|
const { push } = useNavigation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function load() {
|
async function load() {
|
||||||
const [loadedSessions, activeId] = await Promise.all([
|
const [loadedSessions, activeId, lastModel] = await Promise.all([
|
||||||
listSessions(),
|
listSessions(),
|
||||||
getActiveSessionId(),
|
getActiveSessionId(),
|
||||||
|
getLastUsedModel(),
|
||||||
]);
|
]);
|
||||||
setSessions(loadedSessions);
|
setSessions(loadedSessions);
|
||||||
setActiveSessionId(activeId);
|
setActiveSessionId(activeId);
|
||||||
|
setModel(lastModel);
|
||||||
|
|
||||||
const selection = await getSelectedTextSafely();
|
const selection = await getSelectedTextSafely();
|
||||||
if (selection && selection.trim()) {
|
if (selection && selection.trim()) {
|
||||||
@@ -155,6 +159,8 @@ export default function Command() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setLastUsedModel(values.model);
|
||||||
|
|
||||||
const toast = await showToast({
|
const toast = await showToast({
|
||||||
style: Toast.Style.Animated,
|
style: Toast.Style.Animated,
|
||||||
title: "Pseudonymisiere…",
|
title: "Pseudonymisiere…",
|
||||||
@@ -277,7 +283,8 @@ export default function Command() {
|
|||||||
<Form.Dropdown
|
<Form.Dropdown
|
||||||
id="model"
|
id="model"
|
||||||
title="KI-Modell"
|
title="KI-Modell"
|
||||||
defaultValue={preferences.summaryModel}
|
value={model}
|
||||||
|
onChange={setModel}
|
||||||
>
|
>
|
||||||
{MODEL_OPTIONS.map((option) => (
|
{MODEL_OPTIONS.map((option) => (
|
||||||
<Form.Dropdown.Item
|
<Form.Dropdown.Item
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ import { useEffect, useMemo, useState } from "react";
|
|||||||
import {
|
import {
|
||||||
type Creativity,
|
type Creativity,
|
||||||
CREATIVITY_OPTIONS,
|
CREATIVITY_OPTIONS,
|
||||||
|
DEFAULT_MODEL,
|
||||||
|
getLastUsedModel,
|
||||||
MODEL_OPTIONS,
|
MODEL_OPTIONS,
|
||||||
|
setLastUsedModel,
|
||||||
STRICT_PLACEHOLDER_RULE,
|
STRICT_PLACEHOLDER_RULE,
|
||||||
} from "./ai";
|
} from "./ai";
|
||||||
import { PseudonymizationConfirm } from "./ai-views";
|
import { PseudonymizationConfirm } from "./ai-views";
|
||||||
import { getPreferences } from "./preferences";
|
|
||||||
import { getSelectedTextSafely } from "./selection";
|
import { getSelectedTextSafely } from "./selection";
|
||||||
import {
|
import {
|
||||||
createSession,
|
createSession,
|
||||||
@@ -101,23 +103,25 @@ type FormValues = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function Command() {
|
export default function Command() {
|
||||||
const preferences = getPreferences();
|
|
||||||
const [text, setText] = useState("");
|
const [text, setText] = useState("");
|
||||||
const [sessions, setSessions] = useState<VelumSession[]>([]);
|
const [sessions, setSessions] = useState<VelumSession[]>([]);
|
||||||
const [activeSessionId, setActiveSessionId] = useState<string>();
|
const [activeSessionId, setActiveSessionId] = useState<string>();
|
||||||
const [entityTypes, setEntityTypes] = useState<EntityType[]>([]);
|
const [entityTypes, setEntityTypes] = useState<EntityType[]>([]);
|
||||||
const [selectedEntityTypes, setSelectedEntityTypes] = useState<string[]>([]);
|
const [selectedEntityTypes, setSelectedEntityTypes] = useState<string[]>([]);
|
||||||
|
const [model, setModel] = useState<string>(DEFAULT_MODEL);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const { push } = useNavigation();
|
const { push } = useNavigation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function load() {
|
async function load() {
|
||||||
const [loadedSessions, activeId] = await Promise.all([
|
const [loadedSessions, activeId, lastModel] = await Promise.all([
|
||||||
listSessions(),
|
listSessions(),
|
||||||
getActiveSessionId(),
|
getActiveSessionId(),
|
||||||
|
getLastUsedModel(),
|
||||||
]);
|
]);
|
||||||
setSessions(loadedSessions);
|
setSessions(loadedSessions);
|
||||||
setActiveSessionId(activeId);
|
setActiveSessionId(activeId);
|
||||||
|
setModel(lastModel);
|
||||||
|
|
||||||
const selection = await getSelectedTextSafely();
|
const selection = await getSelectedTextSafely();
|
||||||
if (selection && selection.trim()) {
|
if (selection && selection.trim()) {
|
||||||
@@ -183,6 +187,8 @@ export default function Command() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setLastUsedModel(values.model);
|
||||||
|
|
||||||
const toast = await showToast({
|
const toast = await showToast({
|
||||||
style: Toast.Style.Animated,
|
style: Toast.Style.Animated,
|
||||||
title: "Pseudonymisiere…",
|
title: "Pseudonymisiere…",
|
||||||
@@ -337,7 +343,8 @@ export default function Command() {
|
|||||||
<Form.Dropdown
|
<Form.Dropdown
|
||||||
id="model"
|
id="model"
|
||||||
title="KI-Modell"
|
title="KI-Modell"
|
||||||
defaultValue={preferences.summaryModel}
|
value={model}
|
||||||
|
onChange={setModel}
|
||||||
>
|
>
|
||||||
{MODEL_OPTIONS.map((option) => (
|
{MODEL_OPTIONS.map((option) => (
|
||||||
<Form.Dropdown.Item
|
<Form.Dropdown.Item
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ export type NormalizedPreferences = {
|
|||||||
scope: string;
|
scope: string;
|
||||||
sessionMode: SessionMode;
|
sessionMode: SessionMode;
|
||||||
quickOutput: QuickOutput;
|
quickOutput: QuickOutput;
|
||||||
summaryModel: string;
|
|
||||||
userFullName: string;
|
userFullName: string;
|
||||||
maxSessions: number;
|
maxSessions: number;
|
||||||
closeAfterAction: boolean;
|
closeAfterAction: boolean;
|
||||||
@@ -37,8 +36,6 @@ export function getPreferences(): NormalizedPreferences {
|
|||||||
scope: preferences.scope?.trim() || "profile",
|
scope: preferences.scope?.trim() || "profile",
|
||||||
sessionMode: preferences.sessionMode,
|
sessionMode: preferences.sessionMode,
|
||||||
quickOutput: preferences.quickOutput,
|
quickOutput: preferences.quickOutput,
|
||||||
summaryModel:
|
|
||||||
preferences.summaryModel?.trim() || "anthropic-claude-sonnet-4-6",
|
|
||||||
userFullName: preferences.userFullName?.trim() ?? "",
|
userFullName: preferences.userFullName?.trim() ?? "",
|
||||||
maxSessions: parsePositiveInteger(preferences.maxSessions, 20),
|
maxSessions: parsePositiveInteger(preferences.maxSessions, 20),
|
||||||
closeAfterAction: preferences.closeAfterAction ?? true,
|
closeAfterAction: preferences.closeAfterAction ?? true,
|
||||||
|
|||||||
@@ -12,7 +12,13 @@ import {
|
|||||||
} from "@raycast/api";
|
} from "@raycast/api";
|
||||||
import { getSelectedTextSafely } from "./selection";
|
import { getSelectedTextSafely } from "./selection";
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { CREATIVITY_OPTIONS, MODEL_OPTIONS } from "./ai";
|
import {
|
||||||
|
CREATIVITY_OPTIONS,
|
||||||
|
DEFAULT_MODEL,
|
||||||
|
getLastUsedModel,
|
||||||
|
MODEL_OPTIONS,
|
||||||
|
setLastUsedModel,
|
||||||
|
} from "./ai";
|
||||||
import { getPreferences } from "./preferences";
|
import { getPreferences } from "./preferences";
|
||||||
import {
|
import {
|
||||||
buildDisclosureContent,
|
buildDisclosureContent,
|
||||||
@@ -65,7 +71,7 @@ export default function Command() {
|
|||||||
const [greeting, setGreeting] = useState("Lieber");
|
const [greeting, setGreeting] = useState("Lieber");
|
||||||
const [signOff, setSignOff] = useState("Alles Liebe,");
|
const [signOff, setSignOff] = useState("Alles Liebe,");
|
||||||
const [userFullName, setUserFullName] = useState(preferences.userFullName);
|
const [userFullName, setUserFullName] = useState(preferences.userFullName);
|
||||||
const [model, setModel] = useState(preferences.summaryModel);
|
const [model, setModel] = useState<string>(DEFAULT_MODEL);
|
||||||
const [creativity, setCreativity] = useState<Creativity>("medium");
|
const [creativity, setCreativity] = useState<Creativity>("medium");
|
||||||
const [disclosure, setDisclosure] = useState(false);
|
const [disclosure, setDisclosure] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
@@ -73,17 +79,20 @@ export default function Command() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function load() {
|
async function load() {
|
||||||
const [loadedSessions, activeId, defaults] = await Promise.all([
|
const [loadedSessions, activeId, defaults, lastModel] = await Promise.all(
|
||||||
listSessions(),
|
[
|
||||||
getActiveSessionId(),
|
listSessions(),
|
||||||
loadReplyDefaults(),
|
getActiveSessionId(),
|
||||||
]);
|
loadReplyDefaults(),
|
||||||
|
getLastUsedModel(),
|
||||||
|
],
|
||||||
|
);
|
||||||
setSessions(loadedSessions);
|
setSessions(loadedSessions);
|
||||||
setActiveSessionId(activeId);
|
setActiveSessionId(activeId);
|
||||||
|
setModel(lastModel);
|
||||||
|
|
||||||
if (defaults.greeting) setGreeting(defaults.greeting);
|
if (defaults.greeting) setGreeting(defaults.greeting);
|
||||||
if (defaults.signOff) setSignOff(defaults.signOff);
|
if (defaults.signOff) setSignOff(defaults.signOff);
|
||||||
if (defaults.model) setModel(defaults.model);
|
|
||||||
if (defaults.creativity) setCreativity(defaults.creativity as Creativity);
|
if (defaults.creativity) setCreativity(defaults.creativity as Creativity);
|
||||||
if (typeof defaults.disclosure === "boolean")
|
if (typeof defaults.disclosure === "boolean")
|
||||||
setDisclosure(defaults.disclosure);
|
setDisclosure(defaults.disclosure);
|
||||||
@@ -104,13 +113,12 @@ export default function Command() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
load();
|
load();
|
||||||
}, [preferences.summaryModel, preferences.userFullName]);
|
}, [preferences.userFullName]);
|
||||||
|
|
||||||
function persist(
|
function persist(
|
||||||
overrides: Partial<{
|
overrides: Partial<{
|
||||||
greeting: string;
|
greeting: string;
|
||||||
signOff: string;
|
signOff: string;
|
||||||
model: string;
|
|
||||||
creativity: Creativity;
|
creativity: Creativity;
|
||||||
disclosure: boolean;
|
disclosure: boolean;
|
||||||
}>,
|
}>,
|
||||||
@@ -118,7 +126,6 @@ export default function Command() {
|
|||||||
saveReplyDefaults({
|
saveReplyDefaults({
|
||||||
greeting: overrides.greeting ?? greeting,
|
greeting: overrides.greeting ?? greeting,
|
||||||
signOff: overrides.signOff ?? signOff,
|
signOff: overrides.signOff ?? signOff,
|
||||||
model: overrides.model ?? model,
|
|
||||||
creativity: overrides.creativity ?? creativity,
|
creativity: overrides.creativity ?? creativity,
|
||||||
disclosure: overrides.disclosure ?? disclosure,
|
disclosure: overrides.disclosure ?? disclosure,
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
@@ -173,10 +180,10 @@ export default function Command() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setLastUsedModel(model);
|
||||||
await saveReplyDefaults({
|
await saveReplyDefaults({
|
||||||
greeting,
|
greeting,
|
||||||
signOff,
|
signOff,
|
||||||
model,
|
|
||||||
creativity,
|
creativity,
|
||||||
disclosure,
|
disclosure,
|
||||||
});
|
});
|
||||||
@@ -358,10 +365,7 @@ export default function Command() {
|
|||||||
id="model"
|
id="model"
|
||||||
title="KI-Modell"
|
title="KI-Modell"
|
||||||
value={model}
|
value={model}
|
||||||
onChange={(v) => {
|
onChange={setModel}
|
||||||
setModel(v);
|
|
||||||
persist({ model: v });
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{MODEL_OPTIONS.map((option) => (
|
{MODEL_OPTIONS.map((option) => (
|
||||||
<Form.Dropdown.Item
|
<Form.Dropdown.Item
|
||||||
@@ -432,7 +436,6 @@ function ConfirmReply(props: StageProps) {
|
|||||||
await saveReplyDefaults({
|
await saveReplyDefaults({
|
||||||
greeting,
|
greeting,
|
||||||
signOff,
|
signOff,
|
||||||
model: props.model,
|
|
||||||
creativity: props.creativity,
|
creativity: props.creativity,
|
||||||
disclosure,
|
disclosure,
|
||||||
});
|
});
|
||||||
@@ -487,7 +490,6 @@ function ConfirmReply(props: StageProps) {
|
|||||||
saveReplyDefaults({
|
saveReplyDefaults({
|
||||||
greeting: v,
|
greeting: v,
|
||||||
signOff,
|
signOff,
|
||||||
model: props.model,
|
|
||||||
creativity: props.creativity,
|
creativity: props.creativity,
|
||||||
disclosure,
|
disclosure,
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
@@ -510,7 +512,6 @@ function ConfirmReply(props: StageProps) {
|
|||||||
saveReplyDefaults({
|
saveReplyDefaults({
|
||||||
greeting,
|
greeting,
|
||||||
signOff: v,
|
signOff: v,
|
||||||
model: props.model,
|
|
||||||
creativity: props.creativity,
|
creativity: props.creativity,
|
||||||
disclosure,
|
disclosure,
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
@@ -546,7 +547,6 @@ function ConfirmReply(props: StageProps) {
|
|||||||
saveReplyDefaults({
|
saveReplyDefaults({
|
||||||
greeting,
|
greeting,
|
||||||
signOff,
|
signOff,
|
||||||
model: props.model,
|
|
||||||
creativity: props.creativity,
|
creativity: props.creativity,
|
||||||
disclosure: v,
|
disclosure: v,
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ const REPLY_DEFAULTS_KEY = "velum.reply.defaults.v1";
|
|||||||
export type ReplyDefaults = {
|
export type ReplyDefaults = {
|
||||||
greeting: string;
|
greeting: string;
|
||||||
signOff: string;
|
signOff: string;
|
||||||
model: string;
|
|
||||||
creativity: string;
|
creativity: string;
|
||||||
disclosure: boolean;
|
disclosure: boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import {
|
|||||||
import { copyRichText, markdownToHtml, maybeCloseRaycast } from "./ai-views";
|
import { copyRichText, markdownToHtml, maybeCloseRaycast } from "./ai-views";
|
||||||
import { getSelectedTextSafely } from "./selection";
|
import { getSelectedTextSafely } from "./selection";
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { getPreferences } from "./preferences";
|
|
||||||
import {
|
import {
|
||||||
createSession,
|
createSession,
|
||||||
getActiveSessionId,
|
getActiveSessionId,
|
||||||
@@ -23,7 +22,13 @@ import {
|
|||||||
setActiveSession,
|
setActiveSession,
|
||||||
updateSessionMapping,
|
updateSessionMapping,
|
||||||
} from "./sessions";
|
} from "./sessions";
|
||||||
import { CREATIVITY_OPTIONS, MODEL_OPTIONS } from "./ai";
|
import {
|
||||||
|
CREATIVITY_OPTIONS,
|
||||||
|
DEFAULT_MODEL,
|
||||||
|
getLastUsedModel,
|
||||||
|
MODEL_OPTIONS,
|
||||||
|
setLastUsedModel,
|
||||||
|
} from "./ai";
|
||||||
import { buildSummaryPrompt, type Creativity } from "./summarize";
|
import { buildSummaryPrompt, type Creativity } from "./summarize";
|
||||||
import type { EntityType, VelumSession } from "./types";
|
import type { EntityType, VelumSession } from "./types";
|
||||||
import {
|
import {
|
||||||
@@ -49,23 +54,25 @@ type FormValues = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function Command() {
|
export default function Command() {
|
||||||
const preferences = getPreferences();
|
|
||||||
const [text, setText] = useState("");
|
const [text, setText] = useState("");
|
||||||
const [sessions, setSessions] = useState<VelumSession[]>([]);
|
const [sessions, setSessions] = useState<VelumSession[]>([]);
|
||||||
const [activeSessionId, setActiveSessionId] = useState<string>();
|
const [activeSessionId, setActiveSessionId] = useState<string>();
|
||||||
const [entityTypes, setEntityTypes] = useState<EntityType[]>([]);
|
const [entityTypes, setEntityTypes] = useState<EntityType[]>([]);
|
||||||
const [selectedEntityTypes, setSelectedEntityTypes] = useState<string[]>([]);
|
const [selectedEntityTypes, setSelectedEntityTypes] = useState<string[]>([]);
|
||||||
|
const [model, setModel] = useState<string>(DEFAULT_MODEL);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const { push } = useNavigation();
|
const { push } = useNavigation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function load() {
|
async function load() {
|
||||||
const [loadedSessions, activeId] = await Promise.all([
|
const [loadedSessions, activeId, lastModel] = await Promise.all([
|
||||||
listSessions(),
|
listSessions(),
|
||||||
getActiveSessionId(),
|
getActiveSessionId(),
|
||||||
|
getLastUsedModel(),
|
||||||
]);
|
]);
|
||||||
setSessions(loadedSessions);
|
setSessions(loadedSessions);
|
||||||
setActiveSessionId(activeId);
|
setActiveSessionId(activeId);
|
||||||
|
setModel(lastModel);
|
||||||
|
|
||||||
const selection = await getSelectedTextSafely();
|
const selection = await getSelectedTextSafely();
|
||||||
if (selection && selection.trim()) {
|
if (selection && selection.trim()) {
|
||||||
@@ -124,6 +131,8 @@ export default function Command() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setLastUsedModel(values.model);
|
||||||
|
|
||||||
const toast = await showToast({
|
const toast = await showToast({
|
||||||
style: Toast.Style.Animated,
|
style: Toast.Style.Animated,
|
||||||
title: "Pseudonymisiere…",
|
title: "Pseudonymisiere…",
|
||||||
@@ -238,7 +247,8 @@ export default function Command() {
|
|||||||
<Form.Dropdown
|
<Form.Dropdown
|
||||||
id="model"
|
id="model"
|
||||||
title="KI-Modell"
|
title="KI-Modell"
|
||||||
defaultValue={preferences.summaryModel}
|
value={model}
|
||||||
|
onChange={setModel}
|
||||||
>
|
>
|
||||||
{MODEL_OPTIONS.map((option) => (
|
{MODEL_OPTIONS.map((option) => (
|
||||||
<Form.Dropdown.Item
|
<Form.Dropdown.Item
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ export type ExtensionPreferences = {
|
|||||||
scope?: string;
|
scope?: string;
|
||||||
sessionMode: SessionMode;
|
sessionMode: SessionMode;
|
||||||
quickOutput: QuickOutput;
|
quickOutput: QuickOutput;
|
||||||
summaryModel: string;
|
|
||||||
userFullName?: string;
|
userFullName?: string;
|
||||||
maxSessions: string;
|
maxSessions: string;
|
||||||
closeAfterAction: boolean;
|
closeAfterAction: boolean;
|
||||||
|
|||||||
Reference in New Issue
Block a user