use environment variables from cloudflare's environment

This commit is contained in:
Avraham Sakal
2025-09-16 09:09:33 -04:00
parent c98342e886
commit 81338b8831
11 changed files with 323 additions and 268 deletions
+12 -1
View File
@@ -1,11 +1,22 @@
import type { PageContextServer } from "vike/types";
import { createCaller } from "../trpc.js";
import { getDb } from "../../../database/postgres.js";
import { getOpenrouter } from "../provider.js";
import { env } from "../../../server/env.js";
export type Data = Awaited<ReturnType<typeof data>>;
export const data = async (pageContext: PageContextServer) => {
const { id } = pageContext.routeParams;
const caller = createCaller({});
const caller = createCaller({
db: getDb(
(pageContext.env?.POSTGRES_CONNECTION_STRING ||
env.POSTGRES_CONNECTION_STRING) as string
),
openrouter: getOpenrouter(
(pageContext.env?.OPENROUTER_API_KEY || env.OPENROUTER_API_KEY) as string
),
});
const [
conversation,
+6 -7
View File
@@ -3,18 +3,17 @@ import {
publicProcedure,
createCallerFactory,
} from "../../trpc/server";
import { db } from "../../database/index";
export const conversations = router({
fetchAll: publicProcedure.query(async () => {
fetchAll: publicProcedure.query(async ({ ctx: { db } }) => {
return await db.conversations.findAll();
}),
fetchOne: publicProcedure
.input((x) => x as { id: string })
.query(async ({ input: { id } }) => {
.query(async ({ input: { id }, ctx: { db } }) => {
return await db.conversations.findById(id);
}),
start: publicProcedure.mutation(async () => {
start: publicProcedure.mutation(async ({ ctx: { db } }) => {
const row = {
title: "New Conversation",
userId: "019900bb-61b3-7333-b760-b27784dfe33b",
@@ -23,7 +22,7 @@ export const conversations = router({
}),
deleteOne: publicProcedure
.input((x) => x as { id: string })
.mutation(async ({ input: { id } }) => {
.mutation(async ({ input: { id }, ctx: { db } }) => {
await db.conversations.delete(id);
return { ok: true };
}),
@@ -35,13 +34,13 @@ export const conversations = router({
title: string;
}
)
.mutation(async ({ input: { id, title } }) => {
.mutation(async ({ input: { id, title }, ctx: { db } }) => {
await db.conversations.update(id, { title });
return { ok: true };
}),
fetchMessages: publicProcedure
.input((x) => x as { conversationId: string })
.query(async ({ input: { conversationId } }) => {
.query(async ({ input: { conversationId }, ctx: { db } }) => {
return await db.conversations.fetchMessages(conversationId);
}),
});
+6 -6
View File
@@ -3,9 +3,8 @@ import {
publicProcedure,
createCallerFactory,
} from "../../trpc/server.js";
import { db } from "../../database/index.js";
import type { DraftMessage } from "../../types.js";
import { openrouter, MODEL_NAME } from "./provider.js";
import { MODEL_NAME } from "./provider.js";
import { generateObject, generateText, jsonSchema } from "ai";
import type { Fact } from "../../database/common.js";
@@ -61,12 +60,12 @@ Generate a list of situations in which the fact is useful.`;
export const factTriggers = router({
fetchByFactId: publicProcedure
.input((x) => x as { factId: string })
.query(async ({ input: { factId } }) => {
.query(async ({ input: { factId }, ctx: { db } }) => {
return db.factTriggers.findByFactId(factId);
}),
fetchByConversationId: publicProcedure
.input((x) => x as { conversationId: string })
.query(async ({ input: { conversationId } }) => {
.query(async ({ input: { conversationId }, ctx: { db } }) => {
return await db.factTriggers.findByConversationId(conversationId);
}),
deleteOne: publicProcedure
@@ -76,7 +75,7 @@ export const factTriggers = router({
factTriggerId: string;
}
)
.mutation(async ({ input: { factTriggerId } }) => {
.mutation(async ({ input: { factTriggerId }, ctx: { db } }) => {
await db.factTriggers.delete(factTriggerId);
return { ok: true };
}),
@@ -88,7 +87,7 @@ export const factTriggers = router({
content: string;
}
)
.mutation(async ({ input: { factTriggerId, content } }) => {
.mutation(async ({ input: { factTriggerId, content }, ctx: { db } }) => {
db.factTriggers.update(factTriggerId, { content });
return { ok: true };
}),
@@ -110,6 +109,7 @@ export const factTriggers = router({
mainResponseContent,
fact,
},
ctx: { openrouter },
}) => {
const factTriggers = await generateObject({
model: openrouter(MODEL_NAME),
+4 -4
View File
@@ -3,7 +3,6 @@ import {
publicProcedure,
createCallerFactory,
} from "../../trpc/server.js";
import { db } from "../../database/index.js";
import type { DraftMessage } from "../../types.js";
import { MODEL_NAME, openrouter } from "./provider.js";
import { generateObject, generateText, jsonSchema } from "ai";
@@ -56,7 +55,7 @@ Extract new facts from these messages.`;
export const facts = router({
fetchByConversationId: publicProcedure
.input((x) => x as { conversationId: string })
.query(async ({ input: { conversationId } }) => {
.query(async ({ input: { conversationId }, ctx: { db } }) => {
return await db.facts.findByConversationId(conversationId);
}),
deleteOne: publicProcedure
@@ -66,7 +65,7 @@ export const facts = router({
factId: string;
}
)
.mutation(async ({ input: { factId } }) => {
.mutation(async ({ input: { factId }, ctx: { db } }) => {
await db.facts.delete(factId);
return { ok: true };
}),
@@ -78,7 +77,7 @@ export const facts = router({
content: string;
}
)
.mutation(async ({ input: { factId, content } }) => {
.mutation(async ({ input: { factId, content }, ctx: { db } }) => {
await db.facts.update(factId, { content });
return { ok: true };
}),
@@ -100,6 +99,7 @@ export const facts = router({
messagesSincePreviousRunningSummary,
newMessages,
},
ctx: { db },
}) => {
const factsFromUserMessageResponse = await generateObject({
model: openrouter(MODEL_NAME),
+4 -4
View File
@@ -3,10 +3,9 @@ import {
publicProcedure,
createCallerFactory,
} from "../../trpc/server";
import { MODEL_NAME, openrouter } from "./provider.js";
import { MODEL_NAME } from "./provider.js";
import { generateObject, generateText, jsonSchema } from "ai";
import type { DraftMessage } from "../../types.js";
import { db } from "../../database/index";
const runningSummarySystemPrompt = ({
previousRunningSummary,
@@ -51,12 +50,12 @@ Generate a new running summary of the conversation.`;
export const messages = router({
fetchByConversationId: publicProcedure
.input((x) => x as { conversationId: string })
.query(async ({ input: { conversationId } }) => {
.query(async ({ input: { conversationId }, ctx: { db } }) => {
return await db.messages.findByConversationId(conversationId);
}),
deleteOne: publicProcedure
.input((x) => x as { id: string })
.mutation(async ({ input: { id } }) => {
.mutation(async ({ input: { id }, ctx: { db } }) => {
await db.messages.delete(id);
return { success: true };
}),
@@ -76,6 +75,7 @@ export const messages = router({
messagesSincePreviousRunningSummary,
mainResponseContent,
},
ctx: { openrouter },
}) => {
const runningSummaryResponse = await generateText({
model: openrouter(MODEL_NAME),
+5
View File
@@ -4,6 +4,11 @@ export const openrouter = createOpenRouter({
apiKey: env.OPENROUTER_API_KEY,
});
export function getOpenrouter(OPENROUTER_API_KEY: string) {
return createOpenRouter({
apiKey: OPENROUTER_API_KEY,
});
}
export const MODEL_NAME = "mistralai/mistral-nemo";
// export const MODEL_NAME = "z-ai/glm-4.5-air";
// export const MODEL_NAME = "openai/gpt-5-mini";
+7 -7
View File
@@ -14,20 +14,15 @@ import type {
// ConsistencyLevelEnum,
// type NumberArrayId,
// } from "@zilliz/milvus2-sdk-node";
import { db } from "../../database/index.js";
import { conversations } from "./conversations.js";
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 { MODEL_NAME, openrouter } from "./provider.js";
import { MODEL_NAME } from "./provider.js";
import type { Fact, FactTrigger } from "../../database/common.js";
const factsCaller = createCallerFacts({});
const messagesCaller = createCallerMessages({});
const factTriggerCaller = createCallerFactTriggers({});
const mainSystemPrompt = ({
systemPrompt,
previousRunningSummary,
@@ -54,7 +49,7 @@ export const chat = router({
message: string;
}
)
.subscription(async function* ({ input, signal }) {
.subscription(async function* ({ input, signal, ctx: { openrouter } }) {
const result = streamText({
model: openrouter(MODEL_NAME),
messages: [{ role: "user" as const, content: input.message }],
@@ -76,7 +71,12 @@ export const chat = router({
)
.subscription(async function* ({
input: { conversationId, messages, systemPrompt, parameters },
ctx,
}) {
const { db, openrouter } = ctx;
const factsCaller = createCallerFacts(ctx);
const messagesCaller = createCallerMessages(ctx);
const factTriggerCaller = createCallerFactTriggers(ctx);
/** TODO: Save all unsaved messages (i.e. those without an `id`) to the
* database. Is this dangerous? Can an attacker just send a bunch of
* messages, omitting the ids, causing me to save a bunch of them to the