From 26f0ff67fc1ff90579d5487a79f76f2aff5bd9bc Mon Sep 17 00:00:00 2001 From: Aadesh Kheria Date: Wed, 13 May 2026 16:07:26 -0700 Subject: [PATCH] bot comments --- .../internal/mcp-review/add-manual/route.ts | 6 +- .../mcp-review/update-correction/route.ts | 3 +- .../api/latest/internal/mcp-review.test.ts | 2 +- .../tests/spacetimedb/private-tables.test.ts | 2 +- .../published-qa-projection.test.ts | 2 +- .../published-qa-visibility.test.ts | 8 +-- .../spacetimedb/qa-entries-invariants.test.ts | 4 +- .../tests/spacetimedb/reducer-auth.test.ts | 4 +- apps/internal-tool/spacetimedb/src/index.ts | 66 ++++++++++++++++++- 9 files changed, 79 insertions(+), 18 deletions(-) diff --git a/apps/backend/src/app/api/latest/internal/mcp-review/add-manual/route.ts b/apps/backend/src/app/api/latest/internal/mcp-review/add-manual/route.ts index f41111df4..3a5ed4e7e 100644 --- a/apps/backend/src/app/api/latest/internal/mcp-review/add-manual/route.ts +++ b/apps/backend/src/app/api/latest/internal/mcp-review/add-manual/route.ts @@ -1,4 +1,4 @@ -import { callReducerStrict, opt } from "@/lib/ai/spacetimedb-client"; +import { callReducerStrict } from "@/lib/ai/spacetimedb-client"; import { assertIsAiChatReviewer } from "@/lib/ai/qa/reviewer-auth"; import { createSmartRouteHandler } from "@/route-handlers/smart-route-handler"; import { adaptSchema, yupBoolean, yupNumber, yupObject, yupString } from "@stackframe/stack-shared/dist/schema-fields"; @@ -16,7 +16,7 @@ export const POST = createSmartRouteHandler({ question: yupString().defined(), answer: yupString().defined(), publish: yupBoolean().defined(), - requestId: yupString(), + requestId: yupString().defined(), }).defined(), method: yupString().oneOf(["POST"]).defined(), }), @@ -38,7 +38,7 @@ export const POST = createSmartRouteHandler({ body.answer, body.publish, user.display_name ?? user.primary_email ?? user.id, - body.requestId + body.requestId, ]); return { diff --git a/apps/backend/src/app/api/latest/internal/mcp-review/update-correction/route.ts b/apps/backend/src/app/api/latest/internal/mcp-review/update-correction/route.ts index 5907462be..e5e397c80 100644 --- a/apps/backend/src/app/api/latest/internal/mcp-review/update-correction/route.ts +++ b/apps/backend/src/app/api/latest/internal/mcp-review/update-correction/route.ts @@ -34,7 +34,7 @@ export const POST = createSmartRouteHandler({ const token = getEnvVariable("STACK_MCP_LOG_TOKEN"); const reviewer = user.display_name ?? user.primary_email ?? user.id; - await callReducerStrict("upsert_qa_from_call", [ + await callReducerStrict("upsert_qa_from_call_and_mark_reviewed", [ token, body.correlationId, body.correctedQuestion, @@ -42,7 +42,6 @@ export const POST = createSmartRouteHandler({ body.publish, reviewer, ]); - await callReducerStrict("mark_human_reviewed", [token, body.correlationId, reviewer]); return { statusCode: 200, diff --git a/apps/e2e/tests/backend/endpoints/api/latest/internal/mcp-review.test.ts b/apps/e2e/tests/backend/endpoints/api/latest/internal/mcp-review.test.ts index b723999bf..e1746538e 100644 --- a/apps/e2e/tests/backend/endpoints/api/latest/internal/mcp-review.test.ts +++ b/apps/e2e/tests/backend/endpoints/api/latest/internal/mcp-review.test.ts @@ -27,7 +27,7 @@ const endpoints = [ }, { path: "/api/latest/internal/mcp-review/add-manual", - validBody: { question: "q", answer: "a", publish: false }, + validBody: { question: "q", answer: "a", publish: false, requestId: "test-req-id" }, invalidBody: { question: "q" }, }, { diff --git a/apps/e2e/tests/spacetimedb/private-tables.test.ts b/apps/e2e/tests/spacetimedb/private-tables.test.ts index 2ef64f8d1..dd9028da5 100644 --- a/apps/e2e/tests/spacetimedb/private-tables.test.ts +++ b/apps/e2e/tests/spacetimedb/private-tables.test.ts @@ -77,7 +77,7 @@ describe.skipIf(!canRun)("private log tables and view gating", () => { const seed = await niceBackendFetch("/api/latest/internal/mcp-review/add-manual", { method: "POST", accessType: "client", - body: { question: seedMarker, answer: "a", publish: false }, + body: { question: seedMarker, answer: "a", publish: false, requestId: seedMarker }, }); expect(seed.status).toBe(200); diff --git a/apps/e2e/tests/spacetimedb/published-qa-projection.test.ts b/apps/e2e/tests/spacetimedb/published-qa-projection.test.ts index 3358ac792..ef441bad7 100644 --- a/apps/e2e/tests/spacetimedb/published-qa-projection.test.ts +++ b/apps/e2e/tests/spacetimedb/published-qa-projection.test.ts @@ -56,7 +56,7 @@ describe.skipIf(!canRun)("published_qa view projection", () => { const publish = await niceBackendFetch("/api/latest/internal/mcp-review/add-manual", { method: "POST", accessType: "client", - body: { question: markerQuestion, answer: markerAnswer, publish: true }, + body: { question: markerQuestion, answer: markerAnswer, publish: true, requestId: markerQuestion }, }); expect(publish.status).toBe(200); diff --git a/apps/e2e/tests/spacetimedb/published-qa-visibility.test.ts b/apps/e2e/tests/spacetimedb/published-qa-visibility.test.ts index efccfca62..56685d692 100644 --- a/apps/e2e/tests/spacetimedb/published-qa-visibility.test.ts +++ b/apps/e2e/tests/spacetimedb/published-qa-visibility.test.ts @@ -40,7 +40,7 @@ describe.skipIf(!canRun)("published_qa visibility", () => { const add = await niceBackendFetch("/api/latest/internal/mcp-review/add-manual", { method: "POST", accessType: "client", - body: { question: marker, answer: "x", publish: false }, + body: { question: marker, answer: "x", publish: false, requestId: marker }, }); expect(add.status).toBe(200); @@ -63,7 +63,7 @@ describe.skipIf(!canRun)("published_qa visibility", () => { const add = await niceBackendFetch("/api/latest/internal/mcp-review/add-manual", { method: "POST", accessType: "client", - body: { question: marker, answer: "x", publish: true }, + body: { question: marker, answer: "x", publish: true, requestId: marker }, }); expect(add.status).toBe(200); expect(await publishedQaContains(marker)).toBe(true); @@ -102,7 +102,7 @@ describe.skipIf(!canRun)("published_qa visibility", () => { const add = await niceBackendFetch("/api/latest/internal/mcp-review/add-manual", { method: "POST", accessType: "client", - body: { question: marker, answer: "x", publish: true }, + body: { question: marker, answer: "x", publish: true, requestId: marker }, }); expect(add.status).toBe(200); expect(await publishedQaContains(marker)).toBe(true); @@ -137,7 +137,7 @@ describe.skipIf(!canRun)("published_qa visibility", () => { const add = await niceBackendFetch("/api/latest/internal/mcp-review/add-manual", { method: "POST", accessType: "client", - body: { question: marker, answer: "x", publish: true }, + body: { question: marker, answer: "x", publish: true, requestId: marker }, }); expect(add.status).toBe(200); expect(await publishedQaContains(marker)).toBe(true); diff --git a/apps/e2e/tests/spacetimedb/qa-entries-invariants.test.ts b/apps/e2e/tests/spacetimedb/qa-entries-invariants.test.ts index 3b48bfa47..776a3023e 100644 --- a/apps/e2e/tests/spacetimedb/qa-entries-invariants.test.ts +++ b/apps/e2e/tests/spacetimedb/qa-entries-invariants.test.ts @@ -61,7 +61,7 @@ describe.skipIf(!canRun)("qa_entries CRUD invariants", () => { const add = await niceBackendFetch("/api/latest/internal/mcp-review/add-manual", { method: "POST", accessType: "client", - body: { question: marker, answer: "a", publish: true }, + body: { question: marker, answer: "a", publish: true, requestId: marker }, }); expect(add.status).toBe(200); @@ -120,7 +120,7 @@ describe.skipIf(!canRun)("qa_entries CRUD invariants", () => { const add = await niceBackendFetch("/api/latest/internal/mcp-review/add-manual", { method: "POST", accessType: "client", - body: { question: marker, answer: "a", publish: true }, + body: { question: marker, answer: "a", publish: true, requestId: marker }, }); expect(add.status).toBe(200); diff --git a/apps/e2e/tests/spacetimedb/reducer-auth.test.ts b/apps/e2e/tests/spacetimedb/reducer-auth.test.ts index 57bc1ca9d..52c8a9595 100644 --- a/apps/e2e/tests/spacetimedb/reducer-auth.test.ts +++ b/apps/e2e/tests/spacetimedb/reducer-auth.test.ts @@ -36,7 +36,7 @@ describe.skipIf(!canRun)("SpacetimeDB reducer auth", () => { const seedPublish = await niceBackendFetch("/api/latest/internal/mcp-review/add-manual", { method: "POST", accessType: "client", - body: { question: seedMarker, answer: "a", publish: false }, + body: { question: seedMarker, answer: "a", publish: false, requestId: seedMarker }, }); expect(seedPublish.status).toBe(200); @@ -65,7 +65,7 @@ describe.skipIf(!canRun)("SpacetimeDB reducer auth", () => { name: "upsert_qa_from_call", args: [wrong, "corr", "q", "a", false, "reviewer"], }, - { name: "add_manual_qa", args: [wrong, "q", "a", false, "reviewer", opt(null)] }, + { name: "add_manual_qa", args: [wrong, "q", "a", false, "reviewer", "req-id"] }, { name: "delete_qa_entry", args: [wrong, 0n] }, { name: "update_qa_entry_with_publish", args: [wrong, 0n, "q", "a", false, "reviewer"] }, { diff --git a/apps/internal-tool/spacetimedb/src/index.ts b/apps/internal-tool/spacetimedb/src/index.ts index 790b27686..8f7957733 100644 --- a/apps/internal-tool/spacetimedb/src/index.ts +++ b/apps/internal-tool/spacetimedb/src/index.ts @@ -441,6 +441,68 @@ export const upsert_qa_from_call = spacetimedb.reducer( } ); +export const upsert_qa_from_call_and_mark_reviewed = spacetimedb.reducer( + { + token: t.string(), + correlationId: t.string(), + question: t.string(), + answer: t.string(), + publish: t.bool(), + reviewer: t.string(), + }, + (ctx, args) => { + if (args.token !== EXPECTED_LOG_TOKEN) { + throw new SenderError('Invalid log token'); + } + const callLogRow = ctx.db.mcpCallLog.correlationId.find(args.correlationId); + if (callLogRow == null) { + throw new SenderError('Call log not found for correlationId: ' + args.correlationId); + } + + let existing = null; + for (const row of ctx.db.qaEntries.shard.filter(0)) { + if (row.sourceMcpCorrelationId === args.correlationId) { + existing = row; + break; + } + } + if (existing != null) { + ctx.db.qaEntries.id.update({ + ...existing, + question: args.question, + answer: args.answer, + lastEditedBy: args.reviewer, + lastEditedAt: ctx.timestamp, + published: args.publish, + firstPublishedAt: args.publish ? (existing.firstPublishedAt ?? ctx.timestamp) : existing.firstPublishedAt, + lastPublishedAt: args.publish ? ctx.timestamp : existing.lastPublishedAt, + }); + } else { + ctx.db.qaEntries.insert({ + id: 0n, + shard: 0, + sourceMcpCorrelationId: args.correlationId, + requestId: undefined, + question: args.question, + answer: args.answer, + createdBy: args.reviewer, + createdAt: ctx.timestamp, + lastEditedBy: args.reviewer, + lastEditedAt: ctx.timestamp, + published: args.publish, + firstPublishedAt: args.publish ? ctx.timestamp : undefined, + lastPublishedAt: args.publish ? ctx.timestamp : undefined, + } as Parameters[0]); + } + + ctx.db.mcpCallLog.id.update({ + ...callLogRow, + humanReviewedAt: ctx.timestamp, + humanReviewedBy: args.reviewer, + }); + } +); + export const add_manual_qa = spacetimedb.reducer( { token: t.string(), @@ -448,13 +510,13 @@ export const add_manual_qa = spacetimedb.reducer( answer: t.string(), publish: t.bool(), createdBy: t.string(), - requestId: t.string().optional(), + requestId: t.string(), }, (ctx, args) => { if (args.token !== EXPECTED_LOG_TOKEN) { throw new SenderError('Invalid log token'); } - if (args.requestId != null && args.requestId !== '') { + if (args.requestId !== '') { for (const existing of ctx.db.qaEntries.iter()) { if (existing.requestId === args.requestId) return; }