diff --git a/Agent.md b/Agent.md index b387504..cd7c175 100644 --- a/Agent.md +++ b/Agent.md @@ -93,7 +93,7 @@ Community needs voiced in HN agent-UI discussions map directly to EMRG's design: pkill -f "emrg.server"; rm -f ~/.emrg/emrgd.port; python -m emrg ``` -Python: `uv run pytest tests/ -v` (489) — import check: `uv run python -c "from emrg.client.app import run_client"` +Python: `uv run pytest tests/ -v` (490) — import check: `uv run python -c "from emrg.client.app import run_client"` GUI: `cd emrg/gui && npm test` (86: 22 daemon_client + 22 app-commands + 17 renderer smoke + 15 i18n + 7 integration + 3 commands) — syntax: `node --check main.js preload.js daemon_client.js renderer/js/*.js` CI: `uv run pytest` + GUI tests + **actionlint workflow lint** (`rhysd/actionlint@v1.7.12` gate, #444 — workflow 解析错误在 PR CI 即失败,如 `if:` secrets 上下文) diff --git a/README.md b/README.md index 63cfe8a..e7fd85d 100644 --- a/README.md +++ b/README.md @@ -276,7 +276,7 @@ EMRG doesn't just keep up — it catches up on its own. git clone https://github.com/argszero/emrg.git cd emrg uv sync # install deps -uv run pytest tests/ -v # run tests (currently 489 items) +uv run pytest tests/ -v # run tests (currently 490 items) uv run python -m emrg # launch TUI # CI includes actionlint workflow gate (#444): workflow parse errors fail PR CI diff --git a/emrg/server/daemon.py b/emrg/server/daemon.py index e575492..77e72d3 100644 --- a/emrg/server/daemon.py +++ b/emrg/server/daemon.py @@ -400,7 +400,7 @@ async def _handle_client(self, ws) -> None: session = self._get_or_create_session(session_id, Path(cwd)) logger.info( 'task received: session=%s prompt="%s" → routing via LLM (stream=%s)', - session_id, req.prompt[:60], req.stream, + session_id, _redact_string(req.prompt[:60]), req.stream, ) _cancel_event = asyncio.Event() self._session_busy[session_id] = True # lock (released in *locked wrapper) @@ -892,7 +892,7 @@ async def _process_message( count = len(rants) logger.info("rant recorded (%d total)%s: %s", - count, f" project={project}" if project else "", rant_message[:100]) + count, f" project={project}" if project else "", _redact_string(rant_message[:100])) await self._send(ws, {"ok": True, "count": count}) elif msg_type == "list_models": @@ -2343,7 +2343,7 @@ async def _reflect(): "tool_call_id": tc_id, "content": result_text, }) - logger.debug("memory reflection tool: %s → %s", tc_name, result_text[:100]) + logger.debug("memory reflection tool: %s → %s", tc_name, _redact_string(result_text[:100])) except Exception: logger.debug("memory reflection failed", exc_info=True) @@ -2447,7 +2447,7 @@ async def _consolidate_session_memories( "tool_call_id": tc_id, "content": result_text, }) - logger.debug("consolidation tool: %s → %s", tc_name, result_text[:100]) + logger.debug("consolidation tool: %s → %s", tc_name, _redact_string(result_text[:100])) except Exception: logger.debug("memory consolidation failed", exc_info=True) diff --git a/tests/test_daemon.py b/tests/test_daemon.py index 73d9a15..690c3fc 100644 --- a/tests/test_daemon.py +++ b/tests/test_daemon.py @@ -586,3 +586,16 @@ def test_redact_real_key_formats_still_masked(): # Anthropic sk-ant-apiNN-(裸值) ant = "sk-ant-api03-" + "Q2xjbHVkZ" * 4 assert "sk-ant-" not in _redact({"command": f"echo {ant}"})["command"] + + +# ── _redact_string 覆盖日志内容预览(rant/任务 prompt/记忆工具结果)────── + + +def test_redact_string_applies_to_log_previews(): + """日志内容预览(rant 消息/任务 prompt/记忆工具结果)同样脱敏。""" + from emrg.server.daemon import _redact_string + # 用户消息/提示词里粘贴的密钥 + assert "sk-" not in _redact_string("帮我看看 sk-A1b2C3d4A1b2C3d4A1b2C3d4A1b2C3d4 是不是我的 key") + assert "ghp_" not in _redact_string("token 是 ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 吗") + # 普通内容保留 + assert "帮我看看这个文件" in _redact_string("帮我看看这个文件")