完成 WebSocket 与 workspace 架构优化收尾,并修复全量回归阻塞。

本次将握手鉴权、Origin 校验、限流、重连补偿、发送背压与观测字段打通,同时修复 gateway 异常路径与备份清理兼容问题,确保工具历史压缩语义一致并恢复全量测试通过。

Made-with: Cursor
This commit is contained in:
oliver 2026-04-27 20:41:50 +08:00
parent 09836dddfa
commit 7253f6795d
12 changed files with 536 additions and 24 deletions

View file

@ -39,7 +39,6 @@ _SQL_REPLAY_COMPACT_TOOL_NAMES = {
}
_TABULAR_QUERY_TOOL_NAMES = {
"query_tabular_attachment",
"run_tabular_sql",
"analyze_tabular_attachment_full_scan",
}
_TEXT_QUERY_TOOL_NAMES = {
@ -583,6 +582,14 @@ class ToolExecutor:
turn_tool_name_counts, turn_tool_observed_rows = _load_turn_tool_stats()
local_turn_tool_name_counts: dict[str, int] = {}
local_turn_tool_observed_rows: dict[str, int] = {}
planned_sql_name_counts: dict[str, int] = {}
for tc in tool_uses:
name = str(tc.name or "")
if name in _SQL_REPLAY_COMPACT_TOOL_NAMES:
planned_sql_name_counts[name] = int(planned_sql_name_counts.get(name, 0)) + 1
compact_sql_names = {
name for name, cnt in planned_sql_name_counts.items() if int(cnt) >= int(tool_history_summary_after_calls())
}
has_tabular_ref_in_session = _session_has_tabular_ref(ctx.store, ctx.session_id)
has_text_ref_in_session = _session_has_text_ref(ctx.store, ctx.session_id)
has_image_ref_in_session = _session_has_image_ref(ctx.store, ctx.session_id)
@ -759,6 +766,13 @@ class ToolExecutor:
current_rows = int(local_turn_tool_observed_rows.get(tc.name, 0))
local_turn_tool_name_counts[tc.name] = current + 1
local_turn_tool_observed_rows[tc.name] = current_rows + observed_rows_this_call
if tc.name in compact_sql_names:
cumulative_rows = int(turn_tool_observed_rows.get(tc.name, 0)) + int(local_turn_tool_observed_rows.get(tc.name, 0))
result_for_llm["_history_compacted"] = True
result_for_llm["_history_compact_reason"] = "repeated_tool_calls_in_turn"
result_for_llm["_tool_observed_rows_this_call"] = int(observed_rows_this_call)
result_for_llm["_tool_observed_rows_cumulative_in_turn"] = int(cumulative_rows)
result_for_llm["audit_note"] = "Result compacted for history replay safety."
trunc_ms = int((time.perf_counter() - t_trunc) * 1000)
tool_content = self._json_dumps_safe(result_for_llm)
t_db2 = time.perf_counter()

View file

@ -335,7 +335,7 @@ class OclawGateway:
if isinstance(dispatch, dict):
instruction_text = str(dispatch.get("instruction_text") or "").strip()
if not instruction_text:
return ("generalist", "manager_instruction_missing", None, "", False, None, "", "")
return ("generalist", "manager_instruction_missing", None, "", False, None, "", "", "")
need_wiki_inject: bool | None = None
wiki_query = ""
memory_write_text = ""
@ -766,6 +766,7 @@ class OclawGateway:
ws_received_ms = None
trace_id = new_trace_id()
rid = str(run_id or "").strip() or str(uuid.uuid4())
executed_turn_uuid = ""
ctx = OclawSessionContext(
session_id=msg.session_id,
tenant_id=msg.tenant_id,
@ -926,7 +927,7 @@ class OclawGateway:
user_id=msg.user_id,
role=msg.role,
channel=msg.channel,
text=str(instruction_text or "").strip(),
text=str(manager_instruction_text or "").strip(),
attachments=list(msg.attachments or []),
metadata=(
{