fix(agent-chat): streaming state leak, document parser magic bytes, HITL flow

### 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
This commit is contained in:
2026-06-29 17:15:25 +03:00
parent ab3293ac0d
commit 576fff8cc6
115 changed files with 8948 additions and 1763 deletions

View File

@@ -138,6 +138,41 @@ class TestListTasks:
resp = client.get("/api/tasks?task_type=unsupported")
assert resp.status_code == 400
def test_with_search(self):
mock_tm = MagicMock()
mock_tm.get_tasks.return_value = []
from src.dependencies import get_task_manager
client = _make_client({get_task_manager: lambda: mock_tm})
resp = client.get("/api/tasks?search=backup")
assert resp.status_code == 200
mock_tm.get_tasks.assert_called_once()
assert mock_tm.get_tasks.call_args.kwargs["search"] == "backup"
def test_with_search_max_length(self):
mock_tm = MagicMock()
mock_tm.get_tasks.return_value = []
from src.dependencies import get_task_manager
client = _make_client({get_task_manager: lambda: mock_tm})
# max_length=200 on the Query param — this should pass
resp = client.get(f"/api/tasks?search={'a' * 200}")
assert resp.status_code == 200
def test_logs_cleared(self):
from src.core.task_manager import Task
mock_tm = MagicMock()
mock_task = MagicMock(spec=Task)
mock_task.id = "task-1"
mock_task.logs = ["log_entry_1", "log_entry_2"]
mock_tm.get_tasks.return_value = [mock_task]
from src.dependencies import get_task_manager
client = _make_client({get_task_manager: lambda: mock_tm})
resp = client.get("/api/tasks")
assert resp.status_code == 200
assert mock_task.logs == []
# ── get_task ──