Files
app/src/admin/lib/queries/ai.ts
BOHA 674b44d047 feat(odin): Phase 2a read-only agentic assistant + tool-trace UI
- agentic chat loop (max 6 round-trips, budget re-checked between iterations)
  over 10 read-only, permission-delegated tools in src/services/ai-tools.ts
- persist assistant tool trace in ai_chat_messages.content_json (+ migration)
- consulted-tools chips in OdinThread; header now shows month spend only
  (budget cap hidden from the UI, server-side 402 guard unchanged)
- seed: ai.use permission; Settings exposes the ai permission module
- docs: REVIEW consolidation; deployment-guide.md superseded by docs/release.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:31:50 +02:00

66 lines
1.6 KiB
TypeScript

import { queryOptions } from "@tanstack/react-query";
import { jsonQuery } from "../apiAdapter";
export interface AiUsage {
configured: boolean;
month_spend_usd: number;
budget_usd: number;
remaining_usd: number;
}
export interface ExtractedInvoice {
supplier_name: string;
invoice_number: string | null;
amount: number;
currency: string;
vat_rate: number;
issue_date: string | null;
due_date: string | null;
description: string | null;
}
export interface StoredChatMessage {
role: "user" | "assistant";
content: string;
created_at: string;
/** Parsed content_json — the assistant turn's tool trace, when present. */
meta?: {
tools?: { name: string; label: string; ok: boolean }[];
} | null;
}
export const aiUsageOptions = () =>
queryOptions({
queryKey: ["ai", "usage"],
queryFn: () => jsonQuery<AiUsage>("/api/admin/ai/usage"),
staleTime: 30_000,
});
export interface Conversation {
id: number;
title: string;
updated_at: string;
}
export const aiConversationsOptions = () =>
queryOptions({
queryKey: ["ai", "conversations"],
queryFn: () =>
jsonQuery<{ conversations: Conversation[] }>(
"/api/admin/ai/conversations",
),
staleTime: 30_000,
});
export const aiConversationMessagesOptions = (id: number) =>
queryOptions({
queryKey: ["ai", "conversation", id, "messages"],
queryFn: () =>
jsonQuery<{ messages: StoredChatMessage[] }>(
`/api/admin/ai/conversations/${id}/messages`,
),
// Re-read the DB on each mount/selection (no stale-cache resurrection).
staleTime: Infinity,
gcTime: 0,
});