fix(ops): create new session each call and show host empty state#42
Open
LinChuang2008 wants to merge 7 commits intomainfrom
Open
fix(ops): create new session each call and show host empty state#42LinChuang2008 wants to merge 7 commits intomainfrom
LinChuang2008 wants to merge 7 commits intomainfrom
Conversation
Two bugs in the AI 运维助手 (/ops) page made it unusable on a fresh
install:
1. POST /api/v1/ops/sessions was reusing the user's existing empty
draft via _cleanup_empty_sessions(), so clicking "新建会话"
silently returned the same session id every time and body.title
was dropped on the floor. Replace the reuse path with explicit
cleanup of stale empty drafts (no title + no messages) followed
by always creating a fresh session that respects body.title.
2. OpsInputBar wrapped the entire host-picker row in
`{hosts.length > 0 && ...}`. On a fresh install with no hosts
in the database the row vanished, but the send guard still
required selectedHostId, so users saw "请先选择目标主机" with
no way to actually select one. Always render the row and show
an empty-state hint linking to /hosts when no hosts exist.
Add 4 regression tests covering:
- Two consecutive POSTs return different ids
- body.title is persisted
- Stale empty drafts are cleaned up on create
- Sessions with title or messages are preserved
Verified end-to-end against the running backend (3 POSTs returned
3 distinct ids with titles "first" / "second" / null) and via
git stash to confirm the tests fail without the backend fix.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend: - Add DEMO_MODE and DEMO_FAULT_DELAY_SECONDS config options - Create demo_orchestrator.py: seed data, fault injection, auto AI diagnosis - Create demo.py router: GET /api/v1/demo/status endpoint - Add auto_approve flag to ToolContext for demo command execution - Register demo flow as background task in main.py lifespan Frontend: - Add DEMO badge to OpsAssistant header when demo mode active - Add global alert bar to AppLayout with auto-redirect to OpsAssistant - Add getDemoStatus API to opsApi.ts - Auto-select demo session and poll demo phase Infrastructure: - Create docker-compose.demo.yml with DEMO_MODE=true Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… TLS, host override - Restore with_for_update() on first-user admin check (race condition fix) - Demo auto_approve now uses safe command whitelist instead of blanket approve - Demo state synced to Redis for multi-worker consistency - Host override only applies when LLM omits host_id (no silent overwrite) - Draft session cleanup skips recently active sessions - restore_yum function defined before usage in install script Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… hardening - notifications.py: add missing datetime/timezone import (NameError fix) - settings.py: add missing HTTPException import (NameError fix) - service_checker.py: remove verify=False on httpx client - main.py: remove hardcoded production IP from CORS origins - docker-compose.prod.yml: POSTGRES_PASSWORD now required (no default fallback) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… cleanup - ruff --fix: removed 181 unused imports across backend - requirements.txt: bump cryptography>=46.0.6, asyncssh>=2.14.2, PyJWT>=2.12.0, python-multipart==0.0.22, fastmcp>=3.2.0 (5 CVE fixes) - npm audit fix: resolved 11 vulnerabilities (including critical axios SSRF) - Removed 5 unused npm deps: @dnd-kit/*, @monaco-editor/react, @types/react-grid-layout Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
修复 AI 运维助手页面 (
/ops) 在全新安装环境下的两个相互配合的 bug,导致整页基本不可用:Bug 1 — POST
/api/v1/ops/sessions复用空白草稿旧实现 (
backend/app/routers/ops.py:256-258) 调用_cleanup_empty_sessions后直接返回 reuse 结果,导致:body.title被静默丢弃修复:删除 reuse 分支,显式清理用户残留的空白草稿(无 title + 无消息)后总是创建新 session。
Bug 2 — OpsInputBar 在 hosts 空时进入死循环
frontend/src/components/ops/OpsInputBar.tsx:141用{hosts.length > 0 && ...}把整段主机选择 row 包起来。Fresh DB 没有主机时 row 消失,但 L84 的发送守卫if (!selectedHostId) return仍然阻止发送,L221 还在显示 "请先选择目标主机"。用户陷入一个连选择控件都看不见的死循环。修复:始终渲染 host row。
hosts.length === 0时显示空状态 "暂无在线主机 — 请先到 主机管理 添加并启动 Agent",并保留 host picker 的所有原有逻辑。Test Coverage
新增
backend/tests/test_ops_session_routes.py(4 个回归测试):test_post_sessions_returns_new_id_each_calltest_post_sessions_persists_titlebody.title必须落库test_post_sessions_cleans_up_empty_draftstest_post_sessions_preserves_titled_and_messaged_sessionsIron Law 验证:测试在没有 backend fix 时正确失败(
assert id1 != id2命中 reuse bug),有 fix 时全部通过。命令:End-to-End 验证
修复前对同一个端点连续 3 次 curl POST:3 次都返回
id=4085c76b-...、title=null。修复后:
{title:"first"}5d6acde5-...first{title:"second"}c6f84769-...second{}49b86321-...null3 个不同 id,title 全部正确持久化。
文件改动
backend/app/routers/ops.py(+17/-3) — 替换create_session的 reuse 逻辑frontend/src/components/ops/OpsInputBar.tsx(+21/-8) — host row 始终渲染 + 空状态backend/tests/test_ops_session_routes.py(+102 新文件) — 4 个回归测试CHANGELOG.md(+13) — 2026.04.08 版本条目Test plan
/ops,点击 "新建会话" 看是否每次得到新 session;hosts 空时是否显示空状态提示和跳转链接🤖 Generated with Claude Code