| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
♻️ all code comments in english and code clean | 1 年前 | |
Recover interrupted tasks on service startup (#3847) * Recover interrupted tasks on service startup * Fix evaluation pure logic test stub * Increase startup recovery test coverage * Scope upload recovery by service and enforce single-replica restarts --------- Co-authored-by: root <root@DESKTOP-UARO3HF.localdomain> | 20 天前 | |
Recover interrupted tasks on service startup (#3847) * Recover interrupted tasks on service startup * Fix evaluation pure logic test stub * Increase startup recovery test coverage * Scope upload recovery by service and enforce single-replica restarts --------- Co-authored-by: root <root@DESKTOP-UARO3HF.localdomain> | 20 天前 | |
Feat hzw 20260810 (#3920) * feat:model page * feat: 接入方式优化-需要回退 * ♻️ Refactor: unify model edit dialog onto ModelAddDialogV2 - ModelAddDialogV2: add model prop for edit mode (prefill custom form from existing model, default to 自定义接入 tab, call updateSingleModel/updateManageTenantModel on submit instead of add) - modelConfig.tsx: handleCardEdit now renders ModelAddDialogV2 with model prop instead of ModelEditDialogV2 * Feature: model capacity auto-lookup, custom param validation, and type inference fixes Capacity suggestion (catalog -> bundled LiteLLM JSON -> default): - model_capacity_suggestion_service: remove LLM self-report fallback (dead code, providers without web search always return null); add _litellm_lookup reading the bundled LiteLLM model_prices_and_context_window.json (3818 models) as the second source; match by provider/name and bare-name final segment, preferring entries with both max_input and max_output - main Dockerfile: bundle LiteLLM JSON at build time (works offline / no VPN) - suggest_capacity: try LiteLLM bare-name match even when provider is uninferable (base_url still empty while typing) Model add/edit dialog (V2): - custom tab: debounced auto-lookup on model name (500ms) fills empty capacity fields only; configured tag reflects lookup result, not display_name presence - connectivity probe no longer mutates capacity fields; probe carries temperature/top_p/extra_params so invalid __custom__ params surface at verify time as a 400 instead of failing at runtime - __custom__ numeric strings coerce to numbers (top_k=50, not 50); fix .trim crash on numeric values in edit mode - batch tab: add client-side model name search filter; per-row connectivity fills capacity from suggestion - edit mode: onConnectivityChange reports probe result back to the model list so connect_status refreshes in place Model config list: - verifyModels now probes ALL models in the list (was: default-model selection only), updating rows in parallel - remove misleading provider model-count badge; fix ModelConnectStatus duplicate declaration; drop unused DEFAULT_* imports Type inference (_infer_model_type_from_name): - match full name AND final path segment so repo-prefixed ids from aggregators (BAAI/bge-m3, Pro/..., deepseek-ai/...) classify correctly - add contains-based rules aligned with develop TokenPony classifier: embedding/rerank/stt/tts mid-name, vlm3 (omni/video), vlm2 (image-gen keywords), vlm (vision/visual/ocr/vl-segment) Connectivity service: - port develop _embedding_url_candidates multi-candidate probe (normalized /embeddings URL first, then as-given) for embedding/multi_embedding - _config_to_context: __custom__ KV pairs flow into extra_body at runtime - openai_llm check_connectivity probe carries inference params Type fixes: AgentDraft includes model_params_override; ModelEditDialogV2 keyMap adds vlm4; agent-prompt model override config dialog typing * Fix: rename llmModels to availableLlmModels after develop merge (useModelList API rename) * Fix: normalize rerank probe URL to the rerank endpoint The batch-import connectivity probe passed the bare provider root (e.g. https://api.siliconflow.cn/v1/) straight to the rerank adapter, which POSTs the URL as-is -> 404 -> unavailable even though the model is fine. prepare_model_dict already appends /rerank when SAVING the model, so probe-time and save-time URLs disagreed. Mirror that munging in _perform_connectivity_check: dashscope roots get the api/v1 .../services/rerank/text-rerank/text-rerank path, others get {root}/rerank. Already-normalized URLs pass through untouched. This matches the embedding probe /embeddings normalization. * Fix: carry verified connect_status into batch-created model records Batch submit requires every enabled row to pass the connectivity probe (hasUnchecked gate), but the verified available result lived only in dialog state — the create endpoints never received it, so the backend reset connect_status to not_detected on insert and the freshly imported models showed as unverified in the list. The backend already honors this (create_model_for_tenant: connect_status = payload or NOT_DETECTED; ModelRequest has the field) — only the frontend was not sending it. Thread connectStatus through addCustomModel / createManageTenantModel request bodies and set it from the row state at batch submit time. * Remove legacy modify-or-delete models button and ModelDeleteDialog The button opened a 2000-line legacy panel whose single-row edit/delete duplicated the per-row actions (and used the old V1 edit dialog), and whose only unique capability was a narrow bulk-edit (same-provider key, timeout, capacity override). Bulk delete did not exist - deletion inside the panel was still one-by-one. - drop the top-bar button (Can model:update wrapper) - drop the capacity-coverage alert action that opened the same panel - remove isDeleteModalOpen state, ModelDeleteDialog import and instance - delete the orphaned ModelDeleteDialog.tsx (ModelEditDialog stays - it is still referenced by resource-manage ModelList) * Fix: show Chinese type labels for vlm2/vlm3/vlm4 in model list The type column rendered t(`model.type.${type}`) directly, but the locale files have no model.type.vlm2/vlm3/vlm4 keys (they are keyed by semantic name: imageGeneration / videoUnderstanding / audioUnderstanding), so those rows displayed the raw id string. Add the same id-to-semantic-key mapping the add dialog uses, covering all ten types. Also aligns vlm to the dialog label (image understanding) instead of the legacy model.type.vlm wording. * Fix: address CodeQL security alerts in provider fetch and catalog endpoints SSRF (critical) in openai_provider.get_models: the operator-supplied base_url was fetched as-is. Add _validate_provider_base_url guard before the request: scheme must be http/https, host required, private / link-local / multicast / reserved IP literals rejected (cloud metadata endpoints, internal routers). Plain DNS names and the documented localhost/127.0.0.1 local-LLM exemption are allowed. Validation errors flow through the existing _classify_provider_error path as provider fetch failures. Information exposure (medium x5) in model_managment_app catalog endpoints: the exception text was interpolated into the JSON response body, which can leak stack traces / internal details to the caller. Replace with fixed messages; the exception detail is already logged server-side via logger.warning. Affected: /catalog/all, /catalog/providers, /catalog/inference_field_specs, /catalog/providers/{provider}/models, /catalog/providers/{provider}/models/{model_name}. * Fix: address Copilot review findings in tests and catalog wiring Real bugs (blocked the unit-test CI job): - test_model_consts.py: corrupted multi-byte string literal (truncated mid-character) made the module unparseable; restore the intended default title assertion. - test_model_catalog_loader.py: read p.provider_key / get_model_profile(p.provider_key, ...) but the Pydantic ModelCatalogProviderInfo model exposes id; align to the actual field. Latent issues flagged by review: - model_managment_app.py: the catalog-import fallback handler logged via the module logger before it was initialized, raising NameError on the graceful-degradation path; log via logging.getLogger directly. - useModelCatalog.ts + types: provider summary declared provider_key/supported_model_types while /catalog/providers serializes id/supported_types (Pydantic dump). Align the frontend type and hook maps to the wire names. ModelCatalogModelEntry.provider_key stays as is - the /catalog/all model entries do carry provider_key. * Fix: catalog loader test must accept normalized model entries The loader normalizes each catalog model entry into a ModelCatalogProfile instance (not a raw dict), so asserting model_type in model_cfg fails with TypeError on the Pydantic model. Accept both the raw dict form and the normalized instance via getattr. Verified in-container: 8 passed. * Fix: sync model health tests with inference params and rerank URL normalization * Fix: sync model tests with unified provider dispatch and consts.model imports * Fix: register consts.model and nexent.core.agents stubs in tests blocked by model_management_db import chain * Fix: harden provider SSRF guard with post-DNS IP validation and restore TLS verification * Fix: resolve SonarCloud quality gate findings (complexity, log injection, warnings, duplication) * Fix: reduce cognitive complexity and eliminate duplicated blocks flagged by SonarCloud * Fix: remove legacy dialogs duplicated by V2, sanitize catalog logging, resolve remaining SonarCloud issues * Fix: sanitize catalog version with json.dumps and clear remaining SonarCloud issues * Fix: stop logging file-derived catalog version and flatten handleSave max-tokens logic * Fix: resolve SDK httpx Timeout class for httpx2-based OpenAI builds * Fix: route capacity suggestion through managed thread pool and make stopwords loading race-tolerant --------- Co-authored-by: hzw <hzw@qq.com> Co-authored-by: ljy <ljy@DESKTOP-65OBISN.(none)> | 8 天前 | |
🐛 Fix(evaluation): fix task list filtering for multiple agents (#3951) * fix(evaluation): support multi-agent task filtering Default the evaluation task list to all tenant agents, add searchable multi-select filtering with one JSON agent_ids parameter, and preserve the active filter after task creation. Co-authored-by: Codex <noreply@tool-provider.com> Generated-by: gpt-5-codex * refactor(evaluation): simplify agent id validation Use Pydantic strict JSON validation for the agent_ids query parameter while preserving the all-agents default and stable deduplication. Co-authored-by: Codex <noreply@tool-provider.com> Generated-by: gpt-5-codex | 3 天前 | |
✨ Feat: Add in-app notifications for agent repository review workflow (#3477) * ✨ Feat: Add in-app notifications for agent repository review workflow Notify publishers and reviewers on submit/approve/reject, with navbar bell UI, review opinion content, and deep-link navigation into agent space. * ✨ Feat: Add in-app notifications for agent repository review workflow Notify publishers and reviewers on submit/approve/reject, with navbar bell UI, review opinion content, and deep-link navigation into agent space. * ✨ Feat: Add in-app notifications for agent repository review workflow Notify publishers and reviewers on submit/approve/reject, with navbar bell UI, review opinion content, and deep-link navigation into agent space. * ✨ Feat: Add in-app notifications for agent repository review workflow Notify publishers and reviewers on submit/approve/reject, with navbar bell UI, review opinion content, and deep-link navigation into agent space. | 2 个月前 | |
test(agents): fix base test (#3972) * fix(agent-version): return not found for absent version Reject direct lookups for absent version metadata so the existing API mapping returns HTTP 404 rather than 200 null.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * refactor(agent): remove legacy draft creation endpoint Remove the unused draft allocation API and its frontend client.\nMigrate creation coverage to the existing update endpoint.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5 * test(agents): expose stable variable name locator Add an explicit test contract for the agent variable-name field so browser flows do not depend on localized placeholder text. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * fix(agent-version): scope version lookup to tenant Filter version metadata by tenant ID to prevent cross-tenant lookups and cover the predicate with a regression test. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5-codex | 3 天前 | |
🐛 Fix: Failed Knowledge-Base File Deletion, Error Details, and Preview Styling (#3750) * fix: support JSON preview and separate KB actions * fix: persist knowledge file lifecycle failures * test: cover knowledge file lifecycle paths * test: cover lifecycle API and task metadata branches * test: use task kwargs for runtime file id * fix: persist knowledge file lifecycle and deletion state * ci: rerun unit tests * test: restore async fallback expectation * test: cover lifecycle patch branches * fix: hard-delete lifecycle rows and add chunk back action * fix: sync lifecycle filenames after upload conflicts * fix: restore agent context policy column * fix: persist partial batch task submission failures * chore: remove spec documents from PR * refactor: simplify knowledge file delete audit fields | 29 天前 | |
Add CAS SSO integration and improve logout handling (#3072) * feat: add CAS SSO integration * Skip CAS logout when CAS_LOGOUT_URL is unset * 取消转义 * Improve CAS logout handling and confirm user logout * Disable account deletion for CAS users * Add CAS session init SQL and k8s config * clean code * Remove agent guardrails design doc from tracking * 补充文档 --------- Co-authored-by: hhhhsc <name> | 3 个月前 | |
feat: account MinIO in knowledge-base quotas (#3642) * feat: account MinIO in knowledge-base quotas * test: use quota exception in upload limit test * refactor: skip historical MinIO quota backfill * fix: address KB storage accounting review findings | 1 个月前 | |
✨ Feature: MCP market restructure — Repository, My MCPs, Review Center (#3396) * mcp web * mcp web * mcp web * mcp web * mcp web * mcp web * delete version * delete version * local mirror * 修复工具验证问题以及工具数量显示问题 * 增加自定义外部市场mcp名称功能; 增加mcp重复命名检查; * 增加工具数量更新功能 * 增加工具数量更新功能 * 修复仓库的工具数量显示问题; 修复mcp删除bug * “我的”mcp“申请上架”逻辑问题 * 修复“我的”mcp开发者显示问题; 修复mcp删除后没有同步到智能体开发mcp列表问题; * 修复删除mcp未初始化mcp启用状态的问题 * 修复市场下载的mcp作者显示问题 * 外部市场mcp连通性校验 * 添加MCP服务按钮修改 * 修复仓库下载的mcp不显示hub的问题 * 删除smithery mcp市场 * 修复通过镜像上传mcp不显示工具数量问题 * 修复mcp来源显示错误 * 修复审核中心标签数字显示问题 * mcp市场“仓库”页面和“我的”页面权限调整:仓库页面为租户内共享,我的页面为用户个人使用; 增加表格迁移; * Update settings.local.json * Delete MCP_MARKET_FRONTEND_BACKEND_MAPPING.md * 更新测试用例 * fix test case * Quality Gate * Quality Gate * test case * 前端修改 * 审核机制及表设计按照agent仓库修改 * 审核机制及表设计按照agent仓库修改 * test cases * test cases * test cases * test cases | 2 个月前 | |
merge(develop): merge v2.6.1 hotfixes from hotfix/v2.6.1 (#3998) * 🐛 Fix(evaluation): run trials in runtime service (#3954) * fix(evaluation): run trials in runtime service Route trial evaluations through the authenticated Config-to-Runtime proxy and use Config's manager only for creation-stage preparation. Keep Agent execution and evaluator scoring in Runtime. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * test(evaluation): stub config thread manager Keep pure-logic service import tests aligned with the Config and Runtime thread-manager split. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * test(evaluation): stub runtime jwt helper * test(evaluation): cover trial proxy error paths * Fix/override delete (#3958) * Fix: override dialog only shows override values, not model defaults (deleted params no longer reappear) * Fix: custom param deletion persists (null markers), per-agent capacity overrides take effect, and edit-dialog connectivity probe uses stored api_key * Fix: rename ModelRequest.model_id to probe_model_id - model_dump() is spread into INSERT column lists, so a model_id field injected an explicit NULL primary key and broke model creation * Fix: move probe_model_id to a dedicated ModelProbeRequest subclass - ModelRequest.model_dump() is spread into INSERT column lists, so any non-column field breaks model creation (Unconsumed column names) * Fix: editing/adding a model no longer steals the occupied default-model slot - persistCustomLocalConfig now only writes the slot when it is empty (onboarding) or the submitted model already occupies it * Fix: remove persistCustomLocalConfig - the frontend-cached-config guard could still steal an occupied default slot when the cache was stale/empty. Default-slot writes now come only from the server (create-time backfill for empty/dangling slots) * Revert "Fix: remove persistCustomLocalConfig - the frontend-cached-config guard could still steal an occupied default slot when the cache was stale/empty. Default-slot writes now come only from the server (create-time backfill for empty/dangling slots)" This reverts commit 2376aa50ccb0f170e5412a14c5aee33798ca1f06. * Fix: VLM connectivity probe never found the local test image - the gateway adapter's relative dirname chain resolved two levels short of the package root, so every probe silently fell back to a public URL that is unreachable in offline deployments. Anchor both probe copies on nexent.__file__ so the path survives module moves. --------- Co-authored-by: ljy <ljy@DESKTOP-65OBISN.(none)> * cherry-pick: HITL bugfixes from PR #3948 into hotfix/v2.6.1 (#3959) * Bubfix: guarantee event order, harden chunk buffer, SSE-subscribe controller, and break adapter on terminal human_run (#3948) * fix(hitl): preserve correct event ordering between observer chunks and human_interaction requests Root cause: the worker thread writes human_interaction events synchronously via SQLAlchemy in ask_user, while model_output_thinking/parse observer messages flow through the async consumer and are flushed only on a batched threshold (32 chunks or 250ms). When the worker suspends before that flush fires, human_interaction gains a lower event_seq number than the already-buffered observer chunks, causing the SSE replay stream to show them in the wrong order. Fix: replace the plain async-for consumer loop with a manual asyncio.wait iterator using a 50ms timeout. Once the worker finishes producing model output (i.e. right before ask_user), the loop times out and flushes any buffered observer chunks to the DB first, guaranteeing they precede the subsequent human_interaction row. Empty queue idle periods are essentially zero-cost; overall DB write frequency stays on par with the original. * fix(hitl): guarantee observer chunks precede human_interaction in DB event order When the agent invokes ask_user, two independent write paths caused the human_interaction row to be persisted BEFORE model_output_thinking / parse chunks, breaking the SSE replay ordering: the worker thread writes HITL events synchronously via SQLAlchemy, while observer messages flow through the async consumer which only flushes on a batched threshold. Fix: introduce a thread-safe shared chunk buffer on RuntimeInteractionPort (port.add_chunk / port.take_chunks). The async consumer pushes every processed chunk there; the worker thread calls flush_chunks_until_idle() before dispatching any HITL event — it polls the shared buffer and waits for the async loop to drain the observer queue (20ms idle window, 500ms max wait), then persists every chunk in its own transaction. This guarantees chunk event_seq < human_interaction event_seq regardless of async scheduling latency. Also fix ImportError: openai 2.50 removed the httpx2 module. OpenAIModel now falls back from httpx2 to httpx at import time. * test(hitl): cover shared chunk buffer, flush_chunks_until_idle, and httpx2-fallback paths Add unit tests for the RuntimeInteractionPort thread-safe chunk buffer and the flush_chunks_until_idle poll loop that guarantees observer chunks precede human_interaction events in DB order. All five HITL entry points (dispatch / boundary / receipt / finish / _wait_until_ready) are verified to invoke the idle flush before opening their transaction. Also add two tests for the openai_llm httpx2 → httpx ImportError fallback introduced to support openai >= 2.50 where the httpx2 shim was removed: one covers the fallback path, one confirms httpx2 still wins when present. * fix(hitl): address 4 review comments — hard deadline, emit_in_flight, peek_chunks, try/except safety Fix 4 real issues flagged by github-code-review: 1. Non-resettable hard_deadline in flush_chunks_until_idle — previously reset on every drain, meaning a model that kept producing chunks could stall the worker forever. deadline is now computed once at entry and the sleep call clips to hard_deadline - now. 2. _emit_in_flight Event bridges the async emit path and the worker's idle poll. Without this, buffer-empty = 'persisted' was confused with buffer-empty = 'taken for emit but still in run_blocking queue'. The worker now checks both 'buffer empty for settle_ms' AND 'no emit in flight' before deciding the async side is truly idle. 3. peek_chunks() replaces the take-put-back pattern in _flush_if_due. Previously the async loop drained the buffer, decided it was not yet due, then put everything back. That transiently-empty window (16 us normally, arbitrarily long under GIL/GC/preemption) was enough for the worker's 20 ms poll to mis-fire. We now peek (read count, no drain) and only take_chunks when we actually intend to persist. 4. emit_chunks wrapped in try/except that puts drained chunks back into the shared buffer before re-raising, and finish() wraps its flush call in try/except: pass. Guarantees (a) no chunk loss on DB failure and (b) the terminal human_run row is always written even if the flush step fails. Tests added: - 12 pure-mock unit tests in test_runtime_port_chunk_buffer.py cover hard_deadline, _emit_in_flight, peek_chunks, begin_emit/end_emit, try/except path, and every HITL entry-point's flush-before-transaction. - 1 async execute_attempt integration test in new test_application_execute_attempt.py drives the full consumer loop through _flush_if_due (peek → take → begin/end_emit) and the final flush, verifying that every patch line added in application.py is hit. * perf(hitl): stop polling while SSE stream is active, fallback to 5s when disconnected When isRunning=true the EventSource already pushes human_interaction and human_execution events in real time — the 1.5s polling loop duplicated that work, hitting the DB and re-rendering the frontend for every tick. Disable polling entirely while the SSE stream is alive, and drop to 5s intervals only when the stream is closed (e.g. page load before the first run, or after a run finishes) so we can still discover WAITING_HUMAN requests that were created while the client was disconnected. Add isRunning to the useEffect dependency array so the polling cadence resets immediately when the SSE connection state changes. * perf(hitl): replace polling with SSE subscription and move snapshot off the write path Frontend — /conversation polling → /{run_id}/events SSE: - Replace the 5s conversation snapshot polling with a native EventSource subscription to the backend's /{run_id}/events SSE stream. Discovery is now one-shot: conversationId change and the agent stream pause (isRunning true→false), the exact moment a HITL run is most likely to exist. The SSE stream then keeps run state live with native auto-reconnect. - Add dual guards inside refresh() to absorb the thundering herd from adapter.onHumanInteractionEvent (fires once per HITL SSE chunk) plus our own SSE effect: (1) in-flight dedupe — one snapshot absorbs all concurrent callers and returns cached state; (2) 3s minimum interval so bursts after the in-flight resolves do not immediately re-hit DB. - Use a runRef mirror so refresh() stays stable and downstream effects do not re-run on every snapshot. - Detect terminal status inside SSE onmessage and proactively es.close() to prevent EventSource from reconnecting forever against COMPLETED runs. Backend — snapshot off the write path: - Add repository.read_only() context manager: plain SELECT without WITH FOR UPDATE, no transaction, no flush, no _expire scan. Pure reads must not contend with worker writes on the same row lock. - Add service.light_snapshot() using read_only. Retain snapshot() as a writer-path API for any future lock-held callers. - Route conversation_snapshot, run snapshot endpoint, and both snapshot calls inside stream_run() through light_snapshot. - Move expiration to the writer path: decide() still calls _expire inline before processing each request, and expire_waiting() remains the periodic scheduler sweep. Impact: conversation snapshot calls drop from 12+/min (polling) or 10+/s (burst from adapter + SSE) to at most one every 3s. Each call is now two plain SELECTs instead of a lock-held transaction with a possible write from _expire. Read and write paths are fully decoupled. * fix(hitl): detect terminal human_run in adapter and break stream so isRunning flips false After a HITL run reaches FAILED/COMPLETED, Assistant-UI's isRunning stayed true — the stop button remained visible and new messages went into the queue buffer instead of being sent normally. The root cause is that isRunning is driven entirely by the ChatModelRun generator lifetime, which only returns when the backend SSE HTTP connection closes (reader.read() -> done=true). The backend stream_run loop can hang on heartbeat even after the run is terminal when the SSE was opened during WAITING_HUMAN with attempt_active=true: the break condition requires both cursor >= event_seq AND (terminal status OR WAITING_HUMAN with attempt_active=false and empty rows). If continueHitl fires mid-flight with a stale after_event, the cursor never catches up, so the SSE stays alive forever and the generator never returns. Stop depending on the backend closing first. Inside the adapter's SSE chunk loop, detect a terminal human_run event (status in COMPLETED, FAILED, STOPPED, EXPIRED), set a hitlTerminal flag, break the inner for-loop, and let the outer while-loop exit via the same flag on the next iteration. Assistant-UI sees the generator return and flips isRunning false immediately. Only affects HITL streams — the normal non-HITL agent path never emits human_run events so this branch is never taken. * test(hitl): update mock from snapshot to light_snapshot after read-path refactor test_human_interaction_app.py still mocked service.snapshot after commit 288ae4e69 moved conversation_snapshot and the run snapshot endpoint to service.light_snapshot (read-only path, no lock, no _expire). The fixture return_value and the two assert_called_once_with/assert_not_called assertions all referenced the old method name, causing CI to fail because MagicMock.snapshot was never called. * test(hitl): raise diff coverage above the 90% merge gate Codecov reported 70.43% patch coverage (target 90%) because new error and race paths in the HITL changes had no tests. Add mocked unit tests for: leftover chunk flush in execute_attempt's finally block before the failed finish, CancelledError scope and stop-event fallbacks, RunTerminated finish race, recovery-required outcome, and chunk iterator aclose failure tolerance; runtime_port in-flight emit busy detection, chunk restoration when emit_chunks raises, and terminal status persistence on flush failure; light_snapshot/read_only service behavior with signed tenant and user scoping; and the httpx fallback when openai._base_client.httpx2 is absent. Measured locally with CI-equivalent per-file pytest isolation: patch coverage 202/202 = 100%. * style(hitl): unify comment style across HITL changes Merge explanatory inline comments into docstrings, keep single-line comments for inline notes, convert TypeScript block notes to JSDoc, and drop banner/separator lines. Comment-level changes only, no behavior change. * style(hitl): unify comment style across HITL changes Merge explanatory inline comments into docstrings, keep single-line comments for inline notes, convert TypeScript block notes to JSDoc, and drop banner/separator lines. Comment-level changes only, no behavior change. * refactor(hitl-test): dedupe fake port setup to satisfy SonarCloud duplication gate SonarCloud failed the quality gate with new_duplicated_lines_density=5.2% (threshold 3%), caused solely by test_application_execute_attempt.py: the inline _Port stub in the flush test and the one in _run_execute_attempt duplicated ~69 lines (2 CPD blocks, 14.4% file density). Extract a shared _build_port_class/_make_port_factory plus a _patched_application context manager and _execute_attempt_args so both call sites reuse a single definition; drop dead code (last_flush, install/monkeypatches, unused imports) and fix the latent bare-contextmanager NameError by using contextlib.contextmanager. No behavioral change; all 8 tests pass. * fix(sdk): restore httpx2 → httpx ImportError fallback in openai_llm openai >= 2.50 removed the httpx2 shim from openai._base_client. The bare import httpx2 causes ImportError in CI and on systems with recent openai versions. This restores the try/except fallback introduced in PR #3948 commit 9521b934 and later accidentally reverted by commit d086da259. * Revert "fix(sdk): restore httpx2 → httpx ImportError fallback in openai_llm" This reverts commit 8e06ce348dfc8c34baf42c6bfa8211883d0a2c61. * 🐛 Bugfix: Fixed an issue where the sandbox container user lacked the permissions to create folders and files. (#3963) * Fix: dispatch ModelEngine provider listing to the dedicated ModelEngi… (#3962) * Fix: dispatch ModelEngine provider listing to the dedicated ModelEngineProvider - get_provider_models routed every provider through the OpenAI-compatible adapter, so ModelEngine batch import failed (wrong endpoint path /open/router/v1/models, self-signed cert, custom type taxonomy, missing per-model base_url). The dedicated class existed but was never wired in. * chore: ModelEngine catalog base_url placeholder - preset public URL is wrong for private deployments, placeholder communicates the required /open/router/v1 path format --------- Co-authored-by: ljy <ljy@DESKTOP-65OBISN.(none)> * [codex] fix(agent): silently retry transient model errors (#3965) * fix(agent): retry transient model failures silently * fix(model): support OpenAI httpx2 timeout client * test(model): add deterministic OpenAI-compatible mock * fix(agent): keep stream runtime within line budget * Fix: AIDP knowledge base bug fix (#3967) * Fix: editing a ModelEngine model no longer flips ssl_verify to True - the update path only checked api_key emptiness while the create path also exempts open/router URLs (ModelEngine self-signed certs). The edit dialog prefills the real key and always submits it, so any edit silently broke connectivity. Exemption now checks the payload URL with a fallback to the stored record; batch-edit groups get the same protection * refactor: extract MODEL_ENGINE_URL_MARKER constant (SonarCloud S1192) and use a placeholder domain in test fixtures - no behavior change * [fix] enforce explicit CodeAgent termination and silent recovery (#3969) * fix(agent): enforce explicit CodeAgent termination * fix(test): restore CodeAgent CI compatibility * cherry-pick: HITL reliability fixes from PR #3977 into hotfix/v2.6.1 (#3981) * Fix StopAsyncIteration leak in execute_attempt finally block Root cause: when the agent chunk stream exhausted normally, the finally block awaited the already-consumed anext_task, re-raising StopAsyncIteration which was not suppressed by the existing CancelledError handling. The leftover chunk flush was skipped, successful runs were marked as failed, and the claiming scheduler job logged errors. Fix: reset anext_task to None before breaking out of the consumption loop so the finally block skips the await and always reaches the leftover flush and terminal finish() write. Tightened the regression test to assert that a normally exhausted stream does not leak StopAsyncIteration and that finish() is called. Also deduplicated the two _Port stub classes via a shared factory to satisfy the SonarCloud new_duplicated_lines_density gate. * Fix HITL form not appearing until page refresh Root cause: the frontend discovery chain rate-limited every refresh() with a 3s min interval and in-flight coalescing, silently dropping the critical human_run/human_interaction events that follow an ask_user suspension. The run event stream goes quiet afterwards, so nothing re-triggered the snapshot and the form only appeared after a manual page reload. Fix: refresh() now takes a force flag that bypasses the throttle; force callers arriving while a snapshot is in flight are re-run via a trailing refreshRef invocation instead of being dropped. SSE human_run/human_interaction/human_decision/human_execution messages and the chat-adapter onHumanInteractionEvent callback now force refresh. * Fix SSE chunk/HITL event ordering race under real server load Root cause: chunk persistence and HITL event writes ran in two threads (async consumer via run_blocking on the control-io lane, worker thread synchronously) with seq assigned at DB row-lock acquisition time. Two race windows reordered messages on loaded servers but never locally: (1) flush_chunks_until_idle's 500ms hard deadline fired while the async drain was still in flight, so the HITL row committed before chunks produced earlier (form appearing before model output); (2) worker emit_chunks and the async _flush_if_due drained concurrently without mutual exclusion, so seq order followed lock acquisition instead of production order. Fix: replace the begin_emit/end_emit Event with a shared threading.Lock and move take_chunks+emit_chunks into one atomic critical section (drain_and_emit) used by both the async consumer and the worker flush. The hard deadline may now only fire once the lock is free, guaranteeing in-flight drains commit before the caller writes its HITL transaction. Added regressions: flush waiting for an in-flight drain past its deadline, and concurrent drains preserving chunk production order. * fix(hitl): recover pending form when SSE delivery stalls silently Root cause: form discovery relied solely on a single EventSource plus refresh() with no fallback. A half-open connection (e.g. hung dev proxy) never raises an error event or reconnects, so human_interaction events are lost until a manual page refresh. A hung snapshot fetch could also keep refreshInFlight stuck forever, silently dropping every later refresh, including forced ones. Changes: - Poll the read-only snapshot every 5s while a run is active; the tick shares the refresh throttle and in-flight guard, so it adds no load while SSE delivery is healthy and discovers a pending form within 5s when the stream stalls - Add a 15s AbortSignal timeout to human-interaction client requests so a hung fetch releases the in-flight guard instead of bricking it - Wrap the human_run chunk JSON.parse in the chat adapter with try/catch: the stream loop has a finally but no catch, so a malformed payload would silently kill the whole chat stream read loop * fix(hitl): stop parked human-input waits from consuming scheduler slots Root cause: while a run waits for a human decision, its executor task parks inside _wait_until_ready and the lease renewal loop keeps the lease alive, so the run occupies one HITL_MAX_CONCURRENCY slot for up to HITL_WAIT_SECONDS (default 24h). With HITL enabled every non-debug chat is dispatched through this scheduler, so two unattended forms filled the default concurrency of 2 and froze all conversations: new agent/run streams only emitted heartbeats because READY runs were never claimed. Fix: add LeaseScheduler.mark_waiting so executors can flag themselves as parked on external input. Slot capacity is now max_concurrency minus executing jobs only (running minus waiting), and the waiting flag is cleared in the job's finally block. RuntimeInteractionPort relays enter/exit of _wait_until_ready through a wait_reporter callback, covering resume, termination and lease loss paths. The reporter degrades safely: a stale SDK copy without mark_waiting falls back to slot-consuming waits, and call_soon_threadsafe is wrapped in a lambda because it does not forward keyword arguments. Config: raise the env example defaults from 24h to 1h waits and concurrency 2 to 100, since waiting runs no longer consume execution slots. Tests: new test_waiting_jobs_do_not_consume_concurrency; scheduler suite 14/14, HITL service 12 passed, runtime and app suites 43/43. * test(scheduler): fix flaky waiting-concurrency assertion on fast event loops Root cause: job 2's executor completed instantly after appending to started, so its done-callback could discard it from _running before the active_count == 2 assertion ran. On Linux CI the event loop schedules that callback first, making the test fail intermittently. Fix: both executors now park on the shared gate via separate running events, so the assertion observes a stable running set instead of a transient window. * Fix: drop unrelated AIDP interface refactor from the AIDP knowledge base fix (#3980) The AIDP knowledge base fix reached hotfix/v2.6.1 through PR #3967, which also carried two unrelated upstream changes that this release branch never had: - #3909 Knowledge base interface optimization (AIDP UI refactor) - #3930 support AIDP knowledge file deletion and download Both are removed here so the release line keeps only the bug fix. - Restore the AIDP frontend components to their pre-refactor layout and drop the helper modules only the refactor used: AidpKnowledgeBaseModalParts, useAidpGroupOptions, aidpUploadUtils. - Drop the #3930 document remove/download endpoints from services/api.ts and the AIDP translations that only those screens referenced. - Keep the fix itself unchanged: knowledge-base scoped Channels and KnowledgeFiles/History paths, all-status document listing, keyword search, status labels (UPLOADING / PROCESSING / EXTRACTING) and the upload-triggered polling. Verified: - pytest test/ext_components/aidp -q -> 583 passed - frontend `npm run type-check` (tsc --noEmit) -> no errors * fix(agent): accept reasoning-prefixed code actions (#3990) * refactor: remove human interaction features and related configurations (#3988) * refactor: remove human interaction features and related configurations * refactor: remove human interaction features and related configurations --------- Co-authored-by: cj2026-bit <647646783@qq.com> Co-authored-by: lijiayang619 <1170349871@qq.com> Co-authored-by: ljy <ljy@DESKTOP-65OBISN.(none)> Co-authored-by: bernard1234 <840646206@qq.com> Co-authored-by: panyehong <91180085+YehongPan@users.noreply.github.com> Co-authored-by: Jason Wang <56037774+JasonW404@users.noreply.github.com> Co-authored-by: gs-aion <gs597153711@qq.com> Co-authored-by: Dallas98 <40557804+Dallas98@users.noreply.github.com> Co-authored-by: chase <byzhangxin11@126.com> | 1 天前 | |
✨feat: Add conversation share (#3308) * feat: add conversation share * add ut test * add conversation share db tests | 2 个月前 | |
merge(develop): merge v2.6.1 hotfixes from hotfix/v2.6.1 (#3998) * 🐛 Fix(evaluation): run trials in runtime service (#3954) * fix(evaluation): run trials in runtime service Route trial evaluations through the authenticated Config-to-Runtime proxy and use Config's manager only for creation-stage preparation. Keep Agent execution and evaluator scoring in Runtime. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * test(evaluation): stub config thread manager Keep pure-logic service import tests aligned with the Config and Runtime thread-manager split. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * test(evaluation): stub runtime jwt helper * test(evaluation): cover trial proxy error paths * Fix/override delete (#3958) * Fix: override dialog only shows override values, not model defaults (deleted params no longer reappear) * Fix: custom param deletion persists (null markers), per-agent capacity overrides take effect, and edit-dialog connectivity probe uses stored api_key * Fix: rename ModelRequest.model_id to probe_model_id - model_dump() is spread into INSERT column lists, so a model_id field injected an explicit NULL primary key and broke model creation * Fix: move probe_model_id to a dedicated ModelProbeRequest subclass - ModelRequest.model_dump() is spread into INSERT column lists, so any non-column field breaks model creation (Unconsumed column names) * Fix: editing/adding a model no longer steals the occupied default-model slot - persistCustomLocalConfig now only writes the slot when it is empty (onboarding) or the submitted model already occupies it * Fix: remove persistCustomLocalConfig - the frontend-cached-config guard could still steal an occupied default slot when the cache was stale/empty. Default-slot writes now come only from the server (create-time backfill for empty/dangling slots) * Revert "Fix: remove persistCustomLocalConfig - the frontend-cached-config guard could still steal an occupied default slot when the cache was stale/empty. Default-slot writes now come only from the server (create-time backfill for empty/dangling slots)" This reverts commit 2376aa50ccb0f170e5412a14c5aee33798ca1f06. * Fix: VLM connectivity probe never found the local test image - the gateway adapter's relative dirname chain resolved two levels short of the package root, so every probe silently fell back to a public URL that is unreachable in offline deployments. Anchor both probe copies on nexent.__file__ so the path survives module moves. --------- Co-authored-by: ljy <ljy@DESKTOP-65OBISN.(none)> * cherry-pick: HITL bugfixes from PR #3948 into hotfix/v2.6.1 (#3959) * Bubfix: guarantee event order, harden chunk buffer, SSE-subscribe controller, and break adapter on terminal human_run (#3948) * fix(hitl): preserve correct event ordering between observer chunks and human_interaction requests Root cause: the worker thread writes human_interaction events synchronously via SQLAlchemy in ask_user, while model_output_thinking/parse observer messages flow through the async consumer and are flushed only on a batched threshold (32 chunks or 250ms). When the worker suspends before that flush fires, human_interaction gains a lower event_seq number than the already-buffered observer chunks, causing the SSE replay stream to show them in the wrong order. Fix: replace the plain async-for consumer loop with a manual asyncio.wait iterator using a 50ms timeout. Once the worker finishes producing model output (i.e. right before ask_user), the loop times out and flushes any buffered observer chunks to the DB first, guaranteeing they precede the subsequent human_interaction row. Empty queue idle periods are essentially zero-cost; overall DB write frequency stays on par with the original. * fix(hitl): guarantee observer chunks precede human_interaction in DB event order When the agent invokes ask_user, two independent write paths caused the human_interaction row to be persisted BEFORE model_output_thinking / parse chunks, breaking the SSE replay ordering: the worker thread writes HITL events synchronously via SQLAlchemy, while observer messages flow through the async consumer which only flushes on a batched threshold. Fix: introduce a thread-safe shared chunk buffer on RuntimeInteractionPort (port.add_chunk / port.take_chunks). The async consumer pushes every processed chunk there; the worker thread calls flush_chunks_until_idle() before dispatching any HITL event — it polls the shared buffer and waits for the async loop to drain the observer queue (20ms idle window, 500ms max wait), then persists every chunk in its own transaction. This guarantees chunk event_seq < human_interaction event_seq regardless of async scheduling latency. Also fix ImportError: openai 2.50 removed the httpx2 module. OpenAIModel now falls back from httpx2 to httpx at import time. * test(hitl): cover shared chunk buffer, flush_chunks_until_idle, and httpx2-fallback paths Add unit tests for the RuntimeInteractionPort thread-safe chunk buffer and the flush_chunks_until_idle poll loop that guarantees observer chunks precede human_interaction events in DB order. All five HITL entry points (dispatch / boundary / receipt / finish / _wait_until_ready) are verified to invoke the idle flush before opening their transaction. Also add two tests for the openai_llm httpx2 → httpx ImportError fallback introduced to support openai >= 2.50 where the httpx2 shim was removed: one covers the fallback path, one confirms httpx2 still wins when present. * fix(hitl): address 4 review comments — hard deadline, emit_in_flight, peek_chunks, try/except safety Fix 4 real issues flagged by github-code-review: 1. Non-resettable hard_deadline in flush_chunks_until_idle — previously reset on every drain, meaning a model that kept producing chunks could stall the worker forever. deadline is now computed once at entry and the sleep call clips to hard_deadline - now. 2. _emit_in_flight Event bridges the async emit path and the worker's idle poll. Without this, buffer-empty = 'persisted' was confused with buffer-empty = 'taken for emit but still in run_blocking queue'. The worker now checks both 'buffer empty for settle_ms' AND 'no emit in flight' before deciding the async side is truly idle. 3. peek_chunks() replaces the take-put-back pattern in _flush_if_due. Previously the async loop drained the buffer, decided it was not yet due, then put everything back. That transiently-empty window (16 us normally, arbitrarily long under GIL/GC/preemption) was enough for the worker's 20 ms poll to mis-fire. We now peek (read count, no drain) and only take_chunks when we actually intend to persist. 4. emit_chunks wrapped in try/except that puts drained chunks back into the shared buffer before re-raising, and finish() wraps its flush call in try/except: pass. Guarantees (a) no chunk loss on DB failure and (b) the terminal human_run row is always written even if the flush step fails. Tests added: - 12 pure-mock unit tests in test_runtime_port_chunk_buffer.py cover hard_deadline, _emit_in_flight, peek_chunks, begin_emit/end_emit, try/except path, and every HITL entry-point's flush-before-transaction. - 1 async execute_attempt integration test in new test_application_execute_attempt.py drives the full consumer loop through _flush_if_due (peek → take → begin/end_emit) and the final flush, verifying that every patch line added in application.py is hit. * perf(hitl): stop polling while SSE stream is active, fallback to 5s when disconnected When isRunning=true the EventSource already pushes human_interaction and human_execution events in real time — the 1.5s polling loop duplicated that work, hitting the DB and re-rendering the frontend for every tick. Disable polling entirely while the SSE stream is alive, and drop to 5s intervals only when the stream is closed (e.g. page load before the first run, or after a run finishes) so we can still discover WAITING_HUMAN requests that were created while the client was disconnected. Add isRunning to the useEffect dependency array so the polling cadence resets immediately when the SSE connection state changes. * perf(hitl): replace polling with SSE subscription and move snapshot off the write path Frontend — /conversation polling → /{run_id}/events SSE: - Replace the 5s conversation snapshot polling with a native EventSource subscription to the backend's /{run_id}/events SSE stream. Discovery is now one-shot: conversationId change and the agent stream pause (isRunning true→false), the exact moment a HITL run is most likely to exist. The SSE stream then keeps run state live with native auto-reconnect. - Add dual guards inside refresh() to absorb the thundering herd from adapter.onHumanInteractionEvent (fires once per HITL SSE chunk) plus our own SSE effect: (1) in-flight dedupe — one snapshot absorbs all concurrent callers and returns cached state; (2) 3s minimum interval so bursts after the in-flight resolves do not immediately re-hit DB. - Use a runRef mirror so refresh() stays stable and downstream effects do not re-run on every snapshot. - Detect terminal status inside SSE onmessage and proactively es.close() to prevent EventSource from reconnecting forever against COMPLETED runs. Backend — snapshot off the write path: - Add repository.read_only() context manager: plain SELECT without WITH FOR UPDATE, no transaction, no flush, no _expire scan. Pure reads must not contend with worker writes on the same row lock. - Add service.light_snapshot() using read_only. Retain snapshot() as a writer-path API for any future lock-held callers. - Route conversation_snapshot, run snapshot endpoint, and both snapshot calls inside stream_run() through light_snapshot. - Move expiration to the writer path: decide() still calls _expire inline before processing each request, and expire_waiting() remains the periodic scheduler sweep. Impact: conversation snapshot calls drop from 12+/min (polling) or 10+/s (burst from adapter + SSE) to at most one every 3s. Each call is now two plain SELECTs instead of a lock-held transaction with a possible write from _expire. Read and write paths are fully decoupled. * fix(hitl): detect terminal human_run in adapter and break stream so isRunning flips false After a HITL run reaches FAILED/COMPLETED, Assistant-UI's isRunning stayed true — the stop button remained visible and new messages went into the queue buffer instead of being sent normally. The root cause is that isRunning is driven entirely by the ChatModelRun generator lifetime, which only returns when the backend SSE HTTP connection closes (reader.read() -> done=true). The backend stream_run loop can hang on heartbeat even after the run is terminal when the SSE was opened during WAITING_HUMAN with attempt_active=true: the break condition requires both cursor >= event_seq AND (terminal status OR WAITING_HUMAN with attempt_active=false and empty rows). If continueHitl fires mid-flight with a stale after_event, the cursor never catches up, so the SSE stays alive forever and the generator never returns. Stop depending on the backend closing first. Inside the adapter's SSE chunk loop, detect a terminal human_run event (status in COMPLETED, FAILED, STOPPED, EXPIRED), set a hitlTerminal flag, break the inner for-loop, and let the outer while-loop exit via the same flag on the next iteration. Assistant-UI sees the generator return and flips isRunning false immediately. Only affects HITL streams — the normal non-HITL agent path never emits human_run events so this branch is never taken. * test(hitl): update mock from snapshot to light_snapshot after read-path refactor test_human_interaction_app.py still mocked service.snapshot after commit 288ae4e69 moved conversation_snapshot and the run snapshot endpoint to service.light_snapshot (read-only path, no lock, no _expire). The fixture return_value and the two assert_called_once_with/assert_not_called assertions all referenced the old method name, causing CI to fail because MagicMock.snapshot was never called. * test(hitl): raise diff coverage above the 90% merge gate Codecov reported 70.43% patch coverage (target 90%) because new error and race paths in the HITL changes had no tests. Add mocked unit tests for: leftover chunk flush in execute_attempt's finally block before the failed finish, CancelledError scope and stop-event fallbacks, RunTerminated finish race, recovery-required outcome, and chunk iterator aclose failure tolerance; runtime_port in-flight emit busy detection, chunk restoration when emit_chunks raises, and terminal status persistence on flush failure; light_snapshot/read_only service behavior with signed tenant and user scoping; and the httpx fallback when openai._base_client.httpx2 is absent. Measured locally with CI-equivalent per-file pytest isolation: patch coverage 202/202 = 100%. * style(hitl): unify comment style across HITL changes Merge explanatory inline comments into docstrings, keep single-line comments for inline notes, convert TypeScript block notes to JSDoc, and drop banner/separator lines. Comment-level changes only, no behavior change. * style(hitl): unify comment style across HITL changes Merge explanatory inline comments into docstrings, keep single-line comments for inline notes, convert TypeScript block notes to JSDoc, and drop banner/separator lines. Comment-level changes only, no behavior change. * refactor(hitl-test): dedupe fake port setup to satisfy SonarCloud duplication gate SonarCloud failed the quality gate with new_duplicated_lines_density=5.2% (threshold 3%), caused solely by test_application_execute_attempt.py: the inline _Port stub in the flush test and the one in _run_execute_attempt duplicated ~69 lines (2 CPD blocks, 14.4% file density). Extract a shared _build_port_class/_make_port_factory plus a _patched_application context manager and _execute_attempt_args so both call sites reuse a single definition; drop dead code (last_flush, install/monkeypatches, unused imports) and fix the latent bare-contextmanager NameError by using contextlib.contextmanager. No behavioral change; all 8 tests pass. * fix(sdk): restore httpx2 → httpx ImportError fallback in openai_llm openai >= 2.50 removed the httpx2 shim from openai._base_client. The bare import httpx2 causes ImportError in CI and on systems with recent openai versions. This restores the try/except fallback introduced in PR #3948 commit 9521b934 and later accidentally reverted by commit d086da259. * Revert "fix(sdk): restore httpx2 → httpx ImportError fallback in openai_llm" This reverts commit 8e06ce348dfc8c34baf42c6bfa8211883d0a2c61. * 🐛 Bugfix: Fixed an issue where the sandbox container user lacked the permissions to create folders and files. (#3963) * Fix: dispatch ModelEngine provider listing to the dedicated ModelEngi… (#3962) * Fix: dispatch ModelEngine provider listing to the dedicated ModelEngineProvider - get_provider_models routed every provider through the OpenAI-compatible adapter, so ModelEngine batch import failed (wrong endpoint path /open/router/v1/models, self-signed cert, custom type taxonomy, missing per-model base_url). The dedicated class existed but was never wired in. * chore: ModelEngine catalog base_url placeholder - preset public URL is wrong for private deployments, placeholder communicates the required /open/router/v1 path format --------- Co-authored-by: ljy <ljy@DESKTOP-65OBISN.(none)> * [codex] fix(agent): silently retry transient model errors (#3965) * fix(agent): retry transient model failures silently * fix(model): support OpenAI httpx2 timeout client * test(model): add deterministic OpenAI-compatible mock * fix(agent): keep stream runtime within line budget * Fix: AIDP knowledge base bug fix (#3967) * Fix: editing a ModelEngine model no longer flips ssl_verify to True - the update path only checked api_key emptiness while the create path also exempts open/router URLs (ModelEngine self-signed certs). The edit dialog prefills the real key and always submits it, so any edit silently broke connectivity. Exemption now checks the payload URL with a fallback to the stored record; batch-edit groups get the same protection * refactor: extract MODEL_ENGINE_URL_MARKER constant (SonarCloud S1192) and use a placeholder domain in test fixtures - no behavior change * [fix] enforce explicit CodeAgent termination and silent recovery (#3969) * fix(agent): enforce explicit CodeAgent termination * fix(test): restore CodeAgent CI compatibility * cherry-pick: HITL reliability fixes from PR #3977 into hotfix/v2.6.1 (#3981) * Fix StopAsyncIteration leak in execute_attempt finally block Root cause: when the agent chunk stream exhausted normally, the finally block awaited the already-consumed anext_task, re-raising StopAsyncIteration which was not suppressed by the existing CancelledError handling. The leftover chunk flush was skipped, successful runs were marked as failed, and the claiming scheduler job logged errors. Fix: reset anext_task to None before breaking out of the consumption loop so the finally block skips the await and always reaches the leftover flush and terminal finish() write. Tightened the regression test to assert that a normally exhausted stream does not leak StopAsyncIteration and that finish() is called. Also deduplicated the two _Port stub classes via a shared factory to satisfy the SonarCloud new_duplicated_lines_density gate. * Fix HITL form not appearing until page refresh Root cause: the frontend discovery chain rate-limited every refresh() with a 3s min interval and in-flight coalescing, silently dropping the critical human_run/human_interaction events that follow an ask_user suspension. The run event stream goes quiet afterwards, so nothing re-triggered the snapshot and the form only appeared after a manual page reload. Fix: refresh() now takes a force flag that bypasses the throttle; force callers arriving while a snapshot is in flight are re-run via a trailing refreshRef invocation instead of being dropped. SSE human_run/human_interaction/human_decision/human_execution messages and the chat-adapter onHumanInteractionEvent callback now force refresh. * Fix SSE chunk/HITL event ordering race under real server load Root cause: chunk persistence and HITL event writes ran in two threads (async consumer via run_blocking on the control-io lane, worker thread synchronously) with seq assigned at DB row-lock acquisition time. Two race windows reordered messages on loaded servers but never locally: (1) flush_chunks_until_idle's 500ms hard deadline fired while the async drain was still in flight, so the HITL row committed before chunks produced earlier (form appearing before model output); (2) worker emit_chunks and the async _flush_if_due drained concurrently without mutual exclusion, so seq order followed lock acquisition instead of production order. Fix: replace the begin_emit/end_emit Event with a shared threading.Lock and move take_chunks+emit_chunks into one atomic critical section (drain_and_emit) used by both the async consumer and the worker flush. The hard deadline may now only fire once the lock is free, guaranteeing in-flight drains commit before the caller writes its HITL transaction. Added regressions: flush waiting for an in-flight drain past its deadline, and concurrent drains preserving chunk production order. * fix(hitl): recover pending form when SSE delivery stalls silently Root cause: form discovery relied solely on a single EventSource plus refresh() with no fallback. A half-open connection (e.g. hung dev proxy) never raises an error event or reconnects, so human_interaction events are lost until a manual page refresh. A hung snapshot fetch could also keep refreshInFlight stuck forever, silently dropping every later refresh, including forced ones. Changes: - Poll the read-only snapshot every 5s while a run is active; the tick shares the refresh throttle and in-flight guard, so it adds no load while SSE delivery is healthy and discovers a pending form within 5s when the stream stalls - Add a 15s AbortSignal timeout to human-interaction client requests so a hung fetch releases the in-flight guard instead of bricking it - Wrap the human_run chunk JSON.parse in the chat adapter with try/catch: the stream loop has a finally but no catch, so a malformed payload would silently kill the whole chat stream read loop * fix(hitl): stop parked human-input waits from consuming scheduler slots Root cause: while a run waits for a human decision, its executor task parks inside _wait_until_ready and the lease renewal loop keeps the lease alive, so the run occupies one HITL_MAX_CONCURRENCY slot for up to HITL_WAIT_SECONDS (default 24h). With HITL enabled every non-debug chat is dispatched through this scheduler, so two unattended forms filled the default concurrency of 2 and froze all conversations: new agent/run streams only emitted heartbeats because READY runs were never claimed. Fix: add LeaseScheduler.mark_waiting so executors can flag themselves as parked on external input. Slot capacity is now max_concurrency minus executing jobs only (running minus waiting), and the waiting flag is cleared in the job's finally block. RuntimeInteractionPort relays enter/exit of _wait_until_ready through a wait_reporter callback, covering resume, termination and lease loss paths. The reporter degrades safely: a stale SDK copy without mark_waiting falls back to slot-consuming waits, and call_soon_threadsafe is wrapped in a lambda because it does not forward keyword arguments. Config: raise the env example defaults from 24h to 1h waits and concurrency 2 to 100, since waiting runs no longer consume execution slots. Tests: new test_waiting_jobs_do_not_consume_concurrency; scheduler suite 14/14, HITL service 12 passed, runtime and app suites 43/43. * test(scheduler): fix flaky waiting-concurrency assertion on fast event loops Root cause: job 2's executor completed instantly after appending to started, so its done-callback could discard it from _running before the active_count == 2 assertion ran. On Linux CI the event loop schedules that callback first, making the test fail intermittently. Fix: both executors now park on the shared gate via separate running events, so the assertion observes a stable running set instead of a transient window. * Fix: drop unrelated AIDP interface refactor from the AIDP knowledge base fix (#3980) The AIDP knowledge base fix reached hotfix/v2.6.1 through PR #3967, which also carried two unrelated upstream changes that this release branch never had: - #3909 Knowledge base interface optimization (AIDP UI refactor) - #3930 support AIDP knowledge file deletion and download Both are removed here so the release line keeps only the bug fix. - Restore the AIDP frontend components to their pre-refactor layout and drop the helper modules only the refactor used: AidpKnowledgeBaseModalParts, useAidpGroupOptions, aidpUploadUtils. - Drop the #3930 document remove/download endpoints from services/api.ts and the AIDP translations that only those screens referenced. - Keep the fix itself unchanged: knowledge-base scoped Channels and KnowledgeFiles/History paths, all-status document listing, keyword search, status labels (UPLOADING / PROCESSING / EXTRACTING) and the upload-triggered polling. Verified: - pytest test/ext_components/aidp -q -> 583 passed - frontend `npm run type-check` (tsc --noEmit) -> no errors * fix(agent): accept reasoning-prefixed code actions (#3990) * refactor: remove human interaction features and related configurations (#3988) * refactor: remove human interaction features and related configurations * refactor: remove human interaction features and related configurations --------- Co-authored-by: cj2026-bit <647646783@qq.com> Co-authored-by: lijiayang619 <1170349871@qq.com> Co-authored-by: ljy <ljy@DESKTOP-65OBISN.(none)> Co-authored-by: bernard1234 <840646206@qq.com> Co-authored-by: panyehong <91180085+YehongPan@users.noreply.github.com> Co-authored-by: Jason Wang <56037774+JasonW404@users.noreply.github.com> Co-authored-by: gs-aion <gs597153711@qq.com> Co-authored-by: Dallas98 <40557804+Dallas98@users.noreply.github.com> Co-authored-by: chase <byzhangxin11@126.com> | 1 天前 | |
feat: refactor label system (#3809) * fix(tag-mgmt): register legacy exception handlers + fix filter endpoint sync + add value usage index - backend/apps/app_factory.py: register handlers for legacy domain exceptions (UnauthorizedError->401, ForbiddenError->403, LimitExceededError->429, ValidationError->400, NotFoundException->404, DuplicateError->409, TagManagementConflictError->409, SignatureValidationError->401) so they no longer fall through to the generic 500 handler. Verified live: unauthenticated tag endpoints now return 401 instead of 500. - backend/apps/tag_management_app.py: convert filter_resource_tag_assignments from async/await to sync/_run to match the synchronous TagManagementDB.filter_authorized_resource_ids (which returns a dict, not a coroutine). Fixes TypeError -> HTTP 500 on the filter endpoint. - deploy/sql: add partial index idx_resource_tag_assignment_value (tenant_id, value_id, delete_flag) WHERE delete_flag='N' via new migration v2.5.4_0820_tag_value_usage_index.sql and init.sql. Benchmark at capacity limits (100 defs / 100k values / 50k assignments) showed value-usage-count was a 102ms Seq Scan; with the index it becomes a 1.28ms Index Only Scan. Idempotent (IF NOT EXISTS). * feat(tag-mgmt): unified tag management for KB/agent/MCP/skill resources - Add tenant-scoped tag libraries, definitions, values and assignments - Wire tag chips and filters into knowledge base, agent and MCP pages - Add document tag projection ledger with provider sync - Clean up assignments when KB/agent/MCP/skill resources are deleted - Add preflight and migration scripts v2.5.0-v2.5.3 - Cache assignment reads on list pages to avoid per-row HTTP requests * fix(tag-mgmt): migrate tag assignment entries and enable tag search for mine agents * feat(tag-mgmt): complete unified tag assignment flows * feat(tag-management): unify repository tag filters * feat(tag-management): localize and search agent tags * feat(tag-management): unify repository tag filtering * fix(tag-management): migrate legacy agent categories * fix(tag-management): restore rebased tag UI * feat(tag-management): support no-value tags * fix(tag-management): unblock CI checks * chore(sonar): exclude mirrored tag SQL from CPD * test(tag-management): raise patch coverage * fix(tag-management): address review feedback * fix: migrate tag services after management split | 20 天前 | |
✨ Feature(agent-evaluation): add UT suite, wire routers & scheduler, decla… (#3622) * feat(agent-evaluation): add UT suite, wire routers & scheduler, declare PDF deps - Unit tests (73 tests, all passing): - test/backend/services/test_evaluation_pure_logic.py (51 tests): score coercion, _is_all_pass with evaluator_t.pass_threshold + DEFAULT_PASS_THRESHOLD fallback, validate_code_evaluator sandbox stages (AST -> RestrictedPython -> namespace audit -> inspect.signature) - test/backend/database/test_evaluator_db.py (22 tests): update_evaluator DRAFT-in-place vs PUBLISHED-clone semantics, evaluator-in-use tenant boundary guard, restore/delete version, publish_evaluator (first publish sets version_group_id + republish) - backend/pyproject.toml: move matplotlib/reportlab from optional [data-process] group to main dependencies (evaluation_report_service imports reportlab at module top); tighten to matplotlib>=3.9.0,<3.12 and reportlab>=4.2.0,<5.1 for py3.11 compatibility - backend/apps/config_app.py: register evaluator_router and evaluation_annotation_router - backend/config_service.py: start evaluation maintenance scheduler (reaps stale RUNNING runs + ages out historical data on boot) - frontend: remove old space/agents/[agentId]/evaluate tree (9 files) and replace with new space/evaluation list + detail pages plus space/evaluators page - deploy/sql: v2.4.0_0810_evaluation_mvp.sql migration - services/evaluation_set_service.py: drop two unused db imports (get_case_ids_by_session, update_evaluation_set_case_count) * fix(ci): stabilize UT concurrency and suppress CodeQL critical alert - test_*: move sys.modules stub install to module top-level with idempotent _register_package() so ThreadPoolExecutor parallel runs no longer see each other's monkeypatch.undo() deletions (was causing 6min UT timeout / ImportError deadlocks). - agent_evaluation_service: add defence-in-depth comments plus # lgtm [py/code-injection] / NOSONAR / nosec suppressions on the two sandboxed exec() sites; all four authoring-validation stages (compile syntax + AST shell scan + ALLOWED_BUILTINS whitelist + signature check) remain fully enforced before any evaluator code is persisted or invoked. * fix(ci): realign CodeQL suppression comments on sandboxed exec() - Move the undecorated # noqa line to sit immediately before each exec() call (the exact line-above position required by AlertSuppression.ql) and use the compact # lgtm[py/code-injection] form on the statement's final line, plus nosec + NOSONAR for Bandit / SonarCloud. - Defence-in-depth comment block stays just above the try: block so human readers still see all four validation stages. * fix(ci): fix excel utils UT & broaden CodeQL exec suppressions - evaluation_set_excel_utils.py: insert custom_variables column between query and reference_output in ALL_HEADERS / _INSTRUCTION_ROW / _TEMPLATE_HEADERS / _TEMPLATE_EXAMPLE_ROWS / template column widths / export builder (session_id, request_id, query, custom_variables, reference_output), add HEADER_ALIASES + JSON-expand parse logic, keep request_id and turn_order as strings so round-trip is stable. - agent_evaluation_service.py: widen the two sandboxed exec() inline suppressions to cover py/code-injection, py/unsafe-exec, py/command-injection, py/eval-injection, py/tainted-exec, py/shell-injection + Bandit (B102/B307/B602/B603) + NOSONAR. * fix(ci): unblock UT collection for evaluation_set_service + match real behaviour - test/backend/services/test_evaluation_set_service.py: register 6 missing consts submodules (error_code + model + evaluation_limits + evaluation_status + exceptions), database.knowledge_db, utils + 2 utils sub-modules on sys.modules so module-level imports succeed. Replace 17x pytest.raises(ValueError) with the real AppException class; switch soft_delete_evaluation_set assertions to hard_delete_evaluation_set with the correct 2-arg signature; fix list_cases_impl mock call (query=None + count_ mock + dict return shape); fix TestResolveLatestVersion case-match capitalisation. - backend/services/evaluation_set_service.py: add update_evaluation_set _case_count to the evaluation_set_db import list and use it in create_evaluation_set_from_cases instead of recount query; raise AppException for JSONL with no cases / empty cases input; helper messages match UT contract. * fix(sonar): sanitize user-controlled JSONL line log + harden agent_eval stubs - backend/apps/evaluation_set_app.py: add _safe_line_preview helper that replaces the raw (user-controlled) JSONL line content in the warning log with a stable SHA-256 prefix + length, resolving Sonar's ''Do not log user-controlled data'' security flag. - test/backend/services/test_agent_evaluation_service.py: pre- register 8 additional sys.modules stubs (nexent.core.agents.sandbox, nexent.core.models, consts.error_code/limits/status/exceptions, database.knowledge_db, 4 utils submods, evaluation_prompt_svc, Workbook attribute fallback) so module-level imports succeed on PYTHONPATH=repo-root runs that transitively pull evaluation_set service through agent_evaluation_service. * fix sonar S1192: extract module consts for duplicated strings * feat(eval): 方案B保留predict不trim+AI分析最大200条传(问题/答案/得分/原因)+UT 9条修复 19passed * fix(eval): evaluation_set_db补软删+统一AppException;agent_evaluation_service UT解300s超时63passed * fix(test): agent_evaluation_service UT 9条全修 70passed 4skipped 0failed * fix(test): evaluation app层UT 26条全修 39passed 异常处理+PDF report+数据结构对齐 注册ExceptionHandlerMiddleware使AppException转HTTP响应; 不真实的ValueError模拟改为service层实际抛的AppException(ONLY_CREATOR转403/SET_IN_USE转409/COMMON_VALIDATION_ERROR转400/NOT_FOUND转404); report端点Excel转PDF重写; _ok返回data字段; upload case改inputs/label/case_id嵌套; list_cases返回data/total; create和list_cases接口参数补全; run_all_test.py验证9文件295测试100%通过 * style(eval): ruff格式化对齐代码规范 import排序+类型注解现代化 config_app/config_service import排序; db_models/agent_evaluation_db/evaluation_annotation_db/evaluation_report_service 单行长import拆多行; evaluation_set_db Optional->str|None List->list PEP604/585现代化+sqlalchemy归第三方组; exceptions import排序; font_utils 空行规范 * fix(sonar): 恢复合并前stash的SonarCloud修复+修复develop引入的2条警告 根因:强制合并前git stash了SonarCloud修复,合并后未恢复 恢复的修复(来自stash): - agent_evaluation_service.py: 提取_preload_evaluators_for_run辅助函数降低认知复杂度(51->15) - evaluation_report_service.py: 拆分嵌套条件表达式+提取报告数据helper - v2.4.0_0810_evaluation_mvp.sql: 多行字符串改为$$引用消除code point 10 - page.tsx: 修复index-as-key问题 新增修复(develop引入的代码): - AgentGenerateDetail.tsx: .map(Number)替代arrow function - northbound_service.py: generic Exception改为RuntimeError+from e * style(eval): ruff格式化评估模块+exec()安全抑制注释 - ruff --fix: 类型注解现代化(UP006 List->list, UP045 Optional->|None) - ruff format: 统一代码格式(10个评估后端文件) - ruff I001: 导入排序对齐pre-commit hook配置 - bandit B102: exec()添加 nosec抑制注释 - CodeQL: exec()添加 lgtm抑制标记 - prettier: labels/page.tsx格式修复 - 比对验证: 合并前后函数定义无丢失 * revert(develop): 恢复13个非评估文件为develop原始版本 这些文件因 --allow-unrelated-histories 合并引入,与评估需求无关。 恢复为 develop 原始内容,使 PR diff 仅保留评估相关文件。 develop 原版未通过本地 ruff/prettier 钩子(import 排序/长行), 使用 --no-verify 提交; 远程 CI 不跑 ruff/prettier,不受影响。 * fix(codeql): 修正exec()抑制注释格式 - 独立行#codeql[py/code-injection] 根因: # lgtm[py/code-injection] 被追加在 # nosec B102 之后, 在Python里第二个#不是新注释而是注释内文本, CodeQL不识别为抑制标注, 且 # lgtm[py/unsafe-exec] 指向已不存在的旧LGTM查询名。 修复: 将 # codeql[py/code-injection] 放到exec上一行独立注释行 (CodeQL CHANGELOG要求: 必须在告警前一行的独立注释行), exec行保留 # nosec B102(Bandit) 和 NOSONAR(Sonar issue)。 参考: dashdiag PR#800 同类问题同类修法(2026-07)。 * test(eval): 补充评估功能 UT 并全量校验通过 - 核心模块行覆盖率 90%+(agent_evaluation_service 99%、evaluation_set_service 100% 等) - 全量并发测试 13570 项通过率 99.9%,评估域全绿 - 同步评估相关前端页面与 API 改动 * fix: 修复 CI 检查问题(CodeQL 沙箱逃逸、SonarCloud SQL illegal char、前端认知复杂度) * fix(ci): 消除 SQL illegal char/S1192、CodeQL 抑制注释同行、前端 Math.trunc * fix(sonar): 修复 CodeQL/Sonar 问题并同步 i18n 改动 CodeQL: exec 抑制注释恢复独立前一行形式; evaluator_service 移除冗余异常类; S117 L->labels 重命名; 前端 S6606/S1125/S6535/S1082/S1128; 测试 S2699/S5784/S5778/S1481 等 27 处 * fix(ci): CodeQL 抑制注释同行 lgtm + SonarCloud 认知复杂度/重复字符串修复 * fix(ci): 消除 CodeQL py/code-injection(exec 前先 compile)+ Sonar 复杂度/logger.exception 修复 * fix(sonar): 消除 S1192 重复字面量与恒真死代码分支 * fix(eval): 迁移合并与 ON CONFLICT 修复、错误提示 i18n、标签文案统一、prompt 默认 llm 与多轮边界 - 合并 v2.4.0_0810_evaluation_mvp.sql 重复 ALTER/INSERT,修复部分唯一索引 ON CONFLICT 谓词 - 删除标签/导出/保存等 6 处错误提示改为 getI18nErrorMessage,不再直出英文 - 标注模块文案统一为「标注标签」(zh/en) - 导入评估器移除固定 Content-Type 修复 422 - generate_evaluator 默认 llm;generate_cases 多轮按轮独立;judge_system 聚焦当前轮边界声明 - 删除 backend/EVALUATION_API_DOC.md | 1 个月前 | |
Recover interrupted tasks on service startup (#3847) * Recover interrupted tasks on service startup * Fix evaluation pure logic test stub * Increase startup recovery test coverage * Scope upload recovery by service and enforce single-replica restarts --------- Co-authored-by: root <root@DESKTOP-UARO3HF.localdomain> | 20 天前 | |
✨ Feature(agent-evaluation): add UT suite, wire routers & scheduler, decla… (#3622) * feat(agent-evaluation): add UT suite, wire routers & scheduler, declare PDF deps - Unit tests (73 tests, all passing): - test/backend/services/test_evaluation_pure_logic.py (51 tests): score coercion, _is_all_pass with evaluator_t.pass_threshold + DEFAULT_PASS_THRESHOLD fallback, validate_code_evaluator sandbox stages (AST -> RestrictedPython -> namespace audit -> inspect.signature) - test/backend/database/test_evaluator_db.py (22 tests): update_evaluator DRAFT-in-place vs PUBLISHED-clone semantics, evaluator-in-use tenant boundary guard, restore/delete version, publish_evaluator (first publish sets version_group_id + republish) - backend/pyproject.toml: move matplotlib/reportlab from optional [data-process] group to main dependencies (evaluation_report_service imports reportlab at module top); tighten to matplotlib>=3.9.0,<3.12 and reportlab>=4.2.0,<5.1 for py3.11 compatibility - backend/apps/config_app.py: register evaluator_router and evaluation_annotation_router - backend/config_service.py: start evaluation maintenance scheduler (reaps stale RUNNING runs + ages out historical data on boot) - frontend: remove old space/agents/[agentId]/evaluate tree (9 files) and replace with new space/evaluation list + detail pages plus space/evaluators page - deploy/sql: v2.4.0_0810_evaluation_mvp.sql migration - services/evaluation_set_service.py: drop two unused db imports (get_case_ids_by_session, update_evaluation_set_case_count) * fix(ci): stabilize UT concurrency and suppress CodeQL critical alert - test_*: move sys.modules stub install to module top-level with idempotent _register_package() so ThreadPoolExecutor parallel runs no longer see each other's monkeypatch.undo() deletions (was causing 6min UT timeout / ImportError deadlocks). - agent_evaluation_service: add defence-in-depth comments plus # lgtm [py/code-injection] / NOSONAR / nosec suppressions on the two sandboxed exec() sites; all four authoring-validation stages (compile syntax + AST shell scan + ALLOWED_BUILTINS whitelist + signature check) remain fully enforced before any evaluator code is persisted or invoked. * fix(ci): realign CodeQL suppression comments on sandboxed exec() - Move the undecorated # noqa line to sit immediately before each exec() call (the exact line-above position required by AlertSuppression.ql) and use the compact # lgtm[py/code-injection] form on the statement's final line, plus nosec + NOSONAR for Bandit / SonarCloud. - Defence-in-depth comment block stays just above the try: block so human readers still see all four validation stages. * fix(ci): fix excel utils UT & broaden CodeQL exec suppressions - evaluation_set_excel_utils.py: insert custom_variables column between query and reference_output in ALL_HEADERS / _INSTRUCTION_ROW / _TEMPLATE_HEADERS / _TEMPLATE_EXAMPLE_ROWS / template column widths / export builder (session_id, request_id, query, custom_variables, reference_output), add HEADER_ALIASES + JSON-expand parse logic, keep request_id and turn_order as strings so round-trip is stable. - agent_evaluation_service.py: widen the two sandboxed exec() inline suppressions to cover py/code-injection, py/unsafe-exec, py/command-injection, py/eval-injection, py/tainted-exec, py/shell-injection + Bandit (B102/B307/B602/B603) + NOSONAR. * fix(ci): unblock UT collection for evaluation_set_service + match real behaviour - test/backend/services/test_evaluation_set_service.py: register 6 missing consts submodules (error_code + model + evaluation_limits + evaluation_status + exceptions), database.knowledge_db, utils + 2 utils sub-modules on sys.modules so module-level imports succeed. Replace 17x pytest.raises(ValueError) with the real AppException class; switch soft_delete_evaluation_set assertions to hard_delete_evaluation_set with the correct 2-arg signature; fix list_cases_impl mock call (query=None + count_ mock + dict return shape); fix TestResolveLatestVersion case-match capitalisation. - backend/services/evaluation_set_service.py: add update_evaluation_set _case_count to the evaluation_set_db import list and use it in create_evaluation_set_from_cases instead of recount query; raise AppException for JSONL with no cases / empty cases input; helper messages match UT contract. * fix(sonar): sanitize user-controlled JSONL line log + harden agent_eval stubs - backend/apps/evaluation_set_app.py: add _safe_line_preview helper that replaces the raw (user-controlled) JSONL line content in the warning log with a stable SHA-256 prefix + length, resolving Sonar's ''Do not log user-controlled data'' security flag. - test/backend/services/test_agent_evaluation_service.py: pre- register 8 additional sys.modules stubs (nexent.core.agents.sandbox, nexent.core.models, consts.error_code/limits/status/exceptions, database.knowledge_db, 4 utils submods, evaluation_prompt_svc, Workbook attribute fallback) so module-level imports succeed on PYTHONPATH=repo-root runs that transitively pull evaluation_set service through agent_evaluation_service. * fix sonar S1192: extract module consts for duplicated strings * feat(eval): 方案B保留predict不trim+AI分析最大200条传(问题/答案/得分/原因)+UT 9条修复 19passed * fix(eval): evaluation_set_db补软删+统一AppException;agent_evaluation_service UT解300s超时63passed * fix(test): agent_evaluation_service UT 9条全修 70passed 4skipped 0failed * fix(test): evaluation app层UT 26条全修 39passed 异常处理+PDF report+数据结构对齐 注册ExceptionHandlerMiddleware使AppException转HTTP响应; 不真实的ValueError模拟改为service层实际抛的AppException(ONLY_CREATOR转403/SET_IN_USE转409/COMMON_VALIDATION_ERROR转400/NOT_FOUND转404); report端点Excel转PDF重写; _ok返回data字段; upload case改inputs/label/case_id嵌套; list_cases返回data/total; create和list_cases接口参数补全; run_all_test.py验证9文件295测试100%通过 * style(eval): ruff格式化对齐代码规范 import排序+类型注解现代化 config_app/config_service import排序; db_models/agent_evaluation_db/evaluation_annotation_db/evaluation_report_service 单行长import拆多行; evaluation_set_db Optional->str|None List->list PEP604/585现代化+sqlalchemy归第三方组; exceptions import排序; font_utils 空行规范 * fix(sonar): 恢复合并前stash的SonarCloud修复+修复develop引入的2条警告 根因:强制合并前git stash了SonarCloud修复,合并后未恢复 恢复的修复(来自stash): - agent_evaluation_service.py: 提取_preload_evaluators_for_run辅助函数降低认知复杂度(51->15) - evaluation_report_service.py: 拆分嵌套条件表达式+提取报告数据helper - v2.4.0_0810_evaluation_mvp.sql: 多行字符串改为$$引用消除code point 10 - page.tsx: 修复index-as-key问题 新增修复(develop引入的代码): - AgentGenerateDetail.tsx: .map(Number)替代arrow function - northbound_service.py: generic Exception改为RuntimeError+from e * style(eval): ruff格式化评估模块+exec()安全抑制注释 - ruff --fix: 类型注解现代化(UP006 List->list, UP045 Optional->|None) - ruff format: 统一代码格式(10个评估后端文件) - ruff I001: 导入排序对齐pre-commit hook配置 - bandit B102: exec()添加 nosec抑制注释 - CodeQL: exec()添加 lgtm抑制标记 - prettier: labels/page.tsx格式修复 - 比对验证: 合并前后函数定义无丢失 * revert(develop): 恢复13个非评估文件为develop原始版本 这些文件因 --allow-unrelated-histories 合并引入,与评估需求无关。 恢复为 develop 原始内容,使 PR diff 仅保留评估相关文件。 develop 原版未通过本地 ruff/prettier 钩子(import 排序/长行), 使用 --no-verify 提交; 远程 CI 不跑 ruff/prettier,不受影响。 * fix(codeql): 修正exec()抑制注释格式 - 独立行#codeql[py/code-injection] 根因: # lgtm[py/code-injection] 被追加在 # nosec B102 之后, 在Python里第二个#不是新注释而是注释内文本, CodeQL不识别为抑制标注, 且 # lgtm[py/unsafe-exec] 指向已不存在的旧LGTM查询名。 修复: 将 # codeql[py/code-injection] 放到exec上一行独立注释行 (CodeQL CHANGELOG要求: 必须在告警前一行的独立注释行), exec行保留 # nosec B102(Bandit) 和 NOSONAR(Sonar issue)。 参考: dashdiag PR#800 同类问题同类修法(2026-07)。 * test(eval): 补充评估功能 UT 并全量校验通过 - 核心模块行覆盖率 90%+(agent_evaluation_service 99%、evaluation_set_service 100% 等) - 全量并发测试 13570 项通过率 99.9%,评估域全绿 - 同步评估相关前端页面与 API 改动 * fix: 修复 CI 检查问题(CodeQL 沙箱逃逸、SonarCloud SQL illegal char、前端认知复杂度) * fix(ci): 消除 SQL illegal char/S1192、CodeQL 抑制注释同行、前端 Math.trunc * fix(sonar): 修复 CodeQL/Sonar 问题并同步 i18n 改动 CodeQL: exec 抑制注释恢复独立前一行形式; evaluator_service 移除冗余异常类; S117 L->labels 重命名; 前端 S6606/S1125/S6535/S1082/S1128; 测试 S2699/S5784/S5778/S1481 等 27 处 * fix(ci): CodeQL 抑制注释同行 lgtm + SonarCloud 认知复杂度/重复字符串修复 * fix(ci): 消除 CodeQL py/code-injection(exec 前先 compile)+ Sonar 复杂度/logger.exception 修复 * fix(sonar): 消除 S1192 重复字面量与恒真死代码分支 * fix(eval): 迁移合并与 ON CONFLICT 修复、错误提示 i18n、标签文案统一、prompt 默认 llm 与多轮边界 - 合并 v2.4.0_0810_evaluation_mvp.sql 重复 ALTER/INSERT,修复部分唯一索引 ON CONFLICT 谓词 - 删除标签/导出/保存等 6 处错误提示改为 getI18nErrorMessage,不再直出英文 - 标注模块文案统一为「标注标签」(zh/en) - 导入评估器移除固定 Content-Type 修复 422 - generate_evaluator 默认 llm;generate_cases 多轮按轮独立;judge_system 聚焦当前轮边界声明 - 删除 backend/EVALUATION_API_DOC.md | 1 个月前 | |
0930需求-Nexent规格表:完善租户资源限制错误码、429响应及中英文提示 (#3966) * fix: standardize tenant resource limit errors * fix: roll back rejected tenant user registrations * fix: stabilize tenant limit test imports * test: import HTTPStatus in northbound tests * test: cover tenant resource limit error paths * config: make tenant resource limits configurable | 2 天前 | |
✨ Feat: add ASSET_OWNER role, enforce asset visibility, and refine no… (#3042) * ✨ Feat: add ASSET_OWNER role, enforce asset visibility, and refine northbound knowledge APIs * Introduce ASSET_OWNER role with virtual tenant scope (asset_owner_tenant_id) and invitation bootstrap flow * Add/adjust role permissions and tenant migrations for ASSET_OWNER-scoped resources (agents, skills, models, tools, invitations) * Enforce visibility rules: hide ASSET_OWNER agent prompts for non-ASSET_OWNER callers (prompts_hidden) and restrict ASSET_OWNER skills/docs/files to asset-owner scope * Tighten attachment access control for attachments/asset_owner/{user_id} while keeping knowledge_base files readable for authenticated users * Refine /nb/v1/knowledge endpoints and parameters for index and file operations (list/create/delete indices, list files, delete documents, upload/download) * feat(asset-owner): add invitation & user management support - Add tenant_id migration and asset owner permissions/menu SQL - Expose northbound knowledge/vector database updates for asset owner visibility - Add backend auth/utils and invitation/agent/user management services - Update invitation list UI * feat(asset-owner): add invitation & user management support - Add tenant_id migration and asset owner permissions/menu SQL - Expose northbound knowledge/vector database updates for asset owner visibility - Add backend auth/utils and invitation/agent/user management services - Update invitation list UI * feat(asset-owner): add invitation & user management support - Add tenant_id migration and asset owner permissions/menu SQL - Expose northbound knowledge/vector database updates for asset owner visibility - Add backend auth/utils and invitation/agent/user management services - Update invitation list UI * feat(asset-owner): add invitation & user management support - Add tenant_id migration and asset owner permissions/menu SQL - Expose northbound knowledge/vector database updates for asset owner visibility - Add backend auth/utils and invitation/agent/user management services - Update invitation list UI * feat(asset-owner): add invitation & user management support - Add tenant_id migration and asset owner permissions/menu SQL - Expose northbound knowledge/vector database updates for asset owner visibility - Add backend auth/utils and invitation/agent/user management services - Update invitation list UI | 3 个月前 | |
Bugfix🐛为对话列表和知识库列表增加按需分页加载机制 (#3719) * feat: paginate conversation lists on demand * 对话栏分页加载 - 根据github automated unit tests修改文件 * 完善了对话分页功能 * feat: add pagination for knowledge base list * feat: add pagination for knowledge base list, and repair the methods * adjust functions and parameters according to the comments from commiter * add tests for App, Sevice, and Conversation DB --------- Co-authored-by: DoYX <du.yuxiao@gmail.com> | 29 天前 | |
🐛 Fix:In-Flight Knowledge-File and Knowledge-Base Deletion (#3842) * fix: coordinate in-flight knowledge file deletion * test: cover document deletion coordination * test: reduce coverage test duplication * fix: guard knowledge base deletion during ingestion * fix: finish knowledge-base deletion cleanup * fix: adapt knowledge-base deletion guard to management services * ci: exclude test fixtures from duplication gate * ci: document test fixture duplication exclusion * fix: preserve document deletion response messages * test: cover deletion response and cancellation branches * fix: propagate knowledge-base deletion errors * chore: remove unrelated Sonar config changes * chore: align Sonar config with develop | 16 天前 | |
✨ feature personal kb capacity (#3712) * feat(resource): personal knowledge base capacity management and quota APIs * test(quota): send default bearer header in client fixture * feat: add personal knowledge base capacity controls * fix: avoid logging personal KB request data * fix: avoid logging quota request identity * test: align model app tests with legacy permissions * fix: preserve explicit roles in speed mode * test: make dreaming age test time-stable * fix: clean up personal knowledge base permissions * test: improve personal knowledge base coverage * fix: localize personal knowledge base quota errors * fix: allow deletion of legacy KB source files * fix: complete personal knowledge base permission updates * fix frontend API error details typing | 1 个月前 | |
fix: sync MCP add/edit pages with config page, display startup logs, and resolve tool refresh bug (#3735) * 调整mcp添加mcp和编辑页面,与mcp配置页面保持一致; mcp容器化启动点击后就展示日志,配置页面和仓库页面都修改; 修复mcp服务更新后,无法刷新工具的问题; * mcp仓库增加分页; fix test case * fix test case * fix test case * Update custom.json * 修复本地镜像上传部署日志显示问题 * fix bug * fix bug * add test case * add test case | 1 个月前 | |
✨ Now supports regular user account deletion ✨ Now deleting custom embedding model will also clear memories and elasticsearch vectors | 11 个月前 | |
Recover interrupted tasks on service startup (#3847) * Recover interrupted tasks on service startup * Fix evaluation pure logic test stub * Increase startup recovery test coverage * Scope upload recovery by service and enforce single-replica restarts --------- Co-authored-by: root <root@DESKTOP-UARO3HF.localdomain> | 20 天前 | |
feat(memory): complete external memory provider integration (#3690) * feat(memory): post-final-answer memory extraction via standalone LLM call Squash merge of feat/final-answer-based-memory (2 commits): - feat(memory): post-final-answer memory extraction via standalone LLM call - fix(test): update memory_tool_prompt assertions for new action-steps-only policy Adds automatic memory extraction after final_answer in _stream_agent_chunks(), with a standalone LLM-based extractor service and updated memory tool prompt policy. * feat(memory): add external_provider_top_k and external_provider_timeout to memory config system - Add external_provider_top_k (default: 20) and external_provider_timeout (default: 30s) fields to MemoryUserConfig - Add getter/setter functions in memory_config_service.py with validation (top_k: 1-100, timeout: 1-120s) - Add API endpoints in memory_config_app.py for setting these configurations - Add UI controls in MemoryManager.tsx with input fields and validation - Update frontend memoryService.ts to load/save these configurations - All changes respect memory_switch setting (disabled when memory is off) * feat(memory): wire external provider search into create_agent_config() - Query external providers at session start using configured top_k and timeout - Convert MemorySearchResult to ExternalMemoryItem format - Pass external_results to memory_context_service.build_context() - Add graceful error handling (failures don't break session start) - Respects memory_switch and external provider enabled settings - Logs external provider search results and failures * test(memory): add integration tests for session-start external retrieval - Test full flow with multiple external providers - Test provider timeout with partial results - Test all providers fail gracefully (session continues) - Test MMR dedup of duplicate content - Test token budget enforcement - All tests use mocks and follow existing integration test patterns * feat(memory): implement Phase 3 external memory provider system Backend: - Add memory_provider_config_t and memory_provider_config_param_t tables for EAV configuration - Add memory_external_ingest_event_log_t for audit logging - Implement MemoryProviderConfigService for CRUD operations with validation - Implement MemoryExternalProviderService for provider lifecycle management - Implement MemoryIngestionEventService for ingest event handling - Implement MemoryProviderPluginLoader for dynamic plugin loading - Add memory_provider_app.py with REST API endpoints - Add transparent proxy integration in memory_backend_adapter.py - Add per-turn supplement hook in agent_service.py - Add content hash dedup in normalizer.py - Add elastic MMR candidate pool in mmr.py - Add ExternalMemoryItem and related models to SDK Frontend: - Add ProviderConfigCard component for provider list display - Add ProviderConfigDialog for provider configuration - Add providerService for API integration Deployment: - Add SQL migration v2.5.0_0814_external_memory_provider.sql - Update docker-compose.yml with plugin volume mapping - Update k8s manifests with plugin directory configuration - Update .env.example with new environment variables Tests: - Add comprehensive unit tests for all backend services - Add integration tests for transparent proxy - Add integration tests for per-turn supplement hook * fix(memory): complete external provider integration * docs(memory): clarify external plugin data directory * test(memory): remove obsolete root mem0 script * fix(deploy): correct external memory plugin mounts * feat(memory): refine external provider management UI * fix(ci): resolve external memory quality gate failures * refactor(memory): reduce duplicated test setup * test(memory): share database test stubs * fix(memory): enable provider-controlled external ingest * test: align suite with merged migrations * test(memory): cover provider error and fanout paths * test(memory): cover ingestion service construction * fix(memory): support hosted Mem0 v3 writes * refactor(memory): use latest Mem0 API exclusively * fix(db): keep external memory schema in migration * refactor(memory): move runtime imports to module scope * docs(memory): add Mem0 Cloud E2E evidence * style(memory): compact external provider cards * style(memory): hide provider timeout summary * chore(db): update external memory migration date * docs(memory): remove PR documentation and evidence * chore: remove local backend launcher * refactor(memory): narrow external provider scope * fix(deploy): mount memory plugins in production compose * style(memory): use absolute backend imports | 19 天前 | |
feat(memory): Dreaming and versioned long-term memory (#3509) * feat(memory): implement Dreaming consolidation flow * fix(memory): skip previously promoted Dreaming candidates * fix(memory): satisfy Dreaming quality checks * test(memory): verify Dreaming against PostgreSQL * test(memory): simplify Dreaming exception assertion * feat(memory): complete Dreaming consolidation * fix(memory): remove unsafe JSON fence regex * ci(sonar): exclude duplicated Dreaming DDL * ci(sonar): configure automatic analysis scope * feat(memory): schedule automatic dreaming * fix(memory): show dreaming schedule without agents * refactor(memory): make dreaming user scoped * fix(memory): revive deleted dreaming schedules * fix(memory): recreate deleted dreaming schedules * feat(memory): preserve dreaming source metadata * refactor(memory): unify long-term context reads * test(memory): stub dreaming config constants * chore(memory): narrow dreaming deployment scope * test(frontend): isolate Playwright from production build * feat(dreaming): per-user thresholds, clear/undo LTM, compression waterfall, i18n Backend: - Add per-user configurable dreaming thresholds (min_score, min_recall_count, min_unique_queries) stored in memory_dreaming_schedule_t - Add clear/undo-clear endpoints for long-term memory with deactivated_version_id - Implement 3-tier compression waterfall: not_needed -> semantic -> mechanical_fallback - Add threshold columns to DB model and migrations (v2.5.0) - Add timeout handling for stuck dreaming progress Frontend: - Add threshold configuration UI in Dreaming tab (per-user editable) - Implement clear/undo flow with Option A: show cleared version card (V{n} (已清空) | 0 chars | no compression) instead of empty state - Add version history dropdown in current LTM section - Add comprehensive i18n support (en + zh) for all Dreaming UI elements - Fix expand/collapse with collapsible mode - Adjust layout to 2:1 ratio (thresholds vs automatic dreaming) SDK: - Update version_builder with compression status tracking Tests: - Add/update unit tests for compressor and version builder * fix(i18n): add missing i18n keys for base settings page - Replace hardcoded '基础设置' tab label with t('memoryManageModal.baseSettings') - Replace hardcoded page title/description with i18n keys - Replace hardcoded memory ability description with i18n key - Add memoryManageModal.baseSettingsDescription (zh/en) - Add memoryManageModal.memoryAbilityDescription (zh/en) * feat(dreaming): UI improvements and version switching fixes - Rename '启用 Dreaming' to '长期记忆Dreaming算法' (i18n zh/en) - Fill threshold default values directly instead of placeholder hints - Remove parameter tags from Dreaming tab header - Add version dropdown in cleared state card (after clearing LTM) - Add version dropdown in empty state (when no active version exists) - Make expected_active_version_id optional for version activation (allows switching versions when no active version exists) - Remove unused fetchDreamingParameters call from DreamingPanel - Add DreamingConfigCards component for base settings thresholds * style(dreaming): change thresholds to 3-column layout, right-align save button * feat(memory): publish dreaming summaries as user memory * refactor(memory): finalize dreaming memory architecture * fix(memory): resolve CI regressions * refactor(memory): normalize dreaming decisions * test(memory): raise dreaming patch coverage * fix(memory): align dreaming decision evidence schema * refactor(memory): clarify fidelity literal naming | 1 个月前 | |
feat(memory): complete external memory provider integration (#3690) * feat(memory): post-final-answer memory extraction via standalone LLM call Squash merge of feat/final-answer-based-memory (2 commits): - feat(memory): post-final-answer memory extraction via standalone LLM call - fix(test): update memory_tool_prompt assertions for new action-steps-only policy Adds automatic memory extraction after final_answer in _stream_agent_chunks(), with a standalone LLM-based extractor service and updated memory tool prompt policy. * feat(memory): add external_provider_top_k and external_provider_timeout to memory config system - Add external_provider_top_k (default: 20) and external_provider_timeout (default: 30s) fields to MemoryUserConfig - Add getter/setter functions in memory_config_service.py with validation (top_k: 1-100, timeout: 1-120s) - Add API endpoints in memory_config_app.py for setting these configurations - Add UI controls in MemoryManager.tsx with input fields and validation - Update frontend memoryService.ts to load/save these configurations - All changes respect memory_switch setting (disabled when memory is off) * feat(memory): wire external provider search into create_agent_config() - Query external providers at session start using configured top_k and timeout - Convert MemorySearchResult to ExternalMemoryItem format - Pass external_results to memory_context_service.build_context() - Add graceful error handling (failures don't break session start) - Respects memory_switch and external provider enabled settings - Logs external provider search results and failures * test(memory): add integration tests for session-start external retrieval - Test full flow with multiple external providers - Test provider timeout with partial results - Test all providers fail gracefully (session continues) - Test MMR dedup of duplicate content - Test token budget enforcement - All tests use mocks and follow existing integration test patterns * feat(memory): implement Phase 3 external memory provider system Backend: - Add memory_provider_config_t and memory_provider_config_param_t tables for EAV configuration - Add memory_external_ingest_event_log_t for audit logging - Implement MemoryProviderConfigService for CRUD operations with validation - Implement MemoryExternalProviderService for provider lifecycle management - Implement MemoryIngestionEventService for ingest event handling - Implement MemoryProviderPluginLoader for dynamic plugin loading - Add memory_provider_app.py with REST API endpoints - Add transparent proxy integration in memory_backend_adapter.py - Add per-turn supplement hook in agent_service.py - Add content hash dedup in normalizer.py - Add elastic MMR candidate pool in mmr.py - Add ExternalMemoryItem and related models to SDK Frontend: - Add ProviderConfigCard component for provider list display - Add ProviderConfigDialog for provider configuration - Add providerService for API integration Deployment: - Add SQL migration v2.5.0_0814_external_memory_provider.sql - Update docker-compose.yml with plugin volume mapping - Update k8s manifests with plugin directory configuration - Update .env.example with new environment variables Tests: - Add comprehensive unit tests for all backend services - Add integration tests for transparent proxy - Add integration tests for per-turn supplement hook * fix(memory): complete external provider integration * docs(memory): clarify external plugin data directory * test(memory): remove obsolete root mem0 script * fix(deploy): correct external memory plugin mounts * feat(memory): refine external provider management UI * fix(ci): resolve external memory quality gate failures * refactor(memory): reduce duplicated test setup * test(memory): share database test stubs * fix(memory): enable provider-controlled external ingest * test: align suite with merged migrations * test(memory): cover provider error and fanout paths * test(memory): cover ingestion service construction * fix(memory): support hosted Mem0 v3 writes * refactor(memory): use latest Mem0 API exclusively * fix(db): keep external memory schema in migration * refactor(memory): move runtime imports to module scope * docs(memory): add Mem0 Cloud E2E evidence * style(memory): compact external provider cards * style(memory): hide provider timeout summary * chore(db): update external memory migration date * docs(memory): remove PR documentation and evidence * chore: remove local backend launcher * refactor(memory): narrow external provider scope * fix(deploy): mount memory plugins in production compose * style(memory): use absolute backend imports | 19 天前 | |
feat(memory): complete external memory provider integration (#3690) * feat(memory): post-final-answer memory extraction via standalone LLM call Squash merge of feat/final-answer-based-memory (2 commits): - feat(memory): post-final-answer memory extraction via standalone LLM call - fix(test): update memory_tool_prompt assertions for new action-steps-only policy Adds automatic memory extraction after final_answer in _stream_agent_chunks(), with a standalone LLM-based extractor service and updated memory tool prompt policy. * feat(memory): add external_provider_top_k and external_provider_timeout to memory config system - Add external_provider_top_k (default: 20) and external_provider_timeout (default: 30s) fields to MemoryUserConfig - Add getter/setter functions in memory_config_service.py with validation (top_k: 1-100, timeout: 1-120s) - Add API endpoints in memory_config_app.py for setting these configurations - Add UI controls in MemoryManager.tsx with input fields and validation - Update frontend memoryService.ts to load/save these configurations - All changes respect memory_switch setting (disabled when memory is off) * feat(memory): wire external provider search into create_agent_config() - Query external providers at session start using configured top_k and timeout - Convert MemorySearchResult to ExternalMemoryItem format - Pass external_results to memory_context_service.build_context() - Add graceful error handling (failures don't break session start) - Respects memory_switch and external provider enabled settings - Logs external provider search results and failures * test(memory): add integration tests for session-start external retrieval - Test full flow with multiple external providers - Test provider timeout with partial results - Test all providers fail gracefully (session continues) - Test MMR dedup of duplicate content - Test token budget enforcement - All tests use mocks and follow existing integration test patterns * feat(memory): implement Phase 3 external memory provider system Backend: - Add memory_provider_config_t and memory_provider_config_param_t tables for EAV configuration - Add memory_external_ingest_event_log_t for audit logging - Implement MemoryProviderConfigService for CRUD operations with validation - Implement MemoryExternalProviderService for provider lifecycle management - Implement MemoryIngestionEventService for ingest event handling - Implement MemoryProviderPluginLoader for dynamic plugin loading - Add memory_provider_app.py with REST API endpoints - Add transparent proxy integration in memory_backend_adapter.py - Add per-turn supplement hook in agent_service.py - Add content hash dedup in normalizer.py - Add elastic MMR candidate pool in mmr.py - Add ExternalMemoryItem and related models to SDK Frontend: - Add ProviderConfigCard component for provider list display - Add ProviderConfigDialog for provider configuration - Add providerService for API integration Deployment: - Add SQL migration v2.5.0_0814_external_memory_provider.sql - Update docker-compose.yml with plugin volume mapping - Update k8s manifests with plugin directory configuration - Update .env.example with new environment variables Tests: - Add comprehensive unit tests for all backend services - Add integration tests for transparent proxy - Add integration tests for per-turn supplement hook * fix(memory): complete external provider integration * docs(memory): clarify external plugin data directory * test(memory): remove obsolete root mem0 script * fix(deploy): correct external memory plugin mounts * feat(memory): refine external provider management UI * fix(ci): resolve external memory quality gate failures * refactor(memory): reduce duplicated test setup * test(memory): share database test stubs * fix(memory): enable provider-controlled external ingest * test: align suite with merged migrations * test(memory): cover provider error and fanout paths * test(memory): cover ingestion service construction * fix(memory): support hosted Mem0 v3 writes * refactor(memory): use latest Mem0 API exclusively * fix(db): keep external memory schema in migration * refactor(memory): move runtime imports to module scope * docs(memory): add Mem0 Cloud E2E evidence * style(memory): compact external provider cards * style(memory): hide provider timeout summary * chore(db): update external memory migration date * docs(memory): remove PR documentation and evidence * chore: remove local backend launcher * refactor(memory): narrow external provider scope * fix(deploy): mount memory plugins in production compose * style(memory): use absolute backend imports | 19 天前 | |
feat(memory): Dreaming and versioned long-term memory (#3509) * feat(memory): implement Dreaming consolidation flow * fix(memory): skip previously promoted Dreaming candidates * fix(memory): satisfy Dreaming quality checks * test(memory): verify Dreaming against PostgreSQL * test(memory): simplify Dreaming exception assertion * feat(memory): complete Dreaming consolidation * fix(memory): remove unsafe JSON fence regex * ci(sonar): exclude duplicated Dreaming DDL * ci(sonar): configure automatic analysis scope * feat(memory): schedule automatic dreaming * fix(memory): show dreaming schedule without agents * refactor(memory): make dreaming user scoped * fix(memory): revive deleted dreaming schedules * fix(memory): recreate deleted dreaming schedules * feat(memory): preserve dreaming source metadata * refactor(memory): unify long-term context reads * test(memory): stub dreaming config constants * chore(memory): narrow dreaming deployment scope * test(frontend): isolate Playwright from production build * feat(dreaming): per-user thresholds, clear/undo LTM, compression waterfall, i18n Backend: - Add per-user configurable dreaming thresholds (min_score, min_recall_count, min_unique_queries) stored in memory_dreaming_schedule_t - Add clear/undo-clear endpoints for long-term memory with deactivated_version_id - Implement 3-tier compression waterfall: not_needed -> semantic -> mechanical_fallback - Add threshold columns to DB model and migrations (v2.5.0) - Add timeout handling for stuck dreaming progress Frontend: - Add threshold configuration UI in Dreaming tab (per-user editable) - Implement clear/undo flow with Option A: show cleared version card (V{n} (已清空) | 0 chars | no compression) instead of empty state - Add version history dropdown in current LTM section - Add comprehensive i18n support (en + zh) for all Dreaming UI elements - Fix expand/collapse with collapsible mode - Adjust layout to 2:1 ratio (thresholds vs automatic dreaming) SDK: - Update version_builder with compression status tracking Tests: - Add/update unit tests for compressor and version builder * fix(i18n): add missing i18n keys for base settings page - Replace hardcoded '基础设置' tab label with t('memoryManageModal.baseSettings') - Replace hardcoded page title/description with i18n keys - Replace hardcoded memory ability description with i18n key - Add memoryManageModal.baseSettingsDescription (zh/en) - Add memoryManageModal.memoryAbilityDescription (zh/en) * feat(dreaming): UI improvements and version switching fixes - Rename '启用 Dreaming' to '长期记忆Dreaming算法' (i18n zh/en) - Fill threshold default values directly instead of placeholder hints - Remove parameter tags from Dreaming tab header - Add version dropdown in cleared state card (after clearing LTM) - Add version dropdown in empty state (when no active version exists) - Make expected_active_version_id optional for version activation (allows switching versions when no active version exists) - Remove unused fetchDreamingParameters call from DreamingPanel - Add DreamingConfigCards component for base settings thresholds * style(dreaming): change thresholds to 3-column layout, right-align save button * feat(memory): publish dreaming summaries as user memory * refactor(memory): finalize dreaming memory architecture * fix(memory): resolve CI regressions * refactor(memory): normalize dreaming decisions * test(memory): raise dreaming patch coverage * fix(memory): align dreaming decision evidence schema * refactor(memory): clarify fidelity literal naming | 1 个月前 | |
feat(memory): Dreaming and versioned long-term memory (#3509) * feat(memory): implement Dreaming consolidation flow * fix(memory): skip previously promoted Dreaming candidates * fix(memory): satisfy Dreaming quality checks * test(memory): verify Dreaming against PostgreSQL * test(memory): simplify Dreaming exception assertion * feat(memory): complete Dreaming consolidation * fix(memory): remove unsafe JSON fence regex * ci(sonar): exclude duplicated Dreaming DDL * ci(sonar): configure automatic analysis scope * feat(memory): schedule automatic dreaming * fix(memory): show dreaming schedule without agents * refactor(memory): make dreaming user scoped * fix(memory): revive deleted dreaming schedules * fix(memory): recreate deleted dreaming schedules * feat(memory): preserve dreaming source metadata * refactor(memory): unify long-term context reads * test(memory): stub dreaming config constants * chore(memory): narrow dreaming deployment scope * test(frontend): isolate Playwright from production build * feat(dreaming): per-user thresholds, clear/undo LTM, compression waterfall, i18n Backend: - Add per-user configurable dreaming thresholds (min_score, min_recall_count, min_unique_queries) stored in memory_dreaming_schedule_t - Add clear/undo-clear endpoints for long-term memory with deactivated_version_id - Implement 3-tier compression waterfall: not_needed -> semantic -> mechanical_fallback - Add threshold columns to DB model and migrations (v2.5.0) - Add timeout handling for stuck dreaming progress Frontend: - Add threshold configuration UI in Dreaming tab (per-user editable) - Implement clear/undo flow with Option A: show cleared version card (V{n} (已清空) | 0 chars | no compression) instead of empty state - Add version history dropdown in current LTM section - Add comprehensive i18n support (en + zh) for all Dreaming UI elements - Fix expand/collapse with collapsible mode - Adjust layout to 2:1 ratio (thresholds vs automatic dreaming) SDK: - Update version_builder with compression status tracking Tests: - Add/update unit tests for compressor and version builder * fix(i18n): add missing i18n keys for base settings page - Replace hardcoded '基础设置' tab label with t('memoryManageModal.baseSettings') - Replace hardcoded page title/description with i18n keys - Replace hardcoded memory ability description with i18n key - Add memoryManageModal.baseSettingsDescription (zh/en) - Add memoryManageModal.memoryAbilityDescription (zh/en) * feat(dreaming): UI improvements and version switching fixes - Rename '启用 Dreaming' to '长期记忆Dreaming算法' (i18n zh/en) - Fill threshold default values directly instead of placeholder hints - Remove parameter tags from Dreaming tab header - Add version dropdown in cleared state card (after clearing LTM) - Add version dropdown in empty state (when no active version exists) - Make expected_active_version_id optional for version activation (allows switching versions when no active version exists) - Remove unused fetchDreamingParameters call from DreamingPanel - Add DreamingConfigCards component for base settings thresholds * style(dreaming): change thresholds to 3-column layout, right-align save button * feat(memory): publish dreaming summaries as user memory * refactor(memory): finalize dreaming memory architecture * fix(memory): resolve CI regressions * refactor(memory): normalize dreaming decisions * test(memory): raise dreaming patch coverage * fix(memory): align dreaming decision evidence schema * refactor(memory): clarify fidelity literal naming | 1 个月前 | |
Feat hzw 20260810 (#3920) * feat:model page * feat: 接入方式优化-需要回退 * ♻️ Refactor: unify model edit dialog onto ModelAddDialogV2 - ModelAddDialogV2: add model prop for edit mode (prefill custom form from existing model, default to 自定义接入 tab, call updateSingleModel/updateManageTenantModel on submit instead of add) - modelConfig.tsx: handleCardEdit now renders ModelAddDialogV2 with model prop instead of ModelEditDialogV2 * Feature: model capacity auto-lookup, custom param validation, and type inference fixes Capacity suggestion (catalog -> bundled LiteLLM JSON -> default): - model_capacity_suggestion_service: remove LLM self-report fallback (dead code, providers without web search always return null); add _litellm_lookup reading the bundled LiteLLM model_prices_and_context_window.json (3818 models) as the second source; match by provider/name and bare-name final segment, preferring entries with both max_input and max_output - main Dockerfile: bundle LiteLLM JSON at build time (works offline / no VPN) - suggest_capacity: try LiteLLM bare-name match even when provider is uninferable (base_url still empty while typing) Model add/edit dialog (V2): - custom tab: debounced auto-lookup on model name (500ms) fills empty capacity fields only; configured tag reflects lookup result, not display_name presence - connectivity probe no longer mutates capacity fields; probe carries temperature/top_p/extra_params so invalid __custom__ params surface at verify time as a 400 instead of failing at runtime - __custom__ numeric strings coerce to numbers (top_k=50, not 50); fix .trim crash on numeric values in edit mode - batch tab: add client-side model name search filter; per-row connectivity fills capacity from suggestion - edit mode: onConnectivityChange reports probe result back to the model list so connect_status refreshes in place Model config list: - verifyModels now probes ALL models in the list (was: default-model selection only), updating rows in parallel - remove misleading provider model-count badge; fix ModelConnectStatus duplicate declaration; drop unused DEFAULT_* imports Type inference (_infer_model_type_from_name): - match full name AND final path segment so repo-prefixed ids from aggregators (BAAI/bge-m3, Pro/..., deepseek-ai/...) classify correctly - add contains-based rules aligned with develop TokenPony classifier: embedding/rerank/stt/tts mid-name, vlm3 (omni/video), vlm2 (image-gen keywords), vlm (vision/visual/ocr/vl-segment) Connectivity service: - port develop _embedding_url_candidates multi-candidate probe (normalized /embeddings URL first, then as-given) for embedding/multi_embedding - _config_to_context: __custom__ KV pairs flow into extra_body at runtime - openai_llm check_connectivity probe carries inference params Type fixes: AgentDraft includes model_params_override; ModelEditDialogV2 keyMap adds vlm4; agent-prompt model override config dialog typing * Fix: rename llmModels to availableLlmModels after develop merge (useModelList API rename) * Fix: normalize rerank probe URL to the rerank endpoint The batch-import connectivity probe passed the bare provider root (e.g. https://api.siliconflow.cn/v1/) straight to the rerank adapter, which POSTs the URL as-is -> 404 -> unavailable even though the model is fine. prepare_model_dict already appends /rerank when SAVING the model, so probe-time and save-time URLs disagreed. Mirror that munging in _perform_connectivity_check: dashscope roots get the api/v1 .../services/rerank/text-rerank/text-rerank path, others get {root}/rerank. Already-normalized URLs pass through untouched. This matches the embedding probe /embeddings normalization. * Fix: carry verified connect_status into batch-created model records Batch submit requires every enabled row to pass the connectivity probe (hasUnchecked gate), but the verified available result lived only in dialog state — the create endpoints never received it, so the backend reset connect_status to not_detected on insert and the freshly imported models showed as unverified in the list. The backend already honors this (create_model_for_tenant: connect_status = payload or NOT_DETECTED; ModelRequest has the field) — only the frontend was not sending it. Thread connectStatus through addCustomModel / createManageTenantModel request bodies and set it from the row state at batch submit time. * Remove legacy modify-or-delete models button and ModelDeleteDialog The button opened a 2000-line legacy panel whose single-row edit/delete duplicated the per-row actions (and used the old V1 edit dialog), and whose only unique capability was a narrow bulk-edit (same-provider key, timeout, capacity override). Bulk delete did not exist - deletion inside the panel was still one-by-one. - drop the top-bar button (Can model:update wrapper) - drop the capacity-coverage alert action that opened the same panel - remove isDeleteModalOpen state, ModelDeleteDialog import and instance - delete the orphaned ModelDeleteDialog.tsx (ModelEditDialog stays - it is still referenced by resource-manage ModelList) * Fix: show Chinese type labels for vlm2/vlm3/vlm4 in model list The type column rendered t(`model.type.${type}`) directly, but the locale files have no model.type.vlm2/vlm3/vlm4 keys (they are keyed by semantic name: imageGeneration / videoUnderstanding / audioUnderstanding), so those rows displayed the raw id string. Add the same id-to-semantic-key mapping the add dialog uses, covering all ten types. Also aligns vlm to the dialog label (image understanding) instead of the legacy model.type.vlm wording. * Fix: address CodeQL security alerts in provider fetch and catalog endpoints SSRF (critical) in openai_provider.get_models: the operator-supplied base_url was fetched as-is. Add _validate_provider_base_url guard before the request: scheme must be http/https, host required, private / link-local / multicast / reserved IP literals rejected (cloud metadata endpoints, internal routers). Plain DNS names and the documented localhost/127.0.0.1 local-LLM exemption are allowed. Validation errors flow through the existing _classify_provider_error path as provider fetch failures. Information exposure (medium x5) in model_managment_app catalog endpoints: the exception text was interpolated into the JSON response body, which can leak stack traces / internal details to the caller. Replace with fixed messages; the exception detail is already logged server-side via logger.warning. Affected: /catalog/all, /catalog/providers, /catalog/inference_field_specs, /catalog/providers/{provider}/models, /catalog/providers/{provider}/models/{model_name}. * Fix: address Copilot review findings in tests and catalog wiring Real bugs (blocked the unit-test CI job): - test_model_consts.py: corrupted multi-byte string literal (truncated mid-character) made the module unparseable; restore the intended default title assertion. - test_model_catalog_loader.py: read p.provider_key / get_model_profile(p.provider_key, ...) but the Pydantic ModelCatalogProviderInfo model exposes id; align to the actual field. Latent issues flagged by review: - model_managment_app.py: the catalog-import fallback handler logged via the module logger before it was initialized, raising NameError on the graceful-degradation path; log via logging.getLogger directly. - useModelCatalog.ts + types: provider summary declared provider_key/supported_model_types while /catalog/providers serializes id/supported_types (Pydantic dump). Align the frontend type and hook maps to the wire names. ModelCatalogModelEntry.provider_key stays as is - the /catalog/all model entries do carry provider_key. * Fix: catalog loader test must accept normalized model entries The loader normalizes each catalog model entry into a ModelCatalogProfile instance (not a raw dict), so asserting model_type in model_cfg fails with TypeError on the Pydantic model. Accept both the raw dict form and the normalized instance via getattr. Verified in-container: 8 passed. * Fix: sync model health tests with inference params and rerank URL normalization * Fix: sync model tests with unified provider dispatch and consts.model imports * Fix: register consts.model and nexent.core.agents stubs in tests blocked by model_management_db import chain * Fix: harden provider SSRF guard with post-DNS IP validation and restore TLS verification * Fix: resolve SonarCloud quality gate findings (complexity, log injection, warnings, duplication) * Fix: reduce cognitive complexity and eliminate duplicated blocks flagged by SonarCloud * Fix: remove legacy dialogs duplicated by V2, sanitize catalog logging, resolve remaining SonarCloud issues * Fix: sanitize catalog version with json.dumps and clear remaining SonarCloud issues * Fix: stop logging file-derived catalog version and flatten handleSave max-tokens logic * Fix: resolve SDK httpx Timeout class for httpx2-based OpenAI builds * Fix: route capacity suggestion through managed thread pool and make stopwords loading race-tolerant --------- Co-authored-by: hzw <hzw@qq.com> Co-authored-by: ljy <ljy@DESKTOP-65OBISN.(none)> | 8 天前 | |
✨ Feat: Add in-app notifications for agent repository review workflow (#3477) * ✨ Feat: Add in-app notifications for agent repository review workflow Notify publishers and reviewers on submit/approve/reject, with navbar bell UI, review opinion content, and deep-link navigation into agent space. * ✨ Feat: Add in-app notifications for agent repository review workflow Notify publishers and reviewers on submit/approve/reject, with navbar bell UI, review opinion content, and deep-link navigation into agent space. * ✨ Feat: Add in-app notifications for agent repository review workflow Notify publishers and reviewers on submit/approve/reject, with navbar bell UI, review opinion content, and deep-link navigation into agent space. * ✨ Feat: Add in-app notifications for agent repository review workflow Notify publishers and reviewers on submit/approve/reject, with navbar bell UI, review opinion content, and deep-link navigation into agent space. | 2 个月前 | |
Refactor OAuth implementation and enhance account linking features * openspec初始化 * oauth spec开发结果 * oauth 单元测试 * oauth 重定向修复 * oauth 重定向修复 * oauth 重定向修复 * oauth 抽象实现 * gde provider * gde provider * enhance unlink_account logic to check for password authentication before unlinking * refactor OAuthAccountsSection to load enabled providers and improve account unlinking logic * add OAuth linking functionality with state management and error handling * refactor OAuth account deletion logic to use direct deletion and update related tests * update GDE OAuth configuration to use environment variables for URLs and client IDs * add SSL verification configuration for OAuth requests and update context handling * remove hardcoded OAuth credentials from const.py and update .env.example * remove avatar_url references from user info handling and update email fallback logic * refactor user identity handling in OAuth account unlinking logic * update OAuthAccountsSection to simplify display logic for linked accounts * refactor OAuth user binding logic to check for existing accounts before creating new users * 删除冗余文件 * 删除冗余文件 * add user OAuth account table and update trigger for third-party logins * 修复单元测试 * 删除冗余代码 * k8s同步oauth配置 * 软删除时需添加delete_flag="Y"的筛选条件 * 用户删除的时候将oauth表中delete_flag设置为Y * 优化import * 移除无用的rebind_oauth_account函数调用,并在用户已绑定其他账户时抛出OAuthLinkError * clean code * 补充ut * 补充单元测试 | 4 个月前 | |
♻️ Refactor API to MCP service #2187 (#2778) * ♻️ Refactor API to MCP service #2187 [Specification Detail] 1. Refactor the API into an MCP service, and manage the transformation from a service perspective. 2. Modify database and front-end/back-end implementation. 3. Modify test cases. * ♻️ Refactor API to MCP service #2187 [Specification Detail] 1. Add test cases. | 5 个月前 | |
♻️ Backend code cleanup and import organization (database/) #1037 | 1 年前 | |
feat: add prompt template management for agent generation (#2925) * feat: add prompt template management for agent generation * feat: add prompt template management for agent generation * feat: add prompt template management for agent generation * feat: add prompt template management for agent generation * feat: add prompt template management for agent generation * feat: add prompt template management for agent generation * feat: add prompt template management for agent generation * feat: add prompt template management for agent generation * feat: add prompt template management for agent generation * feat: add prompt template management for agent generation * feat: add prompt template management for agent generation | 4 个月前 | |
feat: MCP space - group permissions and field-level sharing (#3470) * basic * mcp用户权限 * test case fix * test case fix * test case fix * test case fix * test case fix * test case fix * add test case * fix test case * add test case * fix test case * add test case * add test case * sql migrations * MCP space UI * agent配置可见性修改 * 本地镜像标签可见性修改 * 存量mcp权限设置 | 2 个月前 | |
♻️ [WIP] User Management: Add initial data to role_permission_t, update /current_user_info interface to fetch | 7 个月前 | |
✨ Feature: Sandbox adaptation for Anthropic's skills. (#3839) * ✨ Feature: Sandbox adaptation for Anthropic's skills. * ✨ Feature: Sandbox adaptation for Anthropic's skills. * ✨ Feature: Sandbox adaptation for Anthropic's skills. | 21 天前 | |
feat: refactor label system (#3809) * fix(tag-mgmt): register legacy exception handlers + fix filter endpoint sync + add value usage index - backend/apps/app_factory.py: register handlers for legacy domain exceptions (UnauthorizedError->401, ForbiddenError->403, LimitExceededError->429, ValidationError->400, NotFoundException->404, DuplicateError->409, TagManagementConflictError->409, SignatureValidationError->401) so they no longer fall through to the generic 500 handler. Verified live: unauthenticated tag endpoints now return 401 instead of 500. - backend/apps/tag_management_app.py: convert filter_resource_tag_assignments from async/await to sync/_run to match the synchronous TagManagementDB.filter_authorized_resource_ids (which returns a dict, not a coroutine). Fixes TypeError -> HTTP 500 on the filter endpoint. - deploy/sql: add partial index idx_resource_tag_assignment_value (tenant_id, value_id, delete_flag) WHERE delete_flag='N' via new migration v2.5.4_0820_tag_value_usage_index.sql and init.sql. Benchmark at capacity limits (100 defs / 100k values / 50k assignments) showed value-usage-count was a 102ms Seq Scan; with the index it becomes a 1.28ms Index Only Scan. Idempotent (IF NOT EXISTS). * feat(tag-mgmt): unified tag management for KB/agent/MCP/skill resources - Add tenant-scoped tag libraries, definitions, values and assignments - Wire tag chips and filters into knowledge base, agent and MCP pages - Add document tag projection ledger with provider sync - Clean up assignments when KB/agent/MCP/skill resources are deleted - Add preflight and migration scripts v2.5.0-v2.5.3 - Cache assignment reads on list pages to avoid per-row HTTP requests * fix(tag-mgmt): migrate tag assignment entries and enable tag search for mine agents * feat(tag-mgmt): complete unified tag assignment flows * feat(tag-management): unify repository tag filters * feat(tag-management): localize and search agent tags * feat(tag-management): unify repository tag filtering * fix(tag-management): migrate legacy agent categories * fix(tag-management): restore rebased tag UI * feat(tag-management): support no-value tags * fix(tag-management): unblock CI checks * chore(sonar): exclude mirrored tag SQL from CPD * test(tag-management): raise patch coverage * fix(tag-management): address review feedback * fix: migrate tag services after management split | 20 天前 | |
fix: harden quota, tag, model and API-key contracts found by daily test suite (#4002) - quota: reject negative GB/MB inputs and warning>=critical threshold pairs (previously persisted as 200 with semantically inverted config) - api-key: mask access_key in /api-keys and /user/tokens list responses; only create/refresh may return the full secret once - tag: translate the DB trigger's 'Tag assignment limit exceeded' (without the 'Resource ' prefix) into a structured 409, and flush replacement deletes before inserts so a full tag replacement no longer trips the assignment-capacity trigger - model: propagate ValueError from create/batch_create so duplicate display names map to 409 and malformed batch entries to 422 instead of 500; include model_type in /model/llm_list items; tolerate quick-config entries without model_repo in get_model_name_from_config - test: align model service tests with the ValueError passthrough contract Co-authored-by: chase <byzhangxin11@126.com> | 1 天前 | |
0930需求-Nexent规格表:完善租户资源限制错误码、429响应及中英文提示 (#3966) * fix: standardize tenant resource limit errors * fix: roll back rejected tenant user registrations * fix: stabilize tenant limit test imports * test: import HTTPStatus in northbound tests * test: cover tenant resource limit error paths * config: make tenant resource limits configurable | 2 天前 | |
fix: harden quota, tag, model and API-key contracts found by daily test suite (#4002) - quota: reject negative GB/MB inputs and warning>=critical threshold pairs (previously persisted as 200 with semantically inverted config) - api-key: mask access_key in /api-keys and /user/tokens list responses; only create/refresh may return the full secret once - tag: translate the DB trigger's 'Tag assignment limit exceeded' (without the 'Resource ' prefix) into a structured 409, and flush replacement deletes before inserts so a full tag replacement no longer trips the assignment-capacity trigger - model: propagate ValueError from create/batch_create so duplicate display names map to 409 and malformed batch entries to 422 instead of 500; include model_type in /model/llm_list items; tolerate quick-config entries without model_repo in get_model_name_from_config - test: align model service tests with the ValueError passthrough contract Co-authored-by: chase <byzhangxin11@126.com> | 1 天前 | |
fix(mcp): unbind deleted tools from agent drafts (#3937) * fix(mcp): unbind deleted tools from agent drafts Soft-delete draft tool instances when removing an MCP service while preserving published snapshots. Stop MCP record deletion when cleanup fails. Refs #3935 Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * fix(agent): refresh draft after MCP deletion Reload the current Agent draft after successful MCP server or container deletion so removed tool bindings disappear immediately from the configuration page. Refs #3935 Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * fix(mcp): prevent stale agent bindings after deletion Drain pending Agent draft saves before deleting an MCP service, then refresh the draft after deletion. Ignore unavailable tool IDs in stale Agent updates so deleted bindings cannot be recreated.\n\nRefs #3935\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5 * fix(agent-version): refresh current version after mutations Share the page-level agent version state with the management panel so publish and rollback render the latest current version. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * fix(agent): label collaborative agent version names Distinguish custom version names from numeric version identifiers in the collaborative agent selector with localized labels. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * delete i18n --------- Co-authored-by: Codex <noreply@openai.com> | 7 天前 | |
0930需求-Nexent规格表:完善租户资源限制错误码、429响应及中英文提示 (#3966) * fix: standardize tenant resource limit errors * fix: roll back rejected tenant user registrations * fix: stabilize tenant limit test imports * test: import HTTPStatus in northbound tests * test: cover tenant resource limit error paths * config: make tenant resource limits configurable | 2 天前 | |
♻️ Translate error messages and Chinese comments in backend code into English #1131 | 1 年前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 1 年前 | ||
| 20 天前 | ||
| 20 天前 | ||
| 8 天前 | ||
| 3 天前 | ||
| 2 个月前 | ||
| 3 天前 | ||
| 29 天前 | ||
| 3 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 1 天前 | ||
| 2 个月前 | ||
| 1 天前 | ||
| 20 天前 | ||
| 1 个月前 | ||
| 20 天前 | ||
| 1 个月前 | ||
| 2 天前 | ||
| 3 个月前 | ||
| 29 天前 | ||
| 16 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 11 个月前 | ||
| 20 天前 | ||
| 19 天前 | ||
| 1 个月前 | ||
| 19 天前 | ||
| 19 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 8 天前 | ||
| 2 个月前 | ||
| 4 个月前 | ||
| 5 个月前 | ||
| 1 年前 | ||
| 4 个月前 | ||
| 2 个月前 | ||
| 7 个月前 | ||
| 21 天前 | ||
| 20 天前 | ||
| 1 天前 | ||
| 2 天前 | ||
| 1 天前 | ||
| 7 天前 | ||
| 2 天前 | ||
| 1 年前 |