lisa-cli 0.3.0__tar.gz → 0.4.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.
- {lisa_cli-0.3.0/src/lisa_cli.egg-info → lisa_cli-0.4.0}/PKG-INFO +9 -9
- lisa_cli-0.4.0/pyproject.toml +177 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/src/hosts/cli/entry.py +13 -7
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/src/hosts/cli/main.py +410 -147
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/src/hosts/cli/render.py +13 -4
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/src/hosts/cli/transport.py +74 -23
- lisa_cli-0.4.0/src/hosts/cli/update.py +624 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0/src/lisa_cli.egg-info}/PKG-INFO +9 -9
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/src/lisa_cli.egg-info/SOURCES.txt +12 -1
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/src/lisa_cli.egg-info/requires.txt +8 -8
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_approval_panel.py +1 -2
- lisa_cli-0.4.0/tests/test_changed_coverage.py +158 -0
- lisa_cli-0.4.0/tests/test_check_coverage_gate.py +108 -0
- lisa_cli-0.4.0/tests/test_check_docs.py +227 -0
- lisa_cli-0.4.0/tests/test_direct_io_policy.py +134 -0
- lisa_cli-0.4.0/tests/test_error_text_escaping.py +118 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_group_resolution.py +48 -5
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_last_command.py +11 -4
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_models_command.py +4 -6
- lisa_cli-0.4.0/tests/test_no_locals_dump.py +69 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_pack_update.py +55 -4
- lisa_cli-0.4.0/tests/test_profile_env_fallback.py +99 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_profile_option.py +23 -8
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_prompt_decisions.py +7 -19
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_prompt_transport.py +98 -6
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_render_catalogs.py +3 -2
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_streaming.py +1 -1
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_update_command.py +136 -20
- lisa_cli-0.4.0/tests/test_update_policy.py +550 -0
- lisa_cli-0.4.0/tests/test_update_policy_uv.py +497 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_verify_command.py +115 -19
- lisa_cli-0.4.0/tests/test_version_output.py +71 -0
- lisa_cli-0.3.0/pyproject.toml +0 -75
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/LICENSE +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/setup.cfg +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/src/hosts/__init__.py +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/src/hosts/cli/__init__.py +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/src/hosts/cli/expand.py +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/src/lisa_cli.egg-info/dependency_links.txt +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/src/lisa_cli.egg-info/entry_points.txt +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/src/lisa_cli.egg-info/top_level.txt +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_prompt_command.py +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_prompt_entry.py +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_prompt_expand.py +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_render_models.py +1 -1
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_restart.py +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_runtime_teardown.py +0 -0
- {lisa_cli-0.3.0 → lisa_cli-0.4.0}/tests/test_transport_stage.py +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lisa-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Terminal CLI for the Lisa Harness
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Python: >=3.11
|
|
7
7
|
License-File: LICENSE
|
|
8
|
-
Requires-Dist: lisa-harness-runtime
|
|
9
|
-
Requires-Dist: lisa-harness-kernel
|
|
10
|
-
Requires-Dist: lisa-harness-sdk
|
|
11
|
-
Requires-Dist: lisa-harness-mcp-servers
|
|
12
|
-
Requires-Dist: lisa-pack-core
|
|
13
|
-
Requires-Dist: lisa-pack-introspect
|
|
14
|
-
Requires-Dist: lisa-pack-memory
|
|
15
|
-
Requires-Dist: lisa-pack-recovery
|
|
8
|
+
Requires-Dist: lisa-harness-runtime>=0.5.2
|
|
9
|
+
Requires-Dist: lisa-harness-kernel>=0.5.2
|
|
10
|
+
Requires-Dist: lisa-harness-sdk>=0.5.2
|
|
11
|
+
Requires-Dist: lisa-harness-mcp-servers>=0.5.2
|
|
12
|
+
Requires-Dist: lisa-pack-core>=0.5.2
|
|
13
|
+
Requires-Dist: lisa-pack-introspect>=0.5.2
|
|
14
|
+
Requires-Dist: lisa-pack-memory>=0.5.2
|
|
15
|
+
Requires-Dist: lisa-pack-recovery>=0.5.2
|
|
16
16
|
Requires-Dist: openai>=1.30.0
|
|
17
17
|
Requires-Dist: rich>=13.7.0
|
|
18
18
|
Requires-Dist: typer>=0.12.3
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[tool.setuptools.packages.find]
|
|
6
|
+
where = ["src"]
|
|
7
|
+
|
|
8
|
+
[project]
|
|
9
|
+
name = "lisa-cli"
|
|
10
|
+
version = "0.4.0"
|
|
11
|
+
description = "Terminal CLI for the Lisa Harness"
|
|
12
|
+
requires-python = ">=3.11"
|
|
13
|
+
license = "MIT"
|
|
14
|
+
license-files = ["LICENSE"]
|
|
15
|
+
dependencies = [
|
|
16
|
+
"lisa-harness-runtime>=0.5.2",
|
|
17
|
+
"lisa-harness-kernel>=0.5.2",
|
|
18
|
+
"lisa-harness-sdk>=0.5.2",
|
|
19
|
+
"lisa-harness-mcp-servers>=0.5.2",
|
|
20
|
+
"lisa-pack-core>=0.5.2",
|
|
21
|
+
"lisa-pack-introspect>=0.5.2",
|
|
22
|
+
"lisa-pack-memory>=0.5.2",
|
|
23
|
+
"lisa-pack-recovery>=0.5.2",
|
|
24
|
+
"openai>=1.30.0",
|
|
25
|
+
"rich>=13.7.0",
|
|
26
|
+
"typer>=0.12.3",
|
|
27
|
+
"pyyaml>=6.0",
|
|
28
|
+
"httpx>=0.27.0",
|
|
29
|
+
"pydantic>=2.7.0",
|
|
30
|
+
"python-dotenv>=1.0.0",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
lisa = "hosts.cli.main:main"
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
dev = [
|
|
38
|
+
"pyinstaller>=6.10.0",
|
|
39
|
+
"pytest>=8.0.0",
|
|
40
|
+
"pytest-asyncio>=0.23.0",
|
|
41
|
+
"ruff>=0.8.0",
|
|
42
|
+
"types-PyYAML>=6.0",
|
|
43
|
+
]
|
|
44
|
+
# Interactive no-args `lisa prompt` editor: single-box input with
|
|
45
|
+
# history. Without the extra the plain EOF-terminated reader is used.
|
|
46
|
+
prompt = ["prompt-toolkit>=3.0"]
|
|
47
|
+
|
|
48
|
+
[tool.pytest.ini_options]
|
|
49
|
+
pythonpath = ["src"]
|
|
50
|
+
testpaths = ["tests"]
|
|
51
|
+
markers = [
|
|
52
|
+
"live: hits real external signal or provider APIs and prints a tester-visible summary",
|
|
53
|
+
"integration: multi-module in-process test; may require local services",
|
|
54
|
+
"eval: deterministic agent regression evals (no model calls, no I/O)",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[tool.coverage.run]
|
|
58
|
+
branch = true
|
|
59
|
+
relative_files = true
|
|
60
|
+
source = ["src"]
|
|
61
|
+
omit = [
|
|
62
|
+
"*/tests/*",
|
|
63
|
+
"*/test_*.py",
|
|
64
|
+
"*/conftest.py",
|
|
65
|
+
]
|
|
66
|
+
source_pkgs = ["hosts.cli"]
|
|
67
|
+
|
|
68
|
+
[tool.coverage.paths]
|
|
69
|
+
source = [
|
|
70
|
+
"src",
|
|
71
|
+
"*/src",
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
[tool.coverage.report]
|
|
75
|
+
show_missing = true
|
|
76
|
+
skip_covered = true
|
|
77
|
+
fail_under = 85
|
|
78
|
+
exclude_also = [
|
|
79
|
+
".*/tests/.*",
|
|
80
|
+
".*/test_[^/]*\\.py$",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
[tool.ruff]
|
|
84
|
+
line-length = 100
|
|
85
|
+
target-version = "py311"
|
|
86
|
+
extend-exclude = ["vulture_allowlist.py"]
|
|
87
|
+
|
|
88
|
+
[tool.ruff.lint]
|
|
89
|
+
select = [
|
|
90
|
+
"E",
|
|
91
|
+
"F",
|
|
92
|
+
"I",
|
|
93
|
+
"UP",
|
|
94
|
+
"B",
|
|
95
|
+
"SIM",
|
|
96
|
+
"PL",
|
|
97
|
+
"C90",
|
|
98
|
+
"RET",
|
|
99
|
+
"RUF",
|
|
100
|
+
"W",
|
|
101
|
+
"YTT",
|
|
102
|
+
"C4",
|
|
103
|
+
"PERF",
|
|
104
|
+
"PIE",
|
|
105
|
+
"FURB",
|
|
106
|
+
"G",
|
|
107
|
+
]
|
|
108
|
+
ignore = ["PLR0913", "PLC0415", "RUF001", "RUF002", "RUF003"]
|
|
109
|
+
|
|
110
|
+
[tool.ruff.lint.per-file-ignores]
|
|
111
|
+
"**/tests/**" = ["PLC0415", "PLR2004"]
|
|
112
|
+
"**/hosts/cli/main.py" = ["E402", "PLC0415", "PLR0917"]
|
|
113
|
+
"**/hosts/cli/render.py" = ["PLC0415"]
|
|
114
|
+
"**/hosts/cli/entry.py" = ["PLC0415", "RUF001"]
|
|
115
|
+
|
|
116
|
+
[tool.ruff.lint.mccabe]
|
|
117
|
+
max-complexity = 10
|
|
118
|
+
|
|
119
|
+
[tool.ruff.lint.pylint]
|
|
120
|
+
max-returns = 6
|
|
121
|
+
max-branches = 12
|
|
122
|
+
max-statements = 50
|
|
123
|
+
max-locals = 15
|
|
124
|
+
|
|
125
|
+
[tool.ruff.format]
|
|
126
|
+
line-ending = "lf"
|
|
127
|
+
|
|
128
|
+
[tool.mypy]
|
|
129
|
+
python_version = "3.11"
|
|
130
|
+
files = ["src/hosts/cli"]
|
|
131
|
+
mypy_path = ["$MYPY_CONFIG_FILE_DIR/src"]
|
|
132
|
+
explicit_package_bases = true
|
|
133
|
+
strict = true
|
|
134
|
+
warn_unused_ignores = true
|
|
135
|
+
warn_redundant_casts = true
|
|
136
|
+
warn_return_any = true
|
|
137
|
+
no_implicit_optional = true
|
|
138
|
+
check_untyped_defs = true
|
|
139
|
+
disallow_untyped_defs = true
|
|
140
|
+
disallow_incomplete_defs = true
|
|
141
|
+
exclude = ["vulture_allowlist.py", '(^|/)(tests|test_[^/]*\.py$)']
|
|
142
|
+
|
|
143
|
+
[tool.vulture]
|
|
144
|
+
paths = ["src/hosts/cli", "vulture_allowlist.py"]
|
|
145
|
+
min_confidence = 80
|
|
146
|
+
exclude = [
|
|
147
|
+
"**/tests/",
|
|
148
|
+
"**/test_*.py",
|
|
149
|
+
"**/conftest.py",
|
|
150
|
+
"**/*egg-info*/",
|
|
151
|
+
"**/__pycache__/",
|
|
152
|
+
".venv/",
|
|
153
|
+
]
|
|
154
|
+
ignore_names = [
|
|
155
|
+
"main",
|
|
156
|
+
"*SignalCollector",
|
|
157
|
+
"*Collector",
|
|
158
|
+
"*ProcessingLoop",
|
|
159
|
+
"*Detector",
|
|
160
|
+
"*Registry",
|
|
161
|
+
"*Store",
|
|
162
|
+
"*Broker",
|
|
163
|
+
"*Catalog",
|
|
164
|
+
"*Spec",
|
|
165
|
+
"*Config",
|
|
166
|
+
"*Policy",
|
|
167
|
+
"*Manifest",
|
|
168
|
+
"*Error",
|
|
169
|
+
"*Exception",
|
|
170
|
+
"*Context",
|
|
171
|
+
"*Fragments",
|
|
172
|
+
"*Sections",
|
|
173
|
+
"*Evidence",
|
|
174
|
+
"*Summary",
|
|
175
|
+
"*Anomalies",
|
|
176
|
+
]
|
|
177
|
+
ignore_decorators = ["@property"]
|
|
@@ -50,10 +50,13 @@ from __future__ import annotations
|
|
|
50
50
|
import os
|
|
51
51
|
import unicodedata
|
|
52
52
|
from pathlib import Path
|
|
53
|
-
from typing import Any
|
|
53
|
+
from typing import TYPE_CHECKING, Any
|
|
54
54
|
|
|
55
55
|
from rich.console import Console
|
|
56
56
|
|
|
57
|
+
if TYPE_CHECKING:
|
|
58
|
+
from prompt_toolkit.key_binding import KeyBindings
|
|
59
|
+
|
|
57
60
|
#: Unicode general categories that extend a grapheme cluster: combining
|
|
58
61
|
#: marks, enclosing marks, format characters (variation selectors, ZWSP),
|
|
59
62
|
#: and modifier symbols (skin-tone modifiers). ZWJ itself is ``Cf`` but is
|
|
@@ -186,7 +189,7 @@ def settings_file_path(data_dir: str | Path, profile: str) -> Path:
|
|
|
186
189
|
"""
|
|
187
190
|
from runtime.config import profile_data_dir # lazy: import cost
|
|
188
191
|
|
|
189
|
-
base = str(data_dir).strip()
|
|
192
|
+
base = str(data_dir).strip() or ""
|
|
190
193
|
if not base and profile.strip():
|
|
191
194
|
base = str(profile_data_dir(profile.strip()))
|
|
192
195
|
if not base:
|
|
@@ -289,7 +292,7 @@ def prompt_history_path(data_dir: str | Path, profile: str) -> Path:
|
|
|
289
292
|
the profile dir; empty hands the decision to the framework's default
|
|
290
293
|
(``LISA_DATA_DIR`` > ``~/.lisa``).
|
|
291
294
|
"""
|
|
292
|
-
base = str(data_dir).strip()
|
|
295
|
+
base = str(data_dir).strip() or ""
|
|
293
296
|
if not base and profile.strip():
|
|
294
297
|
from runtime.config import profile_data_dir # lazy: import cost
|
|
295
298
|
|
|
@@ -429,7 +432,7 @@ def _delete_first_grapheme(text: str) -> int:
|
|
|
429
432
|
return i
|
|
430
433
|
|
|
431
434
|
|
|
432
|
-
def _add_navigate_bindings(bindings:
|
|
435
|
+
def _add_navigate_bindings(bindings: KeyBindings, *, swapped: bool = True) -> None:
|
|
433
436
|
"""Bind submit/newline and navigation keys.
|
|
434
437
|
|
|
435
438
|
``swapped`` (the default) puts newline on Enter and send on
|
|
@@ -476,7 +479,7 @@ def _add_navigate_bindings(bindings: Any, *, swapped: bool = True) -> None:
|
|
|
476
479
|
event.current_buffer.history_forward()
|
|
477
480
|
|
|
478
481
|
|
|
479
|
-
def _add_grapheme_delete_bindings(bindings:
|
|
482
|
+
def _add_grapheme_delete_bindings(bindings: KeyBindings) -> None:
|
|
480
483
|
"""Bind backspace (Ctrl-H) and forward Delete to cluster-aware cuts.
|
|
481
484
|
|
|
482
485
|
prompt_toolkit deletes one codepoint, tearing multi-codepoint emoji
|
|
@@ -504,14 +507,17 @@ def _add_grapheme_delete_bindings(bindings: Any) -> None:
|
|
|
504
507
|
buffer.cursor_position = pos
|
|
505
508
|
|
|
506
509
|
|
|
507
|
-
def _tui_key_bindings(swapped: bool = True) ->
|
|
510
|
+
def _tui_key_bindings(swapped: bool = True) -> KeyBindings:
|
|
508
511
|
"""Build the owned key model for the TUI reader.
|
|
509
512
|
|
|
510
513
|
``swapped`` selects the send/newline layout (see
|
|
511
514
|
:func:`_add_navigate_bindings`); this exists so the reader body
|
|
512
515
|
stays under its complexity budget.
|
|
513
516
|
"""
|
|
514
|
-
|
|
517
|
+
pt = _PT
|
|
518
|
+
if pt is None: # pragma: no cover - guarded by the caller's _PT check
|
|
519
|
+
raise RuntimeError("_tui_key_bindings requires the prompt extra")
|
|
520
|
+
bindings: KeyBindings = pt["KeyBindings"]()
|
|
515
521
|
_add_navigate_bindings(bindings, swapped=swapped)
|
|
516
522
|
_add_grapheme_delete_bindings(bindings)
|
|
517
523
|
return bindings
|