| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
✨ Feature: Development of Agent Workbench Features (#4010) * ✨ Feature: Development of Agent Workbench Features * ✨ Feature: Development of Agent Workbench Features * ✨ Feature: Development of Agent Workbench Features * 🐛 Bugfix: The upload_to_s3 and download_from_s3 tools do not support user configuration. * feat:add-workbench * 工作台知识库选择依据aidp开关 * feat:工作台前端风格统一优化 * fix(workbench): restore chat modes and tenant model selection * fix(workbench): restore header and system skills * fix(workbench): hide built-in skills from composer * fix(workbench): restore managed agent invocation * fix(workbench): authorize hidden system agent for HITL * fix(workbench): persist creation history and retry branches * test(workbench): align legacy Skill API mocks with creation history * feat(workbench): separate chat entrypoints and refine creation UX * fix: restore workbench attachment reuse and landing layout * feat(workbench): gate workbench with deployment flag * feat(workbench): gate workbench with deployment flag * feat(workbench): Resolved conflicts and fixed an issue where historical sessions became unavailable after deleting and recreating the agent. * feat(workbench): Fix frontend pipeline build issues. * test(workbench): fix unit test isolation * test(workbench): raise patch coverage above threshold * refactor(workbench): consolidate database migration * fix(workbench): align reasoning defaults and skill card actions * test(workbench): use complete Agent fixture for reasoning defaults --------- Co-authored-by: dongjibao2001 <332722455@qq.com> | 8 小时前 | |
fix(agents): show related agent version labels (#3906) * docs(agents): define collaborative version label Document the approved version-name label behavior and implementation plan.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): show related agent version labels Display each internal collaborative agent's saved version name beside its name.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): distinguish related agent versions Show version number and name when selecting an internal agent, while keeping related agent labels compact with the saved version number.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): guard version detail during agent switch Skip version-detail requests while an agent switch is pending or no published version exists. This prevents stale agent state from requesting a nonexistent version.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * delete frontend * delete plan * fix(agents): initialize agent before route switch Keep the active agent and URL synchronized by updating the route only after the selected agent data has been loaded into the store.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): preserve target route during selector load Set the selected agent URL before asynchronous loading so URL synchronization cannot reload the previous agent after initialization.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): centralize selector synchronization Use the URL as the sole selection source and load the selected agent only from its synchronization effect, preventing competing route and store updates.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex | 14 天前 | |
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> | 8 天前 | |
fix(agents): show related agent version labels (#3906) * docs(agents): define collaborative version label Document the approved version-name label behavior and implementation plan.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): show related agent version labels Display each internal collaborative agent's saved version name beside its name.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): distinguish related agent versions Show version number and name when selecting an internal agent, while keeping related agent labels compact with the saved version number.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): guard version detail during agent switch Skip version-detail requests while an agent switch is pending or no published version exists. This prevents stale agent state from requesting a nonexistent version.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * delete frontend * delete plan * fix(agents): initialize agent before route switch Keep the active agent and URL synchronized by updating the route only after the selected agent data has been loaded into the store.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): preserve target route during selector load Set the selected agent URL before asynchronous loading so URL synchronization cannot reload the previous agent after initialization.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): centralize selector synchronization Use the URL as the sole selection source and load the selected agent only from its synchronization effect, preventing competing route and store updates.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex | 14 天前 | |
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> | 2 天前 | |
♻️ Refactor: Refactored ReAct recoverable exceptions (#3915) * 🐛 Bugfix: Changed ReAct recoverable exceptions to yellow warnings. (#3897) * 🐛 Bugfix: Changed ReAct recoverable exceptions to yellow warnings. * Support alternate reasoning stream fields (#3863) * Support alternate reasoning stream fields * Test support for alternate reasoning field in OpenAI streaming * Support reasoning field in LLM stream chunks * Test alternate reasoning fields in LLM prompt generation --------- Co-authored-by: hhhhsc <name> * 🧪 Test: Add warning process type to NexentAgent mock --------- Co-authored-by: hhhhsc701 <56435672+hhhhsc701@users.noreply.github.com> * ♻️ Refactor: Refactored ReAct recoverable exceptions: changed to gray text, limited to a maximum of 3 lines. --------- Co-authored-by: hhhhsc701 <56435672+hhhhsc701@users.noreply.github.com> | 10 天前 | |
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> | 8 天前 | |
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> | 30 天前 | |
fix: generate conversation titles with session model (#3898) (#3919) (cherry picked from commit 68b99763e76ada0164aa6436e65d6bd47e34dfa7) | 9 天前 | |
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> | 30 天前 | |
fix(frontend): prevent knowledge preview refresh during polling (#3947) | 7 天前 | |
🐛 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 | 4 天前 | |
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> | 2 天前 | |
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> | 30 天前 | |
🐛bugfix:Fix AIDP knowledge base saving and session vector model prompts (#3918) * bugfix: 修改aidp知识库信息保存 * addtest * bugfix:修复会话页面频繁跳出向量模型未配置提示 | 10 天前 | |
✨Feature: 在新旧版对话窗口中添加消息时间戳 (#3732) * feat/display database message timestamps * add Timestamps to both the new and old versions of the conversation page * resolve pagination and timestamp adapter conflict * remove irrelevant methods * Revert "remove irrelevant methods" This reverts commit 8d17c8a1c6bc284c81ef8556f03465cfb18090db. --------- Co-authored-by: DoYX <du.yuxiao@gmail.com> | 29 天前 | |
fix(newchat): restore conversation after returning (#3908) * fix(newchat): restore conversation after returning Switch to a fresh thread before returning to the agent landing page so the previous conversation can be selected and rendered again. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * fix(hotfix): sync remaining v2.5.1 fixes Port deployment-aware knowledge tool filtering, historical conversation timing, and parallel tool-call completion from #3895. Exclude the already handled empty agent input fix. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 --------- Co-authored-by: Codex <noreply@openai.com> Co-authored-by: panyehong <2655992392@qq.com> | 9 天前 | |
feat(agents): support model priority sorting (#3914) * docs(agents): define collaborative version label Document the approved version-name label behavior and implementation plan.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): show related agent version labels Display each internal collaborative agent's saved version name beside its name.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): distinguish related agent versions Show version number and name when selecting an internal agent, while keeping related agent labels compact with the saved version number.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): guard version detail during agent switch Skip version-detail requests while an agent switch is pending or no published version exists. This prevents stale agent state from requesting a nonexistent version.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * delete frontend * delete plan * fix(agents): initialize agent before route switch Keep the active agent and URL synchronized by updating the route only after the selected agent data has been loaded into the store.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): preserve target route during selector load Set the selected agent URL before asynchronous loading so URL synchronization cannot reload the previous agent after initialization.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): centralize selector synchronization Use the URL as the sole selection source and load the selected agent only from its synchronization effect, preventing competing route and store updates.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * feat(agents): support model priority sorting Allow selected agent models to be reordered with drag and drop, keeping the first model and display names synchronized. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5-codex * fix(newchat): show agent name in conversation header Replace the fixed conversation subtitle with the selected agent's display name and cover the header behavior with a regression test. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5-codex * feat(agents): collapse model priority editor Keep selected model tags compact and expose priority sorting through an on-demand popover. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5-codex * fix(agents): sync reordered models with form Write reordered model IDs to the form store so Select tags render the updated priority. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5-codex * fix(newchat): disable Markdown strikethrough rendering Render GFM delete nodes as plain text in newchat while retaining other GFM features. Add a focused regression test and implementation plan. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * fix(agents): remove duplicate model selection state Use the filtered selection state for model priority controls after merging develop. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5-codex * delete plan --------- Co-authored-by: Codex <noreply@openai.com> | 9 天前 | |
Configure monitoring dashboard role access (#3928) Co-authored-by: hhhhsc <name> | 9 天前 | |
fix(newchat): reject attachments larger than 10 MB (#3960) * fix(newchat): reject attachments larger than 10 MB Validate attachments before upload in the newchat page and show a localized size error so oversized files never enter the upload queue. Cover the exact 10 MB boundary. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * fix(i18n): clarify local A2A development URLs 区分本地直启、本地容器和 k8s 启动时使用的 A2A 基础 URL。 Co-authored-by: Cursor <noreply@cursor.com> Generated-by: gpt-5.6-sol * fix(i18n): sync English local A2A URL hint Clarify the local, local-container, and k8s A2A base URLs in English. Co-authored-by: Cursor <noreply@cursor.com> Generated-by: gpt-5.6-sol * fix(newchat): limit attachments to 50 files Track pending newchat attachments per runtime and reject the 51st file with a localized error message. Releasing slots on removal or successful upload keeps subsequent selections available. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 --------- Co-authored-by: Codex <noreply@openai.com> | 4 天前 | |
feat(agents): support model priority sorting (#3914) * docs(agents): define collaborative version label Document the approved version-name label behavior and implementation plan.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): show related agent version labels Display each internal collaborative agent's saved version name beside its name.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): distinguish related agent versions Show version number and name when selecting an internal agent, while keeping related agent labels compact with the saved version number.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): guard version detail during agent switch Skip version-detail requests while an agent switch is pending or no published version exists. This prevents stale agent state from requesting a nonexistent version.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * delete frontend * delete plan * fix(agents): initialize agent before route switch Keep the active agent and URL synchronized by updating the route only after the selected agent data has been loaded into the store.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): preserve target route during selector load Set the selected agent URL before asynchronous loading so URL synchronization cannot reload the previous agent after initialization.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * fix(agents): centralize selector synchronization Use the URL as the sole selection source and load the selected agent only from its synchronization effect, preventing competing route and store updates.\n\nCo-authored-by: Codex <noreply@openai.com>\nGenerated-by: gpt-5-codex * feat(agents): support model priority sorting Allow selected agent models to be reordered with drag and drop, keeping the first model and display names synchronized. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5-codex * fix(newchat): show agent name in conversation header Replace the fixed conversation subtitle with the selected agent's display name and cover the header behavior with a regression test. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5-codex * feat(agents): collapse model priority editor Keep selected model tags compact and expose priority sorting through an on-demand popover. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5-codex * fix(agents): sync reordered models with form Write reordered model IDs to the form store so Select tags render the updated priority. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5-codex * fix(newchat): disable Markdown strikethrough rendering Render GFM delete nodes as plain text in newchat while retaining other GFM features. Add a focused regression test and implementation plan. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * fix(agents): remove duplicate model selection state Use the filtered selection state for model priority controls after merging develop. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5-codex * delete plan --------- Co-authored-by: Codex <noreply@openai.com> | 9 天前 | |
fix(newchat): restore conversation after returning (#3908) * fix(newchat): restore conversation after returning Switch to a fresh thread before returning to the agent landing page so the previous conversation can be selected and rendered again. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * fix(hotfix): sync remaining v2.5.1 fixes Port deployment-aware knowledge tool filtering, historical conversation timing, and parallel tool-call completion from #3895. Exclude the already handled empty agent input fix. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 --------- Co-authored-by: Codex <noreply@openai.com> Co-authored-by: panyehong <2655992392@qq.com> | 9 天前 | |
✨ Feature: Development of Agent Workbench Features (#4010) * ✨ Feature: Development of Agent Workbench Features * ✨ Feature: Development of Agent Workbench Features * ✨ Feature: Development of Agent Workbench Features * 🐛 Bugfix: The upload_to_s3 and download_from_s3 tools do not support user configuration. * feat:add-workbench * 工作台知识库选择依据aidp开关 * feat:工作台前端风格统一优化 * fix(workbench): restore chat modes and tenant model selection * fix(workbench): restore header and system skills * fix(workbench): hide built-in skills from composer * fix(workbench): restore managed agent invocation * fix(workbench): authorize hidden system agent for HITL * fix(workbench): persist creation history and retry branches * test(workbench): align legacy Skill API mocks with creation history * feat(workbench): separate chat entrypoints and refine creation UX * fix: restore workbench attachment reuse and landing layout * feat(workbench): gate workbench with deployment flag * feat(workbench): gate workbench with deployment flag * feat(workbench): Resolved conflicts and fixed an issue where historical sessions became unavailable after deleting and recreating the agent. * feat(workbench): Fix frontend pipeline build issues. * test(workbench): fix unit test isolation * test(workbench): raise patch coverage above threshold * refactor(workbench): consolidate database migration * fix(workbench): align reasoning defaults and skill card actions * test(workbench): use complete Agent fixture for reasoning defaults --------- Co-authored-by: dongjibao2001 <332722455@qq.com> | 8 小时前 | |
[fix] 合并 CodeAgent 静默重试与显式终止协议 (#3973) * [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(agent): enforce explicit CodeAgent termination * fix(test): restore CodeAgent CI compatibility * test(agent): keep develop isolation checks compatible * fix(agent): hide protocol repair generation stream * fix(ci): satisfy CodeAgent quality gate * test(model): cover retry classification branches | 3 天前 | |
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> | 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> | 2 天前 | |
fix(newchat): restore conversation after returning (#3908) * fix(newchat): restore conversation after returning Switch to a fresh thread before returning to the agent landing page so the previous conversation can be selected and rendered again. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 * fix(hotfix): sync remaining v2.5.1 fixes Port deployment-aware knowledge tool filtering, historical conversation timing, and parallel tool-call completion from #3895. Exclude the already handled empty agent input fix. Co-authored-by: Codex <noreply@openai.com> Generated-by: gpt-5 --------- Co-authored-by: Codex <noreply@openai.com> Co-authored-by: panyehong <2655992392@qq.com> | 9 天前 | |
♻️ Refactor: Refactored ReAct recoverable exceptions (#3915) * 🐛 Bugfix: Changed ReAct recoverable exceptions to yellow warnings. (#3897) * 🐛 Bugfix: Changed ReAct recoverable exceptions to yellow warnings. * Support alternate reasoning stream fields (#3863) * Support alternate reasoning stream fields * Test support for alternate reasoning field in OpenAI streaming * Support reasoning field in LLM stream chunks * Test alternate reasoning fields in LLM prompt generation --------- Co-authored-by: hhhhsc <name> * 🧪 Test: Add warning process type to NexentAgent mock --------- Co-authored-by: hhhhsc701 <56435672+hhhhsc701@users.noreply.github.com> * ♻️ Refactor: Refactored ReAct recoverable exceptions: changed to gray text, limited to a maximum of 3 lines. --------- Co-authored-by: hhhhsc701 <56435672+hhhhsc701@users.noreply.github.com> | 10 天前 | |
✨ Feature: Development of Agent Workbench Features (#4010) * ✨ Feature: Development of Agent Workbench Features * ✨ Feature: Development of Agent Workbench Features * ✨ Feature: Development of Agent Workbench Features * 🐛 Bugfix: The upload_to_s3 and download_from_s3 tools do not support user configuration. * feat:add-workbench * 工作台知识库选择依据aidp开关 * feat:工作台前端风格统一优化 * fix(workbench): restore chat modes and tenant model selection * fix(workbench): restore header and system skills * fix(workbench): hide built-in skills from composer * fix(workbench): restore managed agent invocation * fix(workbench): authorize hidden system agent for HITL * fix(workbench): persist creation history and retry branches * test(workbench): align legacy Skill API mocks with creation history * feat(workbench): separate chat entrypoints and refine creation UX * fix: restore workbench attachment reuse and landing layout * feat(workbench): gate workbench with deployment flag * feat(workbench): gate workbench with deployment flag * feat(workbench): Resolved conflicts and fixed an issue where historical sessions became unavailable after deleting and recreating the agent. * feat(workbench): Fix frontend pipeline build issues. * test(workbench): fix unit test isolation * test(workbench): raise patch coverage above threshold * refactor(workbench): consolidate database migration * fix(workbench): align reasoning defaults and skill card actions * test(workbench): use complete Agent fixture for reasoning defaults --------- Co-authored-by: dongjibao2001 <332722455@qq.com> | 8 小时前 | |
✨ Feature: Development of Agent Workbench Features (#4010) * ✨ Feature: Development of Agent Workbench Features * ✨ Feature: Development of Agent Workbench Features * ✨ Feature: Development of Agent Workbench Features * 🐛 Bugfix: The upload_to_s3 and download_from_s3 tools do not support user configuration. * feat:add-workbench * 工作台知识库选择依据aidp开关 * feat:工作台前端风格统一优化 * fix(workbench): restore chat modes and tenant model selection * fix(workbench): restore header and system skills * fix(workbench): hide built-in skills from composer * fix(workbench): restore managed agent invocation * fix(workbench): authorize hidden system agent for HITL * fix(workbench): persist creation history and retry branches * test(workbench): align legacy Skill API mocks with creation history * feat(workbench): separate chat entrypoints and refine creation UX * fix: restore workbench attachment reuse and landing layout * feat(workbench): gate workbench with deployment flag * feat(workbench): gate workbench with deployment flag * feat(workbench): Resolved conflicts and fixed an issue where historical sessions became unavailable after deleting and recreating the agent. * feat(workbench): Fix frontend pipeline build issues. * test(workbench): fix unit test isolation * test(workbench): raise patch coverage above threshold * refactor(workbench): consolidate database migration * fix(workbench): align reasoning defaults and skill card actions * test(workbench): use complete Agent fixture for reasoning defaults --------- Co-authored-by: dongjibao2001 <332722455@qq.com> | 8 小时前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 8 小时前 | ||
| 14 天前 | ||
| 8 天前 | ||
| 14 天前 | ||
| 2 天前 | ||
| 10 天前 | ||
| 8 天前 | ||
| 30 天前 | ||
| 9 天前 | ||
| 30 天前 | ||
| 7 天前 | ||
| 4 天前 | ||
| 2 天前 | ||
| 30 天前 | ||
| 10 天前 | ||
| 29 天前 | ||
| 9 天前 | ||
| 9 天前 | ||
| 9 天前 | ||
| 4 天前 | ||
| 9 天前 | ||
| 9 天前 | ||
| 8 小时前 | ||
| 3 天前 | ||
| 2 天前 | ||
| 2 天前 | ||
| 9 天前 | ||
| 10 天前 | ||
| 8 小时前 | ||
| 8 小时前 |