### Bugfixes — Agent Chat 'Думаю' State Leak - fix(agent-chat): loadHistory() now resets streamingState/idle + cancels stale submission — prevents 'Думаю' state leak across conversation switches - fix(agent-chat): onDisconnected/onDisconnectedPermanent cascade to streamingState — prevents permanent hang on connection loss during stream - fix(agent-chat): guard on isLoadingHistory — prevents false commit of 'agent unavailable' fallback when switching conversations - fix(agent-chat): remove race in _sendNow empty-response check vs Svelte microtask (duplicate logic removed, handles correctly) - fix(stream-processor): confirm_resolved now appends msg.text to partialText instead of dropping it ### Bugfixes — Backend PDF Upload - fix(document-parser): _detect_format_by_magic() — reads file header magic bytes as fallback when Gradio loses filename - fix(document-parser): improved name extraction — tries orig_name, path stem - fix(document-parser): @RELATION AgentChatTypes -> AgentChat.Types ### HITL Flow & Agent Chat Improvements - feat(agent): HITL resume confirm/deny with userId/userJwt/envId propagation - feat(agent): confirm_required metadata fallback via aget_state() after 'Event loop is closed' error during interrupt - feat(agent): interrupt_before re-enabled via AGENT_CONFIRM_TOOLS env var - feat(frontend): debug panel with connection/stream state monitoring - feat(frontend): AgentChatModel constructor options + onBeforeSend callback - feat(frontend): crypto.randomUUID() for local conversation ID on first send ### Backend Agent Refactoring - refactor(agent): langgraph_setup — monkey-patch for PydanticSerializationError - refactor(agent): tools.py — dual identity headers, expanded tool set - refactor(agent): run.py — _find_free_port, Gradio server port fallback - refactor(agent): app.py — file size validation, message truncation, HITL path ### Frontend - feat(dashboard-hub): DashboardHubModel with filters, pagination, git actions - feat(ui): DateRangeFilter component - feat(i18n): new dashboard keys; cache tooltips fix - fix(i18n): full run tooltips — cache is NOT ignored ### Semantic Protocol - chore(agents): update all agents with canonical format - chore(skills): sync semantics-core, semantics-contracts, molecular-cot-logging ### Housekeeping - chore: remove stale semantic reports (10 files, Jan 2026) - chore: update 033-gradio-agent-chat specs, contracts, UX, tasks, tests - chore: add .agents/ directory (mirrors .opencode/ agent layouts) - chore: update run.sh with DEV_MODE, port management
4.5 KiB
4.5 KiB
#region AgentChat.Contracts [C:4] [TYPE ADR] [SEMANTICS contracts,modules,agent-chat,langgraph,final]
@BRIEF Final module contracts — LangGraph create_react_agent(), native LangChain @tool, static interrupt_before HITL, PostgresSaver, structured JSON metadata, dual-identity RBAC, compact per-turn tool subsets.
Backend
| Contract | C | File | Notes |
|---|---|---|---|
| AgentChat.GradioApp | C4 | backend/src/agent/app.py |
gr.ChatInterface(type="messages", multimodal=True, additional_inputs=[gr.Textbox("conversation_id"), gr.Textbox("action")], examples=[["Покажи дашборды",null,null],["Статус системы",null,null]]). Handler: def handler(message, history, request: gr.Request, conversation_id=None, action=None). Per-user lock via in-memory dict (no global concurrency_limit — Gradio handles concurrent users by default). |
| AgentChat.GradioApp.Handler | C4 | ↑ | Creates create_react_agent() with PostgresSaver and a compact tool subset. astream_events(config={"configurable":{"thread_id":conversation_id}}). Resume: detects action="confirm"/"deny" in additional_inputs, loads checkpoint, recreates graph with interrupt_before=[] to avoid repeated pause, and continues the checkpoint stream. |
| AgentChat.LangGraph.Setup | C4 | backend/src/agent/langgraph_setup.py |
create_react_agent(model, tools=<subset>, checkpointer=PostgresSaver(conn_string), interrupt_before=<dangerous tools or []>). No RunnableWithMessageHistory; history/checkpoint continuity is keyed by thread_id=conversation_id. |
| AgentChat.Tools | C4 | backend/src/agent/tools.py |
17 native @tool functions. Each: Pydantic BaseModel args_schema, calls FastAPI REST with dual-identity headers (Authorization: service JWT + X-User-JWT: user JWT, fallback to user JWT as Authorization if service JWT absent). Includes get_tools_for_query() for context-budgeted subset selection. |
| AgentChat.Middleware | C3 | backend/src/agent/middleware.py |
LoggingMiddleware only (audit trail). |
| AgentChat.Document.Parser | C3 | backend/src/agent/document_parser.py |
pdfplumber (PDF) + openpyxl (XLSX). |
| AgentChat.Api.Conversations | C3 | backend/src/api/routes/agent_conversations.py |
CRUD (list, history, create, archive) + multi-tab gate GET .../conversations/{id}/active. |
| AgentChat.Api.ServiceToken | C3 | backend/src/api/routes/auth.py |
POST /api/auth/service-token — returns service JWT (role agent). |
| Models.Agent | C2 | backend/src/models/agent.py |
AgentConversation, AgentMessage. |
| Schemas.Agent | C1 | backend/src/schemas/agent.py |
Pydantic: ConversationItem, ConversationListResponse, MessageItem, HistoryResponse, DeleteResponse. |
Frontend
| Contract | C | File | Notes |
|---|---|---|---|
| AgentChat.Model | C4 | frontend/src/lib/models/AgentChatModel.svelte.ts |
submit("/chat", {text,files}, [conversationId, action]) lifecycle. Structured ChatMessage.metadata parsing. HITL resume via second submit with additional_inputs[1]="confirm"/"deny" and immediate streaming state. No tabRole, no follower. |
| AgentChat.Panel | C4 | frontend/src/lib/components/agent/AgentChat.svelte |
Client.connect("${window.location.origin}/api/agent/gradio"), submit(), metadata-based rendering of tool cards + confirmation cards, debug/reference block. |
| AgentChat.Page | C3 | frontend/src/routes/agent/+page.svelte |
Full-page route hosting current AgentChat.svelte. |
| AgentChat.ConversationList | C3 | frontend/src/lib/components/assistant/ConversationList.svelte |
Search, infinite scroll, date grouping, archive action. |
| AgentChat.ToolCallCard | C2 | frontend/src/lib/components/assistant/ToolCallCard.svelte |
Props from metadata.type="tool_start"/"tool_end"/"tool_error". |
| AgentChat.ConfirmationCard | C3 | frontend/src/lib/components/assistant/ConfirmationCard.svelte |
Renders on metadata.type="confirm_required". Calls second submit() with additional_inputs=[conversation_id, "confirm"/"deny"]. |
Contracts Removed (vs prior versions)
AgentChat.LangChain.Setup→ renamed toAgentChat.LangGraph.SetupHumanInTheLoopMiddleware→ replaced byinterrupt_before=DANGEROUS_TOOLS(LangGraph native)__resume__field → replaced byadditional_inputs[1]="confirm"/"deny"- Full tool-catalog injection on every prompt → replaced by
get_tools_for_query()compact subset selection RunnableWithMessageHistoryrequirement → replaced by explicit persisted conversation records plus LangGraph checkpoints keyed bythread_id
#endregion AgentChat.Contracts