ha-mcp-dev 6.3.1.dev137__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. ha_mcp/__init__.py +51 -0
  2. ha_mcp/__main__.py +753 -0
  3. ha_mcp/_pypi_marker +0 -0
  4. ha_mcp/auth/__init__.py +10 -0
  5. ha_mcp/auth/consent_form.py +501 -0
  6. ha_mcp/auth/provider.py +786 -0
  7. ha_mcp/client/__init__.py +10 -0
  8. ha_mcp/client/rest_client.py +924 -0
  9. ha_mcp/client/websocket_client.py +656 -0
  10. ha_mcp/client/websocket_listener.py +340 -0
  11. ha_mcp/config.py +175 -0
  12. ha_mcp/errors.py +399 -0
  13. ha_mcp/py.typed +0 -0
  14. ha_mcp/resources/card_types.json +48 -0
  15. ha_mcp/resources/dashboard_guide.md +573 -0
  16. ha_mcp/server.py +189 -0
  17. ha_mcp/smoke_test.py +108 -0
  18. ha_mcp/tools/__init__.py +11 -0
  19. ha_mcp/tools/backup.py +457 -0
  20. ha_mcp/tools/device_control.py +687 -0
  21. ha_mcp/tools/enhanced.py +191 -0
  22. ha_mcp/tools/helpers.py +184 -0
  23. ha_mcp/tools/registry.py +199 -0
  24. ha_mcp/tools/smart_search.py +797 -0
  25. ha_mcp/tools/tools_addons.py +343 -0
  26. ha_mcp/tools/tools_areas.py +478 -0
  27. ha_mcp/tools/tools_blueprints.py +279 -0
  28. ha_mcp/tools/tools_bug_report.py +570 -0
  29. ha_mcp/tools/tools_calendar.py +391 -0
  30. ha_mcp/tools/tools_camera.py +149 -0
  31. ha_mcp/tools/tools_config_automations.py +508 -0
  32. ha_mcp/tools/tools_config_dashboards.py +1502 -0
  33. ha_mcp/tools/tools_config_entry_flow.py +223 -0
  34. ha_mcp/tools/tools_config_helpers.py +925 -0
  35. ha_mcp/tools/tools_config_info.py +258 -0
  36. ha_mcp/tools/tools_config_scripts.py +267 -0
  37. ha_mcp/tools/tools_entities.py +76 -0
  38. ha_mcp/tools/tools_filesystem.py +589 -0
  39. ha_mcp/tools/tools_groups.py +306 -0
  40. ha_mcp/tools/tools_hacs.py +787 -0
  41. ha_mcp/tools/tools_history.py +714 -0
  42. ha_mcp/tools/tools_integrations.py +297 -0
  43. ha_mcp/tools/tools_labels.py +713 -0
  44. ha_mcp/tools/tools_mcp_component.py +305 -0
  45. ha_mcp/tools/tools_registry.py +1115 -0
  46. ha_mcp/tools/tools_resources.py +622 -0
  47. ha_mcp/tools/tools_search.py +573 -0
  48. ha_mcp/tools/tools_service.py +211 -0
  49. ha_mcp/tools/tools_services.py +352 -0
  50. ha_mcp/tools/tools_system.py +363 -0
  51. ha_mcp/tools/tools_todo.py +530 -0
  52. ha_mcp/tools/tools_traces.py +496 -0
  53. ha_mcp/tools/tools_updates.py +476 -0
  54. ha_mcp/tools/tools_utility.py +519 -0
  55. ha_mcp/tools/tools_voice_assistant.py +345 -0
  56. ha_mcp/tools/tools_zones.py +387 -0
  57. ha_mcp/tools/util_helpers.py +199 -0
  58. ha_mcp/utils/__init__.py +30 -0
  59. ha_mcp/utils/domain_handlers.py +380 -0
  60. ha_mcp/utils/fuzzy_search.py +339 -0
  61. ha_mcp/utils/operation_manager.py +442 -0
  62. ha_mcp/utils/usage_logger.py +290 -0
  63. ha_mcp_dev-6.3.1.dev137.dist-info/METADATA +229 -0
  64. ha_mcp_dev-6.3.1.dev137.dist-info/RECORD +71 -0
  65. ha_mcp_dev-6.3.1.dev137.dist-info/WHEEL +5 -0
  66. ha_mcp_dev-6.3.1.dev137.dist-info/entry_points.txt +7 -0
  67. ha_mcp_dev-6.3.1.dev137.dist-info/licenses/LICENSE +21 -0
  68. ha_mcp_dev-6.3.1.dev137.dist-info/top_level.txt +2 -0
  69. tests/__init__.py +1 -0
  70. tests/test_constants.py +15 -0
  71. tests/test_env_manager.py +336 -0
