context-forge-cli 0.4.8__tar.gz → 0.4.9__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.
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/PKG-INFO +1 -1
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/widgets/session_detail.py +16 -5
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/widgets/tokens_panel.py +13 -18
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/pyproject.toml +1 -1
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/.contextforge.toml +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/.github/workflows/publish.yml +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/.gitignore +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/.python-version +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/AGENTS.md +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/PLAN.md +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/README.md +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/__init__.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/adapters/__init__.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/adapters/altimate_code.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/adapters/base.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/adapters/claude_code.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/adapters/claude_desktop.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/adapters/codex.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/adapters/gemini.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/adapters/registry.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/cli.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/core/__init__.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/core/analytics.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/core/compactor.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/core/db.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/core/injector.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/core/scanner.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/core/summarizer.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/core/token_analyzer.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/mcp_server.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/models/__init__.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/models/config.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/models/session.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/__init__.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/app.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/clipboard.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/styles.tcss +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/widgets/__init__.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/widgets/session_table.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/widgets/stats_panel.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/widgets/status_bar.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/widgets/transfer_panel.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/utils/__init__.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/utils/display.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/utils/tokens.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/__init__.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/adapters/__init__.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/adapters/test_claude_code.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/conftest.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/core/__init__.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/core/test_compactor.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/core/test_db.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/core/test_injector.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/core/test_summarizer.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/core/test_token_analyzer.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/fixtures/claude_session_sample.jsonl +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/test_mcp_server.py +0 -0
- {context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: context-forge-cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.9
|
|
4
4
|
Summary: Session manager and context bridge for agentic CLI tools
|
|
5
5
|
Project-URL: Homepage, https://github.com/emmver/contextforge
|
|
6
6
|
Project-URL: Repository, https://github.com/emmver/contextforge
|
{context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/widgets/session_detail.py
RENAMED
|
@@ -8,7 +8,7 @@ from pathlib import Path
|
|
|
8
8
|
from textual.app import ComposeResult
|
|
9
9
|
from textual.containers import Vertical
|
|
10
10
|
from textual.widget import Widget
|
|
11
|
-
from textual.widgets import Markdown, Static
|
|
11
|
+
from textual.widgets import Markdown, Static, TextArea
|
|
12
12
|
|
|
13
13
|
TOOL_COLORS = {
|
|
14
14
|
"claude_code": "cyan",
|
|
@@ -101,6 +101,17 @@ class SessionDetail(Widget):
|
|
|
101
101
|
background: transparent;
|
|
102
102
|
color: $text;
|
|
103
103
|
}
|
|
104
|
+
SessionDetail TextArea {
|
|
105
|
+
height: 1;
|
|
106
|
+
border: none;
|
|
107
|
+
background: transparent;
|
|
108
|
+
color: $text;
|
|
109
|
+
padding: 0;
|
|
110
|
+
margin: 0;
|
|
111
|
+
}
|
|
112
|
+
SessionDetail TextArea:focus {
|
|
113
|
+
border: none;
|
|
114
|
+
}
|
|
104
115
|
"""
|
|
105
116
|
|
|
106
117
|
_current_id: str | None = None
|
|
@@ -110,13 +121,13 @@ class SessionDetail(Widget):
|
|
|
110
121
|
yield Static("", id="detail-title")
|
|
111
122
|
with Vertical(id="detail-meta-block"):
|
|
112
123
|
yield Static("", id="detail-tool")
|
|
113
|
-
yield
|
|
124
|
+
yield TextArea("", id="detail-cwd", read_only=True)
|
|
114
125
|
yield Static("", id="detail-tokens")
|
|
115
126
|
yield Static("", id="detail-created")
|
|
116
127
|
yield Static("", id="detail-updated")
|
|
117
128
|
yield Static("", id="detail-status")
|
|
118
129
|
yield Static("", id="detail-tags")
|
|
119
|
-
yield
|
|
130
|
+
yield TextArea("", id="detail-id", read_only=True)
|
|
120
131
|
yield Static("✎ Summary", id="detail-summary-label")
|
|
121
132
|
yield Markdown("", id="detail-summary-md")
|
|
122
133
|
|
|
@@ -176,13 +187,13 @@ class SessionDetail(Widget):
|
|
|
176
187
|
|
|
177
188
|
self.query_one("#detail-title", Static).update(f"[bold]{title}[/bold]")
|
|
178
189
|
self.query_one("#detail-tool", Static).update(_meta_line("Tool", tool_markup))
|
|
179
|
-
self.query_one("#detail-cwd",
|
|
190
|
+
self.query_one("#detail-cwd", TextArea).load_text("Project " + cwd)
|
|
180
191
|
self.query_one("#detail-tokens", Static).update(_meta_line("Tokens", tok_markup))
|
|
181
192
|
self.query_one("#detail-created", Static).update(_meta_line("Created", f"[dim]{created_str}[/dim]"))
|
|
182
193
|
self.query_one("#detail-updated", Static).update(_meta_line("Updated", f"[dim]{updated_str}[/dim]"))
|
|
183
194
|
self.query_one("#detail-status", Static).update(_meta_line("Status", f"[dim]{status}[/dim]"))
|
|
184
195
|
self.query_one("#detail-tags", Static).update(_meta_line("Tags", f"[dim]{tags}[/dim]"))
|
|
185
|
-
self.query_one("#detail-id",
|
|
196
|
+
self.query_one("#detail-id", TextArea).load_text("ID " + session_id)
|
|
186
197
|
|
|
187
198
|
md = self.query_one("#detail-summary-md", Markdown)
|
|
188
199
|
self.app.call_later(md.update, summary)
|
{context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/widgets/tokens_panel.py
RENAMED
|
@@ -4,12 +4,11 @@ from __future__ import annotations
|
|
|
4
4
|
import json
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
|
-
from rich.text import Text
|
|
8
7
|
from textual.app import ComposeResult
|
|
9
8
|
from textual.binding import Binding
|
|
10
|
-
from textual.containers import
|
|
9
|
+
from textual.containers import Vertical
|
|
11
10
|
from textual.screen import ModalScreen
|
|
12
|
-
from textual.widgets import DataTable, Static
|
|
11
|
+
from textual.widgets import DataTable, Static, TextArea
|
|
13
12
|
|
|
14
13
|
from contextforge.models.session import Message
|
|
15
14
|
from contextforge.tui.clipboard import copy as clipboard_copy
|
|
@@ -76,10 +75,16 @@ class TurnDetailPanel(ModalScreen):
|
|
|
76
75
|
border-bottom: solid $primary-background-lighten-1;
|
|
77
76
|
margin-bottom: 1;
|
|
78
77
|
}
|
|
79
|
-
TurnDetailPanel
|
|
78
|
+
TurnDetailPanel TextArea {
|
|
80
79
|
height: 1fr;
|
|
80
|
+
border: none;
|
|
81
|
+
background: transparent;
|
|
82
|
+
color: $text;
|
|
81
83
|
padding: 0 1;
|
|
82
84
|
}
|
|
85
|
+
TurnDetailPanel TextArea:focus {
|
|
86
|
+
border: none;
|
|
87
|
+
}
|
|
83
88
|
TurnDetailPanel #turn-footer {
|
|
84
89
|
height: 1;
|
|
85
90
|
color: $text-disabled;
|
|
@@ -96,9 +101,8 @@ class TurnDetailPanel(ModalScreen):
|
|
|
96
101
|
def compose(self) -> ComposeResult:
|
|
97
102
|
with Vertical():
|
|
98
103
|
yield Static("", id="turn-header")
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
yield Static("[dim]ESC / q — close Y — copy[/dim]", id="turn-footer")
|
|
104
|
+
yield TextArea("", id="turn-body", read_only=True)
|
|
105
|
+
yield Static("[dim]ESC / q — close select & Ctrl+C[/dim]", id="turn-footer")
|
|
102
106
|
|
|
103
107
|
def on_mount(self) -> None:
|
|
104
108
|
msg = self._msg
|
|
@@ -120,17 +124,13 @@ class TurnDetailPanel(ModalScreen):
|
|
|
120
124
|
if msg.tool_results else "")
|
|
121
125
|
)
|
|
122
126
|
|
|
123
|
-
body = Text()
|
|
124
127
|
plain_parts = []
|
|
125
128
|
|
|
126
129
|
if msg.content:
|
|
127
|
-
body.append("── Content ──\n", style="bold dim")
|
|
128
|
-
body.append(msg.content + "\n")
|
|
129
130
|
plain_parts.append("── Content ──\n")
|
|
130
131
|
plain_parts.append(msg.content + "\n")
|
|
131
132
|
|
|
132
133
|
if msg.tool_calls:
|
|
133
|
-
body.append("\n── Tool Calls ──\n", style="bold dim")
|
|
134
134
|
plain_parts.append("\n── Tool Calls ──\n")
|
|
135
135
|
for i, tc in enumerate(msg.tool_calls, 1):
|
|
136
136
|
name = tc.get("name", "?")
|
|
@@ -139,28 +139,23 @@ class TurnDetailPanel(ModalScreen):
|
|
|
139
139
|
formatted = json.dumps(json.loads(raw_input), indent=2)
|
|
140
140
|
except (json.JSONDecodeError, TypeError):
|
|
141
141
|
formatted = raw_input if isinstance(raw_input, str) else str(raw_input)
|
|
142
|
-
body.append(f"⚙ {i}. {name}\n", style="bold yellow")
|
|
143
|
-
body.append(formatted + "\n", style="dim")
|
|
144
142
|
plain_parts.append(f"⚙ {i}. {name}\n")
|
|
145
143
|
plain_parts.append(formatted + "\n")
|
|
146
144
|
|
|
147
145
|
if msg.tool_results:
|
|
148
|
-
body.append("\n── Tool Results ──\n", style="bold dim")
|
|
149
146
|
plain_parts.append("\n── Tool Results ──\n")
|
|
150
147
|
for i, tr in enumerate(msg.tool_results, 1):
|
|
151
148
|
output = tr.get("output", "")
|
|
152
149
|
if not isinstance(output, str):
|
|
153
150
|
output = str(output)
|
|
154
|
-
body.append(f"⇥ Result {i}\n", style="bold green")
|
|
155
|
-
body.append(output + "\n", style="dim")
|
|
156
151
|
plain_parts.append(f"⇥ Result {i}\n")
|
|
157
152
|
plain_parts.append(output + "\n")
|
|
158
153
|
|
|
159
154
|
self._plain_text = "".join(plain_parts)
|
|
160
|
-
self.query_one("#turn-body",
|
|
155
|
+
self.query_one("#turn-body", TextArea).load_text(self._plain_text)
|
|
161
156
|
|
|
162
157
|
def action_copy_content(self) -> None:
|
|
163
|
-
"""Copy the turn content to the clipboard."""
|
|
158
|
+
"""Copy the full turn content to the clipboard."""
|
|
164
159
|
if clipboard_copy(self._plain_text):
|
|
165
160
|
self.notify(f"Copied turn #{self._turn_num} content", title="Copy")
|
|
166
161
|
else:
|
|
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
|
{context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/widgets/session_table.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/contextforge/tui/widgets/transfer_panel.py
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
|
{context_forge_cli-0.4.8 → context_forge_cli-0.4.9}/tests/fixtures/claude_session_sample.jsonl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|