fixos 2.2.27__tar.gz → 2.2.28__tar.gz
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.
- {fixos-2.2.27 → fixos-2.2.28}/CHANGELOG.md +25 -0
- {fixos-2.2.27 → fixos-2.2.28}/PKG-INFO +6 -6
- {fixos-2.2.27 → fixos-2.2.28}/README.md +5 -5
- {fixos-2.2.27 → fixos-2.2.28}/fixos/__init__.py +1 -1
- {fixos-2.2.27 → fixos-2.2.28}/fixos/agent/session_core.py +34 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos.egg-info/PKG-INFO +6 -6
- {fixos-2.2.27 → fixos-2.2.28}/fixos.egg-info/top_level.txt +1 -0
- {fixos-2.2.27 → fixos-2.2.28}/pyproject.toml +1 -1
- {fixos-2.2.27 → fixos-2.2.28}/setup.py +1 -1
- {fixos-2.2.27 → fixos-2.2.28}/tests/unit/test_core.py +87 -0
- {fixos-2.2.27 → fixos-2.2.28}/.env.example +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/LICENSE +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/MANIFEST.in +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/README.md +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/TEST_RESULTS.md +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/TEST_RESULTS_V2.md +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/alpine/Dockerfile +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/arch/Dockerfile +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/base/Dockerfile +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/broken-audio/Dockerfile +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/broken-full/Dockerfile +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/broken-network/Dockerfile +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/broken-thumbnails/Dockerfile +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/debian/Dockerfile +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/docker-compose.multi-system.yml +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/docker-compose.yml +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/fedora/Dockerfile +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/test-multi-system.sh +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/test-scenarios.sh +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/ubuntu/Dockerfile +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docker/validate-scenario.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docs/examples/advanced_usage.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/docs/examples/quickstart.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/agent/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/agent/autonomous.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/agent/autonomous_session.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/agent/hitl.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/agent/hitl_session.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/agent/session_handlers.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/agent/session_io.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/anonymizer.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/ask_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/cleanup_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/config_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/features_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/fix_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/history_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/main.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/orchestrate_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/output_formatter.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/profile_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/provider_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/quickfix_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/report_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/rollback_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/scan_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/shared.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/token_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli/watch_cmd.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/cli.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/config.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/config_interactive.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/constants.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/checks/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/checks/_shared.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/checks/audio.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/checks/hardware.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/checks/resources.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/checks/security.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/checks/system_core.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/checks/thumbnails.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/dev_project_analyzer.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/disk_analyzer.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/flatpak_analyzer.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/service_cleanup.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/service_details.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/service_scanner.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/storage_analyzer.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/diagnostics/system_checks.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/features/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/features/auditor.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/features/catalog.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/features/installer.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/features/profiles.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/features/renderer.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/fixes/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/interactive/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/interactive/cleanup_planner.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/llm_shell.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/orchestrator/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/orchestrator/executor.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/orchestrator/graph.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/orchestrator/orchestrator.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/orchestrator/rollback.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/platform_utils.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/plugins/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/plugins/base.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/plugins/builtin/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/plugins/builtin/audio.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/plugins/builtin/disk.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/plugins/builtin/hardware.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/plugins/builtin/resources.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/plugins/builtin/security.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/plugins/builtin/thumbnails.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/plugins/registry.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/profiles/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/providers/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/providers/llm.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/providers/llm_analyzer.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/providers/schemas.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/system_checks.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/utils/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/utils/anonymizer.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/utils/terminal.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/utils/timeout.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/utils/web_search.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos/watch.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos.egg-info/SOURCES.txt +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos.egg-info/dependency_links.txt +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos.egg-info/entry_points.txt +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/fixos.egg-info/requires.txt +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/pytest.ini +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/requirements-dev.txt +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/requirements.txt +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/scripts/pyqual-calibrate.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/setup.cfg +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/conftest.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/e2e/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/e2e/test_anonymization_layers.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/e2e/test_audio_broken.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/e2e/test_cli.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/e2e/test_executor.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/e2e/test_multi_system.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/e2e/test_network_broken.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/e2e/test_thumbnails_broken.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/test_fixos.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/unit/__init__.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/unit/test_anonymizer.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/unit/test_executor.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/unit/test_orchestrator.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/unit/test_service_cleanup.py +0 -0
- {fixos-2.2.27 → fixos-2.2.28}/tests/unit/test_service_scanner.py +0 -0
|
@@ -150,6 +150,31 @@ fix(goal): code analysis engine
|
|
|
150
150
|
- **refactor(cli):** Usunięto zduplikowany kod ujednolicając funkcje analizy dysku do wspólnego helpera `_run_disk_analysis`.
|
|
151
151
|
- **refactor(ui):** Usunięto ikony Unicode z CLI i sformatowano wyjście `stderr` oraz standardowego logowania na czysty kod Markdown dla poprawy czytelności w oknach terminalowych.
|
|
152
152
|
|
|
153
|
+
## [2.2.28] - 2026-05-06
|
|
154
|
+
|
|
155
|
+
### Docs
|
|
156
|
+
- Update README.md
|
|
157
|
+
- Update SUMD.md
|
|
158
|
+
- Update SUMR.md
|
|
159
|
+
- Update project/README.md
|
|
160
|
+
- Update project/context.md
|
|
161
|
+
|
|
162
|
+
### Test
|
|
163
|
+
- Update tests/unit/test_core.py
|
|
164
|
+
|
|
165
|
+
### Other
|
|
166
|
+
- Update app.doql.less
|
|
167
|
+
- Update docker/docker-compose.yml
|
|
168
|
+
- Update fixos/agent/session_core.py
|
|
169
|
+
- Update project/analysis.toon.yaml
|
|
170
|
+
- Update project/calls.mmd
|
|
171
|
+
- Update project/calls.png
|
|
172
|
+
- Update project/calls.toon.yaml
|
|
173
|
+
- Update project/calls.yaml
|
|
174
|
+
- Update project/compact_flow.mmd
|
|
175
|
+
- Update project/compact_flow.png
|
|
176
|
+
- ... and 10 more files
|
|
177
|
+
|
|
153
178
|
## [2.2.27] - 2026-05-04
|
|
154
179
|
|
|
155
180
|
### Docs
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fixos
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.28
|
|
4
4
|
Summary: AI-powered Linux/Windows diagnostics and repair – audio, hardware, system issues
|
|
5
5
|
Home-page: https://github.com/wronai/fixos
|
|
6
6
|
Author: fixos contributors
|
|
@@ -63,13 +63,13 @@ AI-powered OS Diagnostics
|
|
|
63
63
|
|
|
64
64
|
## AI Cost Tracking
|
|
65
65
|
|
|
66
|
-
     
