feat(assistant): Fragen an die Daten im Kopf der Anwendung

Management und Administration koennen oben rechts eine Frage in Worten
stellen - "wie viele Stunden im August", "welches Projekt hat noch
Budget", "wie ist die Auslastung".

Aufbau: das Modell bekommt eine Uebersicht (Kunden, laufende Projekte,
Eckdaten) und vier Werkzeuge - auswertung, projekte, buchungen,
personen. Damit fragt es gezielt nach, statt dass ihm der ganze Bestand
vorgelegt wird; 19.000 Buchungen passen in keinen Kontext. Die Werkzeuge
rechnen mit loadEntries und loadProjects, also mit denselben Funktionen
wie die Reports - der Assistent kann so keine zweite Wahrheit erzeugen.
Was einfliesst, begrenzt visibleUserIds wie ueberall sonst.

Benutzt wird die Responses-API von OpenAI: die neueren Modelle nehmen
Werkzeuge in /v1/chat/completions nur ohne Nachdenken an. Mit
"store: false" bleibt nichts bei OpenAI liegen, der Verlauf geht deshalb
je Runde komplett mit. Der Schluessel liegt verschluesselt in den
Einstellungen (AES-256-GCM wie das SSO-Secret) und wird nie ausgeliefert;
das Modell ist einstellbar, Vorgabe gpt-5.6-luna.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
schakal00783
2026-09-21 17:31:51 +02:00
co-authored by Claude Opus 5
parent c3aed8a3d3
commit e908db2788
11 changed files with 909 additions and 2 deletions
+22 -1
View File
@@ -136,6 +136,7 @@ export const settingsApi = {
all: () => get<AdminSettings>('/settings'),
save: (changes: Partial<AdminSettingsInput>) => send<{ ok: true }>('PUT', '/settings', changes),
ssoTest: () => send<{ ok: true; sample: string[]; checked: number; eligible: number }>('POST', '/settings/sso/test'),
aiTest: () => send<{ ok: true; model: string; answer: string }>('POST', '/settings/ai/test'),
};
export interface ExportSettings {
@@ -225,15 +226,35 @@ export const hrworksApi = {
removeAll: () => send<{ deleted: number }>('DELETE', '/hrworks/entries'),
};
export interface AiSettings {
enabled: boolean;
api_key: string;
key_set?: boolean;
configured?: boolean;
model: string;
}
export interface AdminSettings extends PublicSettings {
export: ExportSettings;
sso: SsoSettings;
hrworks: HrworksSettings;
ai: AiSettings;
}
export type AdminSettingsInput = Omit<AdminSettings, 'export' | 'sso' | 'hrworks'> & {
export type AdminSettingsInput = Omit<AdminSettings, 'export' | 'sso' | 'hrworks' | 'ai'> & {
export: Partial<ExportSettings>;
sso: Partial<SsoSettings> & { clear_secret?: boolean };
hrworks: Partial<HrworksSettings> & { clear_secret?: boolean };
ai: Partial<AiSettings> & { clear_key?: boolean };
};
export interface AssistantAnswer {
answer: string;
model: string;
tools: { name: string; args: Record<string, unknown> }[];
}
export const assistantApi = {
status: () => get<{ available: boolean; enabled: boolean; model: string }>('/assistant/status'),
ask: (question: string, verlauf: { frage: string; antwort: string }[]) =>
send<AssistantAnswer>('POST', '/assistant/ask', { question, verlauf }),
};
export interface AdUser {