From 46595649df32d0c1a23aa279b7e794a7d6ad45a2 Mon Sep 17 00:00:00 2001 From: Avraham Sakal Date: Fri, 8 Aug 2025 17:24:31 -0400 Subject: [PATCH] add "Fact Triggers" tab in UI --- pages/chat/@id/+Page.tsx | 32 ++++++++++++++++++++++++++++++++ pages/chat/@id/+data.ts | 10 +++++++++- pages/chat/fact-triggers.ts | 8 ++++---- pages/chat/trpc.ts | 2 ++ state.ts | 12 ++++++++++++ types.ts | 5 ++++- 6 files changed, 63 insertions(+), 6 deletions(-) diff --git a/pages/chat/@id/+Page.tsx b/pages/chat/@id/+Page.tsx index e60496a..50ccfa5 100644 --- a/pages/chat/@id/+Page.tsx +++ b/pages/chat/@id/+Page.tsx @@ -35,6 +35,7 @@ export default function ChatPage() { const systemPrompt = useStore((state) => state.systemPrompt); const parameters = useStore((state) => state.parameters); const facts = useStore((state) => state.facts); + const factTriggers = useStore((state) => state.factTriggers); const loading = useStore((state) => state.loading); const setConversationId = useStore((state) => state.setConversationId); const setConversationTitle = useStore((state) => state.setConversationTitle); @@ -43,13 +44,16 @@ export default function ChatPage() { const setSystemPrompt = useStore((state) => state.setSystemPrompt); const setParameters = useStore((state) => state.setParameters); const setFacts = useStore((state) => state.setFacts); + const setFactTriggers = useStore((state) => state.setFactTriggers); const removeFact = useStore((state) => state.removeFact); + const removeFactTrigger = useStore((state) => state.removeFactTrigger); const setLoading = useStore((state) => state.setLoading); const { conversation, messages: initialMessages, facts: initialFacts, + factTriggers: initialFactTriggers, } = useData(); useEffect(() => { @@ -76,11 +80,20 @@ export default function ChatPage() { setFacts(initialFacts); }, [initialFacts, setFacts]); + useEffect(() => { + setFactTriggers(initialFactTriggers); + }, [initialFactTriggers, setFactTriggers]); + async function handleDeleteFact(factId: string) { removeFact(factId); await trpc.chat.facts.deleteOne.mutate({ factId }); } + async function handleDeleteFactTrigger(factTriggerId: string) { + removeFactTrigger(factTriggerId); + await trpc.chat.factTriggers.deleteOne.mutate({ factTriggerId }); + } + return ( <>
@@ -105,6 +118,7 @@ export default function ChatPage() { System Prompt Parameters Facts + Fact Triggers @@ -193,6 +207,24 @@ export default function ChatPage() { ))} + + + {factTriggers.map((factTrigger) => ( + + {factTrigger.content}{" "} + { + e.stopPropagation(); + e.preventDefault(); + handleDeleteFactTrigger(factTrigger.id); + }} + /> + + ))} + + ); diff --git a/pages/chat/@id/+data.ts b/pages/chat/@id/+data.ts index 1ce759f..7e48e42 100644 --- a/pages/chat/@id/+data.ts +++ b/pages/chat/@id/+data.ts @@ -15,5 +15,13 @@ export const data = async (pageContext: PageContextServer) => { const facts = await caller.facts.fetchByConversationId({ conversationId: id, }); - return { conversation, messages, facts }; + + // Fetch all fact triggers for the conversation's facts + const factTriggerPromises = facts.map(fact => + caller.factTriggers.fetchByFactId({ factId: fact.id }) + ); + const factTriggersArrays = await Promise.all(factTriggerPromises); + const factTriggers = factTriggersArrays.flat(); + + return { conversation, messages, facts, factTriggers }; }; diff --git a/pages/chat/fact-triggers.ts b/pages/chat/fact-triggers.ts index 18dfe89..c4ba163 100644 --- a/pages/chat/fact-triggers.ts +++ b/pages/chat/fact-triggers.ts @@ -70,12 +70,12 @@ export const factTriggers = router({ }, ) .mutation(async ({ input: { factTriggerId } }) => { - const deletedFactTriggerIndex = db.data.facts.findIndex( - (fact) => fact.id === factTriggerId, + const deletedFactTriggerIndex = db.data.factTriggers.findIndex( + (factTrigger) => factTrigger.id === factTriggerId, ); - if (deletedFactTriggerIndex === -1) throw new Error("Fact not found"); + if (deletedFactTriggerIndex === -1) throw new Error("Fact trigger not found"); db.data.factTriggers.splice(deletedFactTriggerIndex, 1); - db.write(); + await db.write(); return { ok: true }; }), generateFromFact: publicProcedure diff --git a/pages/chat/trpc.ts b/pages/chat/trpc.ts index 2e8b388..2442788 100644 --- a/pages/chat/trpc.ts +++ b/pages/chat/trpc.ts @@ -21,6 +21,7 @@ import { messages } from "./messages.js"; import { facts, createCaller as createCallerFacts } from "./facts.js"; import { createCaller as createCallerMessages } from "./messages.js"; import { createCaller as createCallerFactTriggers } from "./fact-triggers.js"; +import { factTriggers } from "./fact-triggers.js"; import { openrouter } from "./provider.js"; const factsCaller = createCallerFacts({}); @@ -42,6 +43,7 @@ export const chat = router({ conversations, messages, facts, + factTriggers, sendMessage: publicProcedure .input( (x) => diff --git a/state.ts b/state.ts index 24a62f2..980d9fa 100644 --- a/state.ts +++ b/state.ts @@ -17,6 +17,7 @@ export const useStore = create()( systemPrompt: defaultSystemPrompt, parameters: defaultParameters, facts: [], + factTriggers: [], loading: false, setConversationId: (conversationId) => set((stateDraft) => { @@ -69,6 +70,10 @@ export const useStore = create()( set((stateDraft) => { stateDraft.facts = facts; }), + setFactTriggers: (factTriggers) => + set((stateDraft) => { + stateDraft.factTriggers = factTriggers; + }), removeFact: (factId) => set((stateDraft) => { stateDraft.facts.splice( @@ -76,6 +81,13 @@ export const useStore = create()( 1, ); }), + removeFactTrigger: (factTriggerId) => + set((stateDraft) => { + stateDraft.factTriggers.splice( + stateDraft.factTriggers.findIndex((ft) => ft.id === factTriggerId), + 1, + ); + }), setLoading: (loading) => set((stateDraft) => { stateDraft.loading = loading; diff --git a/types.ts b/types.ts index 3510618..107bef4 100644 --- a/types.ts +++ b/types.ts @@ -1,6 +1,6 @@ import type { Message as UIMessage } from "ai"; import type { generateText } from "ai"; -import type { Conversation, Fact } from "./database/lowdb.js"; +import type { Conversation, Fact, FactTrigger } from "./database/lowdb.js"; export type OtherParameters = Omit< Parameters[0], @@ -19,6 +19,7 @@ export type Store = { systemPrompt: string; parameters: OtherParameters; facts: Array; + factTriggers: Array; loading: boolean; setConversationId: (conversationId: string) => void; setConversationTitle: (conversationTitle: string) => void; @@ -30,7 +31,9 @@ export type Store = { setSystemPrompt: (systemPrompt: string) => void; setParameters: (parameters: OtherParameters) => void; setFacts: (facts: Array) => void; + setFactTriggers: (factTriggers: Array) => void; removeFact: (factId: string) => void; + removeFactTrigger: (factTriggerId: string) => void; setLoading: (loading: boolean) => void; };