import type { AsyncEvalRunStartResponse, AsyncEvalRunStatusResponse, AutoGenPersonalityCatalogResponse, AutoGenHistoryResponse, AutoGenHistoryRecord, AutoGenMode, AutoRunAnnotationsResponse, AutoRunAnnotationRecord, AutoRunDetailResponse, AutoRunDialogResponse, AutoRunHistoryResponse, AutoRunPostAnalysisResponse, AssistantAnnotationsResponse, AssistantAnnotationRecord, AssistantMessageResultState, AssistantConversationItem, ConnectionState, HistoryItem, ManualCaseDecision, NormalizeResultState, PromptState, RuntimeRun } from "../state/types"; const PREFIX = "/api"; async function request(path: string, init?: RequestInit): Promise { const response = await fetch(`${PREFIX}${path}`, { ...init, headers: { "Content-Type": "application/json", ...(init?.headers ?? {}) } }); const payload = (await response.json()) as T & { error?: { message?: string } }; if (!response.ok) { const message = (payload as { error?: { message?: string } }).error?.message ?? "Ошибка запроса"; throw new Error(message); } return payload; } export const apiClient = { async loadSharedConnectionConfig(): Promise<{ ok: boolean; connection: Omit | null; updated_at: string | null; exists: boolean; }> { return request("/llm/shared-connection"); }, async saveSharedConnectionConfig(connection: ConnectionState): Promise<{ ok: boolean; connection: Omit; updated_at: string; }> { return request("/llm/shared-connection", { method: "POST", body: JSON.stringify({ llmProvider: connection.llmProvider, model: connection.model, baseUrl: connection.baseUrl, temperature: connection.temperature, maxOutputTokens: connection.maxOutputTokens }) }); }, async listModels(connection: ConnectionState): Promise<{ ok: boolean; models: string[]; count: number; timestamp: string }> { return request("/llm/models", { method: "POST", body: JSON.stringify({ llmProvider: connection.llmProvider, apiKey: connection.apiKey, model: connection.model, baseUrl: connection.baseUrl }) }); }, async testConnection(connection: ConnectionState): Promise<{ ok: boolean; provider: "openai" | "local"; model: string; model_found: boolean | null; models_count: number | null; timestamp: string; }> { return request("/llm/test-connection", { method: "POST", body: JSON.stringify({ llmProvider: connection.llmProvider, apiKey: connection.apiKey, model: connection.model, baseUrl: connection.baseUrl }) }); }, async normalize(params: { connection: ConnectionState; prompts: PromptState; promptVersion?: string; query: { userQuestion: string; periodHint?: string; businessContext?: string; expectedRoute?: string; }; saveAsTestCase?: boolean; useMock?: boolean; }): Promise { return request("/normalize", { method: "POST", body: JSON.stringify({ llmProvider: params.connection.llmProvider, apiKey: params.connection.apiKey, model: params.connection.model, baseUrl: params.connection.baseUrl, temperature: params.connection.temperature, maxOutputTokens: params.connection.maxOutputTokens, promptVersion: params.promptVersion, systemPrompt: params.prompts.systemPrompt, developerPrompt: params.prompts.developerPrompt, domainPrompt: params.prompts.domainPrompt, fewShotExamples: params.prompts.fewShotExamples, userQuestion: params.query.userQuestion, context: { period_hint: params.query.periodHint ?? "", business_context: params.query.businessContext ?? "", expected_route: params.query.expectedRoute ?? "" }, saveAsTestCase: Boolean(params.saveAsTestCase), useMock: Boolean(params.useMock) }) }); }, async loadHistory(): Promise<{ ok: boolean; items: HistoryItem[] }> { return request("/history"); }, async loadTrace(traceId: string): Promise<{ ok: boolean; trace: unknown }> { return request(`/history/${traceId}`); }, async loadPresets(): Promise<{ ok: boolean; presets: Array<{ id: string; name: string; prompt_version: string; systemPrompt: string; developerPrompt: string; domainPrompt: string; schemaNotes?: string; fewShotExamples?: string; }>; }> { return request("/presets"); }, async savePreset(input: { id?: string; name: string; prompt_version?: string; systemPrompt: string; developerPrompt: string; domainPrompt: string; schemaNotes?: string; fewShotExamples?: string; }): Promise<{ ok: boolean }> { return request("/presets/save", { method: "POST", body: JSON.stringify(input) }); }, async runEval(input: { connection: ConnectionState; prompts: PromptState; promptVersion?: string; caseIds?: string[]; useMock?: boolean; mode?: "standard" | "single-pass-strict"; caseSetFile?: string; rawQuestions?: string; evalTarget?: "normalizer" | "assistant_stage1" | "assistant_stage2" | "assistant_p0"; compareWithReportFile?: string; analysisDate?: string; }): Promise<{ ok: boolean; report: unknown }> { return request("/eval/run", { method: "POST", body: JSON.stringify({ normalizeConfig: { llmProvider: input.connection.llmProvider, apiKey: input.connection.apiKey, model: input.connection.model, baseUrl: input.connection.baseUrl, temperature: input.connection.temperature, maxOutputTokens: input.connection.maxOutputTokens, promptVersion: input.promptVersion, systemPrompt: input.prompts.systemPrompt, developerPrompt: input.prompts.developerPrompt, domainPrompt: input.prompts.domainPrompt, fewShotExamples: input.prompts.fewShotExamples }, caseIds: input.caseIds, useMock: Boolean(input.useMock), mode: input.mode ?? "standard", caseSetFile: input.caseSetFile, rawQuestions: input.rawQuestions, eval_target: input.evalTarget, compare_with_report_file: input.compareWithReportFile, analysis_date: input.analysisDate }) }); }, async startEvalRunAsync(input: { connection: ConnectionState; prompts: PromptState; promptVersion?: string; caseIds?: string[]; useMock?: boolean; mode?: "standard" | "single-pass-strict"; caseSetFile?: string; rawQuestions?: string; evalTarget?: "normalizer" | "assistant_stage1" | "assistant_stage2" | "assistant_p0"; compareWithReportFile?: string; questions?: string[]; scenarioQuestions?: string[]; scenarioTitle?: string; analysisDate?: string; }): Promise { return request("/eval/run-async/start", { method: "POST", body: JSON.stringify({ normalizeConfig: { llmProvider: input.connection.llmProvider, apiKey: input.connection.apiKey, model: input.connection.model, baseUrl: input.connection.baseUrl, temperature: input.connection.temperature, maxOutputTokens: input.connection.maxOutputTokens, promptVersion: input.promptVersion, systemPrompt: input.prompts.systemPrompt, developerPrompt: input.prompts.developerPrompt, domainPrompt: input.prompts.domainPrompt, fewShotExamples: input.prompts.fewShotExamples }, caseIds: input.caseIds, useMock: Boolean(input.useMock), mode: input.mode ?? "standard", caseSetFile: input.caseSetFile, rawQuestions: input.rawQuestions, eval_target: input.evalTarget, compare_with_report_file: input.compareWithReportFile, questions: input.questions, scenarioQuestions: input.scenarioQuestions, scenarioTitle: input.scenarioTitle, analysis_date: input.analysisDate }) }); }, async loadEvalRunAsyncStatus(jobId: string): Promise { return request(`/eval/run-async/${encodeURIComponent(jobId)}`); }, async startRun(): Promise<{ ok: boolean; run: RuntimeRun; runId: string; sessionId: string; status: string }> { return request("/accounting-agent/v1/runs/start", { method: "POST", body: JSON.stringify({ initiator: "ndc_operator", source: "gui" }) }); }, async finishRun(runId: string): Promise<{ ok: boolean; run: RuntimeRun }> { return request("/accounting-agent/v1/runs/finish", { method: "POST", body: JSON.stringify({ runId, status: "DONE", source: "gui", reason: "Остановлено оператором из GUI" }) }); }, async listRuns(): Promise<{ ok: boolean; items: RuntimeRun[] }> { return request("/accounting-agent/v1/runs"); }, async listResults(): Promise<{ ok: boolean; items: unknown[] }> { return request("/accounting-agent/v1/results"); }, async runTrace(runId: string): Promise<{ ok: boolean; items: unknown[] }> { return request(`/accounting-agent/v1/trace/run/${runId}`); }, async sendAssistantMessage(input: { connection: ConnectionState; prompts: PromptState; userMessage: string; sessionId?: string; promptVersion?: string; context?: { periodHint?: string; businessContext?: string; }; useMock?: boolean; }): Promise { return request("/assistant/message", { method: "POST", body: JSON.stringify({ session_id: input.sessionId ?? "", mode: "assistant", message: input.userMessage, user_message: input.userMessage, llmProvider: input.connection.llmProvider, apiKey: input.connection.apiKey, model: input.connection.model, baseUrl: input.connection.baseUrl, temperature: input.connection.temperature, maxOutputTokens: input.connection.maxOutputTokens, promptVersion: input.promptVersion ?? "address_query_runtime_v1", systemPrompt: input.prompts.systemPrompt, developerPrompt: input.prompts.developerPrompt, domainPrompt: input.prompts.domainPrompt, fewShotExamples: input.prompts.fewShotExamples, context: { period_hint: input.context?.periodHint ?? "", business_context: input.context?.businessContext ?? "" }, useMock: Boolean(input.useMock) }) }); }, async loadAssistantSession(sessionId: string): Promise<{ ok: boolean; session: { items: AssistantConversationItem[] } }> { return request(`/assistant/session/${sessionId}`); }, async saveAutoRunAssistantSession(input: { session_id: string; title: string; generated_by?: string; context?: { llm_provider?: string; model?: string; assistant_prompt_version?: string; decomposition_prompt_version?: string; prompt_fingerprint?: string; }; }): Promise<{ ok: boolean; generation: AutoGenHistoryRecord }> { return request("/autoruns/autogen/save-assistant-session", { method: "POST", body: JSON.stringify(input) }); }, async loadAssistantAnnotations(input?: { session_id?: string; limit?: number; }): Promise { const params = new URLSearchParams(); if (input?.session_id) params.set("session_id", input.session_id); if (typeof input?.limit === "number") params.set("limit", String(input.limit)); const query = params.toString(); return request(`/assistant/annotations${query ? `?${query}` : ""}`); }, async saveAssistantAnnotation(input: { session_id: string; message_index: number; rating: number; comment: string; annotation_author?: string; }): Promise<{ ok: boolean; annotation: AssistantAnnotationRecord }> { return request("/assistant/annotations", { method: "POST", body: JSON.stringify(input) }); }, async loadAutoRunsHistory(input?: { from?: string; to?: string; target?: string; mode?: string; use_mock?: "any" | "true" | "false"; prompt_contains?: string; limit?: number; scan_limit?: number; }): Promise { const params = new URLSearchParams(); if (input?.from) params.set("from", input.from); if (input?.to) params.set("to", input.to); if (input?.target) params.set("target", input.target); if (input?.mode) params.set("mode", input.mode); if (input?.use_mock) params.set("use_mock", input.use_mock); if (input?.prompt_contains) params.set("prompt_contains", input.prompt_contains); if (typeof input?.limit === "number") params.set("limit", String(input.limit)); if (typeof input?.scan_limit === "number") params.set("scan_limit", String(input.scan_limit)); const query = params.toString(); return request(`/autoruns/history${query ? `?${query}` : ""}`); }, async loadAutoRunDetail(runId: string): Promise { return request(`/autoruns/history/${encodeURIComponent(runId)}`); }, async loadAutoRunCaseDialog(runId: string, caseId: string): Promise { return request(`/autoruns/history/${encodeURIComponent(runId)}/case/${encodeURIComponent(caseId)}/dialog`); }, async loadAutoRunAnnotations(input?: { run_id?: string; case_id?: string; min_rating?: number; manual_case_decision?: ManualCaseDecision | "all"; limit?: number; }): Promise { const params = new URLSearchParams(); if (input?.run_id) params.set("run_id", input.run_id); if (input?.case_id) params.set("case_id", input.case_id); if (typeof input?.min_rating === "number") params.set("min_rating", String(input.min_rating)); if (input?.manual_case_decision) params.set("manual_case_decision", input.manual_case_decision); if (typeof input?.limit === "number") params.set("limit", String(input.limit)); const query = params.toString(); return request(`/autoruns/annotations${query ? `?${query}` : ""}`); }, async saveAutoRunAnnotation(input: { run_id: string; case_id: string; message_index: number; rating: number; comment: string; manual_case_decision: ManualCaseDecision; annotation_author?: string; }): Promise<{ ok: boolean; annotation: AutoRunAnnotationRecord; case_annotation_stats: { count: number; latest_at: string | null; avg_rating: number | null } | null }> { return request("/autoruns/annotations", { method: "POST", body: JSON.stringify(input) }); }, async updateAutoRunAnnotation(input: { annotation_id: string; resolved: boolean; resolved_by?: string; }): Promise<{ ok: boolean; annotation: AutoRunAnnotationRecord; case_annotation_stats: { count: number; latest_at: string | null; avg_rating: number | null } | null }> { return request(`/autoruns/annotations/${encodeURIComponent(input.annotation_id)}`, { method: "PATCH", body: JSON.stringify({ resolved: input.resolved, resolved_by: input.resolved_by }) }); }, async loadAutoRunPostAnalysis(input?: { run_id?: string; limit_per_queue?: number; annotation_limit?: number; scan_limit?: number; from?: string; to?: string; target?: string; mode?: string; use_mock?: "any" | "true" | "false"; prompt_contains?: string; }): Promise { const params = new URLSearchParams(); if (input?.run_id) params.set("run_id", input.run_id); if (typeof input?.limit_per_queue === "number") params.set("limit_per_queue", String(input.limit_per_queue)); if (typeof input?.annotation_limit === "number") params.set("annotation_limit", String(input.annotation_limit)); if (typeof input?.scan_limit === "number") params.set("scan_limit", String(input.scan_limit)); if (input?.from) params.set("from", input.from); if (input?.to) params.set("to", input.to); if (input?.target) params.set("target", input.target); if (input?.mode) params.set("mode", input.mode); if (input?.use_mock) params.set("use_mock", input.use_mock); if (input?.prompt_contains) params.set("prompt_contains", input.prompt_contains); const query = params.toString(); return request(`/autoruns/post-analysis${query ? `?${query}` : ""}`); }, async loadAutoRunAutogenHistory(input?: { mode?: AutoGenMode; limit?: number; }): Promise { const params = new URLSearchParams(); if (input?.mode) params.set("mode", input.mode); if (typeof input?.limit === "number") params.set("limit", String(input.limit)); const query = params.toString(); return request(`/autoruns/autogen/history${query ? `?${query}` : ""}`); }, async loadAutoRunAutogenPersonalityCatalog(): Promise { return request("/autoruns/autogen/personality-catalog"); }, async updateAutoRunAutogenQuestions(input: { generation_id: string; questions: string[]; }): Promise<{ ok: boolean; generation: AutoGenHistoryRecord }> { return request(`/autoruns/autogen/history/${encodeURIComponent(input.generation_id)}/questions`, { method: "PATCH", body: JSON.stringify({ questions: input.questions }) }); }, async deleteAutoRunAutogenHistoryRecord(generationId: string): Promise<{ ok: boolean; generation_id: string; deleted_files: string[]; }> { return request(`/autoruns/autogen/history/${encodeURIComponent(generationId)}`, { method: "DELETE" }); }, async generateAutoRunQuestions(input: { mode: AutoGenMode; count: number; domain?: string; persist_to_eval_cases?: boolean; generated_by?: string; llm?: { llm_provider?: "openai" | "local"; api_key?: string; model?: string; base_url?: string; temperature?: number; max_output_tokens?: number; }; context?: { llm_provider?: string; model?: string; assistant_prompt_version?: string; decomposition_prompt_version?: string; prompt_fingerprint?: string; autogen_personality_id?: string; autogen_personality_prompt?: string; }; }): Promise<{ ok: boolean; generation: AutoGenHistoryRecord }> { return request("/autoruns/autogen/generate", { method: "POST", body: JSON.stringify(input) }); } };