Requests / src /lib /store.ts
armand0e's picture
Optionally add name upon submission + update source models with Qwen3 2507 specifications
f15ff24
import { supabaseRest } from "@/lib/supabaseRest";
export interface DistillationRequest {
id: string;
sourceDataset: string;
studentModel: string;
submitterName?: string;
additionalNotes: string;
upvotes: number;
votedIps: string[];
ownerId: string;
createdAt: string;
status: "pending" | "in_progress" | "completed";
}
export interface DatasetRequest {
id: string;
sourceModel: string;
submitterName?: string;
datasetSize: string;
reasoningDepth: string;
topics: string[];
additionalNotes: string;
upvotes: number;
votedIps: string[];
ownerId: string;
createdAt: string;
status: "pending" | "in_progress" | "completed";
}
export type RequestType = "distillation" | "dataset";
export interface DiscussionComment {
id: string;
body: string;
author: string;
role: "admin" | "user";
ownerId: string;
createdAt: string;
editedAt?: string;
}
export interface DiscussionThread {
key: string;
requestType: RequestType;
requestId: string;
comments: DiscussionComment[];
}
interface Store {
distillationRequests: DistillationRequest[];
datasetRequests: DatasetRequest[];
threads: Record<string, DiscussionThread>;
}
function normalizeStatus(value: unknown): "pending" | "in_progress" | "completed" {
return value === "in_progress" || value === "completed" ? value : "pending";
}
function mapDistillationRow(row: any): DistillationRequest {
const submitterNameRaw = typeof row?.submitter_name === "string" ? row.submitter_name.trim() : "";
return {
id: String(row?.id ?? ""),
sourceDataset: String(row?.source_dataset ?? ""),
studentModel: String(row?.student_model ?? ""),
submitterName: submitterNameRaw ? submitterNameRaw : undefined,
additionalNotes: String(row?.additional_notes ?? ""),
upvotes: typeof row?.upvotes === "number" ? row.upvotes : 0,
votedIps: Array.isArray(row?.voted_ips) ? row.voted_ips.map(String) : [],
ownerId: String(row?.owner_id ?? ""),
createdAt: String(row?.created_at ?? new Date().toISOString()),
status: normalizeStatus(row?.status),
};
}
function mapDatasetRow(row: any): DatasetRequest {
const submitterNameRaw = typeof row?.submitter_name === "string" ? row.submitter_name.trim() : "";
return {
id: String(row?.id ?? ""),
sourceModel: String(row?.source_model ?? ""),
submitterName: submitterNameRaw ? submitterNameRaw : undefined,
datasetSize: String(row?.dataset_size ?? "250x"),
reasoningDepth: String(row?.reasoning_depth ?? "high"),
topics: Array.isArray(row?.topics) ? row.topics.map(String) : [],
additionalNotes: String(row?.additional_notes ?? ""),
upvotes: typeof row?.upvotes === "number" ? row.upvotes : 0,
votedIps: Array.isArray(row?.voted_ips) ? row.voted_ips.map(String) : [],
ownerId: String(row?.owner_id ?? ""),
createdAt: String(row?.created_at ?? new Date().toISOString()),
status: normalizeStatus(row?.status),
};
}
function mapCommentRow(row: any): DiscussionComment {
return {
id: String(row?.id ?? ""),
body: String(row?.body ?? ""),
author: String(row?.author ?? (row?.role === "user" ? "Anonymous" : "TeichAI")),
role: row?.role === "user" ? "user" : "admin",
ownerId: String(row?.owner_id ?? ""),
createdAt: String(row?.created_at ?? new Date().toISOString()),
editedAt: row?.edited_at ? String(row.edited_at) : undefined,
};
}
export async function getDistillationRequests(): Promise<DistillationRequest[]> {
const { data, error } = await supabaseRest<any[]>("/rest/v1/distillation_requests", {
query: {
select: "*",
order: "upvotes.desc,created_at.desc",
},
});
if (error) {
throw new Error(error.message);
}
return Array.isArray(data) ? data.map(mapDistillationRow) : [];
}
export async function getDatasetRequests(): Promise<DatasetRequest[]> {
const { data, error } = await supabaseRest<any[]>("/rest/v1/dataset_requests", {
query: {
select: "*",
order: "upvotes.desc,created_at.desc",
},
});
if (error) {
throw new Error(error.message);
}
return Array.isArray(data) ? data.map(mapDatasetRow) : [];
}
export async function getRequest(type: RequestType, id: string): Promise<DistillationRequest | DatasetRequest | null> {
const table = type === "distillation" ? "distillation_requests" : "dataset_requests";
const { data, error } = await supabaseRest<any[]>(`/rest/v1/${table}`, {
query: {
select: "*",
id: `eq.${id}`,
},
});
if (error) {
throw new Error(error.message);
}
const row = Array.isArray(data) ? data[0] : null;
if (!row) return null;
return type === "distillation" ? mapDistillationRow(row) : mapDatasetRow(row);
}
export async function updateDistillationRequest(
id: string,
updates: Partial<Pick<DistillationRequest, "sourceDataset" | "studentModel" | "additionalNotes">>
): Promise<DistillationRequest | null> {
const body: Record<string, any> = {};
if (typeof updates.sourceDataset === "string") body.source_dataset = updates.sourceDataset;
if (typeof updates.studentModel === "string") body.student_model = updates.studentModel;
if (typeof updates.additionalNotes === "string") body.additional_notes = updates.additionalNotes;
const { data, error } = await supabaseRest<any[]>("/rest/v1/distillation_requests", {
method: "PATCH",
body: JSON.stringify(body),
query: { select: "*", id: `eq.${id}` },
preferReturn: "representation",
requireServiceRole: true,
});
if (error) {
throw new Error(error.message);
}
const row = Array.isArray(data) ? data[0] : null;
return row ? mapDistillationRow(row) : null;
}
export async function updateDatasetRequest(
id: string,
updates: Partial<Pick<DatasetRequest, "sourceModel" | "datasetSize" | "reasoningDepth" | "topics" | "additionalNotes">>
): Promise<DatasetRequest | null> {
const body: Record<string, any> = {};
if (typeof updates.sourceModel === "string") body.source_model = updates.sourceModel;
if (typeof updates.datasetSize === "string") body.dataset_size = updates.datasetSize;
if (typeof updates.reasoningDepth === "string") body.reasoning_depth = updates.reasoningDepth;
if (Array.isArray(updates.topics)) body.topics = updates.topics.map(String);
if (typeof updates.additionalNotes === "string") body.additional_notes = updates.additionalNotes;
const { data, error } = await supabaseRest<any[]>("/rest/v1/dataset_requests", {
method: "PATCH",
body: JSON.stringify(body),
query: { select: "*", id: `eq.${id}` },
preferReturn: "representation",
requireServiceRole: true,
});
if (error) {
throw new Error(error.message);
}
const row = Array.isArray(data) ? data[0] : null;
return row ? mapDatasetRow(row) : null;
}
export async function updateRequestStatus(
type: RequestType,
id: string,
status: "pending" | "in_progress" | "completed"
): Promise<boolean> {
const table = type === "distillation" ? "distillation_requests" : "dataset_requests";
const { data, error } = await supabaseRest<any[]>(`/rest/v1/${table}`, {
method: "PATCH",
body: JSON.stringify({ status }),
query: { select: "id", id: `eq.${id}` },
preferReturn: "representation",
requireServiceRole: true,
});
if (error) {
throw new Error(error.message);
}
return Array.isArray(data) ? Boolean(data[0]?.id) : false;
}
export async function deleteRequest(type: RequestType, id: string): Promise<boolean> {
await supabaseRest("/rest/v1/request_comments", {
method: "DELETE",
query: {
request_type: `eq.${type}`,
request_id: `eq.${id}`,
},
requireServiceRole: true,
});
const table = type === "distillation" ? "distillation_requests" : "dataset_requests";
const { data, error } = await supabaseRest<any[]>(`/rest/v1/${table}`, {
method: "DELETE",
body: null,
query: { select: "id", id: `eq.${id}` },
preferReturn: "representation",
requireServiceRole: true,
});
if (error) {
throw new Error(error.message);
}
return Array.isArray(data) ? Boolean(data[0]?.id) : false;
}
export async function getThread(type: RequestType, id: string): Promise<DiscussionThread> {
const key = `${type}:${id}`;
const { data, error } = await supabaseRest<any[]>("/rest/v1/request_comments", {
query: {
select: "*",
request_type: `eq.${type}`,
request_id: `eq.${id}`,
order: "created_at.asc",
},
});
if (error) {
throw new Error(error.message);
}
return {
key,
requestType: type,
requestId: id,
comments: Array.isArray(data) ? data.map(mapCommentRow) : [],
};
}
export async function addAdminComment(type: RequestType, id: string, body: string, ownerId: string): Promise<DiscussionComment> {
const { data, error } = await supabaseRest<any[]>("/rest/v1/request_comments", {
method: "POST",
body: JSON.stringify({
request_type: type,
request_id: id,
body,
author: "TeichAI",
role: "admin",
owner_id: ownerId,
}),
query: { select: "*" },
preferReturn: "representation",
requireServiceRole: true,
});
if (error) {
throw new Error(error.message);
}
const row = Array.isArray(data) ? data[0] : null;
if (!row) {
throw new Error("Failed to create comment");
}
return mapCommentRow(row);
}
export async function addUserComment(
type: RequestType,
id: string,
body: string,
author: string | undefined,
ownerId: string
): Promise<DiscussionComment> {
const { data, error } = await supabaseRest<any>("/rest/v1/request_comments", {
method: "POST",
body: JSON.stringify({
request_type: type,
request_id: id,
body,
author: author?.trim() ? author.trim() : "Anonymous",
role: "user",
owner_id: ownerId,
}),
query: { select: "*" },
preferReturn: "representation",
acceptObject: true,
});
if (error) {
throw new Error(error.message);
}
if (!data) {
throw new Error("Failed to create comment");
}
return mapCommentRow(data);
}
export async function updateComment(
type: RequestType,
requestId: string,
commentId: string,
body: string
): Promise<DiscussionComment | null> {
const { data, error } = await supabaseRest<any[]>("/rest/v1/request_comments", {
method: "PATCH",
body: JSON.stringify({ body, edited_at: new Date().toISOString() }),
query: {
select: "*",
id: `eq.${commentId}`,
request_type: `eq.${type}`,
request_id: `eq.${requestId}`,
},
preferReturn: "representation",
requireServiceRole: true,
});
if (error) {
throw new Error(error.message);
}
const row = Array.isArray(data) ? data[0] : null;
return row ? mapCommentRow(row) : null;
}
export async function deleteComment(
type: RequestType,
requestId: string,
commentId: string
): Promise<boolean> {
const { data, error } = await supabaseRest<any[]>("/rest/v1/request_comments", {
method: "DELETE",
body: null,
query: {
select: "id",
id: `eq.${commentId}`,
request_type: `eq.${type}`,
request_id: `eq.${requestId}`,
},
preferReturn: "representation",
requireServiceRole: true,
});
if (error) {
throw new Error(error.message);
}
return Array.isArray(data) ? Boolean(data[0]?.id) : false;
}
export async function addDistillationRequest(
request: Omit<DistillationRequest, "id" | "upvotes" | "votedIps" | "createdAt" | "status">
): Promise<DistillationRequest> {
const { data, error } = await supabaseRest<any>("/rest/v1/distillation_requests", {
method: "POST",
body: JSON.stringify({
source_dataset: request.sourceDataset,
student_model: request.studentModel,
submitter_name: request.submitterName ? request.submitterName : null,
additional_notes: request.additionalNotes,
owner_id: request.ownerId,
}),
query: { select: "*" },
preferReturn: "representation",
acceptObject: true,
});
if (error) {
throw new Error(error.message);
}
if (!data) {
throw new Error("Failed to create request");
}
return mapDistillationRow(data);
}
export async function addDatasetRequest(
request: Omit<DatasetRequest, "id" | "upvotes" | "votedIps" | "createdAt" | "status">
): Promise<DatasetRequest> {
const { data, error } = await supabaseRest<any>("/rest/v1/dataset_requests", {
method: "POST",
body: JSON.stringify({
source_model: request.sourceModel,
submitter_name: request.submitterName ? request.submitterName : null,
dataset_size: request.datasetSize,
reasoning_depth: request.reasoningDepth,
topics: request.topics,
additional_notes: request.additionalNotes,
owner_id: request.ownerId,
}),
query: { select: "*" },
preferReturn: "representation",
acceptObject: true,
});
if (error) {
throw new Error(error.message);
}
if (!data) {
throw new Error("Failed to create request");
}
return mapDatasetRow(data);
}
export async function upvoteDistillation(
id: string,
ip: string
): Promise<{ success: boolean; upvotes: number; action?: "upvoted" | "unvoted" }> {
const { data, error } = await supabaseRest<any[]>("/rest/v1/rpc/toggle_upvote_distillation", {
method: "POST",
body: JSON.stringify({ request_id: id, voter_ip: ip }),
});
if (error) {
throw new Error(error.message);
}
const row = Array.isArray(data) ? data[0] : null;
if (!row) {
return { success: false, upvotes: 0 };
}
return {
success: Boolean(row.success),
upvotes: typeof row.upvotes === "number" ? row.upvotes : 0,
action: row.action === "upvoted" || row.action === "unvoted" ? row.action : undefined,
};
}
export async function upvoteDataset(
id: string,
ip: string
): Promise<{ success: boolean; upvotes: number; action?: "upvoted" | "unvoted" }> {
const { data, error } = await supabaseRest<any[]>("/rest/v1/rpc/toggle_upvote_dataset", {
method: "POST",
body: JSON.stringify({ request_id: id, voter_ip: ip }),
});
if (error) {
throw new Error(error.message);
}
const row = Array.isArray(data) ? data[0] : null;
if (!row) {
return { success: false, upvotes: 0 };
}
return {
success: Boolean(row.success),
upvotes: typeof row.upvotes === "number" ? row.upvotes : 0,
action: row.action === "upvoted" || row.action === "unvoted" ? row.action : undefined,
};
}