Ground Bean Bro in displayed temperatures, stream replies, and add activity calendar
Test and deploy / test-and-deploy (push) Successful in 1m19s
Test and deploy / test-and-deploy (push) Successful in 1m19s
This commit is contained in:
1 parent
a72aec9f86
commit
d96ed22de1
16 files changed
+551
-484
No files matched your search
+35
-8
@@ -345,7 +345,7 @@ export function createApp({
|
||||
app.get("/", async (req, res, next) => {
|
||||
try {
|
||||
// Returning users should not be left on the marketing page after signing in.
|
||||
if (await session(req)) return res.status(302).location("/app").end();
|
||||
if (await session(req)) return res.status(302).location("/home").end();
|
||||
res.set("Cache-Control", "no-store, private");
|
||||
res.sendFile(path.join(root, "public", "landing.html"));
|
||||
} catch (error) {
|
||||
@@ -355,7 +355,7 @@ export function createApp({
|
||||
for (const route of ["/login", "/signup", "/forgot"]) {
|
||||
app.get(route, async (req, res, next) => {
|
||||
try {
|
||||
if (await session(req)) return res.status(302).location("/app").end();
|
||||
if (await session(req)) return res.status(302).location("/home").end();
|
||||
res.set("Cache-Control", "no-store, private");
|
||||
res.sendFile(path.join(root, "public", `${route.slice(1)}.html`));
|
||||
} catch (error) {
|
||||
@@ -365,7 +365,7 @@ export function createApp({
|
||||
}
|
||||
app.get("/reset", async (req, res, next) => {
|
||||
try {
|
||||
if (await session(req)) return res.status(302).location("/app").end();
|
||||
if (await session(req)) return res.status(302).location("/home").end();
|
||||
res.set("Cache-Control", "no-store, private");
|
||||
res.sendFile(path.join(root, "public", "reset.html"));
|
||||
} catch (error) {
|
||||
@@ -374,7 +374,7 @@ export function createApp({
|
||||
});
|
||||
app.get("/setup", async (req, res, next) => {
|
||||
try {
|
||||
if (await session(req)) return res.status(302).location("/app").end();
|
||||
if (await session(req)) return res.status(302).location("/home").end();
|
||||
const exists = await db.query("SELECT 1 FROM users WHERE email=$1", [
|
||||
ADMIN_EMAIL,
|
||||
]);
|
||||
@@ -433,9 +433,10 @@ export function createApp({
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
app.get("/coffees", requireAuth, (req, res) => res.redirect("/home"));
|
||||
for (const [route, file] of [
|
||||
["/plans", "plans.html"],
|
||||
["/home", "workspace.html"], ["/coffees", "workspace.html"],
|
||||
["/home", "workspace.html"],
|
||||
["/beans", "beans.html"],
|
||||
["/brews", "brews.html"],
|
||||
["/gear", "gear.html"],
|
||||
@@ -1494,6 +1495,14 @@ export function createApp({
|
||||
}
|
||||
});
|
||||
app.post("/api/plan-chat", requireAuth, csrf, async (req, res, next) => {
|
||||
const streaming = req.get("accept")?.includes("text/event-stream");
|
||||
const controller = new AbortController();
|
||||
let heartbeat;
|
||||
const emit = (event, data) => {
|
||||
if (!res.destroyed && !res.writableEnded)
|
||||
res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
|
||||
};
|
||||
const disconnect = () => controller.abort();
|
||||
try {
|
||||
if (!req.body.plan || typeof req.body.plan !== "object" || Array.isArray(req.body.plan))
|
||||
return res.status(400).json({ ok: false, code: "bad_plan" });
|
||||
@@ -1506,14 +1515,32 @@ export function createApp({
|
||||
const workspace = await workspaceFor(db,req.user.id);
|
||||
const coffee = workspace.coffees.find(c=>c.key===coffeeKey(req.body.plan));
|
||||
const evidence = coffee ? {name:coffee.name,roasts:coffee.roasts.slice(0,12),cuppings:coffee.cuppings.slice(0,12),experiments:coffee.plans.map(p=>({id:p.id,experiment:p.experiment})).slice(0,12)} : null;
|
||||
const result = await runPlanChat({ plan: req.body.plan, messages, evidence, preferredModel: await llmModelSetting() });
|
||||
const preferredModel = await llmModelSetting();
|
||||
if (streaming) {
|
||||
res.set({"Content-Type":"text/event-stream", "Cache-Control":"no-cache, no-transform", "X-Accel-Buffering":"no"});
|
||||
res.flushHeaders();
|
||||
res.on("close", disconnect);
|
||||
heartbeat = setInterval(() => { if (!res.destroyed) res.write(": heartbeat\n\n"); }, 15000);
|
||||
}
|
||||
const result = await runPlanChat({
|
||||
plan: req.body.plan, messages, evidence, preferredModel,
|
||||
signal: controller.signal,
|
||||
onText: streaming ? (text) => emit("reply", {text}) : undefined,
|
||||
});
|
||||
result.suggestions = cleanSuggestions(result.suggestions).map(s=>({...s,evidenceRoastIds:s.evidenceRoastIds.filter(id=>evidence?.roasts.some(r=>r.id===id))}));
|
||||
res.json({ ok: true, ...result });
|
||||
if (streaming) { emit("done", {ok:true, ...result}); res.end(); }
|
||||
else res.json({ ok: true, ...result });
|
||||
} catch (err) {
|
||||
const code = err.code ?? "chat_failed";
|
||||
res
|
||||
if (res.headersSent) {
|
||||
emit("error", {ok:false, code, error:err.message});
|
||||
res.end();
|
||||
} else res
|
||||
.status(code === "no_model" ? 503 : 422)
|
||||
.json({ ok: false, code, error: err.message });
|
||||
} finally {
|
||||
clearInterval(heartbeat);
|
||||
res.off("close", disconnect);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user