kirox 1.1.0__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.
- kirox-1.1.0/.github/workflows/ci.yml +118 -0
- kirox-1.1.0/.github/workflows/release.yml +61 -0
- kirox-1.1.0/.gitignore +73 -0
- kirox-1.1.0/CHANGELOG.md +63 -0
- kirox-1.1.0/CONTRIBUTING.md +82 -0
- kirox-1.1.0/LICENSE +21 -0
- kirox-1.1.0/PKG-INFO +188 -0
- kirox-1.1.0/README.md +148 -0
- kirox-1.1.0/docs/api-reference.md +223 -0
- kirox-1.1.0/docs/configuration.md +122 -0
- kirox-1.1.0/docs/installation.md +98 -0
- kirox-1.1.0/pyproject.toml +101 -0
- kirox-1.1.0/scripts/verify_distribution.py +145 -0
- kirox-1.1.0/src/kirox/__init__.py +20 -0
- kirox-1.1.0/src/kirox/_version.py +3 -0
- kirox-1.1.0/src/kirox/cli/__init__.py +387 -0
- kirox-1.1.0/src/kirox/core/__init__.py +1 -0
- kirox-1.1.0/src/kirox/core/auth.py +358 -0
- kirox-1.1.0/src/kirox/core/client.py +262 -0
- kirox-1.1.0/src/kirox/core/errors.py +27 -0
- kirox-1.1.0/src/kirox/core/eventstream.py +254 -0
- kirox-1.1.0/src/kirox/core/models.py +163 -0
- kirox-1.1.0/src/kirox/mcp/__init__.py +1 -0
- kirox-1.1.0/src/kirox/mcp/server.py +172 -0
- kirox-1.1.0/src/kirox/py.typed +0 -0
- kirox-1.1.0/src/kirox/service/__init__.py +1 -0
- kirox-1.1.0/src/kirox/service/_http_adapter.py +170 -0
- kirox-1.1.0/src/kirox/service/daemon.py +234 -0
- kirox-1.1.0/src/kirox/service/process_identity.py +299 -0
- kirox-1.1.0/src/kirox/service/scheduler.py +136 -0
- kirox-1.1.0/src/kirox/service/server.py +639 -0
- kirox-1.1.0/src/kirox/service/state.py +194 -0
- kirox-1.1.0/src/kirox/service/tray.py +113 -0
- kirox-1.1.0/src/kirox/utils/__init__.py +6 -0
- kirox-1.1.0/src/kirox/utils/config.py +52 -0
- kirox-1.1.0/src/kirox/utils/logging.py +30 -0
- kirox-1.1.0/tests/conftest.py +18 -0
- kirox-1.1.0/tests/test_auth.py +270 -0
- kirox-1.1.0/tests/test_cli.py +163 -0
- kirox-1.1.0/tests/test_cli_commands.py +421 -0
- kirox-1.1.0/tests/test_client.py +513 -0
- kirox-1.1.0/tests/test_config.py +22 -0
- kirox-1.1.0/tests/test_e2e.py +66 -0
- kirox-1.1.0/tests/test_eventstream.py +140 -0
- kirox-1.1.0/tests/test_logging.py +12 -0
- kirox-1.1.0/tests/test_mcp.py +227 -0
- kirox-1.1.0/tests/test_models.py +148 -0
- kirox-1.1.0/tests/test_performance.py +47 -0
- kirox-1.1.0/tests/test_process_identity.py +298 -0
- kirox-1.1.0/tests/test_scheduler.py +160 -0
- kirox-1.1.0/tests/test_server.py +711 -0
- kirox-1.1.0/tests/test_service_lifecycle.py +154 -0
- kirox-1.1.0/tests/test_state.py +90 -0
- kirox-1.1.0/tests/test_tray.py +121 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
quality:
|
|
14
|
+
name: ${{ matrix.os }} / Python ${{ matrix.python-version }}
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
os: [ubuntu-latest, windows-latest]
|
|
20
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v7
|
|
24
|
+
- uses: actions/setup-python@v7
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python-version }}
|
|
27
|
+
cache: pip
|
|
28
|
+
|
|
29
|
+
- name: Install development and MCP dependencies
|
|
30
|
+
run: |
|
|
31
|
+
python -m pip install --upgrade pip
|
|
32
|
+
python -m pip install -e ".[dev,mcp]"
|
|
33
|
+
|
|
34
|
+
- name: Ruff format check
|
|
35
|
+
run: python -m ruff format --check .
|
|
36
|
+
|
|
37
|
+
- name: Ruff lint
|
|
38
|
+
run: python -m ruff check .
|
|
39
|
+
|
|
40
|
+
- name: Mypy
|
|
41
|
+
run: python -m mypy src tests scripts
|
|
42
|
+
|
|
43
|
+
- name: Pyrefly
|
|
44
|
+
run: python -m pyrefly check
|
|
45
|
+
|
|
46
|
+
- name: Test with branch coverage
|
|
47
|
+
run: python -m pytest tests -q --cov=kirox --cov-branch --cov-report=term-missing
|
|
48
|
+
|
|
49
|
+
- name: Build wheel and source distribution
|
|
50
|
+
run: python -m build
|
|
51
|
+
|
|
52
|
+
- name: Inspect wheel and run clean-install smoke test
|
|
53
|
+
run: python scripts/verify_distribution.py
|
|
54
|
+
|
|
55
|
+
- uses: actions/upload-artifact@v7
|
|
56
|
+
with:
|
|
57
|
+
name: kirox-${{ matrix.os }}-py${{ matrix.python-version }}
|
|
58
|
+
path: dist/*
|
|
59
|
+
if-no-files-found: error
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
service-extra:
|
|
63
|
+
name: Optional service extra / ${{ matrix.os }}
|
|
64
|
+
runs-on: ${{ matrix.os }}
|
|
65
|
+
strategy:
|
|
66
|
+
fail-fast: false
|
|
67
|
+
matrix:
|
|
68
|
+
os: [ubuntu-latest, windows-latest]
|
|
69
|
+
|
|
70
|
+
steps:
|
|
71
|
+
- uses: actions/checkout@v7
|
|
72
|
+
- uses: actions/setup-python@v7
|
|
73
|
+
with:
|
|
74
|
+
python-version: "3.13"
|
|
75
|
+
cache: pip
|
|
76
|
+
|
|
77
|
+
- name: Build wheel
|
|
78
|
+
run: |
|
|
79
|
+
python -m pip install --upgrade pip
|
|
80
|
+
python -m pip install build==1.5.0
|
|
81
|
+
python -m build --wheel
|
|
82
|
+
|
|
83
|
+
- name: Install wheel with the service extra
|
|
84
|
+
shell: bash
|
|
85
|
+
run: python -m pip install "$(ls dist/*.whl)[service]"
|
|
86
|
+
|
|
87
|
+
- name: Verify dependency resolution
|
|
88
|
+
run: python -m pip check
|
|
89
|
+
|
|
90
|
+
- name: Headless tray import smoke test
|
|
91
|
+
shell: bash
|
|
92
|
+
run: |
|
|
93
|
+
python - <<'PY'
|
|
94
|
+
import importlib.util
|
|
95
|
+
import os
|
|
96
|
+
import sys
|
|
97
|
+
|
|
98
|
+
import kirox.service.tray as tray
|
|
99
|
+
from kirox.service.daemon import KiroxService
|
|
100
|
+
|
|
101
|
+
# Prove the optional dependencies are installed without importing
|
|
102
|
+
# pystray, which probes a display backend at import time.
|
|
103
|
+
for name in ("pystray", "PIL"):
|
|
104
|
+
assert importlib.util.find_spec(name) is not None, f"{name} is not installed"
|
|
105
|
+
|
|
106
|
+
assert tray.KiroTray is not None
|
|
107
|
+
assert KiroxService is not None
|
|
108
|
+
|
|
109
|
+
if sys.platform.startswith("linux") and not os.environ.get("DISPLAY"):
|
|
110
|
+
assert tray.HAS_PYSTRAY is False, "tray must degrade without a display"
|
|
111
|
+
assert tray.create_icon_image() is None
|
|
112
|
+
assert tray.KiroTray().start() is False, "start() must refuse headless"
|
|
113
|
+
|
|
114
|
+
print("tray import ok, HAS_PYSTRAY =", tray.HAS_PYSTRAY)
|
|
115
|
+
PY
|
|
116
|
+
|
|
117
|
+
- name: Console script smoke test
|
|
118
|
+
run: kirox --help
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
name: Publish to PyPI
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
environment:
|
|
15
|
+
name: pypi
|
|
16
|
+
url: https://pypi.org/p/kirox
|
|
17
|
+
permissions:
|
|
18
|
+
# Required for PyPI trusted publishing. No API token is used.
|
|
19
|
+
id-token: write
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v7
|
|
23
|
+
- uses: actions/setup-python@v7
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.13"
|
|
26
|
+
cache: pip
|
|
27
|
+
|
|
28
|
+
- name: Verify the tag matches the packaged version
|
|
29
|
+
shell: bash
|
|
30
|
+
run: |
|
|
31
|
+
python - <<'PY'
|
|
32
|
+
import importlib.util
|
|
33
|
+
import os
|
|
34
|
+
import sys
|
|
35
|
+
|
|
36
|
+
# Load _version.py on its own. Importing kirox._version would execute
|
|
37
|
+
# kirox/__init__.py, which needs runtime dependencies that are not
|
|
38
|
+
# installed yet at this point in the job.
|
|
39
|
+
spec = importlib.util.spec_from_file_location("_kirox_version", "src/kirox/_version.py")
|
|
40
|
+
assert spec is not None and spec.loader is not None
|
|
41
|
+
module = importlib.util.module_from_spec(spec)
|
|
42
|
+
spec.loader.exec_module(module)
|
|
43
|
+
|
|
44
|
+
ref = os.environ["GITHUB_REF_NAME"]
|
|
45
|
+
tag = ref.removeprefix("v")
|
|
46
|
+
if tag != module.__version__:
|
|
47
|
+
sys.exit(f"tag {ref} does not match src/kirox/_version.py ({module.__version__})")
|
|
48
|
+
print(f"tag {ref} matches packaged version {module.__version__}")
|
|
49
|
+
PY
|
|
50
|
+
|
|
51
|
+
- name: Build wheel and source distribution
|
|
52
|
+
run: |
|
|
53
|
+
python -m pip install --upgrade pip
|
|
54
|
+
python -m pip install build==1.5.0
|
|
55
|
+
python -m build
|
|
56
|
+
|
|
57
|
+
- name: Inspect wheel and run clean-install smoke test
|
|
58
|
+
run: python scripts/verify_distribution.py
|
|
59
|
+
|
|
60
|
+
- name: Publish to PyPI
|
|
61
|
+
uses: pypa/gh-action-pypi-publish@v1.14.2
|
kirox-1.1.0/.gitignore
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.so
|
|
5
|
+
.Python
|
|
6
|
+
build/
|
|
7
|
+
develop-eggs/
|
|
8
|
+
dist/
|
|
9
|
+
downloads/
|
|
10
|
+
eggs/
|
|
11
|
+
.eggs/
|
|
12
|
+
lib/
|
|
13
|
+
lib64/
|
|
14
|
+
parts/
|
|
15
|
+
sdist/
|
|
16
|
+
var/
|
|
17
|
+
wheels/
|
|
18
|
+
*.egg-info/
|
|
19
|
+
.installed.cfg
|
|
20
|
+
*.egg
|
|
21
|
+
MANIFEST
|
|
22
|
+
.venv/
|
|
23
|
+
venv/
|
|
24
|
+
ENV/
|
|
25
|
+
env/
|
|
26
|
+
.vscode/
|
|
27
|
+
.idea/
|
|
28
|
+
*.swp
|
|
29
|
+
*.swo
|
|
30
|
+
*~
|
|
31
|
+
.pytest_cache/
|
|
32
|
+
.coverage
|
|
33
|
+
.coverage.*
|
|
34
|
+
coverage.xml
|
|
35
|
+
htmlcov/
|
|
36
|
+
.tox/
|
|
37
|
+
.nox/
|
|
38
|
+
.mypy_cache/
|
|
39
|
+
.pyre/
|
|
40
|
+
.pytype/
|
|
41
|
+
.ruff_cache/
|
|
42
|
+
.ipynb_checkpoints/
|
|
43
|
+
.DS_Store
|
|
44
|
+
Thumbs.db
|
|
45
|
+
Desktop.ini
|
|
46
|
+
*.log
|
|
47
|
+
*.tmp
|
|
48
|
+
*.temp
|
|
49
|
+
.env
|
|
50
|
+
.env.*
|
|
51
|
+
!.env.example
|
|
52
|
+
.kiro/
|
|
53
|
+
*.mitm
|
|
54
|
+
|
|
55
|
+
# Compiled extensions on Windows (companion to *.so above)
|
|
56
|
+
*.pyd
|
|
57
|
+
|
|
58
|
+
# Type checker daemons and caches not covered above
|
|
59
|
+
.dmypy.json
|
|
60
|
+
dmypy.json
|
|
61
|
+
.pyrefly_cache/
|
|
62
|
+
|
|
63
|
+
# Local interpreter pins and build metadata
|
|
64
|
+
.python-version
|
|
65
|
+
pip-wheel-metadata/
|
|
66
|
+
|
|
67
|
+
# Merge, patch, and backup leftovers
|
|
68
|
+
*.orig
|
|
69
|
+
*.rej
|
|
70
|
+
*.bak
|
|
71
|
+
|
|
72
|
+
# Created by mistyped PowerShell redirection on Windows
|
|
73
|
+
nul
|
kirox-1.1.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Kirox are documented in this file. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
|
+
|
|
5
|
+
## [1.1.0] - 2026-07-31
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Strict incremental AWS EventStream decoder with CRC, size, header-type, UTF-8, and truncation validation.
|
|
10
|
+
- Deterministic credential resolution with explicit/config/KIROX/ASSISTANT/database precedence and fixed database discovery locations.
|
|
11
|
+
- Managed service state, authenticated loopback shutdown, startup rollback, socket/thread ownership, and idempotent client cleanup.
|
|
12
|
+
- Text-only OpenAI chat-completions and Anthropic messages adapters with canonical history, field-addressed validation, incremental SSE, disconnect cleanup, and sanitized errors.
|
|
13
|
+
- Operational `kirox-mcp` stdio entry point with lazy optional imports, strict tool input, worker-thread bridging, one client, and lifecycle cleanup.
|
|
14
|
+
- PEP 561 `py.typed` marker and wheel/clean-install distribution verifier.
|
|
15
|
+
- Windows and Ubuntu CI matrix for Python 3.10–3.14 covering Ruff, mypy, Pyrefly, branch coverage, wheel/sdist build, metadata inspection, and install smoke tests, plus a dedicated job that installs the built wheel with the optional `service` extra and runs a headless tray-import and `pip check` smoke test.
|
|
16
|
+
- Pyrefly as a second required type checker, with an explicit `[tool.pyrefly]` section so it does not fall back to the permissive `basic` preset, and warnings promoted to failures.
|
|
17
|
+
- Loopback `Host` header validation and a 1 MiB request-body limit on every bridge route, returning HTTP 400 and provider-shaped HTTP 413 responses before validation or upstream work.
|
|
18
|
+
- Kernel-derived process identity in service state, with identity-bound `kirox stop --force` termination on Linux and Windows that fails closed on PID reuse, missing identity, or unsupported platforms.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- The token scheduler now treats HTTP 401 and 403 from its authentication check as credential failures, re-resolves credentials, and retries the check once instead of relying on error-message text.
|
|
23
|
+
- `AssistantClient.list_tools()` now validates the upstream envelope strictly and raises `APIError` for a missing `result`, a missing or non-array `tools` member, or entries without a non-empty `name` and an `inputSchema` object.
|
|
24
|
+
- Package version now has one source in `src/kirox/_version.py`; CLI, health responses, root metadata, and built distributions report 1.1.0.
|
|
25
|
+
- HTTP service binding is explicitly loopback-only.
|
|
26
|
+
- The service token scheduler now uses an interruptible standard-library worker, removing the unused APScheduler dependency.
|
|
27
|
+
- CLI, tray, scheduler, and server lifecycle paths now close owned resources deterministically.
|
|
28
|
+
- Quality configuration now checks formatting, imports, common bugs, repository typing with two checkers, and a minimum 80% branch-aware coverage threshold.
|
|
29
|
+
- Development tooling is pinned to exact versions, and runtime dependencies now carry both a tested floor and a major upper bound. The optional MCP extra stays on `mcp>=1.28.1,<2`: the v2 SDK moved the low-level `Server` handlers from decorators to constructor parameters, so the current stdio server would not run against it.
|
|
30
|
+
- Installation, configuration, API, contribution, and lifecycle documentation now match actual behavior and text-only limitations.
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- EventStream parsing no longer assumes complete HTTP chunks or accepts bad checksums, impossible lengths, unsupported header encodings, or trailing partial frames.
|
|
35
|
+
- Streaming provider responses no longer prebuffer the upstream iterator, leak it on disconnect/error, duplicate terminal events, expose exception details, or fabricate usage values.
|
|
36
|
+
- MCP import no longer exits the host process when the optional dependency is absent.
|
|
37
|
+
- CLI stop no longer targets a PID until persisted state and service ownership have been validated, and force stop now additionally proves process identity so a reused PID is never signalled.
|
|
38
|
+
- `ModelInfo.from_api()` no longer stores `None` in fields declared `str`, `int`, or `float` when upstream sends an explicit null, and no longer raises `AttributeError` for a null `tokenLimits`; an unusable `modelId` now raises `ValueError` instead of producing a mistyped model.
|
|
39
|
+
- `AssistantClient.list_models()` now validates the response envelope and reports malformed payloads as `APIError` rather than letting `KeyError` or `ValueError` escape the SDK.
|
|
40
|
+
- Importing `kirox.service.tray` no longer crashes on a host with no usable display. `pystray` probes a display backend while importing, so a headless Linux server raised `Xlib.error.DisplayNameError`, which the previous `except ImportError` guard did not catch. The tray now degrades to unavailable and reports a message that names the missing display as a possible cause.
|
|
41
|
+
|
|
42
|
+
## [1.0.0] - 2026-07-30
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- Initial core API client with streaming and multi-model support.
|
|
47
|
+
- CLI with interactive chat and update checks.
|
|
48
|
+
- Background HTTP service and optional system tray.
|
|
49
|
+
- Token refresh scheduler and configuration management.
|
|
50
|
+
- OpenAI- and Anthropic-compatible bridge endpoints.
|
|
51
|
+
- MCP integration and unit, integration, end-to-end, and performance tests.
|
|
52
|
+
|
|
53
|
+
## [0.2.0] - 2026-07-30
|
|
54
|
+
|
|
55
|
+
### Added
|
|
56
|
+
|
|
57
|
+
- Background service module, system tray support, token scheduler, HTTP API server, and associated tests.
|
|
58
|
+
|
|
59
|
+
## [0.1.0] - 2026-07-30
|
|
60
|
+
|
|
61
|
+
### Added
|
|
62
|
+
|
|
63
|
+
- Initial project structure, API client, EventStream parser, CLI interface, and basic tests.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Contributing to Kirox
|
|
2
|
+
|
|
3
|
+
## Development setup
|
|
4
|
+
|
|
5
|
+
Kirox supports Python 3.10–3.14 on Windows and Linux CI.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/your-username/kirox.git
|
|
9
|
+
cd kirox
|
|
10
|
+
python -m venv .venv
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Activate the environment with `.venv\Scripts\Activate.ps1` on Windows PowerShell or `source .venv/bin/activate` in a POSIX shell, then install all development dependencies used by the test suite:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
python -m pip install -e ".[dev,mcp]"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The tray extra is not required for tests; tray behavior is exercised with fakes so CI does not need a desktop session.
|
|
20
|
+
|
|
21
|
+
## Required quality gates
|
|
22
|
+
|
|
23
|
+
Run every command from the repository root before opening a pull request:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
python -m ruff format --check .
|
|
27
|
+
python -m ruff check .
|
|
28
|
+
python -m mypy src tests scripts
|
|
29
|
+
python -m pyrefly check
|
|
30
|
+
python -m pytest tests -q --cov=kirox --cov-branch --cov-report=term-missing
|
|
31
|
+
python -m build
|
|
32
|
+
python scripts/verify_distribution.py
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Branch coverage must remain at least 80%. Both type checkers are required: they disagree often enough that each one catches errors the other misses. Pyrefly reads its `[tool.pyrefly]` section in `pyproject.toml`; without that section it would fall back to the `basic` preset and silence most type errors. The distribution verifier checks the wheel version, `kirox/py.typed`, `kirox` and `kirox-mcp` entry points, then performs a clean temporary-environment install/import/CLI/missing-extra smoke test and `pip check`.
|
|
36
|
+
|
|
37
|
+
CI runs the same gates on Windows and Ubuntu with Python 3.10, 3.11, 3.12, 3.13, and 3.14. A separate job installs the built wheel with the optional `service` extra and runs a headless tray-import and `pip check` smoke test, so the tray dependencies are exercised without requiring a desktop session in the main matrix. A local Python version outside that matrix is useful but does not replace supported-version CI.
|
|
38
|
+
|
|
39
|
+
## Code style and typing
|
|
40
|
+
|
|
41
|
+
- Use Ruff as the formatter and linter; do not hand-format around it.
|
|
42
|
+
- Type public APIs and keep `mypy src tests scripts` and `pyrefly check` clean.
|
|
43
|
+
- Preserve existing public imports and call signatures unless a compatibility plan is documented.
|
|
44
|
+
- Keep optional features lazy: importing the base package must not require MCP or tray dependencies.
|
|
45
|
+
- Do not add runtime dependencies when the standard library or an existing dependency is sufficient.
|
|
46
|
+
- `_version.py` is the single version source. Do not duplicate the package version in `pyproject.toml` or service responses.
|
|
47
|
+
|
|
48
|
+
To apply formatting during development:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
python -m ruff format .
|
|
52
|
+
python -m ruff check .
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Tests
|
|
56
|
+
|
|
57
|
+
Add behavior-focused tests for every change. Tests must not use live credentials, external AI services, or arbitrary user databases.
|
|
58
|
+
|
|
59
|
+
For relevant areas, cover:
|
|
60
|
+
|
|
61
|
+
- Success, validation, and resource-cleanup paths
|
|
62
|
+
- Incremental streaming and malformed/truncated input
|
|
63
|
+
- Authentication precedence without exposing secret values
|
|
64
|
+
- Service startup rollback, idempotent shutdown, socket/thread cleanup, and state ownership
|
|
65
|
+
- Optional dependency present and absent behavior
|
|
66
|
+
- Provider adapter text-only rejection rather than silent semantic loss
|
|
67
|
+
|
|
68
|
+
Use `httpx.MockTransport`, Flask's test client, temporary paths, and injected fakes. Avoid assertions that only repeat implementation constants without exercising a contract.
|
|
69
|
+
|
|
70
|
+
## Documentation and changelog
|
|
71
|
+
|
|
72
|
+
Update README and focused docs whenever configuration, compatibility limitations, entry points, lifecycle behavior, or API envelopes change. Do not publish a static test-count claim; it becomes stale immediately. Add user-visible changes to `CHANGELOG.md` using semantic-versioning categories.
|
|
73
|
+
|
|
74
|
+
## Pull requests
|
|
75
|
+
|
|
76
|
+
1. Create a focused branch and make the smallest compatible change.
|
|
77
|
+
2. Add meaningful tests and documentation.
|
|
78
|
+
3. Run the full quality and distribution gates above.
|
|
79
|
+
4. Include supported-OS/Python limitations and any unverified behavior in the pull-request description.
|
|
80
|
+
5. Submit the pull request without generated temporary virtual environments or distribution-check directories.
|
|
81
|
+
|
|
82
|
+
Be respectful and do not include credentials, database contents, or user prompts in issues, fixtures, logs, or screenshots.
|
kirox-1.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kirox Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
kirox-1.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kirox
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: Production-ready SDK for AI coding assistants with background service and system tray
|
|
5
|
+
Project-URL: Homepage, https://github.com/idugeni/kirox
|
|
6
|
+
Project-URL: Documentation, https://github.com/idugeni/kirox#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/idugeni/kirox
|
|
8
|
+
Project-URL: Issues, https://github.com/idugeni/kirox/issues
|
|
9
|
+
Author: Kirox Contributors
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ai,background-service,claude,coding-assistant,gpt,kiro,llm,sdk
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: flask<4,>=3.1.3
|
|
26
|
+
Requires-Dist: httpx<0.29,>=0.28.1
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: build==1.5.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: mypy==2.3.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pyrefly==1.2.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-cov==7.1.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest==9.1.1; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff==0.16.1; extra == 'dev'
|
|
34
|
+
Provides-Extra: mcp
|
|
35
|
+
Requires-Dist: mcp<2,>=1.28.1; extra == 'mcp'
|
|
36
|
+
Provides-Extra: service
|
|
37
|
+
Requires-Dist: pillow<13,>=12.3.0; extra == 'service'
|
|
38
|
+
Requires-Dist: pystray<0.20,>=0.19.5; extra == 'service'
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# Kirox
|
|
42
|
+
|
|
43
|
+
Kirox is a typed Python SDK and local HTTP bridge for AI coding-assistant workflows. It provides incremental AWS EventStream decoding, a synchronous client, managed local service and tray lifecycle, text-only OpenAI/Anthropic-compatible endpoints, and an optional MCP stdio server.
|
|
44
|
+
|
|
45
|
+
Kirox deliberately binds its HTTP service to loopback addresses only. It is not a network-facing gateway and rejects `0.0.0.0` or other non-loopback hosts.
|
|
46
|
+
|
|
47
|
+
## Requirements
|
|
48
|
+
|
|
49
|
+
- Python 3.10 or newer; tested on 3.10–3.14
|
|
50
|
+
- A Kiro-compatible bearer token or an authenticated supported CLI database
|
|
51
|
+
- Windows, macOS, or Linux; tray support depends on the desktop environment
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
python -m pip install kirox # SDK, CLI, and local HTTP bridge
|
|
57
|
+
python -m pip install "kirox[service]" # Add pystray and Pillow
|
|
58
|
+
python -m pip install "kirox[mcp]" # Add the MCP SDK
|
|
59
|
+
python -m pip install "kirox[service,mcp]" # All optional features
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The MCP dependency is optional and imported only by MCP operations. Running `kirox-mcp` without it exits with an instruction to install `kirox[mcp]`; importing `kirox.mcp.server` remains safe.
|
|
63
|
+
|
|
64
|
+
## Authentication
|
|
65
|
+
|
|
66
|
+
`AuthManager.resolve()` uses a deterministic precedence order:
|
|
67
|
+
|
|
68
|
+
1. Explicit `token` / `profile_arn` arguments
|
|
69
|
+
2. Configuration values
|
|
70
|
+
3. `KIROX_TOKEN` / `KIROX_PROFILE_ARN`
|
|
71
|
+
4. Backward-compatible `ASSISTANT_TOKEN` / `ASSISTANT_PROFILE_ARN` aliases
|
|
72
|
+
5. An explicitly configured database, then fixed supported CLI database locations
|
|
73
|
+
|
|
74
|
+
`KIROX_DB_PATH` and `ASSISTANT_DB_PATH` can select a database. Kirox does not scan arbitrary files or treat unrelated keys such as `OPENAI_API_KEY` as upstream credentials.
|
|
75
|
+
|
|
76
|
+
## CLI and managed lifecycle
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
kirox # Same as `kirox run`
|
|
80
|
+
kirox run --no-tray # Service only
|
|
81
|
+
kirox run --no-update # Disable the background PyPI update check
|
|
82
|
+
kirox status
|
|
83
|
+
kirox stop # Authenticated graceful shutdown
|
|
84
|
+
kirox stop --force # Identity-verified PID fallback for unchanged state
|
|
85
|
+
kirox models
|
|
86
|
+
kirox chat --model auto
|
|
87
|
+
kirox ask --model auto "Hello"
|
|
88
|
+
kirox update
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The service owns one client, refresh scheduler, HTTP server, state file, and optional tray. Startup rolls back partial resources; normal stop closes threads, sockets, state, and the client idempotently. Runtime control data is stored in `~/.kirox/service.json` with a per-process token and is accepted only over loopback. State also records a kernel-derived process identity, so `stop --force` terminates only a process that still matches the recorded owner and fails closed on mismatch, on missing identity, or where the platform cannot supply one.
|
|
92
|
+
|
|
93
|
+
## Python API
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from kirox import AssistantClient
|
|
97
|
+
|
|
98
|
+
with AssistantClient.auto() as client:
|
|
99
|
+
for event in client.chat("Explain this function", model_id="auto"):
|
|
100
|
+
if event.content:
|
|
101
|
+
print(event.content, end="", flush=True)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`AssistantClient.chat()` validates and decodes upstream EventStream frames incrementally, including both CRCs and frame/header bounds. Closing the generator early closes the HTTP response.
|
|
105
|
+
|
|
106
|
+
## Local HTTP bridge
|
|
107
|
+
|
|
108
|
+
Start the service and use `http://127.0.0.1:8420` (or the configured loopback port):
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
kirox run --no-tray
|
|
112
|
+
|
|
113
|
+
curl http://127.0.0.1:8420/v1/chat/completions \
|
|
114
|
+
-H "Content-Type: application/json" \
|
|
115
|
+
-d '{"model":"auto","messages":[{"role":"user","content":"Hello"}],"stream":true}'
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Available routes include:
|
|
119
|
+
|
|
120
|
+
- Native: `/health`, `/`, `/api/models`, `/api/chat`, `/api/token/status`
|
|
121
|
+
- OpenAI-compatible: `/v1/models`, `/v1/chat/completions`
|
|
122
|
+
- Anthropic-compatible: `/v1/messages`
|
|
123
|
+
|
|
124
|
+
The provider adapters are intentionally **text-only**. They accept text strings or arrays of text blocks, preserve system/user/assistant history in a canonical transcript, require the final message to be from the user, and reject unsupported fields instead of silently ignoring them. Tools, tool calls, images, audio, metadata, sampling parameters, and other multimodal semantics are not supported. `max_tokens` is validated for compatibility but not enforced; responses carry an HTTP `Warning` and do not fabricate token usage.
|
|
125
|
+
|
|
126
|
+
Streaming is incremental SSE. OpenAI streams terminate once with `[DONE]`; Anthropic streams use ordered message/content events and a single terminal event. Upstream and internal exception details are sanitized from HTTP responses.
|
|
127
|
+
|
|
128
|
+
Requests must carry a loopback `Host` header, so a browser page on another origin cannot reach the bridge through DNS rebinding, and bodies larger than 1 MiB are rejected with HTTP 413 before validation or upstream work.
|
|
129
|
+
|
|
130
|
+
See [API Reference](docs/api-reference.md) for the complete request contract.
|
|
131
|
+
|
|
132
|
+
## MCP
|
|
133
|
+
|
|
134
|
+
After installing the extra, configure an MCP client to launch the stdio command:
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"mcpServers": {
|
|
139
|
+
"kirox": {"command": "kirox-mcp"}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The server exposes one `kirox_chat` tool with required non-empty `message` and optional non-empty `model` (default `auto`). Unknown tools, unknown arguments, and invalid values return errors. Synchronous client work runs in a worker thread so the MCP event loop stays responsive, and the owned client closes when the stdio session ends.
|
|
145
|
+
|
|
146
|
+
## Configuration
|
|
147
|
+
|
|
148
|
+
The default file is `~/.kirox/config.json`:
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"region": "us-east-1",
|
|
153
|
+
"server_host": "127.0.0.1",
|
|
154
|
+
"server_port": 8420,
|
|
155
|
+
"auto_refresh": true,
|
|
156
|
+
"refresh_interval": 3000,
|
|
157
|
+
"log_level": "INFO"
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Only loopback values are accepted for `server_host`. See [Configuration](docs/configuration.md) for all fields and environment aliases.
|
|
162
|
+
|
|
163
|
+
## Development and release gates
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
python -m pip install -e ".[dev,mcp]"
|
|
167
|
+
python -m ruff format --check .
|
|
168
|
+
python -m ruff check .
|
|
169
|
+
python -m mypy src tests scripts
|
|
170
|
+
python -m pyrefly check
|
|
171
|
+
python -m pytest tests -q --cov=kirox --cov-branch --cov-report=term-missing
|
|
172
|
+
python -m build
|
|
173
|
+
python scripts/verify_distribution.py
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Coverage is branch-aware and must remain at least 80%. Both type checkers run because they catch different classes of error; Pyrefly is configured explicitly in `pyproject.toml` so it does not silently fall back to its permissive `basic` preset. The distribution verifier checks `py.typed`, version metadata, both console scripts, then installs the wheel into a temporary clean virtual environment for import, CLI, missing-MCP, and `pip check` smoke tests.
|
|
177
|
+
|
|
178
|
+
## Documentation
|
|
179
|
+
|
|
180
|
+
- [Installation](docs/installation.md)
|
|
181
|
+
- [Configuration](docs/configuration.md)
|
|
182
|
+
- [API Reference](docs/api-reference.md)
|
|
183
|
+
- [Contributing](CONTRIBUTING.md)
|
|
184
|
+
- [Changelog](CHANGELOG.md)
|
|
185
|
+
|
|
186
|
+
## License
|
|
187
|
+
|
|
188
|
+
MIT License. See [LICENSE](LICENSE).
|