@@ -0,0 +1,570 @@
1
+ """
2
+ Bug report tool for Home Assistant MCP Server.
3
+
4
+ This module provides a tool to collect diagnostic information and guide users
5
+ on how to create effective bug reports.
6
+ """
7
+
8
+ import logging
9
+ import os
10
+ import platform
11
+ import sys
12
+ from pathlib import Path
13
+ from typing import Annotated, Any
14
+
15
+ from pydantic import Field
16
+
17
+ from ha_mcp import __version__
18
+
19
+ from ..utils.usage_logger import AVG_LOG_ENTRIES_PER_TOOL, get_recent_logs, get_startup_logs
20
+ from .helpers import log_tool_usage
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ def _detect_installation_method() -> str:
26
+ """
27
+ Detect how ha-mcp was installed.
28
+
29
+ Returns one of: pyinstaller, addon, docker, git, pypi, unknown
30
+ """
31
+ # 1. PyInstaller binary
32
+ if getattr(sys, "frozen", False):
33
+ return "pyinstaller"
34
+
35
+ # 2. Home Assistant Add-on (has supervisor token)
36
+ if os.environ.get("SUPERVISOR_TOKEN"):
37
+ return "addon"
38
+
39
+ # 3. Docker container (non-addon)
40
+ if Path("/.dockerenv").exists():
41
+ return "docker"
42
+
43
+ # 4. Git clone - check for .git directory relative to package
44
+ try:
45
+ # Go up from tools_bug_report.py -> tools -> ha_mcp -> src -> project_root
46
+ project_root = Path(__file__).parent.parent.parent.parent
47
+ if (project_root / ".git").exists():
48
+ return "git"
49
+ except Exception:
50
+ pass
51
+
52
+ # 5. PyPI install - marker file exists in package
53
+ try:
54
+ marker_path = Path(__file__).parent.parent / "_pypi_marker"
55
+ if marker_path.exists():
56
+ return "pypi"
57
+ except Exception:
58
+ pass
59
+
60
+ # 6. Default - unknown
61
+ return "unknown"
62
+
63
+
64
+ def _detect_platform() -> dict[str, str]:
65
+ """Detect platform information."""
66
+ return {
67
+ "os": platform.system(), # Windows, Darwin, Linux
68
+ "os_release": platform.release(),
69
+ "os_version": platform.version(),
70
+ "architecture": platform.machine(),
71
+ "python_version": platform.python_version(),
72
+ }
73
+
74
+
75
+ def register_bug_report_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
76
+ """Register bug report tools with the MCP server."""
77
+
78
+ @mcp.tool(
79
+ annotations={
80
+ "idempotentHint": True,
81
+ "readOnlyHint": True,
82
+ "tags": ["system", "diagnostics", "feedback"],
83
+ "title": "Report Issue or Feedback",
84
+ }
85
+ )
86
+ @log_tool_usage
87
+ async def ha_report_issue(
88
+ tool_call_count: Annotated[
89
+ int,
90
+ Field(
91
+ default=10,
92
+ ge=1,
93
+ le=16,
94
+ description=(
95
+ "Number of tool calls made since the issue started. "
96
+ "This determines how many log entries to include. "
97
+ "Count how many ha_* tools were called from when the issue began. "
98
+ "Default: 10. Max: 16 (limited by 200-entry log buffer: 16*4*3=192)"
99
+ ),
100
+ ),
101
+ ] = 10,
102
+ ) -> dict[str, Any]:
103
+ """
104
+ Collect diagnostic information for filing issue reports or feedback.
105
+
106
+ This tool generates templates for TWO types of reports:
107
+ 1. **Runtime Bug Report** - For ha-mcp errors, failures, unexpected behavior
108
+ 2. **Agent Behavior Feedback** - For AI agent inefficiency, wrong tool usage
109
+
110
+ **IMPORTANT FOR AI AGENTS:**
111
+ You MUST analyze the conversation context to determine which template to present:
112
+
113
+ 🐛 **Present RUNTIME BUG template if:**
114
+ - User reports an error, failure, or unexpected behavior
115
+ - A tool returned an error or incorrect result
116
+ - Something is broken or not working in ha-mcp
117
+
118
+ 🤖 **Present AGENT BEHAVIOR template if:**
119
+ - User mentions YOU (the agent) used the wrong tool
120
+ - User suggests a more efficient workflow
121
+ - User reports YOUR inefficiency or mistakes
122
+ - User says you should have done something differently
123
+
124
+ **If unclear which type, ASK the user:**
125
+ "Are you reporting a bug in ha-mcp, or providing feedback on how I used the tools?"
126
+
127
+ **WHEN TO USE THIS TOOL:**
128
+ - "I want to file a bug/issue/report"
129
+ - "This isn't working"
130
+ - "You should have used [other tool]"
131
+ - "That was inefficient"
132
+
133
+ **OUTPUT:**
134
+ Returns both templates. Choose the appropriate one based on context.
135
+ """
136
+ # Detect installation method and platform
137
+ install_method = _detect_installation_method()
138
+ platform_info = _detect_platform()
139
+
140
+ diagnostic_info: dict[str, Any] = {
141
+ "ha_mcp_version": __version__,
142
+ "installation_method": install_method,
143
+ "platform": platform_info,
144
+ "connection_status": "Unknown",
145
+ "home_assistant_version": "Unknown",
146
+ "entity_count": 0,
147
+ }
148
+
149
+ # Try to get Home Assistant config and connection status
150
+ try:
151
+ config = await client.get_config()
152
+ diagnostic_info["connection_status"] = "Connected"
153
+ diagnostic_info["home_assistant_version"] = config.get(
154
+ "version", "Unknown"
155
+ )
156
+ diagnostic_info["location_name"] = config.get("location_name", "Unknown")
157
+ diagnostic_info["time_zone"] = config.get("time_zone", "Unknown")
158
+ except Exception as e:
159
+ logger.warning(f"Failed to get Home Assistant config: {e}")
160
+ diagnostic_info["connection_status"] = f"Connection Error: {str(e)}"
161
+
162
+ # Try to get entity count
163
+ try:
164
+ states = await client.get_states()
165
+ if states:
166
+ diagnostic_info["entity_count"] = len(states)
167
+ except Exception as e:
168
+ logger.warning(f"Failed to get entity count: {e}")
169
+
170
+ # Calculate how many log entries to retrieve
171
+ # Formula: AVG_LOG_ENTRIES_PER_TOOL * 4 * tool_call_count (doubled from 2x to 4x)
172
+ max_log_entries = AVG_LOG_ENTRIES_PER_TOOL * 4 * tool_call_count
173
+ recent_logs = get_recent_logs(max_entries=max_log_entries)
174
+
175
+ # Get startup logs (first minute of server operation)
176
+ startup_logs = get_startup_logs()
177
+
178
+ # Format logs for inclusion (sanitized summary)
179
+ log_summary = _format_logs_for_report(recent_logs)
180
+ startup_log_summary = _format_startup_logs(startup_logs)
181
+
182
+ # Build the formatted report
183
+ report_lines = [
184
+ "=== ha-mcp Bug Report Info ===",
185
+ "",
186
+ f"ha-mcp Version: {diagnostic_info['ha_mcp_version']}",
187
+ f"Installation Method: {diagnostic_info['installation_method']}",
188
+ f"Platform: {platform_info['os']} {platform_info['os_release']} ({platform_info['architecture']})",
189
+ f"Python Version: {platform_info['python_version']}",
190
+ f"Home Assistant Version: {diagnostic_info['home_assistant_version']}",
191
+ f"Connection Status: {diagnostic_info['connection_status']}",
192
+ f"Entity Count: {diagnostic_info['entity_count']}",
193
+ ]
194
+
195
+ # Add optional fields if available
196
+ if "location_name" in diagnostic_info:
197
+ report_lines.append(f"Location Name: {diagnostic_info['location_name']}")
198
+ if "time_zone" in diagnostic_info:
199
+ report_lines.append(f"Time Zone: {diagnostic_info['time_zone']}")
200
+
201
+ if startup_logs:
202
+ report_lines.extend([
203
+ "",
204
+ f"=== Startup Logs ({len(startup_logs)} entries) ===",
205
+ startup_log_summary,
206
+ ])
207
+
208
+ if recent_logs:
209
+ report_lines.extend([
210
+ "",
211
+ f"=== Recent Tool Calls ({len(recent_logs)} entries) ===",
212
+ log_summary,
213
+ ])
214
+
215
+ formatted_report = "\n".join(report_lines)
216
+
217
+ # Generate BOTH templates
218
+ runtime_bug_template = _generate_runtime_bug_template(
219
+ diagnostic_info, log_summary, startup_log_summary, recent_logs, startup_logs
220
+ )
221
+
222
+ agent_behavior_template = _generate_agent_behavior_template(
223
+ diagnostic_info, log_summary, recent_logs
224
+ )
225
+
226
+ # Anonymization instructions
227
+ anonymization_guide = _generate_anonymization_guide()
228
+
229
+ return {
230
+ "success": True,
231
+ "diagnostic_info": diagnostic_info,
232
+ "recent_logs": recent_logs,
233
+ "startup_logs": startup_logs,
234
+ "log_count": len(recent_logs),
235
+ "startup_log_count": len(startup_logs),
236
+ "formatted_report": formatted_report,
237
+ "runtime_bug_template": runtime_bug_template,
238
+ "agent_behavior_template": agent_behavior_template,
239
+ "anonymization_guide": anonymization_guide,
240
+ "instructions": (
241
+ "ANALYZE THE CONVERSATION to determine which template to present:\n\n"
242
+ "🐛 Present RUNTIME_BUG_TEMPLATE if:\n"
243
+ " - User reports an error, failure, or unexpected behavior in ha-mcp\n"
244
+ " - A tool returned an error or incorrect result\n"
245
+ " - Something is broken or not working\n"
246
+ " Submit at: https://github.com/homeassistant-ai/ha-mcp/issues/new?template=runtime_bug.md\n\n"
247
+ "🤖 Present AGENT_BEHAVIOR_TEMPLATE if:\n"
248
+ " - User mentions YOU (the agent) used the wrong tool\n"
249
+ " - User suggests YOU should have done something differently\n"
250
+ " - User reports YOUR inefficiency or mistakes\n"
251
+ " Submit at: https://github.com/homeassistant-ai/ha-mcp/issues/new?template=agent_behavior_feedback.md\n\n"
252
+ "If UNCLEAR which type, ASK: 'Are you reporting a bug in ha-mcp, or providing feedback on how I used the tools?'\n\n"
253
+ "Present the chosen template to the user. Ask them to fill in the description sections. "
254
+ "Remind them to follow the anonymization_guide to protect their privacy."
255
+ ),
256
+ }
257
+
258
+
259
+ def _format_logs_for_report(logs: list[dict[str, Any]]) -> str:
260
+ """Format log entries for inclusion in a bug report."""
261
+ if not logs:
262
+ return "(No recent logs available)"
263
+
264
+ lines = []
265
+ for log in logs:
266
+ timestamp = log.get("timestamp", "?")[:19] # Trim to seconds
267
+ tool_name = log.get("tool_name", "unknown")
268
+ success = "OK" if log.get("success") else "FAIL"
269
+ exec_time = log.get("execution_time_ms", 0)
270
+ error = log.get("error_message", "")
271
+
272
+ line = f" {timestamp} | {tool_name} | {success} | {exec_time:.0f}ms"
273
+ if error:
274
+ # Truncate error to avoid leaking sensitive info
275
+ error_short = str(error)[:100]
276
+ line += f" | Error: {error_short}"
277
+ lines.append(line)
278
+
279
+ return "\n".join(lines)
280
+
281
+
282
+ def _format_startup_logs(logs: list[dict[str, Any]]) -> str:
283
+ """Format startup log entries for inclusion in a bug report."""
284
+ if not logs:
285
+ return "(No startup logs available)"
286
+
287
+ lines = []
288
+ for log in logs:
289
+ elapsed = log.get("elapsed_seconds", 0)
290
+ level = log.get("level", "INFO")
291
+ logger_name = log.get("logger", "")
292
+ message = log.get("message", "")
293
+
294
+ # Truncate long messages
295
+ if len(message) > 200:
296
+ message = message[:200] + "..."
297
+
298
+ line = f" +{elapsed:05.2f}s | {level:5} | {logger_name}: {message}"
299
+ lines.append(line)
300
+
301
+ return "\n".join(lines)
302
+
303
+
304
+ def _extract_error_messages(logs: list[dict[str, Any]]) -> list[str]:
305
+ """
306
+ Extract error messages from tool call logs.
307
+
308
+ Returns a list of error messages with context (tool name, timestamp).
309
+ """
310
+ if not logs:
311
+ return []
312
+
313
+ error_messages = []
314
+ for log in logs:
315
+ error = log.get("error_message")
316
+ if error:
317
+ timestamp = log.get("timestamp", "?")[:19] # Trim to seconds
318
+ tool_name = log.get("tool_name", "unknown")
319
+ # Format: [timestamp] tool_name: error_message
320
+ error_messages.append(f"[{timestamp}] {tool_name}: {error}")
321
+
322
+ return error_messages
323
+
324
+
325
+ def _generate_runtime_bug_template(
326
+ diagnostic_info: dict[str, Any],
327
+ log_summary: str,
328
+ startup_log_summary: str,
329
+ recent_logs: list[dict[str, Any]],
330
+ startup_logs: list[dict[str, Any]],
331
+ ) -> str:
332
+ """
333
+ Generate a runtime bug report template matching runtime_bug.md format.
334
+
335
+ This template matches the GitHub issue template EXACTLY so users can
336
+ copy-paste without format conflicts.
337
+ """
338
+ platform_info = diagnostic_info.get("platform", {})
339
+
340
+ # Extract error messages from recent logs
341
+ error_messages = _extract_error_messages(recent_logs)
342
+ error_section = "\n".join(error_messages) if error_messages else "<!-- No errors detected in recent logs -->"
343
+
344
+ # Show startup logs section only if they exist
345
+ startup_section = ""
346
+ if startup_logs:
347
+ startup_section = f"""
348
+ ---
349
+
350
+ ## 🚀 Startup Logs (if relevant)
351
+
352
+ <details>
353
+ <summary>Click to expand startup logs</summary>
354
+
355
+ ```
356
+ {startup_log_summary}
357
+ ```
358
+
359
+ </details>
360
+ """
361
+
362
+ return f"""## 🚨 Auto-Generated by `ha_report_issue` Tool
363
+
364
+ > This template was auto-generated by the ha_report_issue tool.
365
+ > All environment info and logs below were collected automatically.
366
+
367
+ **Submit this report at:**
368
+ https://github.com/homeassistant-ai/ha-mcp/issues/new?template=runtime_bug.md
369
+
370
+ ---
371
+
372
+ ## 📋 Bug Description
373
+ <!-- ONE clear sentence: What went wrong? -->
374
+
375
+
376
+ ## 🔄 Steps to Reproduce
377
+ 1.
378
+ 2.
379
+ 3.
380
+
381
+ ## ✅ Expected vs ❌ Actual Behavior
382
+
383
+ **Expected:**
384
+ <!-- What should have happened? -->
385
+
386
+
387
+ **Actual:**
388
+ <!-- What actually happened? -->
389
+
390
+
391
+ ---
392
+
393
+ ## 🔧 Environment
394
+
395
+ - **ha-mcp Version:** {diagnostic_info.get('ha_mcp_version', 'Unknown')}
396
+ - **Installation Method:** {diagnostic_info.get('installation_method', 'Unknown')}
397
+ - **Platform:** {platform_info.get('os', 'Unknown')} {platform_info.get('os_release', '')} ({platform_info.get('architecture', 'Unknown')})
398
+ - **Python Version:** {platform_info.get('python_version', 'Unknown')}
399
+ - **Home Assistant Version:** {diagnostic_info.get('home_assistant_version', 'Unknown')}
400
+ - **Connection Status:** {diagnostic_info.get('connection_status', 'Unknown')}
401
+ - **Entity Count:** {diagnostic_info.get('entity_count', 0)}
402
+
403
+ ---
404
+
405
+ ## 🚨 Error Messages
406
+
407
+ ```
408
+ {error_section}
409
+ ```
410
+
411
+ ---
412
+
413
+ ## 📊 Recent Tool Calls
414
+
415
+ <details>
416
+ <summary>Click to expand recent tool calls (auto-filled by ha_report_issue)</summary>
417
+
418
+ ```
419
+ {log_summary}
420
+ ```
421
+
422
+ </details>
423
+ {startup_section}
424
+ ---
425
+
426
+ ## 💡 Additional Context
427
+
428
+ <!-- Any other relevant information: -->
429
+ <!-- - Suggested fixes -->
430
+ <!-- - Workarounds you found -->
431
+ <!-- - Related issues -->
432
+ <!-- - Configuration snippets -->
433
+
434
+
435
+ ---
436
+
437
+ **Privacy reminder:** Please review and anonymize sensitive information (tokens, IPs, personal names) before submitting.
438
+ """
439
+
440
+
441
+ def _generate_agent_behavior_template(
442
+ diagnostic_info: dict[str, Any],
443
+ log_summary: str,
444
+ recent_logs: list[dict[str, Any]],
445
+ ) -> str:
446
+ """
447
+ Generate an agent behavior feedback template matching agent_behavior_feedback.md format.
448
+
449
+ This template focuses on AI agent tool usage patterns and inefficiencies.
450
+ """
451
+ platform_info = diagnostic_info.get("platform", {})
452
+
453
+ return f"""## 🤖 Auto-Generated by `ha_report_issue` Tool
454
+
455
+ > This template was auto-generated by the ha_report_issue tool.
456
+ > Tool call history was collected automatically to help analyze agent behavior.
457
+
458
+ **Submit this feedback at:**
459
+ https://github.com/homeassistant-ai/ha-mcp/issues/new?template=agent_behavior_feedback.md
460
+
461
+ ---
462
+
463
+ ## 🤖 What Did the AI Agent Do?
464
+
465
+ <!-- Describe what the AI agent did that could be improved -->
466
+ <!-- Examples: -->
467
+ <!-- - Used the wrong tool initially, then corrected itself -->
468
+ <!-- - Provided invalid parameters to a tool -->
469
+ <!-- - Made multiple unnecessary tool calls -->
470
+ <!-- - Missed an obvious shortcut or better approach -->
471
+ <!-- - Misinterpreted tool output -->
472
+
473
+
474
+ ## 🎯 What Should the Agent Have Done?
475
+
476
+ <!-- Describe the more efficient or correct approach -->
477
+
478
+
479
+ ## 📝 Conversation Context
480
+
481
+ <!-- Provide context about what you were trying to do -->
482
+ <!-- Example: "I asked the agent to create an automation that..." -->
483
+
484
+
485
+ ---
486
+
487
+ ## 🔧 Tool Calls Made (Auto-Filled)
488
+
489
+ <details>
490
+ <summary>Click to expand tool call sequence</summary>
491
+
492
+ ```
493
+ {log_summary}
494
+ ```
495
+
496
+ </details>
497
+
498
+ ---
499
+
500
+ ## 💡 Suggested Improvement
501
+
502
+ <!-- How could the agent be improved? Options: -->
503
+
504
+ - [ ] **Tool documentation** - Tool description or examples need clarification
505
+ - [ ] **Error messages** - Tool should return better guidance on failure
506
+ - [ ] **Tool design** - Tool should accept different parameters or return more info
507
+ - [ ] **Agent prompting** - System prompt should guide agent differently
508
+ - [ ] **New tool needed** - Missing functionality requires a new tool
509
+ - [ ] **Other** - Describe below
510
+
511
+ **Details:**
512
+ <!-- Explain your suggestion -->
513
+
514
+
515
+ ---
516
+
517
+ ## 📊 Environment (Optional)
518
+
519
+ - **ha-mcp Version:** {diagnostic_info.get('ha_mcp_version', 'Unknown')}
520
+ - **AI Client:** (Claude Desktop / Claude Code / Other)
521
+ - **Home Assistant Version:** {diagnostic_info.get('home_assistant_version', 'Unknown')}
522
+
523
+ ---
524
+
525
+ ## 📎 Additional Context
526
+
527
+ <!-- Screenshots, conversation logs, or other helpful info -->
528
+
529
+
530
+ ---
531
+
532
+ **Note:** This is for improving AI agent behavior. For ha-mcp bugs (errors, crashes), use the Runtime Bug template instead.
533
+ """
534
+
535
+
536
+ def _generate_anonymization_guide() -> str:
537
+ """Generate privacy/anonymization instructions."""
538
+ return """## Anonymization Guide
539
+
540
+ Before submitting your bug report, please review and anonymize:
541
+
542
+ ### MUST ANONYMIZE (security-sensitive):
543
+ - API tokens, passwords, secrets -> Replace with "[REDACTED]"
544
+ - IP addresses (internal/external) -> Replace with "192.168.x.x" or "[IP]"
545
+ - MAC addresses -> Replace with "[MAC]"
546
+ - Email addresses -> Replace with "user@example.com"
547
+ - Phone numbers -> Replace with "[PHONE]"
548
+
549
+ ### CONSIDER ANONYMIZING (privacy-sensitive):
550
+ - Location names (city, address) -> Replace with generic names like "Home" or "[LOCATION]"
551
+ - Device names that reveal personal info -> Replace with "Device 1", "Light 1", etc.
552
+ - Person names in entity IDs -> Replace with "person.user1"
553
+ - Calendar/todo items with personal details -> Summarize without specifics
554
+
555
+ ### KEEP AS-IS (helpful for debugging):
556
+ - Entity domains (light, switch, sensor, etc.)
557
+ - Device types and capabilities
558
+ - Automation/script structure (triggers, conditions, actions)
559
+ - Error messages (but check for secrets in them)
560
+ - Timestamps and durations
561
+ - State values (on/off, numeric values, etc.)
562
+ - Home Assistant and ha-mcp versions
563
+
564
+ ### Example anonymization:
565
+ BEFORE: "light.juliens_bedroom" with token "eyJhbG..."
566
+ AFTER: "light.bedroom_1" with token "[REDACTED]"
567
+
568
+ The goal is to preserve enough detail to reproduce and fix the bug
569
+ while protecting your personal information and security.
570
+ """