nexforge-cli 0.2.3__tar.gz → 0.2.5__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.
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/PKG-INFO +1 -1
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/pyproject.toml +1 -1
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/core/session.py +9 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/widgets/messages.py +19 -13
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/.gitignore +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/= +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/INSTALL.md +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/README.md +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/agent.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/cost.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/edit.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/err.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/file.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/model.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/ok.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/read.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/running.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/search.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/shell.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/thinking.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/web.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/assets/icons/write.svg +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/config.example.toml +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/devlog/2026-07-07.md +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//344/274/232/350/257/235/347/256/241/347/220/206.md" +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//345/221/275/344/273/244/344/270/216/345/277/253/346/215/267/351/224/256.md" +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//345/256/211/350/243/205/344/270/216/351/205/215/347/275/256.md" +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//345/257/271/346/257/224/345/210/206/346/236/220.md" +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//345/267/245/345/205/267/345/217/202/350/200/203.md" +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//346/200/273/350/247/210.md" +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//346/235/203/351/231/220/347/263/273/347/273/237.md" +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//350/256/241/345/210/222/346/250/241/345/274/217.md" +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//351/253/230/347/272/247/345/212/237/350/203/275.md" +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/scripts/publish.sh +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/scripts/smoke_provider.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/scripts/smoke_tui.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/__init__.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/__main__.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/app.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/cli.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/config.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/core/__init__.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/core/agent.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/core/jobs.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/core/permissions.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/core/router.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/core/types.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/icons.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/mcp/__init__.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/provider/__init__.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/provider/balance.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/provider/deepseek.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/skills/loader.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/store/__init__.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/store/plan_store.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/store/session_store.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/theme.tcss +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/__init__.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/_paths.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/background.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/base.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/edit_file.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/fs_ops.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/git.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/list_dir.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/multi_edit.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/read_file.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/registry.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/search_content.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/search_files.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/shell.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/web.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/tools/write_file.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/__init__.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/screens/__init__.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/screens/chat.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/widgets/__init__.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/widgets/apikey_modal.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/widgets/banner.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/widgets/confirm_modal.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/widgets/diff_modal.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/widgets/mode_warning.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/widgets/multiline_modal.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/widgets/multiline_prompt.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/widgets/plan_sidebar.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/widgets/sidebar.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/ui/widgets/statusbar.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/web/__init__.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/web/server.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/src/nexforge/web/static/index.html +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/tests/test_approval.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/tests/test_config.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/tests/test_icons.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/tests/test_m2_tools.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/tests/test_sidebar.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/tests/test_sidebar_actions.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/tests/test_tools.py +0 -0
- {nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/tests/test_tui.py +0 -0
|
@@ -31,6 +31,15 @@ class Session:
|
|
|
31
31
|
self.messages.append({"role": "system", "content": self.system_prompt})
|
|
32
32
|
|
|
33
33
|
def add_user(self, text: str) -> None:
|
|
34
|
+
# 中断恢复:若上一条 assistant 有未完成 tool_calls,补 tool 错误
|
|
35
|
+
if self.messages and self.messages[-1].get("role") == "assistant":
|
|
36
|
+
pending = self.messages[-1].get("tool_calls", [])
|
|
37
|
+
for tc in pending:
|
|
38
|
+
self.messages.append({
|
|
39
|
+
"role": "tool",
|
|
40
|
+
"tool_call_id": tc.get("id", ""),
|
|
41
|
+
"content": "已取消(用户中断)。",
|
|
42
|
+
})
|
|
34
43
|
self.messages.append({"role": "user", "content": text})
|
|
35
44
|
|
|
36
45
|
def add_assistant(self, msg: AssistantMessage) -> None:
|
|
@@ -2,16 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from rich.markup import escape
|
|
6
5
|
from textual.app import ComposeResult
|
|
7
6
|
from textual.containers import Vertical
|
|
8
7
|
from textual.widgets import Collapsible, Static
|
|
9
8
|
from rich.markdown import Markdown as RichMarkdown
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def _esc(text: str) -> str:
|
|
13
|
-
"""Rich markup safe escape: [ -> \\[ , ] -> \\]."""
|
|
14
|
-
return escape(text).replace("]", r"\]")
|
|
9
|
+
from rich.text import Text
|
|
15
10
|
|
|
16
11
|
|
|
17
12
|
class SystemNote(Static):
|
|
@@ -22,14 +17,20 @@ class SystemNote(Static):
|
|
|
22
17
|
|
|
23
18
|
sym = icon("err") if error else icon("running")
|
|
24
19
|
color = "red" if error else "#22D3EE"
|
|
25
|
-
|
|
20
|
+
t = Text()
|
|
21
|
+
t.append(f"{sym} ", style=color)
|
|
22
|
+
t.append(text)
|
|
23
|
+
super().__init__(t)
|
|
26
24
|
|
|
27
25
|
|
|
28
26
|
class UserMessage(Static):
|
|
29
27
|
def __init__(self, text: str) -> None:
|
|
30
28
|
from nexforge.icons import icon
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
t = Text()
|
|
31
|
+
t.append(f"{icon('user')} ", style="bold #6D5EF5")
|
|
32
|
+
t.append(text)
|
|
33
|
+
super().__init__(t)
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
class ToolCard(Static):
|
|
@@ -44,17 +45,22 @@ class ToolCard(Static):
|
|
|
44
45
|
from nexforge.icons import icon
|
|
45
46
|
|
|
46
47
|
ic = icon(self._icon)
|
|
47
|
-
|
|
48
|
+
t = Text()
|
|
49
|
+
t.append(f"{ic} ", style="#22D3EE")
|
|
50
|
+
t.append(self._preview)
|
|
51
|
+
t.append(" 执行…", style="dim")
|
|
52
|
+
self.update(t)
|
|
48
53
|
|
|
49
54
|
def set_result(self, ok: bool, summary: str) -> None:
|
|
50
55
|
from nexforge.icons import icon
|
|
51
56
|
|
|
52
57
|
mark = icon("ok") if ok else icon("err")
|
|
53
58
|
color = "green" if ok else "red"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
)
|
|
59
|
+
t = Text()
|
|
60
|
+
t.append(f"{mark} ", style=color)
|
|
61
|
+
t.append(f"{self._preview} ", style="#22D3EE")
|
|
62
|
+
t.append(summary, style="dim")
|
|
63
|
+
self.update(t)
|
|
58
64
|
|
|
59
65
|
|
|
60
66
|
class AssistantTurn(Vertical):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//344/274/232/350/257/235/347/256/241/347/220/206.md"
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//345/257/271/346/257/224/345/210/206/346/236/220.md"
RENAMED
|
File without changes
|
{nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//345/267/245/345/205/267/345/217/202/350/200/203.md"
RENAMED
|
File without changes
|
|
File without changes
|
{nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//346/235/203/351/231/220/347/263/273/347/273/237.md"
RENAMED
|
File without changes
|
{nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//350/256/241/345/210/222/346/250/241/345/274/217.md"
RENAMED
|
File without changes
|
{nexforge_cli-0.2.3 → nexforge_cli-0.2.5}/doc//351/253/230/347/272/247/345/212/237/350/203/275.md"
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|