fixos 2.2.18__tar.gz → 2.2.20__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.18 → fixos-2.2.20}/CHANGELOG.md +28 -0
- {fixos-2.2.18 → fixos-2.2.20}/PKG-INFO +5 -5
- {fixos-2.2.18 → fixos-2.2.20}/README.md +4 -4
- {fixos-2.2.18 → fixos-2.2.20}/fixos/__init__.py +1 -1
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/ask_cmd.py +1 -1
- fixos-2.2.20/fixos/cli/config_cmd.py +221 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/features_cmd.py +1 -1
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/fix_cmd.py +2 -2
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/main.py +4 -4
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/quickfix_cmd.py +1 -1
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/report_cmd.py +1 -1
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/rollback_cmd.py +4 -4
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/scan_cmd.py +4 -3
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/shared.py +3 -5
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/token_cmd.py +6 -6
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/watch_cmd.py +1 -1
- {fixos-2.2.18 → fixos-2.2.20}/fixos/config.py +81 -1
- {fixos-2.2.18 → fixos-2.2.20}/fixos.egg-info/PKG-INFO +5 -5
- {fixos-2.2.18 → fixos-2.2.20}/pyproject.toml +1 -1
- {fixos-2.2.18 → fixos-2.2.20}/setup.py +1 -1
- fixos-2.2.18/fixos/cli/config_cmd.py +0 -83
- {fixos-2.2.18 → fixos-2.2.20}/.env.example +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/LICENSE +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/MANIFEST.in +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/README.md +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/TEST_RESULTS.md +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/TEST_RESULTS_V2.md +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/alpine/Dockerfile +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/arch/Dockerfile +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/base/Dockerfile +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/broken-audio/Dockerfile +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/broken-full/Dockerfile +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/broken-network/Dockerfile +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/broken-thumbnails/Dockerfile +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/debian/Dockerfile +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/docker-compose.multi-system.yml +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/docker-compose.yml +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/fedora/Dockerfile +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/test-multi-system.sh +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docker/ubuntu/Dockerfile +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docs/examples/advanced_usage.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/docs/examples/quickstart.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/agent/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/agent/autonomous.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/agent/autonomous_session.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/agent/hitl.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/agent/hitl_session.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/agent/session_core.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/agent/session_handlers.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/agent/session_io.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/anonymizer.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/cleanup_cmd.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/history_cmd.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/orchestrate_cmd.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/profile_cmd.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli/provider_cmd.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/cli.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/config_interactive.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/constants.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/checks/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/checks/_shared.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/checks/audio.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/checks/hardware.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/checks/resources.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/checks/security.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/checks/system_core.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/checks/thumbnails.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/dev_project_analyzer.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/disk_analyzer.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/flatpak_analyzer.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/service_cleanup.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/service_details.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/service_scanner.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/storage_analyzer.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/diagnostics/system_checks.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/features/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/features/auditor.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/features/catalog.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/features/installer.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/features/profiles.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/features/renderer.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/fixes/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/interactive/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/interactive/cleanup_planner.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/llm_shell.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/orchestrator/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/orchestrator/executor.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/orchestrator/graph.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/orchestrator/orchestrator.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/orchestrator/rollback.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/platform_utils.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/plugins/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/plugins/base.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/plugins/builtin/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/plugins/builtin/audio.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/plugins/builtin/disk.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/plugins/builtin/hardware.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/plugins/builtin/resources.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/plugins/builtin/security.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/plugins/builtin/thumbnails.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/plugins/registry.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/profiles/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/providers/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/providers/llm.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/providers/llm_analyzer.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/providers/schemas.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/system_checks.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/utils/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/utils/anonymizer.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/utils/terminal.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/utils/timeout.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/utils/web_search.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos/watch.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos.egg-info/SOURCES.txt +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos.egg-info/dependency_links.txt +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos.egg-info/entry_points.txt +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos.egg-info/requires.txt +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/fixos.egg-info/top_level.txt +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/pytest.ini +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/requirements-dev.txt +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/requirements.txt +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/scripts/pyqual-calibrate.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/setup.cfg +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/conftest.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/e2e/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/e2e/test_anonymization_layers.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/e2e/test_audio_broken.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/e2e/test_cli.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/e2e/test_executor.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/e2e/test_multi_system.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/e2e/test_network_broken.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/e2e/test_thumbnails_broken.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/test_fixos.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/unit/__init__.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/unit/test_anonymizer.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/unit/test_core.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/unit/test_executor.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/unit/test_orchestrator.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/unit/test_service_cleanup.py +0 -0
- {fixos-2.2.18 → fixos-2.2.20}/tests/unit/test_service_scanner.py +0 -0
|
@@ -150,6 +150,34 @@ 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.20] - 2026-05-04
|
|
154
|
+
|
|
155
|
+
### Docs
|
|
156
|
+
- Update README.md
|
|
157
|
+
|
|
158
|
+
### Other
|
|
159
|
+
- Update fixos/cli/ask_cmd.py
|
|
160
|
+
- Update fixos/cli/features_cmd.py
|
|
161
|
+
- Update fixos/cli/fix_cmd.py
|
|
162
|
+
- Update fixos/cli/main.py
|
|
163
|
+
- Update fixos/cli/quickfix_cmd.py
|
|
164
|
+
- Update fixos/cli/report_cmd.py
|
|
165
|
+
- Update fixos/cli/rollback_cmd.py
|
|
166
|
+
- Update fixos/cli/scan_cmd.py
|
|
167
|
+
- Update fixos/cli/shared.py
|
|
168
|
+
- Update fixos/cli/token_cmd.py
|
|
169
|
+
- ... and 3 more files
|
|
170
|
+
|
|
171
|
+
## [2.2.19] - 2026-05-04
|
|
172
|
+
|
|
173
|
+
### Docs
|
|
174
|
+
- Update README.md
|
|
175
|
+
|
|
176
|
+
### Other
|
|
177
|
+
- Update fixos/cli/config_cmd.py
|
|
178
|
+
- Update fixos/config.py
|
|
179
|
+
- Update uv.lock
|
|
180
|
+
|
|
153
181
|
## [2.2.18] - 2026-05-04
|
|
154
182
|
|
|
155
183
|
### Docs
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fixos
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.20
|
|
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,11 +63,11 @@ 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 (119 commits)
|
|
70
|
+
- 👤 **Human dev:** ~$2223 (22.2h @ $100/h, 30min dedup)
|
|
71
71
|
|
|
72
72
|
Generated on 2026-05-04 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
73
73
|
|
|
@@ -19,11 +19,11 @@ 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 (119 commits)
|
|
26
|
+
- 👤 **Human dev:** ~$2223 (22.2h @ $100/h, 30min dedup)
|
|
27
27
|
|
|
28
28
|
Generated on 2026-05-04 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
29
29
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""fixos – AI-powered Linux/Windows diagnostics and repair."""
|
|
2
|
-
__version__ = "2.2.
|
|
2
|
+
__version__ = "2.2.20"
|
|
@@ -36,7 +36,7 @@ _OBJECT_KEYWORDS: list[tuple[list[str], tuple]] = [
|
|
|
36
36
|
]
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
def _object_based_match(prompt_lower: str):
|
|
39
|
+
def _object_based_match(prompt_lower: str) -> object:
|
|
40
40
|
"""Fallback object-based matching when no action keyword is found."""
|
|
41
41
|
for keywords, cmd in _OBJECT_KEYWORDS:
|
|
42
42
|
if any(kw in prompt_lower for kw in keywords):
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Config management commands for fixOS CLI
|
|
3
|
+
"""
|
|
4
|
+
import click
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _env_path() -> Path:
|
|
9
|
+
"""Return path to active .env file (cwd > home)."""
|
|
10
|
+
for p in [Path.cwd() / ".env", Path.home() / ".fixos.env", Path.home() / ".fixos.conf"]:
|
|
11
|
+
if p.exists():
|
|
12
|
+
return p
|
|
13
|
+
return Path.cwd() / ".env"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _set_env_key(key: str, value: str) -> Path:
|
|
17
|
+
"""Update or insert KEY=VALUE in the active .env file."""
|
|
18
|
+
path = _env_path()
|
|
19
|
+
lines: list[str] = path.read_text(encoding="utf-8").splitlines() if path.exists() else []
|
|
20
|
+
replaced = False
|
|
21
|
+
for i, line in enumerate(lines):
|
|
22
|
+
if line.startswith(f"{key}="):
|
|
23
|
+
lines[i] = f"{key}={value}"
|
|
24
|
+
replaced = True
|
|
25
|
+
break
|
|
26
|
+
if not replaced:
|
|
27
|
+
lines.append(f"{key}={value}")
|
|
28
|
+
path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
29
|
+
path.chmod(0o600)
|
|
30
|
+
return path
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@click.group("config")
|
|
34
|
+
def config() -> None:
|
|
35
|
+
"""Zarządzanie konfiguracją fixOS."""
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@config.command("show")
|
|
40
|
+
def config_show() -> None:
|
|
41
|
+
"""Pokaż aktualną konfigurację."""
|
|
42
|
+
from fixos.config import FixOsConfig
|
|
43
|
+
|
|
44
|
+
cfg = FixOsConfig.load()
|
|
45
|
+
click.echo(click.style("\nKonfiguracja fixOS:", fg="cyan", bold=True))
|
|
46
|
+
click.echo(click.style("─" * 40, fg="cyan"))
|
|
47
|
+
|
|
48
|
+
click.echo(f" Provider: {cfg.provider}")
|
|
49
|
+
click.echo(f" Model: {cfg.model}")
|
|
50
|
+
click.echo(f" Timeout: {cfg.session_timeout}s")
|
|
51
|
+
click.echo(f" Agent mode: {cfg.agent_mode}")
|
|
52
|
+
click.echo(f" Web search: {'włączone' if cfg.enable_web_search else 'wyłączone'}")
|
|
53
|
+
|
|
54
|
+
key_status = click.style("skonfigurowany", fg="green") if cfg.api_key else click.style("BRAK", fg="red")
|
|
55
|
+
click.echo(f" API Key: {key_status}")
|
|
56
|
+
|
|
57
|
+
if cfg.env_file_loaded:
|
|
58
|
+
click.echo(f" Plik .env: {cfg.env_file_loaded}")
|
|
59
|
+
else:
|
|
60
|
+
click.echo(" Plik .env: nie znaleziono")
|
|
61
|
+
click.echo()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@config.command("init")
|
|
65
|
+
@click.option("--force", is_flag=True, help="Nadpisz istniejący plik")
|
|
66
|
+
def config_init(force) -> None:
|
|
67
|
+
"""Zainicjalizuj plik konfiguracyjny .env."""
|
|
68
|
+
from pathlib import Path
|
|
69
|
+
|
|
70
|
+
env_path = Path(".env")
|
|
71
|
+
if env_path.exists() and not force:
|
|
72
|
+
click.echo(click.style("Plik .env już istnieje. Użyj --force aby nadpisać.", fg="yellow"))
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
template = """# fixOS Configuration
|
|
76
|
+
# Provider: gemini|openai|xai|openrouter|ollama|custom
|
|
77
|
+
PROVIDER=gemini
|
|
78
|
+
|
|
79
|
+
# API Keys (wypełnij odpowiedni dla swojego providera)
|
|
80
|
+
GEMINI_API_KEY=
|
|
81
|
+
# OPENAI_API_KEY=
|
|
82
|
+
# XAI_API_KEY=
|
|
83
|
+
# OPENROUTER_API_KEY=
|
|
84
|
+
|
|
85
|
+
# Opcjonalne ustawienia
|
|
86
|
+
# MODEL=gemini-2.0-flash-exp
|
|
87
|
+
# SESSION_TIMEOUT=300
|
|
88
|
+
# AGENT_MODE=hitl
|
|
89
|
+
"""
|
|
90
|
+
env_path.write_text(template)
|
|
91
|
+
click.echo(click.style(f"Utworzono {env_path}", fg="green"))
|
|
92
|
+
click.echo("Edytuj plik i dodaj swój klucz API.")
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@config.command("set")
|
|
96
|
+
@click.argument("key")
|
|
97
|
+
@click.argument("value")
|
|
98
|
+
def config_set(key, value) -> None:
|
|
99
|
+
"""Ustaw wartość konfiguracyjną w .env."""
|
|
100
|
+
from dotenv import set_key
|
|
101
|
+
|
|
102
|
+
env_path = Path(".env")
|
|
103
|
+
if not env_path.exists():
|
|
104
|
+
click.echo(click.style("Plik .env nie istnieje. Uruchom: fixos config init", fg="yellow"))
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
set_key(str(env_path), key.upper(), value)
|
|
108
|
+
click.echo(click.style(f"Ustawiono {key.upper()}={value}", fg="green"))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@config.command("model")
|
|
112
|
+
@click.option("--provider", "-p", default=None, help="Provider (domyślnie: aktualny z .env)")
|
|
113
|
+
def config_model(provider: str) -> None:
|
|
114
|
+
"""Interaktywnie wybierz model LLM z listy."""
|
|
115
|
+
from fixos.config import FixOsConfig, PROVIDER_MODELS, PROVIDER_DEFAULTS
|
|
116
|
+
|
|
117
|
+
cfg = FixOsConfig.load(provider=provider)
|
|
118
|
+
current_provider = cfg.provider
|
|
119
|
+
models = PROVIDER_MODELS.get(current_provider, [])
|
|
120
|
+
|
|
121
|
+
click.echo(click.style(f"\n🤖 Wybór modelu dla providera: ", fg="cyan") +
|
|
122
|
+
click.style(current_provider, fg="yellow", bold=True))
|
|
123
|
+
click.echo(click.style(f" Aktualny model: {cfg.model}", fg="white"))
|
|
124
|
+
click.echo(click.style("─" * 50, fg="cyan"))
|
|
125
|
+
|
|
126
|
+
if not models:
|
|
127
|
+
click.echo(click.style(f"Brak znanych modeli dla '{current_provider}'.", fg="yellow"))
|
|
128
|
+
custom = click.prompt("Podaj nazwę modelu ręcznie", default=cfg.model)
|
|
129
|
+
chosen = custom
|
|
130
|
+
else:
|
|
131
|
+
click.echo()
|
|
132
|
+
for i, m in enumerate(models, 1):
|
|
133
|
+
marker = click.style("◀ aktualny", fg="green") if m == cfg.model else ""
|
|
134
|
+
click.echo(f" [{i:2d}] {m} {marker}")
|
|
135
|
+
click.echo(f" [ 0] Wpisz własną nazwę modelu")
|
|
136
|
+
click.echo()
|
|
137
|
+
|
|
138
|
+
while True:
|
|
139
|
+
raw = click.prompt(click.style("Wybierz numer lub 0", fg="cyan"), default="1")
|
|
140
|
+
if raw == "0":
|
|
141
|
+
chosen = click.prompt("Podaj nazwę modelu", default=cfg.model)
|
|
142
|
+
break
|
|
143
|
+
if raw.isdigit() and 1 <= int(raw) <= len(models):
|
|
144
|
+
chosen = models[int(raw) - 1]
|
|
145
|
+
break
|
|
146
|
+
click.echo(click.style(f" ❌ Wpisz numer 0–{len(models)}", fg="red"))
|
|
147
|
+
|
|
148
|
+
provider_key = f"{current_provider.upper()}_MODEL"
|
|
149
|
+
env_file = _set_env_key(provider_key, chosen)
|
|
150
|
+
click.echo()
|
|
151
|
+
click.echo(click.style(f" ✅ Ustawiono {provider_key}={chosen}", fg="green"))
|
|
152
|
+
click.echo(click.style(f" 💾 Zapisano → {env_file}", fg="cyan"))
|
|
153
|
+
click.echo()
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@config.command("provider")
|
|
157
|
+
def config_provider() -> None:
|
|
158
|
+
"""Interaktywnie wybierz providera LLM z listy."""
|
|
159
|
+
from fixos.config import FixOsConfig, PROVIDER_DEFAULTS
|
|
160
|
+
|
|
161
|
+
cfg = FixOsConfig.load()
|
|
162
|
+
free = [(n, d) for n, d in PROVIDER_DEFAULTS.items() if d.get("free_tier")]
|
|
163
|
+
paid = [(n, d) for n, d in PROVIDER_DEFAULTS.items() if not d.get("free_tier")]
|
|
164
|
+
|
|
165
|
+
click.echo(click.style("\n⚙️ Wybór providera LLM", fg="cyan", bold=True))
|
|
166
|
+
click.echo(click.style(f" Aktualny: {cfg.provider} ({cfg.model})", fg="white"))
|
|
167
|
+
click.echo(click.style("─" * 60, fg="cyan"))
|
|
168
|
+
click.echo()
|
|
169
|
+
click.echo(click.style(" 🟢 DARMOWE:", fg="green"))
|
|
170
|
+
|
|
171
|
+
num_map: dict[int, str] = {}
|
|
172
|
+
idx = 1
|
|
173
|
+
for name, d in free:
|
|
174
|
+
marker = click.style(" ◀ aktualny", fg="green") if name == cfg.provider else ""
|
|
175
|
+
click.echo(f" [{idx:2d}] {click.style(name, fg='yellow'):<20} {d['model']:<38}{marker}")
|
|
176
|
+
num_map[idx] = name
|
|
177
|
+
idx += 1
|
|
178
|
+
|
|
179
|
+
click.echo()
|
|
180
|
+
click.echo(click.style(" 💰 PŁATNE:", fg="yellow"))
|
|
181
|
+
for name, d in paid:
|
|
182
|
+
marker = click.style(" ◀ aktualny", fg="green") if name == cfg.provider else ""
|
|
183
|
+
click.echo(f" [{idx:2d}] {click.style(name, fg='yellow'):<20} {d['model']:<38}{marker}")
|
|
184
|
+
num_map[idx] = name
|
|
185
|
+
idx += 1
|
|
186
|
+
|
|
187
|
+
click.echo()
|
|
188
|
+
click.echo(" [ 0] Anuluj")
|
|
189
|
+
click.echo()
|
|
190
|
+
|
|
191
|
+
while True:
|
|
192
|
+
raw = click.prompt(click.style("Wybierz numer providera", fg="cyan"), default="0")
|
|
193
|
+
if raw == "0":
|
|
194
|
+
click.echo(click.style("Anulowano.", fg="yellow"))
|
|
195
|
+
return
|
|
196
|
+
if raw.isdigit() and int(raw) in num_map:
|
|
197
|
+
chosen = num_map[int(raw)]
|
|
198
|
+
break
|
|
199
|
+
click.echo(click.style(f" ❌ Wpisz numer 0–{len(num_map)}", fg="red"))
|
|
200
|
+
|
|
201
|
+
pdef = PROVIDER_DEFAULTS[chosen]
|
|
202
|
+
key_env = pdef.get("key_env")
|
|
203
|
+
|
|
204
|
+
env_file = _set_env_key("LLM_PROVIDER", chosen)
|
|
205
|
+
click.echo()
|
|
206
|
+
click.echo(click.style(f" ✅ Ustawiono LLM_PROVIDER={chosen}", fg="green"))
|
|
207
|
+
|
|
208
|
+
if chosen != "ollama" and key_env:
|
|
209
|
+
import os
|
|
210
|
+
existing_key = os.environ.get(key_env, "")
|
|
211
|
+
if not existing_key:
|
|
212
|
+
click.echo(click.style(f" ℹ️ Pobierz klucz API: {pdef.get('key_url', '')}", fg="cyan"))
|
|
213
|
+
if click.confirm(click.style(f" Chcesz teraz wpisać klucz {key_env}?", fg="yellow"), default=False):
|
|
214
|
+
key = click.prompt(f" Wklej klucz {key_env}", hide_input=True)
|
|
215
|
+
if key.strip():
|
|
216
|
+
_set_env_key(key_env, key.strip())
|
|
217
|
+
click.echo(click.style(f" ✅ Zapisano {key_env}", fg="green"))
|
|
218
|
+
|
|
219
|
+
click.echo(click.style(f" 💾 Zapisano → {env_file}", fg="cyan"))
|
|
220
|
+
click.echo(click.style(f"\n Następny krok – wybierz model: fixos config model", fg="white"))
|
|
221
|
+
click.echo()
|
|
@@ -218,7 +218,7 @@ def handle_disk_cleanup_mode(disk_analysis: Dict[str, Any], cfg, dry_run: bool,
|
|
|
218
218
|
click.echo(click.style("\nBrak bezpiecznych akcji do automatycznego wykonania", fg="yellow"))
|
|
219
219
|
|
|
220
220
|
|
|
221
|
-
def execute_cleanup_actions(actions: List[Dict], cfg, llm_fallback: bool):
|
|
221
|
+
def execute_cleanup_actions(actions: List[Dict], cfg, llm_fallback: bool) -> None:
|
|
222
222
|
"""Execute cleanup actions with safety checks"""
|
|
223
223
|
from fixos.orchestrator.executor import CommandExecutor
|
|
224
224
|
|
|
@@ -259,7 +259,7 @@ def execute_cleanup_actions(actions: List[Dict], cfg, llm_fallback: bool):
|
|
|
259
259
|
try_llm_fallback_for_failures(failed, cfg)
|
|
260
260
|
|
|
261
261
|
|
|
262
|
-
def try_llm_fallback_for_failures(failed_actions, cfg):
|
|
262
|
+
def try_llm_fallback_for_failures(failed_actions, cfg) -> None:
|
|
263
263
|
"""Try to fix failed actions using LLM"""
|
|
264
264
|
from fixos.providers.llm import LLMClient
|
|
265
265
|
|
|
@@ -110,10 +110,10 @@ def _print_welcome() -> None:
|
|
|
110
110
|
click.echo(f"{click.style(' fixos fix', fg='yellow')} # zapyta o provider interaktywnie")
|
|
111
111
|
else:
|
|
112
112
|
click.echo(click.style(" Przykłady użycia:", fg="yellow", bold=True))
|
|
113
|
-
click.echo(click.style(
|
|
114
|
-
click.echo(click.style(
|
|
115
|
-
click.echo(click.style(
|
|
116
|
-
click.echo(click.style(
|
|
113
|
+
click.echo(f"{click.style(' fixos fix', fg='yellow')} # pełna diagnostyka + naprawa")
|
|
114
|
+
click.echo(f"{click.style(' fixos fix --modules security,resources', fg='yellow')} # bezpieczeństwo + zasoby")
|
|
115
|
+
click.echo(f"{click.style(' fixos scan --modules security', fg='yellow')} # tylko skan bezpieczeństwa")
|
|
116
|
+
click.echo(f"{click.style(' fixos orchestrate --dry-run', fg='yellow')} # podgląd napraw bez wykonania")
|
|
117
117
|
click.echo()
|
|
118
118
|
|
|
119
119
|
|
|
@@ -9,7 +9,7 @@ from fixos.plugins.base import Severity
|
|
|
9
9
|
@click.command("quickfix")
|
|
10
10
|
@click.option("--dry-run", is_flag=True, default=False, help="Symuluj bez wykonania")
|
|
11
11
|
@click.option("--modules", "-m", default=None, help="Moduły: audio,disk,security,...")
|
|
12
|
-
def quickfix(dry_run, modules):
|
|
12
|
+
def quickfix(dry_run, modules) -> None:
|
|
13
13
|
"""
|
|
14
14
|
Natychmiastowe naprawy bez API — baza znanych bugów.
|
|
15
15
|
|
|
@@ -70,7 +70,7 @@ code {{ background: #e9ecef; padding: 2px 6px; border-radius: 3px; }}
|
|
|
70
70
|
@click.option("--output", "-o", default=None, help="Ścieżka pliku wyjściowego")
|
|
71
71
|
@click.option("--modules", "-m", default=None, help="Moduły diagnostyki")
|
|
72
72
|
@click.option("--profile", "-p", default=None, help="Profil diagnostyczny")
|
|
73
|
-
def report(output_format, output, modules, profile):
|
|
73
|
+
def report(output_format, output, modules, profile) -> None:
|
|
74
74
|
"""
|
|
75
75
|
Eksport wyników diagnostyki do raportu HTML/Markdown/JSON.
|
|
76
76
|
|
|
@@ -6,14 +6,14 @@ from fixos.orchestrator.rollback import RollbackSession
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
@click.group("rollback")
|
|
9
|
-
def rollback():
|
|
9
|
+
def rollback() -> None:
|
|
10
10
|
"""Zarządzanie cofaniem operacji fixOS."""
|
|
11
11
|
pass
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
@rollback.command("list")
|
|
15
15
|
@click.option("--limit", default=20, help="Ile sesji pokazać")
|
|
16
|
-
def rollback_list(limit):
|
|
16
|
+
def rollback_list(limit) -> None:
|
|
17
17
|
"""Pokaż historię sesji naprawczych."""
|
|
18
18
|
sessions = RollbackSession.list_sessions(limit)
|
|
19
19
|
if not sessions:
|
|
@@ -34,7 +34,7 @@ def rollback_list(limit):
|
|
|
34
34
|
|
|
35
35
|
@rollback.command("show")
|
|
36
36
|
@click.argument("session_id")
|
|
37
|
-
def rollback_show(session_id):
|
|
37
|
+
def rollback_show(session_id) -> None:
|
|
38
38
|
"""Pokaż szczegóły sesji rollback."""
|
|
39
39
|
try:
|
|
40
40
|
session = RollbackSession.load(session_id)
|
|
@@ -60,7 +60,7 @@ def rollback_show(session_id):
|
|
|
60
60
|
@click.argument("session_id")
|
|
61
61
|
@click.option("--last", default=1, help="Ile ostatnich operacji cofnąć")
|
|
62
62
|
@click.option("--dry-run", is_flag=True, default=False, help="Tylko pokaż co by się cofnęło")
|
|
63
|
-
def rollback_undo(session_id, last, dry_run):
|
|
63
|
+
def rollback_undo(session_id, last, dry_run) -> None:
|
|
64
64
|
"""Cofnij operacje z podanej sesji."""
|
|
65
65
|
try:
|
|
66
66
|
session = RollbackSession.load(session_id)
|
|
@@ -13,9 +13,10 @@ from fixos.cli.shared import add_shared_options, BANNER
|
|
|
13
13
|
@click.option("--system", "modules", flag_value="system", help="Tylko system")
|
|
14
14
|
@click.option("--all", "modules", flag_value="all", default=True, help="Wszystkie moduły (domyślnie)")
|
|
15
15
|
@add_shared_options
|
|
16
|
+
@click.option("--no-banner", "no_banner", is_flag=True, default=False, help="Ukryj baner fixos")
|
|
16
17
|
@click.option("--output", "-o", default=None, help="Zapisz wyniki do pliku")
|
|
17
18
|
@click.option("--profile", "-p", default=None, help="Profil diagnostyczny (server/desktop/developer/minimal)")
|
|
18
|
-
def scan(modules, output, show_raw, no_banner, disc, dry_run, interactive, json_output, llm_fallback, profile):
|
|
19
|
+
def scan(modules, output, show_raw, no_banner, disc, dry_run, interactive, json_output, llm_fallback, profile) -> None:
|
|
19
20
|
"""
|
|
20
21
|
Przeprowadza diagnostykę systemu.
|
|
21
22
|
|
|
@@ -124,7 +125,7 @@ def _display_disk_scan_mode(disk_analysis: dict) -> None:
|
|
|
124
125
|
click.echo(f" {safe_icon} {suggestion['description']} ({suggestion.get('size_gb', 0):.1f}GB)")
|
|
125
126
|
|
|
126
127
|
|
|
127
|
-
def _run_disk_analysis(data: dict, json_output: bool, is_fix_mode: bool = False):
|
|
128
|
+
def _run_disk_analysis(data: dict, json_output: bool, is_fix_mode: bool = False) -> None:
|
|
128
129
|
"""Helper for disk analysis logic to avoid duplication between scan and fix"""
|
|
129
130
|
indent = " " if is_fix_mode else ""
|
|
130
131
|
click.echo(click.style("Analizowanie zajętości dysku...", fg="blue"))
|
|
@@ -155,7 +156,7 @@ def _run_disk_analysis(data: dict, json_output: bool, is_fix_mode: bool = False)
|
|
|
155
156
|
click.echo(click.style(f"{indent}Błąd podczas analizy dysku: {str(e)}", fg="red"))
|
|
156
157
|
|
|
157
158
|
|
|
158
|
-
def _print_quick_issues(data: dict):
|
|
159
|
+
def _print_quick_issues(data: dict) -> None:
|
|
159
160
|
"""Wyświetla szybki przegląd problemów z zebranych danych."""
|
|
160
161
|
import click
|
|
161
162
|
click.echo(click.style("\nSzybki przegląd problemów:", fg="cyan"))
|
|
@@ -23,19 +23,17 @@ COMMON_OPTIONS = [
|
|
|
23
23
|
]
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
def add_common_options(fn):
|
|
26
|
+
def add_common_options(fn) -> object:
|
|
27
27
|
"""Decorator adding common LLM options to a Click command."""
|
|
28
28
|
for opt in reversed(COMMON_OPTIONS):
|
|
29
29
|
fn = opt(fn)
|
|
30
30
|
return fn
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def add_shared_options(func):
|
|
33
|
+
def add_shared_options(func) -> object:
|
|
34
34
|
"""Shared options for both scan and fix commands."""
|
|
35
35
|
func = click.option("--show-raw", "show_raw", is_flag=True, default=False,
|
|
36
36
|
help="Pokaż surowe dane diagnostyczne (JSON)")(func)
|
|
37
|
-
func = click.option("--no-banner", "no_banner", is_flag=True, default=False,
|
|
38
|
-
help="Ukryj baner fixos")(func)
|
|
39
37
|
func = click.option("--disc", is_flag=True, default=False,
|
|
40
38
|
help="Analiza zajętości dysku + grupowanie przyczyn")(func)
|
|
41
39
|
func = click.option("--disk", "disc", is_flag=True, default=False,
|
|
@@ -54,7 +52,7 @@ def add_shared_options(func):
|
|
|
54
52
|
class NaturalLanguageGroup(click.Group):
|
|
55
53
|
"""Click group that routes unknown commands to 'ask' command."""
|
|
56
54
|
|
|
57
|
-
def resolve_command(self, ctx, args):
|
|
55
|
+
def resolve_command(self, ctx, args) -> tuple[str, click.Command, list[str]]:
|
|
58
56
|
cmd_name = args[0] if args else None
|
|
59
57
|
cmd = self.get_command(ctx, cmd_name) if cmd_name else None
|
|
60
58
|
if cmd is None and args and not args[0].startswith("-"):
|
|
@@ -7,7 +7,7 @@ from pathlib import Path
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
@click.group("token")
|
|
10
|
-
def token():
|
|
10
|
+
def token() -> None:
|
|
11
11
|
"""Zarządzanie tokenem API."""
|
|
12
12
|
pass
|
|
13
13
|
|
|
@@ -16,7 +16,7 @@ def token():
|
|
|
16
16
|
@click.argument("key")
|
|
17
17
|
@click.option("--provider", "-p", default=None, help="Provider (auto-detect if not provided)")
|
|
18
18
|
@click.option("--env-file", "-e", default=".env", help="Plik .env do zapisu")
|
|
19
|
-
def token_set(key, provider, env_file):
|
|
19
|
+
def token_set(key, provider, env_file) -> None:
|
|
20
20
|
"""
|
|
21
21
|
Zapisz token API do pliku .env.
|
|
22
22
|
|
|
@@ -69,7 +69,7 @@ def token_set(key, provider, env_file):
|
|
|
69
69
|
set_key(str(env_path), env_var, key)
|
|
70
70
|
# Set file permissions to 600 (owner read/write only)
|
|
71
71
|
os.chmod(env_path, 0o600)
|
|
72
|
-
masked = key[:8]
|
|
72
|
+
masked = f"{key[:8]}...{key[-4:]}" if len(key) > 12 else "***"
|
|
73
73
|
click.echo(click.style(f"Zapisano {env_var}={masked} do {env_path}", fg="green"))
|
|
74
74
|
|
|
75
75
|
# Also update current process
|
|
@@ -87,13 +87,13 @@ def token_set(key, provider, env_file):
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
@token.command("show")
|
|
90
|
-
def token_show():
|
|
90
|
+
def token_show() -> None:
|
|
91
91
|
"""Pokaż obecny token (masked)."""
|
|
92
92
|
from fixos.config import FixOsConfig
|
|
93
93
|
|
|
94
94
|
cfg = FixOsConfig.load()
|
|
95
95
|
if cfg.api_key:
|
|
96
|
-
masked = cfg.api_key[:8]
|
|
96
|
+
masked = f"{cfg.api_key[:8]}...{cfg.api_key[-4:]}"
|
|
97
97
|
click.echo(f"Provider: {cfg.provider}")
|
|
98
98
|
click.echo(f"Model: {cfg.model}")
|
|
99
99
|
click.echo(f"Token: {masked}")
|
|
@@ -103,7 +103,7 @@ def token_show():
|
|
|
103
103
|
|
|
104
104
|
@token.command("clear")
|
|
105
105
|
@click.option("--env-file", "-e", default=".env", help="Plik .env do edycji")
|
|
106
|
-
def token_clear(env_file):
|
|
106
|
+
def token_clear(env_file) -> None:
|
|
107
107
|
"""Usuń token z pliku .env."""
|
|
108
108
|
from dotenv import unset_key
|
|
109
109
|
|
|
@@ -15,7 +15,7 @@ from fixos.plugins.base import Severity
|
|
|
15
15
|
help="Minimalny poziom alertów")
|
|
16
16
|
@click.option("--max-iterations", default=0, show_default=True,
|
|
17
17
|
help="Maksymalna liczba iteracji (0 = bez limitu)")
|
|
18
|
-
def watch(interval, modules, alert_on, max_iterations):
|
|
18
|
+
def watch(interval, modules, alert_on, max_iterations) -> None:
|
|
19
19
|
"""
|
|
20
20
|
Monitorowanie systemu w tle z powiadomieniami.
|
|
21
21
|
|
|
@@ -51,7 +51,7 @@ PROVIDER_DEFAULTS = {
|
|
|
51
51
|
},
|
|
52
52
|
"openrouter": {
|
|
53
53
|
"base_url": "https://openrouter.ai/api/v1",
|
|
54
|
-
"model": "
|
|
54
|
+
"model": "deepseek/deepseek-v4-flash",
|
|
55
55
|
"key_env": "OPENROUTER_API_KEY",
|
|
56
56
|
"key_url": "https://openrouter.ai/settings/keys",
|
|
57
57
|
"free_tier": True,
|
|
@@ -312,6 +312,86 @@ KEY_PREFIXES: list[tuple[str, str]] = [
|
|
|
312
312
|
]
|
|
313
313
|
|
|
314
314
|
|
|
315
|
+
PROVIDER_MODELS: dict[str, list[str]] = {
|
|
316
|
+
"gemini": [
|
|
317
|
+
"gemini-2.5-flash-preview-04-17",
|
|
318
|
+
"gemini-2.0-flash",
|
|
319
|
+
"gemini-2.0-flash-lite",
|
|
320
|
+
"gemini-1.5-flash",
|
|
321
|
+
"gemini-1.5-pro",
|
|
322
|
+
],
|
|
323
|
+
"openai": [
|
|
324
|
+
"gpt-4o-mini",
|
|
325
|
+
"gpt-4o",
|
|
326
|
+
"gpt-4-turbo",
|
|
327
|
+
"gpt-3.5-turbo",
|
|
328
|
+
],
|
|
329
|
+
"openrouter": [
|
|
330
|
+
"deepseek/deepseek-v4-flash",
|
|
331
|
+
"meta-llama/llama-3.1-8b-instruct:free",
|
|
332
|
+
"mistralai/mistral-small-3.1-24b-instruct:free",
|
|
333
|
+
"qwen/qwen3-235b-a22b:free",
|
|
334
|
+
"meta-llama/llama-3.3-70b-instruct",
|
|
335
|
+
"google/gemini-2.0-flash-001",
|
|
336
|
+
"google/gemini-flash-1.5",
|
|
337
|
+
"openai/gpt-4o-mini",
|
|
338
|
+
"openai/gpt-4o",
|
|
339
|
+
],
|
|
340
|
+
"anthropic": [
|
|
341
|
+
"claude-3-haiku-20240307",
|
|
342
|
+
"claude-3-5-haiku-20241022",
|
|
343
|
+
"claude-3-5-sonnet-20241022",
|
|
344
|
+
"claude-3-opus-20240229",
|
|
345
|
+
],
|
|
346
|
+
"mistral": [
|
|
347
|
+
"mistral-small-latest",
|
|
348
|
+
"mistral-medium-latest",
|
|
349
|
+
"mistral-large-latest",
|
|
350
|
+
"open-mixtral-8x22b",
|
|
351
|
+
],
|
|
352
|
+
"groq": [
|
|
353
|
+
"llama-3.1-8b-instant",
|
|
354
|
+
"llama-3.3-70b-versatile",
|
|
355
|
+
"llama3-70b-8192",
|
|
356
|
+
"gemma2-9b-it",
|
|
357
|
+
"mixtral-8x7b-32768",
|
|
358
|
+
],
|
|
359
|
+
"together": [
|
|
360
|
+
"meta-llama/Llama-3.2-11B-Vision-Instruct-Turbo",
|
|
361
|
+
"meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo",
|
|
362
|
+
"mistralai/Mixtral-8x22B-Instruct-v0.1",
|
|
363
|
+
],
|
|
364
|
+
"cohere": [
|
|
365
|
+
"command-r",
|
|
366
|
+
"command-r-plus",
|
|
367
|
+
"command-a-03-2025",
|
|
368
|
+
],
|
|
369
|
+
"deepseek": [
|
|
370
|
+
"deepseek-chat",
|
|
371
|
+
"deepseek-reasoner",
|
|
372
|
+
],
|
|
373
|
+
"cerebras": [
|
|
374
|
+
"llama3.1-8b",
|
|
375
|
+
"llama-3.3-70b",
|
|
376
|
+
"llama3.1-70b",
|
|
377
|
+
],
|
|
378
|
+
"xai": [
|
|
379
|
+
"grok-beta",
|
|
380
|
+
"grok-2-1212",
|
|
381
|
+
"grok-2-vision-1212",
|
|
382
|
+
],
|
|
383
|
+
"ollama": [
|
|
384
|
+
"llama3.2",
|
|
385
|
+
"llama3.1",
|
|
386
|
+
"mistral",
|
|
387
|
+
"gemma2",
|
|
388
|
+
"qwen2.5",
|
|
389
|
+
"phi3",
|
|
390
|
+
"deepseek-r1",
|
|
391
|
+
],
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
|
|
315
395
|
def detect_provider_from_key(key: str) -> Optional[str]:
|
|
316
396
|
"""Wykrywa provider na podstawie prefiksu klucza API."""
|
|
317
397
|
for prefix, provider in KEY_PREFIXES:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fixos
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.20
|
|
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,11 +63,11 @@ 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 (119 commits)
|
|
70
|
+
- 👤 **Human dev:** ~$2223 (22.2h @ $100/h, 30min dedup)
|
|
71
71
|
|
|
72
72
|
Generated on 2026-05-04 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
73
73
|
|