lithe-cli 0.6.2__tar.gz → 0.6.3__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.
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/PKG-INFO +12 -10
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/README.md +11 -9
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli/__init__.py +1 -1
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli/tui.py +2 -6
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli.egg-info/PKG-INFO +12 -10
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli.egg-info/requires.txt +1 -1
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/pyproject.toml +1 -1
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/tests/test_cli.py +27 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/LICENSE +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli/__main__.py +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli/agent.py +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli/config.py +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli/main.py +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli/prompts.py +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli/py.typed +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli/setup.py +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli/ui.py +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli.egg-info/SOURCES.txt +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli.egg-info/dependency_links.txt +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli.egg-info/entry_points.txt +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/lithe_cli.egg-info/top_level.txt +0 -0
- {lithe-cli-0.6.2 → lithe-cli-0.6.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lithe-cli
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
4
4
|
Summary: Command-line interface for the lithe agent kernel: chat, one-shot runs, undo, and run inspection.
|
|
5
5
|
License: MIT License
|
|
6
6
|
|
|
@@ -99,12 +99,12 @@ $ lithe run "总结 README.md 的要点,存到 SUMMARY.md"
|
|
|
99
99
|
⚒ read_file 读取 README.md
|
|
100
100
|
✓ 已读取 README.md(120 行) 0.1s
|
|
101
101
|
⚒ write_file 写入 SUMMARY.md
|
|
102
|
-
✓ 写入 SUMMARY.md 0.0s
|
|
102
|
+
✓ 写入 SUMMARY.md(+12 行,新建) 0.0s
|
|
103
103
|
已把要点写入 SUMMARY.md。
|
|
104
104
|
── done · steps 3 · tokens 2100 · cost 0.0042
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
修改已有文件时,助手优先调用 `edit_file` 或 `apply_patch` 做局部更新;只有新建文件或需要整体替换时才使用 `write_file
|
|
107
|
+
修改已有文件时,助手优先调用 `edit_file` 或 `apply_patch` 做局部更新;只有新建文件或需要整体替换时才使用 `write_file`。工具调用界面只显示工具名、文件路径等摘要,文件写入/编辑的结果带 `+N -M 行` 的行数变化提示(lithe 0.9.10 起由内核统计)。
|
|
108
108
|
|
|
109
109
|
`--stream` streams tokens as they generate; `-v` adds per-call
|
|
110
110
|
usage/context gauges; `--max-steps` caps the tool loop;
|
|
@@ -122,8 +122,8 @@ into the console:
|
|
|
122
122
|
│ 把 a.txt 改成三行待办清单 ││ ● 完成 · 0.2s │
|
|
123
123
|
│ ◆ update_todos ││ 步骤 2/35 · 0.2s │
|
|
124
124
|
│ ✓ 任务清单已更新(3 条) 0.0s ││ ✓ update_todos 0.0s│
|
|
125
|
-
│ ◆ edit_file · 局部修改 a.txt ││ ✓ edit_file 0.0s │
|
|
126
|
-
│ ✓
|
|
125
|
+
│ ◆ edit_file · 局部修改 a.txt ││ ✓ edit_file 0.0s │
|
|
126
|
+
│ ✓ 编辑 a.txt(+3 -1 行) 0.0s ││ ◆ 待办 1/3 │
|
|
127
127
|
│ 已完成。 ││ [~] 修改 a.txt │
|
|
128
128
|
│ ││ ◆ 会话用量 │
|
|
129
129
|
│ ││ 输入 1,024 · 输出 216│
|
|
@@ -132,14 +132,16 @@ into the console:
|
|
|
132
132
|
│ ││ 上下文 1,024 / 128,000 (0.8%)│
|
|
133
133
|
╰─────────────────────────────────────╯╰────────────────────╯
|
|
134
134
|
lithe ❯ _
|
|
135
|
-
● 完成 ·
|
|
135
|
+
● 完成 · 0.2s Enter 发送 · F2 侧栏 · /help 命令
|
|
136
136
|
```
|
|
137
137
|
|
|
138
138
|
The left pane is the conversation (task, compact tool-call summaries
|
|
139
|
-
and outcomes
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
and outcomes — file edits land with `+N -M 行` counts — and the
|
|
140
|
+
streaming assistant reply). The right sidebar shows run status, recent
|
|
141
|
+
tools, todos, session-wide cumulative input/output/cached tokens and
|
|
142
|
+
cost, plus the latest model-call context length and window percentage;
|
|
143
|
+
usage numbers live only there, the bottom bar keeps status and key
|
|
144
|
+
hints. The two panes are separate windows — selecting text
|
|
143
145
|
in one never captures the other — and the conversation scrolls: mouse
|
|
144
146
|
wheel, PageUp/PageDown, Home/End (a new turn jumps back to the output).
|
|
145
147
|
F2 or `/sidebar` hides the status pane so a reply can be copied from a
|
|
@@ -56,12 +56,12 @@ $ lithe run "总结 README.md 的要点,存到 SUMMARY.md"
|
|
|
56
56
|
⚒ read_file 读取 README.md
|
|
57
57
|
✓ 已读取 README.md(120 行) 0.1s
|
|
58
58
|
⚒ write_file 写入 SUMMARY.md
|
|
59
|
-
✓ 写入 SUMMARY.md 0.0s
|
|
59
|
+
✓ 写入 SUMMARY.md(+12 行,新建) 0.0s
|
|
60
60
|
已把要点写入 SUMMARY.md。
|
|
61
61
|
── done · steps 3 · tokens 2100 · cost 0.0042
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
修改已有文件时,助手优先调用 `edit_file` 或 `apply_patch` 做局部更新;只有新建文件或需要整体替换时才使用 `write_file
|
|
64
|
+
修改已有文件时,助手优先调用 `edit_file` 或 `apply_patch` 做局部更新;只有新建文件或需要整体替换时才使用 `write_file`。工具调用界面只显示工具名、文件路径等摘要,文件写入/编辑的结果带 `+N -M 行` 的行数变化提示(lithe 0.9.10 起由内核统计)。
|
|
65
65
|
|
|
66
66
|
`--stream` streams tokens as they generate; `-v` adds per-call
|
|
67
67
|
usage/context gauges; `--max-steps` caps the tool loop;
|
|
@@ -79,8 +79,8 @@ into the console:
|
|
|
79
79
|
│ 把 a.txt 改成三行待办清单 ││ ● 完成 · 0.2s │
|
|
80
80
|
│ ◆ update_todos ││ 步骤 2/35 · 0.2s │
|
|
81
81
|
│ ✓ 任务清单已更新(3 条) 0.0s ││ ✓ update_todos 0.0s│
|
|
82
|
-
│ ◆ edit_file · 局部修改 a.txt ││ ✓ edit_file 0.0s │
|
|
83
|
-
│ ✓
|
|
82
|
+
│ ◆ edit_file · 局部修改 a.txt ││ ✓ edit_file 0.0s │
|
|
83
|
+
│ ✓ 编辑 a.txt(+3 -1 行) 0.0s ││ ◆ 待办 1/3 │
|
|
84
84
|
│ 已完成。 ││ [~] 修改 a.txt │
|
|
85
85
|
│ ││ ◆ 会话用量 │
|
|
86
86
|
│ ││ 输入 1,024 · 输出 216│
|
|
@@ -89,14 +89,16 @@ into the console:
|
|
|
89
89
|
│ ││ 上下文 1,024 / 128,000 (0.8%)│
|
|
90
90
|
╰─────────────────────────────────────╯╰────────────────────╯
|
|
91
91
|
lithe ❯ _
|
|
92
|
-
● 完成 ·
|
|
92
|
+
● 完成 · 0.2s Enter 发送 · F2 侧栏 · /help 命令
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
The left pane is the conversation (task, compact tool-call summaries
|
|
96
|
-
and outcomes
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
and outcomes — file edits land with `+N -M 行` counts — and the
|
|
97
|
+
streaming assistant reply). The right sidebar shows run status, recent
|
|
98
|
+
tools, todos, session-wide cumulative input/output/cached tokens and
|
|
99
|
+
cost, plus the latest model-call context length and window percentage;
|
|
100
|
+
usage numbers live only there, the bottom bar keeps status and key
|
|
101
|
+
hints. The two panes are separate windows — selecting text
|
|
100
102
|
in one never captures the other — and the conversation scrolls: mouse
|
|
101
103
|
wheel, PageUp/PageDown, Home/End (a new turn jumps back to the output).
|
|
102
104
|
F2 or `/sidebar` hides the status pane so a reply can be copied from a
|
|
@@ -450,13 +450,9 @@ def body_layout(state: TuiState, width: int, height: int):
|
|
|
450
450
|
|
|
451
451
|
|
|
452
452
|
def compose_footer(state: TuiState, width: int, running_hint: str) -> list:
|
|
453
|
+
"""Status + key hints only; usage lives in the sidebar, not down here."""
|
|
453
454
|
dot = f"class:foot class:{_status_class(state.status)}"
|
|
454
|
-
|
|
455
|
-
total_cost = state.cost + state._turn_cost
|
|
456
|
-
left = (
|
|
457
|
-
f" ● {state.status} · step {state.step}/{state.max_steps}"
|
|
458
|
-
f" · {total_tokens:,} tok · ${total_cost:.4f}"
|
|
459
|
-
)
|
|
455
|
+
left = f" ● {state.status} "
|
|
460
456
|
room = width - display_width(running_hint) - display_width(left) - 2
|
|
461
457
|
text = left + (" " * max(1, room)) if room >= 1 else truncate(left, width - display_width(running_hint) - 1)
|
|
462
458
|
return [(dot, " "), ("class:foot", pad(text, width - display_width(running_hint))), ("class:foot", running_hint)]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lithe-cli
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
4
4
|
Summary: Command-line interface for the lithe agent kernel: chat, one-shot runs, undo, and run inspection.
|
|
5
5
|
License: MIT License
|
|
6
6
|
|
|
@@ -99,12 +99,12 @@ $ lithe run "总结 README.md 的要点,存到 SUMMARY.md"
|
|
|
99
99
|
⚒ read_file 读取 README.md
|
|
100
100
|
✓ 已读取 README.md(120 行) 0.1s
|
|
101
101
|
⚒ write_file 写入 SUMMARY.md
|
|
102
|
-
✓ 写入 SUMMARY.md 0.0s
|
|
102
|
+
✓ 写入 SUMMARY.md(+12 行,新建) 0.0s
|
|
103
103
|
已把要点写入 SUMMARY.md。
|
|
104
104
|
── done · steps 3 · tokens 2100 · cost 0.0042
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
修改已有文件时,助手优先调用 `edit_file` 或 `apply_patch` 做局部更新;只有新建文件或需要整体替换时才使用 `write_file
|
|
107
|
+
修改已有文件时,助手优先调用 `edit_file` 或 `apply_patch` 做局部更新;只有新建文件或需要整体替换时才使用 `write_file`。工具调用界面只显示工具名、文件路径等摘要,文件写入/编辑的结果带 `+N -M 行` 的行数变化提示(lithe 0.9.10 起由内核统计)。
|
|
108
108
|
|
|
109
109
|
`--stream` streams tokens as they generate; `-v` adds per-call
|
|
110
110
|
usage/context gauges; `--max-steps` caps the tool loop;
|
|
@@ -122,8 +122,8 @@ into the console:
|
|
|
122
122
|
│ 把 a.txt 改成三行待办清单 ││ ● 完成 · 0.2s │
|
|
123
123
|
│ ◆ update_todos ││ 步骤 2/35 · 0.2s │
|
|
124
124
|
│ ✓ 任务清单已更新(3 条) 0.0s ││ ✓ update_todos 0.0s│
|
|
125
|
-
│ ◆ edit_file · 局部修改 a.txt ││ ✓ edit_file 0.0s │
|
|
126
|
-
│ ✓
|
|
125
|
+
│ ◆ edit_file · 局部修改 a.txt ││ ✓ edit_file 0.0s │
|
|
126
|
+
│ ✓ 编辑 a.txt(+3 -1 行) 0.0s ││ ◆ 待办 1/3 │
|
|
127
127
|
│ 已完成。 ││ [~] 修改 a.txt │
|
|
128
128
|
│ ││ ◆ 会话用量 │
|
|
129
129
|
│ ││ 输入 1,024 · 输出 216│
|
|
@@ -132,14 +132,16 @@ into the console:
|
|
|
132
132
|
│ ││ 上下文 1,024 / 128,000 (0.8%)│
|
|
133
133
|
╰─────────────────────────────────────╯╰────────────────────╯
|
|
134
134
|
lithe ❯ _
|
|
135
|
-
● 完成 ·
|
|
135
|
+
● 完成 · 0.2s Enter 发送 · F2 侧栏 · /help 命令
|
|
136
136
|
```
|
|
137
137
|
|
|
138
138
|
The left pane is the conversation (task, compact tool-call summaries
|
|
139
|
-
and outcomes
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
and outcomes — file edits land with `+N -M 行` counts — and the
|
|
140
|
+
streaming assistant reply). The right sidebar shows run status, recent
|
|
141
|
+
tools, todos, session-wide cumulative input/output/cached tokens and
|
|
142
|
+
cost, plus the latest model-call context length and window percentage;
|
|
143
|
+
usage numbers live only there, the bottom bar keeps status and key
|
|
144
|
+
hints. The two panes are separate windows — selecting text
|
|
143
145
|
in one never captures the other — and the conversation scrolls: mouse
|
|
144
146
|
wheel, PageUp/PageDown, Home/End (a new turn jumps back to the output).
|
|
145
147
|
F2 or `/sidebar` hides the status pane so a reply can be copied from a
|
|
@@ -9,7 +9,7 @@ description = "Command-line interface for the lithe agent kernel: chat, one-shot
|
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
11
11
|
requires-python = ">=3.10"
|
|
12
|
-
dependencies = ["lithe>=0.9.
|
|
12
|
+
dependencies = ["lithe>=0.9.10", "prompt-toolkit>=3.0.38"]
|
|
13
13
|
keywords = ["agent", "llm", "react", "cli", "tool-calling"]
|
|
14
14
|
classifiers = [
|
|
15
15
|
"Development Status :: 4 - Beta",
|
|
@@ -672,6 +672,33 @@ def _pty_drain(fd) -> bytes:
|
|
|
672
672
|
return out
|
|
673
673
|
|
|
674
674
|
|
|
675
|
+
def test_footer_does_not_duplicate_sidebar_usage():
|
|
676
|
+
from lithe_cli.tui import TuiState, compose_footer
|
|
677
|
+
|
|
678
|
+
state = TuiState("m", "/ws", 5)
|
|
679
|
+
state.on_event({"type": "done", "status": "done", "steps": 3, "tokens": 120, "cost": 0.5})
|
|
680
|
+
line = "".join(f[1] for f in compose_footer(state, 100, " hint "))
|
|
681
|
+
assert "完成" in line
|
|
682
|
+
assert "tok" not in line and "$" not in line and "step" not in line
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
def test_file_tools_report_line_delta_in_feed(tmp_path):
|
|
686
|
+
script = [
|
|
687
|
+
{"tool_calls": [_tc("write_file", {"path": "a.txt", "content": "hi"}, "c1")]},
|
|
688
|
+
{"tool_calls": [_tc("edit_file",
|
|
689
|
+
{"path": "a.txt", "old_text": "hi", "new_text": "hi\nyo"}, "c2")]},
|
|
690
|
+
{"content": "完成"},
|
|
691
|
+
]
|
|
692
|
+
cfg = make_config(tmp_path, script)
|
|
693
|
+
seen = []
|
|
694
|
+
rid, done, _ = asyncio.run(execute(cfg, "编辑 a.txt", on_event=seen.append))
|
|
695
|
+
assert done["status"] == "done"
|
|
696
|
+
summaries = [e.get("summary", "") for e in seen if e["type"] == "tool_result"]
|
|
697
|
+
assert any("写入 a.txt(+1 行,新建)" in s for s in summaries)
|
|
698
|
+
assert any("编辑 a.txt(+1 行)" in s for s in summaries)
|
|
699
|
+
assert (cfg.workspace_dir / "a.txt").read_text(encoding="utf-8") == "hi\nyo"
|
|
700
|
+
|
|
701
|
+
|
|
675
702
|
def test_fullscreen_app_scrolls_and_toggles_sidebar():
|
|
676
703
|
code = """
|
|
677
704
|
import asyncio
|
|
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
|