Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions rag-service/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ def update_processing_progress(session_id, stage, progress):
"/validate-session-write",
"/sessions/lookup",
"/demo-query-validation",
"/sessions/flashcards",
"/sessions/flashcards/progress",
}
PROTECTED_RAG_PREFIXES = (
"/ask/",
Expand Down Expand Up @@ -4473,7 +4475,7 @@ def generate_flashcards_from_text(indexed_docs, count):
return cards


@app.post("/sessions/flashcards/generate")
@app.post("/sessions/flashcards")
Comment thread
atul-upadhyay-7 marked this conversation as resolved.
def generate_flashcards(data: FlashcardGenerateRequest):
cleanup_expired_sessions()
session_id = str(data.session_id)
Expand Down Expand Up @@ -4517,7 +4519,7 @@ def generate_flashcards(data: FlashcardGenerateRequest):
return {"flashcards": cards}


@app.post("/sessions/flashcards/update-progress")
@app.post("/sessions/flashcards/progress")
Comment thread
atul-upadhyay-7 marked this conversation as resolved.
def update_flashcard_progress(data: FlashcardProgressRequest):
cleanup_expired_sessions()
session_id = str(data.session_id)
Expand Down
46 changes: 46 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const {
sessionsLookupSchema,
knowledgeGapsSchema,
MAX_QUESTION_LENGTH,
generateFlashcardsSchema,
updateFlashcardProgressSchema,
} = require("./validators/schemas");
const { clientIpFromRequest } = require("./security/ip");
const { createRedisClient } = require("./security/redis");
Expand Down Expand Up @@ -1337,6 +1339,50 @@ app.post("/sessions/lookup", async (req, res) => {
}
});

app.post("/sessions/flashcards", async (req, res) => {
const validation = generateFlashcardsSchema.safeParse(req.body);

if (!validation.success) {
return res.status(400).json({
error: "Validation failed",
details: validation.error.flatten(),
});
}

try {
const response = await axios.post(
`${RAG_SERVICE_URL}/sessions/flashcards`,
validation.data,
{ headers: ragAuthHeaders(), timeout: 60000 },
);
return res.json(response.data);
} catch (err) {
return propagateRagError(err, res, "Failed to generate flashcards");
}
});

app.post("/sessions/flashcards/progress", async (req, res) => {
const validation = updateFlashcardProgressSchema.safeParse(req.body);

if (!validation.success) {
return res.status(400).json({
error: "Validation failed",
details: validation.error.flatten(),
});
}

try {
const response = await axios.post(
`${RAG_SERVICE_URL}/sessions/flashcards/progress`,
validation.data,
{ headers: ragAuthHeaders(), timeout: 10000 },
);
return res.json(response.data);
} catch (err) {
return propagateRagError(err, res, "Failed to update flashcard progress");
}
});
Comment thread
atul-upadhyay-7 marked this conversation as resolved.

app.get("/health", (req, res) => {
res.json({ status: "ok" });
});
Expand Down
57 changes: 55 additions & 2 deletions server.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ describe("route error responses", () => {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer test-token",
Authorization: `Bearer ${jwt.sign({ role: "authenticated" }, process.env.SUPABASE_JWT_SECRET)}`,
Comment thread
atul-upadhyay-7 marked this conversation as resolved.
},
body: JSON.stringify({
url: "https://xyz.supabase.co//evil.com/file.pdf?download=1",
Expand Down Expand Up @@ -560,7 +560,7 @@ describe("route error responses", () => {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer test-token",
Authorization: `Bearer ${jwt.sign({ role: "authenticated" }, process.env.SUPABASE_JWT_SECRET)}`,
Comment thread
atul-upadhyay-7 marked this conversation as resolved.
},
body: JSON.stringify({
url: " https://xyz.supabase.co/storage/v1/object/public/docs/trimmed.pdf ",
Expand Down Expand Up @@ -845,6 +845,59 @@ describe("route error responses", () => {
}
});

test("POST /sessions/flashcards generates flashcards", async () => {
const originalPost = axios.post;
let forwardedHeaders = null;

axios.post = async (url, body, options) => {
forwardedHeaders = options?.headers;
return { data: { flashcards: [] } };
};
Comment thread
atul-upadhyay-7 marked this conversation as resolved.

try {
const res = await fetch(`${baseUrl}/sessions/flashcards`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
session_id: "550e8400-e29b-41d4-a716-446655440000",
session_secret: "secret-abc",
count: 5,
}),
});
assert.equal(res.status, 200);
assert.equal(forwardedHeaders["X-Internal-Token"], process.env.INTERNAL_RAG_TOKEN);
} finally {
axios.post = originalPost;
}
});

test("POST /sessions/flashcards/progress updates progress", async () => {
const originalPost = axios.post;
let forwardedHeaders = null;

axios.post = async (url, body, options) => {
forwardedHeaders = options?.headers;
return { data: { success: true } };
};
Comment thread
atul-upadhyay-7 marked this conversation as resolved.

try {
const res = await fetch(`${baseUrl}/sessions/flashcards/progress`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
session_id: "550e8400-e29b-41d4-a716-446655440000",
session_secret: "secret-abc",
card_id: "card-1",
rating: "good",
}),
});
assert.equal(res.status, 200);
assert.equal(forwardedHeaders["X-Internal-Token"], process.env.INTERNAL_RAG_TOKEN);
} finally {
axios.post = originalPost;
}
});

test("GET unknown route returns 404", async () => {
const res = await fetch(`${baseUrl}/nonexistent`, {
method: "GET",
Expand Down
Loading