feat(assistant): add consent-gated diagnostics - #189
Conversation
Reviewer's GuideAdds a consent-gated diagnostic assistant workspace wired to sanitized launcher logs, strengthens assistant provider health checks and streaming robustness for Ollama and OpenAI-compatible backends, and documents the feature with EN/ZH guides and fixtures. Sequence diagram for consent-gated diagnostic assistant with sanitized log contextsequenceDiagram
actor User
participant AssistantPage
participant AssistantStore
participant Backend as TauriCommands
participant GameAssistant
participant Provider as LLMProvider
User->>AssistantPage: click [Ask diagnostic assistant]
AssistantPage->>AssistantStore: refreshContext(recentLogs.map(message))
AssistantStore->>Backend: get_assistant_log_context(lines)
Backend->>GameAssistant: get_sanitized_log_context(lines)
GameAssistant->>GameAssistant: sanitize_log_line / sanitize_log_text
GameAssistant-->>Backend: AssistantLogContext
Backend-->>AssistantStore: AssistantLogContext
AssistantStore-->>AssistantPage: update context preview
User->>AssistantPage: compose prompt
User->>AssistantPage: toggle includeContext
AssistantPage->>AssistantStore: sendMessage(prompt, logContext | null)
AssistantStore->>Backend: assistant_chat_stream(messages, logContext)
Backend->>GameAssistant: chat_stream(messages, config.assistant, window, log_context)
GameAssistant->>GameAssistant: validate_config(config)
GameAssistant->>Provider: POST /api/chat or /chat/completions (stream)
Provider-->>GameAssistant: bytes_stream
GameAssistant->>GameAssistant: take_complete_lines / process_line
GameAssistant-->>Backend: emit("assistant-stream", StreamChunk)
Backend-->>AssistantStore: assistant-stream events
AssistantStore-->>AssistantPage: append AssistantMessage, stats
AssistantPage-->>User: show recovery guidance
File-Level Changes
Assessment against linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Workspace change through: 9b799a91 changesets found Planned changes to release
|
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="src-tauri/src/core/assistant.rs" line_range="618-622" />
<code_context>
let mut stream = response.bytes_stream();
+ let mut buffer = Vec::new();
+
+ let process_line = |line: &[u8], full_content: &mut String| -> Result<(), String> {
+ if line.iter().all(u8::is_ascii_whitespace) {
+ return Ok(());
+ }
+ let stream_response = serde_json::from_slice::<OllamaStreamResponse>(line)
+ .map_err(|error| format!("Failed to parse Ollama stream response: {error}"))?;
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Streaming now fails hard on any malformed Ollama line, which may be too strict for mixed or diagnostic outputs.
The previous streaming path tolerated per-line JSON parse failures and continued streaming. With `process_line` now returning `Err` on any `serde_json::from_slice` failure, the whole response aborts if the endpoint emits non-JSON diagnostics or partial lines (e.g., log prefixes before JSON). Please consider either logging and skipping malformed lines to preserve robustness, or limiting strict parsing to endpoints guaranteed to emit only well-formed JSON frames.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Pull request overview
This PR introduces a new “Diagnostic assistant” workflow that helps users troubleshoot failed launches using either a local Ollama provider or an OpenAI-compatible provider, with explicit per-request consent for attaching redacted session evidence. It adds backend support for bounded provider health checks and request-isolated streaming, plus a new UI page, fixtures/tests, and EN/ZH documentation.
Changes:
- Add backend assistant log-context sanitization utilities, configuration validation, provider health timeouts, and cancellable/request-isolated streaming.
- Add a new UI assistant page + navigation, failure-entry routing, evidence preview/attachment controls, and optional OS speech for completed responses.
- Extend fixtures, UI tests, bindings, and docs (EN/ZH) to cover the new assistant recovery flow.
Reviewed changes
Copilot reviewed 26 out of 46 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src-tauri/src/main.rs | Adds assistant log-context + streaming request lifecycle commands and wires them into the Tauri handler. |
| src-tauri/src/core/config.rs | Updates assistant config comment to reflect the new TTS provider options. |
| src-tauri/src/core/assistant.rs | Implements sanitized log context, config validation, provider health checks, and request-isolated streaming with timeouts. |
| packages/ui/tests/launcher-fixtures.spec.ts | Adds visual/accessibility and behavior coverage for assistant states, failure recovery flow, stream isolation, and TTS. |
| packages/ui/src/types/bindings/assistant.ts | Updates generated bindings for AssistantLogContext and adds requestId to stream chunks. |
| packages/ui/src/pages/routes.ts | Registers the new /assistant route. |
| packages/ui/src/pages/home.tsx | Adds a failure-state CTA to open the diagnostic assistant from the Overview page. |
| packages/ui/src/pages/assistant.tsx | New diagnostic assistant page: transcript UI, evidence preview + attach toggle, provider setup, and speech synthesis. |
| packages/ui/src/models/game.ts | Ensures recent logs are cleared on a new launch reset. |
| packages/ui/src/models/assistant.ts | New Zustand store for assistant health checks, context refresh, streaming chat, and cancellation handling. |
| packages/ui/src/locales/zh-CN.json | Adds Chinese localization for assistant UI and navigation. |
| packages/ui/src/locales/en.json | Adds English localization for assistant UI and navigation. |
| packages/ui/src/lib/launcher-runtime.ts | Adds assistant-related fixtures to the supported fixture list. |
| packages/ui/src/fixtures/launcher.ts | Adds fixture implementations for assistant commands and streaming event emissions. |
| packages/ui/src/fixtures/bootstrap.ts | Extends bootstrap state for assistant-related fixtures and failure-driven entry. |
| packages/ui/src/components/sidebar.tsx | Adds a sidebar navigation item for the assistant. |
| packages/ui/src/client.ts | Adds/updates client wrappers for assistant streaming lifecycle and log-context retrieval. |
| packages/docs/content/zh/manual/troubleshooting.mdx | Documents the assistant recovery workflow from failed launches (ZH). |
| packages/docs/content/zh/manual/features/meta.json | Adds assistant to the ZH features navigation metadata. |
| packages/docs/content/zh/manual/features/index.mdx | Updates ZH features overview to reference the diagnostic assistant. |
| packages/docs/content/zh/manual/features/assistant.mdx | New ZH manual page describing setup, consent model, and behavior. |
| packages/docs/content/en/manual/troubleshooting.mdx | Documents the assistant recovery workflow from failed launches (EN). |
| packages/docs/content/en/manual/features/meta.json | Adds assistant to the EN features navigation metadata. |
| packages/docs/content/en/manual/features/index.mdx | Updates EN features overview to reference the diagnostic assistant. |
| packages/docs/content/en/manual/features/assistant.mdx | New EN manual page describing setup, consent model, and behavior. |
| .changes/beta1-assistant.md | Adds a changeset entry announcing the new consent-gated diagnostic assistant feature. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 46 changed files in this pull request and generated 1 comment.
Suppressed comments (4)
src-tauri/src/core/assistant.rs:533
- The OpenAI-compatible chat request builds an invalid Authorization header (
format!("******", api_key)) which is both a compile-time error (unused format argument) and would not authenticate at runtime. Use a Bearer auth header derived from the API key.
src-tauri/src/core/assistant.rs:846 - The OpenAI-compatible streaming request uses
format!("******", api_key)for the Authorization header, which is invalid (unused format argument) and will break streaming authentication. Use bearer auth with the API key.
src-tauri/src/core/assistant.rs:622 - The OpenAI-compatible model listing request uses
format!("******", api_key)for the Authorization header, which is invalid and prevents authenticating (and may not compile due to the unused format arg). Use bearer auth with the API key.
packages/ui/src/locales/en.json:35 - Navigation label uses "Assistant" but the feature and page copy consistently call it "Diagnostic assistant" (e.g.,
assistant.title). This inconsistency can confuse users and makes it harder to map the sidebar entry to the recovery workspace.
"overview": "Overview",
"instances": "Instances",
"assistant": "Assistant",
"versions": "Versions",
da514ab to
3e0d82a
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 46 changed files in this pull request and generated no new comments.
Suppressed comments (5)
src-tauri/src/core/assistant.rs:671
- Same as the non-streaming path:
log_contextis sanitized but not size/line bounded before being embedded into the system prompt. This can inflate streaming requests and make timeouts/cancellations less effective under large inputs. Cap the context toself.max_log_lines(or a max size) after sanitization.
src-tauri/src/core/assistant.rs:438 log_contextis accepted as an arbitrary string and only sanitized, not bounded. A large value can significantly increase memory use and request size/cost to the provider (and could be abused by a compromised frontend). Consider capping the injected context to the assistant's existingmax_log_lines(or a max byte/char limit) after sanitization.
This issue also appears on line 668 of the same file.
packages/docs/content/en/manual/features/index.mdx:154
- This section is now describing the “diagnostic assistant”, but the heading still says “AI Assistant”, which is inconsistent with the rest of the page (and the table row above). Consider renaming the heading to match the feature name used elsewhere.
### AI Assistant
The [diagnostic assistant](/en/docs/manual/features/assistant) provides:
packages/docs/content/zh/manual/features/index.mdx:154
- 这一段已经改为介绍“诊断助手”,但标题仍为“AI 助手”,与上方表格及后续内容不一致。建议将标题改为“诊断助手”以保持一致性。
### AI 助手
[诊断助手](/docs/manual/features/assistant) 提供:
packages/ui/src/locales/en.json:36
- The sidebar navigation label uses “Assistant”, while the page title and other UI copy consistently use “Diagnostic assistant”. Consider aligning the nav label to reduce ambiguity.
"overview": "Overview",
"instances": "Instances",
"assistant": "Assistant",
"versions": "Versions",
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 46 changed files in this pull request and generated no new comments.
Suppressed comments (3)
src-tauri/src/core/assistant.rs:1086
assistant_context_deduplicates_after_redactioncurrently adds the same already-redacted line twice, so it doesn't prove that different secrets collapse to one sanitized line (the key behavioral guarantee for consent-gated evidence). Use two different bearer tokens and assert the sanitized output is the single redacted form.
src-tauri/src/core/assistant.rs:1075- The redaction test uses
"Authorization: ******"and then asserts the output still contains******. That doesn't exercise theAuthorization: Bearer <token>redaction path at all, and makes several assertions (e.g.!contains("secret-token")) vacuous. Using a fake bearer token here is safe and ensures the test actually guards against leaking tokens.
This issue also appears on line 1083 of the same file.
src-tauri/src/core/assistant.rs:327
get_sanitized_log_context()iterates and deduplicates over alladditional_linesbefore trimming tomax_log_lines. If the frontend (or any caller) passes a very largelinesarray, theHashSetand intermediateVeccan grow unbounded, causing avoidable CPU/memory use. Sincelog_bufferis already bounded, capadditional_linesup front (e.g., lastmax_log_linesonly) so processing remains bounded.
Summary
Validation
Closes #35
Summary by Sourcery
Introduce a consent-gated diagnostic assistant workspace that analyzes failed launches using sanitized session evidence and supports local Ollama and OpenAI-compatible providers.
New Features:
Enhancements:
Documentation:
Tests: