| import { resolveModel, sanitizeSettings } from "../settings"; |
| import type { AnalysisDetails, AnalysisJob, AnalysisKind, AppSettings } from "../types"; |
| import { apiFetch, downloadBlob } from "./http"; |
|
|
| export interface AnalysisOptions { |
| kind: AnalysisKind; |
| optimizeTask: boolean; |
| strictFullMarks: boolean; |
| ignoreTaskComplexityForFullMarks: boolean; |
| feedback: string; |
| } |
|
|
| export async function createAnalysisJob(files: File[], requestedMode: AnalysisKind): Promise<{ |
| jobId: string; |
| items: AnalysisJob["items"]; |
| }> { |
| const form = new FormData(); |
| form.append("requestedMode", requestedMode); |
| files.forEach((file) => form.append("files", file, file.name)); |
| const response = await fetch("/api/analysis/jobs", { method: "POST", body: form }); |
| const payload = await response.json().catch(() => null); |
| if (!response.ok || !payload || payload.code !== 0) { |
| throw new Error(payload?.msg || `HTTP ${response.status}`); |
| } |
| return payload.data; |
| } |
|
|
| export async function startAnalysisJob(jobId: string, settings: AppSettings, options: AnalysisOptions): Promise<void> { |
| await apiFetch("/api/analysis/jobs/" + encodeURIComponent(jobId) + "/start", { |
| method: "POST", |
| headers: { "Content-Type": "application/json" }, |
| body: JSON.stringify({ optionsSnapshot: buildOptionsSnapshot(settings, options) }), |
| }); |
| } |
|
|
| export async function getAnalysisJob(jobId: string): Promise<AnalysisJob> { |
| return apiFetch("/api/analysis/jobs/" + encodeURIComponent(jobId)); |
| } |
|
|
| export async function getAnalysisItemResult(jobId: string, itemId: string): Promise<AnalysisDetails> { |
| return apiFetch("/api/analysis/jobs/" + encodeURIComponent(jobId) + "/items/" + encodeURIComponent(itemId) + "/result"); |
| } |
|
|
| export async function cancelAnalysisJob(jobId: string): Promise<void> { |
| await apiFetch("/api/analysis/jobs/" + encodeURIComponent(jobId) + "/cancel", { method: "POST" }); |
| } |
|
|
| export async function retryAnalysisItem(jobId: string, itemId: string): Promise<void> { |
| await apiFetch("/api/analysis/jobs/" + encodeURIComponent(jobId) + "/items/" + encodeURIComponent(itemId) + "/retry", { |
| method: "POST", |
| }); |
| } |
|
|
| export async function downloadAnalysisItem(jobId: string, itemId: string, filename: string): Promise<void> { |
| await downloadBlob( |
| "/api/analysis/jobs/" + encodeURIComponent(jobId) + "/items/" + encodeURIComponent(itemId) + "/download", |
| filename.replace(/\.zip$/i, "") + ".task-package.zip", |
| ); |
| } |
|
|
| export async function downloadAnalysisJob(jobId: string): Promise<void> { |
| await downloadBlob("/api/analysis/jobs/" + encodeURIComponent(jobId) + "/download-all", "all-results.zip"); |
| } |
|
|
| export function buildOptionsSnapshot(settings: AppSettings, options: AnalysisOptions): Record<string, unknown> { |
| const cleanSettings = sanitizeSettings(settings); |
| return { |
| requestedMode: options.kind, |
| model: resolveModel(cleanSettings), |
| baseURL: cleanSettings.baseURL, |
| apiKey: cleanSettings.apiKey, |
| apiMode: cleanSettings.apiMode, |
| concurrency: cleanSettings.concurrency, |
| temperature: cleanSettings.temperature, |
| topP: cleanSettings.topP, |
| maxTokens: cleanSettings.maxTokens, |
| enableThinking: cleanSettings.enableThinking, |
| clearThinking: cleanSettings.clearThinking, |
| ruleProfile: cleanSettings.ruleProfile, |
| optimizeTask: options.optimizeTask, |
| feedback: options.feedback, |
| strictFullMarks: options.strictFullMarks, |
| ignoreTaskComplexityForFullMarks: options.ignoreTaskComplexityForFullMarks, |
| }; |
| } |
|
|