|
|
67
|
+
  
|
|
68
68
|
|
|
69
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
70
|
-
- 👤 **Human dev:** ~$
|
|
69
|
+
- 🤖 **LLM usage:** $7.5000 (127 commits)
|
|
70
|
+
- 👤 **Human dev:** ~$2647 (26.5h @ $100/h, 30min dedup)
|
|
71
71
|
|
|
72
|
-
Generated on 2026-05-
|
|
72
|
+
Generated on 2026-05-06 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
73
73
|
|
|
74
74
|
---
|
|
75
75
|
|
|
@@ -19,13 +19,13 @@ AI-powered OS Diagnostics
|
|
|
19
19
|
|
|
20
20
|
## AI Cost Tracking
|
|
21
21
|
|
|
22
|
-
     
|
|
23
|
+
  
|
|
24
24
|
|
|
25
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
26
|
-
- 👤 **Human dev:** ~$
|
|
25
|
+
- 🤖 **LLM usage:** $7.5000 (127 commits)
|
|
26
|
+
- 👤 **Human dev:** ~$2647 (26.5h @ $100/h, 30min dedup)
|
|
27
27
|
|
|
28
|
-
Generated on 2026-05-
|
|
28
|
+
Generated on 2026-05-06 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
29
29
|
|
|
30
30
|
---
|
|
31
31
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""fixos – AI-powered Linux/Windows diagnostics and repair."""
|
|
2
|
-
__version__ = "2.2.
|
|
2
|
+
__version__ = "2.2.28"
|
|
@@ -111,9 +111,17 @@ def _is_part_diagnostic_only(part: str) -> bool:
|
|
|
111
111
|
return normalized.startswith(diagnostic_prefixes)
|
|
112
112
|
|
|
113
113
|
|
|
114
|
+
def _extract_co_robi(text: str) -> str:
|
|
115
|
+
"""Extract 'Co robi:' comment from text following a command match."""
|
|
116
|
+
m = re.search(r"\s*\*{0,2}Co robi:\*{0,2}\s*(.+?)(?:\n|$)", text, re.IGNORECASE)
|
|
117
|
+
return m.group(1).strip() if m else ""
|
|
118
|
+
|
|
119
|
+
|
|
114
120
|
def extract_fixes(reply: str) -> List[Tuple[str, str]]:
|
|
115
121
|
"""Extract (command, comment) pairs from LLM reply."""
|
|
116
122
|
fixes: List[Tuple[str, str]] = []
|
|
123
|
+
|
|
124
|
+
# Pattern 1: **Komenda:** `command` (strict: bold + backticks)
|
|
117
125
|
for m in re.finditer(
|
|
118
126
|
r"\*\*Komenda:\*\*\s*`([^`]+)`(?:[^\n]*?\*\*Co robi:\*\*\s*(.+?))?(?=\n|$)",
|
|
119
127
|
reply, re.IGNORECASE,
|
|
@@ -121,12 +129,38 @@ def extract_fixes(reply: str) -> List[Tuple[str, str]]:
|
|
|
121
129
|
cmd = m.group(1).strip()
|
|
122
130
|
if cmd:
|
|
123
131
|
fixes.append((cmd, (m.group(2) or "").strip()))
|
|
132
|
+
|
|
133
|
+
# Pattern 2: Komenda: `command` (backticks, optional bold)
|
|
134
|
+
if not fixes:
|
|
135
|
+
for m in re.finditer(
|
|
136
|
+
r"\*{0,2}Komenda:\*{0,2}\s*`([^`]+)`",
|
|
137
|
+
reply, re.IGNORECASE,
|
|
138
|
+
):
|
|
139
|
+
cmd = m.group(1).strip()
|
|
140
|
+
if cmd:
|
|
141
|
+
fixes.append((cmd, _extract_co_robi(reply[m.end():])))
|
|
142
|
+
|
|
143
|
+
# Pattern 3: Komenda: command (no backticks — command until Co robi:/next problem/section)
|
|
144
|
+
if not fixes:
|
|
145
|
+
for m in re.finditer(
|
|
146
|
+
r"\*{0,2}Komenda:\*{0,2}\s*"
|
|
147
|
+
r"(.+?)"
|
|
148
|
+
r"(?=\n\s*\*{0,2}Co robi:|\n[🔴🟡🟢]|\n━|\n─|\n\[[\dA-Z]|\Z)",
|
|
149
|
+
reply, re.IGNORECASE | re.DOTALL,
|
|
150
|
+
):
|
|
151
|
+
cmd = re.sub(r"\s*\n\s*", " ", m.group(1)).strip()
|
|
152
|
+
if cmd:
|
|
153
|
+
fixes.append((cmd, _extract_co_robi(reply[m.end():])))
|
|
154
|
+
|
|
155
|
+
# Fallback: → Fix: `command`
|
|
124
156
|
if not fixes:
|
|
125
157
|
for m in re.finditer(r"→\s*Fix:\s*`([^`]+)`", reply, re.IGNORECASE):
|
|
126
158
|
fixes.append((m.group(1).strip(), ""))
|
|
159
|
+
# Fallback: [N] ... `command`
|
|
127
160
|
if not fixes:
|
|
128
161
|
for m in re.finditer(r"\[(\d+)\][^`\n]+`([^`]+)`", reply):
|
|
129
162
|
fixes.append((m.group(2).strip(), f"Fix #{m.group(1)}"))
|
|
163
|
+
# Fallback: EXEC: `command`
|
|
130
164
|
if not fixes:
|
|
131
165
|
for m in re.finditer(r"EXEC:\s*`([^`]+)`", reply, re.IGNORECASE):
|
|
132
166
|
fixes.append((m.group(1).strip(), ""))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fixos
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.28
|
|
4
4
|
Summary: AI-powered Linux/Windows diagnostics and repair – audio, hardware, system issues
|
|
5
5
|
Home-page: https://github.com/wronai/fixos
|
|
6
6
|
Author: fixos contributors
|
|
@@ -63,13 +63,13 @@ AI-powered OS Diagnostics
|
|
|
63
63
|
|
|
64
64
|
## AI Cost Tracking
|
|
65
65
|
|
|
66
|
-
     
|
|
67
|
+
  
|
|
68
68
|
|
|
69
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
70
|
-
- 👤 **Human dev:** ~$
|
|
69
|
+
- 🤖 **LLM usage:** $7.5000 (127 commits)
|
|
70
|
+
- 👤 **Human dev:** ~$2647 (26.5h @ $100/h, 30min dedup)
|
|
71
71
|
|
|
72
|
-
Generated on 2026-05-
|
|
72
|
+
Generated on 2026-05-06 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
73
73
|
|
|
74
74
|
---
|
|
75
75
|
|
|
@@ -5,7 +5,7 @@ long_description = (Path(__file__).parent / "README.md").read_text(encoding="utf
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="fixos",
|
|
8
|
-
version="2.2.
|
|
8
|
+
version="2.2.27",
|
|
9
9
|
description="AI-powered Linux/Windows diagnostics and repair with anonymization",
|
|
10
10
|
long_description=long_description,
|
|
11
11
|
long_description_content_type="text/markdown",
|
|
@@ -191,6 +191,93 @@ class TestDiagnosticOnlyCommand:
|
|
|
191
191
|
assert _is_diagnostic_only_command("df -h && free -h") is True
|
|
192
192
|
|
|
193
193
|
|
|
194
|
+
class TestExtractFixes:
|
|
195
|
+
"""Regression tests for extract_fixes – covers multiple LLM output formats."""
|
|
196
|
+
|
|
197
|
+
def test_strict_bold_backticks(self):
|
|
198
|
+
"""Pattern 1: **Komenda:** `command` **Co robi:** explanation"""
|
|
199
|
+
from fixos.agent.session_core import extract_fixes
|
|
200
|
+
reply = (
|
|
201
|
+
"🔴 **Problem 1: disk full**\n"
|
|
202
|
+
" **Komenda:** `sudo dnf autoremove -y`\n"
|
|
203
|
+
" **Co robi:** removes unused packages\n"
|
|
204
|
+
)
|
|
205
|
+
fixes = extract_fixes(reply)
|
|
206
|
+
assert len(fixes) == 1
|
|
207
|
+
assert fixes[0][0] == "sudo dnf autoremove -y"
|
|
208
|
+
|
|
209
|
+
def test_backticks_no_bold(self):
|
|
210
|
+
"""Pattern 2: Komenda: `command` (backticks, no bold)"""
|
|
211
|
+
from fixos.agent.session_core import extract_fixes
|
|
212
|
+
reply = (
|
|
213
|
+
"🔴 Problem 1: disk full\n"
|
|
214
|
+
"Komenda: `sudo dnf autoremove -y`\n"
|
|
215
|
+
"Co robi: removes unused packages\n"
|
|
216
|
+
)
|
|
217
|
+
fixes = extract_fixes(reply)
|
|
218
|
+
assert len(fixes) == 1
|
|
219
|
+
assert fixes[0][0] == "sudo dnf autoremove -y"
|
|
220
|
+
|
|
221
|
+
def test_no_backticks_no_bold(self):
|
|
222
|
+
"""Pattern 3: Komenda: command (plain text – deepseek bug scenario)"""
|
|
223
|
+
from fixos.agent.session_core import extract_fixes
|
|
224
|
+
reply = (
|
|
225
|
+
"🔴 **Problem 1: Krytyczne zapełnienie dysku.**\n"
|
|
226
|
+
"Komenda: sudo journalctl --vacuum-size=200M && sudo dnf autoremove -y\n"
|
|
227
|
+
"Co robi: Oczyszcza logi i pakiety.\n"
|
|
228
|
+
"🟡 **Problem 2: swap failed.**\n"
|
|
229
|
+
"Komenda: sudo systemctl restart swapfile.swap\n"
|
|
230
|
+
"Co robi: Restartuje swap.\n"
|
|
231
|
+
)
|
|
232
|
+
fixes = extract_fixes(reply)
|
|
233
|
+
assert len(fixes) == 2
|
|
234
|
+
assert "journalctl" in fixes[0][0]
|
|
235
|
+
assert "swapfile" in fixes[1][0]
|
|
236
|
+
|
|
237
|
+
def test_multiline_command_collapsed(self):
|
|
238
|
+
"""Pattern 3 with multiline command – should be collapsed to single line."""
|
|
239
|
+
from fixos.agent.session_core import extract_fixes
|
|
240
|
+
reply = (
|
|
241
|
+
"🔴 **Problem 1: disk full.**\n"
|
|
242
|
+
"Komenda: sudo journalctl --vacuum-size=200M && sudo rm -rf\n"
|
|
243
|
+
"/var/cache/abrt-diag/* && sudo dnf autoremove -y\n"
|
|
244
|
+
"Co robi: cleanup\n"
|
|
245
|
+
)
|
|
246
|
+
fixes = extract_fixes(reply)
|
|
247
|
+
assert len(fixes) >= 1
|
|
248
|
+
cmd = fixes[0][0]
|
|
249
|
+
assert "\n" not in cmd
|
|
250
|
+
assert "journalctl" in cmd
|
|
251
|
+
assert "dnf autoremove" in cmd
|
|
252
|
+
|
|
253
|
+
def test_co_robi_extracted_as_comment(self):
|
|
254
|
+
from fixos.agent.session_core import extract_fixes
|
|
255
|
+
reply = (
|
|
256
|
+
"🔴 Problem 1: disk\n"
|
|
257
|
+
"Komenda: `sudo dnf autoremove -y`\n"
|
|
258
|
+
"Co robi: removes unused packages\n"
|
|
259
|
+
)
|
|
260
|
+
fixes = extract_fixes(reply)
|
|
261
|
+
assert len(fixes) == 1
|
|
262
|
+
assert "removes" in fixes[0][1]
|
|
263
|
+
|
|
264
|
+
def test_diagnostic_only_filtered(self):
|
|
265
|
+
"""Read-only commands should be filtered out."""
|
|
266
|
+
from fixos.agent.session_core import extract_fixes
|
|
267
|
+
reply = (
|
|
268
|
+
"🔴 Problem 1: check disk\n"
|
|
269
|
+
" **Komenda:** `df -h`\n"
|
|
270
|
+
" **Co robi:** shows disk usage\n"
|
|
271
|
+
)
|
|
272
|
+
fixes = extract_fixes(reply)
|
|
273
|
+
assert len(fixes) == 0
|
|
274
|
+
|
|
275
|
+
def test_empty_reply(self):
|
|
276
|
+
from fixos.agent.session_core import extract_fixes
|
|
277
|
+
assert extract_fixes("") == []
|
|
278
|
+
assert extract_fixes("No problems found.") == []
|
|
279
|
+
|
|
280
|
+
|
|
194
281
|
class TestInteractiveBlocker:
|
|
195
282
|
def test_newgrp_blocked(self):
|
|
196
283
|
from fixos.platform_utils import is_interactive_blocker
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|